From c5561c9c5c8aac7b257adfcac7c66a872865cb8c Mon Sep 17 00:00:00 2001 From: Mady Mellor Date: Mon, 1 Feb 2021 11:22:40 -0800 Subject: [PATCH] API: Expose whether bubbles are enabled or not There's no way for devs to check whether the user has disabled or enabled bubbles at the feature level. This adds an API for devs to make this query. Test: atest NotificationManagerTest NotificationManagerServiceTest Bug: 171162184 Change-Id: I3b201e8267f36b45473987db773c08663b8d8126 --- core/api/current.txt | 1 + .../android/app/INotificationManager.aidl | 1 + .../java/android/app/NotificationManager.java | 16 ++++++++++- .../NotificationManagerService.java | 14 ++++++++++ .../NotificationManagerServiceTest.java | 28 +++++++++++++++++++ 5 files changed, 59 insertions(+), 1 deletion(-) diff --git a/core/api/current.txt b/core/api/current.txt index acd1e99de8495..19a22adb797ee 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -6195,6 +6195,7 @@ package android.app { public class NotificationManager { method public String addAutomaticZenRule(android.app.AutomaticZenRule); method @Deprecated public boolean areBubblesAllowed(); + method public boolean areBubblesEnabled(); method public boolean areNotificationsEnabled(); method public boolean areNotificationsPaused(); method public boolean canNotifyAsPackage(@NonNull String); diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index bda2fa9b96229..f497b62a3f3b4 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -85,6 +85,7 @@ interface INotificationManager void setBubblesAllowed(String pkg, int uid, int bubblePreference); boolean areBubblesAllowed(String pkg); + boolean areBubblesEnabled(in UserHandle user); int getBubblePreferenceForPackage(String pkg, int uid); void createNotificationChannelGroups(String pkg, in ParceledListSlice channelGroupList); diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 6cce270bc5a3f..f0d580f066d88 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -1326,7 +1326,6 @@ public class NotificationManager { } } - /** * Gets whether all notifications posted by this app can appear outside of the * notification shade, floating over other apps' content. @@ -1347,6 +1346,21 @@ public class NotificationManager { } } + /** + * Returns whether bubbles are enabled at the feature level for the current user. When enabled, + * notifications able to bubble will display an affordance allowing the user to bubble them. + * + * @see Notification.Builder#setBubbleMetadata(Notification.BubbleMetadata) + */ + public boolean areBubblesEnabled() { + INotificationManager service = getService(); + try { + return service.areBubblesEnabled(mContext.getUser()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Gets the bubble preference for the app. This preference only applies to notifications that * have been properly configured to bubble. diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 08dbd77708a4a..191d24898f7fd 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -3304,6 +3304,20 @@ public class NotificationManagerService extends SystemService { == BUBBLE_PREFERENCE_ALL; } + /** + * @return true if this user has bubbles enabled at the feature-level. + */ + @Override + public boolean areBubblesEnabled(UserHandle user) { + if (UserHandle.getCallingUserId() != user.getIdentifier()) { + getContext().enforceCallingPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS, + "areBubblesEnabled for user " + user.getIdentifier()); + } + // TODO: incorporate uid / per-user prefs once settings moves off global table. + return mPreferencesHelper.bubblesEnabled(); + } + @Override public int getBubblePreferenceForPackage(String pkg, int uid) { enforceSystemOrSystemUIOrSamePackage(pkg, diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 55ebe11e4ca8f..dc6babcc25d2f 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -4706,6 +4706,34 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertFalse(mBinderService.areBubblesAllowed(PKG)); } + @Test + public void testAreBubblesEnabled() throws Exception { + assertTrue(mBinderService.areBubblesEnabled(UserHandle.getUserHandleForUid(mUid))); + } + + @Test + public void testAreBubblesEnabled_false() throws Exception { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.NOTIFICATION_BUBBLES, 0); + mService.mPreferencesHelper.updateBubblesEnabled(); + assertFalse(mBinderService.areBubblesEnabled(UserHandle.getUserHandleForUid(mUid))); + } + + @Test + public void testAreBubblesEnabled_exception() throws Exception { + try { + assertTrue(mBinderService.areBubblesEnabled( + UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE))); + fail("Cannot call cross user without permission"); + } catch (SecurityException e) { + // pass + } + // cross user, with permission, no problem + enableInteractAcrossUsers(); + assertTrue(mBinderService.areBubblesEnabled( + UserHandle.getUserHandleForUid(mUid + UserHandle.PER_USER_RANGE))); + } + @Test public void testIsCallerInstantApp_primaryUser() throws Exception { ApplicationInfo info = new ApplicationInfo();