Allow callers to specify UserHandle when launching an intent in a Bubble
Test: atest SystemUITests:com.android.systemui.wmshell.BubblesTest atest SystemUITests:com.android.systemui.notetask.NoteTaskControllerTest Fix: 268351693 Change-Id: I853102bb1e6866d1efde19eb65cbd33680ea753b
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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" }
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
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, 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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user