diff options
author | Dianne Hackborn <hackbod@google.com> | 2013-09-09 09:44:05 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2013-09-09 09:49:52 -0700 |
commit | be4c1d74a758f40de25e796a991ccfd1fe356857 (patch) | |
tree | 8597f656b9de4c244c38e01a07dd2e35f03e06e4 /services | |
parent | c8fb093a8970b78084f2b4505fc283ac9e24317b (diff) | |
download | frameworks_base-be4c1d74a758f40de25e796a991ccfd1fe356857.zip frameworks_base-be4c1d74a758f40de25e796a991ccfd1fe356857.tar.gz frameworks_base-be4c1d74a758f40de25e796a991ccfd1fe356857.tar.bz2 |
Fix issue #10671878: Proc stats needs to remove old data structures
We now keep track of which process and service states are actively
in use, and remove any that are not in use during a commit. The
activity manager needed to be tweaked to report this data, and ensure
it does not try to operate on one of these structures when not in
use.
Also some other fixes:
- We now keep track of process names associated with services, for
display in the UI.
- Keep track of total run time for each service, also for UI.
- The parceled format is more efficient, not storing duplicates of
process/package names, and writing times as ints when possible.
- Reduced commit period from 1 day to 12 hours, so that our UI can
be a little closer at its attempt to display the stats over 1 day.
Change-Id: Ifeda0ffe963a7b49d8eb2a3f6923f3a5e71a4e43
Diffstat (limited to 'services')
4 files changed, 82 insertions, 25 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 75cf5d0..fad3fc6 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -1574,12 +1574,12 @@ public final class ActivityManagerService extends ActivityManagerNative mSystemThread.installSystemApplicationInfo(info); synchronized (mSelf) { - ProcessRecord app = mSelf.newProcessRecordLocked( - mSystemThread.getApplicationThread(), info, + ProcessRecord app = mSelf.newProcessRecordLocked(info, info.processName, false); app.persistent = true; app.pid = MY_PID; app.maxAdj = ProcessList.SYSTEM_ADJ; + app.makeActive(mSystemThread.getApplicationThread(), mSelf.mProcessStats); mSelf.mProcessNames.put(app.processName, app.uid, app); synchronized (mSelf.mPidsSelfLocked) { mSelf.mPidsSelfLocked.put(app.pid, app); @@ -2282,7 +2282,7 @@ public final class ActivityManagerService extends ActivityManagerNative } if (app == null) { - app = newProcessRecordLocked(null, info, processName, isolated); + app = newProcessRecordLocked(info, processName, isolated); if (app == null) { Slog.w(TAG, "Failed making new process record for " + processName + "/" + info.uid + " isolated=" + isolated); @@ -4487,7 +4487,7 @@ public final class ActivityManagerService extends ActivityManagerNative EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName); - app.thread = thread; + app.makeActive(thread, mProcessStats); app.curAdj = app.setAdj = -100; app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT; app.forcingToForeground = null; @@ -7544,8 +7544,8 @@ public final class ActivityManagerService extends ActivityManagerNative // GLOBAL MANAGEMENT // ========================================================= - final ProcessRecord newProcessRecordLocked(IApplicationThread thread, - ApplicationInfo info, String customProcess, boolean isolated) { + final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess, + boolean isolated) { String proc = customProcess != null ? customProcess : info.processName; BatteryStatsImpl.Uid.Proc ps = null; BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); @@ -7573,8 +7573,7 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized (stats) { ps = stats.getProcessStatsLocked(info.uid, proc); } - return new ProcessRecord(ps, thread, info, proc, uid, - mProcessStats.getProcessStateLocked(info.packageName, info.uid, proc)); + return new ProcessRecord(ps, info, proc, uid); } final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated) { @@ -7586,7 +7585,7 @@ public final class ActivityManagerService extends ActivityManagerNative } if (app == null) { - app = newProcessRecordLocked(null, info, null, isolated); + app = newProcessRecordLocked(info, null, isolated); mProcessNames.put(info.processName, app.uid, app); if (isolated) { mIsolatedProcesses.put(app.uid, app); @@ -11788,7 +11787,7 @@ public final class ActivityManagerService extends ActivityManagerNative app.resetPackageList(mProcessStats); app.unlinkDeathRecipient(); - app.thread = null; + app.makeInactive(mProcessStats); app.forcingToForeground = null; app.foregroundServices = false; app.foregroundActivities = false; @@ -14692,7 +14691,9 @@ public final class ActivityManagerService extends ActivityManagerNative } private final void setProcessTrackerState(ProcessRecord proc, int memFactor, long now) { - proc.baseProcessTracker.setState(proc.repProcState, memFactor, now, proc.pkgList); + if (proc.thread != null) { + proc.baseProcessTracker.setState(proc.repProcState, memFactor, now, proc.pkgList); + } } private final boolean updateOomAdjLocked(ProcessRecord app, int cachedAdj, diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java index f1a030e..283d122 100644 --- a/services/java/com/android/server/am/ProcessRecord.java +++ b/services/java/com/android/server/am/ProcessRecord.java @@ -52,13 +52,13 @@ 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 ProcessStats.ProcessState baseProcessTracker; // List of packages running in the process final ArrayMap<String, ProcessStats.ProcessState> pkgList = new ArrayMap<String, ProcessStats.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) + ProcessStats.ProcessState baseProcessTracker; int pid; // The process of this application; 0 if none boolean starting; // True if the process is being started long lastActivityTime; // For managing the LRU list @@ -349,18 +349,15 @@ final class ProcessRecord { } } - ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, IApplicationThread _thread, - ApplicationInfo _info, String _processName, int _uid, - ProcessStats.ProcessState tracker) { + ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, ApplicationInfo _info, + String _processName, int _uid) { batteryStats = _batteryStats; info = _info; isolated = _info.uid != _uid; uid = _uid; userId = UserHandle.getUserId(_uid); processName = _processName; - baseProcessTracker = tracker; - pkgList.put(_info.packageName, tracker); - thread = _thread; + pkgList.put(_info.packageName, null); maxAdj = ProcessList.UNKNOWN_ADJ; curRawAdj = setRawAdj = -100; curAdj = setAdj = -100; @@ -374,7 +371,53 @@ final class ProcessRecord { shortStringName = null; stringName = null; } - + + public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) { + if (thread == null) { + final ProcessStats.ProcessState origBase = baseProcessTracker; + if (origBase != null) { + origBase.setState(ProcessStats.STATE_NOTHING, + tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList); + origBase.makeInactive(); + } + baseProcessTracker = tracker.getProcessStateLocked(info.packageName, info.uid, + processName); + baseProcessTracker.makeActive(); + for (int i=0; i<pkgList.size(); i++) { + ProcessStats.ProcessState ps = pkgList.valueAt(i); + if (ps != null && ps != origBase) { + ps.makeInactive(); + } + ps = tracker.getProcessStateLocked(pkgList.keyAt(i), info.uid, processName); + if (ps != baseProcessTracker) { + ps.makeActive(); + } + pkgList.setValueAt(i, ps); + } + } + thread = _thread; + } + + public void makeInactive(ProcessStatsService tracker) { + if (thread != null) { + thread = null; + final ProcessStats.ProcessState origBase = baseProcessTracker; + if (origBase != null) { + origBase.setState(ProcessStats.STATE_NOTHING, + tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList); + origBase.makeInactive(); + } + baseProcessTracker = null; + for (int i=0; i<pkgList.size(); i++) { + ProcessStats.ProcessState ps = pkgList.valueAt(i); + if (ps != null && ps != origBase) { + ps.makeInactive(); + } + pkgList.setValueAt(i, null); + } + } + } + /** * This method returns true if any of the activities within the process record are interesting * to the user. See HistoryRecord.isInterestingToUserLocked() @@ -518,10 +561,22 @@ final class ProcessRecord { long now = SystemClock.uptimeMillis(); baseProcessTracker.setState(ProcessStats.STATE_NOTHING, tracker.getMemFactorLocked(), now, pkgList); - if (pkgList.size() != 1) { + final int N = pkgList.size(); + if (N != 1) { + for (int i=0; i<N; i++) { + ProcessStats.ProcessState ps = pkgList.valueAt(i); + if (ps != null && ps != baseProcessTracker) { + ps.makeInactive(); + } + + } pkgList.clear(); - pkgList.put(info.packageName, tracker.getProcessStateLocked( - info.packageName, info.uid, processName)); + ProcessStats.ProcessState ps = tracker.getProcessStateLocked( + info.packageName, info.uid, processName); + pkgList.put(info.packageName, ps); + if (thread != null && ps != baseProcessTracker) { + ps.makeActive(); + } } } diff --git a/services/java/com/android/server/am/ProcessStatsService.java b/services/java/com/android/server/am/ProcessStatsService.java index 43ae46f..c180f6e 100644 --- a/services/java/com/android/server/am/ProcessStatsService.java +++ b/services/java/com/android/server/am/ProcessStatsService.java @@ -54,12 +54,12 @@ public final class ProcessStatsService extends IProcessStats.Stub { // exists in and the offset into the array to find it. The constants below // define the encoding of that data in an integer. - static final int MAX_HISTORIC_STATES = 4; // Maximum number of historic states we will keep. + static final int MAX_HISTORIC_STATES = 6; // Maximum number of historic states we will keep. static final String STATE_FILE_PREFIX = "state-"; // Prefix to use for state filenames. static final String STATE_FILE_SUFFIX = ".bin"; // Suffix to use for state filenames. static final String STATE_FILE_CHECKIN_SUFFIX = ".ci"; // State files that have checked in. static long WRITE_PERIOD = 30*60*1000; // Write file every 30 minutes or so. - static long COMMIT_PERIOD = 24*60*60*1000; // Commit current stats every day. + static long COMMIT_PERIOD = 12*60*60*1000; // Commit current stats every 12 hours. final ActivityManagerService mAm; final File mBaseDir; @@ -132,7 +132,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { ArrayMap<String, ProcessStats.ServiceState> services = pkg.mServices; for (int k=0; k<services.size(); k++) { ProcessStats.ServiceState service = services.valueAt(k); - if (service.isActive()) { + if (service.isInUse()) { if (service.mStartedState != ProcessStats.STATE_NOTHING) { service.setStarted(true, memFactor, now); } diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java index 39756c3..8293bb8 100644 --- a/services/java/com/android/server/am/ServiceRecord.java +++ b/services/java/com/android/server/am/ServiceRecord.java @@ -318,6 +318,7 @@ final class ServiceRecord extends Binder { if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) { tracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName, serviceInfo.applicationInfo.uid, serviceInfo.processName, serviceInfo.name); + tracker.makeActive(); } return tracker; } |