am 3d2b6212: Merge "high-frequency notification stats." into mnc-dev

* commit '3d2b621204bf74eb0adf548ae1c8850a05aea01a':
  high-frequency notification stats.
This commit is contained in:
Chris Wren
2015-06-17 15:53:34 +00:00
committed by Android Git Automerger
9 changed files with 164 additions and 113 deletions

View File

@@ -33,7 +33,7 @@ public class NotificationIntrusivenessExtractor implements NotificationSignalExt
the top of the ranking order, before it falls back to its natural position. */ the top of the ranking order, before it falls back to its natural position. */
private static final long HANG_TIME_MS = 10000; private static final long HANG_TIME_MS = 10000;
public void initialize(Context ctx) { public void initialize(Context ctx, NotificationUsageStats usageStats) {
if (DBG) Slog.d(TAG, "Initializing " + getClass().getSimpleName() + "."); if (DBG) Slog.d(TAG, "Initializing " + getClass().getSimpleName() + ".");
} }

View File

@@ -856,8 +856,10 @@ public class NotificationManagerService extends SystemService {
} catch (Resources.NotFoundException e) { } catch (Resources.NotFoundException e) {
extractorNames = new String[0]; extractorNames = new String[0];
} }
mUsageStats = new NotificationUsageStats(getContext());
mRankingHelper = new RankingHelper(getContext(), mRankingHelper = new RankingHelper(getContext(),
new RankingWorkerHandler(mRankingThread.getLooper()), new RankingWorkerHandler(mRankingThread.getLooper()),
mUsageStats,
extractorNames); extractorNames);
mConditionProviders = new ConditionProviders(getContext(), mHandler, mUserProfiles); mConditionProviders = new ConditionProviders(getContext(), mHandler, mUserProfiles);
mZenModeHelper = new ZenModeHelper(getContext(), mHandler.getLooper(), mConditionProviders); mZenModeHelper = new ZenModeHelper(getContext(), mHandler.getLooper(), mConditionProviders);
@@ -882,7 +884,6 @@ public class NotificationManagerService extends SystemService {
}); });
final File systemDir = new File(Environment.getDataDirectory(), "system"); final File systemDir = new File(Environment.getDataDirectory(), "system");
mPolicyFile = new AtomicFile(new File(systemDir, "notification_policy.xml")); mPolicyFile = new AtomicFile(new File(systemDir, "notification_policy.xml"));
mUsageStats = new NotificationUsageStats(getContext());
importOldBlockDb(); importOldBlockDb();
@@ -2071,6 +2072,7 @@ public class NotificationManagerService extends SystemService {
r.score = JUNK_SCORE; r.score = JUNK_SCORE;
Slog.e(TAG, "Suppressing notification from package " + pkg Slog.e(TAG, "Suppressing notification from package " + pkg
+ " by user request."); + " by user request.");
mUsageStats.registerBlocked(r);
} }
} }
@@ -2736,12 +2738,6 @@ public class NotificationManagerService extends SystemService {
case REASON_NOMAN_CANCEL_ALL: case REASON_NOMAN_CANCEL_ALL:
mUsageStats.registerRemovedByApp(r); mUsageStats.registerRemovedByApp(r);
break; break;
case REASON_DELEGATE_CLICK:
mUsageStats.registerCancelDueToClick(r);
break;
default:
mUsageStats.registerCancelUnknown(r);
break;
} }
mNotificationsByKey.remove(r.sbn.getKey()); mNotificationsByKey.remove(r.sbn.getKey());

View File

@@ -26,7 +26,7 @@ import android.content.Context;
public interface NotificationSignalExtractor { public interface NotificationSignalExtractor {
/** One-time initialization. */ /** One-time initialization. */
public void initialize(Context context); public void initialize(Context context, NotificationUsageStats usageStats);
/** /**
* Called once per notification that is posted or updated. * Called once per notification that is posted or updated.

View File

@@ -25,13 +25,13 @@ import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.Message; import android.os.Message;
import android.os.SystemClock; import android.os.SystemClock;
import android.service.notification.StatusBarNotification;
import android.util.Log; import android.util.Log;
import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsLogger;
import com.android.server.notification.NotificationManagerService.DumpFilter; import com.android.server.notification.NotificationManagerService.DumpFilter;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -47,21 +47,45 @@ import java.util.Map;
* {@hide} * {@hide}
*/ */
public class NotificationUsageStats { public class NotificationUsageStats {
// WARNING: Aggregated stats can grow unboundedly with pkg+id+tag. private static final String TAG = "NotificationUsageStats";
// Don't enable on production builds.
private static final boolean ENABLE_AGGREGATED_IN_MEMORY_STATS = false;
private static final boolean ENABLE_SQLITE_LOG = true;
private static final boolean ENABLE_AGGREGATED_IN_MEMORY_STATS = true;
private static final boolean ENABLE_SQLITE_LOG = true;
private static final AggregatedStats[] EMPTY_AGGREGATED_STATS = new AggregatedStats[0]; private static final AggregatedStats[] EMPTY_AGGREGATED_STATS = new AggregatedStats[0];
private static final String DEVICE_GLOBAL_STATS = "__global"; // packages start with letters
private static final int MSG_EMIT = 1;
private static final boolean DEBUG = false;
public static final int TEN_SECONDS = 1000 * 10;
public static final int ONE_HOUR = 1000 * 60 * 60;
private static final long EMIT_PERIOD = DEBUG ? TEN_SECONDS : ONE_HOUR;
// Guarded by synchronized(this). // Guarded by synchronized(this).
private final Map<String, AggregatedStats> mStats = new HashMap<String, AggregatedStats>(); private final Map<String, AggregatedStats> mStats = new HashMap<>();
private final ArrayDeque<AggregatedStats[]> mStatsArrays = new ArrayDeque<>();
private final SQLiteLog mSQLiteLog; private final SQLiteLog mSQLiteLog;
private final Context mContext; private final Context mContext;
private final Handler mHandler;
private long mLastEmitTime;
public NotificationUsageStats(Context context) { public NotificationUsageStats(Context context) {
mContext = context; mContext = context;
mLastEmitTime = SystemClock.elapsedRealtime();
mSQLiteLog = ENABLE_SQLITE_LOG ? new SQLiteLog(context) : null; mSQLiteLog = ENABLE_SQLITE_LOG ? new SQLiteLog(context) : null;
mHandler = new Handler(mContext.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_EMIT:
emit();
break;
default:
Log.wtf(TAG, "Unknown message type: " + msg.what);
break;
}
}
};
mHandler.sendEmptyMessageDelayed(MSG_EMIT, EMIT_PERIOD);
} }
/** /**
@@ -70,9 +94,12 @@ public class NotificationUsageStats {
public synchronized void registerPostedByApp(NotificationRecord notification) { public synchronized void registerPostedByApp(NotificationRecord notification) {
notification.stats = new SingleNotificationStats(); notification.stats = new SingleNotificationStats();
notification.stats.posttimeElapsedMs = SystemClock.elapsedRealtime(); notification.stats.posttimeElapsedMs = SystemClock.elapsedRealtime();
for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(notification);
for (AggregatedStats stats : aggregatedStatsArray) {
stats.numPostedByApp++; stats.numPostedByApp++;
} }
releaseAggregatedStatsLocked(aggregatedStatsArray);
if (ENABLE_SQLITE_LOG) { if (ENABLE_SQLITE_LOG) {
mSQLiteLog.logPosted(notification); mSQLiteLog.logPosted(notification);
} }
@@ -83,9 +110,11 @@ public class NotificationUsageStats {
*/ */
public void registerUpdatedByApp(NotificationRecord notification, NotificationRecord old) { public void registerUpdatedByApp(NotificationRecord notification, NotificationRecord old) {
notification.stats = old.stats; notification.stats = old.stats;
for (AggregatedStats stats : getAggregatedStatsLocked(notification)) { AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(notification);
for (AggregatedStats stats : aggregatedStatsArray) {
stats.numUpdatedByApp++; stats.numUpdatedByApp++;
} }
releaseAggregatedStatsLocked(aggregatedStatsArray);
} }
/** /**
@@ -93,10 +122,11 @@ public class NotificationUsageStats {
*/ */
public synchronized void registerRemovedByApp(NotificationRecord notification) { public synchronized void registerRemovedByApp(NotificationRecord notification) {
notification.stats.onRemoved(); notification.stats.onRemoved();
for (AggregatedStats stats : getAggregatedStatsLocked(notification)) { AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(notification);
for (AggregatedStats stats : aggregatedStatsArray) {
stats.numRemovedByApp++; stats.numRemovedByApp++;
stats.collect(notification.stats);
} }
releaseAggregatedStatsLocked(aggregatedStatsArray);
if (ENABLE_SQLITE_LOG) { if (ENABLE_SQLITE_LOG) {
mSQLiteLog.logRemoved(notification); mSQLiteLog.logRemoved(notification);
} }
@@ -109,10 +139,6 @@ public class NotificationUsageStats {
MetricsLogger.histogram(mContext, "note_dismiss_longevity", MetricsLogger.histogram(mContext, "note_dismiss_longevity",
(int) (System.currentTimeMillis() - notification.getRankingTimeMs()) / (60 * 1000)); (int) (System.currentTimeMillis() - notification.getRankingTimeMs()) / (60 * 1000));
notification.stats.onDismiss(); notification.stats.onDismiss();
for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
stats.numDismissedByUser++;
stats.collect(notification.stats);
}
if (ENABLE_SQLITE_LOG) { if (ENABLE_SQLITE_LOG) {
mSQLiteLog.logDismissed(notification); mSQLiteLog.logDismissed(notification);
} }
@@ -125,36 +151,36 @@ public class NotificationUsageStats {
MetricsLogger.histogram(mContext, "note_click_longevity", MetricsLogger.histogram(mContext, "note_click_longevity",
(int) (System.currentTimeMillis() - notification.getRankingTimeMs()) / (60 * 1000)); (int) (System.currentTimeMillis() - notification.getRankingTimeMs()) / (60 * 1000));
notification.stats.onClick(); notification.stats.onClick();
for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
stats.numClickedByUser++;
}
if (ENABLE_SQLITE_LOG) { if (ENABLE_SQLITE_LOG) {
mSQLiteLog.logClicked(notification); mSQLiteLog.logClicked(notification);
} }
} }
/** public synchronized void registerPeopleAffinity(NotificationRecord notification, boolean valid,
* Called when the notification is canceled because the user clicked it. boolean starred, boolean cached) {
* AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(notification);
* <p>Called after {@link #registerClickedByUser(NotificationRecord)}.</p> for (AggregatedStats stats : aggregatedStatsArray) {
*/ if (valid) {
public synchronized void registerCancelDueToClick(NotificationRecord notification) { stats.numWithValidPeople++;
notification.stats.onCancel(); }
for (AggregatedStats stats : getAggregatedStatsLocked(notification)) { if (starred) {
stats.collect(notification.stats); stats.numWithStaredPeople++;
}
if (cached) {
stats.numPeopleCacheHit++;
} else {
stats.numPeopleCacheMiss++;
}
} }
releaseAggregatedStatsLocked(aggregatedStatsArray);
} }
/** public synchronized void registerBlocked(NotificationRecord notification) {
* Called when the notification is canceled due to unknown reasons. AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(notification);
* for (AggregatedStats stats : aggregatedStatsArray) {
* <p>Called for notifications of apps being uninstalled, for example.</p> stats.numBlocked++;
*/
public synchronized void registerCancelUnknown(NotificationRecord notification) {
notification.stats.onCancel();
for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
stats.collect(notification.stats);
} }
releaseAggregatedStatsLocked(aggregatedStatsArray);
} }
// Locked by this. // Locked by this.
@@ -163,24 +189,28 @@ public class NotificationUsageStats {
return EMPTY_AGGREGATED_STATS; return EMPTY_AGGREGATED_STATS;
} }
StatusBarNotification n = record.sbn; // TODO: expand to package-level counts in the future.
AggregatedStats[] array = mStatsArrays.poll();
if (array == null) {
array = new AggregatedStats[1];
}
array[0] = getOrCreateAggregatedStatsLocked(DEVICE_GLOBAL_STATS);
return array;
}
String user = String.valueOf(n.getUserId()); // Locked by this.
String userPackage = user + ":" + n.getPackageName(); private void releaseAggregatedStatsLocked(AggregatedStats[] array) {
for(int i = 0; i < array.length; i++) {
// TODO: Use pool of arrays. array[i] = null;
return new AggregatedStats[] { }
getOrCreateAggregatedStatsLocked(user), mStatsArrays.offer(array);
getOrCreateAggregatedStatsLocked(userPackage),
getOrCreateAggregatedStatsLocked(n.getKey()),
};
} }
// Locked by this. // Locked by this.
private AggregatedStats getOrCreateAggregatedStatsLocked(String key) { private AggregatedStats getOrCreateAggregatedStatsLocked(String key) {
AggregatedStats result = mStats.get(key); AggregatedStats result = mStats.get(key);
if (result == null) { if (result == null) {
result = new AggregatedStats(key); result = new AggregatedStats(mContext, key);
mStats.put(key, result); mStats.put(key, result);
} }
return result; return result;
@@ -193,64 +223,74 @@ public class NotificationUsageStats {
continue; continue;
as.dump(pw, indent); as.dump(pw, indent);
} }
pw.println(indent + "mStatsArrays.size(): " + mStatsArrays.size());
} }
if (ENABLE_SQLITE_LOG) { if (ENABLE_SQLITE_LOG) {
mSQLiteLog.dump(pw, indent, filter); mSQLiteLog.dump(pw, indent, filter);
} }
} }
public synchronized void emit() {
// TODO: expand to package-level counts in the future.
AggregatedStats stats = getOrCreateAggregatedStatsLocked(DEVICE_GLOBAL_STATS);
stats.emit();
mLastEmitTime = SystemClock.elapsedRealtime();
mHandler.removeMessages(MSG_EMIT);
mHandler.sendEmptyMessageDelayed(MSG_EMIT, EMIT_PERIOD);
}
/** /**
* Aggregated notification stats. * Aggregated notification stats.
*/ */
private static class AggregatedStats { private static class AggregatedStats {
private final Context mContext;
public final String key; public final String key;
// ---- Updated as the respective events occur. // ---- Updated as the respective events occur.
public int numPostedByApp; public int numPostedByApp;
public int numUpdatedByApp; public int numUpdatedByApp;
public int numRemovedByApp; public int numRemovedByApp;
public int numClickedByUser; public int numPeopleCacheHit;
public int numDismissedByUser; public int numPeopleCacheMiss;;
public int numWithStaredPeople;
public int numWithValidPeople;
public int numBlocked;
// ---- Updated when a notification is canceled. private AggregatedStats mPrevious;
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 final Aggregate userExpansionCount = new Aggregate();
public final Aggregate airtimeExpandedMs = new Aggregate();
public final Aggregate posttimeToFirstVisibleExpansionMs = new Aggregate();
public AggregatedStats(String key) { public AggregatedStats(Context context, String key) {
this.key = key; this.key = key;
mContext = context;
} }
public void collect(SingleNotificationStats singleNotificationStats) { public void emit() {
posttimeMs.addSample( if (mPrevious == null) {
SystemClock.elapsedRealtime() - singleNotificationStats.posttimeElapsedMs); mPrevious = new AggregatedStats(null, key);
if (singleNotificationStats.posttimeToDismissMs >= 0) {
posttimeToDismissMs.addSample(singleNotificationStats.posttimeToDismissMs);
} }
if (singleNotificationStats.posttimeToFirstClickMs >= 0) {
posttimeToFirstClickMs.addSample(singleNotificationStats.posttimeToFirstClickMs); maybeCount("note_post", (numPostedByApp - mPrevious.numPostedByApp));
} maybeCount("note_update", (numUpdatedByApp - mPrevious.numUpdatedByApp));
airtimeCount.addSample(singleNotificationStats.airtimeCount); maybeCount("note_remove", (numRemovedByApp - mPrevious.numRemovedByApp));
if (singleNotificationStats.airtimeMs >= 0) { maybeCount("note_with_people", (numWithValidPeople - mPrevious.numWithValidPeople));
airtimeMs.addSample(singleNotificationStats.airtimeMs); maybeCount("note_with_stars", (numWithStaredPeople - mPrevious.numWithStaredPeople));
} maybeCount("people_cache_hit", (numPeopleCacheHit - mPrevious.numPeopleCacheHit));
if (singleNotificationStats.posttimeToFirstAirtimeMs >= 0) { maybeCount("people_cache_miss", (numPeopleCacheMiss - mPrevious.numPeopleCacheMiss));
posttimeToFirstAirtimeMs.addSample( maybeCount("note_blocked", (numBlocked - mPrevious.numBlocked));
singleNotificationStats.posttimeToFirstAirtimeMs);
} mPrevious.numPostedByApp = numPostedByApp;
if (singleNotificationStats.posttimeToFirstVisibleExpansionMs >= 0) { mPrevious.numUpdatedByApp = numUpdatedByApp;
posttimeToFirstVisibleExpansionMs.addSample( mPrevious.numRemovedByApp = numRemovedByApp;
singleNotificationStats.posttimeToFirstVisibleExpansionMs); mPrevious.numPeopleCacheHit = numPeopleCacheHit;
} mPrevious.numPeopleCacheMiss = numPeopleCacheMiss;
userExpansionCount.addSample(singleNotificationStats.userExpansionCount); mPrevious.numWithStaredPeople = numWithStaredPeople;
if (singleNotificationStats.airtimeExpandedMs >= 0) { mPrevious.numWithValidPeople = numWithValidPeople;
airtimeExpandedMs.addSample(singleNotificationStats.airtimeExpandedMs); mPrevious.numBlocked = numBlocked;
}
void maybeCount(String name, int value) {
if (value > 0) {
MetricsLogger.count(mContext, name, value);
} }
} }
@@ -269,17 +309,11 @@ public class NotificationUsageStats {
indent + " numPostedByApp=" + numPostedByApp + ",\n" + indent + " numPostedByApp=" + numPostedByApp + ",\n" +
indent + " numUpdatedByApp=" + numUpdatedByApp + ",\n" + indent + " numUpdatedByApp=" + numUpdatedByApp + ",\n" +
indent + " numRemovedByApp=" + numRemovedByApp + ",\n" + indent + " numRemovedByApp=" + numRemovedByApp + ",\n" +
indent + " numClickedByUser=" + numClickedByUser + ",\n" + indent + " numPeopleCacheHit=" + numPeopleCacheHit + ",\n" +
indent + " numDismissedByUser=" + numDismissedByUser + ",\n" + indent + " numWithStaredPeople=" + numWithStaredPeople + ",\n" +
indent + " posttimeMs=" + posttimeMs + ",\n" + indent + " numWithValidPeople=" + numWithValidPeople + ",\n" +
indent + " posttimeToDismissMs=" + posttimeToDismissMs + ",\n" + indent + " numPeopleCacheMiss=" + numPeopleCacheMiss + ",\n" +
indent + " posttimeToFirstClickMs=" + posttimeToFirstClickMs + ",\n" + indent + " numBlocked=" + numBlocked + ",\n" +
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 + "}"; indent + "}";
} }
} }

View File

@@ -24,7 +24,7 @@ public class PackagePriorityExtractor implements NotificationSignalExtractor {
private RankingConfig mConfig; private RankingConfig mConfig;
public void initialize(Context ctx) { public void initialize(Context ctx, NotificationUsageStats usageStats) {
if (DBG) Slog.d(TAG, "Initializing " + getClass().getSimpleName() + "."); if (DBG) Slog.d(TAG, "Initializing " + getClass().getSimpleName() + ".");
} }

View File

@@ -24,7 +24,7 @@ public class PackageVisibilityExtractor implements NotificationSignalExtractor {
private RankingConfig mConfig; private RankingConfig mConfig;
public void initialize(Context ctx) { public void initialize(Context ctx, NotificationUsageStats usageStats) {
if (DBG) Slog.d(TAG, "Initializing " + getClass().getSimpleName() + "."); if (DBG) Slog.d(TAG, "Initializing " + getClass().getSimpleName() + ".");
} }

View File

@@ -68,7 +68,8 @@ public class RankingHelper implements RankingConfig {
private final Context mContext; private final Context mContext;
private final Handler mRankingHandler; private final Handler mRankingHandler;
public RankingHelper(Context context, Handler rankingHandler, String[] extractorNames) { public RankingHelper(Context context, Handler rankingHandler, NotificationUsageStats usageStats,
String[] extractorNames) {
mContext = context; mContext = context;
mRankingHandler = rankingHandler; mRankingHandler = rankingHandler;
@@ -79,7 +80,7 @@ public class RankingHelper implements RankingConfig {
Class<?> extractorClass = mContext.getClassLoader().loadClass(extractorNames[i]); Class<?> extractorClass = mContext.getClassLoader().loadClass(extractorNames[i]);
NotificationSignalExtractor extractor = NotificationSignalExtractor extractor =
(NotificationSignalExtractor) extractorClass.newInstance(); (NotificationSignalExtractor) extractorClass.newInstance();
extractor.initialize(mContext); extractor.initialize(mContext, usageStats);
extractor.setConfig(this); extractor.setConfig(this);
mSignalExtractors[i] = extractor; mSignalExtractors[i] = extractor;
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {

View File

@@ -34,7 +34,6 @@ import android.util.ArrayMap;
import android.util.Log; import android.util.Log;
import android.util.LruCache; import android.util.LruCache;
import android.util.Slog; import android.util.Slog;
import com.android.internal.logging.MetricsLogger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
@@ -85,11 +84,13 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
private Handler mHandler; private Handler mHandler;
private ContentObserver mObserver; private ContentObserver mObserver;
private int mEvictionCount; private int mEvictionCount;
private NotificationUsageStats mUsageStats;
public void initialize(Context context) { public void initialize(Context context, NotificationUsageStats usageStats) {
if (DEBUG) Slog.d(TAG, "Initializing " + getClass().getSimpleName() + "."); if (DEBUG) Slog.d(TAG, "Initializing " + getClass().getSimpleName() + ".");
mUserToContextMap = new ArrayMap<>(); mUserToContextMap = new ArrayMap<>();
mBaseContext = context; mBaseContext = context;
mUsageStats = usageStats;
mPeopleCache = new LruCache<String, LookupResult>(PEOPLE_CACHE_SIZE); mPeopleCache = new LruCache<String, LookupResult>(PEOPLE_CACHE_SIZE);
mEnabled = ENABLE_PEOPLE_VALIDATOR && 1 == Settings.Global.getInt( mEnabled = ENABLE_PEOPLE_VALIDATOR && 1 == Settings.Global.getInt(
mBaseContext.getContentResolver(), SETTING_ENABLE_PEOPLE_VALIDATOR, 1); mBaseContext.getContentResolver(), SETTING_ENABLE_PEOPLE_VALIDATOR, 1);
@@ -203,8 +204,15 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
final String key = record.getKey(); final String key = record.getKey();
final Bundle extras = record.getNotification().extras; final Bundle extras = record.getNotification().extras;
final float[] affinityOut = new float[1]; final float[] affinityOut = new float[1];
final RankingReconsideration rr = validatePeople(context, key, extras, affinityOut); final PeopleRankingReconsideration rr = validatePeople(context, key, extras, affinityOut);
record.setContactAffinity(affinityOut[0]); final float affinity = affinityOut[0];
record.setContactAffinity(affinity);
if (rr == null) {
mUsageStats.registerPeopleAffinity(record, affinity > NONE, affinity == STARRED_CONTACT,
true /* cached */);
} else {
rr.setRecord(record);
}
return rr; return rr;
} }
@@ -245,7 +253,6 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
if (pendingLookups.isEmpty()) { if (pendingLookups.isEmpty()) {
if (VERBOSE) Slog.i(TAG, "final affinity: " + affinity); if (VERBOSE) Slog.i(TAG, "final affinity: " + affinity);
if (affinity != NONE) MetricsLogger.count(mBaseContext, "note_with_people", 1);
return null; return null;
} }
@@ -413,6 +420,7 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
private final Context mContext; private final Context mContext;
private float mContactAffinity = NONE; private float mContactAffinity = NONE;
private NotificationRecord mRecord;
private PeopleRankingReconsideration(Context context, String key, LinkedList<String> pendingLookups) { private PeopleRankingReconsideration(Context context, String key, LinkedList<String> pendingLookups) {
super(key); super(key);
@@ -456,7 +464,10 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
"ms"); "ms");
} }
if (mContactAffinity != NONE) MetricsLogger.count(mBaseContext, "note_with_people", 1); if (mRecord != null) {
mUsageStats.registerPeopleAffinity(mRecord, mContactAffinity > NONE,
mContactAffinity == STARRED_CONTACT, false /* cached */);
}
} }
@Override @Override
@@ -469,6 +480,10 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor {
public float getContactAffinity() { public float getContactAffinity() {
return mContactAffinity; return mContactAffinity;
} }
public void setRecord(NotificationRecord record) {
mRecord = record;
}
} }
} }

View File

@@ -15,6 +15,9 @@
*/ */
package com.android.server.notification; package com.android.server.notification;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import android.app.Notification; import android.app.Notification;
import android.os.UserHandle; import android.os.UserHandle;
import android.service.notification.StatusBarNotification; import android.service.notification.StatusBarNotification;
@@ -24,6 +27,7 @@ import android.test.suitebuilder.annotation.SmallTest;
import java.util.ArrayList; import java.util.ArrayList;
public class RankingHelperTest extends AndroidTestCase { public class RankingHelperTest extends AndroidTestCase {
@Mock NotificationUsageStats mUsageStats;
private Notification mNotiGroupGSortA; private Notification mNotiGroupGSortA;
private Notification mNotiGroupGSortB; private Notification mNotiGroupGSortB;
@@ -39,9 +43,10 @@ public class RankingHelperTest extends AndroidTestCase {
@Override @Override
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this);
UserHandle user = UserHandle.ALL; UserHandle user = UserHandle.ALL;
mHelper = new RankingHelper(getContext(), null, new String[0]); mHelper = new RankingHelper(getContext(), null, mUsageStats, new String[0]);
mNotiGroupGSortA = new Notification.Builder(getContext()) mNotiGroupGSortA = new Notification.Builder(getContext())
.setContentTitle("A") .setContentTitle("A")