summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ats Jenk <atsjenk@google.com> 2024-08-15 05:55:24 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-08-15 05:55:24 +0000
commitfdd28a9ddeec172e94e1138256d8dc7f034fe1c5 (patch)
tree2d46a1dccea4a3542f2aae7910762fe18e0c3f74
parent40b8be4a4e8ef494765f0094752e8f768764b97e (diff)
parenta687a41a9e876f9ae7e45276ced5e73da090ecfd (diff)
Merge changes Ibb936cd6,Ibfdb2f3f into main
* changes: Add background executor to Bubble class Create a copy of BubbleViewInfoTask to flag refactor
-rw-r--r--libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt23
-rw-r--r--libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleStackViewTest.kt5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java149
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java346
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java8
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataRepositoryTest.kt4
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java26
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java12
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/BubbleEducationControllerTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java5
15 files changed, 540 insertions, 79 deletions
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt
index ae60d8bc2596..4b97451a0c41 100644
--- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubblePositionerTest.kt
@@ -268,7 +268,8 @@ class BubblePositionerTest {
)
positioner.update(deviceConfig)
val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName)
- val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor())
+ val bubble =
+ Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor())
assertThat(positioner.getExpandedViewHeight(bubble)).isEqualTo(MAX_HEIGHT)
}
@@ -294,6 +295,7 @@ class BubblePositionerTest {
0 /* taskId */,
null /* locus */,
true /* isDismissable */,
+ directExecutor(),
directExecutor()
) {}
@@ -322,6 +324,7 @@ class BubblePositionerTest {
0 /* taskId */,
null /* locus */,
true /* isDismissable */,
+ directExecutor(),
directExecutor()
) {}
@@ -416,7 +419,8 @@ class BubblePositionerTest {
positioner.update(deviceConfig)
val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName)
- val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor())
+ val bubble =
+ Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor())
// This bubble will have max height so it'll always be top aligned
assertThat(positioner.getExpandedViewY(bubble, 0f /* bubblePosition */))
@@ -433,7 +437,8 @@ class BubblePositionerTest {
positioner.update(deviceConfig)
val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName)
- val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor())
+ val bubble =
+ Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor())
// Always top aligned in phone portrait
assertThat(positioner.getExpandedViewY(bubble, 0f /* bubblePosition */))
@@ -452,7 +457,8 @@ class BubblePositionerTest {
positioner.update(deviceConfig)
val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName)
- val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor())
+ val bubble =
+ Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor())
// This bubble will have max height which is always top aligned on small tablets
assertThat(positioner.getExpandedViewY(bubble, 0f /* bubblePosition */))
@@ -470,7 +476,8 @@ class BubblePositionerTest {
positioner.update(deviceConfig)
val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName)
- val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor())
+ val bubble =
+ Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor())
// This bubble will have max height which is always top aligned on small tablets
assertThat(positioner.getExpandedViewY(bubble, 0f /* bubblePosition */))
@@ -489,7 +496,8 @@ class BubblePositionerTest {
positioner.update(deviceConfig)
val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName)
- val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor())
+ val bubble =
+ Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor())
// This bubble will have max height which is always top aligned on landscape, large tablet
assertThat(positioner.getExpandedViewY(bubble, 0f /* bubblePosition */))
@@ -507,7 +515,8 @@ class BubblePositionerTest {
positioner.update(deviceConfig)
val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName)
- val bubble = Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor())
+ val bubble =
+ Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor())
val manageButtonHeight =
context.resources.getDimensionPixelSize(R.dimen.bubble_manage_button_height)
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleStackViewTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleStackViewTest.kt
index 84f7bb27ca82..faadf1d623c9 100644
--- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleStackViewTest.kt
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleStackViewTest.kt
@@ -102,6 +102,7 @@ class BubbleStackViewTest {
BubbleLogger(UiEventLoggerFake()),
positioner,
BubbleEducationController(context),
+ shellExecutor,
shellExecutor
)
bubbleStackViewManager = FakeBubbleStackViewManager()
@@ -364,6 +365,7 @@ class BubbleStackViewTest {
/* taskId= */ 0,
"locus",
/* isDismissable= */ true,
+ directExecutor(),
directExecutor()
) {}
inflateBubble(bubble)
@@ -373,7 +375,8 @@ class BubbleStackViewTest {
private fun createAndInflateBubble(): Bubble {
val intent = Intent(Intent.ACTION_VIEW).setPackage(context.packageName)
val icon = Icon.createWithResource(context.resources, R.drawable.bubble_ic_overflow_button)
- val bubble = Bubble.createAppBubble(intent, UserHandle(1), icon, directExecutor())
+ val bubble =
+ Bubble.createAppBubble(intent, UserHandle(1), icon, directExecutor(), directExecutor())
inflateBubble(bubble)
return bubble
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index 5cd2cb7d51d5..021d3c32fd63 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -54,6 +54,8 @@ import com.android.wm.shell.Flags;
import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView;
import com.android.wm.shell.bubbles.bar.BubbleBarLayerView;
import com.android.wm.shell.common.bubbles.BubbleInfo;
+import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
+import com.android.wm.shell.shared.annotations.ShellMainThread;
import java.io.PrintWriter;
import java.util.List;
@@ -79,6 +81,7 @@ public class Bubble implements BubbleViewProvider {
private final LocusId mLocusId;
private final Executor mMainExecutor;
+ private final Executor mBgExecutor;
private long mLastUpdated;
private long mLastAccessed;
@@ -111,7 +114,10 @@ public class Bubble implements BubbleViewProvider {
@Nullable
private BubbleTaskView mBubbleTaskView;
+ @Nullable
private BubbleViewInfoTask mInflationTask;
+ @Nullable
+ private BubbleViewInfoTaskLegacy mInflationTaskLegacy;
private boolean mInflateSynchronously;
private boolean mPendingIntentCanceled;
private boolean mIsImportantConversation;
@@ -203,7 +209,9 @@ public class Bubble implements BubbleViewProvider {
@VisibleForTesting(visibility = PRIVATE)
public Bubble(@NonNull final String key, @NonNull final ShortcutInfo shortcutInfo,
final int desiredHeight, final int desiredHeightResId, @Nullable final String title,
- int taskId, @Nullable final String locus, boolean isDismissable, Executor mainExecutor,
+ int taskId, @Nullable final String locus, boolean isDismissable,
+ @ShellMainThread Executor mainExecutor,
+ @ShellBackgroundThread Executor bgExecutor,
final Bubbles.BubbleMetadataFlagListener listener) {
Objects.requireNonNull(key);
Objects.requireNonNull(shortcutInfo);
@@ -222,6 +230,7 @@ public class Bubble implements BubbleViewProvider {
mTitle = title;
mShowBubbleUpdateDot = false;
mMainExecutor = mainExecutor;
+ mBgExecutor = bgExecutor;
mTaskId = taskId;
mBubbleMetadataFlagListener = listener;
mIsAppBubble = false;
@@ -233,7 +242,8 @@ public class Bubble implements BubbleViewProvider {
@Nullable Icon icon,
boolean isAppBubble,
String key,
- Executor mainExecutor) {
+ @ShellMainThread Executor mainExecutor,
+ @ShellBackgroundThread Executor bgExecutor) {
mGroupKey = null;
mLocusId = null;
mFlags = 0;
@@ -243,13 +253,15 @@ public class Bubble implements BubbleViewProvider {
mKey = key;
mShowBubbleUpdateDot = false;
mMainExecutor = mainExecutor;
+ mBgExecutor = bgExecutor;
mTaskId = INVALID_TASK_ID;
mAppIntent = intent;
mDesiredHeight = Integer.MAX_VALUE;
mPackageName = intent.getPackage();
}
- private Bubble(ShortcutInfo info, Executor mainExecutor) {
+ private Bubble(ShortcutInfo info, @ShellMainThread Executor mainExecutor,
+ @ShellBackgroundThread Executor bgExecutor) {
mGroupKey = null;
mLocusId = null;
mFlags = 0;
@@ -259,6 +271,7 @@ public class Bubble implements BubbleViewProvider {
mKey = getBubbleKeyForShortcut(info);
mShowBubbleUpdateDot = false;
mMainExecutor = mainExecutor;
+ mBgExecutor = bgExecutor;
mTaskId = INVALID_TASK_ID;
mAppIntent = null;
mDesiredHeight = Integer.MAX_VALUE;
@@ -267,24 +280,21 @@ public class Bubble implements BubbleViewProvider {
}
/** Creates an app bubble. */
- public static Bubble createAppBubble(
- Intent intent,
- UserHandle user,
- @Nullable Icon icon,
- Executor mainExecutor) {
+ public static Bubble createAppBubble(Intent intent, UserHandle user, @Nullable Icon icon,
+ @ShellMainThread Executor mainExecutor, @ShellBackgroundThread Executor bgExecutor) {
return new Bubble(intent,
user,
icon,
/* isAppBubble= */ true,
/* key= */ getAppBubbleKeyForApp(intent.getPackage(), user),
- mainExecutor);
+ mainExecutor, bgExecutor);
}
/** Creates a shortcut bubble. */
public static Bubble createShortcutBubble(
ShortcutInfo info,
- Executor mainExecutor) {
- return new Bubble(info, mainExecutor);
+ @ShellMainThread Executor mainExecutor, @ShellBackgroundThread Executor bgExecutor) {
+ return new Bubble(info, mainExecutor, bgExecutor);
}
/**
@@ -309,7 +319,7 @@ public class Bubble implements BubbleViewProvider {
public Bubble(@NonNull final BubbleEntry entry,
final Bubbles.BubbleMetadataFlagListener listener,
final Bubbles.PendingIntentCanceledListener intentCancelListener,
- Executor mainExecutor) {
+ @ShellMainThread Executor mainExecutor, @ShellBackgroundThread Executor bgExecutor) {
mIsAppBubble = false;
mKey = entry.getKey();
mGroupKey = entry.getGroupKey();
@@ -324,6 +334,7 @@ public class Bubble implements BubbleViewProvider {
});
};
mMainExecutor = mainExecutor;
+ mBgExecutor = bgExecutor;
mTaskId = INVALID_TASK_ID;
setEntry(entry);
}
@@ -557,40 +568,70 @@ public class Bubble implements BubbleViewProvider {
@Nullable BubbleBarLayerView layerView,
BubbleIconFactory iconFactory,
boolean skipInflation) {
- if (isBubbleLoading()) {
- mInflationTask.cancel(true /* mayInterruptIfRunning */);
- }
- mInflationTask = new BubbleViewInfoTask(this,
- context,
- expandedViewManager,
- taskViewFactory,
- positioner,
- stackView,
- layerView,
- iconFactory,
- skipInflation,
- callback,
- mMainExecutor);
- if (mInflateSynchronously) {
- mInflationTask.onPostExecute(mInflationTask.doInBackground());
+ if (Flags.bubbleViewInfoExecutors()) {
+ if (mInflationTask != null && mInflationTask.getStatus() != FINISHED) {
+ mInflationTask.cancel(true /* mayInterruptIfRunning */);
+ }
+ // TODO(b/353894869): switch to executors
+ mInflationTask = new BubbleViewInfoTask(this,
+ context,
+ expandedViewManager,
+ taskViewFactory,
+ positioner,
+ stackView,
+ layerView,
+ iconFactory,
+ skipInflation,
+ callback,
+ mMainExecutor);
+ if (mInflateSynchronously) {
+ mInflationTask.onPostExecute(mInflationTask.doInBackground());
+ } else {
+ mInflationTask.execute();
+ }
} else {
- mInflationTask.execute();
+ if (mInflationTaskLegacy != null && mInflationTaskLegacy.getStatus() != FINISHED) {
+ mInflationTaskLegacy.cancel(true /* mayInterruptIfRunning */);
+ }
+ mInflationTaskLegacy = new BubbleViewInfoTaskLegacy(this,
+ context,
+ expandedViewManager,
+ taskViewFactory,
+ positioner,
+ stackView,
+ layerView,
+ iconFactory,
+ skipInflation,
+ bubble -> {
+ if (callback != null) {
+ callback.onBubbleViewsReady(bubble);
+ }
+ },
+ mMainExecutor);
+ if (mInflateSynchronously) {
+ mInflationTaskLegacy.onPostExecute(mInflationTaskLegacy.doInBackground());
+ } else {
+ mInflationTaskLegacy.execute();
+ }
}
}
- private boolean isBubbleLoading() {
- return mInflationTask != null && mInflationTask.getStatus() != FINISHED;
- }
-
boolean isInflated() {
return (mIconView != null && mExpandedView != null) || mBubbleBarExpandedView != null;
}
void stopInflation() {
- if (mInflationTask == null) {
- return;
+ if (Flags.bubbleViewInfoExecutors()) {
+ if (mInflationTask == null) {
+ return;
+ }
+ mInflationTask.cancel(true /* mayInterruptIfRunning */);
+ } else {
+ if (mInflationTaskLegacy == null) {
+ return;
+ }
+ mInflationTaskLegacy.cancel(true /* mayInterruptIfRunning */);
}
- mInflationTask.cancel(true /* mayInterruptIfRunning */);
}
void setViewInfo(BubbleViewInfoTask.BubbleViewInfo info) {
@@ -626,6 +667,42 @@ public class Bubble implements BubbleViewProvider {
}
/**
+ * @deprecated {@link BubbleViewInfoTaskLegacy} is deprecated.
+ */
+ @Deprecated
+ void setViewInfoLegacy(BubbleViewInfoTaskLegacy.BubbleViewInfo info) {
+ if (!isInflated()) {
+ mIconView = info.imageView;
+ mExpandedView = info.expandedView;
+ mBubbleBarExpandedView = info.bubbleBarExpandedView;
+ }
+
+ mShortcutInfo = info.shortcutInfo;
+ mAppName = info.appName;
+ if (mTitle == null) {
+ mTitle = mAppName;
+ }
+ mFlyoutMessage = info.flyoutMessage;
+
+ mBadgeBitmap = info.badgeBitmap;
+ mRawBadgeBitmap = info.rawBadgeBitmap;
+ mBubbleBitmap = info.bubbleBitmap;
+
+ mDotColor = info.dotColor;
+ mDotPath = info.dotPath;
+
+ if (mExpandedView != null) {
+ mExpandedView.update(this /* bubble */);
+ }
+ if (mBubbleBarExpandedView != null) {
+ mBubbleBarExpandedView.update(this /* bubble */);
+ }
+ if (mIconView != null) {
+ mIconView.setRenderedBubble(this /* bubble */);
+ }
+ }
+
+ /**
* Set visibility of bubble in the expanded state.
*
* <p>Note that this contents visibility doesn't affect visibility at {@link android.view.View},
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 29520efd70b0..cfe3cfad123f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -1495,7 +1495,7 @@ public class BubbleController implements ConfigurationChangeListener,
b.setAppBubbleIntent(intent);
} else {
// App bubble does not exist, lets add and expand it
- b = Bubble.createAppBubble(intent, user, icon, mMainExecutor);
+ b = Bubble.createAppBubble(intent, user, icon, mMainExecutor, mBackgroundExecutor);
}
ProtoLog.d(WM_SHELL_BUBBLES, "inflateAndAdd %s", appBubbleKey);
b.setShouldAutoExpand(true);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
index 3c6c6fa0d8d5..4ad1802cba7f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
@@ -43,6 +43,8 @@ import com.android.wm.shell.R;
import com.android.wm.shell.bubbles.Bubbles.DismissReason;
import com.android.wm.shell.common.bubbles.BubbleBarUpdate;
import com.android.wm.shell.common.bubbles.RemovedBubble;
+import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
+import com.android.wm.shell.shared.annotations.ShellMainThread;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -201,6 +203,7 @@ public class BubbleData {
private final BubblePositioner mPositioner;
private final BubbleEducationController mEducationController;
private final Executor mMainExecutor;
+ private final Executor mBgExecutor;
/** Bubbles that are actively in the stack. */
private final List<Bubble> mBubbles;
/** Bubbles that aged out to overflow. */
@@ -246,12 +249,14 @@ public class BubbleData {
private HashMap<String, String> mSuppressedGroupKeys = new HashMap<>();
public BubbleData(Context context, BubbleLogger bubbleLogger, BubblePositioner positioner,
- BubbleEducationController educationController, Executor mainExecutor) {
+ BubbleEducationController educationController, @ShellMainThread Executor mainExecutor,
+ @ShellBackgroundThread Executor bgExecutor) {
mContext = context;
mLogger = bubbleLogger;
mPositioner = positioner;
mEducationController = educationController;
mMainExecutor = mainExecutor;
+ mBgExecutor = bgExecutor;
mOverflow = new BubbleOverflow(context, positioner);
mBubbles = new ArrayList<>();
mOverflowBubbles = new ArrayList<>();
@@ -431,7 +436,8 @@ public class BubbleData {
bubbleToReturn = new Bubble(entry,
mBubbleMetadataFlagListener,
mCancelledListener,
- mMainExecutor);
+ mMainExecutor,
+ mBgExecutor);
} else {
// If there's no entry it must be a persisted bubble
bubbleToReturn = persistedBubble;
@@ -450,7 +456,7 @@ public class BubbleData {
String bubbleKey = Bubble.getBubbleKeyForShortcut(info);
Bubble bubbleToReturn = findAndRemoveBubbleFromOverflow(bubbleKey);
if (bubbleToReturn == null) {
- bubbleToReturn = Bubble.createShortcutBubble(info, mMainExecutor);
+ bubbleToReturn = Bubble.createShortcutBubble(info, mMainExecutor, mBgExecutor);
}
return bubbleToReturn;
}
@@ -461,7 +467,7 @@ public class BubbleData {
user);
Bubble bubbleToReturn = findAndRemoveBubbleFromOverflow(bubbleKey);
if (bubbleToReturn == null) {
- bubbleToReturn = Bubble.createAppBubble(intent, user, null, mMainExecutor);
+ bubbleToReturn = Bubble.createAppBubble(intent, user, null, mMainExecutor, mBgExecutor);
}
return bubbleToReturn;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt
index df12999afc9d..818ba45bec42 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt
@@ -31,6 +31,9 @@ import com.android.wm.shell.bubbles.storage.BubbleEntity
import com.android.wm.shell.bubbles.storage.BubblePersistentRepository
import com.android.wm.shell.bubbles.storage.BubbleVolatileRepository
import com.android.wm.shell.common.ShellExecutor
+import com.android.wm.shell.shared.annotations.ShellBackgroundThread
+import com.android.wm.shell.shared.annotations.ShellMainThread
+import java.util.concurrent.Executor
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@@ -41,7 +44,8 @@ import kotlinx.coroutines.yield
class BubbleDataRepository(
private val launcherApps: LauncherApps,
- private val mainExecutor: ShellExecutor,
+ @ShellMainThread private val mainExecutor: ShellExecutor,
+ @ShellBackgroundThread private val bgExecutor: Executor,
private val persistentRepository: BubblePersistentRepository,
) {
private val volatileRepository = BubbleVolatileRepository(launcherApps)
@@ -259,8 +263,8 @@ class BubbleDataRepository(
entity.locus,
entity.isDismissable,
mainExecutor,
- bubbleMetadataFlagListener
- )
+ bgExecutor,
+ bubbleMetadataFlagListener)
}
}
mainExecutor.execute { cb(bubbles) }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
index 69119cf4338e..03a2efd902f9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
@@ -54,6 +54,7 @@ import java.util.concurrent.Executor;
/**
* Simple task to inflate views & load necessary info to display a bubble.
*/
+// TODO(b/353894869): switch to executors
public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask.BubbleViewInfo> {
private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleViewInfoTask" : TAG_BUBBLES;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java
new file mode 100644
index 000000000000..5cfebf8f1647
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTaskLegacy.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.bubbles;
+
+import static com.android.wm.shell.bubbles.BadgedImageView.DEFAULT_PATH_SIZE;
+import static com.android.wm.shell.bubbles.BadgedImageView.WHITE_SCRIM_ALPHA;
+import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES;
+import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ShortcutInfo;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Path;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.os.AsyncTask;
+import android.util.Log;
+import android.util.PathParser;
+import android.view.LayoutInflater;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.graphics.ColorUtils;
+import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.BubbleIconFactory;
+import com.android.wm.shell.R;
+import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView;
+import com.android.wm.shell.bubbles.bar.BubbleBarLayerView;
+
+import java.lang.ref.WeakReference;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+
+/**
+ * Simple task to inflate views & load necessary info to display a bubble.
+ *
+ * @deprecated Deprecated since this is using an AsyncTask. Use {@link BubbleViewInfoTask} instead.
+ */
+@Deprecated
+// TODO(b/353894869): remove once flag for loading view info with executors rolls out
+public class BubbleViewInfoTaskLegacy extends
+ AsyncTask<Void, Void, BubbleViewInfoTaskLegacy.BubbleViewInfo> {
+ private static final String TAG =
+ TAG_WITH_CLASS_NAME ? "BubbleViewInfoTaskLegacy" : TAG_BUBBLES;
+
+
+ /**
+ * Callback to find out when the bubble has been inflated & necessary data loaded.
+ */
+ public interface Callback {
+ /**
+ * Called when data has been loaded for the bubble.
+ */
+ void onBubbleViewsReady(Bubble bubble);
+ }
+
+ private Bubble mBubble;
+ private WeakReference<Context> mContext;
+ private WeakReference<BubbleExpandedViewManager> mExpandedViewManager;
+ private WeakReference<BubbleTaskViewFactory> mTaskViewFactory;
+ private WeakReference<BubblePositioner> mPositioner;
+ private WeakReference<BubbleStackView> mStackView;
+ private WeakReference<BubbleBarLayerView> mLayerView;
+ private BubbleIconFactory mIconFactory;
+ private boolean mSkipInflation;
+ private Callback mCallback;
+ private Executor mMainExecutor;
+
+ /**
+ * Creates a task to load information for the provided {@link Bubble}. Once all info
+ * is loaded, {@link Callback} is notified.
+ */
+ BubbleViewInfoTaskLegacy(Bubble b,
+ Context context,
+ BubbleExpandedViewManager expandedViewManager,
+ BubbleTaskViewFactory taskViewFactory,
+ BubblePositioner positioner,
+ @Nullable BubbleStackView stackView,
+ @Nullable BubbleBarLayerView layerView,
+ BubbleIconFactory factory,
+ boolean skipInflation,
+ Callback c,
+ Executor mainExecutor) {
+ mBubble = b;
+ mContext = new WeakReference<>(context);
+ mExpandedViewManager = new WeakReference<>(expandedViewManager);
+ mTaskViewFactory = new WeakReference<>(taskViewFactory);
+ mPositioner = new WeakReference<>(positioner);
+ mStackView = new WeakReference<>(stackView);
+ mLayerView = new WeakReference<>(layerView);
+ mIconFactory = factory;
+ mSkipInflation = skipInflation;
+ mCallback = c;
+ mMainExecutor = mainExecutor;
+ }
+
+ @Override
+ protected BubbleViewInfo doInBackground(Void... voids) {
+ if (!verifyState()) {
+ // If we're in an inconsistent state, then switched modes and should just bail now.
+ return null;
+ }
+ if (mLayerView.get() != null) {
+ return BubbleViewInfo.populateForBubbleBar(mContext.get(), mExpandedViewManager.get(),
+ mTaskViewFactory.get(), mPositioner.get(), mLayerView.get(), mIconFactory,
+ mBubble, mSkipInflation);
+ } else {
+ return BubbleViewInfo.populate(mContext.get(), mExpandedViewManager.get(),
+ mTaskViewFactory.get(), mPositioner.get(), mStackView.get(), mIconFactory,
+ mBubble, mSkipInflation);
+ }
+ }
+
+ @Override
+ protected void onPostExecute(BubbleViewInfo viewInfo) {
+ if (isCancelled() || viewInfo == null) {
+ return;
+ }
+
+ mMainExecutor.execute(() -> {
+ if (!verifyState()) {
+ return;
+ }
+ mBubble.setViewInfoLegacy(viewInfo);
+ if (mCallback != null) {
+ mCallback.onBubbleViewsReady(mBubble);
+ }
+ });
+ }
+
+ private boolean verifyState() {
+ if (mExpandedViewManager.get().isShowingAsBubbleBar()) {
+ return mLayerView.get() != null;
+ } else {
+ return mStackView.get() != null;
+ }
+ }
+
+ /**
+ * Info necessary to render a bubble.
+ */
+ @VisibleForTesting
+ public static class BubbleViewInfo {
+ // TODO(b/273312602): for foldables it might make sense to populate all of the views
+
+ // Always populated
+ ShortcutInfo shortcutInfo;
+ String appName;
+ Bitmap rawBadgeBitmap;
+
+ // Only populated when showing in taskbar
+ @Nullable BubbleBarExpandedView bubbleBarExpandedView;
+
+ // These are only populated when not showing in taskbar
+ @Nullable BadgedImageView imageView;
+ @Nullable BubbleExpandedView expandedView;
+ int dotColor;
+ Path dotPath;
+ @Nullable Bubble.FlyoutMessage flyoutMessage;
+ Bitmap bubbleBitmap;
+ Bitmap badgeBitmap;
+
+ @Nullable
+ public static BubbleViewInfo populateForBubbleBar(Context c,
+ BubbleExpandedViewManager expandedViewManager,
+ BubbleTaskViewFactory taskViewFactory,
+ BubblePositioner positioner,
+ BubbleBarLayerView layerView,
+ BubbleIconFactory iconFactory,
+ Bubble b,
+ boolean skipInflation) {
+ BubbleViewInfo info = new BubbleViewInfo();
+
+ if (!skipInflation && !b.isInflated()) {
+ BubbleTaskView bubbleTaskView = b.getOrCreateBubbleTaskView(taskViewFactory);
+ LayoutInflater inflater = LayoutInflater.from(c);
+ info.bubbleBarExpandedView = (BubbleBarExpandedView) inflater.inflate(
+ R.layout.bubble_bar_expanded_view, layerView, false /* attachToRoot */);
+ info.bubbleBarExpandedView.initialize(
+ expandedViewManager, positioner, false /* isOverflow */, bubbleTaskView);
+ }
+
+ if (!populateCommonInfo(info, c, b, iconFactory)) {
+ // if we failed to update common fields return null
+ return null;
+ }
+
+ return info;
+ }
+
+ @VisibleForTesting
+ @Nullable
+ public static BubbleViewInfo populate(Context c,
+ BubbleExpandedViewManager expandedViewManager,
+ BubbleTaskViewFactory taskViewFactory,
+ BubblePositioner positioner,
+ BubbleStackView stackView,
+ BubbleIconFactory iconFactory,
+ Bubble b,
+ boolean skipInflation) {
+ BubbleViewInfo info = new BubbleViewInfo();
+
+ // View inflation: only should do this once per bubble
+ if (!skipInflation && !b.isInflated()) {
+ LayoutInflater inflater = LayoutInflater.from(c);
+ info.imageView = (BadgedImageView) inflater.inflate(
+ R.layout.bubble_view, stackView, false /* attachToRoot */);
+ info.imageView.initialize(positioner);
+
+ BubbleTaskView bubbleTaskView = b.getOrCreateBubbleTaskView(taskViewFactory);
+ info.expandedView = (BubbleExpandedView) inflater.inflate(
+ R.layout.bubble_expanded_view, stackView, false /* attachToRoot */);
+ info.expandedView.initialize(
+ expandedViewManager, stackView, positioner, false /* isOverflow */,
+ bubbleTaskView);
+ }
+
+ if (!populateCommonInfo(info, c, b, iconFactory)) {
+ // if we failed to update common fields return null
+ return null;
+ }
+
+ // Flyout
+ info.flyoutMessage = b.getFlyoutMessage();
+ if (info.flyoutMessage != null) {
+ info.flyoutMessage.senderAvatar =
+ loadSenderAvatar(c, info.flyoutMessage.senderIcon);
+ }
+ return info;
+ }
+ }
+
+ /**
+ * Modifies the given {@code info} object and populates common fields in it.
+ *
+ * <p>This method returns {@code true} if the update was successful and {@code false} otherwise.
+ * Callers should assume that the info object is unusable if the update was unsuccessful.
+ */
+ private static boolean populateCommonInfo(
+ BubbleViewInfo info, Context c, Bubble b, BubbleIconFactory iconFactory) {
+ if (b.getShortcutInfo() != null) {
+ info.shortcutInfo = b.getShortcutInfo();
+ }
+
+ // App name & app icon
+ PackageManager pm = BubbleController.getPackageManagerForUser(c,
+ b.getUser().getIdentifier());
+ ApplicationInfo appInfo;
+ Drawable badgedIcon;
+ Drawable appIcon;
+ try {
+ appInfo = pm.getApplicationInfo(
+ b.getPackageName(),
+ PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.MATCH_DISABLED_COMPONENTS
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE);
+ if (appInfo != null) {
+ info.appName = String.valueOf(pm.getApplicationLabel(appInfo));
+ }
+ appIcon = pm.getApplicationIcon(b.getPackageName());
+ badgedIcon = pm.getUserBadgedIcon(appIcon, b.getUser());
+ } catch (PackageManager.NameNotFoundException exception) {
+ // If we can't find package... don't think we should show the bubble.
+ Log.w(TAG, "Unable to find package: " + b.getPackageName());
+ return false;
+ }
+
+ Drawable bubbleDrawable = null;
+ try {
+ // Badged bubble image
+ bubbleDrawable = iconFactory.getBubbleDrawable(c, info.shortcutInfo,
+ b.getIcon());
+ } catch (Exception e) {
+ // If we can't create the icon we'll default to the app icon
+ Log.w(TAG, "Exception creating icon for the bubble: " + b.getKey());
+ }
+
+ if (bubbleDrawable == null) {
+ // Default to app icon
+ bubbleDrawable = appIcon;
+ }
+
+ BitmapInfo badgeBitmapInfo = iconFactory.getBadgeBitmap(badgedIcon,
+ b.isImportantConversation());
+ info.badgeBitmap = badgeBitmapInfo.icon;
+ // Raw badge bitmap never includes the important conversation ring
+ info.rawBadgeBitmap = b.isImportantConversation()
+ ? iconFactory.getBadgeBitmap(badgedIcon, false).icon
+ : badgeBitmapInfo.icon;
+
+ float[] bubbleBitmapScale = new float[1];
+ info.bubbleBitmap = iconFactory.getBubbleBitmap(bubbleDrawable, bubbleBitmapScale);
+
+ // Dot color & placement
+ Path iconPath = PathParser.createPathFromPathData(
+ c.getResources().getString(com.android.internal.R.string.config_icon_mask));
+ Matrix matrix = new Matrix();
+ float scale = bubbleBitmapScale[0];
+ float radius = DEFAULT_PATH_SIZE / 2f;
+ matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
+ radius /* pivot y */);
+ iconPath.transform(matrix);
+ info.dotPath = iconPath;
+ info.dotColor = ColorUtils.blendARGB(badgeBitmapInfo.color,
+ Color.WHITE, WHITE_SCRIM_ALPHA);
+ return true;
+ }
+
+ @Nullable
+ static Drawable loadSenderAvatar(@NonNull final Context context, @Nullable final Icon icon) {
+ Objects.requireNonNull(context);
+ if (icon == null) return null;
+ try {
+ if (icon.getType() == Icon.TYPE_URI
+ || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP) {
+ context.grantUriPermission(context.getPackageName(),
+ icon.getUri(), Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ }
+ return icon.loadDrawable(context);
+ } catch (Exception e) {
+ Log.w(TAG, "loadSenderAvatar failed: " + e.getMessage());
+ return null;
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 955361ffac1b..63a25730f1aa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -164,8 +164,10 @@ public abstract class WMShellModule {
BubbleLogger logger,
BubblePositioner positioner,
BubbleEducationController educationController,
- @ShellMainThread ShellExecutor mainExecutor) {
- return new BubbleData(context, logger, positioner, educationController, mainExecutor);
+ @ShellMainThread ShellExecutor mainExecutor,
+ @ShellBackgroundThread ShellExecutor bgExecutor) {
+ return new BubbleData(context, logger, positioner, educationController, mainExecutor,
+ bgExecutor);
}
// Note: Handler needed for LauncherApps.register
@@ -198,7 +200,7 @@ public abstract class WMShellModule {
IWindowManager wmService) {
return new BubbleController(context, shellInit, shellCommandHandler, shellController, data,
null /* synchronizer */, floatingContentCoordinator,
- new BubbleDataRepository(launcherApps, mainExecutor,
+ new BubbleDataRepository(launcherApps, mainExecutor, bgExecutor,
new BubblePersistentRepository(context)),
statusBarService, windowManager, windowManagerShellWrapper, userManager,
launcherApps, logger, taskStackListener, organizer, positioner, displayController,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataRepositoryTest.kt
index e35995775f76..9ec62c965a14 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataRepositoryTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataRepositoryTest.kt
@@ -124,6 +124,7 @@ class BubbleDataRepositoryTest : ShellTestCase() {
private val testHandler = Handler(Looper.getMainLooper())
private val mainExecutor = HandlerExecutor(testHandler)
+ private val bgExecutor = HandlerExecutor(testHandler)
private val launcherApps = mock<LauncherApps>()
private val persistedBubbles = SparseArray<List<BubbleEntity>>()
@@ -134,7 +135,8 @@ class BubbleDataRepositoryTest : ShellTestCase() {
@Before
fun setup() {
persistentRepository = BubblePersistentRepository(mContext)
- dataRepository = spy(BubbleDataRepository(launcherApps, mainExecutor, persistentRepository))
+ dataRepository =
+ spy(BubbleDataRepository(launcherApps, mainExecutor, bgExecutor, persistentRepository))
persistedBubbles.put(0, user0BubbleEntities)
persistedBubbles.put(1, user1BubbleEntities)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
index c138a2498d35..859602ec709f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
@@ -117,6 +117,8 @@ public class BubbleDataTest extends ShellTestCase {
private BubbleEducationController mEducationController;
@Mock
private ShellExecutor mMainExecutor;
+ @Mock
+ private ShellExecutor mBgExecutor;
@Captor
private ArgumentCaptor<BubbleData.Update> mUpdateCaptor;
@@ -144,47 +146,47 @@ public class BubbleDataTest extends ShellTestCase {
when(ranking.isTextChanged()).thenReturn(true);
mEntryInterruptive = createBubbleEntry(1, "interruptive", "package.d", ranking);
mBubbleInterruptive = new Bubble(mEntryInterruptive, mBubbleMetadataFlagListener, null,
- mMainExecutor);
+ mMainExecutor, mBgExecutor);
mEntryDismissed = createBubbleEntry(1, "dismissed", "package.d", null);
mBubbleDismissed = new Bubble(mEntryDismissed, mBubbleMetadataFlagListener, null,
- mMainExecutor);
+ mMainExecutor, mBgExecutor);
mEntryLocusId = createBubbleEntry(1, "keyLocus", "package.e", null,
new LocusId("locusId1"));
mBubbleLocusId = new Bubble(mEntryLocusId,
mBubbleMetadataFlagListener,
null /* pendingIntentCanceledListener */,
- mMainExecutor);
+ mMainExecutor, mBgExecutor);
mBubbleA1 = new Bubble(mEntryA1,
mBubbleMetadataFlagListener,
mPendingIntentCanceledListener,
- mMainExecutor);
+ mMainExecutor, mBgExecutor);
mBubbleA2 = new Bubble(mEntryA2,
mBubbleMetadataFlagListener,
mPendingIntentCanceledListener,
- mMainExecutor);
+ mMainExecutor, mBgExecutor);
mBubbleA3 = new Bubble(mEntryA3,
mBubbleMetadataFlagListener,
mPendingIntentCanceledListener,
- mMainExecutor);
+ mMainExecutor, mBgExecutor);
mBubbleB1 = new Bubble(mEntryB1,
mBubbleMetadataFlagListener,
mPendingIntentCanceledListener,
- mMainExecutor);
+ mMainExecutor, mBgExecutor);
mBubbleB2 = new Bubble(mEntryB2,
mBubbleMetadataFlagListener,
mPendingIntentCanceledListener,
- mMainExecutor);
+ mMainExecutor, mBgExecutor);
mBubbleB3 = new Bubble(mEntryB3,
mBubbleMetadataFlagListener,
mPendingIntentCanceledListener,
- mMainExecutor);
+ mMainExecutor, mBgExecutor);
mBubbleC1 = new Bubble(mEntryC1,
mBubbleMetadataFlagListener,
mPendingIntentCanceledListener,
- mMainExecutor);
+ mMainExecutor, mBgExecutor);
Intent appBubbleIntent = new Intent(mContext, BubblesTestActivity.class);
appBubbleIntent.setPackage(mContext.getPackageName());
@@ -192,12 +194,12 @@ public class BubbleDataTest extends ShellTestCase {
appBubbleIntent,
new UserHandle(1),
mock(Icon.class),
- mMainExecutor);
+ mMainExecutor, mBgExecutor);
mPositioner = new TestableBubblePositioner(mContext,
mContext.getSystemService(WindowManager.class));
mBubbleData = new BubbleData(getContext(), mBubbleLogger, mPositioner, mEducationController,
- mMainExecutor);
+ mMainExecutor, mBgExecutor);
// Used by BubbleData to set lastAccessedTime
when(mTimeSource.currentTimeMillis()).thenReturn(1000L);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java
index afec1ee12341..50c4a1828026 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleTest.java
@@ -61,6 +61,8 @@ public class BubbleTest extends ShellTestCase {
private StatusBarNotification mSbn;
@Mock
private ShellExecutor mMainExecutor;
+ @Mock
+ private ShellExecutor mBgExecutor;
private BubbleEntry mBubbleEntry;
private Bundle mExtras;
@@ -85,7 +87,8 @@ public class BubbleTest extends ShellTestCase {
when(mNotif.getBubbleMetadata()).thenReturn(metadata);
when(mSbn.getKey()).thenReturn("mock");
mBubbleEntry = new BubbleEntry(mSbn, null, true, false, false, false);
- mBubble = new Bubble(mBubbleEntry, mBubbleMetadataFlagListener, null, mMainExecutor);
+ mBubble = new Bubble(mBubbleEntry, mBubbleMetadataFlagListener, null, mMainExecutor,
+ mBgExecutor);
}
@Test
@@ -176,7 +179,8 @@ public class BubbleTest extends ShellTestCase {
@Test
public void testBubbleIsConversation_hasNoShortcut() {
- Bubble bubble = new Bubble(mBubbleEntry, mBubbleMetadataFlagListener, null, mMainExecutor);
+ Bubble bubble = new Bubble(mBubbleEntry, mBubbleMetadataFlagListener, null, mMainExecutor,
+ mBgExecutor);
assertThat(bubble.getShortcutInfo()).isNull();
assertThat(bubble.isConversation()).isFalse();
}
@@ -199,7 +203,7 @@ public class BubbleTest extends ShellTestCase {
Intent intent = new Intent(mContext, BubblesTestActivity.class);
intent.setPackage(mContext.getPackageName());
Bubble bubble = Bubble.createAppBubble(intent, new UserHandle(1 /* userId */),
- null /* icon */, mMainExecutor);
+ null /* icon */, mMainExecutor, mBgExecutor);
BubbleInfo bubbleInfo = bubble.asBubbleBarBubble();
assertThat(bubble.getShortcutInfo()).isNull();
@@ -215,6 +219,6 @@ public class BubbleTest extends ShellTestCase {
.build();
return new Bubble("mockKey", shortcutInfo, 10, Resources.ID_NULL,
"mockTitle", 0 /* taskId */, "mockLocus", true /* isDismissible */,
- mMainExecutor, mBubbleMetadataFlagListener);
+ mMainExecutor, mBgExecutor, mBubbleMetadataFlagListener);
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt
index 4a4c5e860bb2..8035e917d5b4 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleViewInfoTest.kt
@@ -70,6 +70,7 @@ class BubbleViewInfoTest : ShellTestCase() {
private lateinit var bubble: Bubble
private lateinit var bubbleController: BubbleController
private lateinit var mainExecutor: ShellExecutor
+ private lateinit var bgExecutor: ShellExecutor
private lateinit var bubbleStackView: BubbleStackView
private lateinit var bubbleBarLayerView: BubbleBarLayerView
private lateinit var bubblePositioner: BubblePositioner
@@ -92,6 +93,7 @@ class BubbleViewInfoTest : ShellTestCase() {
)
mainExecutor = TestShellExecutor()
+ bgExecutor = TestShellExecutor()
val windowManager = context.getSystemService(WindowManager::class.java)
val shellInit = ShellInit(mainExecutor)
val shellCommandHandler = ShellCommandHandler()
@@ -104,7 +106,8 @@ class BubbleViewInfoTest : ShellTestCase() {
mock<BubbleLogger>(),
bubblePositioner,
BubbleEducationController(context),
- mainExecutor
+ mainExecutor,
+ bgExecutor
)
val surfaceSynchronizer = { obj: Runnable -> obj.run() }
@@ -132,7 +135,7 @@ class BubbleViewInfoTest : ShellTestCase() {
null,
mainExecutor,
mock<Handler>(),
- mock<ShellExecutor>(),
+ bgExecutor,
mock<TaskViewTransitions>(),
mock<Transitions>(),
mock<SyncTransactionQueue>(),
@@ -256,7 +259,7 @@ class BubbleViewInfoTest : ShellTestCase() {
"mockLocus",
true /* isDismissible */,
mainExecutor,
- metadataFlagListener
- )
+ bgExecutor,
+ metadataFlagListener)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubbleEducationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubbleEducationControllerTest.kt
index 2021f02e5a8a..55aff130f691 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubbleEducationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubbleEducationControllerTest.kt
@@ -123,11 +123,12 @@ class BubbleEducationControllerTest : SysUiStateTest() {
/* taskId= */ 0,
"locus",
/* isDismissable= */ true,
+ directExecutor(),
directExecutor()
) {}
} else {
val intent = Intent(Intent.ACTION_VIEW).setPackage(mContext.packageName)
- Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor())
+ Bubble.createAppBubble(intent, UserHandle(1), null, directExecutor(), directExecutor())
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index e5e04dc9b82f..9dd3e53efa63 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -459,7 +459,7 @@ public class BubblesTest extends SysuiTestCase {
mContext.getSystemService(WindowManager.class));
mPositioner.setMaxBubbles(5);
mBubbleData = new BubbleData(mContext, mBubbleLogger, mPositioner, mEducationController,
- syncExecutor);
+ syncExecutor, syncExecutor);
when(mUserManager.getProfiles(ActivityManager.getCurrentUser())).thenReturn(
Collections.singletonList(mock(UserInfo.class)));
@@ -2465,9 +2465,10 @@ public class BubblesTest extends SysuiTestCase {
workEntry.setBubbleMetadata(getMetadata());
workEntry.setFlagBubble(true);
+ SyncExecutor executor = new SyncExecutor();
return new Bubble(mBubblesManager.notifToBubbleEntry(workEntry),
null,
- mock(Bubbles.PendingIntentCanceledListener.class), new SyncExecutor());
+ mock(Bubbles.PendingIntentCanceledListener.class), executor, executor);
}
private BubbleEntry createBubbleEntry(boolean isConversation) {