Improve process tracking.
We now keep track of when each process is running, batched by the current memory status of the device. In addition, the stats are organized by package first, and then processes associated with each package inside of that. Finally, we also keep track of the overall time spent in each memory status. This should start to actually get us to some information we can reach some conclusions about. The total time spent in each memory status gives us some indication of how much we are running while memory is low; the new package organization batched by memory status lets us see what packages have what processes running when memory is low. Change-Id: I389d62d39d115a846126cf354e4c20070d8f1180
This commit is contained in:
@@ -1015,7 +1015,7 @@ public final class ActiveServices {
|
||||
Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);
|
||||
if (app != null && app.thread != null) {
|
||||
try {
|
||||
app.addPackage(r.appInfo.packageName);
|
||||
app.addPackage(r.appInfo.packageName, mAm.mProcessTracker);
|
||||
realStartServiceLocked(r, app);
|
||||
return null;
|
||||
} catch (RemoteException e) {
|
||||
|
||||
@@ -817,10 +817,10 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
int mNumNonCachedProcs = 0;
|
||||
|
||||
/**
|
||||
* Keep track of the number of cached procs, to balance oom adj
|
||||
* Keep track of the number of cached hidden procs, to balance oom adj
|
||||
* distribution between those and empty procs.
|
||||
*/
|
||||
int mNumCachedProcs = 0;
|
||||
int mNumCachedHiddenProcs = 0;
|
||||
|
||||
/**
|
||||
* Keep track of the number of service processes we last found, to
|
||||
@@ -2151,7 +2151,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
// come up (we have a pid but not yet its thread), so keep it.
|
||||
if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
|
||||
// If this is a new package in the process, add the package to the list
|
||||
app.addPackage(info.packageName);
|
||||
app.addPackage(info.packageName, mProcessTracker);
|
||||
return app;
|
||||
}
|
||||
|
||||
@@ -2206,7 +2206,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
}
|
||||
} else {
|
||||
// If this is a new package in the process, add the package to the list
|
||||
app.addPackage(info.packageName);
|
||||
app.addPackage(info.packageName, mProcessTracker);
|
||||
}
|
||||
|
||||
// If the system is not ready yet, then hold off on starting this
|
||||
@@ -3039,10 +3039,8 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
proc = p;
|
||||
break;
|
||||
}
|
||||
for (String str : p.pkgList) {
|
||||
if (str.equals(packageName)) {
|
||||
proc = p;
|
||||
}
|
||||
if (p.pkgList.containsKey(packageName)) {
|
||||
proc = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4014,7 +4012,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
if (userId != UserHandle.USER_ALL && app.userId != userId) {
|
||||
continue;
|
||||
}
|
||||
if (!app.pkgList.contains(packageName)) {
|
||||
if (!app.pkgList.containsKey(packageName)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -6220,7 +6218,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
if (proc.userId != tr.userId) {
|
||||
continue;
|
||||
}
|
||||
if (!proc.pkgList.contains(pkg)) {
|
||||
if (!proc.pkgList.containsKey(pkg)) {
|
||||
continue;
|
||||
}
|
||||
procs.add(proc);
|
||||
@@ -6577,7 +6575,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
if (DEBUG_MU)
|
||||
Slog.v(TAG_MU, "generateApplicationProvidersLocked, cpi.uid = " + cpr.uid);
|
||||
app.pubProviders.put(cpi.name, cpr);
|
||||
app.addPackage(cpi.applicationInfo.packageName);
|
||||
app.addPackage(cpi.applicationInfo.packageName, mProcessTracker);
|
||||
ensurePackageDexOpt(cpi.applicationInfo.packageName);
|
||||
}
|
||||
}
|
||||
@@ -7316,7 +7314,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
ps = stats.getProcessStatsLocked(info.uid, proc);
|
||||
}
|
||||
return new ProcessRecord(ps, thread, info, proc, uid,
|
||||
mProcessTracker.getStateLocked(info.processName, info.uid));
|
||||
mProcessTracker.getProcessStateLocked(info.packageName, uid, proc));
|
||||
}
|
||||
|
||||
final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated) {
|
||||
@@ -8895,7 +8893,8 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
int flags = process.info.flags;
|
||||
IPackageManager pm = AppGlobals.getPackageManager();
|
||||
sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
|
||||
for (String pkg : process.pkgList) {
|
||||
for (int ip=0; ip<process.pkgList.size(); ip++) {
|
||||
String pkg = process.pkgList.keyAt(ip);
|
||||
sb.append("Package: ").append(pkg);
|
||||
try {
|
||||
PackageInfo pi = pm.getPackageInfo(pkg, 0, UserHandle.getCallingUserId());
|
||||
@@ -9630,7 +9629,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
final int NA = procs.size();
|
||||
for (int ia=0; ia<NA; ia++) {
|
||||
ProcessRecord r = procs.valueAt(ia);
|
||||
if (dumpPackage != null && !r.pkgList.contains(dumpPackage)) {
|
||||
if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
|
||||
continue;
|
||||
}
|
||||
if (!needSep) {
|
||||
@@ -9653,7 +9652,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
boolean printed = false;
|
||||
for (int i=0; i<mIsolatedProcesses.size(); i++) {
|
||||
ProcessRecord r = mIsolatedProcesses.valueAt(i);
|
||||
if (dumpPackage != null && !r.pkgList.contains(dumpPackage)) {
|
||||
if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
|
||||
continue;
|
||||
}
|
||||
if (!printed) {
|
||||
@@ -9685,7 +9684,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
boolean printed = false;
|
||||
for (int i=0; i<mPidsSelfLocked.size(); i++) {
|
||||
ProcessRecord r = mPidsSelfLocked.valueAt(i);
|
||||
if (dumpPackage != null && !r.pkgList.contains(dumpPackage)) {
|
||||
if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
|
||||
continue;
|
||||
}
|
||||
if (!printed) {
|
||||
@@ -9708,7 +9707,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
ProcessRecord r = mPidsSelfLocked.get(
|
||||
mForegroundProcesses.valueAt(i).pid);
|
||||
if (dumpPackage != null && (r == null
|
||||
|| !r.pkgList.contains(dumpPackage))) {
|
||||
|| !r.pkgList.containsKey(dumpPackage))) {
|
||||
continue;
|
||||
}
|
||||
if (!printed) {
|
||||
@@ -9766,7 +9765,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
int puid = uids.keyAt(i);
|
||||
ProcessRecord r = mProcessNames.get(pname, puid);
|
||||
if (dumpPackage != null && (r == null
|
||||
|| !r.pkgList.contains(dumpPackage))) {
|
||||
|| !r.pkgList.containsKey(dumpPackage))) {
|
||||
continue;
|
||||
}
|
||||
if (!printed) {
|
||||
@@ -9797,7 +9796,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
int puid = uids.keyAt(i);
|
||||
ProcessRecord r = mProcessNames.get(pname, puid);
|
||||
if (dumpPackage != null && (r == null
|
||||
|| !r.pkgList.contains(dumpPackage))) {
|
||||
|| !r.pkgList.containsKey(dumpPackage))) {
|
||||
continue;
|
||||
}
|
||||
if (!printed) {
|
||||
@@ -9840,7 +9839,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
}
|
||||
}
|
||||
if (mHomeProcess != null && (dumpPackage == null
|
||||
|| mHomeProcess.pkgList.contains(dumpPackage))) {
|
||||
|| mHomeProcess.pkgList.containsKey(dumpPackage))) {
|
||||
if (needSep) {
|
||||
pw.println();
|
||||
needSep = false;
|
||||
@@ -9848,7 +9847,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
pw.println(" mHomeProcess: " + mHomeProcess);
|
||||
}
|
||||
if (mPreviousProcess != null && (dumpPackage == null
|
||||
|| mPreviousProcess.pkgList.contains(dumpPackage))) {
|
||||
|| mPreviousProcess.pkgList.containsKey(dumpPackage))) {
|
||||
if (needSep) {
|
||||
pw.println();
|
||||
needSep = false;
|
||||
@@ -9862,7 +9861,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
pw.println(sb);
|
||||
}
|
||||
if (mHeavyWeightProcess != null && (dumpPackage == null
|
||||
|| mHeavyWeightProcess.pkgList.contains(dumpPackage))) {
|
||||
|| mHeavyWeightProcess.pkgList.containsKey(dumpPackage))) {
|
||||
if (needSep) {
|
||||
pw.println();
|
||||
needSep = false;
|
||||
@@ -9959,7 +9958,8 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
pw.println(" mLaunchingActivity=" + getFocusedStack().mLaunchingActivity);
|
||||
pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
|
||||
pw.println(" mNumNonCachedProcs=" + mNumNonCachedProcs
|
||||
+ " mNumCachedProcs=" + mNumCachedProcs
|
||||
+ " (" + mLruProcesses.size() + " total)"
|
||||
+ " mNumCachedHiddenProcs=" + mNumCachedHiddenProcs
|
||||
+ " mNumServiceProcs=" + mNumServiceProcs
|
||||
+ " mNewNumServiceProcs=" + mNewNumServiceProcs);
|
||||
}
|
||||
@@ -10463,7 +10463,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
= new ArrayList<Pair<ProcessRecord, Integer>>(origList.size());
|
||||
for (int i=0; i<origList.size(); i++) {
|
||||
ProcessRecord r = origList.get(i);
|
||||
if (dumpPackage != null && !r.pkgList.contains(dumpPackage)) {
|
||||
if (dumpPackage != null && !r.pkgList.containsKey(dumpPackage)) {
|
||||
continue;
|
||||
}
|
||||
list.add(new Pair<ProcessRecord, Integer>(origList.get(i), i));
|
||||
@@ -11079,7 +11079,6 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
|
||||
final void dumpProcessTracker(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
synchronized (this) {
|
||||
pw.println("Process Stats:");
|
||||
mProcessTracker.dumpLocked(fd, pw, args);
|
||||
}
|
||||
}
|
||||
@@ -11787,7 +11786,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
+ ") when registering receiver " + receiver);
|
||||
}
|
||||
if (callerApp.info.uid != Process.SYSTEM_UID &&
|
||||
!callerApp.pkgList.contains(callerPackage)) {
|
||||
!callerApp.pkgList.containsKey(callerPackage)) {
|
||||
throw new SecurityException("Given caller package " + callerPackage
|
||||
+ " is not running in process " + callerApp);
|
||||
}
|
||||
@@ -13899,7 +13898,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
}
|
||||
|
||||
private final boolean updateOomAdjLocked(ProcessRecord app, int cachedAdj,
|
||||
int clientCachedAdj, int emptyAdj, ProcessRecord TOP_APP, boolean doingAll) {
|
||||
int clientCachedAdj, int emptyAdj, ProcessRecord TOP_APP, boolean doingAll, long now) {
|
||||
app.cachedAdj = cachedAdj;
|
||||
app.clientCachedAdj = clientCachedAdj;
|
||||
app.emptyAdj = emptyAdj;
|
||||
@@ -13936,9 +13935,10 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
TAG, "Set " + app.pid + " " + app.processName +
|
||||
" adj " + app.curAdj + ": " + app.adjType);
|
||||
app.setAdj = app.curAdj;
|
||||
if (app.setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
|
||||
app.tracker.setState(mProcessList.adjToTrackedState(app.setAdj),
|
||||
SystemClock.uptimeMillis());
|
||||
app.setAdjChanged = true;
|
||||
if (!doingAll) {
|
||||
app.setProcessTrackerState(TOP_APP, mProcessTracker.getMemFactor(),
|
||||
now, mProcessList);
|
||||
}
|
||||
} else {
|
||||
success = false;
|
||||
@@ -13997,7 +13997,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
mAdjSeq++;
|
||||
|
||||
boolean success = updateOomAdjLocked(app, app.cachedAdj, app.clientCachedAdj,
|
||||
app.emptyAdj, TOP_APP, false);
|
||||
app.emptyAdj, TOP_APP, false, SystemClock.uptimeMillis());
|
||||
final boolean nowCached = app.curAdj >= ProcessList.CACHED_APP_MIN_ADJ
|
||||
&& app.curAdj <= ProcessList.CACHED_APP_MAX_ADJ;
|
||||
if (nowCached != wasCached) {
|
||||
@@ -14011,7 +14011,8 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
final void updateOomAdjLocked() {
|
||||
final ActivityRecord TOP_ACT = resumedAppLocked();
|
||||
final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
|
||||
final long oldTime = SystemClock.uptimeMillis() - ProcessList.MAX_EMPTY_TIME;
|
||||
final long now = SystemClock.uptimeMillis();
|
||||
final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
|
||||
|
||||
if (false) {
|
||||
RuntimeException e = new RuntimeException();
|
||||
@@ -14040,7 +14041,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
// them.
|
||||
int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
|
||||
- ProcessList.CACHED_APP_MIN_ADJ + 1) / 2;
|
||||
int numEmptyProcs = mLruProcesses.size()- mNumNonCachedProcs - mNumCachedProcs;
|
||||
int numEmptyProcs = mLruProcesses.size()- mNumNonCachedProcs - mNumCachedHiddenProcs;
|
||||
if (numEmptyProcs > cachedProcessLimit) {
|
||||
// If there are more empty processes than our limit on cached
|
||||
// processes, then use the cached process limit for the factor.
|
||||
@@ -14052,7 +14053,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
}
|
||||
int emptyFactor = numEmptyProcs/numSlots;
|
||||
if (emptyFactor < 1) emptyFactor = 1;
|
||||
int cachedFactor = (mNumCachedProcs > 0 ? mNumCachedProcs : 1)/numSlots;
|
||||
int cachedFactor = (mNumCachedHiddenProcs > 0 ? mNumCachedHiddenProcs : 1)/numSlots;
|
||||
if (cachedFactor < 1) cachedFactor = 1;
|
||||
int stepCached = 0;
|
||||
int stepEmpty = 0;
|
||||
@@ -14061,7 +14062,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
int numTrimming = 0;
|
||||
|
||||
mNumNonCachedProcs = 0;
|
||||
mNumCachedProcs = 0;
|
||||
mNumCachedHiddenProcs = 0;
|
||||
|
||||
// First update the OOM adjustment for each of the
|
||||
// application processes based on their current state.
|
||||
@@ -14071,16 +14072,20 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
|
||||
int nextEmptyAdj = curEmptyAdj+2;
|
||||
int curClientCachedAdj = curEmptyAdj;
|
||||
boolean changed = false;
|
||||
while (i > 0) {
|
||||
i--;
|
||||
ProcessRecord app = mLruProcesses.get(i);
|
||||
//Slog.i(TAG, "OOM " + app + ": cur cached=" + curCachedAdj);
|
||||
updateOomAdjLocked(app, curCachedAdj, curClientCachedAdj, curEmptyAdj, TOP_APP, true);
|
||||
app.setAdjChanged = false;
|
||||
updateOomAdjLocked(app, curCachedAdj, curClientCachedAdj, curEmptyAdj, TOP_APP,
|
||||
true, now);
|
||||
changed |= app.setAdjChanged;
|
||||
if (!app.killedBackground) {
|
||||
if (app.curRawAdj == curCachedAdj && app.hasActivities) {
|
||||
// This process was assigned as a cached process... step the
|
||||
// cached level.
|
||||
mNumCachedProcs++;
|
||||
mNumCachedHiddenProcs++;
|
||||
if (curCachedAdj != nextCachedAdj) {
|
||||
stepCached++;
|
||||
if (stepCached >= cachedFactor) {
|
||||
@@ -14188,6 +14193,7 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
// are managing to keep around is less than half the maximum we desire;
|
||||
// if we are keeping a good number around, we'll let them use whatever
|
||||
// memory they want.
|
||||
int memFactor = ProcessTracker.STATE_MEM_FACTOR_NORMAL_ADJ;
|
||||
if (numCached <= ProcessList.TRIM_CACHED_APPS
|
||||
&& numEmpty <= ProcessList.TRIM_EMPTY_APPS) {
|
||||
final int numCachedAndEmpty = numCached + numEmpty;
|
||||
@@ -14201,10 +14207,13 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
int fgTrimLevel;
|
||||
if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
|
||||
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
|
||||
memFactor = ProcessTracker.STATE_MEM_FACTOR_CRITIAL_ADJ;
|
||||
} else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
|
||||
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
|
||||
memFactor = ProcessTracker.STATE_MEM_FACTOR_LOW_ADJ;
|
||||
} else {
|
||||
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
|
||||
memFactor = ProcessTracker.STATE_MEM_FACTOR_MODERATE_ADJ;
|
||||
}
|
||||
int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
|
||||
for (i=0; i<N; i++) {
|
||||
@@ -14303,6 +14312,21 @@ public final class ActivityManagerService extends ActivityManagerNative
|
||||
// be in a consistent state at this point.
|
||||
mStackSupervisor.scheduleDestroyAllActivities(null, "always-finish");
|
||||
}
|
||||
|
||||
boolean allChanged = mProcessTracker.setMemFactor(memFactor, !mSleeping, now);
|
||||
if (changed || allChanged) {
|
||||
memFactor = mProcessTracker.getMemFactor();
|
||||
for (i=mLruProcesses.size()-1; i>=0; i--) {
|
||||
ProcessRecord app = mLruProcesses.get(i);
|
||||
if (allChanged || app.setAdjChanged) {
|
||||
app.setProcessTrackerState(TOP_APP, memFactor, now, mProcessList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG_OOM_ADJ) {
|
||||
Slog.d(TAG, "Did OOM ADJ in " + (SystemClock.uptimeMillis()-now) + "ms");
|
||||
}
|
||||
}
|
||||
|
||||
final void trimApplications() {
|
||||
|
||||
@@ -987,7 +987,7 @@ public final class ActivityStackSupervisor {
|
||||
|
||||
if (app != null && app.thread != null) {
|
||||
try {
|
||||
app.addPackage(r.info.packageName);
|
||||
app.addPackage(r.info.packageName, mService.mProcessTracker);
|
||||
realStartActivityLocked(r, app, andResume, checkConfig);
|
||||
return;
|
||||
} catch (RemoteException e) {
|
||||
|
||||
@@ -795,7 +795,7 @@ public final class BroadcastQueue {
|
||||
info.activityInfo.applicationInfo.uid);
|
||||
if (app != null && app.thread != null) {
|
||||
try {
|
||||
app.addPackage(info.activityInfo.packageName);
|
||||
app.addPackage(info.activityInfo.packageName, mService.mProcessTracker);
|
||||
processCurBroadcastLocked(r, app);
|
||||
return;
|
||||
} catch (RemoteException e) {
|
||||
|
||||
@@ -300,7 +300,7 @@ public final class CompatModePackages {
|
||||
// Tell all processes that loaded this package about the change.
|
||||
for (int i=mService.mLruProcesses.size()-1; i>=0; i--) {
|
||||
ProcessRecord app = mService.mLruProcesses.get(i);
|
||||
if (!app.pkgList.contains(packageName)) {
|
||||
if (!app.pkgList.containsKey(packageName)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
|
||||
@@ -244,7 +244,7 @@ final class ProcessList {
|
||||
}
|
||||
|
||||
int adjToTrackedState(int adj) {
|
||||
return mAdjToTrackedState[adj];
|
||||
return adj >= FOREGROUND_APP_ADJ ? mAdjToTrackedState[adj] : ProcessTracker.STATE_NOTHING;
|
||||
}
|
||||
|
||||
private void writeFile(String path, String data) {
|
||||
|
||||
@@ -51,9 +51,10 @@ final class ProcessRecord {
|
||||
final int uid; // uid of process; may be different from 'info' if isolated
|
||||
final int userId; // user of process.
|
||||
final String processName; // name of the process
|
||||
final ProcessTracker.ProcessState tracker; // tracking execution of process
|
||||
final ProcessTracker.ProcessState baseProcessTracker;
|
||||
// List of packages running in the process
|
||||
final HashSet<String> pkgList = new HashSet<String>();
|
||||
final ArrayMap<String, ProcessTracker.ProcessState> pkgList
|
||||
= new ArrayMap<String, ProcessTracker.ProcessState>();
|
||||
IApplicationThread thread; // the actual proc... may be null only if
|
||||
// 'persistent' is true (in which case we
|
||||
// are in the process of launching the app)
|
||||
@@ -87,6 +88,7 @@ final class ProcessRecord {
|
||||
boolean hasAboveClient; // Bound using BIND_ABOVE_CLIENT, so want to be lower
|
||||
boolean bad; // True if disabled in the bad process list
|
||||
boolean killedBackground; // True when proc has been killed due to too many bg
|
||||
boolean setAdjChanged; // Keep track of whether we changed 'setAdj'.
|
||||
String waitingToKill; // Process is waiting to be killed when in the bg; reason
|
||||
IBinder forcingToForeground;// Token that is forcing this process to be foreground
|
||||
int adjSeq; // Sequence id for identifying oom_adj assignment cycles
|
||||
@@ -327,15 +329,15 @@ final class ProcessRecord {
|
||||
|
||||
ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, IApplicationThread _thread,
|
||||
ApplicationInfo _info, String _processName, int _uid,
|
||||
ProcessTracker.ProcessState _tracker) {
|
||||
ProcessTracker.ProcessState tracker) {
|
||||
batteryStats = _batteryStats;
|
||||
info = _info;
|
||||
isolated = _info.uid != _uid;
|
||||
uid = _uid;
|
||||
userId = UserHandle.getUserId(_uid);
|
||||
processName = _processName;
|
||||
tracker = _tracker;
|
||||
pkgList.add(_info.packageName);
|
||||
baseProcessTracker = tracker;
|
||||
pkgList.put(_info.packageName, tracker);
|
||||
thread = _thread;
|
||||
maxAdj = ProcessList.CACHED_APP_MAX_ADJ;
|
||||
cachedAdj = clientCachedAdj = emptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
|
||||
@@ -437,20 +439,33 @@ final class ProcessRecord {
|
||||
/*
|
||||
* Return true if package has been added false if not
|
||||
*/
|
||||
public boolean addPackage(String pkg) {
|
||||
if (!pkgList.contains(pkg)) {
|
||||
pkgList.add(pkg);
|
||||
public boolean addPackage(String pkg, ProcessTracker tracker) {
|
||||
if (!pkgList.containsKey(pkg)) {
|
||||
pkgList.put(pkg, tracker.getProcessStateLocked(pkg, info.uid, processName));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public void setProcessTrackerState(ProcessRecord TOP_APP, int memFactor, long now,
|
||||
ProcessList plist) {
|
||||
int state = this == TOP_APP ? ProcessTracker.STATE_TOP
|
||||
: plist.adjToTrackedState(setAdj);
|
||||
for (int ip=pkgList.size()-1; ip>=0; ip--) {
|
||||
pkgList.valueAt(ip).setState(state, memFactor, now);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete all packages from list except the package indicated in info
|
||||
*/
|
||||
public void resetPackageList() {
|
||||
long now = SystemClock.uptimeMillis();
|
||||
for (int i=0; i<pkgList.size(); i++) {
|
||||
pkgList.valueAt(i).setState(ProcessTracker.STATE_NOTHING, 0, now);
|
||||
}
|
||||
pkgList.clear();
|
||||
pkgList.add(info.packageName);
|
||||
pkgList.put(info.packageName, baseProcessTracker);
|
||||
}
|
||||
|
||||
public String[] getPackageList() {
|
||||
@@ -459,7 +474,9 @@ final class ProcessRecord {
|
||||
return null;
|
||||
}
|
||||
String list[] = new String[size];
|
||||
pkgList.toArray(list);
|
||||
for (int i=0; i<pkgList.size(); i++) {
|
||||
list[i] = pkgList.keyAt(i);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,15 @@ public final class ProcessTracker {
|
||||
public static final int STATE_HOME = 6;
|
||||
public static final int STATE_PREVIOUS = 7;
|
||||
public static final int STATE_CACHED = 8;
|
||||
public static final int STATE_SCREEN_ON_MOD = STATE_CACHED+1;
|
||||
public static final int STATE_MEM_FACTOR_MOD = STATE_CACHED+1;
|
||||
public static final int STATE_MEM_FACTOR_NORMAL_ADJ = 0;
|
||||
public static final int STATE_MEM_FACTOR_MODERATE_ADJ = STATE_MEM_FACTOR_MOD;
|
||||
public static final int STATE_MEM_FACTOR_LOW_ADJ = STATE_MEM_FACTOR_MOD*2;
|
||||
public static final int STATE_MEM_FACTOR_CRITIAL_ADJ = STATE_MEM_FACTOR_MOD*3;
|
||||
public static final int STATE_MEM_FACTOR_COUNT = STATE_MEM_FACTOR_MOD*4;
|
||||
public static final int STATE_SCREEN_ON_MOD = STATE_MEM_FACTOR_COUNT;
|
||||
public static final int STATE_SCREEN_OFF_ADJ = 0;
|
||||
public static final int STATE_SCREEN_ON_ADJ = STATE_SCREEN_ON_MOD;
|
||||
public static final int STATE_COUNT = STATE_SCREEN_ON_MOD*2;
|
||||
|
||||
static String[] STATE_NAMES = new String[] {
|
||||
@@ -45,21 +53,44 @@ public final class ProcessTracker {
|
||||
};
|
||||
|
||||
public static final class ProcessState {
|
||||
final long[] mTimes = new long[STATE_COUNT];
|
||||
final long[] mDurations = new long[STATE_COUNT];
|
||||
int mCurState = STATE_NOTHING;
|
||||
long mStartTime;
|
||||
|
||||
public void setState(int state, long now) {
|
||||
if (mCurState != STATE_NOTHING) {
|
||||
mTimes[mCurState] += now - mStartTime;
|
||||
public void setState(int state, int memFactor, long now) {
|
||||
if (state != STATE_NOTHING) {
|
||||
state += memFactor;
|
||||
}
|
||||
mCurState = state;
|
||||
mStartTime = now;
|
||||
if (mCurState != state) {
|
||||
if (mCurState != STATE_NOTHING) {
|
||||
mDurations[mCurState] += now - mStartTime;
|
||||
}
|
||||
mCurState = state;
|
||||
mStartTime = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ServiceState {
|
||||
long mStartedDuration;
|
||||
long mStartedTime;
|
||||
}
|
||||
|
||||
public static final class PackageState {
|
||||
final ArrayMap<String, ProcessState> mProcesses = new ArrayMap<String, ProcessState>();
|
||||
final ArrayMap<String, ServiceState> mServices = new ArrayMap<String, ServiceState>();
|
||||
final int mUid;
|
||||
|
||||
public PackageState(int uid) {
|
||||
mUid = uid;
|
||||
}
|
||||
}
|
||||
|
||||
static final class State {
|
||||
final ProcessMap<ProcessState> mProcesses = new ProcessMap<ProcessState>();
|
||||
final ProcessMap<PackageState> mPackages = new ProcessMap<PackageState>();
|
||||
final long[] mMemFactorDurations = new long[STATE_COUNT/STATE_MEM_FACTOR_MOD];
|
||||
int mMemFactor = STATE_NOTHING;
|
||||
long mStartTime;
|
||||
}
|
||||
|
||||
final State mState = new State();
|
||||
@@ -67,44 +98,198 @@ public final class ProcessTracker {
|
||||
public ProcessTracker() {
|
||||
}
|
||||
|
||||
public ProcessState getStateLocked(String name, int uid) {
|
||||
ProcessState ps = mState.mProcesses.get(name, uid);
|
||||
private PackageState getPackageStateLocked(String packageName, int uid) {
|
||||
PackageState as = mState.mPackages.get(packageName, uid);
|
||||
if (as != null) {
|
||||
return as;
|
||||
}
|
||||
as = new PackageState(uid);
|
||||
mState.mPackages.put(packageName, uid, as);
|
||||
return as;
|
||||
}
|
||||
|
||||
public ProcessState getProcessStateLocked(String packageName, int uid, String processName) {
|
||||
final PackageState as = getPackageStateLocked(packageName, uid);
|
||||
ProcessState ps = as.mProcesses.get(processName);
|
||||
if (ps != null) {
|
||||
return ps;
|
||||
}
|
||||
ps = new ProcessState();
|
||||
mState.mProcesses.put(name, uid, ps);
|
||||
as.mProcesses.put(processName, ps);
|
||||
return ps;
|
||||
}
|
||||
|
||||
public ServiceState getServiceStateLocked(String packageName, int uid, String className) {
|
||||
final PackageState as = getPackageStateLocked(packageName, uid);
|
||||
ServiceState ss = as.mServices.get(className);
|
||||
if (ss != null) {
|
||||
return ss;
|
||||
}
|
||||
ss = new ServiceState();
|
||||
as.mServices.put(className, ss);
|
||||
return ss;
|
||||
}
|
||||
|
||||
public boolean setMemFactor(int memFactor, boolean screenOn, long now) {
|
||||
if (screenOn) {
|
||||
memFactor += STATE_SCREEN_ON_MOD;
|
||||
}
|
||||
if (memFactor != mState.mMemFactor) {
|
||||
if (mState.mMemFactor != STATE_NOTHING) {
|
||||
mState.mMemFactorDurations[mState.mMemFactor/STATE_MEM_FACTOR_MOD]
|
||||
+= now - mState.mStartTime;
|
||||
}
|
||||
mState.mMemFactor = memFactor;
|
||||
mState.mStartTime = now;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getMemFactor() {
|
||||
return mState.mMemFactor != STATE_NOTHING ? mState.mMemFactor : 0;
|
||||
}
|
||||
|
||||
private void printScreenLabel(PrintWriter pw, int offset) {
|
||||
switch (offset) {
|
||||
case STATE_NOTHING:
|
||||
pw.print(" ");
|
||||
break;
|
||||
case STATE_SCREEN_OFF_ADJ:
|
||||
pw.print("Screen Off / ");
|
||||
break;
|
||||
case STATE_SCREEN_ON_ADJ:
|
||||
pw.print("Screen On / ");
|
||||
break;
|
||||
default:
|
||||
pw.print("?????????? / ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void printMemLabel(PrintWriter pw, int offset) {
|
||||
switch (offset) {
|
||||
case STATE_NOTHING:
|
||||
pw.print(" ");
|
||||
break;
|
||||
case STATE_MEM_FACTOR_NORMAL_ADJ:
|
||||
pw.print("Norm / ");
|
||||
break;
|
||||
case STATE_MEM_FACTOR_MODERATE_ADJ:
|
||||
pw.print("Mod / ");
|
||||
break;
|
||||
case STATE_MEM_FACTOR_LOW_ADJ:
|
||||
pw.print("Low / ");
|
||||
break;
|
||||
case STATE_MEM_FACTOR_CRITIAL_ADJ:
|
||||
pw.print("Crit / ");
|
||||
break;
|
||||
default:
|
||||
pw.print("???? / ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
final long now = SystemClock.uptimeMillis();
|
||||
ArrayMap<String, SparseArray<ProcessState>> pmap = mState.mProcesses.getMap();
|
||||
ArrayMap<String, SparseArray<PackageState>> pmap = mState.mPackages.getMap();
|
||||
pw.println("Process Stats:");
|
||||
for (int ip=0; ip<pmap.size(); ip++) {
|
||||
String procName = pmap.keyAt(ip);
|
||||
SparseArray<ProcessState> procs = pmap.valueAt(ip);
|
||||
SparseArray<PackageState> procs = pmap.valueAt(ip);
|
||||
for (int iu=0; iu<procs.size(); iu++) {
|
||||
int uid = procs.keyAt(iu);
|
||||
ProcessState state = procs.valueAt(iu);
|
||||
PackageState state = procs.valueAt(iu);
|
||||
pw.print(" "); pw.print(procName); pw.print(" / "); pw.print(uid); pw.println(":");
|
||||
long totalTime = 0;
|
||||
for (int is=0; is<STATE_NAMES.length; is++) {
|
||||
long time = state.mTimes[is];
|
||||
if (state.mCurState == is) {
|
||||
time += now - state.mStartTime;
|
||||
for (int iproc=0; iproc<state.mProcesses.size(); iproc++) {
|
||||
pw.print(" Process ");
|
||||
pw.print(state.mProcesses.keyAt(iproc));
|
||||
pw.println(":");
|
||||
long totalTime = 0;
|
||||
ProcessState proc = state.mProcesses.valueAt(iproc);
|
||||
int printedScreen = -1;
|
||||
for (int iscreen=0; iscreen<STATE_COUNT; iscreen+=STATE_SCREEN_ON_MOD) {
|
||||
int printedMem = -1;
|
||||
for (int imem=0; imem<STATE_MEM_FACTOR_COUNT; imem+=STATE_MEM_FACTOR_MOD) {
|
||||
for (int is=0; is<STATE_NAMES.length; is++) {
|
||||
int bucket = is+imem+iscreen;
|
||||
long time = proc.mDurations[bucket];
|
||||
String running = "";
|
||||
if (proc.mCurState == bucket) {
|
||||
time += now - proc.mStartTime;
|
||||
running = " (running)";
|
||||
}
|
||||
if (time != 0) {
|
||||
pw.print(" ");
|
||||
printScreenLabel(pw, printedScreen != iscreen
|
||||
? iscreen : STATE_NOTHING);
|
||||
printedScreen = iscreen;
|
||||
printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
|
||||
printedMem = imem;
|
||||
pw.print(STATE_NAMES[is]); pw.print(": ");
|
||||
TimeUtils.formatDuration(time, pw); pw.println(running);
|
||||
totalTime += time;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (time != 0) {
|
||||
pw.print(" "); pw.print(STATE_NAMES[is]); pw.print(": ");
|
||||
TimeUtils.formatDuration(time, pw); pw.println();
|
||||
totalTime += time;
|
||||
if (totalTime != 0) {
|
||||
pw.print(" ");
|
||||
printScreenLabel(pw, STATE_NOTHING);
|
||||
printMemLabel(pw, STATE_NOTHING);
|
||||
pw.print("TOTAL : ");
|
||||
TimeUtils.formatDuration(totalTime, pw);
|
||||
pw.println();
|
||||
}
|
||||
}
|
||||
if (totalTime != 0) {
|
||||
pw.print(" TOTAL : ");
|
||||
TimeUtils.formatDuration(totalTime, pw);
|
||||
pw.println();
|
||||
for (int isvc=0; isvc<state.mServices.size(); isvc++) {
|
||||
pw.print(" Service ");
|
||||
pw.print(state.mServices.keyAt(isvc));
|
||||
pw.println(":");
|
||||
ServiceState svc = state.mServices.valueAt(isvc);
|
||||
long time = svc.mStartedDuration;
|
||||
if (svc.mStartedTime >= 0) {
|
||||
time += now - svc.mStartedTime;
|
||||
}
|
||||
if (time != 0) {
|
||||
pw.print(" Started: ");
|
||||
TimeUtils.formatDuration(time, pw); pw.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pw.println();
|
||||
pw.println("Run time Stats:");
|
||||
long totalTime = 0;
|
||||
int printedScreen = -1;
|
||||
for (int iscreen=0; iscreen<STATE_COUNT; iscreen+=STATE_SCREEN_ON_MOD) {
|
||||
int printedMem = -1;
|
||||
for (int imem=0; imem<STATE_MEM_FACTOR_COUNT; imem+=STATE_MEM_FACTOR_MOD) {
|
||||
int bucket = imem+iscreen;
|
||||
long time = mState.mMemFactorDurations[bucket/STATE_MEM_FACTOR_MOD];
|
||||
String running = "";
|
||||
if (mState.mMemFactor == bucket) {
|
||||
time += now - mState.mStartTime;
|
||||
running = " (running)";
|
||||
}
|
||||
if (time != 0) {
|
||||
pw.print(" ");
|
||||
printScreenLabel(pw, printedScreen != iscreen
|
||||
? iscreen : STATE_NOTHING);
|
||||
printedScreen = iscreen;
|
||||
printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
|
||||
printedMem = imem;
|
||||
TimeUtils.formatDuration(time, pw); pw.println(running);
|
||||
totalTime += time;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (totalTime != 0) {
|
||||
pw.print(" ");
|
||||
printScreenLabel(pw, STATE_NOTHING);
|
||||
pw.print("TOTAL: ");
|
||||
TimeUtils.formatDuration(totalTime, pw);
|
||||
pw.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user