diff options
6 files changed, 295 insertions, 199 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 5296f752c0f8..5555650d9be2 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1962,7 +1962,7 @@ public class ActivityManagerService extends IActivityManager.Stub nativeTotalPss += Debug.getPss(stats.get(j).pid, null, null); } memInfo.readMemInfo(); - synchronized (ActivityManagerService.this) { + synchronized (mProcessStats.mLock) { if (DEBUG_PSS) Slog.d(TAG_PSS, "Collected native and kernel memory in " + (SystemClock.uptimeMillis()-start) + "ms"); final long cachedKb = memInfo.getCachedSizeKb(); @@ -7054,9 +7054,7 @@ public class ActivityManagerService extends IActivityManager.Stub mUsageStatsService.prepareShutdown(); } mBatteryStatsService.shutdown(); - synchronized (this) { - mProcessStats.shutdownLocked(); - } + mProcessStats.shutdown(); return timedout; } @@ -12358,7 +12356,7 @@ public class ActivityManagerService extends IActivityManager.Stub MemInfoReader memInfo = new MemInfoReader(); memInfo.readMemInfo(); if (nativeProcTotalPss > 0) { - synchronized (this) { + synchronized (mProcessStats.mLock) { final long cachedKb = memInfo.getCachedSizeKb(); final long freeKb = memInfo.getFreeSizeKb(); final long zramKb = memInfo.getZramTotalSizeKb(); @@ -12940,7 +12938,7 @@ public class ActivityManagerService extends IActivityManager.Stub MemInfoReader memInfo = new MemInfoReader(); memInfo.readMemInfo(); if (nativeProcTotalPss > 0) { - synchronized (this) { + synchronized (mProcessStats.mLock) { final long cachedKb = memInfo.getCachedSizeKb(); final long freeKb = memInfo.getFreeSizeKb(); final long zramKb = memInfo.getZramTotalSizeKb(); @@ -16511,9 +16509,7 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override public void run() { - synchronized (mService) { - mProcessStats.writeStateAsyncLocked(); - } + mProcessStats.writeStateAsync(); } } @@ -16563,9 +16559,13 @@ public class ActivityManagerService extends IActivityManager.Stub } mLastMemoryLevel = memFactor; mLastNumProcesses = mProcessList.getLruSizeLocked(); - boolean allChanged = mProcessStats.setMemFactorLocked( - memFactor, mAtmInternal != null ? !mAtmInternal.isSleeping() : true, now); - final int trackerMemFactor = mProcessStats.getMemFactorLocked(); + boolean allChanged; + int trackerMemFactor; + synchronized (mProcessStats.mLock) { + allChanged = mProcessStats.setMemFactorLocked( + memFactor, mAtmInternal != null ? !mAtmInternal.isSleeping() : true, now); + trackerMemFactor = mProcessStats.getMemFactorLocked(); + } if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) { if (mLowRamStartTime == 0) { mLowRamStartTime = now; diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index f0343e1d807c..bf15f1737cfc 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -659,13 +659,15 @@ public final class OomAdjuster { updateUidsLocked(activeUids, nowElapsed); - if (mService.mProcessStats.shouldWriteNowLocked(now)) { - mService.mHandler.post(new ActivityManagerService.ProcStatsRunnable(mService, - mService.mProcessStats)); - } + synchronized (mService.mProcessStats.mLock) { + if (mService.mProcessStats.shouldWriteNowLocked(now)) { + mService.mHandler.post(new ActivityManagerService.ProcStatsRunnable(mService, + mService.mProcessStats)); + } - // Run this after making sure all procstates are updated. - mService.mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, now); + // Run this after making sure all procstates are updated. + mService.mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, now); + } if (DEBUG_OOM_ADJ) { final long duration = SystemClock.uptimeMillis() - now; diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 1647fdaa57b6..e3e13391a8b0 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -673,30 +673,33 @@ class ProcessRecord implements WindowProcessListener { public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) { if (thread == null) { - final ProcessState origBase = baseProcessTracker; - if (origBase != null) { - origBase.setState(ProcessStats.STATE_NOTHING, - tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList.mPkgList); - for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { - FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED, - uid, processName, pkgList.keyAt(ipkg), - ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING), - pkgList.valueAt(ipkg).appVersion); - } - origBase.makeInactive(); - } - baseProcessTracker = tracker.getProcessStateLocked(info.packageName, info.uid, - info.longVersionCode, processName); - baseProcessTracker.makeActive(); - for (int i=0; i<pkgList.size(); i++) { - ProcessStats.ProcessStateHolder holder = pkgList.valueAt(i); - if (holder.state != null && holder.state != origBase) { - holder.state.makeInactive(); + synchronized (tracker.mLock) { + final ProcessState origBase = baseProcessTracker; + if (origBase != null) { + origBase.setState(ProcessStats.STATE_NOTHING, + tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), + pkgList.mPkgList); + for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED, + uid, processName, pkgList.keyAt(ipkg), + ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING), + pkgList.valueAt(ipkg).appVersion); + } + origBase.makeInactive(); } - tracker.updateProcessStateHolderLocked(holder, pkgList.keyAt(i), info.uid, + baseProcessTracker = tracker.getProcessStateLocked(info.packageName, info.uid, info.longVersionCode, processName); - if (holder.state != baseProcessTracker) { - holder.state.makeActive(); + baseProcessTracker.makeActive(); + for (int i = 0, ipkg = pkgList.size(); i < ipkg; i++) { + ProcessStats.ProcessStateHolder holder = pkgList.valueAt(i); + if (holder.state != null && holder.state != origBase) { + holder.state.makeInactive(); + } + tracker.updateProcessStateHolderLocked(holder, pkgList.keyAt(i), info.uid, + info.longVersionCode, processName); + if (holder.state != baseProcessTracker) { + holder.state.makeActive(); + } } } } @@ -707,27 +710,30 @@ class ProcessRecord implements WindowProcessListener { public void makeInactive(ProcessStatsService tracker) { thread = null; mWindowProcessController.setThread(null); - final ProcessState origBase = baseProcessTracker; - if (origBase != null) { + synchronized (tracker.mLock) { + final ProcessState origBase = baseProcessTracker; if (origBase != null) { - origBase.setState(ProcessStats.STATE_NOTHING, - tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList.mPkgList); - for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { - FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED, - uid, processName, pkgList.keyAt(ipkg), - ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING), - pkgList.valueAt(ipkg).appVersion); + if (origBase != null) { + origBase.setState(ProcessStats.STATE_NOTHING, + tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), + pkgList.mPkgList); + for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED, + uid, processName, pkgList.keyAt(ipkg), + ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING), + pkgList.valueAt(ipkg).appVersion); + } + origBase.makeInactive(); } - origBase.makeInactive(); - } - baseProcessTracker = null; - for (int i=0; i<pkgList.size(); i++) { - ProcessStats.ProcessStateHolder holder = pkgList.valueAt(i); - if (holder.state != null && holder.state != origBase) { - holder.state.makeInactive(); + baseProcessTracker = null; + for (int i = 0, ipkg = pkgList.size(); i < ipkg; i++) { + ProcessStats.ProcessStateHolder holder = pkgList.valueAt(i); + if (holder.state != null && holder.state != origBase) { + holder.state.makeInactive(); + } + holder.pkg = null; + holder.state = null; } - holder.pkg = null; - holder.state = null; } } } @@ -1026,17 +1032,19 @@ class ProcessRecord implements WindowProcessListener { */ public boolean addPackage(String pkg, long versionCode, ProcessStatsService tracker) { if (!pkgList.containsKey(pkg)) { - ProcessStats.ProcessStateHolder holder = new ProcessStats.ProcessStateHolder( - versionCode); - if (baseProcessTracker != null) { - tracker.updateProcessStateHolderLocked(holder, pkg, info.uid, versionCode, - processName); - pkgList.put(pkg, holder); - if (holder.state != baseProcessTracker) { - holder.state.makeActive(); + synchronized (tracker.mLock) { + ProcessStats.ProcessStateHolder holder = new ProcessStats.ProcessStateHolder( + versionCode); + if (baseProcessTracker != null) { + tracker.updateProcessStateHolderLocked(holder, pkg, info.uid, versionCode, + processName); + pkgList.put(pkg, holder); + if (holder.state != baseProcessTracker) { + holder.state.makeActive(); + } + } else { + pkgList.put(pkg, holder); } - } else { - pkgList.put(pkg, holder); } return true; } @@ -1072,31 +1080,33 @@ class ProcessRecord implements WindowProcessListener { public void resetPackageList(ProcessStatsService tracker) { final int N = pkgList.size(); if (baseProcessTracker != null) { - long now = SystemClock.uptimeMillis(); - baseProcessTracker.setState(ProcessStats.STATE_NOTHING, - tracker.getMemFactorLocked(), now, pkgList.mPkgList); - for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { - FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED, - uid, processName, pkgList.keyAt(ipkg), - ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING), - pkgList.valueAt(ipkg).appVersion); - } - if (N != 1) { - for (int i=0; i<N; i++) { - ProcessStats.ProcessStateHolder holder = pkgList.valueAt(i); - if (holder.state != null && holder.state != baseProcessTracker) { - holder.state.makeInactive(); - } - + synchronized (tracker.mLock) { + long now = SystemClock.uptimeMillis(); + baseProcessTracker.setState(ProcessStats.STATE_NOTHING, + tracker.getMemFactorLocked(), now, pkgList.mPkgList); + for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) { + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED, + uid, processName, pkgList.keyAt(ipkg), + ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING), + pkgList.valueAt(ipkg).appVersion); } - pkgList.clear(); - ProcessStats.ProcessStateHolder holder = new ProcessStats.ProcessStateHolder( - info.longVersionCode); - tracker.updateProcessStateHolderLocked(holder, info.packageName, info.uid, - info.longVersionCode, processName); - pkgList.put(info.packageName, holder); - if (holder.state != baseProcessTracker) { - holder.state.makeActive(); + if (N != 1) { + for (int i = 0; i < N; i++) { + ProcessStats.ProcessStateHolder holder = pkgList.valueAt(i); + if (holder.state != null && holder.state != baseProcessTracker) { + holder.state.makeInactive(); + } + + } + pkgList.clear(); + ProcessStats.ProcessStateHolder holder = new ProcessStats.ProcessStateHolder( + info.longVersionCode); + tracker.updateProcessStateHolderLocked(holder, info.packageName, info.uid, + info.longVersionCode, processName); + pkgList.put(info.packageName, holder); + if (holder.state != baseProcessTracker) { + holder.state.makeActive(); + } } } } else if (N != 1) { diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java index a168af5ad842..4e8c386a3c66 100644 --- a/services/core/java/com/android/server/am/ProcessStatsService.java +++ b/services/core/java/com/android/server/am/ProcessStatsService.java @@ -71,33 +71,62 @@ public final class ProcessStatsService extends IProcessStats.Stub { final ActivityManagerService mAm; final File mBaseDir; - ProcessStats mProcessStats; + + // Note: The locking order of the below 3 locks should be: + // mLock, mPendingWriteLock, mFileLock + + // The lock object to protect the internal state/structures + final Object mLock = new Object(); + + // The lock object to protect the access to pending writes + final Object mPendingWriteLock = new Object(); + + // The lock object to protect the access to all of the file read/write + final ReentrantLock mFileLock = new ReentrantLock(); + + @GuardedBy("mLock") + final ProcessStats mProcessStats; + + @GuardedBy("mFileLock") AtomicFile mFile; + + @GuardedBy("mLock") boolean mCommitPending; + + @GuardedBy("mLock") boolean mShuttingDown; + + @GuardedBy("mLock") int mLastMemOnlyState = -1; boolean mMemFactorLowered; - final ReentrantLock mWriteLock = new ReentrantLock(); - final Object mPendingWriteLock = new Object(); + @GuardedBy("mPendingWriteLock") AtomicFile mPendingWriteFile; + + @GuardedBy("mPendingWriteLock") Parcel mPendingWrite; + + @GuardedBy("mPendingWriteLock") boolean mPendingWriteCommitted; + + @GuardedBy("mLock") long mLastWriteTime; /** For CTS to inject the screen state. */ - @GuardedBy("mAm") + @GuardedBy("mLock") Boolean mInjectedScreenState; public ProcessStatsService(ActivityManagerService am, File file) { mAm = am; mBaseDir = file; mBaseDir.mkdirs(); - mProcessStats = new ProcessStats(true); - updateFile(); + synchronized (mLock) { + mProcessStats = new ProcessStats(true); + updateFileLocked(); + } SystemProperties.addChangeCallback(new Runnable() { @Override public void run() { - synchronized (mAm) { + synchronized (mLock) { if (mProcessStats.evaluateSystemProperties(false)) { mProcessStats.mFlags |= ProcessStats.FLAG_SYSPROPS; writeStateLocked(true, true); @@ -121,32 +150,33 @@ public final class ProcessStatsService extends IProcessStats.Stub { } } - @GuardedBy("mAm") - public void updateProcessStateHolderLocked(ProcessStats.ProcessStateHolder holder, + @GuardedBy("mLock") + void updateProcessStateHolderLocked(ProcessStats.ProcessStateHolder holder, String packageName, int uid, long versionCode, String processName) { holder.pkg = mProcessStats.getPackageStateLocked(packageName, uid, versionCode); holder.state = mProcessStats.getProcessStateLocked(holder.pkg, processName); } - @GuardedBy("mAm") - public ProcessState getProcessStateLocked(String packageName, + @GuardedBy("mLock") + ProcessState getProcessStateLocked(String packageName, int uid, long versionCode, String processName) { return mProcessStats.getProcessStateLocked(packageName, uid, versionCode, processName); } - @GuardedBy("mAm") - public ServiceState getServiceStateLocked(String packageName, int uid, + ServiceState getServiceState(String packageName, int uid, long versionCode, String processName, String className) { - return mProcessStats.getServiceStateLocked(packageName, uid, versionCode, processName, - className); + synchronized (mLock) { + return mProcessStats.getServiceStateLocked(packageName, uid, versionCode, processName, + className); + } } - public boolean isMemFactorLowered() { + boolean isMemFactorLowered() { return mMemFactorLowered; } - @GuardedBy("mAm") - public boolean setMemFactorLocked(int memFactor, boolean screenOn, long now) { + @GuardedBy("mLock") + boolean setMemFactorLocked(int memFactor, boolean screenOn, long now) { mMemFactorLowered = memFactor < mLastMemOnlyState; mLastMemOnlyState = memFactor; if (mInjectedScreenState != null) { @@ -184,24 +214,24 @@ public final class ProcessStatsService extends IProcessStats.Stub { return false; } - @GuardedBy("mAm") - public int getMemFactorLocked() { + @GuardedBy("mLock") + int getMemFactorLocked() { return mProcessStats.mMemFactor != ProcessStats.STATE_NOTHING ? mProcessStats.mMemFactor : 0; } - @GuardedBy("mAm") - public void addSysMemUsageLocked(long cachedMem, long freeMem, long zramMem, long kernelMem, + @GuardedBy("mLock") + void addSysMemUsageLocked(long cachedMem, long freeMem, long zramMem, long kernelMem, long nativeMem) { mProcessStats.addSysMemUsage(cachedMem, freeMem, zramMem, kernelMem, nativeMem); } - @GuardedBy("mAm") - public void updateTrackingAssociationsLocked(int curSeq, long now) { + @GuardedBy("mLock") + void updateTrackingAssociationsLocked(int curSeq, long now) { mProcessStats.updateTrackingAssociationsLocked(curSeq, now); } - @GuardedBy("mAm") - public boolean shouldWriteNowLocked(long now) { + @GuardedBy("mLock") + boolean shouldWriteNowLocked(long now) { if (now > (mLastWriteTime+WRITE_PERIOD)) { if (SystemClock.elapsedRealtime() > (mProcessStats.mTimePeriodStartRealtime+ProcessStats.COMMIT_PERIOD) && @@ -214,25 +244,27 @@ public final class ProcessStatsService extends IProcessStats.Stub { return false; } - @GuardedBy("mAm") - public void shutdownLocked() { + void shutdown() { Slog.w(TAG, "Writing process stats before shutdown..."); - mProcessStats.mFlags |= ProcessStats.FLAG_SHUTDOWN; - writeStateSyncLocked(); - mShuttingDown = true; + synchronized (mLock) { + mProcessStats.mFlags |= ProcessStats.FLAG_SHUTDOWN; + writeStateSyncLocked(); + mShuttingDown = true; + } } - @GuardedBy("mAm") - public void writeStateAsyncLocked() { - writeStateLocked(false); + void writeStateAsync() { + synchronized (mLock) { + writeStateLocked(false); + } } - @GuardedBy("mAm") - public void writeStateSyncLocked() { + @GuardedBy("mLock") + private void writeStateSyncLocked() { writeStateLocked(true); } - @GuardedBy("mAm") + @GuardedBy("mLock") private void writeStateLocked(boolean sync) { if (mShuttingDown) { return; @@ -242,8 +274,8 @@ public final class ProcessStatsService extends IProcessStats.Stub { writeStateLocked(sync, commitPending); } - @GuardedBy("mAm") - public void writeStateLocked(boolean sync, final boolean commit) { + @GuardedBy("mLock") + private void writeStateLocked(boolean sync, final boolean commit) { final long totalTime; synchronized (mPendingWriteLock) { final long now = SystemClock.uptimeMillis(); @@ -255,13 +287,13 @@ public final class ProcessStatsService extends IProcessStats.Stub { mProcessStats.mFlags |= ProcessStats.FLAG_COMPLETE; } mProcessStats.writeToParcel(mPendingWrite, 0); - mPendingWriteFile = new AtomicFile(mFile.getBaseFile()); + mPendingWriteFile = new AtomicFile(getCurrentFile()); mPendingWriteCommitted = commit; } if (commit) { mProcessStats.resetSafely(); - updateFile(); - mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false); + updateFileLocked(); + scheduleRequestPssAllProcs(true, false); } mLastWriteTime = SystemClock.uptimeMillis(); totalTime = SystemClock.uptimeMillis() - now; @@ -279,14 +311,37 @@ public final class ProcessStatsService extends IProcessStats.Stub { performWriteState(totalTime); } - private void updateFile() { - mFile = new AtomicFile(new File(mBaseDir, STATE_FILE_PREFIX - + mProcessStats.mTimePeriodStartClockStr + STATE_FILE_SUFFIX)); + private void scheduleRequestPssAllProcs(boolean always, boolean memLowered) { + mAm.mHandler.post(() -> { + synchronized (mAm) { + mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), always, memLowered); + } + }); + } + + @GuardedBy("mLock") + private void updateFileLocked() { + mFileLock.lock(); + try { + mFile = new AtomicFile(new File(mBaseDir, STATE_FILE_PREFIX + + mProcessStats.mTimePeriodStartClockStr + STATE_FILE_SUFFIX)); + } finally { + mFileLock.unlock(); + } mLastWriteTime = SystemClock.uptimeMillis(); } - void performWriteState(long initialTime) { - if (DEBUG) Slog.d(TAG, "Performing write to " + mFile.getBaseFile()); + private File getCurrentFile() { + mFileLock.lock(); + try { + return mFile.getBaseFile(); + } finally { + mFileLock.unlock(); + } + } + + private void performWriteState(long initialTime) { + if (DEBUG) Slog.d(TAG, "Performing write to " + getCurrentFile()); Parcel data; AtomicFile file; synchronized (mPendingWriteLock) { @@ -298,7 +353,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { } mPendingWrite = null; mPendingWriteFile = null; - mWriteLock.lock(); + mFileLock.lock(); } final long startTime = SystemClock.uptimeMillis(); @@ -316,13 +371,13 @@ public final class ProcessStatsService extends IProcessStats.Stub { file.failWrite(stream); } finally { data.recycle(); - trimHistoricStatesWriteLocked(); - mWriteLock.unlock(); + trimHistoricStatesWriteLF(); + mFileLock.unlock(); } } - @GuardedBy("mAm") - boolean readLocked(ProcessStats stats, AtomicFile file) { + @GuardedBy("mFileLock") + private boolean readLF(ProcessStats stats, AtomicFile file) { try { FileInputStream stream = file.openRead(); stats.read(stream); @@ -387,7 +442,8 @@ public final class ProcessStatsService extends IProcessStats.Stub { return true; } - private ArrayList<String> getCommittedFiles(int minNum, boolean inclCurrent, + @GuardedBy("mFileLock") + private ArrayList<String> getCommittedFilesLF(int minNum, boolean inclCurrent, boolean inclCheckedIn) { File[] files = mBaseDir.listFiles(); if (files == null || files.length <= minNum) { @@ -414,9 +470,9 @@ public final class ProcessStatsService extends IProcessStats.Stub { return filesArray; } - @GuardedBy("mAm") - public void trimHistoricStatesWriteLocked() { - ArrayList<String> filesArray = getCommittedFiles(MAX_HISTORIC_STATES, false, true); + @GuardedBy("mFileLock") + private void trimHistoricStatesWriteLF() { + ArrayList<String> filesArray = getCommittedFilesLF(MAX_HISTORIC_STATES, false, true); if (filesArray == null) { return; } @@ -427,8 +483,8 @@ public final class ProcessStatsService extends IProcessStats.Stub { } } - @GuardedBy("mAm") - boolean dumpFilteredProcessesCsvLocked(PrintWriter pw, String header, + @GuardedBy("mLock") + private boolean dumpFilteredProcessesCsvLocked(PrintWriter pw, String header, boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates, boolean sepProcStates, int[] procStates, long now, String reqPackage) { ArrayList<ProcessState> procs = mProcessStats.collectProcessesLocked( @@ -502,20 +558,21 @@ public final class ProcessStatsService extends IProcessStats.Stub { return res; } + @Override public byte[] getCurrentStats(List<ParcelFileDescriptor> historic) { mAm.mContext.enforceCallingOrSelfPermission( android.Manifest.permission.PACKAGE_USAGE_STATS, null); Parcel current = Parcel.obtain(); - synchronized (mAm) { + synchronized (mLock) { long now = SystemClock.uptimeMillis(); mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime(); mProcessStats.mTimePeriodEndUptime = now; mProcessStats.writeToParcel(current, now, 0); } - mWriteLock.lock(); + mFileLock.lock(); try { if (historic != null) { - ArrayList<String> files = getCommittedFiles(0, false, true); + ArrayList<String> files = getCommittedFilesLF(0, false, true); if (files != null) { for (int i=files.size()-1; i>=0; i--) { try { @@ -529,7 +586,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { } } } finally { - mWriteLock.unlock(); + mFileLock.unlock(); } return current.marshall(); } @@ -563,9 +620,9 @@ public final class ProcessStatsService extends IProcessStats.Stub { android.Manifest.permission.PACKAGE_USAGE_STATS, null); long newHighWaterMark = highWaterMarkMs; - mWriteLock.lock(); + mFileLock.lock(); try { - ArrayList<String> files = getCommittedFiles(0, false, true); + ArrayList<String> files = getCommittedFilesLF(0, false, true); if (files != null) { String highWaterMarkStr = DateFormat.format("yyyy-MM-dd-HH-mm-ss", highWaterMarkMs).toString(); @@ -612,7 +669,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { } catch (IOException e) { Slog.w(TAG, "Failure opening procstat file", e); } finally { - mWriteLock.unlock(); + mFileLock.unlock(); } return newHighWaterMark; } @@ -625,7 +682,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { return mAm.mConstants.MIN_ASSOC_LOG_DURATION; } - private ParcelFileDescriptor protoToParcelFileDescriptor(ProcessStats stats, int section) + private static ParcelFileDescriptor protoToParcelFileDescriptor(ProcessStats stats, int section) throws IOException { final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe(); Thread thr = new Thread("ProcessStats pipe output") { @@ -645,12 +702,13 @@ public final class ProcessStatsService extends IProcessStats.Stub { return fds[0]; } + @Override public ParcelFileDescriptor getStatsOverTime(long minTime) { mAm.mContext.enforceCallingOrSelfPermission( android.Manifest.permission.PACKAGE_USAGE_STATS, null); Parcel current = Parcel.obtain(); long curTime; - synchronized (mAm) { + synchronized (mLock) { long now = SystemClock.uptimeMillis(); mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime(); mProcessStats.mTimePeriodEndUptime = now; @@ -658,11 +716,11 @@ public final class ProcessStatsService extends IProcessStats.Stub { curTime = mProcessStats.mTimePeriodEndRealtime - mProcessStats.mTimePeriodStartRealtime; } - mWriteLock.lock(); + mFileLock.lock(); try { if (curTime < minTime) { // Need to add in older stats to reach desired time. - ArrayList<String> files = getCommittedFiles(0, false, true); + ArrayList<String> files = getCommittedFilesLF(0, false, true); if (files != null && files.size() > 0) { current.setDataPosition(0); ProcessStats stats = ProcessStats.CREATOR.createFromParcel(current); @@ -673,7 +731,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { AtomicFile file = new AtomicFile(new File(files.get(i))); i--; ProcessStats moreStats = new ProcessStats(false); - readLocked(moreStats, file); + readLF(moreStats, file); if (moreStats.mReadError == null) { stats.add(moreStats); StringBuilder sb = new StringBuilder(); @@ -712,13 +770,14 @@ public final class ProcessStatsService extends IProcessStats.Stub { } catch (IOException e) { Slog.w(TAG, "Failed building output pipe", e); } finally { - mWriteLock.unlock(); + mFileLock.unlock(); } return null; } + @Override public int getCurrentMemoryState() { - synchronized (mAm) { + synchronized (mLock) { return mLastMemOnlyState; } } @@ -947,7 +1006,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { } else if ("--current".equals(arg)) { currentOnly = true; } else if ("--commit".equals(arg)) { - synchronized (mAm) { + synchronized (mLock) { mProcessStats.mFlags |= ProcessStats.FLAG_COMPLETE; writeStateLocked(true, true); pw.println("Process stats committed."); @@ -962,29 +1021,39 @@ public final class ProcessStatsService extends IProcessStats.Stub { } section = parseSectionOptions(args[i]); } else if ("--clear".equals(arg)) { - synchronized (mAm) { + synchronized (mLock) { mProcessStats.resetSafely(); - mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false); - ArrayList<String> files = getCommittedFiles(0, true, true); - if (files != null) { - for (int fi=0; fi<files.size(); fi++) { - (new File(files.get(fi))).delete(); + scheduleRequestPssAllProcs(true, false); + mFileLock.lock(); + try { + ArrayList<String> files = getCommittedFilesLF(0, true, true); + if (files != null) { + for (int fi = files.size() - 1; fi >= 0; fi--) { + (new File(files.get(fi))).delete(); + } } + } finally { + mFileLock.unlock(); } pw.println("All process stats cleared."); quit = true; } } else if ("--write".equals(arg)) { - synchronized (mAm) { + synchronized (mLock) { writeStateSyncLocked(); pw.println("Process stats written."); quit = true; } } else if ("--read".equals(arg)) { - synchronized (mAm) { - readLocked(mProcessStats, mFile); - pw.println("Process stats read."); - quit = true; + synchronized (mLock) { + mFileLock.lock(); + try { + readLF(mProcessStats, mFile); + pw.println("Process stats read."); + quit = true; + } finally { + mFileLock.unlock(); + } } } else if ("--start-testing".equals(arg)) { synchronized (mAm) { @@ -999,17 +1068,17 @@ public final class ProcessStatsService extends IProcessStats.Stub { quit = true; } } else if ("--pretend-screen-on".equals(arg)) { - synchronized (mAm) { + synchronized (mLock) { mInjectedScreenState = true; } quit = true; } else if ("--pretend-screen-off".equals(arg)) { - synchronized (mAm) { + synchronized (mLock) { mInjectedScreenState = false; } quit = true; } else if ("--stop-pretend-screen".equals(arg)) { - synchronized (mAm) { + synchronized (mLock) { mInjectedScreenState = null; } quit = true; @@ -1060,7 +1129,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { } } pw.println(); - synchronized (mAm) { + synchronized (mLock) { dumpFilteredProcessesCsvLocked(pw, null, csvSepScreenStats, csvScreenStats, csvSepMemStats, csvMemStats, csvSepProcStats, csvProcStats, now, reqPackage); @@ -1090,14 +1159,26 @@ public final class ProcessStatsService extends IProcessStats.Stub { return; } else if (lastIndex > 0) { pw.print("LAST STATS AT INDEX "); pw.print(lastIndex); pw.println(":"); - ArrayList<String> files = getCommittedFiles(0, false, true); - if (lastIndex >= files.size()) { - pw.print("Only have "); pw.print(files.size()); pw.println(" data sets"); - return; + + ArrayList<String> files; + AtomicFile file; + ProcessStats processStats; + + mFileLock.lock(); + try { + files = getCommittedFilesLF(0, false, true); + if (lastIndex >= files.size()) { + pw.print("Only have "); pw.print(files.size()); pw.println(" data sets"); + return; + } + file = new AtomicFile(new File(files.get(lastIndex))); + processStats = new ProcessStats(false); + readLF(processStats, file); + } finally { + mFileLock.unlock(); } - AtomicFile file = new AtomicFile(new File(files.get(lastIndex))); - ProcessStats processStats = new ProcessStats(false); - readLocked(processStats, file); + + // No lock is needed now, since only us have the access to the 'processStats'. if (processStats.mReadError != null) { if (isCheckin || isCompact) pw.print("err,"); pw.print("Failure reading "); pw.print(files.get(lastIndex)); @@ -1118,7 +1199,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { processStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpDetails, dumpAll, activeOnly, section); if (dumpAll) { - pw.print(" mFile="); pw.println(mFile.getBaseFile()); + pw.print(" mFile="); pw.println(getCurrentFile()); } } else { processStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly); @@ -1129,9 +1210,9 @@ public final class ProcessStatsService extends IProcessStats.Stub { boolean sepNeeded = false; if ((dumpAll || isCheckin) && !currentOnly) { - mWriteLock.lock(); + mFileLock.lock(); try { - ArrayList<String> files = getCommittedFiles(0, false, !isCheckin); + ArrayList<String> files = getCommittedFilesLF(0, false, !isCheckin); if (files != null) { int start = isCheckin ? 0 : (files.size() - maxNum); if (start < 0) { @@ -1142,7 +1223,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { try { AtomicFile file = new AtomicFile(new File(files.get(i))); ProcessStats processStats = new ProcessStats(false); - readLocked(processStats, file); + readLF(processStats, file); if (processStats.mReadError != null) { if (isCheckin || isCompact) pw.print("err,"); pw.print("Failure reading "); pw.print(files.get(i)); @@ -1188,11 +1269,11 @@ public final class ProcessStatsService extends IProcessStats.Stub { } } } finally { - mWriteLock.unlock(); + mFileLock.unlock(); } } if (!isCheckin) { - synchronized (mAm) { + synchronized (mLock) { if (isCompact) { mProcessStats.dumpCheckinLocked(pw, reqPackage, section); } else { @@ -1204,7 +1285,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpDetails, dumpAll, activeOnly, section); if (dumpAll) { - pw.print(" mFile="); pw.println(mFile.getBaseFile()); + pw.print(" mFile="); pw.println(getCurrentFile()); } } else { mProcessStats.dumpSummaryLocked(pw, reqPackage, now, activeOnly); @@ -1249,7 +1330,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { // dump current procstats long now; - synchronized (mAm) { + synchronized (mLock) { now = SystemClock.uptimeMillis(); final long token = proto.start(ProcessStatsServiceDumpProto.PROCSTATS_NOW); mProcessStats.dumpDebug(proto, now, ProcessStats.REPORT_ALL); diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index 022b04d89774..4a2703056871 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -528,8 +528,9 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN return tracker; } if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) { - tracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName, - serviceInfo.applicationInfo.uid, serviceInfo.applicationInfo.longVersionCode, + tracker = ams.mProcessStats.getServiceState(serviceInfo.packageName, + serviceInfo.applicationInfo.uid, + serviceInfo.applicationInfo.longVersionCode, serviceInfo.processName, serviceInfo.name); tracker.applyNewOwner(this); } @@ -546,7 +547,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN public void makeRestarting(int memFactor, long now) { if (restartTracker == null) { if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) { - restartTracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName, + restartTracker = ams.mProcessStats.getServiceState( + serviceInfo.packageName, serviceInfo.applicationInfo.uid, serviceInfo.applicationInfo.longVersionCode, serviceInfo.processName, serviceInfo.name); diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java index 2a267c413c31..1b2711d3938b 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java @@ -99,6 +99,7 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -165,7 +166,7 @@ public class MockingOomAdjusterTests { setFieldValue(ActivityManagerService.class, sService, "mHandler", mock(ActivityManagerService.MainHandler.class)); setFieldValue(ActivityManagerService.class, sService, "mProcessStats", - mock(ProcessStatsService.class)); + new ProcessStatsService(sService, new File(sContext.getFilesDir(), "procstats"))); setFieldValue(ActivityManagerService.class, sService, "mBackupTargets", mock(SparseArray.class)); setFieldValue(ActivityManagerService.class, sService, "mOomAdjProfiler", |