diff options
6 files changed, 60 insertions, 24 deletions
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 ef53839cb2ea..48fe65d3ce59 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 @@ -1028,19 +1028,21 @@ public class BubbleController implements ConfigurationChangeListener { * the bubble or bubble stack. * * Some notes: - * - Only one app bubble is supported at a time + * - Only one app bubble is supported at a time, regardless of users. Multi-users support is + * tracked in b/273533235. * - Calling this method with a different intent than the existing app bubble will do nothing * * @param intent the intent to display in the bubble expanded view. + * @param user the {@link UserHandle} of the user to start this activity for. */ - public void showOrHideAppBubble(Intent intent) { + public void showOrHideAppBubble(Intent intent, UserHandle user) { if (intent == null || intent.getPackage() == null) { Log.w(TAG, "App bubble failed to show, invalid intent: " + intent + ((intent != null) ? " with package: " + intent.getPackage() : " ")); return; } - PackageManager packageManager = getPackageManagerForUser(mContext, mCurrentUserId); + PackageManager packageManager = getPackageManagerForUser(mContext, user.getIdentifier()); if (!isResizableActivity(intent, packageManager, KEY_APP_BUBBLE)) return; Bubble existingAppBubble = mBubbleData.getBubbleInStackWithKey(KEY_APP_BUBBLE); @@ -1061,7 +1063,7 @@ public class BubbleController implements ConfigurationChangeListener { } } else { // App bubble does not exist, lets add and expand it - Bubble b = new Bubble(intent, UserHandle.of(mCurrentUserId), mMainExecutor); + Bubble b = new Bubble(intent, user, mMainExecutor); b.setShouldAutoExpand(true); inflateAndAdd(b, /* suppressFlyout= */ true, /* showInShade= */ false); } @@ -1869,10 +1871,9 @@ public class BubbleController implements ConfigurationChangeListener { } @Override - public void showOrHideAppBubble(Intent intent) { - mMainExecutor.execute(() -> { - BubbleController.this.showOrHideAppBubble(intent); - }); + public void showOrHideAppBubble(Intent intent, UserHandle user) { + mMainExecutor.execute( + () -> BubbleController.this.showOrHideAppBubble(intent, user)); } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java index ecddbda0fff4..e5a4362e5bf0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java @@ -236,12 +236,17 @@ public class BubbleExpandedView extends LinearLayout { fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); if (mBubble.isAppBubble()) { - PendingIntent pi = PendingIntent.getActivity(mContext, 0, + Context context = + mContext.createContextAsUser( + mBubble.getUser(), Context.CONTEXT_RESTRICTED); + PendingIntent pi = PendingIntent.getActivity( + context, + /* requestCode= */ 0, mBubble.getAppBubbleIntent() .addFlags(FLAG_ACTIVITY_NEW_DOCUMENT) .addFlags(FLAG_ACTIVITY_MULTIPLE_TASK), PendingIntent.FLAG_IMMUTABLE, - null); + /* options= */ null); mTaskView.startActivity(pi, /* fillInIntent= */ null, options, launchBounds); } else if (!mIsOverflow && mBubble.hasMetadataShortcutId()) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java index 4c0a93fb9355..5555bec6a28e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java @@ -129,12 +129,14 @@ public interface Bubbles { * the bubble or bubble stack. * * Some notes: - * - Only one app bubble is supported at a time + * - Only one app bubble is supported at a time, regardless of users. Multi-users support is + * tracked in b/273533235. * - Calling this method with a different intent than the existing app bubble will do nothing * * @param intent the intent to display in the bubble expanded view. + * @param user the {@link UserHandle} of the user to start this activity for. */ - void showOrHideAppBubble(Intent intent); + void showOrHideAppBubble(Intent intent, UserHandle user); /** @return true if the specified {@code taskId} corresponds to app bubble's taskId. */ boolean isAppBubbleTaskId(int taskId); diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt index ac22b7ce8b6b..779f1d8011e3 100644 --- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt +++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt @@ -129,8 +129,7 @@ constructor( logDebug { "onShowNoteTask - start: $info" } when (info.launchMode) { is NoteTaskLaunchMode.AppBubble -> { - // TODO(b/267634412, b/268351693): Should use `showOrHideAppBubbleAsUser` - bubbles.showOrHideAppBubble(intent) + bubbles.showOrHideAppBubble(intent, userTracker.userHandle) // App bubble logging happens on `onBubbleExpandChanged`. logDebug { "onShowNoteTask - opened as app bubble: $info" } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt index 3f940d64f236..40c733a19ccd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt @@ -232,7 +232,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() { verifyZeroInteractions(context) val intentCaptor = argumentCaptor<Intent>() - verify(bubbles).showOrHideAppBubble(capture(intentCaptor)) + verify(bubbles).showOrHideAppBubble(capture(intentCaptor), eq(userTracker.userHandle)) intentCaptor.value.let { intent -> assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE) assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME) @@ -366,7 +366,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() { createNoteTaskController().showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE) val intentCaptor = argumentCaptor<Intent>() - verify(bubbles).showOrHideAppBubble(capture(intentCaptor)) + verify(bubbles).showOrHideAppBubble(capture(intentCaptor), eq(userTracker.userHandle)) intentCaptor.value.let { intent -> assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE) assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME) @@ -389,7 +389,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() { createNoteTaskController().showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE) val intentCaptor = argumentCaptor<Intent>() - verify(bubbles).showOrHideAppBubble(capture(intentCaptor)) + verify(bubbles).showOrHideAppBubble(capture(intentCaptor), eq(userTracker.userHandle)) intentCaptor.value.let { intent -> assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE) assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME) 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 e185922d47d6..12e58c97d523 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java @@ -293,6 +293,8 @@ public class BubblesTest extends SysuiTestCase { private FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext); + private UserHandle mUser0; + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -301,6 +303,8 @@ public class BubblesTest extends SysuiTestCase { // For the purposes of this test, just run everything synchronously ShellExecutor syncExecutor = new SyncExecutor(); + mUser0 = createUserHande(/* userId= */ 0); + when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors); when(mNotificationShadeWindowView.getViewTreeObserver()) .thenReturn(mock(ViewTreeObserver.class)); @@ -1650,7 +1654,7 @@ public class BubblesTest extends SysuiTestCase { assertThat(mBubbleController.isStackExpanded()).isFalse(); assertThat(mBubbleData.getBubbleInStackWithKey(KEY_APP_BUBBLE)).isNull(); - mBubbleController.showOrHideAppBubble(mAppBubbleIntent); + mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0); verify(mBubbleController).inflateAndAdd(any(Bubble.class), /* suppressFlyout= */ eq(true), /* showInShade= */ eq(false)); @@ -1660,13 +1664,13 @@ public class BubblesTest extends SysuiTestCase { @Test public void testShowOrHideAppBubble_expandIfCollapsed() { - mBubbleController.showOrHideAppBubble(mAppBubbleIntent); + mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0); mBubbleController.updateBubble(mBubbleEntry); mBubbleController.collapseStack(); assertThat(mBubbleController.isStackExpanded()).isFalse(); // Calling this while collapsed will expand the app bubble - mBubbleController.showOrHideAppBubble(mAppBubbleIntent); + mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0); assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE); assertThat(mBubbleController.isStackExpanded()).isTrue(); @@ -1675,27 +1679,46 @@ public class BubblesTest extends SysuiTestCase { @Test public void testShowOrHideAppBubble_collapseIfSelected() { - mBubbleController.showOrHideAppBubble(mAppBubbleIntent); + mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0); + assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE); + assertThat(mBubbleController.isStackExpanded()).isTrue(); + + // Calling this while the app bubble is expanded should collapse the stack + mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0); + + assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE); + assertThat(mBubbleController.isStackExpanded()).isFalse(); + assertThat(mBubbleData.getBubbles().size()).isEqualTo(1); + assertThat(mBubbleData.getBubbles().get(0).getUser()).isEqualTo(mUser0); + } + + @Test + public void testShowOrHideAppBubbleWithNonPrimaryUser_bubbleCollapsedWithExpectedUser() { + UserHandle user10 = createUserHande(/* userId = */ 10); + mBubbleController.showOrHideAppBubble(mAppBubbleIntent, user10); assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE); assertThat(mBubbleController.isStackExpanded()).isTrue(); + assertThat(mBubbleData.getBubbles().size()).isEqualTo(1); + assertThat(mBubbleData.getBubbles().get(0).getUser()).isEqualTo(user10); // Calling this while the app bubble is expanded should collapse the stack - mBubbleController.showOrHideAppBubble(mAppBubbleIntent); + mBubbleController.showOrHideAppBubble(mAppBubbleIntent, user10); assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE); assertThat(mBubbleController.isStackExpanded()).isFalse(); assertThat(mBubbleData.getBubbles().size()).isEqualTo(1); + assertThat(mBubbleData.getBubbles().get(0).getUser()).isEqualTo(user10); } @Test public void testShowOrHideAppBubble_selectIfNotSelected() { - mBubbleController.showOrHideAppBubble(mAppBubbleIntent); + mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0); mBubbleController.updateBubble(mBubbleEntry); mBubbleController.expandStackAndSelectBubble(mBubbleEntry); assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(mBubbleEntry.getKey()); assertThat(mBubbleController.isStackExpanded()).isTrue(); - mBubbleController.showOrHideAppBubble(mAppBubbleIntent); + mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0); assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE); assertThat(mBubbleController.isStackExpanded()).isTrue(); assertThat(mBubbleData.getBubbles().size()).isEqualTo(2); @@ -1830,6 +1853,12 @@ public class BubblesTest extends SysuiTestCase { mBubbleController.onUserChanged(userId); } + private UserHandle createUserHande(int userId) { + UserHandle user = mock(UserHandle.class); + when(user.getIdentifier()).thenReturn(userId); + return user; + } + /** * Asserts that the bubble stack is expanded and also validates the cached state is updated. */ |