Loading services/core/java/com/android/server/notification/NotificationManagerService.java +18 −4 Original line number Diff line number Diff line Loading @@ -338,6 +338,7 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import com.android.internal.util.function.TriPredicate; Loading Loading @@ -1825,6 +1826,12 @@ public class NotificationManagerService extends SystemService { } } protected void logSensitiveAdjustmentReceived(boolean hasPosted, boolean hasSensitiveContent, int lifespanMs) { FrameworkStatsLog.write(FrameworkStatsLog.SENSITIVE_NOTIFICATION_REDACTION, hasPosted, hasSensitiveContent, lifespanMs); } @GuardedBy("mNotificationLock") void clearSoundLocked() { mSoundNotificationKey = null; Loading Loading @@ -6384,7 +6391,7 @@ public class NotificationManagerService extends SystemService { if (Objects.equals(adjustment.getKey(), r.getKey()) && Objects.equals(adjustment.getUser(), r.getUserId()) && mAssistants.isSameUser(token, r.getUserId())) { applyAdjustment(r, adjustment); applyAdjustmentLocked(r, adjustment, false); r.applyAdjustments(); // importance is checked at the beginning of the // PostNotificationRunnable, before the signal extractors are run, so Loading @@ -6394,7 +6401,7 @@ public class NotificationManagerService extends SystemService { } } if (!foundEnqueued) { applyAdjustmentFromAssistant(token, adjustment); applyAdjustmentsFromAssistant(token, List.of(adjustment)); } } } finally { Loading Loading @@ -6422,7 +6429,7 @@ public class NotificationManagerService extends SystemService { for (Adjustment adjustment : adjustments) { NotificationRecord r = mNotificationsByKey.get(adjustment.getKey()); if (r != null && mAssistants.isSameUser(token, r.getUserId())) { applyAdjustment(r, adjustment); applyAdjustmentLocked(r, adjustment, true); // If the assistant has blocked the notification, cancel it // This will trigger a sort, so we don't have to explicitly ask for // one here. Loading Loading @@ -6706,7 +6713,9 @@ public class NotificationManagerService extends SystemService { } } private void applyAdjustment(NotificationRecord r, Adjustment adjustment) { @GuardedBy("mNotificationLock") private void applyAdjustmentLocked(NotificationRecord r, Adjustment adjustment, boolean isPosted) { if (r == null) { return; } Loading @@ -6723,6 +6732,11 @@ public class NotificationManagerService extends SystemService { adjustments.remove(removeKey); } r.addAdjustment(adjustment); if (adjustment.getSignals().containsKey(Adjustment.KEY_SENSITIVE_CONTENT)) { logSensitiveAdjustmentReceived(isPosted, adjustment.getSignals().getBoolean(Adjustment.KEY_SENSITIVE_CONTENT), r.getLifespanMs(System.currentTimeMillis())); } } } Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +46 −0 Original line number Diff line number Diff line Loading @@ -6222,6 +6222,52 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(2, mNotificationRecordLogger.get(1).getInstanceId()); } @Test public void testSensitiveAdjustmentsLogged() throws Exception { NotificationManagerService.WorkerHandler handler = mock( NotificationManagerService.WorkerHandler.class); mService.setHandler(handler); when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true); // Set up notifications that will be adjusted final NotificationRecord r1 = spy(generateNotificationRecord( mTestNotificationChannel, 1, null, true)); when(r1.getLifespanMs(anyLong())).thenReturn(1); r1.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); mService.addEnqueuedNotification(r1); // Test an adjustment for an enqueued notification Bundle signals = new Bundle(); signals.putBoolean(Adjustment.KEY_SENSITIVE_CONTENT, true); Adjustment adjustment1 = new Adjustment( r1.getSbn().getPackageName(), r1.getKey(), signals, "", r1.getUser().getIdentifier()); mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment1); assertTrue(mService.checkLastSensitiveLog(false, true, 1)); // Set up notifications that will be adjusted final NotificationRecord r2 = spy(generateNotificationRecord( mTestNotificationChannel, 1, null, true)); when(r2.getLifespanMs(anyLong())).thenReturn(2); r2.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); mService.addNotification(r2); Adjustment adjustment2 = new Adjustment( r2.getSbn().getPackageName(), r2.getKey(), signals, "", r2.getUser().getIdentifier()); mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment2); assertTrue(mService.checkLastSensitiveLog(true, true, 2)); signals.putBoolean(Adjustment.KEY_SENSITIVE_CONTENT, false); Adjustment adjustment3 = new Adjustment( r2.getSbn().getPackageName(), r2.getKey(), signals, "", r2.getUser().getIdentifier()); mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment3); assertTrue(mService.checkLastSensitiveLog(true, false, 2)); } @Test public void testAdjustmentToImportanceNone_cancelsNotification() throws Exception { NotificationManagerService.WorkerHandler handler = mock( Loading services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java +25 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,13 @@ public class TestableNotificationManagerService extends NotificationManagerServi ComponentPermissionChecker permissionChecker; private static class SensitiveLog { public boolean hasPosted; public boolean hasSensitiveContent; public long lifetime; } public SensitiveLog lastSensitiveLog = null; TestableNotificationManagerService(Context context, NotificationRecordLogger logger, InstanceIdSequence notificationInstanceIdSequence) { super(context, logger, notificationInstanceIdSequence); Loading Loading @@ -167,6 +174,15 @@ public class TestableNotificationManagerService extends NotificationManagerServi return permissionChecker.check(permission, uid, owningUid, exported); } @Override protected void logSensitiveAdjustmentReceived(boolean hasPosted, boolean hasSensitiveContent, int lifetimeMs) { lastSensitiveLog = new SensitiveLog(); lastSensitiveLog.hasPosted = hasPosted; lastSensitiveLog.hasSensitiveContent = hasSensitiveContent; lastSensitiveLog.lifetime = lifetimeMs; } public class StrongAuthTrackerFake extends NotificationManagerService.StrongAuthTracker { private int mGetStrongAuthForUserReturnValue = 0; StrongAuthTrackerFake(Context context) { Loading @@ -183,6 +199,15 @@ public class TestableNotificationManagerService extends NotificationManagerServi } } public boolean checkLastSensitiveLog(boolean hasPosted, boolean hasSensitive, int lifetime) { if (lastSensitiveLog == null) { return false; } return hasPosted == lastSensitiveLog.hasPosted && hasSensitive == lastSensitiveLog.hasSensitiveContent && lifetime == lastSensitiveLog.lifetime; } public interface ComponentPermissionChecker { int check(String permission, int uid, int owningUid, boolean exported); } Loading Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +18 −4 Original line number Diff line number Diff line Loading @@ -338,6 +338,7 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import com.android.internal.util.function.TriPredicate; Loading Loading @@ -1825,6 +1826,12 @@ public class NotificationManagerService extends SystemService { } } protected void logSensitiveAdjustmentReceived(boolean hasPosted, boolean hasSensitiveContent, int lifespanMs) { FrameworkStatsLog.write(FrameworkStatsLog.SENSITIVE_NOTIFICATION_REDACTION, hasPosted, hasSensitiveContent, lifespanMs); } @GuardedBy("mNotificationLock") void clearSoundLocked() { mSoundNotificationKey = null; Loading Loading @@ -6384,7 +6391,7 @@ public class NotificationManagerService extends SystemService { if (Objects.equals(adjustment.getKey(), r.getKey()) && Objects.equals(adjustment.getUser(), r.getUserId()) && mAssistants.isSameUser(token, r.getUserId())) { applyAdjustment(r, adjustment); applyAdjustmentLocked(r, adjustment, false); r.applyAdjustments(); // importance is checked at the beginning of the // PostNotificationRunnable, before the signal extractors are run, so Loading @@ -6394,7 +6401,7 @@ public class NotificationManagerService extends SystemService { } } if (!foundEnqueued) { applyAdjustmentFromAssistant(token, adjustment); applyAdjustmentsFromAssistant(token, List.of(adjustment)); } } } finally { Loading Loading @@ -6422,7 +6429,7 @@ public class NotificationManagerService extends SystemService { for (Adjustment adjustment : adjustments) { NotificationRecord r = mNotificationsByKey.get(adjustment.getKey()); if (r != null && mAssistants.isSameUser(token, r.getUserId())) { applyAdjustment(r, adjustment); applyAdjustmentLocked(r, adjustment, true); // If the assistant has blocked the notification, cancel it // This will trigger a sort, so we don't have to explicitly ask for // one here. Loading Loading @@ -6706,7 +6713,9 @@ public class NotificationManagerService extends SystemService { } } private void applyAdjustment(NotificationRecord r, Adjustment adjustment) { @GuardedBy("mNotificationLock") private void applyAdjustmentLocked(NotificationRecord r, Adjustment adjustment, boolean isPosted) { if (r == null) { return; } Loading @@ -6723,6 +6732,11 @@ public class NotificationManagerService extends SystemService { adjustments.remove(removeKey); } r.addAdjustment(adjustment); if (adjustment.getSignals().containsKey(Adjustment.KEY_SENSITIVE_CONTENT)) { logSensitiveAdjustmentReceived(isPosted, adjustment.getSignals().getBoolean(Adjustment.KEY_SENSITIVE_CONTENT), r.getLifespanMs(System.currentTimeMillis())); } } } Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +46 −0 Original line number Diff line number Diff line Loading @@ -6222,6 +6222,52 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(2, mNotificationRecordLogger.get(1).getInstanceId()); } @Test public void testSensitiveAdjustmentsLogged() throws Exception { NotificationManagerService.WorkerHandler handler = mock( NotificationManagerService.WorkerHandler.class); mService.setHandler(handler); when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true); // Set up notifications that will be adjusted final NotificationRecord r1 = spy(generateNotificationRecord( mTestNotificationChannel, 1, null, true)); when(r1.getLifespanMs(anyLong())).thenReturn(1); r1.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); mService.addEnqueuedNotification(r1); // Test an adjustment for an enqueued notification Bundle signals = new Bundle(); signals.putBoolean(Adjustment.KEY_SENSITIVE_CONTENT, true); Adjustment adjustment1 = new Adjustment( r1.getSbn().getPackageName(), r1.getKey(), signals, "", r1.getUser().getIdentifier()); mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment1); assertTrue(mService.checkLastSensitiveLog(false, true, 1)); // Set up notifications that will be adjusted final NotificationRecord r2 = spy(generateNotificationRecord( mTestNotificationChannel, 1, null, true)); when(r2.getLifespanMs(anyLong())).thenReturn(2); r2.getSbn().setInstanceId(mNotificationInstanceIdSequence.newInstanceId()); mService.addNotification(r2); Adjustment adjustment2 = new Adjustment( r2.getSbn().getPackageName(), r2.getKey(), signals, "", r2.getUser().getIdentifier()); mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment2); assertTrue(mService.checkLastSensitiveLog(true, true, 2)); signals.putBoolean(Adjustment.KEY_SENSITIVE_CONTENT, false); Adjustment adjustment3 = new Adjustment( r2.getSbn().getPackageName(), r2.getKey(), signals, "", r2.getUser().getIdentifier()); mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment3); assertTrue(mService.checkLastSensitiveLog(true, false, 2)); } @Test public void testAdjustmentToImportanceNone_cancelsNotification() throws Exception { NotificationManagerService.WorkerHandler handler = mock( Loading
services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java +25 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,13 @@ public class TestableNotificationManagerService extends NotificationManagerServi ComponentPermissionChecker permissionChecker; private static class SensitiveLog { public boolean hasPosted; public boolean hasSensitiveContent; public long lifetime; } public SensitiveLog lastSensitiveLog = null; TestableNotificationManagerService(Context context, NotificationRecordLogger logger, InstanceIdSequence notificationInstanceIdSequence) { super(context, logger, notificationInstanceIdSequence); Loading Loading @@ -167,6 +174,15 @@ public class TestableNotificationManagerService extends NotificationManagerServi return permissionChecker.check(permission, uid, owningUid, exported); } @Override protected void logSensitiveAdjustmentReceived(boolean hasPosted, boolean hasSensitiveContent, int lifetimeMs) { lastSensitiveLog = new SensitiveLog(); lastSensitiveLog.hasPosted = hasPosted; lastSensitiveLog.hasSensitiveContent = hasSensitiveContent; lastSensitiveLog.lifetime = lifetimeMs; } public class StrongAuthTrackerFake extends NotificationManagerService.StrongAuthTracker { private int mGetStrongAuthForUserReturnValue = 0; StrongAuthTrackerFake(Context context) { Loading @@ -183,6 +199,15 @@ public class TestableNotificationManagerService extends NotificationManagerServi } } public boolean checkLastSensitiveLog(boolean hasPosted, boolean hasSensitive, int lifetime) { if (lastSensitiveLog == null) { return false; } return hasPosted == lastSensitiveLog.hasPosted && hasSensitive == lastSensitiveLog.hasSensitiveContent && lifetime == lastSensitiveLog.lifetime; } public interface ComponentPermissionChecker { int check(String permission, int uid, int owningUid, boolean exported); } Loading