Loading services/core/java/com/android/server/notification/NotificationRecord.java +12 −0 Original line number Diff line number Diff line Loading @@ -1289,6 +1289,18 @@ public final class NotificationRecord { return getLogMaker().setCategory(MetricsEvent.NOTIFICATION_ITEM); } public boolean hasUndecoratedRemoteView() { Notification notification = getNotification(); Class<? extends Notification.Style> style = notification.getNotificationStyle(); boolean hasDecoratedStyle = style != null && (Notification.DecoratedCustomViewStyle.class.equals(style) || Notification.DecoratedMediaCustomViewStyle.class.equals(style)); boolean hasCustomRemoteView = notification.contentView != null || notification.bigContentView != null || notification.headsUpContentView != null; return hasCustomRemoteView && !hasDecoratedStyle; } @VisibleForTesting static final class Light { public final int color; Loading services/core/java/com/android/server/notification/NotificationUsageStats.java +2 −9 Original line number Diff line number Diff line Loading @@ -150,7 +150,7 @@ public class NotificationUsageStats { stats.numPostedByApp++; stats.updateInterarrivalEstimate(now); stats.countApiUse(notification); stats.numUndecoratedRemoteViews += (isUndecoratedRemoteView(notification) ? 1 : 0); stats.numUndecoratedRemoteViews += (notification.hasUndecoratedRemoteView() ? 1 : 0); } releaseAggregatedStatsLocked(aggregatedStatsArray); if (ENABLE_SQLITE_LOG) { Loading @@ -158,13 +158,6 @@ public class NotificationUsageStats { } } /** * Does this notification use RemoveViews without a platform decoration? */ protected static boolean isUndecoratedRemoteView(NotificationRecord notification) { return (notification.getNotification().getNotificationStyle() == null); } /** * Called when a notification has been updated. */ Loading Loading @@ -1287,7 +1280,7 @@ public class NotificationUsageStats { } else { putPosttimeVisibility(r, cv); } cv.put(COL_UNDECORATED, (isUndecoratedRemoteView(r) ? 1 : 0)); cv.put(COL_UNDECORATED, (r.hasUndecoratedRemoteView() ? 1 : 0)); SQLiteDatabase db = mHelper.getWritableDatabase(); if (db.insert(TAB_LOG, null, cv) < 0) { Log.wtf(TAG, "Error while trying to insert values: " + cv); Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java +97 −1 Original line number Diff line number Diff line Loading @@ -52,11 +52,13 @@ import android.graphics.drawable.Icon; import android.media.AudioAttributes; import android.metrics.LogMaker; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.UserHandle; import android.provider.Settings; import android.service.notification.Adjustment; import android.service.notification.StatusBarNotification; import android.widget.RemoteViews; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; Loading Loading @@ -114,7 +116,9 @@ public class NotificationRecordTest extends UiServiceTestCase { when(mMockContext.getResources()).thenReturn(getContext().getResources()); when(mMockContext.getPackageManager()).thenReturn(mPm); when(mMockContext.getApplicationInfo()).thenReturn(new ApplicationInfo()); ApplicationInfo appInfo = new ApplicationInfo(); appInfo.targetSdkVersion = Build.VERSION_CODES.O; when(mMockContext.getApplicationInfo()).thenReturn(appInfo); } private StatusBarNotification getNotification(String pkg, boolean noisy, boolean defaultSound, Loading Loading @@ -168,6 +172,28 @@ public class NotificationRecordTest extends UiServiceTestCase { return new StatusBarNotification(pkg, pkg, id1, tag1, uid, uid, n, mUser, null, uid); } private StatusBarNotification getStyledNotification(boolean customContent, boolean customBig, boolean customHeadsUp, Notification.Style style) { final Builder builder = new Builder(mMockContext) .setContentTitle("foo") .setSmallIcon(android.R.drawable.sym_def_app_icon); if (style != null) { builder.setStyle(style); } if (customContent) { builder.setCustomContentView(mock(RemoteViews.class)); } if (customBig) { builder.setCustomBigContentView(mock(RemoteViews.class)); } if (customHeadsUp) { builder.setCustomHeadsUpContentView(mock(RemoteViews.class)); } Notification n = builder.build(); return new StatusBarNotification(pkg, pkg, id1, tag1, uid, uid, n, mUser, null, uid); } // // Tests // Loading Loading @@ -999,4 +1025,74 @@ public class NotificationRecordTest extends UiServiceTestCase { assertEquals(IMPORTANCE_LOW, record.getImportance()); } @Test public void testHasUndecoratedRemoteViews_NoRemoteViews() { StatusBarNotification sbn = getStyledNotification(false, false, false, null); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); assertFalse("false positive detection", record.hasUndecoratedRemoteView()); } @Test public void testHasUndecoratedRemoteViews_NoRemoteViewsWithStyle() { StatusBarNotification sbn = getStyledNotification(false, false, false, new Notification.BigPictureStyle()); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); assertFalse("false positive detection", record.hasUndecoratedRemoteView()); } @Test public void testHasUndecoratedRemoteViews_UndecoratedContent() { StatusBarNotification sbn = getStyledNotification(true, false, false, null); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); assertTrue("false negative detection", record.hasUndecoratedRemoteView()); } @Test public void testHasUndecoratedRemoteViews_UndecoratedBig() { StatusBarNotification sbn = getStyledNotification(false, true, false, null); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); assertTrue("false negative detection", record.hasUndecoratedRemoteView()); } @Test public void testHasUndecoratedRemoteViews_UndecoratedHeadsup() { StatusBarNotification sbn = getStyledNotification(false, false, true, null); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); assertTrue("false negative detection", record.hasUndecoratedRemoteView()); } @Test public void testHasUndecoratedRemoteViews_DecoratedRemoteViews() { StatusBarNotification sbn = getStyledNotification(true, true, true, new Notification.DecoratedCustomViewStyle()); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); assertFalse("false positive detection", record.hasUndecoratedRemoteView()); } @Test public void testHasUndecoratedRemoteViews_DecoratedMediaRemoteViews() { StatusBarNotification sbn = getStyledNotification(true, true, true, new Notification.DecoratedMediaCustomViewStyle()); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); assertFalse("false positive detection", record.hasUndecoratedRemoteView()); } @Test public void testHasUndecoratedRemoteViews_UndecoratedWrongStyle() { StatusBarNotification sbn = getStyledNotification(true, true, true, new Notification.BigPictureStyle()); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); assertTrue("false negative detection", record.hasUndecoratedRemoteView()); } } Loading
services/core/java/com/android/server/notification/NotificationRecord.java +12 −0 Original line number Diff line number Diff line Loading @@ -1289,6 +1289,18 @@ public final class NotificationRecord { return getLogMaker().setCategory(MetricsEvent.NOTIFICATION_ITEM); } public boolean hasUndecoratedRemoteView() { Notification notification = getNotification(); Class<? extends Notification.Style> style = notification.getNotificationStyle(); boolean hasDecoratedStyle = style != null && (Notification.DecoratedCustomViewStyle.class.equals(style) || Notification.DecoratedMediaCustomViewStyle.class.equals(style)); boolean hasCustomRemoteView = notification.contentView != null || notification.bigContentView != null || notification.headsUpContentView != null; return hasCustomRemoteView && !hasDecoratedStyle; } @VisibleForTesting static final class Light { public final int color; Loading
services/core/java/com/android/server/notification/NotificationUsageStats.java +2 −9 Original line number Diff line number Diff line Loading @@ -150,7 +150,7 @@ public class NotificationUsageStats { stats.numPostedByApp++; stats.updateInterarrivalEstimate(now); stats.countApiUse(notification); stats.numUndecoratedRemoteViews += (isUndecoratedRemoteView(notification) ? 1 : 0); stats.numUndecoratedRemoteViews += (notification.hasUndecoratedRemoteView() ? 1 : 0); } releaseAggregatedStatsLocked(aggregatedStatsArray); if (ENABLE_SQLITE_LOG) { Loading @@ -158,13 +158,6 @@ public class NotificationUsageStats { } } /** * Does this notification use RemoveViews without a platform decoration? */ protected static boolean isUndecoratedRemoteView(NotificationRecord notification) { return (notification.getNotification().getNotificationStyle() == null); } /** * Called when a notification has been updated. */ Loading Loading @@ -1287,7 +1280,7 @@ public class NotificationUsageStats { } else { putPosttimeVisibility(r, cv); } cv.put(COL_UNDECORATED, (isUndecoratedRemoteView(r) ? 1 : 0)); cv.put(COL_UNDECORATED, (r.hasUndecoratedRemoteView() ? 1 : 0)); SQLiteDatabase db = mHelper.getWritableDatabase(); if (db.insert(TAB_LOG, null, cv) < 0) { Log.wtf(TAG, "Error while trying to insert values: " + cv); Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java +97 −1 Original line number Diff line number Diff line Loading @@ -52,11 +52,13 @@ import android.graphics.drawable.Icon; import android.media.AudioAttributes; import android.metrics.LogMaker; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.UserHandle; import android.provider.Settings; import android.service.notification.Adjustment; import android.service.notification.StatusBarNotification; import android.widget.RemoteViews; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; Loading Loading @@ -114,7 +116,9 @@ public class NotificationRecordTest extends UiServiceTestCase { when(mMockContext.getResources()).thenReturn(getContext().getResources()); when(mMockContext.getPackageManager()).thenReturn(mPm); when(mMockContext.getApplicationInfo()).thenReturn(new ApplicationInfo()); ApplicationInfo appInfo = new ApplicationInfo(); appInfo.targetSdkVersion = Build.VERSION_CODES.O; when(mMockContext.getApplicationInfo()).thenReturn(appInfo); } private StatusBarNotification getNotification(String pkg, boolean noisy, boolean defaultSound, Loading Loading @@ -168,6 +172,28 @@ public class NotificationRecordTest extends UiServiceTestCase { return new StatusBarNotification(pkg, pkg, id1, tag1, uid, uid, n, mUser, null, uid); } private StatusBarNotification getStyledNotification(boolean customContent, boolean customBig, boolean customHeadsUp, Notification.Style style) { final Builder builder = new Builder(mMockContext) .setContentTitle("foo") .setSmallIcon(android.R.drawable.sym_def_app_icon); if (style != null) { builder.setStyle(style); } if (customContent) { builder.setCustomContentView(mock(RemoteViews.class)); } if (customBig) { builder.setCustomBigContentView(mock(RemoteViews.class)); } if (customHeadsUp) { builder.setCustomHeadsUpContentView(mock(RemoteViews.class)); } Notification n = builder.build(); return new StatusBarNotification(pkg, pkg, id1, tag1, uid, uid, n, mUser, null, uid); } // // Tests // Loading Loading @@ -999,4 +1025,74 @@ public class NotificationRecordTest extends UiServiceTestCase { assertEquals(IMPORTANCE_LOW, record.getImportance()); } @Test public void testHasUndecoratedRemoteViews_NoRemoteViews() { StatusBarNotification sbn = getStyledNotification(false, false, false, null); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); assertFalse("false positive detection", record.hasUndecoratedRemoteView()); } @Test public void testHasUndecoratedRemoteViews_NoRemoteViewsWithStyle() { StatusBarNotification sbn = getStyledNotification(false, false, false, new Notification.BigPictureStyle()); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); assertFalse("false positive detection", record.hasUndecoratedRemoteView()); } @Test public void testHasUndecoratedRemoteViews_UndecoratedContent() { StatusBarNotification sbn = getStyledNotification(true, false, false, null); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); assertTrue("false negative detection", record.hasUndecoratedRemoteView()); } @Test public void testHasUndecoratedRemoteViews_UndecoratedBig() { StatusBarNotification sbn = getStyledNotification(false, true, false, null); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); assertTrue("false negative detection", record.hasUndecoratedRemoteView()); } @Test public void testHasUndecoratedRemoteViews_UndecoratedHeadsup() { StatusBarNotification sbn = getStyledNotification(false, false, true, null); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); assertTrue("false negative detection", record.hasUndecoratedRemoteView()); } @Test public void testHasUndecoratedRemoteViews_DecoratedRemoteViews() { StatusBarNotification sbn = getStyledNotification(true, true, true, new Notification.DecoratedCustomViewStyle()); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); assertFalse("false positive detection", record.hasUndecoratedRemoteView()); } @Test public void testHasUndecoratedRemoteViews_DecoratedMediaRemoteViews() { StatusBarNotification sbn = getStyledNotification(true, true, true, new Notification.DecoratedMediaCustomViewStyle()); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); assertFalse("false positive detection", record.hasUndecoratedRemoteView()); } @Test public void testHasUndecoratedRemoteViews_UndecoratedWrongStyle() { StatusBarNotification sbn = getStyledNotification(true, true, true, new Notification.BigPictureStyle()); NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel); assertTrue("false negative detection", record.hasUndecoratedRemoteView()); } }