Merge change 132 into donut

* changes:
  Let's do bug #1769910 actually right.
This commit is contained in:
Android (Google) Code Review
2009-04-14 13:15:43 -07:00
8 changed files with 347 additions and 244 deletions

View File

@@ -681,6 +681,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
*/
HashMap<String, IBinder> mAppBindArgs;
/**
* Temporary to avoid allocations. Protected by main lock.
*/
final StringBuilder mStringBuilder = new StringBuilder(256);
/**
* Used to control how we initialize the service.
*/
@@ -778,6 +783,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
long mLastCpuTime = 0;
long mLastWriteTime = 0;
long mInitialStartTime = 0;
/**
* Set to true after the system has finished booting.
*/
@@ -1635,6 +1642,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
if (r.startTime == 0) {
r.startTime = SystemClock.uptimeMillis();
if (mInitialStartTime == 0) {
mInitialStartTime = r.startTime;
}
} else if (mInitialStartTime == 0) {
mInitialStartTime = SystemClock.uptimeMillis();
}
if (app != null && app.thread != null) {
@@ -1785,7 +1797,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
Watchdog.getInstance().processStarted(app, app.processName, pid);
}
StringBuilder buf = new StringBuilder(128);
StringBuilder buf = mStringBuilder;
buf.setLength(0);
buf.append("Start proc ");
buf.append(app.processName);
buf.append(" for ");
@@ -2813,7 +2826,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
intent, resolvedType, aInfo, mConfiguration,
resultRecord, resultWho, requestCode, componentSpecified);
r.startTime = SystemClock.uptimeMillis();
HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
!= 0 ? r : null;
@@ -4095,7 +4107,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
StringBuilder info = new StringBuilder();
StringBuilder info = mStringBuilder;
info.setLength(0);
info.append("ANR (application not responding) in process: ");
info.append(app.processName);
if (annotation != null) {
@@ -4517,7 +4530,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
} else if (mStartingProcesses.size() > 0) {
app = mStartingProcesses.remove(0);
app.pid = pid;
app.setPid(pid);
} else {
app = null;
}
@@ -7877,24 +7890,24 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
return;
}
pw.println("Activities in Current Activity Manager State:");
dumpHistoryList(pw, mHistory, " ", "History");
dumpHistoryList(pw, mHistory, " ", "History", true);
pw.println(" ");
pw.println(" Running activities (most recent first):");
dumpHistoryList(pw, mLRUActivities, " ", "Running");
dumpHistoryList(pw, mLRUActivities, " ", "Running", false);
if (mWaitingVisibleActivities.size() > 0) {
pw.println(" ");
pw.println(" Activities waiting for another to become visible:");
dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Waiting");
dumpHistoryList(pw, mWaitingVisibleActivities, " ", "Waiting", false);
}
if (mStoppingActivities.size() > 0) {
pw.println(" ");
pw.println(" Activities waiting to stop:");
dumpHistoryList(pw, mStoppingActivities, " ", "Stopping");
dumpHistoryList(pw, mStoppingActivities, " ", "Stopping", false);
}
if (mFinishingActivities.size() > 0) {
pw.println(" ");
pw.println(" Activities waiting to finish:");
dumpHistoryList(pw, mFinishingActivities, " ", "Finishing");
dumpHistoryList(pw, mFinishingActivities, " ", "Finishing", false);
}
pw.println(" ");
@@ -7931,8 +7944,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
needSep = true;
}
ProcessRecord r = procs.valueAt(ia);
pw.println((r.persistent ? " *PERSISTENT* Process [" : " Process [")
+ r.processName + "] UID " + procs.keyAt(ia));
pw.print(r.persistent ? " *PERSISTENT* Process [" : " Process [");
pw.print(r.processName); pw.print("] UID "); pw.println(procs.keyAt(ia));
r.dump(pw, " ");
if (r.persistent) {
numPers++;
@@ -8360,16 +8373,29 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
private static final void dumpHistoryList(PrintWriter pw, List list,
String prefix, String label) {
String prefix, String label, boolean complete) {
TaskRecord lastTask = null;
for (int i=list.size()-1; i>=0; i--) {
HistoryRecord r = (HistoryRecord)list.get(i);
if (lastTask != r.task) {
lastTask = r.task;
lastTask.dump(pw, prefix + " ");
if (complete || !r.inHistory) {
lastTask.dump(pw, prefix + " ");
} else {
pw.print(prefix);
pw.print(" ");
pw.println(lastTask);
}
}
if (complete || !r.inHistory) {
pw.print(prefix); pw.print(" "); pw.print(label);
pw.print(" #"); pw.print(i); pw.println(":");
r.dump(pw, prefix + " ");
} else {
pw.print(prefix); pw.print(" "); pw.print(label);
pw.print(" #"); pw.print(i); pw.print(": ");
pw.println(r);
}
pw.println(prefix + " " + label + " #" + i + ":");
r.dump(pw, prefix + " ");
}
}
@@ -8738,7 +8764,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
app.pid = 0;
app.setPid(0);
}
}

View File

@@ -28,7 +28,8 @@ class ConnectionRecord {
final HistoryRecord activity; // If non-null, the owning activity.
final IServiceConnection conn; // The client connection.
final int flags; // Binding options.
String stringName; // Caching of toString.
void dump(PrintWriter pw, String prefix) {
pw.println(prefix + this);
pw.println(prefix + "binding=" + binding);
@@ -46,9 +47,17 @@ class ConnectionRecord {
}
public String toString() {
return "ConnectionRecord{"
+ Integer.toHexString(System.identityHashCode(this))
+ " " + binding.service.shortName
+ ":@" + Integer.toHexString(System.identityHashCode(conn.asBinder())) + "}";
if (stringName != null) {
return stringName;
}
StringBuilder sb = new StringBuilder(128);
sb.append("ConnectionRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(' ');
sb.append(binding.service.shortName);
sb.append(":@");
sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder())));
sb.append('}');
return stringName = sb.toString();
}
}

View File

@@ -32,7 +32,8 @@ class ContentProviderRecord extends ContentProviderHolder {
int externals; // number of non-framework processes supported by this provider
ProcessRecord app; // if non-null, hosting application
ProcessRecord launchingApp; // if non-null, waiting for this app to be launched.
String stringName;
public ContentProviderRecord(ProviderInfo _info, ApplicationInfo ai) {
super(_info);
uid = ai.uid;
@@ -69,8 +70,15 @@ class ContentProviderRecord extends ContentProviderHolder {
}
public String toString() {
return "ContentProviderRecord{"
+ Integer.toHexString(System.identityHashCode(this))
+ " " + info.name + "}";
if (stringName != null) {
return stringName;
}
StringBuilder sb = new StringBuilder(128);
sb.append("ContentProviderRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(' ');
sb.append(info.name);
sb.append('}');
return stringName = sb.toString();
}
}

View File

@@ -100,46 +100,74 @@ class HistoryRecord extends IApplicationToken.Stub {
boolean hasBeenLaunched;// has this activity ever been launched?
boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
String stringName; // for caching of toString().
void dump(PrintWriter pw, String prefix) {
pw.println(prefix + this);
pw.println(prefix + "packageName=" + packageName
+ " processName=" + processName);
pw.println(prefix + "launchedFromUid=" + launchedFromUid
+ " app=" + app);
pw.println(prefix + intent);
pw.println(prefix + "frontOfTask=" + frontOfTask + " task=" + task);
pw.println(prefix + "taskAffinity=" + taskAffinity);
pw.println(prefix + "realActivity=" + realActivity);
pw.println(prefix + "dir=" + baseDir + " res=" + resDir + " data=" + dataDir);
pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes)
+ " icon=0x" + Integer.toHexString(icon)
+ " theme=0x" + Integer.toHexString(theme));
pw.println(prefix + "stateNotNeeded=" + stateNotNeeded
+ " componentSpecified=" + componentSpecified
+ " isHomeActivity=" + isHomeActivity);
pw.println(prefix + "configuration=" + configuration);
pw.println(prefix + "resultTo=" + resultTo
+ " resultWho=" + resultWho + " resultCode=" + requestCode);
pw.println(prefix + "results=" + results);
pw.println(prefix + "pendingResults=" + pendingResults);
pw.println(prefix + "readUriPermissions=" + readUriPermissions);
pw.println(prefix + "writeUriPermissions=" + writeUriPermissions);
pw.println(prefix + "launchFailed=" + launchFailed
+ " haveState=" + haveState + " icicle=" + icicle);
pw.println(prefix + "state=" + state
+ " stopped=" + stopped + " finishing=" + finishing);
pw.println(prefix + "keysPaused=" + keysPaused
+ " inHistory=" + inHistory + " persistent=" + persistent
+ " launchMode=" + launchMode);
pw.println(prefix + "fullscreen=" + fullscreen
+ " visible=" + visible
+ " frozenBeforeDestroy=" + frozenBeforeDestroy
+ " thumbnailNeeded=" + thumbnailNeeded + " idle=" + idle);
pw.println(prefix + "waitingVisible=" + waitingVisible
+ " nowVisible=" + nowVisible);
pw.println(prefix + "configDestroy=" + configDestroy
+ " configChangeFlags=" + Integer.toHexString(configChangeFlags));
pw.println(prefix + "connections=" + connections);
pw.print(prefix); pw.println(this);
pw.print(prefix); pw.print("packageName="); pw.print(packageName);
pw.print(" processName="); pw.println(processName);
pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
pw.print(" app="); pw.println(app);
pw.print(prefix); pw.println(intent);
pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask);
pw.print(" task="); pw.println(task);
pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
pw.print(prefix); pw.print("realActivity="); pw.println(realActivity);
pw.print(prefix); pw.print("dir="); pw.print(baseDir);
pw.print(" res="); pw.print(resDir);
pw.print(" data="); pw.println(dataDir);
pw.print(prefix); pw.print("labelRes=0x");
pw.print(Integer.toHexString(labelRes));
pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
pw.print(" componentSpecified="); pw.print(componentSpecified);
pw.print(" isHomeActivity="); pw.println(isHomeActivity);
pw.print(prefix); pw.print("configuration="); pw.println(configuration);
if (resultTo != null || resultWho != null) {
pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
pw.print(" resultWho="); pw.print(resultWho);
pw.print(" resultCode="); pw.println(requestCode);
}
if (results != null) {
pw.print(prefix); pw.print("results="); pw.println(results);
}
if (pendingResults != null) {
pw.print(prefix); pw.print("pendingResults="); pw.println(pendingResults);
}
if (readUriPermissions != null) {
pw.print(prefix); pw.print("readUriPermissions="); pw.println(readUriPermissions);
}
if (writeUriPermissions != null) {
pw.print(prefix); pw.print("writeUriPermissions="); pw.println(writeUriPermissions);
}
pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
pw.print(" haveState="); pw.print(haveState);
pw.print(" icicle="); pw.println(icicle);
pw.print(prefix); pw.print("state="); pw.print(state);
pw.print(" stopped="); pw.print(stopped);
pw.print(" finishing="); pw.println(finishing);
pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
pw.print(" inHistory="); pw.print(inHistory);
pw.print(" persistent="); pw.print(persistent);
pw.print(" launchMode="); pw.println(launchMode);
pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
pw.print(" visible="); pw.print(visible);
pw.print(" frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
pw.print(" thumbnailNeeded="); pw.print(thumbnailNeeded);
pw.print(" idle="); pw.println(idle);
if (waitingVisible || nowVisible) {
pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible);
pw.print(" nowVisible="); pw.println(nowVisible);
}
if (configDestroy || configChangeFlags != 0) {
pw.print(prefix); pw.print("configDestroy="); pw.print(configDestroy);
pw.print(" configChangeFlags=");
pw.println(Integer.toHexString(configChangeFlags));
}
if (connections != null) {
pw.print(prefix); pw.print("connections="); pw.println(connections);
}
}
HistoryRecord(ActivityManagerService _service, ProcessRecord _caller,
@@ -336,18 +364,30 @@ class HistoryRecord extends IApplicationToken.Stub {
public void windowsVisible() {
synchronized(service) {
if (startTime != 0) {
long time = SystemClock.uptimeMillis() - startTime;
final long curTime = SystemClock.uptimeMillis();
final long thisTime = curTime - startTime;
final long totalTime = service.mInitialStartTime != 0
? (curTime - service.mInitialStartTime) : thisTime;
if (ActivityManagerService.SHOW_ACTIVITY_START_TIME) {
EventLog.writeEvent(ActivityManagerService.LOG_ACTIVITY_LAUNCH_TIME,
System.identityHashCode(this), shortComponentName, time);
Log.i(ActivityManagerService.TAG, "Displayed activity "
+ shortComponentName
+ ": " + time + " ms");
System.identityHashCode(this), shortComponentName,
thisTime, totalTime);
StringBuilder sb = service.mStringBuilder;
sb.setLength(0);
sb.append("Displayed activity ");
sb.append(shortComponentName);
sb.append(": ");
sb.append(thisTime);
sb.append(" ms (total ");
sb.append(totalTime);
sb.append(" ms)");
Log.i(ActivityManagerService.TAG, sb.toString());
}
if (time > 0) {
service.mUsageStatsService.noteLaunchTime(realActivity, (int)time);
if (totalTime > 0) {
service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
}
startTime = 0;
service.mInitialStartTime = 0;
}
if (ActivityManagerService.DEBUG_SWITCH) Log.v(
ActivityManagerService.TAG, "windowsVisible(): " + this);
@@ -457,8 +497,15 @@ class HistoryRecord extends IApplicationToken.Stub {
public String toString() {
return "HistoryRecord{"
+ Integer.toHexString(System.identityHashCode(this))
+ " " + intent.getComponent().toShortString() + "}";
if (stringName != null) {
return stringName;
}
StringBuilder sb = new StringBuilder(128);
sb.append("HistoryRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(' ');
sb.append(intent.getComponent().toShortString());
sb.append('}');
return stringName = sb.toString();
}
}

View File

@@ -98,44 +98,82 @@ class ProcessRecord implements Watchdog.PssRequestor {
boolean waitedForDebugger; // has process show wait for debugger dialog?
Dialog waitDialog; // current wait for debugger dialog
String stringName; // caching of toString() result.
// These reports are generated & stored when an app gets into an error condition.
// They will be "null" when all is OK.
ActivityManager.ProcessErrorStateInfo crashingReport;
ActivityManager.ProcessErrorStateInfo notRespondingReport;
void dump(PrintWriter pw, String prefix) {
pw.println(prefix + this);
pw.println(prefix + "class=" + info.className);
pw.println(prefix+"manageSpaceActivityName="+info.manageSpaceActivityName);
pw.println(prefix + "dir=" + info.sourceDir + " publicDir=" + info.publicSourceDir
+ " data=" + info.dataDir);
pw.println(prefix + "packageList=" + pkgList);
pw.println(prefix + "instrumentationClass=" + instrumentationClass
+ " instrumentationProfileFile=" + instrumentationProfileFile);
pw.println(prefix + "instrumentationArguments=" + instrumentationArguments);
pw.println(prefix + "thread=" + thread + " curReceiver=" + curReceiver);
pw.println(prefix + "pid=" + pid + " starting=" + starting
+ " lastPss=" + lastPss);
pw.println(prefix + "maxAdj=" + maxAdj + " hiddenAdj=" + hiddenAdj
+ " curRawAdj=" + curRawAdj + " setRawAdj=" + setRawAdj
+ " curAdj=" + curAdj + " setAdj=" + setAdj);
pw.println(prefix + "isForeground=" + isForeground
+ " setIsForeground=" + setIsForeground
+ " foregroundServices=" + foregroundServices
+ " forcingToForeground=" + forcingToForeground);
pw.println(prefix + "persistent=" + persistent + " removed=" + removed
+ " persistentActivities=" + persistentActivities);
pw.println(prefix + "debugging=" + debugging
+ " crashing=" + crashing + " " + crashDialog
+ " notResponding=" + notResponding + " " + anrDialog
+ " bad=" + bad);
pw.println(prefix + "activities=" + activities);
pw.println(prefix + "services=" + services);
pw.println(prefix + "executingServices=" + executingServices);
pw.println(prefix + "connections=" + connections);
pw.println(prefix + "pubProviders=" + pubProviders);
pw.println(prefix + "conProviders=" + conProviders);
pw.println(prefix + "receivers=" + receivers);
pw.print(prefix); pw.println(this);
if (info.className != null) {
pw.print(prefix); pw.print("class="); pw.println(info.className);
}
if (info.manageSpaceActivityName != null) {
pw.print(prefix); pw.print("manageSpaceActivityName=");
pw.println(info.manageSpaceActivityName);
}
pw.print(prefix); pw.print("dir="); pw.print(info.sourceDir);
pw.print(" publicDir="); pw.print(info.publicSourceDir);
pw.print(" data="); pw.println(info.dataDir);
pw.print(prefix); pw.print("packageList="); pw.println(pkgList);
if (instrumentationClass != null || instrumentationProfileFile != null
|| instrumentationArguments != null) {
pw.print(prefix); pw.print("instrumentationClass=");
pw.print(instrumentationClass);
pw.print(" instrumentationProfileFile=");
pw.println(instrumentationProfileFile);
pw.print(prefix); pw.print("instrumentationArguments=");
pw.println(instrumentationArguments);
}
pw.print(prefix); pw.print("thread="); pw.print(thread);
pw.print(" curReceiver="); pw.println(curReceiver);
pw.print(prefix); pw.print("pid="); pw.print(pid); pw.print(" starting=");
pw.print(starting); pw.print(" lastPss="); pw.println(lastPss);
pw.print(prefix); pw.print("oom: max="); pw.print(maxAdj);
pw.print(" hidden="); pw.print(hiddenAdj);
pw.print(" curRaw="); pw.print(curRawAdj);
pw.print(" setRaw="); pw.print(setRawAdj);
pw.print(" cur="); pw.print(curAdj);
pw.print(" set="); pw.println(setAdj);
pw.print(prefix); pw.print("isForeground="); pw.print(isForeground);
pw.print(" setIsForeground="); pw.print(setIsForeground);
pw.print(" foregroundServices="); pw.print(foregroundServices);
pw.print(" forcingToForeground="); pw.println(forcingToForeground);
pw.print(prefix); pw.print("persistent="); pw.print(persistent);
pw.print(" removed="); pw.print(removed);
pw.print(" persistentActivities="); pw.println(persistentActivities);
if (debugging || crashing || crashDialog != null || notResponding
|| anrDialog != null || bad) {
pw.print(prefix); pw.print("debugging="); pw.print(debugging);
pw.print(" crashing="); pw.print(crashing);
pw.print(" "); pw.print(crashDialog);
pw.print(" notResponding="); pw.print(notResponding);
pw.print(" " ); pw.print(anrDialog);
pw.print(" bad="); pw.println(bad);
}
if (activities.size() > 0) {
pw.print(prefix); pw.print("activities="); pw.println(activities);
}
if (services.size() > 0) {
pw.print(prefix); pw.print("services="); pw.println(services);
}
if (executingServices.size() > 0) {
pw.print(prefix); pw.print("executingServices="); pw.println(executingServices);
}
if (connections.size() > 0) {
pw.print(prefix); pw.print("connections="); pw.println(connections);
}
if (pubProviders.size() > 0) {
pw.print(prefix); pw.print("pubProviders="); pw.println(pubProviders);
}
if (conProviders.size() > 0) {
pw.print(prefix); pw.print("conProviders="); pw.println(conProviders);
}
if (receivers.size() > 0) {
pw.print(prefix); pw.print("receivers="); pw.println(receivers);
}
}
ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, IApplicationThread _thread,
@@ -154,6 +192,11 @@ class ProcessRecord implements Watchdog.PssRequestor {
persistentActivities = 0;
}
public void setPid(int _pid) {
pid = _pid;
stringName = null;
}
/**
* This method returns true if any of the activities within the process record are interesting
* to the user. See HistoryRecord.isInterestingToUserLocked()
@@ -188,9 +231,20 @@ class ProcessRecord implements Watchdog.PssRequestor {
}
public String toString() {
return "ProcessRecord{"
+ Integer.toHexString(System.identityHashCode(this))
+ " " + pid + ":" + processName + "/" + info.uid + "}";
if (stringName != null) {
return stringName;
}
StringBuilder sb = new StringBuilder(128);
sb.append("ProcessRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(' ');
sb.append(pid);
sb.append(':');
sb.append(processName);
sb.append('/');
sb.append(info.uid);
sb.append('}');
return stringName = sb.toString();
}
/*

View File

@@ -39,6 +39,8 @@ class ReceiverList extends ArrayList<BroadcastFilter>
BroadcastRecord curBroadcast = null;
boolean linkedToDeath = false;
String stringName;
ReceiverList(ActivityManagerService _owner, ProcessRecord _app,
int _pid, int _uid, IIntentReceiver _receiver) {
owner = _owner;
@@ -82,11 +84,21 @@ class ReceiverList extends ArrayList<BroadcastFilter>
}
public String toString() {
return "ReceiverList{"
+ Integer.toHexString(System.identityHashCode(this))
+ " " + pid + " " + (app != null ? app.processName : "(unknown name)")
+ "/" + uid + " client "
+ Integer.toHexString(System.identityHashCode(receiver.asBinder()))
+ "}";
if (stringName != null) {
return stringName;
}
StringBuilder sb = new StringBuilder(128);
sb.append("ReceiverList{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(' ');
sb.append(pid);
sb.append(' ');
sb.append((app != null ? app.processName : "(unknown name)"));
sb.append('/');
sb.append(uid);
sb.append(" client ");
sb.append(Integer.toHexString(System.identityHashCode(receiver.asBinder())));
sb.append('}');
return stringName = sb.toString();
}
}

View File

@@ -77,6 +77,8 @@ class ServiceRecord extends Binder {
long restartTime; // time of last restart.
long nextRestartTime; // time when restartDelay will expire.
String stringName; // caching of toString
void dump(PrintWriter pw, String prefix) {
pw.println(prefix + this);
pw.println(prefix + "intent=" + intent.getIntent());
@@ -159,8 +161,15 @@ class ServiceRecord extends Binder {
}
public String toString() {
return "ServiceRecord{"
+ Integer.toHexString(System.identityHashCode(this))
+ " " + shortName + "}";
if (stringName != null) {
return stringName;
}
StringBuilder sb = new StringBuilder(128);
sb.append("ServiceRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(' ');
sb.append(shortName);
sb.append('}');
return stringName = sb.toString();
}
}

View File

@@ -55,9 +55,9 @@ public final class UsageStatsService extends IUsageStats.Stub {
private static final String TAG = "UsageStats";
// Current on-disk Parcel version
private static final int VERSION = 1003;
private static final int VERSION = 1004;
private static final int CHECKIN_VERSION = 2;
private static final int CHECKIN_VERSION = 3;
private static final String FILE_PREFIX = "usage-";
@@ -65,7 +65,10 @@ public final class UsageStatsService extends IUsageStats.Stub {
private static final int MAX_NUM_FILES = 5;
private static final int MAX_LAUNCH_TIME_SAMPLES = 50;
private static final int NUM_LAUNCH_TIME_BINS = 10;
private static final int[] LAUNCH_TIME_BINS = {
250, 500, 750, 1000, 1500, 2000, 3000, 4000, 5000
};
static IUsageStats sService;
private Context mContext;
@@ -88,61 +91,33 @@ public final class UsageStatsService extends IUsageStats.Stub {
private int mLastWriteDay;
static class TimeStats {
int count;
int[] times = new int[NUM_LAUNCH_TIME_BINS];
boolean haveStats;
int samples;
int minimum;
int maximum;
int average;
int median;
int size;
int[] array;
private int avail;
void add(int val) {
count++;
if (size > MAX_LAUNCH_TIME_SAMPLES) {
return;
}
if (size >= avail) {
avail = ((avail+2)*3)/2;
int[] newarray = new int[avail];
if (array != null) {
System.arraycopy(array, 0, newarray, 0, size);
}
array = newarray;
}
array[size] = val;
size++;
haveStats = false;
TimeStats() {
}
void computeStats() {
if (haveStats) {
return;
}
average = 0;
int i = samples = size;
if (i > 0) {
java.util.Arrays.sort(array, 0, i);
i--;
minimum = maximum = average = array[i];
median = array[i/2];
while (i > 0) {
i--;
int v = array[i];
if (v < minimum) minimum = v;
if (v > maximum) maximum = v;
average += v;
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]++;
return;
}
average = average/size;
} else {
minimum = maximum = median = 0;
}
times[NUM_LAUNCH_TIME_BINS-1]++;
}
TimeStats(Parcel in) {
final int[] localTimes = times;
for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
localTimes[i] = in.readInt();
}
}
void writeToParcel(Parcel out) {
final int[] localTimes = times;
for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
out.writeInt(localTimes[i]);
}
}
}
@@ -170,29 +145,9 @@ public final class UsageStatsService extends IUsageStats.Stub {
if (localLOGV) Log.v(TAG, "Reading comps: " + N);
for (int i=0; i<N; i++) {
String comp = in.readString();
final int M = in.readInt();
final int count = in.readInt();
if (localLOGV) Log.v(TAG, "Component: " + comp + ", times: " + M);
if (M > 0) {
TimeStats times = new TimeStats();
times.count = count;
times.size = times.avail = M;
times.array = new int[M];
for (int j=0; j<M; j++) {
times.array[j] = in.readInt();
}
mLaunchTimes.put(comp, times);
} else if (M == -1) {
TimeStats times = new TimeStats();
times.count = count;
times.samples = in.readInt();
times.minimum = in.readInt();
times.maximum = in.readInt();
times.average = in.readInt();
times.median = in.readInt();
times.haveStats = true;
mLaunchTimes.put(comp, times);
}
if (localLOGV) Log.v(TAG, "Component: " + comp);
TimeStats times = new TimeStats(in);
mLaunchTimes.put(comp, times);
}
}
@@ -215,7 +170,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
times.add(millis);
}
void writeToParcel(Parcel out, boolean allTimes) {
void writeToParcel(Parcel out) {
out.writeInt(mLaunchCount);
out.writeLong(mUsageTime);
final int N = mLaunchTimes.size();
@@ -224,23 +179,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
for (Map.Entry<String, TimeStats> ent : mLaunchTimes.entrySet()) {
out.writeString(ent.getKey());
TimeStats times = ent.getValue();
if (allTimes) {
final int M = times.size;
out.writeInt(M);
out.writeInt(times.count);
for (int j=0; j<M; j++) {
out.writeInt(times.array[j]);
}
} else {
times.computeStats();
out.writeInt(-1);
out.writeInt(times.count);
out.writeInt(times.samples);
out.writeInt(times.minimum);
out.writeInt(times.maximum);
out.writeInt(times.average);
out.writeInt(times.median);
}
times.writeToParcel(out);
}
}
}
@@ -423,7 +362,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
mFile.renameTo(backupFile);
try {
// Write mStats to file
writeStatsFLOCK(!dayChanged);
writeStatsFLOCK();
mLastWriteElapsedTime = currElapsedTime;
if (dayChanged) {
mLastWriteDay = curDay;
@@ -448,11 +387,11 @@ public final class UsageStatsService extends IUsageStats.Stub {
}
}
private void writeStatsFLOCK(boolean allTimes) throws IOException {
private void writeStatsFLOCK() throws IOException {
FileOutputStream stream = new FileOutputStream(mFile);
try {
Parcel out = Parcel.obtain();
writeStatsToParcelFLOCK(out, allTimes);
writeStatsToParcelFLOCK(out);
stream.write(out.marshall());
out.recycle();
stream.flush();
@@ -461,7 +400,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
}
}
private void writeStatsToParcelFLOCK(Parcel out, boolean allTimes) {
private void writeStatsToParcelFLOCK(Parcel out) {
synchronized (mStatsLock) {
out.writeInt(VERSION);
Set<String> keys = mStats.keySet();
@@ -469,7 +408,7 @@ public final class UsageStatsService extends IUsageStats.Stub {
for (String key : keys) {
PkgUsageStatsExtended pus = mStats.get(key);
out.writeString(key);
pus.writeToParcel(out, allTimes);
pus.writeToParcel(out);
}
}
}
@@ -696,20 +635,11 @@ public final class UsageStatsService extends IUsageStats.Stub {
for (Map.Entry<String, TimeStats> ent : pus.mLaunchTimes.entrySet()) {
sb.append("A:");
sb.append(ent.getKey());
sb.append(",");
TimeStats times = ent.getValue();
times.computeStats();
sb.append(times.count);
sb.append(",");
sb.append(times.samples);
sb.append(",");
sb.append(times.minimum);
sb.append(",");
sb.append(times.maximum);
sb.append(",");
sb.append(times.average);
sb.append(",");
sb.append(times.median);
for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
sb.append(",");
sb.append(times.times[i]);
}
sb.append('\n');
}
}
@@ -729,19 +659,27 @@ public final class UsageStatsService extends IUsageStats.Stub {
sb.append(" ");
sb.append(ent.getKey());
TimeStats times = ent.getValue();
times.computeStats();
sb.append(": count=");
sb.append(times.count);
sb.append(", samples=");
sb.append(times.samples);
sb.append(", min=");
sb.append(times.minimum);
sb.append(", max=");
sb.append(times.maximum);
sb.append(", avg=");
sb.append(times.average);
sb.append(", med=");
sb.append(times.median);
int lastBin = 0;
boolean first = true;
for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
if (times.times[i] != 0) {
sb.append(first ? ": " : ", ");
sb.append(lastBin);
sb.append('-');
sb.append(LAUNCH_TIME_BINS[i]);
sb.append('=');
sb.append(times.times[i]);
first = false;
}
lastBin = LAUNCH_TIME_BINS[i];
}
if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) {
sb.append(first ? ": " : ", ");
sb.append(">=");
sb.append(lastBin);
sb.append('=');
sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]);
}
sb.append('\n');
}
}