summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Nate Myren <ntmyren@google.com> 2024-02-21 16:48:29 -0800
committer Nate Myren <ntmyren@google.com> 2024-03-11 11:16:10 -0700
commit8a87c56fb4246174d0b4e70cf50c819e2dcd046d (patch)
treefa86775ad3d31163985b357261147c7d8988aa24
parent0ba51e0896ac86f5faea3cd779155d1ed2188cba (diff)
Log sensitive notification adjustments
Fixes: 326651373 Test: atest NotificationManagerServiceTest Change-Id: I24014560da9a5ed3d25b0b9fe01374e873360b9f
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java22
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java46
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java25
3 files changed, 89 insertions, 4 deletions
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b98424cfade4..f4cb1035e045 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -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;
@@ -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;
@@ -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
@@ -6394,7 +6401,7 @@ public class NotificationManagerService extends SystemService {
}
}
if (!foundEnqueued) {
- applyAdjustmentFromAssistant(token, adjustment);
+ applyAdjustmentsFromAssistant(token, List.of(adjustment));
}
}
} finally {
@@ -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.
@@ -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;
}
@@ -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()));
+ }
}
}
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 03f27493c3c7..d983dc87a3ca 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -6223,6 +6223,52 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@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(
NotificationManagerService.WorkerHandler.class);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java b/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
index 6976ec3b0465..07d25dfd814e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
@@ -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);
@@ -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) {
@@ -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);
}