Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4abc249 authored by Chris Wren's avatar Chris Wren Committed by Android Git Automerger
Browse files

am 289e9ebf: am b9b021d0: am 4c0c6739: am 32c4802a: Merge "provide a cleaner...

am 289e9ebf: am b9b021d0: am 4c0c6739: am 32c4802a: Merge "provide a cleaner notification dump" into mnc-dev

* commit '289e9ebf':
  provide a cleaner notification dump
parents 7516e284 289e9ebf
Loading
Loading
Loading
Loading
+80 −17
Original line number Diff line number Diff line
@@ -112,6 +112,9 @@ import com.android.server.statusbar.StatusBarManagerInternal;

import libcore.io.IoUtils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -1663,7 +1666,12 @@ public class NotificationManagerService extends SystemService {
                return;
            }

            dumpImpl(pw, DumpFilter.parseFromArguments(args));
            final DumpFilter filter = DumpFilter.parseFromArguments(args);
            if (filter != null && filter.stats) {
                dumpJson(pw, filter);
            } else {
                dumpImpl(pw, filter);
            }
        }

        @Override
@@ -1799,6 +1807,32 @@ public class NotificationManagerService extends SystemService {
            return "callState";
        }
        return null;
    };

    private void dumpJson(PrintWriter pw, DumpFilter filter) {
        JSONObject dump = new JSONObject();
        try {
            dump.put("service", "Notification Manager");
            JSONArray bans = new JSONArray();
            try {
                ArrayMap<Integer, ArrayList<String>> packageBans = getPackageBans(filter);
                for (Integer userId : packageBans.keySet()) {
                    for (String packageName : packageBans.get(userId)) {
                        JSONObject ban = new JSONObject();
                        ban.put("userId", userId);
                        ban.put("packageName", packageName);
                        bans.put(ban);
                    }
                }
            } catch (NameNotFoundException e) {
                // pass
            }
            dump.put("bans", bans);
            dump.put("stats", mUsageStats.dumpJson(filter));
        } catch (JSONException e) {
            e.printStackTrace();
        }
        pw.println(dump);
    }

    void dumpImpl(PrintWriter pw, DumpFilter filter) {
@@ -1920,24 +1954,42 @@ public class NotificationManagerService extends SystemService {

            try {
                pw.println("\n  Banned Packages:");
                ArrayMap<Integer, ArrayList<String>> packageBans = getPackageBans(filter);
                for (Integer userId : packageBans.keySet()) {
                    for (String packageName : packageBans.get(userId)) {
                        pw.println("    " + userId + ": " + packageName);
                    }
                }
            } catch (NameNotFoundException e) {
                // pass
            }
        }
    }

    private ArrayMap<Integer, ArrayList<String>> getPackageBans(DumpFilter filter)
            throws NameNotFoundException {
        ArrayMap<Integer, ArrayList<String>> packageBans = new ArrayMap<>();
        ArrayList<String> packageNames = new ArrayList<>();
        for (UserInfo user : UserManager.get(getContext()).getUsers()) {
            final int userId = user.getUserHandle().getIdentifier();
                    pw.println("    UserId " + userId);
            final PackageManager packageManager = getContext().getPackageManager();
            List<PackageInfo> packages = packageManager.getInstalledPackages(0, userId);
            final int packageCount = packages.size();
            for (int p = 0; p < packageCount; p++) {
                final String packageName = packages.get(p).packageName;
                if (filter == null || filter.matches(packageName)) {
                    final int uid = packageManager.getPackageUid(packageName, userId);
                    if (!checkNotificationOp(packageName, uid)) {
                            pw.println("       " + packageName);
                        packageNames.add(packageName);
                    }
                }
            }
            } catch (NameNotFoundException e) {
                // pass
            if (!packageNames.isEmpty()) {
                packageBans.put(userId, packageNames);
                packageNames = new ArrayList<>();
            }
        }
        return packageBans;
    }

    /**
@@ -3449,6 +3501,9 @@ public class NotificationManagerService extends SystemService {
    public static final class DumpFilter {
        public String pkgFilter;
        public boolean zen;
        public long since;
        public boolean stats;
        private boolean all;

        public static DumpFilter parseFromArguments(String[] args) {
            if (args != null && args.length == 2 && "p".equals(args[0])
@@ -3460,27 +3515,35 @@ public class NotificationManagerService extends SystemService {
            if (args != null && args.length == 1 && "zen".equals(args[0])) {
                final DumpFilter filter = new DumpFilter();
                filter.zen = true;
                filter.all = true;
                return filter;
            }
            if (args != null && args.length >= 1 && "--stats".equals(args[0])) {
                final DumpFilter filter = new DumpFilter();
                filter.stats = true;
                filter.since = args.length == 2 ? Long.valueOf(args[1]) : 0;
                filter.all = true;
                return filter;
            }
            return null;
        }

        public boolean matches(StatusBarNotification sbn) {
            return zen ? true : sbn != null
            return all ? true : sbn != null
                    && (matches(sbn.getPackageName()) || matches(sbn.getOpPkg()));
        }

        public boolean matches(ComponentName component) {
            return zen ? true : component != null && matches(component.getPackageName());
            return all ? true : component != null && matches(component.getPackageName());
        }

        public boolean matches(String pkg) {
            return zen ? true : pkg != null && pkg.toLowerCase().contains(pkgFilter);
            return all ? true : pkg != null && pkg.toLowerCase().contains(pkgFilter);
        }

        @Override
        public String toString() {
            return zen ? "zen" : ('\'' + pkgFilter + '\'');
            return stats ? "stats" : zen ? "zen" : ('\'' + pkgFilter + '\'');
        }
    }

+131 −4
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
@@ -32,8 +31,14 @@ import android.util.Log;
import com.android.internal.logging.MetricsLogger;
import com.android.server.notification.NotificationManagerService.DumpFilter;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;

@@ -220,6 +225,31 @@ public class NotificationUsageStats {
        return result;
    }

    public synchronized JSONObject dumpJson(DumpFilter filter) {
        JSONObject dump = new JSONObject();
        if (ENABLE_AGGREGATED_IN_MEMORY_STATS) {
            try {
                JSONArray aggregatedStats = new JSONArray();
                for (AggregatedStats as : mStats.values()) {
                    if (filter != null && !filter.matches(as.key))
                        continue;
                    aggregatedStats.put(as.dumpJson());
                }
                dump.put("current", aggregatedStats);
            } catch (JSONException e) {
                // pass
            }
        }
        if (ENABLE_SQLITE_LOG) {
            try {
                dump.put("historical", mSQLiteLog.dumpJson(filter));
            } catch (JSONException e) {
                // pass
            }
        }
        return dump;
    }

    public synchronized void dump(PrintWriter pw, String indent, DumpFilter filter) {
        if (ENABLE_AGGREGATED_IN_MEMORY_STATS) {
            for (AggregatedStats as : mStats.values()) {
@@ -250,6 +280,7 @@ public class NotificationUsageStats {

        private final Context mContext;
        public final String key;
        private final long mCreated;
        private AggregatedStats mPrevious;

        // ---- Updated as the respective events occur.
@@ -285,6 +316,7 @@ public class NotificationUsageStats {
        public AggregatedStats(Context context, String key) {
            this.key = key;
            mContext = context;
            mCreated = SystemClock.elapsedRealtime();
        }

        public void countApiUse(NotificationRecord record) {
@@ -450,6 +482,47 @@ public class NotificationUsageStats {
                    indent + "  numBlocked=" + numBlocked + ",\n" +
                    indent + "}";
        }

        public JSONObject dumpJson() throws JSONException {
            JSONObject dump = new JSONObject();
            dump.put("key", key);
            dump.put("duration", SystemClock.elapsedRealtime() - mCreated);
            maybePut(dump, "numPostedByApp", numPostedByApp);
            maybePut(dump, "numUpdatedByApp", numUpdatedByApp);
            maybePut(dump, "numRemovedByApp", numRemovedByApp);
            maybePut(dump, "numPeopleCacheHit", numPeopleCacheHit);
            maybePut(dump, "numPeopleCacheMiss", numPeopleCacheMiss);
            maybePut(dump, "numWithStaredPeople", numWithStaredPeople);
            maybePut(dump, "numWithValidPeople", numWithValidPeople);
            maybePut(dump, "numBlocked", numBlocked);
            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);
            maybePut(dump, "numForegroundService", numForegroundService);
            maybePut(dump, "numOngoing", numOngoing);
            maybePut(dump, "numAutoCancel", numAutoCancel);
            maybePut(dump, "numWithLargeIcon", numWithLargeIcon);
            maybePut(dump, "numWithInbox", numWithInbox);
            maybePut(dump, "numWithMediaSession", numWithMediaSession);
            maybePut(dump, "numWithTitle", numWithTitle);
            maybePut(dump, "numWithText", numWithText);
            maybePut(dump, "numWithSubText", numWithSubText);
            maybePut(dump, "numWithInfoText", numWithInfoText);
            return dump;
        }

        private void maybePut(JSONObject dump, String name, int value) throws JSONException {
            if (value > 0) {
                dump.put(name, value);
            }
        }
    }

    /**
@@ -780,14 +853,51 @@ public class NotificationUsageStats {
            mWriteHandler.sendMessage(mWriteHandler.obtainMessage(MSG_DISMISS, notification));
        }

        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;
            Cursor cursor = db.rawQuery(q, null);
            try {
                for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
                    int userId = cursor.getInt(0);
                    String pkg = cursor.getString(1);
                    if (filter != null && !filter.matches(pkg)) continue;
                    int day = cursor.getInt(2);
                    int count = cursor.getInt(3);
                    JSONObject row = new JSONObject();
                    row.put("user_id", userId);
                    row.put("package", pkg);
                    row.put("day", day);
                    row.put("count", count);
                    frequencies.put(row);
                }
            } finally {
                cursor.close();
            }
            return frequencies;
        }

        public void printPostFrequencies(PrintWriter pw, String indent, DumpFilter filter) {
            SQLiteDatabase db = mHelper.getReadableDatabase();
            long nowMs = System.currentTimeMillis();
            long midnight = getMidnightMs();
            String q = "SELECT " +
                    COL_EVENT_USER_ID + ", " +
                    COL_PKG + ", " +
                    // Bucket by day by looking at 'floor((nowMs - eventTimeMs) / dayMs)'
                    "CAST(((" + nowMs + " - " + COL_EVENT_TIME + ") / " + DAY_MS + ") AS int) " +
                    // 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 + " " +
@@ -810,6 +920,13 @@ public class NotificationUsageStats {
            }
        }

        private long getMidnightMs() {
            GregorianCalendar midnight = new GregorianCalendar();
            midnight.set(midnight.get(Calendar.YEAR), midnight.get(Calendar.MONTH),
                    midnight.get(Calendar.DATE), 23, 59, 59);
            return midnight.getTimeInMillis();
        }

        private void writeEvent(long eventTimeMs, int eventType, NotificationRecord r) {
            ContentValues cv = new ContentValues();
            cv.put(COL_EVENT_USER_ID, r.sbn.getUser().getIdentifier());
@@ -874,5 +991,15 @@ public class NotificationUsageStats {
        public void dump(PrintWriter pw, String indent, DumpFilter filter) {
            printPostFrequencies(pw, indent, filter);
        }

        public JSONObject dumpJson(DumpFilter filter) {
            JSONObject dump = new JSONObject();
            try {
                dump.put("post_frequency", JsonPostFrequencies(filter));
            } catch (JSONException e) {
                // pass
            }
            return dump;
        }
    }
}