Merge "change the default notification rules"
This commit is contained in:
@@ -33,6 +33,7 @@ import android.service.notification.NotificationListenerService;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.server.EventLogTags;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
@@ -106,6 +107,7 @@ public final class NotificationRecord {
|
||||
mCreationTimeMs = sbn.getPostTime();
|
||||
mUpdateTimeMs = mCreationTimeMs;
|
||||
mContext = context;
|
||||
stats = new NotificationUsageStats.SingleNotificationStats();
|
||||
mImportance = defaultImportance();
|
||||
}
|
||||
|
||||
@@ -133,27 +135,22 @@ public final class NotificationRecord {
|
||||
importance = IMPORTANCE_MAX;
|
||||
break;
|
||||
}
|
||||
stats.requestedImportance = importance;
|
||||
|
||||
boolean isNoisy = (n.defaults & Notification.DEFAULT_SOUND) != 0
|
||||
|| (n.defaults & Notification.DEFAULT_VIBRATE) != 0
|
||||
|| n.sound != null
|
||||
|| n.vibrate != null;
|
||||
stats.isNoisy = isNoisy;
|
||||
if (!isNoisy && importance > IMPORTANCE_DEFAULT) {
|
||||
importance = IMPORTANCE_DEFAULT;
|
||||
}
|
||||
// maybe only do this for target API < N?
|
||||
if (isNoisy) {
|
||||
if (importance >= IMPORTANCE_HIGH) {
|
||||
importance = IMPORTANCE_MAX;
|
||||
} else {
|
||||
importance = IMPORTANCE_HIGH;
|
||||
}
|
||||
}
|
||||
|
||||
if (n.fullScreenIntent != null) {
|
||||
importance = IMPORTANCE_MAX;
|
||||
}
|
||||
|
||||
stats.naturalImportance = importance;
|
||||
return importance;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.notification;
|
||||
|
||||
import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
@@ -101,7 +103,6 @@ public class NotificationUsageStats {
|
||||
* Called when a notification has been posted.
|
||||
*/
|
||||
public synchronized void registerPostedByApp(NotificationRecord notification) {
|
||||
notification.stats = new SingleNotificationStats();
|
||||
notification.stats.posttimeElapsedMs = SystemClock.elapsedRealtime();
|
||||
|
||||
AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(notification);
|
||||
@@ -119,13 +120,16 @@ public class NotificationUsageStats {
|
||||
* Called when a notification has been updated.
|
||||
*/
|
||||
public void registerUpdatedByApp(NotificationRecord notification, NotificationRecord old) {
|
||||
notification.stats = old.stats;
|
||||
notification.stats.updateFrom(old.stats);
|
||||
AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(notification);
|
||||
for (AggregatedStats stats : aggregatedStatsArray) {
|
||||
stats.numUpdatedByApp++;
|
||||
stats.countApiUse(notification);
|
||||
}
|
||||
releaseAggregatedStatsLocked(aggregatedStatsArray);
|
||||
if (ENABLE_SQLITE_LOG) {
|
||||
mSQLiteLog.logPosted(notification);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,10 +301,6 @@ public class NotificationUsageStats {
|
||||
public int numWithActions;
|
||||
public int numPrivate;
|
||||
public int numSecret;
|
||||
public int numPriorityMax;
|
||||
public int numPriorityHigh;
|
||||
public int numPriorityLow;
|
||||
public int numPriorityMin;
|
||||
public int numWithBigText;
|
||||
public int numWithBigPicture;
|
||||
public int numForegroundService;
|
||||
@@ -314,11 +314,17 @@ public class NotificationUsageStats {
|
||||
public int numWithSubText;
|
||||
public int numWithInfoText;
|
||||
public int numInterrupt;
|
||||
public ImportanceHistogram noisyImportance;
|
||||
public ImportanceHistogram quietImportance;
|
||||
public ImportanceHistogram finalImportance;
|
||||
|
||||
public AggregatedStats(Context context, String key) {
|
||||
this.key = key;
|
||||
mContext = context;
|
||||
mCreated = SystemClock.elapsedRealtime();
|
||||
noisyImportance = new ImportanceHistogram(context, "note_imp_noisy_");
|
||||
quietImportance = new ImportanceHistogram(context, "note_imp_quiet_");
|
||||
finalImportance = new ImportanceHistogram(context, "note_importance_");
|
||||
}
|
||||
|
||||
public void countApiUse(NotificationRecord record) {
|
||||
@@ -354,20 +360,12 @@ public class NotificationUsageStats {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (n.priority) {
|
||||
case Notification.PRIORITY_MAX:
|
||||
numPriorityMax++;
|
||||
break;
|
||||
case Notification.PRIORITY_HIGH:
|
||||
numPriorityHigh++;
|
||||
break;
|
||||
case Notification.PRIORITY_LOW:
|
||||
numPriorityLow++;
|
||||
break;
|
||||
case Notification.PRIORITY_MIN:
|
||||
numPriorityMin++;
|
||||
break;
|
||||
if (record.stats.isNoisy) {
|
||||
noisyImportance.increment(record.stats.requestedImportance);
|
||||
} else {
|
||||
quietImportance.increment(record.stats.requestedImportance);
|
||||
}
|
||||
finalImportance.increment(record.getImportance());
|
||||
|
||||
final Set<String> names = n.extras.keySet();
|
||||
if (names.contains(Notification.EXTRA_BIG_TEXT)) {
|
||||
@@ -419,10 +417,6 @@ public class NotificationUsageStats {
|
||||
maybeCount("note_with_actions", (numWithActions - mPrevious.numWithActions));
|
||||
maybeCount("note_private", (numPrivate - mPrevious.numPrivate));
|
||||
maybeCount("note_secret", (numSecret - mPrevious.numSecret));
|
||||
maybeCount("note_prio_max", (numPriorityMax - mPrevious.numPriorityMax));
|
||||
maybeCount("note_prio_high", (numPriorityHigh - mPrevious.numPriorityHigh));
|
||||
maybeCount("note_prio_low", (numPriorityLow - mPrevious.numPriorityLow));
|
||||
maybeCount("note_prio_min", (numPriorityMin - mPrevious.numPriorityMin));
|
||||
maybeCount("note_interupt", (numInterrupt - mPrevious.numInterrupt));
|
||||
maybeCount("note_big_text", (numWithBigText - mPrevious.numWithBigText));
|
||||
maybeCount("note_big_pic", (numWithBigPicture - mPrevious.numWithBigPicture));
|
||||
@@ -436,6 +430,9 @@ public class NotificationUsageStats {
|
||||
maybeCount("note_text", (numWithText - mPrevious.numWithText));
|
||||
maybeCount("note_sub_text", (numWithSubText - mPrevious.numWithSubText));
|
||||
maybeCount("note_info_text", (numWithInfoText - mPrevious.numWithInfoText));
|
||||
noisyImportance.maybeCount(mPrevious.noisyImportance);
|
||||
quietImportance.maybeCount(mPrevious.quietImportance);
|
||||
finalImportance.maybeCount(mPrevious.finalImportance);
|
||||
|
||||
mPrevious.numPostedByApp = numPostedByApp;
|
||||
mPrevious.numUpdatedByApp = numUpdatedByApp;
|
||||
@@ -448,10 +445,6 @@ public class NotificationUsageStats {
|
||||
mPrevious.numWithActions = numWithActions;
|
||||
mPrevious.numPrivate = numPrivate;
|
||||
mPrevious.numSecret = numSecret;
|
||||
mPrevious.numPriorityMax = numPriorityMax;
|
||||
mPrevious.numPriorityHigh = numPriorityHigh;
|
||||
mPrevious.numPriorityLow = numPriorityLow;
|
||||
mPrevious.numPriorityMin = numPriorityMin;
|
||||
mPrevious.numInterrupt = numInterrupt;
|
||||
mPrevious.numWithBigText = numWithBigText;
|
||||
mPrevious.numWithBigPicture = numWithBigPicture;
|
||||
@@ -465,6 +458,9 @@ public class NotificationUsageStats {
|
||||
mPrevious.numWithText = numWithText;
|
||||
mPrevious.numWithSubText = numWithSubText;
|
||||
mPrevious.numWithInfoText = numWithInfoText;
|
||||
noisyImportance.update(mPrevious.noisyImportance);
|
||||
quietImportance.update(mPrevious.quietImportance);
|
||||
finalImportance.update(mPrevious.finalImportance);
|
||||
}
|
||||
|
||||
void maybeCount(String name, int value) {
|
||||
@@ -483,17 +479,64 @@ public class NotificationUsageStats {
|
||||
}
|
||||
|
||||
private String toStringWithIndent(String indent) {
|
||||
return indent + "AggregatedStats{\n" +
|
||||
indent + " key='" + key + "',\n" +
|
||||
indent + " numPostedByApp=" + numPostedByApp + ",\n" +
|
||||
indent + " numUpdatedByApp=" + numUpdatedByApp + ",\n" +
|
||||
indent + " numRemovedByApp=" + numRemovedByApp + ",\n" +
|
||||
indent + " numPeopleCacheHit=" + numPeopleCacheHit + ",\n" +
|
||||
indent + " numWithStaredPeople=" + numWithStaredPeople + ",\n" +
|
||||
indent + " numWithValidPeople=" + numWithValidPeople + ",\n" +
|
||||
indent + " numPeopleCacheMiss=" + numPeopleCacheMiss + ",\n" +
|
||||
indent + " numBlocked=" + numBlocked + ",\n" +
|
||||
indent + "}";
|
||||
StringBuilder output = new StringBuilder();
|
||||
output.append(indent).append("AggregatedStats{\n");
|
||||
String indentPlusTwo = indent + " ";
|
||||
output.append(indentPlusTwo);
|
||||
output.append("key='").append(key).append("',\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numPostedByApp=").append(numPostedByApp).append(",\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numUpdatedByApp=").append(numUpdatedByApp).append(",\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numRemovedByApp=").append(numRemovedByApp).append(",\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numPeopleCacheHit=").append(numPeopleCacheHit).append(",\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numWithStaredPeople=").append(numWithStaredPeople).append(",\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numWithValidPeople=").append(numWithValidPeople).append(",\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numPeopleCacheMiss=").append(numPeopleCacheMiss).append(",\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numBlocked=").append(numBlocked).append(",\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numWithActions=").append(numWithActions).append(",\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numPrivate=").append(numPrivate).append(",\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numSecret=").append(numSecret).append(",\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numInterrupt=").append(numInterrupt).append(",\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numWithBigText=").append(numWithBigText).append(",\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numWithBigPicture=").append(numWithBigPicture).append("\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numForegroundService=").append(numForegroundService).append("\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numOngoing=").append(numOngoing).append("\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numAutoCancel=").append(numAutoCancel).append("\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numWithLargeIcon=").append(numWithLargeIcon).append("\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numWithInbox=").append(numWithInbox).append("\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numWithMediaSession=").append(numWithMediaSession).append("\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numWithTitle=").append(numWithTitle).append("\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numWithText=").append(numWithText).append("\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numWithSubText=").append(numWithSubText).append("\n");
|
||||
output.append(indentPlusTwo);
|
||||
output.append("numWithInfoText=").append(numWithInfoText).append("\n");
|
||||
output.append(indentPlusTwo).append(noisyImportance.toString()).append("\n");
|
||||
output.append(indentPlusTwo).append(quietImportance.toString()).append("\n");
|
||||
output.append(indentPlusTwo).append(finalImportance.toString()).append("\n");
|
||||
output.append(indent).append("}");
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
public JSONObject dumpJson() throws JSONException {
|
||||
@@ -511,10 +554,6 @@ public class NotificationUsageStats {
|
||||
maybePut(dump, "numWithActions", numWithActions);
|
||||
maybePut(dump, "numPrivate", numPrivate);
|
||||
maybePut(dump, "numSecret", numSecret);
|
||||
maybePut(dump, "numPriorityMax", numPriorityMax);
|
||||
maybePut(dump, "numPriorityHigh", numPriorityHigh);
|
||||
maybePut(dump, "numPriorityLow", numPriorityLow);
|
||||
maybePut(dump, "numPriorityMin", numPriorityMin);
|
||||
maybePut(dump, "numInterrupt", numInterrupt);
|
||||
maybePut(dump, "numWithBigText", numWithBigText);
|
||||
maybePut(dump, "numWithBigPicture", numWithBigPicture);
|
||||
@@ -528,6 +567,10 @@ public class NotificationUsageStats {
|
||||
maybePut(dump, "numWithText", numWithText);
|
||||
maybePut(dump, "numWithSubText", numWithSubText);
|
||||
maybePut(dump, "numWithInfoText", numWithInfoText);
|
||||
noisyImportance.maybePut(dump, mPrevious.noisyImportance);
|
||||
quietImportance.maybePut(dump, mPrevious.quietImportance);
|
||||
finalImportance.maybePut(dump, mPrevious.finalImportance);
|
||||
|
||||
return dump;
|
||||
}
|
||||
|
||||
@@ -538,6 +581,65 @@ public class NotificationUsageStats {
|
||||
}
|
||||
}
|
||||
|
||||
private static class ImportanceHistogram {
|
||||
// TODO define these somewhere else
|
||||
private static final int NUM_IMPORTANCES = 5;
|
||||
private static final String[] IMPORTANCE_NAMES = {"none", "low", "default", "high", "max"};
|
||||
private final Context mContext;
|
||||
private final String[] mCounterNames;
|
||||
private final String mPrefix;
|
||||
private int[] mCount;
|
||||
|
||||
ImportanceHistogram(Context context, String prefix) {
|
||||
mContext = context;
|
||||
mCount = new int[NUM_IMPORTANCES];
|
||||
mCounterNames = new String[NUM_IMPORTANCES];
|
||||
mPrefix = prefix;
|
||||
for (int i = 0; i < NUM_IMPORTANCES; i++) {
|
||||
mCounterNames[i] = mPrefix + IMPORTANCE_NAMES[i];
|
||||
}
|
||||
}
|
||||
|
||||
void increment(int imp) {
|
||||
imp = imp < 0 ? 0 : imp > NUM_IMPORTANCES ? NUM_IMPORTANCES : imp;
|
||||
mCount[imp] ++;
|
||||
}
|
||||
|
||||
void maybeCount(ImportanceHistogram prev) {
|
||||
for (int i = 0; i < NUM_IMPORTANCES; i++) {
|
||||
final int value = mCount[i] - prev.mCount[i];
|
||||
if (value > 0) {
|
||||
MetricsLogger.count(mContext, mCounterNames[i], value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void update(ImportanceHistogram that) {
|
||||
for (int i = 0; i < NUM_IMPORTANCES; i++) {
|
||||
mCount[i] = that.mCount[i];
|
||||
}
|
||||
}
|
||||
|
||||
public void maybePut(JSONObject dump, ImportanceHistogram prev)
|
||||
throws JSONException {
|
||||
dump.put(mPrefix, new JSONArray(mCount));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder output = new StringBuilder();
|
||||
output.append(mPrefix).append(": [");
|
||||
for (int i = 0; i < NUM_IMPORTANCES; i++) {
|
||||
output.append(mCount[i]);
|
||||
if (i < (NUM_IMPORTANCES-1)) {
|
||||
output.append(", ");
|
||||
}
|
||||
}
|
||||
output.append("]");
|
||||
return output.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks usage of an individual notification that is currently active.
|
||||
*/
|
||||
@@ -575,6 +677,12 @@ public class NotificationUsageStats {
|
||||
public long airtimeExpandedMs = 0;
|
||||
/** Number of times the notification has been expanded by the user. */
|
||||
public long userExpansionCount = 0;
|
||||
/** Importance directly requested by the app. */
|
||||
public int requestedImportance;
|
||||
/** Did the app include sound or vibration on the notificaiton. */
|
||||
public boolean isNoisy;
|
||||
/** Importance after initial filtering for noise and other features */
|
||||
public int naturalImportance;
|
||||
|
||||
public long getCurrentPosttimeMs() {
|
||||
if (posttimeElapsedMs < 0) {
|
||||
@@ -686,17 +794,40 @@ public class NotificationUsageStats {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SingleNotificationStats{" +
|
||||
"posttimeElapsedMs=" + posttimeElapsedMs +
|
||||
", posttimeToFirstClickMs=" + posttimeToFirstClickMs +
|
||||
", posttimeToDismissMs=" + posttimeToDismissMs +
|
||||
", airtimeCount=" + airtimeCount +
|
||||
", airtimeMs=" + airtimeMs +
|
||||
", currentAirtimeStartElapsedMs=" + currentAirtimeStartElapsedMs +
|
||||
", airtimeExpandedMs=" + airtimeExpandedMs +
|
||||
", posttimeToFirstVisibleExpansionMs=" + posttimeToFirstVisibleExpansionMs +
|
||||
", currentAirtimeExpandedSEMs=" + currentAirtimeExpandedStartElapsedMs +
|
||||
'}';
|
||||
StringBuilder output = new StringBuilder();
|
||||
output.append("SingleNotificationStats{");
|
||||
|
||||
output.append("posttimeElapsedMs=").append(posttimeElapsedMs).append(", ");
|
||||
output.append("posttimeToFirstClickMs=").append(posttimeToFirstClickMs).append(", ");
|
||||
output.append("posttimeToDismissMs=").append(posttimeToDismissMs).append(", ");
|
||||
output.append("airtimeCount=").append(airtimeCount).append(", ");
|
||||
output.append("airtimeMs=").append(airtimeMs).append(", ");
|
||||
output.append("currentAirtimeStartElapsedMs=").append(currentAirtimeStartElapsedMs)
|
||||
.append(", ");
|
||||
output.append("airtimeExpandedMs=").append(airtimeExpandedMs).append(", ");
|
||||
output.append("posttimeToFirstVisibleExpansionMs=")
|
||||
.append(posttimeToFirstVisibleExpansionMs).append(", ");
|
||||
output.append("currentAirtimeExpandedStartElapsedMs=")
|
||||
.append(currentAirtimeExpandedStartElapsedMs).append(", ");
|
||||
output.append("requestedImportance=").append(requestedImportance).append(", ");
|
||||
output.append("naturalImportance=").append(naturalImportance).append(", ");
|
||||
output.append("isNoisy=").append(isNoisy);
|
||||
output.append('}');
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
/** Copy useful information out of the stats from the pre-update notifications. */
|
||||
public void updateFrom(SingleNotificationStats old) {
|
||||
posttimeElapsedMs = old.posttimeElapsedMs;
|
||||
posttimeToFirstClickMs = old.posttimeToFirstClickMs;
|
||||
airtimeCount = old.airtimeCount;
|
||||
posttimeToFirstAirtimeMs = old.posttimeToFirstAirtimeMs;
|
||||
currentAirtimeStartElapsedMs = old.currentAirtimeStartElapsedMs;
|
||||
airtimeMs = old.airtimeMs;
|
||||
posttimeToFirstVisibleExpansionMs = old.posttimeToFirstVisibleExpansionMs;
|
||||
currentAirtimeExpandedStartElapsedMs = old.currentAirtimeExpandedStartElapsedMs;
|
||||
airtimeExpandedMs = old.airtimeExpandedMs;
|
||||
userExpansionCount = old.userExpansionCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -741,7 +872,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 = 4;
|
||||
private static final int DB_VERSION = 5;
|
||||
|
||||
/** Age in ms after which events are pruned from the DB. */
|
||||
private static final long HORIZON_MS = 7 * 24 * 60 * 60 * 1000L; // 1 week
|
||||
@@ -762,7 +893,11 @@ public class NotificationUsageStats {
|
||||
private static final String COL_WHEN_MS = "when_ms";
|
||||
private static final String COL_DEFAULTS = "defaults";
|
||||
private static final String COL_FLAGS = "flags";
|
||||
private static final String COL_PRIORITY = "priority";
|
||||
private static final String COL_IMPORTANCE_REQ = "importance_request";
|
||||
private static final String COL_IMPORTANCE_FINAL = "importance_final";
|
||||
private static final String COL_NOISY = "noisy";
|
||||
private static final String COL_MUTED = "muted";
|
||||
private static final String COL_DEMOTED = "demoted";
|
||||
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";
|
||||
@@ -776,14 +911,28 @@ public class NotificationUsageStats {
|
||||
private static final int EVENT_TYPE_CLICK = 2;
|
||||
private static final int EVENT_TYPE_REMOVE = 3;
|
||||
private static final int EVENT_TYPE_DISMISS = 4;
|
||||
|
||||
private static long sLastPruneMs;
|
||||
|
||||
private static long sNumWrites;
|
||||
|
||||
private final SQLiteOpenHelper mHelper;
|
||||
private final Handler mWriteHandler;
|
||||
|
||||
private final Handler mWriteHandler;
|
||||
private static final long DAY_MS = 24 * 60 * 60 * 1000;
|
||||
private static final String STATS_QUERY = "SELECT " +
|
||||
COL_EVENT_USER_ID + ", " +
|
||||
COL_PKG + ", " +
|
||||
// Bucket by day by looking at 'floor((midnight - eventTimeMs) / dayMs)'
|
||||
"CAST(((%d - " + COL_EVENT_TIME + ") / " + DAY_MS + ") AS int) " +
|
||||
"AS day, " +
|
||||
"COUNT(*) AS cnt, " +
|
||||
"SUM(" + COL_MUTED + ") as muted, " +
|
||||
"SUM(" + COL_NOISY + ") as noisy, " +
|
||||
"SUM(" + COL_DEMOTED + ") as demoted " +
|
||||
"FROM " + TAB_LOG + " " +
|
||||
"WHERE " +
|
||||
COL_EVENT_TYPE + "=" + EVENT_TYPE_POST +
|
||||
" AND " + COL_EVENT_TIME + " > %d " +
|
||||
" GROUP BY " + COL_EVENT_USER_ID + ", day, " + COL_PKG;
|
||||
|
||||
public SQLiteLog(Context context) {
|
||||
HandlerThread backgroundThread = new HandlerThread("notification-sqlite-log",
|
||||
@@ -828,7 +977,11 @@ public class NotificationUsageStats {
|
||||
COL_WHEN_MS + " INT," +
|
||||
COL_DEFAULTS + " INT," +
|
||||
COL_FLAGS + " INT," +
|
||||
COL_PRIORITY + " INT," +
|
||||
COL_IMPORTANCE_REQ + " INT," +
|
||||
COL_IMPORTANCE_FINAL + " INT," +
|
||||
COL_NOISY + " INT," +
|
||||
COL_MUTED + " INT," +
|
||||
COL_DEMOTED + " INT," +
|
||||
COL_CATEGORY + " TEXT," +
|
||||
COL_ACTION_COUNT + " INT," +
|
||||
COL_POSTTIME_MS + " INT," +
|
||||
@@ -841,8 +994,7 @@ public class NotificationUsageStats {
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
if (oldVersion <= 3) {
|
||||
// Version 3 creation left 'log' in a weird state. Just reset for now.
|
||||
if (oldVersion != newVersion) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + TAB_LOG);
|
||||
onCreate(db);
|
||||
}
|
||||
@@ -866,22 +1018,11 @@ public class NotificationUsageStats {
|
||||
mWriteHandler.sendMessage(mWriteHandler.obtainMessage(MSG_DISMISS, notification));
|
||||
}
|
||||
|
||||
private JSONArray JsonPostFrequencies(DumpFilter filter) throws JSONException {
|
||||
private JSONArray jsonPostFrequencies(DumpFilter filter) throws JSONException {
|
||||
JSONArray frequencies = new JSONArray();
|
||||
SQLiteDatabase db = mHelper.getReadableDatabase();
|
||||
long midnight = getMidnightMs();
|
||||
String q = "SELECT " +
|
||||
COL_EVENT_USER_ID + ", " +
|
||||
COL_PKG + ", " +
|
||||
// Bucket by day by looking at 'floor((midnight - eventTimeMs) / dayMs)'
|
||||
"CAST(((" + midnight + " - " + COL_EVENT_TIME + ") / " + DAY_MS + ") AS int) " +
|
||||
"AS day, " +
|
||||
"COUNT(*) AS cnt " +
|
||||
"FROM " + TAB_LOG + " " +
|
||||
"WHERE " +
|
||||
COL_EVENT_TYPE + "=" + EVENT_TYPE_POST +
|
||||
" AND " + COL_EVENT_TIME + " > " + filter.since +
|
||||
" GROUP BY " + COL_EVENT_USER_ID + ", day, " + COL_PKG;
|
||||
String q = String.format(STATS_QUERY, midnight, filter.since);
|
||||
Cursor cursor = db.rawQuery(q, null);
|
||||
try {
|
||||
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
|
||||
@@ -890,11 +1031,17 @@ public class NotificationUsageStats {
|
||||
if (filter != null && !filter.matches(pkg)) continue;
|
||||
int day = cursor.getInt(2);
|
||||
int count = cursor.getInt(3);
|
||||
int muted = cursor.getInt(4);
|
||||
int noisy = cursor.getInt(5);
|
||||
int demoted = cursor.getInt(6);
|
||||
JSONObject row = new JSONObject();
|
||||
row.put("user_id", userId);
|
||||
row.put("package", pkg);
|
||||
row.put("day", day);
|
||||
row.put("count", count);
|
||||
row.put("noisy", noisy);
|
||||
row.put("muted", muted);
|
||||
row.put("demoted", demoted);
|
||||
frequencies.put(row);
|
||||
}
|
||||
} finally {
|
||||
@@ -906,17 +1053,7 @@ public class NotificationUsageStats {
|
||||
public void printPostFrequencies(PrintWriter pw, String indent, DumpFilter filter) {
|
||||
SQLiteDatabase db = mHelper.getReadableDatabase();
|
||||
long midnight = getMidnightMs();
|
||||
String q = "SELECT " +
|
||||
COL_EVENT_USER_ID + ", " +
|
||||
COL_PKG + ", " +
|
||||
// Bucket by day by looking at 'floor((midnight - eventTimeMs) / dayMs)'
|
||||
"CAST(((" + midnight + " - " + COL_EVENT_TIME + ") / " + DAY_MS + ") AS int) " +
|
||||
"AS day, " +
|
||||
"COUNT(*) AS cnt " +
|
||||
"FROM " + TAB_LOG + " " +
|
||||
"WHERE " +
|
||||
COL_EVENT_TYPE + "=" + EVENT_TYPE_POST + " " +
|
||||
"GROUP BY " + COL_EVENT_USER_ID + ", day, " + COL_PKG;
|
||||
String q = String.format(STATS_QUERY, midnight, filter.since);
|
||||
Cursor cursor = db.rawQuery(q, null);
|
||||
try {
|
||||
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
|
||||
@@ -925,8 +1062,12 @@ public class NotificationUsageStats {
|
||||
if (filter != null && !filter.matches(pkg)) continue;
|
||||
int day = cursor.getInt(2);
|
||||
int count = cursor.getInt(3);
|
||||
int muted = cursor.getInt(4);
|
||||
int noisy = cursor.getInt(5);
|
||||
int demoted = cursor.getInt(6);
|
||||
pw.println(indent + "post_frequency{user_id=" + userId + ",pkg=" + pkg +
|
||||
",day=" + day + ",count=" + count + "}");
|
||||
",day=" + day + ",count=" + count + ",muted=" + muted + "/" + noisy +
|
||||
",demoted=" + demoted + "}");
|
||||
}
|
||||
} finally {
|
||||
cursor.close();
|
||||
@@ -985,7 +1126,18 @@ public class NotificationUsageStats {
|
||||
}
|
||||
outCv.put(COL_WHEN_MS, r.sbn.getPostTime());
|
||||
outCv.put(COL_FLAGS, r.getNotification().flags);
|
||||
outCv.put(COL_PRIORITY, r.getNotification().priority);
|
||||
final int before = r.stats.requestedImportance;
|
||||
final int after = r.getImportance();
|
||||
final boolean noisy = r.stats.isNoisy;
|
||||
outCv.put(COL_IMPORTANCE_REQ, before);
|
||||
outCv.put(COL_IMPORTANCE_FINAL, after);
|
||||
outCv.put(COL_DEMOTED, after < before ? 1 : 0);
|
||||
outCv.put(COL_NOISY, noisy);
|
||||
if (noisy && after < IMPORTANCE_HIGH) {
|
||||
outCv.put(COL_MUTED, 1);
|
||||
} else {
|
||||
outCv.put(COL_MUTED, 0);
|
||||
}
|
||||
if (r.getNotification().category != null) {
|
||||
outCv.put(COL_CATEGORY, r.getNotification().category);
|
||||
}
|
||||
@@ -1008,7 +1160,9 @@ public class NotificationUsageStats {
|
||||
public JSONObject dumpJson(DumpFilter filter) {
|
||||
JSONObject dump = new JSONObject();
|
||||
try {
|
||||
dump.put("post_frequency", JsonPostFrequencies(filter));
|
||||
dump.put("post_frequency", jsonPostFrequencies(filter));
|
||||
dump.put("since", filter.since);
|
||||
dump.put("now", System.currentTimeMillis());
|
||||
} catch (JSONException e) {
|
||||
// pass
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user