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

Commit e3cceef7 authored by Brian Carlstrom's avatar Brian Carlstrom Committed by Android Git Automerger
Browse files

am 0f7c0570: Merge "Minor cleanup of UsageStatsService"

* commit '0f7c0570':
  Minor cleanup of UsageStatsService
parents 74ec5808 0f7c0570
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);
                }
            }