diff options
| author | 2019-01-10 15:14:51 -0800 | |
|---|---|---|
| committer | 2019-01-11 12:53:26 -0800 | |
| commit | b4991e60dbf698bfc7460901814c3aafac7942a9 (patch) | |
| tree | 966b574d578d50251bd6ade4613961219cf63b24 | |
| parent | fb922e9bac265358e54729f75a785c4d7905a5b9 (diff) | |
Enable 'real bubbles' and fix our tests
Previously the test was marking entries as 'isBubble' automatically which
isn't quite correct.
This CL fixes that and has the side effect that enables bubbles for real.
This doesn't auto-bubble any notification, however, if the notification
is on an appropriately noisy channel & has an app overlay intent we will
bubble it.
Bug: 111236845
Test: atest BubbleControllerTest
Change-Id: I26c67ce002eec808591d7864b2366bb4140be386
4 files changed, 88 insertions, 36 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index 9f3ff782211d..79ee4b85f887 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -22,12 +22,16 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static com.android.systemui.bubbles.BubbleMovementHelper.EDGE_OVERLAP; +import android.annotation.Nullable; +import android.app.INotificationManager; import android.app.Notification; import android.app.PendingIntent; import android.content.Context; import android.content.pm.ActivityInfo; import android.graphics.Point; import android.graphics.Rect; +import android.os.RemoteException; +import android.os.ServiceManager; import android.provider.Settings; import android.service.notification.StatusBarNotification; import android.util.Log; @@ -35,8 +39,6 @@ import android.view.ViewGroup; import android.view.WindowManager; import android.widget.FrameLayout; -import androidx.annotation.Nullable; - import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Dependency; import com.android.systemui.R; @@ -88,6 +90,8 @@ public class BubbleController { // Bubbles get added to the status bar view private final StatusBarWindowController mStatusBarWindowController; + private INotificationManager mNotificationManagerService; + // Used for determining view rect for touch interaction private Rect mTempRect = new Rect(); @@ -124,6 +128,13 @@ public class BubbleController { mStatusBarWindowController = statusBarWindowController; mNotificationEntryManager.addNotificationEntryListener(mEntryListener); + + try { + mNotificationManagerService = INotificationManager.Stub.asInterface( + ServiceManager.getServiceOrThrow(Context.NOTIFICATION_SERVICE)); + } catch (ServiceManager.ServiceNotFoundException e) { + e.printStackTrace(); + } } /** @@ -268,7 +279,7 @@ public class BubbleController { private final NotificationEntryListener mEntryListener = new NotificationEntryListener() { @Override public void onPendingEntryAdded(NotificationEntry entry) { - if (shouldAutoBubble(mContext, entry)) { + if (shouldAutoBubble(mContext, entry) || shouldBubble(entry)) { entry.setIsBubble(true); } } @@ -368,18 +379,37 @@ public class BubbleController { } /** + * Whether the notification has been developer configured to bubble and is allowed by the user. + */ + private boolean shouldBubble(NotificationEntry entry) { + StatusBarNotification n = entry.notification; + boolean canAppOverlay = false; + try { + canAppOverlay = mNotificationManagerService.areAppOverlaysAllowedForPackage( + n.getPackageName(), n.getUid()); + } catch (RemoteException e) { + Log.w(TAG, "Error calling NoMan to determine if app can overlay", e); + } + + boolean canChannelOverlay = mNotificationEntryManager.getNotificationData().getChannel( + entry.key).canOverlayApps(); + boolean hasOverlayIntent = n.getNotification().getAppOverlayIntent() != null; + return hasOverlayIntent && canChannelOverlay && canAppOverlay; + } + + /** * Whether the notification should bubble or not. */ - private static boolean shouldAutoBubble(Context context, NotificationEntry entry) { + private boolean shouldAutoBubble(Context context, NotificationEntry entry) { if (entry.isBubbleDismissed()) { return false; } + StatusBarNotification n = entry.notification; boolean autoBubbleMessages = shouldAutoBubbleMessages(context) || DEBUG_ENABLE_AUTO_BUBBLE; boolean autoBubbleOngoing = shouldAutoBubbleOngoing(context) || DEBUG_ENABLE_AUTO_BUBBLE; boolean autoBubbleAll = shouldAutoBubbleAll(context) || DEBUG_ENABLE_AUTO_BUBBLE; - StatusBarNotification n = entry.notification; boolean hasRemoteInput = false; if (n.getNotification().actions != null) { for (Notification.Action action : n.getNotification().actions) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java index 21d3652adca7..702a64131ca1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -74,7 +74,8 @@ public class BubbleControllerTest extends SysuiTestCase { private ExpandableNotificationRow mRow; private ExpandableNotificationRow mRow2; - private final NotificationData mNotificationData = new NotificationData(); + @Mock + private NotificationData mNotificationData; @Before public void setUp() throws Exception { @@ -93,6 +94,7 @@ public class BubbleControllerTest extends SysuiTestCase { // Return non-null notification data from the NEM when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData); + when(mNotificationData.getChannel(mRow.getEntry().key)).thenReturn(mRow.getEntry().channel); mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController); @@ -103,11 +105,6 @@ public class BubbleControllerTest extends SysuiTestCase { } @Test - public void testIsBubble() { - assertTrue(mRow.getEntry().isBubble()); - } - - @Test public void testAddBubble() { mBubbleController.addBubble(mRow.getEntry()); assertTrue(mBubbleController.hasBubbles()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java index 529da8251c57..2b13f864b9a5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java @@ -17,13 +17,16 @@ package com.android.systemui.statusbar; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; +import static android.app.NotificationManager.IMPORTANCE_HIGH; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.Instrumentation; import android.app.Notification; import android.app.NotificationChannel; +import android.app.PendingIntent; import android.content.Context; +import android.content.Intent; import android.os.UserHandle; import android.service.notification.StatusBarNotification; import android.support.test.InstrumentationRegistry; @@ -86,8 +89,7 @@ public class NotificationTestHelper { * @throws Exception */ public ExpandableNotificationRow createRow(String pkg, int uid) throws Exception { - return createRow(pkg, uid, false /* isGroupSummary */, null /* groupKey */, - false /* isBubble */); + return createRow(pkg, uid, false /* isGroupSummary */, null /* groupKey */); } /** @@ -98,8 +100,7 @@ public class NotificationTestHelper { * @throws Exception */ public ExpandableNotificationRow createRow(Notification notification) throws Exception { - return generateRow(notification, PKG, UID, 0 /* extraInflationFlags */, - false /* isBubble */); + return generateRow(notification, PKG, UID, 0 /* extraInflationFlags */); } /** @@ -112,8 +113,7 @@ public class NotificationTestHelper { */ public ExpandableNotificationRow createRow(@InflationFlag int extraInflationFlags) throws Exception { - return generateRow(createNotification(), PKG, UID, extraInflationFlags, - false /* isBubble */); + return generateRow(createNotification(), PKG, UID, extraInflationFlags); } /** @@ -134,20 +134,21 @@ public class NotificationTestHelper { return createGroup(2); } - /** - * Retursn an {@link ExpandableNotificationRow} that should be a bubble. - */ - public ExpandableNotificationRow createBubble() throws Exception { - return createRow(PKG, UID, false /* isGroupSummary */, null /* groupKey */, - true /* isBubble */); - } - private ExpandableNotificationRow createGroupSummary(String groupkey) throws Exception { - return createRow(PKG, UID, true /* isGroupSummary */, groupkey, false); + return createRow(PKG, UID, true /* isGroupSummary */, groupkey); } private ExpandableNotificationRow createGroupChild(String groupkey) throws Exception { - return createRow(PKG, UID, false /* isGroupSummary */, groupkey, false); + return createRow(PKG, UID, false /* isGroupSummary */, groupkey); + } + + /** + * Returns an {@link ExpandableNotificationRow} that should be shown as a bubble. + */ + public ExpandableNotificationRow createBubble() throws Exception { + Notification n = createNotification(false /* isGroupSummary */, + null /* groupKey */, true /* isBubble */); + return generateRow(n, PKG, UID, 0 /* extraInflationFlags */, IMPORTANCE_HIGH); } /** @@ -157,7 +158,6 @@ public class NotificationTestHelper { * @param uid uid used for creating a {@link StatusBarNotification} * @param isGroupSummary whether the notification row is a group summary * @param groupKey the group key for the notification group used across notifications - * @param isBubble * @return a row with that's either a standalone notification or a group notification if the * groupKey is non-null * @throws Exception @@ -166,10 +166,10 @@ public class NotificationTestHelper { String pkg, int uid, boolean isGroupSummary, - @Nullable String groupKey, boolean isBubble) + @Nullable String groupKey) throws Exception { Notification notif = createNotification(isGroupSummary, groupKey); - return generateRow(notif, pkg, uid, 0 /* inflationFlags */, isBubble); + return generateRow(notif, pkg, uid, 0 /* inflationFlags */); } /** @@ -188,8 +188,20 @@ public class NotificationTestHelper { * @param groupKey the group key for the notification group used across notifications * @return a notification that is in the group specified or standalone if unspecified */ + private Notification createNotification(boolean isGroupSummary, @Nullable String groupKey) { + return createNotification(isGroupSummary, groupKey, false /* isBubble */); + } + + /** + * Creates a notification with the given parameters. + * + * @param isGroupSummary whether the notification is a group summary + * @param groupKey the group key for the notification group used across notifications + * @param isBubble whether this notification should bubble + * @return a notification that is in the group specified or standalone if unspecified + */ private Notification createNotification(boolean isGroupSummary, - @Nullable String groupKey) { + @Nullable String groupKey, boolean isBubble) { Notification publicVersion = new Notification.Builder(mContext).setSmallIcon( R.drawable.ic_person) .setCustomContentView(new RemoteViews(mContext.getPackageName(), @@ -207,6 +219,10 @@ public class NotificationTestHelper { if (!TextUtils.isEmpty(groupKey)) { notificationBuilder.setGroup(groupKey); } + if (isBubble) { + PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); + notificationBuilder.setAppOverlayIntent(bubbleIntent); + } return notificationBuilder.build(); } @@ -214,7 +230,17 @@ public class NotificationTestHelper { Notification notification, String pkg, int uid, - @InflationFlag int extraInflationFlags, boolean isBubble) + @InflationFlag int extraInflationFlags) + throws Exception { + return generateRow(notification, pkg, uid, extraInflationFlags, IMPORTANCE_DEFAULT); + } + + private ExpandableNotificationRow generateRow( + Notification notification, + String pkg, + int uid, + @InflationFlag int extraInflationFlags, + int importance) throws Exception { LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( mContext.LAYOUT_INFLATER_SERVICE); @@ -242,9 +268,8 @@ public class NotificationTestHelper { entry.setRow(row); entry.createIcons(mContext, sbn); entry.channel = new NotificationChannel( - notification.getChannelId(), notification.getChannelId(), IMPORTANCE_DEFAULT); + notification.getChannelId(), notification.getChannelId(), importance); entry.channel.setBlockableSystem(true); - entry.setIsBubble(isBubble); row.setEntry(entry); row.getNotificationInflater().addInflationFlags(extraInflationFlags); NotificationInflaterTest.runThenWaitForInflation( diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index c68e0f98325e..2d977269207c 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -2313,8 +2313,8 @@ public class NotificationManagerService extends SystemService { @Override public boolean areAppOverlaysAllowedForPackage(String pkg, int uid) { - checkCallerIsSystemOrSameApp(pkg); - + enforceSystemOrSystemUIOrSamePackage("Caller not system or systemui or same package", + pkg); return mPreferencesHelper.areAppOverlaysAllowed(pkg, uid); } |