am e3cceef7: am 0f7c0570: Merge "Minor cleanup of UsageStatsService"

* commit 'e3cceef7ececdac1c6df65d3f7a1557ac3ce5e3c':
  Minor cleanup of UsageStatsService
This commit is contained in:
Brian Carlstrom
2014-05-01 21:45:38 +00:00
committed by Android Git Automerger

View File

@@ -85,7 +85,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
private static final String FILE_HISTORY = FILE_PREFIX + "history.xml"; 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; private static final int MAX_NUM_FILES = 5;
@@ -97,20 +97,22 @@ public final class UsageStatsService extends IUsageStats.Stub {
static IUsageStats sService; static IUsageStats sService;
private Context mContext; private Context mContext;
// structure used to maintain statistics since the last checkin. // 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. // 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. // To remove last-resume time stats when a pacakge is removed.
private PackageMonitor mPackageMonitor; private PackageMonitor mPackageMonitor;
// Lock to update package stats. Methods suffixed by SLOCK should invoked with // Lock to update package stats. Methods suffixed by SLOCK should invoked with
// this lock held // this lock held
final Object mStatsLock; final Object mStatsLock = new Object();
// Lock to write to file. Methods suffixed by FLOCK should invoked with // Lock to write to file. Methods suffixed by FLOCK should invoked with
// this lock held. // this lock held.
final Object mFileLock; final Object mFileLock = new Object();
// Order of locks is mFileLock followed by mStatsLock to avoid deadlocks // Order of locks is mFileLock followed by mStatsLock to avoid deadlocks
private String mLastResumedPkg; private String mLastResumedPkg;
private String mLastResumedComp; private String mLastResumedComp;
@@ -120,52 +122,53 @@ public final class UsageStatsService extends IUsageStats.Stub {
private String mFileLeaf; private String mFileLeaf;
private File mDir; 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 AtomicInteger mLastWriteDay = new AtomicInteger(-1);
private final AtomicLong mLastWriteElapsedTime = new AtomicLong(0); private final AtomicLong mLastWriteElapsedTime = new AtomicLong(0);
private final AtomicBoolean mUnforcedDiskWriteRunning = new AtomicBoolean(false); private final AtomicBoolean mUnforcedDiskWriteRunning = new AtomicBoolean(false);
static class TimeStats { static class TimeStats {
int count; int mCount;
int[] times = new int[NUM_LAUNCH_TIME_BINS]; final int[] mTimes = new int[NUM_LAUNCH_TIME_BINS];
TimeStats() { TimeStats() {
} }
void incCount() { void incCount() {
count++; mCount++;
} }
void add(int val) { void add(int val) {
final int[] bins = LAUNCH_TIME_BINS; final int[] bins = LAUNCH_TIME_BINS;
for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) { for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
if (val < bins[i]) { if (val < bins[i]) {
times[i]++; mTimes[i]++;
return; return;
} }
} }
times[NUM_LAUNCH_TIME_BINS-1]++; mTimes[NUM_LAUNCH_TIME_BINS-1]++;
} }
TimeStats(Parcel in) { TimeStats(Parcel in) {
count = in.readInt(); mCount = in.readInt();
final int[] localTimes = times; final int[] localTimes = mTimes;
for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) { for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
localTimes[i] = in.readInt(); localTimes[i] = in.readInt();
} }
} }
void writeToParcel(Parcel out) { void writeToParcel(Parcel out) {
out.writeInt(count); out.writeInt(mCount);
final int[] localTimes = times; final int[] localTimes = mTimes;
for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) { for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
out.writeInt(localTimes[i]); out.writeInt(localTimes[i]);
} }
} }
} }
private class PkgUsageStatsExtended { static class PkgUsageStatsExtended {
final ArrayMap<String, TimeStats> mLaunchTimes final ArrayMap<String, TimeStats> mLaunchTimes
= new ArrayMap<String, TimeStats>(); = new ArrayMap<String, TimeStats>();
final ArrayMap<String, TimeStats> mFullyDrawnTimes final ArrayMap<String, TimeStats> mFullyDrawnTimes
@@ -209,7 +212,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
void updateResume(String comp, boolean launched) { void updateResume(String comp, boolean launched) {
if (launched) { if (launched) {
mLaunchCount ++; mLaunchCount++;
} }
mResumedTime = SystemClock.elapsedRealtime(); mResumedTime = SystemClock.elapsedRealtime();
} }
@@ -272,26 +275,19 @@ public final class UsageStatsService extends IUsageStats.Stub {
} }
UsageStatsService(String dir) { UsageStatsService(String dir) {
mStats = new ArrayMap<String, PkgUsageStatsExtended>(); if (localLOGV) Slog.v(TAG, "UsageStatsService: " + dir);
mLastResumeTimes = new ArrayMap<String, ArrayMap<String, Long>>();
mStatsLock = new Object();
mFileLock = new Object();
mDir = new File(dir); mDir = new File(dir);
mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
mDir.mkdir(); mDir.mkdir();
// Remove any old usage files from previous versions. // Remove any old /data/system/usagestats.* files from previous versions.
File parentDir = mDir.getParentFile(); File parentDir = mDir.getParentFile();
String fList[] = parentDir.list(); String files[] = parentDir.list();
if (fList != null) { if (files != null) {
String prefix = mDir.getName() + "."; String prefix = mDir.getName() + ".";
int i = fList.length; for (String file : files) {
while (i > 0) { if (file.startsWith(prefix)) {
i--; Slog.i(TAG, "Deleting old usage file: " + file);
if (fList[i].startsWith(prefix)) { (new File(parentDir, file)).delete();
Slog.i(TAG, "Deleting old usage file: " + fList[i]);
(new File(parentDir, fList[i])).delete();
} }
} }
} }
@@ -312,11 +308,11 @@ public final class UsageStatsService extends IUsageStats.Stub {
*/ */
private String getCurrentDateStr(String prefix) { private String getCurrentDateStr(String prefix) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if (prefix != null) {
sb.append(prefix);
}
synchronized (mCal) { synchronized (mCal) {
mCal.setTimeInMillis(System.currentTimeMillis()); mCal.setTimeInMillis(System.currentTimeMillis());
if (prefix != null) {
sb.append(prefix);
}
sb.append(mCal.get(Calendar.YEAR)); sb.append(mCal.get(Calendar.YEAR));
int mm = mCal.get(Calendar.MONTH) - Calendar.JANUARY +1; int mm = mCal.get(Calendar.MONTH) - Calendar.JANUARY +1;
if (mm < 10) { if (mm < 10) {
@@ -334,12 +330,15 @@ public final class UsageStatsService extends IUsageStats.Stub {
private Parcel getParcelForFile(File file) throws IOException { private Parcel getParcelForFile(File file) throws IOException {
FileInputStream stream = new FileInputStream(file); FileInputStream stream = new FileInputStream(file);
byte[] raw = readFully(stream); try {
Parcel in = Parcel.obtain(); byte[] raw = readFully(stream);
in.unmarshall(raw, 0, raw.length); Parcel in = Parcel.obtain();
in.setDataPosition(0); in.unmarshall(raw, 0, raw.length);
stream.close(); in.setDataPosition(0);
return in; return in;
} finally {
stream.close();
}
} }
private void readStatsFromFile() { private void readStatsFromFile() {
@@ -362,8 +361,9 @@ public final class UsageStatsService extends IUsageStats.Stub {
private void readStatsFLOCK(File file) throws IOException { private void readStatsFLOCK(File file) throws IOException {
Parcel in = getParcelForFile(file); Parcel in = getParcelForFile(file);
int vers = in.readInt(); int vers = in.readInt();
if (vers != VERSION) { if (vers != VERSION) { // vers will be 0 if the parcel file was empty
Slog.w(TAG, "Usage stats version changed; dropping"); Slog.w(TAG, "Usage stats version of " + file + " changed from " + vers + " to "
+ VERSION + "; dropping");
return; return;
} }
int N = in.readInt(); int N = in.readInt();
@@ -384,12 +384,12 @@ public final class UsageStatsService extends IUsageStats.Stub {
private void readHistoryStatsFromFile() { private void readHistoryStatsFromFile() {
synchronized (mFileLock) { synchronized (mFileLock) {
if (mHistoryFile.getBaseFile().exists()) { if (mHistoryFile.getBaseFile().exists()) {
readHistoryStatsFLOCK(mHistoryFile); readHistoryStatsFLOCK();
} }
} }
} }
private void readHistoryStatsFLOCK(AtomicFile file) { private void readHistoryStatsFLOCK() {
FileInputStream fis = null; FileInputStream fis = null;
try { try {
fis = mHistoryFile.openRead(); fis = mHistoryFile.openRead();
@@ -477,7 +477,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
// Get all usage stats output files // Get all usage stats output files
ArrayList<String> fileList = getUsageStatsFileListFLOCK(); ArrayList<String> fileList = getUsageStatsFileListFLOCK();
if (fileList == null) { 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; return;
} }
int count = fileList.size(); int count = fileList.size();
@@ -577,8 +577,8 @@ public final class UsageStatsService extends IUsageStats.Stub {
} }
if (dayChanged || forceWriteHistoryStats) { if (dayChanged || forceWriteHistoryStats) {
// Write history stats daily, or when forced (due to shutdown). // Write history stats daily or when forced (due to shutdown) or when debugging.
writeHistoryStatsFLOCK(mHistoryFile); writeHistoryStatsFLOCK();
} }
// Delete the backup file // 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; FileOutputStream fos = null;
try { try {
fos = historyFile.startWrite(); fos = mHistoryFile.startWrite();
XmlSerializer out = new FastXmlSerializer(); XmlSerializer out = new FastXmlSerializer();
out.setOutput(fos, "utf-8"); out.setOutput(fos, "utf-8");
out.startDocument(null, true); out.startDocument(null, true);
@@ -666,11 +666,11 @@ public final class UsageStatsService extends IUsageStats.Stub {
out.endTag(null, "usage-history"); out.endTag(null, "usage-history");
out.endDocument(); out.endDocument();
historyFile.finishWrite(fos); mHistoryFile.finishWrite(fos);
} catch (IOException e) { } catch (IOException e) {
Slog.w(TAG,"Error writing history stats" + e); Slog.w(TAG,"Error writing history stats" + e);
if (fos != null) { if (fos != null) {
historyFile.failWrite(fos); mHistoryFile.failWrite(fos);
} }
} }
} }
@@ -714,6 +714,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
return sService; return sService;
} }
@Override
public void noteResumeComponent(ComponentName componentName) { public void noteResumeComponent(ComponentName componentName) {
enforceCallingPermission(); enforceCallingPermission();
String pkgName; String pkgName;
@@ -764,6 +765,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
} }
} }
@Override
public void notePauseComponent(ComponentName componentName) { public void notePauseComponent(ComponentName componentName) {
enforceCallingPermission(); enforceCallingPermission();
@@ -795,6 +797,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
writeStatsToFile(false, false); writeStatsToFile(false, false);
} }
@Override
public void noteLaunchTime(ComponentName componentName, int millis) { public void noteLaunchTime(ComponentName componentName, int millis) {
enforceCallingPermission(); enforceCallingPermission();
String pkgName; String pkgName;
@@ -841,6 +844,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
Binder.getCallingPid(), Binder.getCallingUid(), null); Binder.getCallingPid(), Binder.getCallingUid(), null);
} }
@Override
public PkgUsageStats getPkgUsageStats(ComponentName componentName) { public PkgUsageStats getPkgUsageStats(ComponentName componentName) {
mContext.enforceCallingOrSelfPermission( mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.PACKAGE_USAGE_STATS, null); android.Manifest.permission.PACKAGE_USAGE_STATS, null);
@@ -861,6 +865,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
} }
} }
@Override
public PkgUsageStats[] getAllPkgUsageStats() { public PkgUsageStats[] getAllPkgUsageStats() {
mContext.enforceCallingOrSelfPermission( mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.PACKAGE_USAGE_STATS, null); 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 pos = 0;
int avail = stream.available(); int avail = stream.available();
byte[] data = new byte[avail]; 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 // Delete old file after collecting info only for checkin requests
dFile.delete(); dFile.delete();
} }
} catch (FileNotFoundException e) {
Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : " + file);
return;
} catch (IOException e) { } catch (IOException e) {
Slog.w(TAG, "Failed with "+e+" when collecting dump info from file : "+file); 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); sb.append(activity);
TimeStats times = pus.mLaunchTimes.valueAt(i); TimeStats times = pus.mLaunchTimes.valueAt(i);
sb.append(','); sb.append(',');
sb.append(times.count); sb.append(times.mCount);
for (int j=0; j<NUM_LAUNCH_TIME_BINS; j++) { for (int j=0; j<NUM_LAUNCH_TIME_BINS; j++) {
sb.append(","); sb.append(",");
sb.append(times.times[j]); sb.append(times.mTimes[j]);
} }
sb.append('\n'); sb.append('\n');
} }
@@ -1007,7 +1009,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
TimeStats times = pus.mFullyDrawnTimes.valueAt(i); TimeStats times = pus.mFullyDrawnTimes.valueAt(i);
for (int j=0; j<NUM_LAUNCH_TIME_BINS; j++) { for (int j=0; j<NUM_LAUNCH_TIME_BINS; j++) {
sb.append(","); sb.append(",");
sb.append(times.times[j]); sb.append(times.mTimes[j]);
} }
sb.append('\n'); sb.append('\n');
} }
@@ -1027,26 +1029,26 @@ public final class UsageStatsService extends IUsageStats.Stub {
sb.append(pus.mLaunchTimes.keyAt(i)); sb.append(pus.mLaunchTimes.keyAt(i));
TimeStats times = pus.mLaunchTimes.valueAt(i); TimeStats times = pus.mLaunchTimes.valueAt(i);
sb.append(": "); sb.append(": ");
sb.append(times.count); sb.append(times.mCount);
sb.append(" starts"); sb.append(" starts");
int lastBin = 0; int lastBin = 0;
for (int j=0; j<NUM_LAUNCH_TIME_BINS-1; j++) { 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(", ");
sb.append(lastBin); sb.append(lastBin);
sb.append('-'); sb.append('-');
sb.append(LAUNCH_TIME_BINS[j]); sb.append(LAUNCH_TIME_BINS[j]);
sb.append("ms="); sb.append("ms=");
sb.append(times.times[j]); sb.append(times.mTimes[j]);
} }
lastBin = LAUNCH_TIME_BINS[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(">="); sb.append(">=");
sb.append(lastBin); sb.append(lastBin);
sb.append("ms="); sb.append("ms=");
sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]); sb.append(times.mTimes[NUM_LAUNCH_TIME_BINS-1]);
} }
sb.append('\n'); sb.append('\n');
} }
@@ -1059,7 +1061,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
boolean needComma = false; boolean needComma = false;
int lastBin = 0; int lastBin = 0;
for (int j=0; j<NUM_LAUNCH_TIME_BINS-1; j++) { for (int j=0; j<NUM_LAUNCH_TIME_BINS-1; j++) {
if (times.times[j] != 0) { if (times.mTimes[j] != 0) {
if (needComma) { if (needComma) {
sb.append(", "); sb.append(", ");
} else { } else {
@@ -1069,18 +1071,18 @@ public final class UsageStatsService extends IUsageStats.Stub {
sb.append('-'); sb.append('-');
sb.append(LAUNCH_TIME_BINS[j]); sb.append(LAUNCH_TIME_BINS[j]);
sb.append("ms="); sb.append("ms=");
sb.append(times.times[j]); sb.append(times.mTimes[j]);
} }
lastBin = LAUNCH_TIME_BINS[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) { if (needComma) {
sb.append(", "); sb.append(", ");
} }
sb.append(">="); sb.append(">=");
sb.append(lastBin); sb.append(lastBin);
sb.append("ms="); sb.append("ms=");
sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]); sb.append(times.mTimes[NUM_LAUNCH_TIME_BINS-1]);
} }
sb.append('\n'); sb.append('\n');
} }
@@ -1126,10 +1128,10 @@ public final class UsageStatsService extends IUsageStats.Stub {
return null; return null;
} }
@Override
/* /*
* The data persisted to file is parsed and the stats are computed. * The data persisted to file is parsed and the stats are computed.
*/ */
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingPermission(android.Manifest.permission.DUMP) if (mContext.checkCallingPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) { != 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 // Make sure the current stats are written to the file. This
// doesn't need to be done if we are deleting files after printing, // 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) { if (!deleteAfterPrint) {
writeStatsToFile(true, false); writeStatsToFile(true, false);
} }
@@ -1156,10 +1158,10 @@ public final class UsageStatsService extends IUsageStats.Stub {
if (!"*".equals(rawPackages)) { if (!"*".equals(rawPackages)) {
// A * is a wildcard to show all packages. // A * is a wildcard to show all packages.
String[] names = rawPackages.split(","); String[] names = rawPackages.split(",");
if (names.length != 0) {
packages = new HashSet<String>();
}
for (String n : names) { for (String n : names) {
if (packages == null) {
packages = new HashSet<String>();
}
packages.add(n); packages.add(n);
} }
} }