summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Will Brockman <brockman@google.com> 2020-01-31 10:30:27 -0500
committer Will Brockman <brockman@google.com> 2020-02-07 16:03:49 -0500
commit75c6057193e923bb2f1e466a8f85fb4f39efec6c (patch)
tree4dde2599111130b54344d4482ba7a1286b5fd866
parent869cb2ad7e8ceae27ceec5ab5bf3f73e90031fcc (diff)
Statsd logging of notification cancels.
Logs notification cancel only if the notification was in fact posted. Uses the UiEventReported framework. Tweaked that framework to handle null InstanceIds better. Bug: 146488473 Test: atest NotificationManagerServiceTest BuzzBeepBlinkTest RoleObserverTest Test: statsd_testdrive 90 244 Change-Id: Ifd6946ce64c3a09f8cac436bb7087ec56521486c
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java26
-rw-r--r--core/java/com/android/internal/logging/UiEventLogger.java4
-rw-r--r--core/java/com/android/internal/logging/UiEventLoggerImpl.java4
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java10
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecordLogger.java144
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java17
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java75
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java25
8 files changed, 258 insertions, 47 deletions
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index e053ed58a82b..0ff2e0386121 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -214,6 +214,32 @@ public abstract class NotificationListenerService extends Service {
public static final int REASON_TIMEOUT = 19;
/**
+ * @hide
+ */
+ @IntDef(prefix = "REASON_", value = {
+ REASON_CLICK,
+ REASON_CANCEL,
+ REASON_CANCEL_ALL,
+ REASON_ERROR,
+ REASON_PACKAGE_CHANGED,
+ REASON_USER_STOPPED,
+ REASON_PACKAGE_BANNED,
+ REASON_APP_CANCEL,
+ REASON_APP_CANCEL_ALL,
+ REASON_LISTENER_CANCEL,
+ REASON_LISTENER_CANCEL_ALL,
+ REASON_GROUP_SUMMARY_CANCELED,
+ REASON_GROUP_OPTIMIZATION,
+ REASON_PACKAGE_SUSPENDED,
+ REASON_PROFILE_TURNED_OFF,
+ REASON_UNAUTOBUNDLED,
+ REASON_CHANNEL_BANNED,
+ REASON_SNOOZED,
+ REASON_TIMEOUT
+ })
+ public @interface NotificationCancelReason{};
+
+ /**
* The full trim of the StatusBarNotification including all its features.
*
* @hide
diff --git a/core/java/com/android/internal/logging/UiEventLogger.java b/core/java/com/android/internal/logging/UiEventLogger.java
index 48d2bc2ae58d..67ffd4d93404 100644
--- a/core/java/com/android/internal/logging/UiEventLogger.java
+++ b/core/java/com/android/internal/logging/UiEventLogger.java
@@ -56,8 +56,8 @@ public interface UiEventLogger {
* @param event an enum implementing UiEventEnum interface.
* @param uid the uid of the relevant app, if known (0 otherwise).
* @param packageName the package name of the relevant app, if known (null otherwise).
- * @param instance An identifier obtained from an InstanceIdSequence.
+ * @param instance An identifier obtained from an InstanceIdSequence. If null, reduces to log().
*/
void logWithInstanceId(@NonNull UiEventEnum event, int uid, @Nullable String packageName,
- @NonNull InstanceId instance);
+ @Nullable InstanceId instance);
}
diff --git a/core/java/com/android/internal/logging/UiEventLoggerImpl.java b/core/java/com/android/internal/logging/UiEventLoggerImpl.java
index 785b2edf2e1b..4d171ec8a3a8 100644
--- a/core/java/com/android/internal/logging/UiEventLoggerImpl.java
+++ b/core/java/com/android/internal/logging/UiEventLoggerImpl.java
@@ -41,9 +41,11 @@ public class UiEventLoggerImpl implements UiEventLogger {
public void logWithInstanceId(UiEventEnum event, int uid, String packageName,
InstanceId instance) {
final int eventID = event.getId();
- if (eventID > 0) {
+ if ((eventID > 0) && (instance != null)) {
FrameworkStatsLog.write(FrameworkStatsLog.UI_EVENT_REPORTED, eventID, uid, packageName,
instance.getId());
+ } else {
+ log(event, uid, packageName);
}
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b52289e36b50..cadfea7e12aa 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -7428,13 +7428,15 @@ public class NotificationManagerService extends SystemService {
}
@GuardedBy("mNotificationLock")
- private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete, int reason,
+ private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete,
+ @NotificationListenerService.NotificationCancelReason int reason,
boolean wasPosted, String listenerName) {
cancelNotificationLocked(r, sendDelete, reason, -1, -1, wasPosted, listenerName);
}
@GuardedBy("mNotificationLock")
- private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete, int reason,
+ private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete,
+ @NotificationListenerService.NotificationCancelReason int reason,
int rank, int count, boolean wasPosted, String listenerName) {
final String canceledKey = r.getKey();
@@ -7552,6 +7554,10 @@ public class NotificationManagerService extends SystemService {
EventLogTags.writeNotificationCanceled(canceledKey, reason,
r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now),
rank, count, listenerName);
+ if (wasPosted) {
+ mNotificationRecordLogger.logNotificationCancelled(r, reason,
+ r.getStats().getDismissalSurface());
+ }
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/notification/NotificationRecordLogger.java b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
index 8d8511f030f0..fc2d9e775149 100644
--- a/services/core/java/com/android/server/notification/NotificationRecordLogger.java
+++ b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
@@ -16,10 +16,16 @@
package com.android.server.notification;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_CLICK;
+import static android.service.notification.NotificationListenerService.REASON_TIMEOUT;
+
import android.annotation.Nullable;
import android.app.Notification;
import android.app.Person;
import android.os.Bundle;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationStats;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
@@ -44,22 +50,144 @@ public interface NotificationRecordLogger {
int position, int buzzBeepBlink);
/**
+ * Logs a notification cancel / dismiss event using UiEventReported (event ids from the
+ * NotificationCancelledEvents enum).
+ * @param r The NotificationRecord. If null, no action is taken.
+ * @param reason The reason the notification was canceled.
+ * @param dismissalSurface The surface the notification was dismissed from.
+ */
+ void logNotificationCancelled(@Nullable NotificationRecord r,
+ @NotificationListenerService.NotificationCancelReason int reason,
+ @NotificationStats.DismissalSurface int dismissalSurface);
+
+ /**
* The UiEvent enums that this class can log.
*/
- enum NotificationReportedEvents implements UiEventLogger.UiEventEnum {
- INVALID(0),
+ enum NotificationReportedEvent implements UiEventLogger.UiEventEnum {
@UiEvent(doc = "New notification enqueued to post")
NOTIFICATION_POSTED(162),
- @UiEvent(doc = "Notification substantially updated")
+ @UiEvent(doc = "Notification substantially updated, or alerted again.")
NOTIFICATION_UPDATED(163);
private final int mId;
- NotificationReportedEvents(int id) {
+ NotificationReportedEvent(int id) {
+ mId = id;
+ }
+ @Override public int getId() {
+ return mId;
+ }
+
+ public static NotificationReportedEvent fromRecordPair(NotificationRecordPair p) {
+ return (p.old != null) ? NotificationReportedEvent.NOTIFICATION_UPDATED :
+ NotificationReportedEvent.NOTIFICATION_POSTED;
+ }
+ }
+
+ enum NotificationCancelledEvent implements UiEventLogger.UiEventEnum {
+ INVALID(0),
+ @UiEvent(doc = "Notification was canceled due to a notification click.")
+ NOTIFICATION_CANCEL_CLICK(164),
+ @UiEvent(doc = "Notification was canceled due to a user dismissal, surface not specified.")
+ NOTIFICATION_CANCEL_USER_OTHER(165),
+ @UiEvent(doc = "Notification was canceled due to a user dismiss-all (from the notification"
+ + " shade).")
+ NOTIFICATION_CANCEL_USER_CANCEL_ALL(166),
+ @UiEvent(doc = "Notification was canceled due to an inflation error.")
+ NOTIFICATION_CANCEL_ERROR(167),
+ @UiEvent(doc = "Notification was canceled by the package manager modifying the package.")
+ NOTIFICATION_CANCEL_PACKAGE_CHANGED(168),
+ @UiEvent(doc = "Notification was canceled by the owning user context being stopped.")
+ NOTIFICATION_CANCEL_USER_STOPPED(169),
+ @UiEvent(doc = "Notification was canceled by the user banning the package.")
+ NOTIFICATION_CANCEL_PACKAGE_BANNED(170),
+ @UiEvent(doc = "Notification was canceled by the app canceling this specific notification.")
+ NOTIFICATION_CANCEL_APP_CANCEL(171),
+ @UiEvent(doc = "Notification was canceled by the app cancelling all its notifications.")
+ NOTIFICATION_CANCEL_APP_CANCEL_ALL(172),
+ @UiEvent(doc = "Notification was canceled by a listener reporting a user dismissal.")
+ NOTIFICATION_CANCEL_LISTENER_CANCEL(173),
+ @UiEvent(doc = "Notification was canceled by a listener reporting a user dismiss all.")
+ NOTIFICATION_CANCEL_LISTENER_CANCEL_ALL(174),
+ @UiEvent(doc = "Notification was canceled because it was a member of a canceled group.")
+ NOTIFICATION_CANCEL_GROUP_SUMMARY_CANCELED(175),
+ @UiEvent(doc = "Notification was canceled because it was an invisible member of a group.")
+ NOTIFICATION_CANCEL_GROUP_OPTIMIZATION(176),
+ @UiEvent(doc = "Notification was canceled by the device administrator suspending the "
+ + "package.")
+ NOTIFICATION_CANCEL_PACKAGE_SUSPENDED(177),
+ @UiEvent(doc = "Notification was canceled by the owning managed profile being turned off.")
+ NOTIFICATION_CANCEL_PROFILE_TURNED_OFF(178),
+ @UiEvent(doc = "Autobundled summary notification was canceled because its group was "
+ + "unbundled")
+ NOTIFICATION_CANCEL_UNAUTOBUNDLED(179),
+ @UiEvent(doc = "Notification was canceled by the user banning the channel.")
+ NOTIFICATION_CANCEL_CHANNEL_BANNED(180),
+ @UiEvent(doc = "Notification was snoozed.")
+ NOTIFICATION_CANCEL_SNOOZED(181),
+ @UiEvent(doc = "Notification was canceled due to timeout")
+ NOTIFICATION_CANCEL_TIMEOUT(182),
+ // Values 183-189 reserved for future system dismissal reasons
+ @UiEvent(doc = "Notification was canceled due to user dismissal of a peeking notification.")
+ NOTIFICATION_CANCEL_USER_PEEK(190),
+ @UiEvent(doc = "Notification was canceled due to user dismissal from the always-on display")
+ NOTIFICATION_CANCEL_USER_AOD(191),
+ @UiEvent(doc = "Notification was canceled due to user dismissal from the notification"
+ + " shade.")
+ NOTIFICATION_CANCEL_USER_SHADE(192),
+ @UiEvent(doc = "Notification was canceled due to user dismissal from the lockscreen")
+ NOTIFICATION_CANCEL_USER_LOCKSCREEN(193);
+
+ private final int mId;
+ NotificationCancelledEvent(int id) {
mId = id;
}
@Override public int getId() {
return mId;
}
+ public static NotificationCancelledEvent fromCancelReason(
+ @NotificationListenerService.NotificationCancelReason int reason,
+ @NotificationStats.DismissalSurface int surface) {
+ // Shouldn't be possible to get a non-dismissed notification here.
+ if (surface == NotificationStats.DISMISSAL_NOT_DISMISSED) {
+ if (NotificationManagerService.DBG) {
+ throw new IllegalArgumentException("Unexpected surface " + surface);
+ }
+ return INVALID;
+ }
+ // Most cancel reasons do not have a meaningful surface. Reason codes map directly
+ // to NotificationCancelledEvent codes.
+ if (surface == NotificationStats.DISMISSAL_OTHER) {
+ if ((REASON_CLICK <= reason) && (reason <= REASON_TIMEOUT)) {
+ return NotificationCancelledEvent.values()[reason];
+ }
+ if (NotificationManagerService.DBG) {
+ throw new IllegalArgumentException("Unexpected cancel reason " + reason);
+ }
+ return INVALID;
+ }
+ // User cancels have a meaningful surface, which we differentiate by. See b/149038335
+ // for caveats.
+ if (reason != REASON_CANCEL) {
+ if (NotificationManagerService.DBG) {
+ throw new IllegalArgumentException("Unexpected cancel with surface " + reason);
+ }
+ return INVALID;
+ }
+ switch (surface) {
+ case NotificationStats.DISMISSAL_PEEK:
+ return NOTIFICATION_CANCEL_USER_PEEK;
+ case NotificationStats.DISMISSAL_AOD:
+ return NOTIFICATION_CANCEL_USER_AOD;
+ case NotificationStats.DISMISSAL_SHADE:
+ return NOTIFICATION_CANCEL_USER_SHADE;
+ default:
+ if (NotificationManagerService.DBG) {
+ throw new IllegalArgumentException("Unexpected surface for user-dismiss "
+ + reason);
+ }
+ return INVALID;
+ }
+ }
}
/**
@@ -88,7 +216,8 @@ public interface NotificationRecordLogger {
return true;
}
- return !(Objects.equals(r.getSbn().getChannelIdLogTag(), old.getSbn().getChannelIdLogTag())
+ return !(Objects.equals(r.getSbn().getChannelIdLogTag(),
+ old.getSbn().getChannelIdLogTag())
&& Objects.equals(r.getSbn().getGroupLogTag(), old.getSbn().getGroupLogTag())
&& (r.getSbn().getNotification().isGroupSummary()
== old.getSbn().getNotification().isGroupSummary())
@@ -97,11 +226,6 @@ public interface NotificationRecordLogger {
&& (r.getImportance() == old.getImportance()));
}
- NotificationReportedEvents getUiEvent() {
- return (old != null) ? NotificationReportedEvents.NOTIFICATION_UPDATED :
- NotificationReportedEvents.NOTIFICATION_POSTED;
- }
-
/**
* @return hash code for the notification style class, or 0 if none exists.
*/
diff --git a/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
index 4974c3001b9b..015d280535e6 100644
--- a/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
+++ b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
@@ -16,6 +16,8 @@
package com.android.server.notification;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
import com.android.internal.util.FrameworkStatsLog;
/**
@@ -24,6 +26,8 @@ import com.android.internal.util.FrameworkStatsLog;
*/
public class NotificationRecordLoggerImpl implements NotificationRecordLogger {
+ UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
+
@Override
public void logNotificationReported(NotificationRecord r, NotificationRecord old,
int position, int buzzBeepBlink) {
@@ -32,7 +36,7 @@ public class NotificationRecordLoggerImpl implements NotificationRecordLogger {
return;
}
FrameworkStatsLog.write(FrameworkStatsLog.NOTIFICATION_REPORTED,
- /* int32 event_id = 1 */ p.getUiEvent().getId(),
+ /* int32 event_id = 1 */ NotificationReportedEvent.fromRecordPair(p).getId(),
/* int32 uid = 2 */ r.getUid(),
/* string package_name = 3 */ r.getSbn().getPackageName(),
/* int32 instance_id = 4 */ p.getInstanceId(),
@@ -61,9 +65,10 @@ public class NotificationRecordLoggerImpl implements NotificationRecordLogger {
);
}
-
-
-
-
-
+ @Override
+ public void logNotificationCancelled(NotificationRecord r, int reason, int dismissalSurface) {
+ mUiEventLogger.logWithInstanceId(
+ NotificationCancelledEvent.fromCancelReason(reason, dismissalSurface),
+ r.getUid(), r.getSbn().getPackageName(), r.getSbn().getInstanceId());
+ }
}
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 e0ee3ce3aa57..990222e0ffa9 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -32,7 +32,6 @@ import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS;
-import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
@@ -50,6 +49,8 @@ import static android.os.Build.VERSION_CODES.P;
import static android.os.UserHandle.USER_SYSTEM;
import static android.service.notification.Adjustment.KEY_IMPORTANCE;
import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
+import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL;
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
@@ -1144,7 +1145,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
waitForIdle();
assertEquals(1, mNotificationRecordLogger.getCalls().size());
NotificationRecordLoggerFake.CallRecord call = mNotificationRecordLogger.get(0);
- assertTrue(call.shouldLog());
+ assertTrue(call.shouldLog);
+ assertEquals(NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
+ call.event);
assertNotNull(call.r);
assertNull(call.old);
assertEquals(0, call.position);
@@ -1153,7 +1156,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
assertEquals(0, call.r.getSbn().getId());
assertEquals(tag, call.r.getSbn().getTag());
assertNotNull(call.r.getSbn().getInstanceId());
- assertEquals(0, call.r.getSbn().getInstanceId().getId());
+ assertEquals(0, call.getInstanceId()); // Fake instance IDs are assigned in order
}
@Test
@@ -1171,18 +1174,18 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
waitForIdle();
assertEquals(2, mNotificationRecordLogger.getCalls().size());
- assertTrue(mNotificationRecordLogger.get(0).shouldLog());
+ assertTrue(mNotificationRecordLogger.get(0).shouldLog);
assertEquals(
- NotificationRecordLogger.NotificationReportedEvents.NOTIFICATION_POSTED,
- mNotificationRecordLogger.get(0).getUiEvent());
- assertEquals(0, mNotificationRecordLogger.get(0).r.getSbn().getInstanceId().getId());
+ NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
+ mNotificationRecordLogger.get(0).event);
+ assertEquals(0, mNotificationRecordLogger.get(0).getInstanceId());
- assertTrue(mNotificationRecordLogger.get(1).shouldLog());
+ assertTrue(mNotificationRecordLogger.get(1).shouldLog);
assertEquals(
- NotificationRecordLogger.NotificationReportedEvents.NOTIFICATION_UPDATED,
- mNotificationRecordLogger.get(1).getUiEvent());
+ NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_UPDATED,
+ mNotificationRecordLogger.get(1).event);
// Instance ID doesn't change on update of an active notification
- assertEquals(0, mNotificationRecordLogger.get(1).r.getSbn().getInstanceId().getId());
+ assertEquals(0, mNotificationRecordLogger.get(1).getInstanceId());
}
@Test
@@ -1194,8 +1197,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
generateNotificationRecord(null).getNotification(), 0);
waitForIdle();
assertEquals(2, mNotificationRecordLogger.getCalls().size());
- assertTrue(mNotificationRecordLogger.get(0).shouldLog());
- assertFalse(mNotificationRecordLogger.get(1).shouldLog());
+ assertTrue(mNotificationRecordLogger.get(0).shouldLog);
+ assertFalse(mNotificationRecordLogger.get(1).shouldLog);
}
@Test
@@ -1210,20 +1213,37 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
waitForIdle();
mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, notification, 0);
waitForIdle();
- assertEquals(2, mNotificationRecordLogger.getCalls().size());
+ assertEquals(3, mNotificationRecordLogger.getCalls().size());
+
+ assertEquals(
+ NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
+ mNotificationRecordLogger.get(0).event);
+ assertTrue(mNotificationRecordLogger.get(0).shouldLog);
+ assertEquals(0, mNotificationRecordLogger.get(0).getInstanceId());
- assertTrue(mNotificationRecordLogger.get(0).shouldLog());
+ assertEquals(REASON_APP_CANCEL, mNotificationRecordLogger.get(1).reason);
assertEquals(
- NotificationRecordLogger.NotificationReportedEvents.NOTIFICATION_POSTED,
- mNotificationRecordLogger.get(0).getUiEvent());
- assertEquals(0, mNotificationRecordLogger.get(0).r.getSbn().getInstanceId().getId());
+ NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_APP_CANCEL,
+ mNotificationRecordLogger.get(1).event);
+ assertTrue(mNotificationRecordLogger.get(1).shouldLog);
+ assertEquals(0, mNotificationRecordLogger.get(1).getInstanceId());
- assertTrue(mNotificationRecordLogger.get(1).shouldLog());
assertEquals(
- NotificationRecordLogger.NotificationReportedEvents.NOTIFICATION_POSTED,
- mNotificationRecordLogger.get(1).getUiEvent());
+ NotificationRecordLogger.NotificationReportedEvent.NOTIFICATION_POSTED,
+ mNotificationRecordLogger.get(2).event);
+ assertTrue(mNotificationRecordLogger.get(2).shouldLog);
// New instance ID because notification was canceled before re-post
- assertEquals(1, mNotificationRecordLogger.get(1).r.getSbn().getInstanceId().getId());
+ assertEquals(1, mNotificationRecordLogger.get(2).getInstanceId());
+ }
+
+ @Test
+ public void testCancelNonexistentNotification() throws Exception {
+ mBinderService.cancelNotificationWithTag(PKG, PKG,
+ "testCancelNonexistentNotification", 0, 0);
+ waitForIdle();
+ // The notification record logger doesn't even get called when a nonexistent notification
+ // is cancelled, because that happens very frequently and is not interesting.
+ assertEquals(0, mNotificationRecordLogger.getCalls().size());
}
@Test
@@ -3365,6 +3385,17 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
waitForIdle();
assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
+
+ // Using mService.addNotification() does not generate a NotificationRecordLogger log,
+ // so we only get the cancel notification.
+ assertEquals(1, mNotificationRecordLogger.getCalls().size());
+
+ assertEquals(REASON_CANCEL, mNotificationRecordLogger.get(0).reason);
+ assertEquals(
+ NotificationRecordLogger.NotificationCancelledEvent.NOTIFICATION_CANCEL_USER_AOD,
+ mNotificationRecordLogger.get(0).event);
+ assertTrue(mNotificationRecordLogger.get(0).shouldLog);
+ assertEquals(0, mNotificationRecordLogger.get(0).getInstanceId());
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java
index 5c1487f0fdf6..b120dbee03c5 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java
@@ -16,6 +16,8 @@
package com.android.server.notification;
+import com.android.internal.logging.UiEventLogger;
+
import java.util.ArrayList;
import java.util.List;
@@ -24,18 +26,27 @@ import java.util.List;
*/
class NotificationRecordLoggerFake implements NotificationRecordLogger {
static class CallRecord extends NotificationRecordPair {
- public int position, buzzBeepBlink;
+ static final int INVALID = -1;
+ public int position = INVALID, buzzBeepBlink = INVALID, reason = INVALID;
+ public boolean shouldLog;
+ public UiEventLogger.UiEventEnum event;
CallRecord(NotificationRecord r, NotificationRecord old, int position,
int buzzBeepBlink) {
super(r, old);
+
this.position = position;
this.buzzBeepBlink = buzzBeepBlink;
+ shouldLog = shouldLog(buzzBeepBlink);
+ event = NotificationReportedEvent.fromRecordPair(this);
}
- boolean shouldLog() {
- return shouldLog(buzzBeepBlink);
+ CallRecord(NotificationRecord r, int reason, int dismissalSurface) {
+ super(r, null);
+ this.reason = reason;
+ shouldLog = true;
+ event = NotificationCancelledEvent.fromCancelReason(reason, dismissalSurface);
}
}
- private List<CallRecord> mCalls = new ArrayList<CallRecord>();
+ private List<CallRecord> mCalls = new ArrayList<>();
List<CallRecord> getCalls() {
return mCalls;
@@ -50,4 +61,10 @@ class NotificationRecordLoggerFake implements NotificationRecordLogger {
int position, int buzzBeepBlink) {
mCalls.add(new CallRecord(r, old, position, buzzBeepBlink));
}
+
+ @Override
+ public void logNotificationCancelled(NotificationRecord r, int reason, int dismissalSurface) {
+ mCalls.add(new CallRecord(r, reason, dismissalSurface));
+ }
+
}