Framework changes to enable Notification listeners on Android Go.
Bug: 148575561
Test: atest
com.android.server.notification.NotificationManagerServiceTest, atest com.android.server.notification.NotificationTest
Change-Id: I1b24b2c8e9c6dd96dcd7be209bae2df7c0ed76b5
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 576b56f..32e7d84 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -6046,21 +6046,18 @@
/**
* Removes RemoteViews that were created for compatibility from {@param n}, if they did not
- * change. Also removes extenders on low ram devices, as
- * {@link android.service.notification.NotificationListenerService} services are disabled.
+ * change.
*
* @return {@param n}, if no stripping is needed, otherwise a stripped clone of {@param n}.
*
* @hide
*/
- public static Notification maybeCloneStrippedForDelivery(Notification n, boolean isLowRam,
- Context context) {
+ public static Notification maybeCloneStrippedForDelivery(Notification n) {
String templateClass = n.extras.getString(EXTRA_TEMPLATE);
// Only strip views for known Styles because we won't know how to
// re-create them otherwise.
- if (!isLowRam
- && !TextUtils.isEmpty(templateClass)
+ if (!TextUtils.isEmpty(templateClass)
&& getNotificationStyleClass(templateClass) == null) {
return n;
}
@@ -6077,8 +6074,7 @@
n.headsUpContentView.getSequenceNumber();
// Nothing to do here, no need to clone.
- if (!isLowRam
- && !stripContentView && !stripBigContentView && !stripHeadsUpContentView) {
+ if (!stripContentView && !stripBigContentView && !stripHeadsUpContentView) {
return n;
}
@@ -6095,15 +6091,6 @@
clone.headsUpContentView = null;
clone.extras.remove(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT);
}
- if (isLowRam) {
- String[] allowedServices = context.getResources().getStringArray(
- R.array.config_allowedManagedServicesOnLowRamDevices);
- if (allowedServices.length == 0) {
- clone.extras.remove(Notification.TvExtender.EXTRA_TV_EXTENDER);
- clone.extras.remove(WearableExtender.EXTRA_WEARABLE_EXTENSIONS);
- clone.extras.remove(CarExtender.EXTRA_CAR_EXTENDER);
- }
- }
return clone;
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 528b508..88edb05 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -592,10 +592,7 @@
}
notification.reduceImageSizes(mContext);
-
- ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
- boolean isLowRam = am.isLowRamDevice();
- return Builder.maybeCloneStrippedForDelivery(notification, isLowRam, mContext);
+ return Builder.maybeCloneStrippedForDelivery(notification);
}
private void fixLegacySmallIcon(Notification n, String pkg) {
diff --git a/core/java/android/service/notification/ConditionProviderService.java b/core/java/android/service/notification/ConditionProviderService.java
index 7d3b13b..f37e01d 100644
--- a/core/java/android/service/notification/ConditionProviderService.java
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -58,7 +58,7 @@
* </service></pre>
*
* <p> Condition providers cannot be bound by the system on
- * {@link ActivityManager#isLowRamDevice() low ram} devices</p>
+ * {@link ActivityManager#isLowRamDevice() low ram} devices running Android Q (and below)</p>
*
* @deprecated Instead of using an automatically bound service, use
* {@link android.app.NotificationManager#setAutomaticZenRuleState(String, Condition)} to tell the
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 0ff2e03..6562572 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -86,8 +86,8 @@
* or after {@link #onListenerDisconnected()}.
* </p>
* <p> Notification listeners cannot get notification access or be bound by the system on
- * {@linkplain ActivityManager#isLowRamDevice() low-RAM} devices. The system also ignores
- * notification listeners running in a work profile. A
+ * {@linkplain ActivityManager#isLowRamDevice() low-RAM} devices running Android Q (and below).
+ * The system also ignores notification listeners running in a work profile. A
* {@link android.app.admin.DevicePolicyManager} might block notifications originating from a work
* profile.</p>
* <p>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b82591f..c15b794 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3534,9 +3534,6 @@
<item>com.android.dialer</item>
</string-array>
- <!-- An array of packages which can listen for notifications on low ram devices. -->
- <string-array translatable="false" name="config_allowedManagedServicesOnLowRamDevices" />
-
<!-- The default value for transition animation scale found in developer settings.
1.0 corresponds to 1x animator scale, 0 means that there will be no transition
animations. Note that this is only a default and will be overridden by a
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 89cc770..b8dd418 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3167,8 +3167,6 @@
<java-symbol type="array" name="config_nonBlockableNotificationPackages" />
<java-symbol type="array" name="config_priorityOnlyDndExemptPackages" />
- <java-symbol type="array" name="config_allowedManagedServicesOnLowRamDevices" />
-
<!-- Screen-size-dependent modes for picker dialogs. -->
<java-symbol type="integer" name="time_picker_mode" />
<java-symbol type="integer" name="date_picker_mode" />
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ad4e81b..fd86f1d 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -8609,21 +8609,11 @@
@VisibleForTesting
boolean canUseManagedServices(String pkg, Integer userId, String requiredPermission) {
- boolean canUseManagedServices = !mActivityManager.isLowRamDevice()
- || mPackageManagerClient.hasSystemFeature(PackageManager.FEATURE_WATCH);
-
- for (String whitelisted : getContext().getResources().getStringArray(
- R.array.config_allowedManagedServicesOnLowRamDevices)) {
- if (whitelisted.equals(pkg)) {
- canUseManagedServices = true;
- break;
- }
- }
-
+ boolean canUseManagedServices = true;
if (requiredPermission != null) {
try {
if (mPackageManager.checkPermission(requiredPermission, pkg, userId)
- != PackageManager.PERMISSION_GRANTED) {
+ != PackageManager.PERMISSION_GRANTED) {
canUseManagedServices = false;
}
} catch (RemoteException e) {
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 e5ffb4d..604fcd3 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -2902,21 +2902,21 @@
}
@Test
- public void testSetListenerAccess_doesNothingOnLowRam() throws Exception {
+ public void testSetListenerAccess_onLowRam() throws Exception {
when(mActivityManager.isLowRamDevice()).thenReturn(true);
ComponentName c = ComponentName.unflattenFromString("package/Component");
mBinderService.setNotificationListenerAccessGranted(c, true);
- verify(mListeners, never()).setPackageOrComponentEnabled(
+ verify(mListeners).setPackageOrComponentEnabled(
anyString(), anyInt(), anyBoolean(), anyBoolean());
- verify(mConditionProviders, never()).setPackageOrComponentEnabled(
+ verify(mConditionProviders).setPackageOrComponentEnabled(
anyString(), anyInt(), anyBoolean(), anyBoolean());
- verify(mAssistants, never()).setPackageOrComponentEnabled(
- any(), anyInt(), anyBoolean(), anyBoolean());
+ verify(mAssistants).migrateToXml();
+ verify(mAssistants).resetDefaultAssistantsIfNecessary();
}
@Test
- public void testSetAssistantAccess_doesNothingOnLowRam() throws Exception {
+ public void testSetAssistantAccess_onLowRam() throws Exception {
when(mActivityManager.isLowRamDevice()).thenReturn(true);
ComponentName c = ComponentName.unflattenFromString("package/Component");
List<UserInfo> uis = new ArrayList<>();
@@ -2927,26 +2927,28 @@
mBinderService.setNotificationAssistantAccessGranted(c, true);
- verify(mListeners, never()).setPackageOrComponentEnabled(
+ verify(mListeners).migrateToXml();
+ verify(mListeners).notifyNotificationChannelChanged(anyString(), any(), any(),
+ anyInt());
+ verify(mConditionProviders).setPackageOrComponentEnabled(
anyString(), anyInt(), anyBoolean(), anyBoolean());
- verify(mConditionProviders, never()).setPackageOrComponentEnabled(
- anyString(), anyInt(), anyBoolean(), anyBoolean());
- verify(mAssistants, never()).setPackageOrComponentEnabled(
- any(), anyInt(), anyBoolean(), anyBoolean());
+ verify(mAssistants).migrateToXml();
+ verify(mAssistants).resetDefaultAssistantsIfNecessary();
}
@Test
- public void testSetDndAccess_doesNothingOnLowRam() throws Exception {
+ public void testSetDndAccess_onLowRam() throws Exception {
when(mActivityManager.isLowRamDevice()).thenReturn(true);
ComponentName c = ComponentName.unflattenFromString("package/Component");
mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
- verify(mListeners, never()).setPackageOrComponentEnabled(
+ verify(mListeners).migrateToXml();
+ verify(mListeners).notifyNotificationChannelChanged(anyString(), any(), any(),
+ anyInt());
+ verify(mConditionProviders).setPackageOrComponentEnabled(
anyString(), anyInt(), anyBoolean(), anyBoolean());
- verify(mConditionProviders, never()).setPackageOrComponentEnabled(
- anyString(), anyInt(), anyBoolean(), anyBoolean());
- verify(mAssistants, never()).setPackageOrComponentEnabled(
- any(), anyInt(), anyBoolean(), anyBoolean());
+ verify(mAssistants).migrateToXml();
+ verify(mAssistants).resetDefaultAssistantsIfNecessary();
}
@Test
@@ -4288,68 +4290,13 @@
}
@Test
- public void testCanUseManagedServicesLowRamNoWatchNullPkg() {
- when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
- when(mActivityManager.isLowRamDevice()).thenReturn(true);
- when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
- .thenReturn(new String[] {"a", "b", "c"});
- when(mContext.getResources()).thenReturn(mResources);
-
- assertEquals(false, mService.canUseManagedServices(null, 0, null));
+ public void testCanUseManagedServicesNullPkg() {
+ assertEquals(true, mService.canUseManagedServices(null, 0, null));
}
- @Test
- public void testCanUseManagedServicesLowRamNoWatchValidPkg() {
- when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
- when(mActivityManager.isLowRamDevice()).thenReturn(true);
- when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
- .thenReturn(new String[] {"a", "b", "c"});
- when(mContext.getResources()).thenReturn(mResources);
-
- assertEquals(true, mService.canUseManagedServices("b", 0, null));
- }
@Test
- public void testCanUseManagedServicesLowRamNoWatchNoValidPkg() {
- when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
- when(mActivityManager.isLowRamDevice()).thenReturn(true);
- when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
- .thenReturn(new String[] {"a", "b", "c"});
- when(mContext.getResources()).thenReturn(mResources);
-
- assertEquals(false, mService.canUseManagedServices("d", 0, null));
- }
-
- @Test
- public void testCanUseManagedServicesLowRamWatchNoValidPkg() {
- when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
- when(mActivityManager.isLowRamDevice()).thenReturn(true);
- when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
- .thenReturn(new String[] {"a", "b", "c"});
- when(mContext.getResources()).thenReturn(mResources);
-
- assertEquals(true, mService.canUseManagedServices("d", 0, null));
- }
-
- @Test
- public void testCanUseManagedServicesNoLowRamNoWatchValidPkg() {
- when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
- when(mActivityManager.isLowRamDevice()).thenReturn(false);
- when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
- .thenReturn(new String[] {"a", "b", "c"});
- when(mContext.getResources()).thenReturn(mResources);
-
- assertEquals(true, mService.canUseManagedServices("d", 0 , null));
- }
-
- @Test
- public void testCanUseManagedServicesNoLowRamWatchValidPkg() {
- when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
- when(mActivityManager.isLowRamDevice()).thenReturn(false);
- when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
- .thenReturn(new String[] {"a", "b", "c"});
- when(mContext.getResources()).thenReturn(mResources);
-
+ public void testCanUseManagedServicesNoValidPkg() {
assertEquals(true, mService.canUseManagedServices("d", 0, null));
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
index 0ea53fa..d765042 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
@@ -22,9 +22,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
@@ -32,15 +30,12 @@
import android.app.PendingIntent;
import android.app.Person;
import android.app.RemoteInput;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Icon;
import android.net.Uri;
-import android.os.Build;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.StyleSpan;
@@ -74,91 +69,13 @@
}
@Test
- public void testStripsExtendersInLowRamModeNoWhitelistNoTv() {
+ public void testDoesNotStripsExtenders() {
Notification.Builder nb = new Notification.Builder(mContext, "channel");
nb.extend(new Notification.CarExtender().setColor(Color.RED));
nb.extend(new Notification.TvExtender().setChannelId("different channel"));
nb.extend(new Notification.WearableExtender().setDismissalId("dismiss"));
Notification before = nb.build();
-
- // No whitelist
- Context context = spy(getContext());
- when(context.getResources()).thenReturn(mResources);
- when(mResources.getStringArray(anyInt())).thenReturn(new String[0]);
-
- Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before, true,
- context);
-
- assertEquals("different channel", new Notification.TvExtender(before).getChannelId());
- assertNull(new Notification.TvExtender(after).getChannelId());
-
- assertEquals(Color.RED, new Notification.CarExtender(before).getColor());
- assertEquals(Notification.COLOR_DEFAULT, new Notification.CarExtender(after).getColor());
-
- assertEquals("dismiss", new Notification.WearableExtender(before).getDismissalId());
- assertNull(new Notification.WearableExtender(after).getDismissalId());
- }
-
- @Test
- public void testStripsExtendersInLowRamModeHasWhitelist() {
- Notification.Builder nb = new Notification.Builder(mContext, "channel");
- nb.extend(new Notification.CarExtender().setColor(Color.RED));
- nb.extend(new Notification.TvExtender().setChannelId("different channel"));
- nb.extend(new Notification.WearableExtender().setDismissalId("dismiss"));
- Notification before = nb.build();
-
- // Has whitelist
- Context context = spy(mContext);
- when(context.getResources()).thenReturn(mResources);
- when(mResources.getStringArray(anyInt())).thenReturn(new String[1]);
-
- Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before, true,
- context);
-
- assertEquals("different channel", new Notification.TvExtender(before).getChannelId());
- assertEquals("different channel", new Notification.TvExtender(after).getChannelId());
-
- assertEquals(Color.RED, new Notification.CarExtender(before).getColor());
- assertEquals(Color.RED, new Notification.CarExtender(after).getColor());
-
- assertEquals("dismiss", new Notification.WearableExtender(before).getDismissalId());
- assertEquals("dismiss", new Notification.WearableExtender(after).getDismissalId());
- }
-
- @Test
- public void testStripsRemoteViewsInLowRamMode() {
- Context context = spy(mContext);
- ApplicationInfo ai = new ApplicationInfo();
- ai.targetSdkVersion = Build.VERSION_CODES.M;
- when(context.getApplicationInfo()).thenReturn(ai);
-
- final Notification.BigTextStyle style = new Notification.BigTextStyle()
- .bigText("hello")
- .setSummaryText("And the summary");
- Notification before = new Notification.Builder(context, "channel")
- .setContentText("hi")
- .setStyle(style)
- .build();
-
- Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before, true,
- mContext);
- assertNotNull(before.contentView);
- assertNotNull(before.bigContentView);
- assertNotNull(before.headsUpContentView);
- assertNull(after.contentView);
- assertNull(after.bigContentView);
- assertNull(after.headsUpContentView);
- }
-
- @Test
- public void testDoesNotStripsExtendersInNormalRamMode() {
- Notification.Builder nb = new Notification.Builder(mContext, "channel");
- nb.extend(new Notification.CarExtender().setColor(Color.RED));
- nb.extend(new Notification.TvExtender().setChannelId("different channel"));
- nb.extend(new Notification.WearableExtender().setDismissalId("dismiss"));
- Notification before = nb.build();
- Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before, false,
- mContext);
+ Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before);
assertTrue(before == after);