summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2009-04-13 18:42:49 -0700
committerDianne Hackborn <hackbod@google.com>2009-04-13 18:42:49 -0700
commitf210d6b75e2c0fe60b90c074ff9f615c1137f23e (patch)
tree112240b6d4c3d2d1f78e7badde174cbe11d1f31b
parent7680d67dc7445ba65a4fc4307afe24b20b333a52 (diff)
downloadframeworks_base-f210d6b75e2c0fe60b90c074ff9f615c1137f23e.zip
frameworks_base-f210d6b75e2c0fe60b90c074ff9f615c1137f23e.tar.gz
frameworks_base-f210d6b75e2c0fe60b90c074ff9f615c1137f23e.tar.bz2
Let's do bug #1769910 actually right.
My original implementation was computing averages and medians. Now we do binning, as requested. So much simpler, too! In addition, it fixes a bug where when hoping across activities we were only accounting for the last activity as the total time; now we count the time from the start of the initial activity. This also includes some reduction and optimization of the activity manager dumpsys output.
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java58
-rw-r--r--services/java/com/android/server/am/ConnectionRecord.java19
-rw-r--r--services/java/com/android/server/am/ContentProviderRecord.java16
-rw-r--r--services/java/com/android/server/am/HistoryRecord.java145
-rw-r--r--services/java/com/android/server/am/ProcessRecord.java124
-rw-r--r--services/java/com/android/server/am/ReceiverList.java24
-rw-r--r--services/java/com/android/server/am/ServiceRecord.java15
-rwxr-xr-xservices/java/com/android/server/am/UsageStatsService.java182
8 files changed, 343 insertions, 240 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 59aa29f..a3c23d3 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -682,6 +682,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.
*/
boolean mStartRunning = false;
@@ -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);
}
}
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java
index 41a783f..b4c7df1 100644
--- a/services/java/com/android/server/am/ConnectionRecord.java
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -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();
}
}
diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/java/com/android/server/am/ContentProviderRecord.java
index 9f37c14..2b9e006 100644
--- a/services/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/java/com/android/server/am/ContentProviderRecord.java
@@ -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();
}
}
diff --git a/services/java/com/android/server/am/HistoryRecord.java b/services/java/com/android/server/am/HistoryRecord.java
index ae16b14..a2fd62b 100644
--- a/services/java/com/android/server/am/HistoryRecord.java
+++ b/services/java/com/android/server/am/HistoryRecord.java
@@ -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();
}
}
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index a1320df..d2667e7 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -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();
}
/*
diff --git a/services/java/com/android/server/am/ReceiverList.java b/services/java/com/android/server/am/ReceiverList.java
index 6ac527b..b8bf30c 100644
--- a/services/java/com/android/server/am/ReceiverList.java
+++ b/services/java/com/android/server/am/ReceiverList.java
@@ -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();
}
}
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 4b90600..a8fc761 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -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();
}
}
diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java
index 7709efd..b6f9158 100755
--- a/services/java/com/android/server/am/UsageStatsService.java
+++ b/services/java/com/android/server/am/UsageStatsService.java
@@ -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;
+ TimeStats() {
+ }
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);
+ final int[] bins = LAUNCH_TIME_BINS;
+ for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
+ if (val < bins[i]) {
+ times[i]++;
+ return;
}
- array = newarray;
}
- array[size] = val;
- size++;
- haveStats = false;
+ times[NUM_LAUNCH_TIME_BINS-1]++;
}
- void computeStats() {
- if (haveStats) {
- return;
+ TimeStats(Parcel in) {
+ final int[] localTimes = times;
+ for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
+ localTimes[i] = in.readInt();
}
-
- 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;
- }
- average = average/size;
- } else {
- minimum = maximum = median = 0;
+ }
+
+ 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');
}
}