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

Commit 5bef1bed authored by Varun Shah's avatar Varun Shah
Browse files

Add a dumpsys for UsageStatsDatabase info.

'dumpsys usagestats file [user] [interval] [filename]' added.
When all options are specified, this command dumps all usage stats
information stored in the specified filename.
If the filename is not specified, information of all files for the
specified interval is dumped.
If the interval is not specified, information of all files in all of the
intervals for the specified user is dumped.
If the user is not specified, information for all users is dumped.

Also added 'dumpsys usagestats database-info [user]'. This simply
connects the existing dump in UsageStatsDatabase.
If the user is not specified, information for all users is dumped.

Bug: 131923219
Test: various combinations of the dumpsys command added
Change-Id: Id2c2b20e07f9ab0e1a577e45fba199d565532b7b
parent 50e31711
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -1280,4 +1280,16 @@ public class UsageStatsDatabase {
            pw.decreaseIndent();
        }
    }

    IntervalStats readIntervalStatsForFile(int interval, long fileName) {
        synchronized (mLock) {
            final IntervalStats stats = new IntervalStats();
            try {
                readLocked(mSortedStatFiles[interval].get(fileName, null), stats);
                return stats;
            } catch (Exception e) {
                return null;
            }
        }
    }
}
+56 −0
Original line number Diff line number Diff line
@@ -774,6 +774,62 @@ public class UsageStatsService extends SystemService implements
                            mAppTimeLimit.dump(remainingArgs, pw);
                        }
                        return;
                    } else if ("file".equals(arg)) {
                        final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
                        if (i + 1 >= args.length) {
                            // dump everything for all users
                            final int numUsers = mUserState.size();
                            for (int user = 0; user < numUsers; user++) {
                                ipw.println("user=" + mUserState.keyAt(user));
                                ipw.increaseIndent();
                                mUserState.valueAt(user).dumpFile(ipw, null);
                                ipw.decreaseIndent();
                            }
                        } else {
                            final int user;
                            try {
                                user = Integer.valueOf(args[i + 1]);
                            } catch (NumberFormatException nfe) {
                                ipw.println("invalid user specified.");
                                return;
                            }
                            if (mUserState.indexOfKey(user) < 0) {
                                ipw.println("the specified user does not exist.");
                                return;
                            }
                            final String[] remainingArgs = Arrays.copyOfRange(
                                    args, i + 2, args.length);
                            // dump everything for the specified user
                            mUserState.get(user).dumpFile(ipw, remainingArgs);
                        }
                        return;
                    } else if ("database-info".equals(arg)) {
                        final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
                        if (i + 1 >= args.length) {
                            // dump info for all users
                            final int numUsers = mUserState.size();
                            for (int user = 0; user < numUsers; user++) {
                                ipw.println("user=" + mUserState.keyAt(user));
                                ipw.increaseIndent();
                                mUserState.valueAt(user).dumpDatabaseInfo(ipw);
                                ipw.decreaseIndent();
                            }
                        } else {
                            final int user;
                            try {
                                user = Integer.valueOf(args[i + 1]);
                            } catch (NumberFormatException nfe) {
                                ipw.println("invalid user specified.");
                                return;
                            }
                            if (mUserState.indexOfKey(user) < 0) {
                                ipw.println("the specified user does not exist.");
                                return;
                            }
                            // dump info only for the specified user
                            mUserState.get(user).dumpDatabaseInfo(ipw);
                        }
                        return;
                    } else if (arg != null && !arg.startsWith("-")) {
                        // Anything else that doesn't start with '-' is a pkg to filter
                        pkg = arg;
+88 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import static android.app.usage.UsageStatsManager.INTERVAL_YEARLY;
import android.app.usage.ConfigurationStats;
import android.app.usage.EventList;
import android.app.usage.EventStats;
import android.app.usage.TimeSparseArray;
import android.app.usage.UsageEvents;
import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageStats;
@@ -38,6 +39,7 @@ import android.os.SystemClock;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.SparseIntArray;

@@ -665,6 +667,77 @@ class UserUsageStatsService {
        mDatabase.dump(pw, compact);
    }

    void dumpDatabaseInfo(IndentingPrintWriter ipw) {
        mDatabase.dump(ipw, false);
    }

    void dumpFile(IndentingPrintWriter ipw, String[] args) {
        if (args == null || args.length == 0) {
            // dump all files for every interval for specified user
            final int numIntervals = mDatabase.mSortedStatFiles.length;
            for (int interval = 0; interval < numIntervals; interval++) {
                ipw.println("interval=" + intervalToString(interval));
                ipw.increaseIndent();
                dumpFileDetailsForInterval(ipw, interval);
                ipw.decreaseIndent();
            }
        } else {
            final int interval;
            try {
                final int intervalValue = stringToInterval(args[0]);
                if (intervalValue == -1) {
                    interval = Integer.valueOf(args[0]);
                } else {
                    interval = intervalValue;
                }
            } catch (NumberFormatException nfe) {
                ipw.println("invalid interval specified.");
                return;
            }
            if (interval < 0 || interval >= mDatabase.mSortedStatFiles.length) {
                ipw.println("the specified interval does not exist.");
                return;
            }
            if (args.length == 1) {
                // dump all files in the specified interval
                dumpFileDetailsForInterval(ipw, interval);
            } else {
                // dump details only for the specified filename
                final long filename;
                try {
                    filename = Long.valueOf(args[1]);
                } catch (NumberFormatException nfe) {
                    ipw.println("invalid filename specified.");
                    return;
                }
                final IntervalStats stats = mDatabase.readIntervalStatsForFile(interval, filename);
                if (stats == null) {
                    ipw.println("the specified filename does not exist.");
                    return;
                }
                dumpFileDetails(ipw, stats, Long.valueOf(args[1]));
            }
        }
    }

    private void dumpFileDetailsForInterval(IndentingPrintWriter ipw, int interval) {
        final TimeSparseArray<AtomicFile> files = mDatabase.mSortedStatFiles[interval];
        final int numFiles = files.size();
        for (int i = 0; i < numFiles; i++) {
            final long filename = files.keyAt(i);
            final IntervalStats stats = mDatabase.readIntervalStatsForFile(interval, filename);
            dumpFileDetails(ipw, stats, filename);
            ipw.println();
        }
    }

    private void dumpFileDetails(IndentingPrintWriter ipw, IntervalStats stats, long filename) {
        ipw.println("file=" + filename);
        ipw.increaseIndent();
        printIntervalStats(ipw, stats, false, false, null);
        ipw.decreaseIndent();
    }

    static String formatDateTime(long dateTime, boolean pretty) {
        if (pretty) {
            return "\"" + sDateFormat.format(dateTime)+ "\"";
@@ -908,6 +981,21 @@ class UserUsageStatsService {
        }
    }

    private static int stringToInterval(String interval) {
        switch (interval.toLowerCase()) {
            case "daily":
                return INTERVAL_DAILY;
            case "weekly":
                return INTERVAL_WEEKLY;
            case "monthly":
                return INTERVAL_MONTHLY;
            case "yearly":
                return INTERVAL_YEARLY;
            default:
                return -1;
        }
    }

    private static String eventToString(int eventType) {
        switch (eventType) {
            case Event.NONE: