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

Commit 0f7c0570 authored by Brian Carlstrom's avatar Brian Carlstrom Committed by Gerrit Code Review
Browse files

Merge "Minor cleanup of UsageStatsService"

parents 7e411f74 393fbe71
Loading
Loading
Loading
Loading
+132 −130
Original line number Diff line number Diff line
@@ -85,7 +85,7 @@ public final class UsageStatsService extends IUsageStats.Stub {

    private static final String FILE_HISTORY = FILE_PREFIX + "history.xml";

    private static final int FILE_WRITE_INTERVAL = 30*60*1000; //ms
    private static final int FILE_WRITE_INTERVAL = (localLOGV) ? 0 : 30*60*1000; // 30m in ms

    private static final int MAX_NUM_FILES = 5;

@@ -97,20 +97,22 @@ public final class UsageStatsService extends IUsageStats.Stub {
    static IUsageStats sService;
    private Context mContext;
    // structure used to maintain statistics since the last checkin.
    final private ArrayMap<String, PkgUsageStatsExtended> mStats;
    final private ArrayMap<String, PkgUsageStatsExtended> mStats
            = new ArrayMap<String, PkgUsageStatsExtended>();

    // Maintains the last time any component was resumed, for all time.
    final private ArrayMap<String, ArrayMap<String, Long>> mLastResumeTimes;
    final private ArrayMap<String, ArrayMap<String, Long>> mLastResumeTimes
            = new ArrayMap<String, ArrayMap<String, Long>>();

    // To remove last-resume time stats when a pacakge is removed.
    private PackageMonitor mPackageMonitor;

    // Lock to update package stats. Methods suffixed by SLOCK should invoked with
    // this lock held
    final Object mStatsLock;
    final Object mStatsLock = new Object();
    // Lock to write to file. Methods suffixed by FLOCK should invoked with
    // this lock held.
    final Object mFileLock;
    final Object mFileLock = new Object();
    // Order of locks is mFileLock followed by mStatsLock to avoid deadlocks
    private String mLastResumedPkg;
    private String mLastResumedComp;
@@ -120,52 +122,53 @@ public final class UsageStatsService extends IUsageStats.Stub {
    private String mFileLeaf;
    private File mDir;

    private Calendar mCal; // guarded by itself
    private final Calendar mCal // guarded by itself
            = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));

    private final AtomicInteger mLastWriteDay = new AtomicInteger(-1);
    private final AtomicLong mLastWriteElapsedTime = new AtomicLong(0);
    private final AtomicBoolean mUnforcedDiskWriteRunning = new AtomicBoolean(false);

    static class TimeStats {
        int count;
        int[] times = new int[NUM_LAUNCH_TIME_BINS];
        int mCount;
        final int[] mTimes = new int[NUM_LAUNCH_TIME_BINS];

        TimeStats() {
        }

        void incCount() {
            count++;
            mCount++;
        }

        void add(int val) {
            final int[] bins = LAUNCH_TIME_BINS;
            for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
                if (val < bins[i]) {
                    times[i]++;
                    mTimes[i]++;
                    return;
                }
            }
            times[NUM_LAUNCH_TIME_BINS-1]++;
            mTimes[NUM_LAUNCH_TIME_BINS-1]++;
        }

        TimeStats(Parcel in) {
            count = in.readInt();
            final int[] localTimes = times;
            mCount = in.readInt();
            final int[] localTimes = mTimes;
            for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
                localTimes[i] = in.readInt();
            }
        }

        void writeToParcel(Parcel out) {
            out.writeInt(count);
            final int[] localTimes = times;
            out.writeInt(mCount);
            final int[] localTimes = mTimes;
            for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
                out.writeInt(localTimes[i]);
            }
        }
    }

    private class PkgUsageStatsExtended {
    static class PkgUsageStatsExtended {
        final ArrayMap<String, TimeStats> mLaunchTimes
                = new ArrayMap<String, TimeStats>();
        final ArrayMap<String, TimeStats> mFullyDrawnTimes
@@ -272,26 +275,19 @@ public final class UsageStatsService extends IUsageStats.Stub {
    }

    UsageStatsService(String dir) {
        mStats = new ArrayMap<String, PkgUsageStatsExtended>();
        mLastResumeTimes = new ArrayMap<String, ArrayMap<String, Long>>();
        mStatsLock = new Object();
        mFileLock = new Object();
        if (localLOGV) Slog.v(TAG, "UsageStatsService: " + dir);
        mDir = new File(dir);
        mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
        
        mDir.mkdir();

        // Remove any old usage files from previous versions.
        // Remove any old /data/system/usagestats.* files from previous versions.
        File parentDir = mDir.getParentFile();
        String fList[] = parentDir.list();
        if (fList != null) {
        String files[] = parentDir.list();
        if (files != null) {
            String prefix = mDir.getName() + ".";
            int i = fList.length;
            while (i > 0) {
                i--;
                if (fList[i].startsWith(prefix)) {
                    Slog.i(TAG, "Deleting old usage file: " + fList[i]);
                    (new File(parentDir, fList[i])).delete();
            for (String file : files) {
                if (file.startsWith(prefix)) {
                    Slog.i(TAG, "Deleting old usage file: " + file);
                    (new File(parentDir, file)).delete();
                }
            }
        }
@@ -312,11 +308,11 @@ public final class UsageStatsService extends IUsageStats.Stub {
     */
    private String getCurrentDateStr(String prefix) {
        StringBuilder sb = new StringBuilder();
        synchronized (mCal) {
            mCal.setTimeInMillis(System.currentTimeMillis());
        if (prefix != null) {
            sb.append(prefix);
        }
        synchronized (mCal) {
            mCal.setTimeInMillis(System.currentTimeMillis());
            sb.append(mCal.get(Calendar.YEAR));
            int mm = mCal.get(Calendar.MONTH) - Calendar.JANUARY +1;
            if (mm < 10) {
@@ -334,12 +330,15 @@ public final class UsageStatsService extends IUsageStats.Stub {

    private Parcel getParcelForFile(File file) throws IOException {
        FileInputStream stream = new FileInputStream(file);
        try {
            byte[] raw = readFully(stream);
            Parcel in = Parcel.obtain();
            in.unmarshall(raw, 0, raw.length);
            in.setDataPosition(0);
        stream.close();
            return in;
        } finally {
            stream.close();
        }
    }

    private void readStatsFromFile() {
@@ -362,8 +361,9 @@ public final class UsageStatsService extends IUsageStats.Stub {
    private void readStatsFLOCK(File file) throws IOException {
        Parcel in = getParcelForFile(file);
        int vers = in.readInt();
        if (vers != VERSION) {
            Slog.w(TAG, "Usage stats version changed; dropping");
        if (vers != VERSION) {  // vers will be 0 if the parcel file was empty
            Slog.w(TAG, "Usage stats version of " + file + " changed from " + vers + " to "
                   + VERSION + "; dropping");
            return;
        }
        int N = in.readInt();
@@ -384,12 +384,12 @@ public final class UsageStatsService extends IUsageStats.Stub {
    private void readHistoryStatsFromFile() {
        synchronized (mFileLock) {
            if (mHistoryFile.getBaseFile().exists()) {
                readHistoryStatsFLOCK(mHistoryFile);
                readHistoryStatsFLOCK();
            }
        }
    }

    private void readHistoryStatsFLOCK(AtomicFile file) {
    private void readHistoryStatsFLOCK() {
        FileInputStream fis = null;
        try {
            fis = mHistoryFile.openRead();
@@ -477,7 +477,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
        // Get all usage stats output files
        ArrayList<String> fileList = getUsageStatsFileListFLOCK();
        if (fileList == null) {
            // Strange but we dont have to delete any thing
            // Empty /data/system/usagestats/ so we don't have anything to delete
            return;
        }
        int count = fileList.size();
@@ -577,8 +577,8 @@ public final class UsageStatsService extends IUsageStats.Stub {
                }

                if (dayChanged || forceWriteHistoryStats) {
                    // Write history stats daily, or when forced (due to shutdown).
                    writeHistoryStatsFLOCK(mHistoryFile);
                    // Write history stats daily or when forced (due to shutdown) or when debugging.
                    writeHistoryStatsFLOCK();
                }

                // Delete the backup file
@@ -640,10 +640,10 @@ public final class UsageStatsService extends IUsageStats.Stub {
        }
    }

    private void writeHistoryStatsFLOCK(AtomicFile historyFile) {
    private void writeHistoryStatsFLOCK() {
        FileOutputStream fos = null;
        try {
            fos = historyFile.startWrite();
            fos = mHistoryFile.startWrite();
            XmlSerializer out = new FastXmlSerializer();
            out.setOutput(fos, "utf-8");
            out.startDocument(null, true);
@@ -666,11 +666,11 @@ public final class UsageStatsService extends IUsageStats.Stub {
            out.endTag(null, "usage-history");
            out.endDocument();

            historyFile.finishWrite(fos);
            mHistoryFile.finishWrite(fos);
        } catch (IOException e) {
            Slog.w(TAG,"Error writing history stats" + e);
            if (fos != null) {
                historyFile.failWrite(fos);
                mHistoryFile.failWrite(fos);
            }
        }
    }
@@ -714,6 +714,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
        return sService;
    }

    @Override
    public void noteResumeComponent(ComponentName componentName) {
        enforceCallingPermission();
        String pkgName;
@@ -764,6 +765,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
        }
    }

    @Override
    public void notePauseComponent(ComponentName componentName) {
        enforceCallingPermission();

@@ -795,6 +797,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
        writeStatsToFile(false, false);
    }

    @Override
    public void noteLaunchTime(ComponentName componentName, int millis) {
        enforceCallingPermission();
        String pkgName;
@@ -841,6 +844,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
                Binder.getCallingPid(), Binder.getCallingUid(), null);
    }

    @Override
    public PkgUsageStats getPkgUsageStats(ComponentName componentName) {
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.PACKAGE_USAGE_STATS, null);
@@ -861,6 +865,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
        }
    }

    @Override
    public PkgUsageStats[] getAllPkgUsageStats() {
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.PACKAGE_USAGE_STATS, null);
@@ -887,7 +892,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
        }
    }

    static byte[] readFully(FileInputStream stream) throws java.io.IOException {
    static byte[] readFully(FileInputStream stream) throws IOException {
        int pos = 0;
        int avail = stream.available();
        byte[] data = new byte[avail];
@@ -934,9 +939,6 @@ public final class UsageStatsService extends IUsageStats.Stub {
                    // Delete old file after collecting info only for checkin requests
                    dFile.delete();
                }
            } catch (FileNotFoundException e) {
                Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : " + file);
                return;
            } catch (IOException e) {
                Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : "+file);
            }
@@ -992,10 +994,10 @@ public final class UsageStatsService extends IUsageStats.Stub {
                    sb.append(activity);
                    TimeStats times = pus.mLaunchTimes.valueAt(i);
                    sb.append(',');
                    sb.append(times.count);
                    sb.append(times.mCount);
                    for (int j=0; j<NUM_LAUNCH_TIME_BINS; j++) {
                        sb.append(",");
                        sb.append(times.times[j]);
                        sb.append(times.mTimes[j]);
                    }
                    sb.append('\n');
                }
@@ -1007,7 +1009,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
                    TimeStats times = pus.mFullyDrawnTimes.valueAt(i);
                    for (int j=0; j<NUM_LAUNCH_TIME_BINS; j++) {
                        sb.append(",");
                        sb.append(times.times[j]);
                        sb.append(times.mTimes[j]);
                    }
                    sb.append('\n');
                }
@@ -1027,26 +1029,26 @@ public final class UsageStatsService extends IUsageStats.Stub {
                    sb.append(pus.mLaunchTimes.keyAt(i));
                    TimeStats times = pus.mLaunchTimes.valueAt(i);
                    sb.append(": ");
                    sb.append(times.count);
                    sb.append(times.mCount);
                    sb.append(" starts");
                    int lastBin = 0;
                    for (int j=0; j<NUM_LAUNCH_TIME_BINS-1; j++) {
                        if (times.times[j] != 0) {
                        if (times.mTimes[j] != 0) {
                            sb.append(", ");
                            sb.append(lastBin);
                            sb.append('-');
                            sb.append(LAUNCH_TIME_BINS[j]);
                            sb.append("ms=");
                            sb.append(times.times[j]);
                            sb.append(times.mTimes[j]);
                        }
                        lastBin = LAUNCH_TIME_BINS[j];
                    }
                    if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) {
                    if (times.mTimes[NUM_LAUNCH_TIME_BINS-1] != 0) {
                        sb.append(", ");
                        sb.append(">=");
                        sb.append(lastBin);
                        sb.append("ms=");
                        sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]);
                        sb.append(times.mTimes[NUM_LAUNCH_TIME_BINS-1]);
                    }
                    sb.append('\n');
                }
@@ -1059,7 +1061,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
                    boolean needComma = false;
                    int lastBin = 0;
                    for (int j=0; j<NUM_LAUNCH_TIME_BINS-1; j++) {
                        if (times.times[j] != 0) {
                        if (times.mTimes[j] != 0) {
                            if (needComma) {
                                sb.append(", ");
                            } else {
@@ -1069,18 +1071,18 @@ public final class UsageStatsService extends IUsageStats.Stub {
                            sb.append('-');
                            sb.append(LAUNCH_TIME_BINS[j]);
                            sb.append("ms=");
                            sb.append(times.times[j]);
                            sb.append(times.mTimes[j]);
                        }
                        lastBin = LAUNCH_TIME_BINS[j];
                    }
                    if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) {
                    if (times.mTimes[NUM_LAUNCH_TIME_BINS-1] != 0) {
                        if (needComma) {
                            sb.append(", ");
                        }
                        sb.append(">=");
                        sb.append(lastBin);
                        sb.append("ms=");
                        sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]);
                        sb.append(times.mTimes[NUM_LAUNCH_TIME_BINS-1]);
                    }
                    sb.append('\n');
                }
@@ -1126,10 +1128,10 @@ public final class UsageStatsService extends IUsageStats.Stub {
        return null;
    }

    @Override
    /*
     * The data persisted to file is parsed and the stats are computed.
     */
    @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (mContext.checkCallingPermission(android.Manifest.permission.DUMP)
                != PackageManager.PERMISSION_GRANTED) {
@@ -1146,7 +1148,7 @@ public final class UsageStatsService extends IUsageStats.Stub {

        // Make sure the current stats are written to the file.  This
        // doesn't need to be done if we are deleting files after printing,
        // since it that case we won't print the current stats.
        // since in that case we won't print the current stats.
        if (!deleteAfterPrint) {
            writeStatsToFile(true, false);
        }
@@ -1156,10 +1158,10 @@ public final class UsageStatsService extends IUsageStats.Stub {
            if (!"*".equals(rawPackages)) {
                // A * is a wildcard to show all packages.
                String[] names = rawPackages.split(",");
                for (String n : names) {
                    if (packages == null) {
                if (names.length != 0) {
                    packages = new HashSet<String>();
                }
                for (String n : names) {
                    packages.add(n);
                }
            }