# when a notification action button has been clicked
27521 notification_action_clicked (key|3),(action_index|1)
# when a notification has been canceled
-27530 notification_canceled (key|3),(reason|1),(lifespan|1)
+27530 notification_canceled (key|3),(reason|1),(lifespan|1),(exposure|1)
+# replaces 27510 with a row per notification
+27531 notification_visibility (key|3),(visibile|1),(lifespan|1),(freshness|1)
# ---------------------------
# Watchdog.java
String[] newlyVisibleKeys, String[] noLongerVisibleKeys) {
// Using ';' as separator since eventlogs uses ',' to separate
// args.
+ // TODO remove this: b/21248682
EventLogTags.writeNotificationVisibilityChanged(
TextUtils.join(";", newlyVisibleKeys),
TextUtils.join(";", noLongerVisibleKeys));
for (String key : newlyVisibleKeys) {
NotificationRecord r = mNotificationsByKey.get(key);
if (r == null) continue;
- r.stats.onVisibilityChanged(true);
+ r.setVisibility(true);
}
// Note that we might receive this event after notifications
// have already left the system, e.g. after dismissing from the
for (String key : noLongerVisibleKeys) {
NotificationRecord r = mNotificationsByKey.get(key);
if (r == null) continue;
- r.stats.onVisibilityChanged(false);
+ r.setVisibility(false);
}
}
}
// Save it for users of getHistoricalNotifications()
mArchive.record(r.sbn);
- int lifespan = (int) (System.currentTimeMillis() - r.getCreationTimeMs());
- EventLogTags.writeNotificationCanceled(canceledKey, reason, lifespan);
+ final long now = System.currentTimeMillis();
+ final int lifespan = (int) (now - r.getCreationTimeMs());
+ final long visibleSinceMs = r.getVisibleSinceMs();
+ final int exposure = visibleSinceMs == 0L ? 0 : (int) (now - visibleSinceMs);
+ EventLogTags.writeNotificationCanceled(canceledKey, reason, lifespan, exposure);
}
/**
import android.service.notification.StatusBarNotification;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.EventLogTags;
import java.io.PrintWriter;
import java.lang.reflect.Array;
// The first post time, stable across updates.
private long mCreationTimeMs;
+ // The most recent visibility event.
+ private long mVisibleSinceMs;
+
+ // The most recent update time, or the creation time if no updates.
+ private long mUpdateTimeMs;
+
// Is this record an update of an old record?
public boolean isUpdate;
private int mPackagePriority;
mOriginalFlags = sbn.getNotification().flags;
mRankingTimeMs = calculateRankingTimeMs(0L);
mCreationTimeMs = sbn.getPostTime();
+ mUpdateTimeMs = mCreationTimeMs;
}
// copy any notes that the ranking system may have made before the update
mIntercept = previous.mIntercept;
mRankingTimeMs = calculateRankingTimeMs(previous.getRankingTimeMs());
mCreationTimeMs = previous.mCreationTimeMs;
+ mVisibleSinceMs = previous.mVisibleSinceMs;
// Don't copy mGlobalSortKey, recompute it.
}
pw.println(prefix + " mGlobalSortKey=" + mGlobalSortKey);
pw.println(prefix + " mRankingTimeMs=" + mRankingTimeMs);
pw.println(prefix + " mCreationTimeMs=" + mCreationTimeMs);
+ pw.println(prefix + " mVisibleSinceMs=" + mVisibleSinceMs);
+ pw.println(prefix + " mUpdateTimeMs=" + mUpdateTimeMs);
}
}
/**
+ * Returns the timestamp of the most recent updates, or the post time if none.
+ */
+ public long getUpdateTimeMs() {
+ return mUpdateTimeMs;
+ }
+
+ /**
* Returns the timestamp of the first post, ignoring updates.
*/
public long getCreationTimeMs() {
}
/**
+ * Returns the timestamp of the most recent visibility event, or 0L if hidden.
+ */
+ public long getVisibleSinceMs() {
+ return mVisibleSinceMs;
+ }
+
+ /**
+ * Set the visibility of the notification.
+ */
+ public void setVisibility(boolean visible) {
+ final long now = System.currentTimeMillis();
+ mVisibleSinceMs = visible ? now : 0L;
+ stats.onVisibilityChanged(visible);
+ EventLogTags.writeNotificationVisibility(getKey(), visible ? 1 : 0,
+ (int) (now - mCreationTimeMs),
+ (int) (now - mUpdateTimeMs));
+ }
+
+ /**
* @param previousRankingTimeMs for updated notifications, {@link #getRankingTimeMs()}
* of the previous notification record, 0 otherwise
*/