Merge "Add a log and statistics for notification expansion." into lmp-dev

This commit is contained in:
Chris Wren
2014-07-30 15:32:50 +00:00
committed by Android (Google) Code Review
8 changed files with 166 additions and 5 deletions

View File

@@ -49,6 +49,7 @@ interface IStatusBarService
void onNotificationClear(String pkg, String tag, int id, int userId);
void onNotificationVisibilityChanged(
in String[] newlyVisibleKeys, in String[] noLongerVisibleKeys);
void onNotificationExpansionChanged(in String key, in boolean userAction, in boolean expanded);
void setSystemUiVisibility(int vis, int mask);
void setHardKeyboardEnabled(boolean enabled);
void setWindowState(int window, int state);

View File

@@ -96,7 +96,7 @@ import static com.android.keyguard.KeyguardHostView.OnDismissAction;
public abstract class BaseStatusBar extends SystemUI implements
CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
RecentsComponent.Callbacks {
RecentsComponent.Callbacks, ExpandableNotificationRow.ExpansionLogger {
public static final String TAG = "StatusBar";
public static final boolean DEBUG = false;
public static final boolean MULTIUSER_DEBUG = false;
@@ -1035,6 +1035,7 @@ public abstract class BaseStatusBar extends SystemUI implements
Context.LAYOUT_INFLATER_SERVICE);
row = (ExpandableNotificationRow) inflater.inflate(R.layout.status_bar_notification_row,
parent, false);
row.setExpansionLogger(this, entry.notification.getKey());
}
// the notification inspector (see SwipeHelper.setLongPressListener)
@@ -1784,4 +1785,13 @@ public abstract class BaseStatusBar extends SystemUI implements
}
return contextForUser.getPackageManager();
}
@Override
public void logNotificationExpansion(String key, boolean userAction, boolean expanded) {
try {
mBarService.onNotificationExpansionChanged(key, userAction, expanded);
} catch (RemoteException e) {
// Ignore.
}
}
}

View File

@@ -54,6 +54,12 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
private int mMaxExpandHeight;
private View mVetoButton;
private boolean mClearable;
private ExpansionLogger mLogger;
private String mLoggingKey;
public interface ExpansionLogger {
public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
public ExpandableNotificationRow(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -66,6 +72,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
public void reset() {
super.reset();
mRowMinHeight = 0;
final boolean wasExpanded = isExpanded();
mRowMaxHeight = 0;
mExpandable = false;
mHasUserChangedExpansion = false;
@@ -76,6 +83,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
mPublicLayout.reset();
mPrivateLayout.reset();
mMaxExpandHeight = 0;
logExpansionEvent(false, wasExpanded);
}
@Override
@@ -131,8 +139,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
*/
public void setUserExpanded(boolean userExpanded) {
if (userExpanded && !mExpandable) return;
final boolean wasExpanded = isExpanded();
mHasUserChangedExpansion = true;
mUserExpanded = userExpanded;
logExpansionEvent(true, wasExpanded);
}
public boolean isUserLocked() {
@@ -156,15 +166,19 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
* @param expand whether the system wants this notification to be expanded.
*/
public void setSystemExpanded(boolean expand) {
final boolean wasExpanded = isExpanded();
mIsSystemExpanded = expand;
notifyHeightChanged();
logExpansionEvent(false, wasExpanded);
}
/**
* @param expansionDisabled whether to prevent notification expansion
*/
public void setExpansionDisabled(boolean expansionDisabled) {
final boolean wasExpanded = isExpanded();
mExpansionDisabled = expansionDisabled;
logExpansionEvent(false, wasExpanded);
notifyHeightChanged();
}
@@ -302,4 +316,17 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
private NotificationContentView getShowingLayout() {
return mShowingPublic ? mPublicLayout : mPrivateLayout;
}
public void setExpansionLogger(ExpansionLogger logger, String key) {
mLogger = logger;
mLoggingKey = key;
}
private void logExpansionEvent(boolean userAction, boolean wasExpanded) {
final boolean nowExpanded = isExpanded();
if (wasExpanded != nowExpanded && mLogger != null) {
mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded) ;
}
}
}

View File

@@ -65,6 +65,8 @@ option java_package com.android.server
27501 notification_panel_hidden
# when notifications are newly displayed on screen, or disappear from screen
27510 notification_visibility_changed (newlyVisibleKeys|3),(noLongerVisibleKeys|3)
# when notifications are expanded, or contracted
27511 notification_expansion (key|3),(user_action|1),(expanded|1)
# when a notification has been clicked
27520 notification_clicked (key|3)

View File

@@ -32,4 +32,5 @@ public interface NotificationDelegate {
boolean allowDisable(int what, IBinder token, String pkg);
void onNotificationVisibilityChanged(
String[] newlyVisibleKeys, String[] noLongerVisibleKeys);
void onNotificationExpansionChanged(String key, boolean userAction, boolean expanded);
}

View File

@@ -611,6 +611,18 @@ public class NotificationManagerService extends SystemService {
}
}
}
@Override
public void onNotificationExpansionChanged(String key,
boolean userAction, boolean expanded) {
EventLogTags.writeNotificationExpansion(key, userAction ? 1 : 0, expanded ? 1 : 0);
synchronized (mNotificationList) {
NotificationRecord r = mNotificationsByKey.get(key);
if (r != null) {
r.stats.onExpansionChanged(userAction, expanded);
}
}
}
};
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {

View File

@@ -200,6 +200,9 @@ public class NotificationUsageStats {
public final Aggregate airtimeCount = new Aggregate();
public final Aggregate airtimeMs = new Aggregate();
public final Aggregate posttimeToFirstAirtimeMs = new Aggregate();
public final Aggregate userExpansionCount = new Aggregate();
public final Aggregate airtimeExpandedMs = new Aggregate();
public final Aggregate posttimeToFirstVisibleExpansionMs = new Aggregate();
public AggregatedStats(String key) {
this.key = key;
@@ -222,6 +225,14 @@ public class NotificationUsageStats {
posttimeToFirstAirtimeMs.addSample(
singleNotificationStats.posttimeToFirstAirtimeMs);
}
if (singleNotificationStats.posttimeToFirstVisibleExpansionMs >= 0) {
posttimeToFirstVisibleExpansionMs.addSample(
singleNotificationStats.posttimeToFirstVisibleExpansionMs);
}
userExpansionCount.addSample(singleNotificationStats.userExpansionCount);
if (singleNotificationStats.airtimeExpandedMs >= 0) {
airtimeExpandedMs.addSample(singleNotificationStats.airtimeExpandedMs);
}
}
public void dump(PrintWriter pw, String indent) {
@@ -247,6 +258,9 @@ public class NotificationUsageStats {
indent + " airtimeCount=" + airtimeCount + ",\n" +
indent + " airtimeMs=" + airtimeMs + ",\n" +
indent + " posttimeToFirstAirtimeMs=" + posttimeToFirstAirtimeMs + ",\n" +
indent + " userExpansionCount=" + userExpansionCount + ",\n" +
indent + " airtimeExpandedMs=" + airtimeExpandedMs + ",\n" +
indent + " posttimeToFVEMs=" + posttimeToFirstVisibleExpansionMs + ",\n" +
indent + "}";
}
}
@@ -255,6 +269,8 @@ public class NotificationUsageStats {
* Tracks usage of an individual notification that is currently active.
*/
public static class SingleNotificationStats {
private boolean isVisible = false;
private boolean isExpanded = false;
/** SystemClock.elapsedRealtime() when the notification was posted. */
public long posttimeElapsedMs = -1;
/** Elapsed time since the notification was posted until it was first clicked, or -1. */
@@ -272,6 +288,20 @@ public class NotificationUsageStats {
public long currentAirtimeStartElapsedMs = -1;
/** Accumulated visible time. */
public long airtimeMs = 0;
/**
* Time in ms between the notification being posted and when it first
* became visible and expanded; -1 if it was never visibly expanded.
*/
public long posttimeToFirstVisibleExpansionMs = -1;
/**
* If currently visible, SystemClock.elapsedRealtime() when the notification was made
* visible; -1 otherwise.
*/
public long currentAirtimeExpandedStartElapsedMs = -1;
/** Accumulated visible expanded time. */
public long airtimeExpandedMs = 0;
/** Number of times the notification has been expanded by the user. */
public long userExpansionCount = 0;
public long getCurrentPosttimeMs() {
if (posttimeElapsedMs < 0) {
@@ -284,7 +314,16 @@ public class NotificationUsageStats {
long result = airtimeMs;
// Add incomplete airtime if currently shown.
if (currentAirtimeStartElapsedMs >= 0) {
result+= (SystemClock.elapsedRealtime() - currentAirtimeStartElapsedMs);
result += (SystemClock.elapsedRealtime() - currentAirtimeStartElapsedMs);
}
return result;
}
public long getCurrentAirtimeExpandedMs() {
long result = airtimeExpandedMs;
// Add incomplete expanded airtime if currently shown.
if (currentAirtimeExpandedStartElapsedMs >= 0) {
result += (SystemClock.elapsedRealtime() - currentAirtimeExpandedStartElapsedMs);
}
return result;
}
@@ -318,6 +357,8 @@ public class NotificationUsageStats {
public void onVisibilityChanged(boolean visible) {
long elapsedNowMs = SystemClock.elapsedRealtime();
final boolean wasVisible = isVisible;
isVisible = visible;
if (visible) {
if (currentAirtimeStartElapsedMs < 0) {
airtimeCount++;
@@ -332,6 +373,37 @@ public class NotificationUsageStats {
currentAirtimeStartElapsedMs = -1;
}
}
if (wasVisible != isVisible) {
updateVisiblyExpandedStats();
}
}
public void onExpansionChanged(boolean userAction, boolean expanded) {
isExpanded = expanded;
if (isExpanded && userAction) {
userExpansionCount++;
}
updateVisiblyExpandedStats();
}
private void updateVisiblyExpandedStats() {
long elapsedNowMs = SystemClock.elapsedRealtime();
if (isExpanded && isVisible) {
// expanded and visible
if (currentAirtimeExpandedStartElapsedMs < 0) {
currentAirtimeExpandedStartElapsedMs = elapsedNowMs;
}
if (posttimeToFirstVisibleExpansionMs < 0) {
posttimeToFirstVisibleExpansionMs = elapsedNowMs - posttimeElapsedMs;
}
} else {
// not-expanded or not-visible
if (currentAirtimeExpandedStartElapsedMs >= 0) {
airtimeExpandedMs += (elapsedNowMs - currentAirtimeExpandedStartElapsedMs);
currentAirtimeExpandedStartElapsedMs = -1;
}
}
}
/** The notification is leaving the system. Finalize. */
@@ -348,6 +420,9 @@ public class NotificationUsageStats {
", airtimeCount=" + airtimeCount +
", airtimeMs=" + airtimeMs +
", currentAirtimeStartElapsedMs=" + currentAirtimeStartElapsedMs +
", airtimeExpandedMs=" + airtimeExpandedMs +
", posttimeToFirstVisibleExpansionMs=" + posttimeToFirstVisibleExpansionMs +
", currentAirtimeExpandedSEMs=" + currentAirtimeExpandedStartElapsedMs +
'}';
}
}
@@ -393,7 +468,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 = 2;
private static final int DB_VERSION = 3;
/** Age in ms after which events are pruned from the DB. */
private static final long HORIZON_MS = 7 * 24 * 60 * 60 * 1000L; // 1 week
@@ -419,6 +494,10 @@ public class NotificationUsageStats {
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 String COL_FIRST_EXPANSIONTIME_MS = "first_expansion_time_ms";
private static final String COL_AIRTIME_EXPANDED_MS = "expansion_airtime_ms";
private static final String COL_EXPAND_COUNT = "expansion_count";
private static final int EVENT_TYPE_POST = 1;
private static final int EVENT_TYPE_CLICK = 2;
@@ -481,6 +560,9 @@ public class NotificationUsageStats {
COL_ACTION_COUNT + " INT," +
COL_POSTTIME_MS + " INT," +
COL_AIRTIME_MS + " INT" +
COL_FIRST_EXPANSIONTIME_MS + " INT" +
COL_AIRTIME_EXPANDED_MS + " INT" +
COL_EXPAND_COUNT + " INT" +
")");
}
@@ -493,6 +575,16 @@ public class NotificationUsageStats {
COL_POSTTIME_MS + " INT");
db.execSQL("ALTER TABLE " + TAB_LOG + " ADD COLUMN " +
COL_AIRTIME_MS + " INT");
case 2:
// Add COL_EXPANSIONTIME_MS column
db.execSQL("ALTER TABLE " + TAB_LOG + " ADD COLUMN " +
COL_FIRST_EXPANSIONTIME_MS + " INT");
// Add COL_AIRTIME_EXPANDED_MS column
db.execSQL("ALTER TABLE " + TAB_LOG + " ADD COLUMN " +
COL_AIRTIME_EXPANDED_MS + " INT");
// Add COL_EXPAND_COUNT column
db.execSQL("ALTER TABLE " + TAB_LOG + " ADD COLUMN " +
COL_EXPAND_COUNT + " INT");
}
}
};
@@ -553,7 +645,7 @@ public class NotificationUsageStats {
if (eventType == EVENT_TYPE_POST) {
putNotificationDetails(r, cv);
} else {
putPosttimeAirtime(r, cv);
putPosttimeVisibility(r, cv);
}
SQLiteDatabase db = mHelper.getWritableDatabase();
if (db.insert(TAB_LOG, null, cv) < 0) {
@@ -597,9 +689,12 @@ public class NotificationUsageStats {
r.getNotification().actions.length : 0);
}
private static void putPosttimeAirtime(NotificationRecord r, ContentValues outCv) {
private static void putPosttimeVisibility(NotificationRecord r, ContentValues outCv) {
outCv.put(COL_POSTTIME_MS, r.stats.getCurrentPosttimeMs());
outCv.put(COL_AIRTIME_MS, r.stats.getCurrentAirtimeMs());
outCv.put(COL_EXPAND_COUNT, r.stats.userExpansionCount);
outCv.put(COL_AIRTIME_EXPANDED_MS, r.stats.getCurrentAirtimeExpandedMs());
outCv.put(COL_FIRST_EXPANSIONTIME_MS, r.stats.posttimeToFirstVisibleExpansionMs);
}
public void dump(PrintWriter pw, String indent, DumpFilter filter) {

View File

@@ -572,6 +572,19 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
}
@Override
public void onNotificationExpansionChanged(String key, boolean userAction,
boolean expanded) throws RemoteException {
enforceStatusBarService();
long identity = Binder.clearCallingIdentity();
try {
mNotificationDelegate.onNotificationExpansionChanged(
key, userAction, expanded);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void onClearAllNotifications(int userId) {
enforceStatusBarService();