App Bubble custom icon support
* Add `Icon` argument to `BubbleController.showOrHideAppBubble` method to allow custom app icon * Update `NoteTaskController` usages of the method Test: atest BubblesTest NoteTaskControllerTest Bug: 268351693 Change-Id: I3366a8e576ff87725e07090f38aec3cd11ad7d39
This commit is contained in:
@@ -206,12 +206,14 @@ public class Bubble implements BubbleViewProvider {
|
||||
|
||||
public Bubble(Intent intent,
|
||||
UserHandle user,
|
||||
@Nullable Icon icon,
|
||||
Executor mainExecutor) {
|
||||
mKey = KEY_APP_BUBBLE;
|
||||
mGroupKey = null;
|
||||
mLocusId = null;
|
||||
mFlags = 0;
|
||||
mUser = user;
|
||||
mIcon = icon;
|
||||
mShowBubbleUpdateDot = false;
|
||||
mMainExecutor = mainExecutor;
|
||||
mTaskId = INVALID_TASK_ID;
|
||||
|
||||
@@ -57,6 +57,7 @@ import android.content.pm.UserInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
@@ -1034,8 +1035,9 @@ public class BubbleController implements ConfigurationChangeListener {
|
||||
*
|
||||
* @param intent the intent to display in the bubble expanded view.
|
||||
* @param user the {@link UserHandle} of the user to start this activity for.
|
||||
* @param icon the {@link Icon} to use for the bubble view.
|
||||
*/
|
||||
public void showOrHideAppBubble(Intent intent, UserHandle user) {
|
||||
public void showOrHideAppBubble(Intent intent, UserHandle user, @Nullable Icon icon) {
|
||||
if (intent == null || intent.getPackage() == null) {
|
||||
Log.w(TAG, "App bubble failed to show, invalid intent: " + intent
|
||||
+ ((intent != null) ? " with package: " + intent.getPackage() : " "));
|
||||
@@ -1063,7 +1065,7 @@ public class BubbleController implements ConfigurationChangeListener {
|
||||
}
|
||||
} else {
|
||||
// App bubble does not exist, lets add and expand it
|
||||
Bubble b = new Bubble(intent, user, mMainExecutor);
|
||||
Bubble b = new Bubble(intent, user, icon, mMainExecutor);
|
||||
b.setShouldAutoExpand(true);
|
||||
inflateAndAdd(b, /* suppressFlyout= */ true, /* showInShade= */ false);
|
||||
}
|
||||
@@ -1871,9 +1873,9 @@ public class BubbleController implements ConfigurationChangeListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showOrHideAppBubble(Intent intent, UserHandle user) {
|
||||
public void showOrHideAppBubble(Intent intent, UserHandle user, @Nullable Icon icon) {
|
||||
mMainExecutor.execute(
|
||||
() -> BubbleController.this.showOrHideAppBubble(intent, user));
|
||||
() -> BubbleController.this.showOrHideAppBubble(intent, user, icon));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,6 +26,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
import android.app.NotificationChannel;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.hardware.HardwareBuffer;
|
||||
import android.os.UserHandle;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
@@ -135,8 +136,9 @@ public interface Bubbles {
|
||||
*
|
||||
* @param intent the intent to display in the bubble expanded view.
|
||||
* @param user the {@link UserHandle} of the user to start this activity for.
|
||||
* @param icon the {@link Icon} to use for the bubble view.
|
||||
*/
|
||||
void showOrHideAppBubble(Intent intent, UserHandle user);
|
||||
void showOrHideAppBubble(Intent intent, UserHandle user, @Nullable Icon icon);
|
||||
|
||||
/** @return true if the specified {@code taskId} corresponds to app bubble's taskId. */
|
||||
boolean isAppBubbleTaskId(int taskId);
|
||||
|
||||
@@ -185,7 +185,8 @@ public class BubbleDataTest extends ShellTestCase {
|
||||
|
||||
Intent appBubbleIntent = new Intent(mContext, BubblesTestActivity.class);
|
||||
appBubbleIntent.setPackage(mContext.getPackageName());
|
||||
mAppBubble = new Bubble(appBubbleIntent, new UserHandle(1), mMainExecutor);
|
||||
mAppBubble = new Bubble(appBubbleIntent, new UserHandle(1), mock(Icon.class),
|
||||
mMainExecutor);
|
||||
|
||||
mPositioner = new TestableBubblePositioner(mContext,
|
||||
mock(WindowManager.class));
|
||||
|
||||
@@ -138,7 +138,8 @@ constructor(
|
||||
logDebug { "onShowNoteTask - start: $info on user#${user.identifier}" }
|
||||
when (info.launchMode) {
|
||||
is NoteTaskLaunchMode.AppBubble -> {
|
||||
bubbles.showOrHideAppBubble(intent, userTracker.userHandle)
|
||||
// TODO: provide app bubble icon
|
||||
bubbles.showOrHideAppBubble(intent, userTracker.userHandle, null /* icon */)
|
||||
// App bubble logging happens on `onBubbleExpandChanged`.
|
||||
logDebug { "onShowNoteTask - opened as app bubble: $info" }
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentMatchers.anyInt
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.isNull
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.verifyZeroInteractions
|
||||
import org.mockito.MockitoAnnotations
|
||||
@@ -267,7 +268,8 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
|
||||
|
||||
verifyZeroInteractions(context)
|
||||
val intentCaptor = argumentCaptor<Intent>()
|
||||
verify(bubbles).showOrHideAppBubble(capture(intentCaptor), eq(userTracker.userHandle))
|
||||
verify(bubbles).showOrHideAppBubble(capture(intentCaptor), eq(userTracker.userHandle),
|
||||
isNull())
|
||||
intentCaptor.value.let { intent ->
|
||||
assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
|
||||
assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
|
||||
@@ -401,7 +403,8 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
|
||||
createNoteTaskController().showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)
|
||||
|
||||
val intentCaptor = argumentCaptor<Intent>()
|
||||
verify(bubbles).showOrHideAppBubble(capture(intentCaptor), eq(userTracker.userHandle))
|
||||
verify(bubbles).showOrHideAppBubble(capture(intentCaptor), eq(userTracker.userHandle),
|
||||
isNull())
|
||||
intentCaptor.value.let { intent ->
|
||||
assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
|
||||
assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
|
||||
@@ -424,7 +427,8 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
|
||||
createNoteTaskController().showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)
|
||||
|
||||
val intentCaptor = argumentCaptor<Intent>()
|
||||
verify(bubbles).showOrHideAppBubble(capture(intentCaptor), eq(userTracker.userHandle))
|
||||
verify(bubbles).showOrHideAppBubble(capture(intentCaptor), eq(userTracker.userHandle),
|
||||
isNull())
|
||||
intentCaptor.value.let { intent ->
|
||||
assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
|
||||
assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
|
||||
|
||||
@@ -284,6 +284,8 @@ public class BubblesTest extends SysuiTestCase {
|
||||
private ShadeWindowLogger mShadeWindowLogger;
|
||||
@Mock
|
||||
private NotifPipelineFlags mNotifPipelineFlags;
|
||||
@Mock
|
||||
private Icon mAppBubbleIcon;
|
||||
|
||||
private TestableBubblePositioner mPositioner;
|
||||
|
||||
@@ -303,7 +305,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
// For the purposes of this test, just run everything synchronously
|
||||
ShellExecutor syncExecutor = new SyncExecutor();
|
||||
|
||||
mUser0 = createUserHande(/* userId= */ 0);
|
||||
mUser0 = createUserHandle(/* userId= */ 0);
|
||||
|
||||
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
|
||||
when(mNotificationShadeWindowView.getViewTreeObserver())
|
||||
@@ -1250,7 +1252,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testShowManageMenuChangesSysuiState_appBubble() {
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0);
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0, mAppBubbleIcon);
|
||||
assertTrue(mBubbleController.hasBubbles());
|
||||
|
||||
// Expand the stack
|
||||
@@ -1671,7 +1673,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
assertThat(mBubbleController.isStackExpanded()).isFalse();
|
||||
assertThat(mBubbleData.getBubbleInStackWithKey(KEY_APP_BUBBLE)).isNull();
|
||||
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0);
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0, mAppBubbleIcon);
|
||||
|
||||
verify(mBubbleController).inflateAndAdd(any(Bubble.class), /* suppressFlyout= */ eq(true),
|
||||
/* showInShade= */ eq(false));
|
||||
@@ -1681,13 +1683,13 @@ public class BubblesTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testShowOrHideAppBubble_expandIfCollapsed() {
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0);
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0, mAppBubbleIcon);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
mBubbleController.collapseStack();
|
||||
assertThat(mBubbleController.isStackExpanded()).isFalse();
|
||||
|
||||
// Calling this while collapsed will expand the app bubble
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0);
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0, mAppBubbleIcon);
|
||||
|
||||
assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE);
|
||||
assertThat(mBubbleController.isStackExpanded()).isTrue();
|
||||
@@ -1696,12 +1698,12 @@ public class BubblesTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testShowOrHideAppBubble_collapseIfSelected() {
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0);
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0, mAppBubbleIcon);
|
||||
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);
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0, mAppBubbleIcon);
|
||||
|
||||
assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE);
|
||||
assertThat(mBubbleController.isStackExpanded()).isFalse();
|
||||
@@ -1711,15 +1713,15 @@ public class BubblesTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testShowOrHideAppBubbleWithNonPrimaryUser_bubbleCollapsedWithExpectedUser() {
|
||||
UserHandle user10 = createUserHande(/* userId = */ 10);
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, user10);
|
||||
UserHandle user10 = createUserHandle(/* userId = */ 10);
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, user10, mAppBubbleIcon);
|
||||
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);
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, user10, mAppBubbleIcon);
|
||||
|
||||
assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE);
|
||||
assertThat(mBubbleController.isStackExpanded()).isFalse();
|
||||
@@ -1729,13 +1731,13 @@ public class BubblesTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testShowOrHideAppBubble_selectIfNotSelected() {
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0);
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0, mAppBubbleIcon);
|
||||
mBubbleController.updateBubble(mBubbleEntry);
|
||||
mBubbleController.expandStackAndSelectBubble(mBubbleEntry);
|
||||
assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(mBubbleEntry.getKey());
|
||||
assertThat(mBubbleController.isStackExpanded()).isTrue();
|
||||
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0);
|
||||
mBubbleController.showOrHideAppBubble(mAppBubbleIntent, mUser0, mAppBubbleIcon);
|
||||
assertThat(mBubbleData.getSelectedBubble().getKey()).isEqualTo(KEY_APP_BUBBLE);
|
||||
assertThat(mBubbleController.isStackExpanded()).isTrue();
|
||||
assertThat(mBubbleData.getBubbles().size()).isEqualTo(2);
|
||||
@@ -1870,7 +1872,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
mBubbleController.onUserChanged(userId);
|
||||
}
|
||||
|
||||
private UserHandle createUserHande(int userId) {
|
||||
private UserHandle createUserHandle(int userId) {
|
||||
UserHandle user = mock(UserHandle.class);
|
||||
when(user.getIdentifier()).thenReturn(userId);
|
||||
return user;
|
||||
|
||||
Reference in New Issue
Block a user