diff options
author | Dianne Hackborn <hackbod@google.com> | 2009-04-13 18:42:49 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2009-04-13 18:42:49 -0700 |
commit | f210d6b75e2c0fe60b90c074ff9f615c1137f23e (patch) | |
tree | 112240b6d4c3d2d1f78e7badde174cbe11d1f31b | |
parent | 7680d67dc7445ba65a4fc4307afe24b20b333a52 (diff) | |
download | frameworks_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.
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'); } } |