diff options
author | Christoph Studer <chstuder@google.com> | 2014-05-15 09:05:11 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-05-15 09:05:12 +0000 |
commit | d04cf4ccf426f70d80e98b46dc74c4dfb18f338f (patch) | |
tree | d25e1c56d96c4ccef5e19be80a1c7b79f6c20894 /services | |
parent | ed1a18f40f59ea54a59a06af31429289731e2405 (diff) | |
parent | ffeb0c38145709b51dee0254b770bccc9083ea5c (diff) | |
download | frameworks_base-d04cf4ccf426f70d80e98b46dc74c4dfb18f338f.zip frameworks_base-d04cf4ccf426f70d80e98b46dc74c4dfb18f338f.tar.gz frameworks_base-d04cf4ccf426f70d80e98b46dc74c4dfb18f338f.tar.bz2 |
Merge "Track notification airtime"
Diffstat (limited to 'services')
-rw-r--r-- | services/core/java/com/android/server/notification/NotificationManagerService.java | 16 | ||||
-rw-r--r-- | services/core/java/com/android/server/notification/NotificationUsageStats.java | 121 |
2 files changed, 122 insertions, 15 deletions
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 2f1d291..1734a33 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -727,6 +727,22 @@ public class NotificationManagerService extends SystemService { EventLogTags.writeNotificationVisibilityChanged( TextUtils.join(";", newlyVisibleKeys), TextUtils.join(";", noLongerVisibleKeys)); + synchronized (mNotificationList) { + for (String key : newlyVisibleKeys) { + NotificationRecord r = mNotificationsByKey.get(key); + if (r == null) continue; + r.stats.onVisibilityChanged(true); + } + // Note that we might receive this event after notifications + // have already left the system, e.g. after dismissing from the + // shade. Hence not finding notifications in + // mNotificationsByKey is not an exceptional condition. + for (String key : noLongerVisibleKeys) { + NotificationRecord r = mNotificationsByKey.get(key); + if (r == null) continue; + r.stats.onVisibilityChanged(false); + } + } } }; diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java index a60e95b..d81a25e 100644 --- a/services/core/java/com/android/server/notification/NotificationUsageStats.java +++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java @@ -80,6 +80,7 @@ public class NotificationUsageStats { * Called when the originating app removed the notification programmatically. */ public synchronized void registerRemovedByApp(NotificationRecord notification) { + notification.stats.onRemoved(); for (AggregatedStats stats : getAggregatedStatsLocked(notification)) { stats.numRemovedByApp++; stats.collect(notification.stats); @@ -116,9 +117,7 @@ public class NotificationUsageStats { * <p>Called after {@link #registerClickedByUser(NotificationRecord)}.</p> */ public synchronized void registerCancelDueToClick(NotificationRecord notification) { - // No explicit stats for this (the click has already been registered in - // registerClickedByUser), just make sure the single notification stats - // are folded up into aggregated stats. + notification.stats.onCancel(); for (AggregatedStats stats : getAggregatedStatsLocked(notification)) { stats.collect(notification.stats); } @@ -130,7 +129,7 @@ public class NotificationUsageStats { * <p>Called for notifications of apps being uninstalled, for example.</p> */ public synchronized void registerCancelUnknown(NotificationRecord notification) { - // Fold up individual stats. + notification.stats.onCancel(); for (AggregatedStats stats : getAggregatedStatsLocked(notification)) { stats.collect(notification.stats); } @@ -185,6 +184,9 @@ public class NotificationUsageStats { public final Aggregate posttimeMs = new Aggregate(); public final Aggregate posttimeToDismissMs = new Aggregate(); public final Aggregate posttimeToFirstClickMs = new Aggregate(); + public final Aggregate airtimeCount = new Aggregate(); + public final Aggregate airtimeMs = new Aggregate(); + public final Aggregate posttimeToFirstAirtimeMs = new Aggregate(); public AggregatedStats(String key) { this.key = key; @@ -199,6 +201,14 @@ public class NotificationUsageStats { if (singleNotificationStats.posttimeToFirstClickMs >= 0) { posttimeToFirstClickMs.addSample(singleNotificationStats.posttimeToFirstClickMs); } + airtimeCount.addSample(singleNotificationStats.airtimeCount); + if (singleNotificationStats.airtimeMs >= 0) { + airtimeMs.addSample(singleNotificationStats.airtimeMs); + } + if (singleNotificationStats.posttimeToFirstAirtimeMs >= 0) { + posttimeToFirstAirtimeMs.addSample( + singleNotificationStats.posttimeToFirstAirtimeMs); + } } public void dump(PrintWriter pw, String indent) { @@ -221,6 +231,9 @@ public class NotificationUsageStats { indent + " posttimeMs=" + posttimeMs + ",\n" + indent + " posttimeToDismissMs=" + posttimeToDismissMs + ",\n" + indent + " posttimeToFirstClickMs=" + posttimeToFirstClickMs + ",\n" + + indent + " airtimeCount=" + airtimeCount + ",\n" + + indent + " airtimeMs=" + airtimeMs + ",\n" + + indent + " posttimeToFirstAirtimeMs=" + posttimeToFirstAirtimeMs + ",\n" + indent + "}"; } } @@ -235,6 +248,33 @@ public class NotificationUsageStats { public long posttimeToFirstClickMs = -1; /** Elpased time since the notification was posted until it was dismissed by the user. */ public long posttimeToDismissMs = -1; + /** Number of times the notification has been made visible. */ + public long airtimeCount = 0; + /** Time in ms between the notification was posted and first shown; -1 if never shown. */ + public long posttimeToFirstAirtimeMs = -1; + /** + * If currently visible, SystemClock.elapsedRealtime() when the notification was made + * visible; -1 otherwise. + */ + public long currentAirtimeStartElapsedMs = -1; + /** Accumulated visible time. */ + public long airtimeMs = 0; + + public long getCurrentPosttimeMs() { + if (posttimeElapsedMs < 0) { + return 0; + } + return SystemClock.elapsedRealtime() - posttimeElapsedMs; + } + + public long getCurrentAirtimeMs() { + long result = airtimeMs; + // Add incomplete airtime if currently shown. + if (currentAirtimeStartElapsedMs >= 0) { + result+= (SystemClock.elapsedRealtime() - currentAirtimeStartElapsedMs); + } + return result; + } /** * Called when the user clicked the notification. @@ -252,6 +292,38 @@ public class NotificationUsageStats { if (posttimeToDismissMs < 0) { posttimeToDismissMs = SystemClock.elapsedRealtime() - posttimeElapsedMs; } + finish(); + } + + public void onCancel() { + finish(); + } + + public void onRemoved() { + finish(); + } + + public void onVisibilityChanged(boolean visible) { + long elapsedNowMs = SystemClock.elapsedRealtime(); + if (visible) { + if (currentAirtimeStartElapsedMs < 0) { + airtimeCount++; + currentAirtimeStartElapsedMs = elapsedNowMs; + } + if (posttimeToFirstAirtimeMs < 0) { + posttimeToFirstAirtimeMs = elapsedNowMs - posttimeElapsedMs; + } + } else { + if (currentAirtimeStartElapsedMs >= 0) { + airtimeMs += (elapsedNowMs - currentAirtimeStartElapsedMs); + currentAirtimeStartElapsedMs = -1; + } + } + } + + /** The notification is leaving the system. Finalize. */ + public void finish() { + onVisibilityChanged(false); } @Override @@ -260,6 +332,9 @@ public class NotificationUsageStats { "posttimeElapsedMs=" + posttimeElapsedMs + ", posttimeToFirstClickMs=" + posttimeToFirstClickMs + ", posttimeToDismissMs=" + posttimeToDismissMs + + ", airtimeCount=" + airtimeCount + + ", airtimeMs=" + airtimeMs + + ", currentAirtimeStartElapsedMs=" + currentAirtimeStartElapsedMs + '}'; } } @@ -305,7 +380,7 @@ public class NotificationUsageStats { private static final int MSG_DISMISS = 4; private static final String DB_NAME = "notification_log.db"; - private static final int DB_VERSION = 1; + private static final int DB_VERSION = 2; /** Age in ms after which events are pruned from the DB. */ private static final long HORIZON_MS = 7 * 24 * 60 * 60 * 1000L; // 1 week @@ -329,6 +404,8 @@ public class NotificationUsageStats { private static final String COL_PRIORITY = "priority"; private static final String COL_CATEGORY = "category"; private static final String COL_ACTION_COUNT = "action_count"; + private static final String COL_POSTTIME_MS = "posttime_ms"; + private static final String COL_AIRTIME_MS = "airtime_ms"; private static final int EVENT_TYPE_POST = 1; private static final int EVENT_TYPE_CLICK = 2; @@ -354,16 +431,16 @@ public class NotificationUsageStats { long nowMs = System.currentTimeMillis(); switch (msg.what) { case MSG_POST: - writeEvent(r.sbn.getPostTime(), EVENT_TYPE_POST, r, true); + writeEvent(r.sbn.getPostTime(), EVENT_TYPE_POST, r); break; case MSG_CLICK: - writeEvent(nowMs, EVENT_TYPE_CLICK, r, false); + writeEvent(nowMs, EVENT_TYPE_CLICK, r); break; case MSG_REMOVE: - writeEvent(nowMs, EVENT_TYPE_REMOVE, r, false); + writeEvent(nowMs, EVENT_TYPE_REMOVE, r); break; case MSG_DISMISS: - writeEvent(nowMs, EVENT_TYPE_DISMISS, r, false); + writeEvent(nowMs, EVENT_TYPE_DISMISS, r); break; default: Log.wtf(TAG, "Unknown message type: " + msg.what); @@ -388,14 +465,22 @@ public class NotificationUsageStats { COL_FLAGS + " INT," + COL_PRIORITY + " INT," + COL_CATEGORY + " TEXT," + - COL_ACTION_COUNT + " INT" + + COL_ACTION_COUNT + " INT," + + COL_POSTTIME_MS + " INT," + + COL_AIRTIME_MS + " INT" + ")"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - db.execSQL("DROP TABLE IF EXISTS " + TAB_LOG); - onCreate(db); + switch (oldVersion) { + case 1: + // Add COL_POSTTIME_MS, COL_AIRTIME_MS columns, + db.execSQL("ALTER TABLE " + TAB_LOG + " ADD COLUMN " + + COL_POSTTIME_MS + " INT"); + db.execSQL("ALTER TABLE " + TAB_LOG + " ADD COLUMN " + + COL_AIRTIME_MS + " INT"); + } } }; } @@ -445,15 +530,16 @@ public class NotificationUsageStats { } } - private void writeEvent(long eventTimeMs, int eventType, NotificationRecord r, - boolean populateNotificationDetails) { + private void writeEvent(long eventTimeMs, int eventType, NotificationRecord r) { ContentValues cv = new ContentValues(); cv.put(COL_EVENT_USER_ID, r.sbn.getUser().getIdentifier()); cv.put(COL_EVENT_TIME, eventTimeMs); cv.put(COL_EVENT_TYPE, eventType); putNotificationIdentifiers(r, cv); - if (populateNotificationDetails) { + if (eventType == EVENT_TYPE_POST) { putNotificationDetails(r, cv); + } else { + putPosttimeAirtime(r, cv); } SQLiteDatabase db = mHelper.getWritableDatabase(); if (db.insert(TAB_LOG, null, cv) < 0) { @@ -497,6 +583,11 @@ public class NotificationUsageStats { r.getNotification().actions.length : 0); } + private static void putPosttimeAirtime(NotificationRecord r, ContentValues outCv) { + outCv.put(COL_POSTTIME_MS, r.stats.getCurrentPosttimeMs()); + outCv.put(COL_AIRTIME_MS, r.stats.getCurrentAirtimeMs()); + } + public void dump(PrintWriter pw, String indent) { printPostFrequencies(pw, indent); } |