Reduce pss collection amount, improve logging.

Tuned rates that we collect PSS, to reduce how much we do
that heavy operation.  Added a new way to determine
whether a process has changed to a state for the
"first" time -- now this is when it has gone to that
state for the first time since it was in a lower state.
This will reduce the amount of time we consider a
process to be first to only when it has previously
gone into a higher state than it had before.

Keep track of more fine-grained information about why we
collect a PSS sample (not just internal, but for a single
process, all processes because of a mem state change, all
processes because of a poll).

Started collecting RSS in various places, so we can start
looking at that w.r.t. PSS and see about transitioning to
it is a new primary metric.

Added logging for many of the places where the system
writes its configuration files, so we can more easily
see any bad behavior going on in those areas.

Added some currently disabled code to read smaps directly
instead of using fgets().  Probably won't help, but want
tot test.

Bug: 70859548
Test: atest CtsAppTestCases
Change-Id: I400dba0f3ae9c024df51c946cfa592561028b598
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index f4675fd..894106a 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -39,6 +39,7 @@
 import android.os.ServiceManager;
 import android.os.ShellCallback;
 import android.os.ShellCommand;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.StorageManagerInternal;
@@ -248,7 +249,7 @@
 
     public AppOpsService(File storagePath, Handler handler) {
         LockGuard.installLock(this, LockGuard.INDEX_APP_OPS);
-        mFile = new AtomicFile(storagePath);
+        mFile = new AtomicFile(storagePath, "appops");
         mHandler = handler;
         readState();
     }
@@ -1666,8 +1667,6 @@
 
     void writeState() {
         synchronized (mFile) {
-            List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null);
-
             FileOutputStream stream;
             try {
                 stream = mFile.startWrite();
@@ -1676,6 +1675,8 @@
                 return;
             }
 
+            List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null);
+
             try {
                 XmlSerializer out = new FastXmlSerializer();
                 out.setOutput(stream, StandardCharsets.UTF_8.name());
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 21137ad..fc91d0d 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -4306,7 +4306,7 @@
                 Slog.w(TAG, "Couldn't create dir.: " + inputMethodDir.getAbsolutePath());
             }
             final File subtypeFile = new File(inputMethodDir, ADDITIONAL_SUBTYPES_FILE_NAME);
-            mAdditionalInputMethodSubtypeFile = new AtomicFile(subtypeFile);
+            mAdditionalInputMethodSubtypeFile = new AtomicFile(subtypeFile, "input-subtypes");
             if (!subtypeFile.exists()) {
                 // If "subtypes.xml" doesn't exist, create a blank file.
                 writeAdditionalInputMethodSubtypes(
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 7361e70..8ec4ef6 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1386,7 +1386,7 @@
         }
 
         mSettingsFile = new AtomicFile(
-                new File(Environment.getDataSystemDirectory(), "storage.xml"));
+                new File(Environment.getDataSystemDirectory(), "storage.xml"), "storage-settings");
 
         synchronized (mLock) {
             readSettingsLocked();
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f469437..1e4bacb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1643,7 +1643,7 @@
     String mTrackAllocationApp = null;
     String mNativeDebuggingApp = null;
 
-    final long[] mTmpLong = new long[2];
+    final long[] mTmpLong = new long[3];
 
     private final ArraySet<BroadcastQueue> mTmpBroadcastQueue = new ArraySet();
 
@@ -2601,22 +2601,24 @@
                 }
 
                 int num = 0;
-                long[] tmp = new long[2];
+                long[] tmp = new long[3];
                 do {
                     ProcessRecord proc;
                     int procState;
+                    int statType;
                     int pid;
                     long lastPssTime;
                     synchronized (ActivityManagerService.this) {
                         if (mPendingPssProcesses.size() <= 0) {
                             if (mTestPssMode || DEBUG_PSS) Slog.d(TAG_PSS,
-                                    "Collected PSS of " + num + " processes in "
+                                    "Collected pss of " + num + " processes in "
                                     + (SystemClock.uptimeMillis() - start) + "ms");
                             mPendingPssProcesses.clear();
                             return;
                         }
                         proc = mPendingPssProcesses.remove(0);
                         procState = proc.pssProcState;
+                        statType = proc.pssStatType;
                         lastPssTime = proc.lastPssTime;
                         if (proc.thread != null && procState == proc.setProcState
                                 && (lastPssTime+ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE)
@@ -2635,8 +2637,17 @@
                             if (pss != 0 && proc.thread != null && proc.setProcState == procState
                                     && proc.pid == pid && proc.lastPssTime == lastPssTime) {
                                 num++;
-                                recordPssSampleLocked(proc, procState, pss, tmp[0], tmp[1],
-                                        endTime-startTime, SystemClock.uptimeMillis());
+                                ProcessList.commitNextPssTime(proc.procStateMemTracker);
+                                recordPssSampleLocked(proc, procState, pss, tmp[0], tmp[1], tmp[2],
+                                        statType, endTime-startTime, SystemClock.uptimeMillis());
+                            } else {
+                                ProcessList.abortNextPssTime(proc.procStateMemTracker);
+                                if (DEBUG_PSS) Slog.d(TAG_PSS, "Skipped pss collection of " + pid +
+                                        ": " + (proc.thread == null ? "NO_THREAD " : "") +
+                                        (proc.pid != pid ? "PID_CHANGED " : "") +
+                                        " initState=" + procState + " curState=" +
+                                        proc.setProcState + " " +
+                                        (proc.lastPssTime != lastPssTime ? "TIME_CHANGED" : ""));
                             }
                         }
                     }
@@ -2933,7 +2944,7 @@
                     }
                 });
 
-        mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));
+        mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"), "uri-grants");
 
         mUserController = new UserController(this);
 
@@ -6750,7 +6761,7 @@
                     if (proc.thread != null && proc.setAdj == oomAdj) {
                         // Record this for posterity if the process has been stable.
                         proc.baseProcessTracker.addPss(infos[i].getTotalPss(),
-                                infos[i].getTotalUss(), false,
+                                infos[i].getTotalUss(), infos[i].getTotalRss(), false,
                                 ProcessStats.ADD_PSS_EXTERNAL_SLOW, endTime-startTime,
                                 proc.pkgList);
                     }
@@ -6773,7 +6784,7 @@
                     oomAdj = proc != null ? proc.setAdj : 0;
                 }
             }
-            long[] tmpUss = new long[1];
+            long[] tmpUss = new long[3];
             long startTime = SystemClock.currentThreadTimeMillis();
             pss[i] = Debug.getPss(pids[i], tmpUss, null);
             long endTime = SystemClock.currentThreadTimeMillis();
@@ -6781,7 +6792,7 @@
                 synchronized (this) {
                     if (proc.thread != null && proc.setAdj == oomAdj) {
                         // Record this for posterity if the process has been stable.
-                        proc.baseProcessTracker.addPss(pss[i], tmpUss[0], false,
+                        proc.baseProcessTracker.addPss(pss[i], tmpUss[0], tmpUss[2], false,
                                 ProcessStats.ADD_PSS_EXTERNAL, endTime-startTime, proc.pkgList);
                     }
                 }
@@ -9940,6 +9951,8 @@
     private void writeGrantedUriPermissions() {
         if (DEBUG_URI_PERMISSION) Slog.v(TAG_URI_PERMISSION, "writeGrantedUriPermissions()");
 
+        final long startTime = SystemClock.uptimeMillis();
+
         // Snapshot permissions so we can persist without lock
         ArrayList<UriPermission.Snapshot> persist = Lists.newArrayList();
         synchronized (this) {
@@ -9956,7 +9969,7 @@
 
         FileOutputStream fos = null;
         try {
-            fos = mGrantFile.startWrite();
+            fos = mGrantFile.startWrite(startTime);
 
             XmlSerializer out = new FastXmlSerializer();
             out.setOutput(fos, StandardCharsets.UTF_8.name());
@@ -14451,7 +14464,7 @@
                         && proc.setProcState >= ActivityManager.PROCESS_STATE_PERSISTENT) {
                     proc.notCachedSinceIdle = true;
                     proc.initialIdlePss = 0;
-                    proc.nextPssTime = ProcessList.computeNextPssTime(proc.setProcState, true,
+                    proc.nextPssTime = ProcessList.computeNextPssTime(proc.setProcState, null,
                             mTestPssMode, isSleepingLocked(), now);
                 }
             }
@@ -18381,12 +18394,13 @@
 
                 final long myTotalPss = mi.getTotalPss();
                 final long myTotalUss = mi.getTotalUss();
+                final long myTotalRss = mi.getTotalRss();
                 final long myTotalSwapPss = mi.getTotalSwappedOutPss();
 
                 synchronized (this) {
                     if (r.thread != null && oomAdj == r.getSetAdjWithServices()) {
                         // Record this for posterity if the process has been stable.
-                        r.baseProcessTracker.addPss(myTotalPss, myTotalUss, true,
+                        r.baseProcessTracker.addPss(myTotalPss, myTotalUss, myTotalRss, true,
                                 reportType, endTime-startTime, r.pkgList);
                     }
                 }
@@ -18877,12 +18891,13 @@
 
             final long myTotalPss = mi.getTotalPss();
             final long myTotalUss = mi.getTotalUss();
+            final long myTotalRss = mi.getTotalRss();
             final long myTotalSwapPss = mi.getTotalSwappedOutPss();
 
             synchronized (this) {
                 if (r.thread != null && oomAdj == r.getSetAdjWithServices()) {
                     // Record this for posterity if the process has been stable.
-                    r.baseProcessTracker.addPss(myTotalPss, myTotalUss, true,
+                    r.baseProcessTracker.addPss(myTotalPss, myTotalUss, myTotalRss, true,
                             reportType, endTime-startTime, r.pkgList);
                 }
             }
@@ -23157,14 +23172,13 @@
      * Record new PSS sample for a process.
      */
     void recordPssSampleLocked(ProcessRecord proc, int procState, long pss, long uss, long swapPss,
-            long pssDuration, long now) {
+            long rss, int statType, long pssDuration, long now) {
         EventLogTags.writeAmPss(proc.pid, proc.uid, proc.processName, pss * 1024, uss * 1024,
-                swapPss * 1024);
+                swapPss * 1024, rss * 1024, statType, procState, pssDuration);
         proc.lastPssTime = now;
-        proc.baseProcessTracker.addPss(pss, uss, true, ProcessStats.ADD_PSS_INTERNAL,
-                pssDuration, proc.pkgList);
+        proc.baseProcessTracker.addPss(pss, uss, rss, true, statType, pssDuration, proc.pkgList);
         if (DEBUG_PSS) Slog.d(TAG_PSS,
-                "PSS of " + proc.toShortString() + ": " + pss + " lastPss=" + proc.lastPss
+                "pss of " + proc.toShortString() + ": " + pss + " lastPss=" + proc.lastPss
                 + " state=" + ProcessList.makeProcStateString(procState));
         if (proc.initialIdlePss == 0) {
             proc.initialIdlePss = pss;
@@ -23263,8 +23277,9 @@
         if (mPendingPssProcesses.size() == 0) {
             mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG);
         }
-        if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting PSS of: " + proc);
+        if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting pss of: " + proc);
         proc.pssProcState = procState;
+        proc.pssStatType = ProcessStats.ADD_PSS_INTERNAL_SINGLE;
         mPendingPssProcesses.add(proc);
     }
 
@@ -23279,7 +23294,7 @@
                 return;
             }
         }
-        if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting PSS of all procs!  memLowered=" + memLowered);
+        if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting pss of all procs!  memLowered=" + memLowered);
         mLastFullPssTime = now;
         mFullPssPending = true;
         mPendingPssProcesses.ensureCapacity(mLruProcesses.size());
@@ -23292,8 +23307,10 @@
             }
             if (memLowered || now > (app.lastStateTime+ProcessList.PSS_ALL_INTERVAL)) {
                 app.pssProcState = app.setProcState;
-                app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
-                        mTestPssMode, isSleepingLocked(), now);
+                app.pssStatType = always ? ProcessStats.ADD_PSS_INTERNAL_ALL_POLL
+                        : ProcessStats.ADD_PSS_INTERNAL_ALL_MEM;
+                app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState,
+                        app.procStateMemTracker, mTestPssMode, isSleepingLocked(), now);
                 mPendingPssProcesses.add(app);
             }
         }
@@ -23660,16 +23677,16 @@
                 long startTime = SystemClock.currentThreadTimeMillis();
                 long pss = Debug.getPss(app.pid, mTmpLong, null);
                 long endTime = SystemClock.currentThreadTimeMillis();
-                recordPssSampleLocked(app, app.curProcState, pss, endTime-startTime,
-                        mTmpLong[0], mTmpLong[1], now);
+                recordPssSampleLocked(app, app.curProcState, pss, mTmpLong[0], mTmpLong[1],
+                        mTmpLong[2], ProcessStats.ADD_PSS_INTERNAL_SINGLE, endTime-startTime, now);
                 mPendingPssProcesses.remove(app);
                 Slog.i(TAG, "Recorded pss for " + app + " state " + app.setProcState
                         + " to " + app.curProcState + ": "
                         + (SystemClock.uptimeMillis()-start) + "ms");
             }
             app.lastStateTime = now;
-            app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
-                    mTestPssMode, isSleepingLocked(), now);
+            app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState,
+                    app.procStateMemTracker, mTestPssMode, isSleepingLocked(), now);
             if (DEBUG_PSS) Slog.d(TAG_PSS, "Process state change from "
                     + ProcessList.makeProcStateString(app.setProcState) + " to "
                     + ProcessList.makeProcStateString(app.curProcState) + " next pss in "
@@ -23679,10 +23696,10 @@
                     && now > (app.lastStateTime+ProcessList.minTimeFromStateChange(
                     mTestPssMode)))) {
                 requestPssLocked(app, app.setProcState);
-                app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, false,
-                        mTestPssMode, isSleepingLocked(), now);
+                app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState,
+                        app.procStateMemTracker, mTestPssMode, isSleepingLocked(), now);
             } else if (false && DEBUG_PSS) Slog.d(TAG_PSS,
-                    "Not requesting PSS of " + app + ": next=" + (app.nextPssTime-now));
+                    "Not requesting pss of " + app + ": next=" + (app.nextPssTime-now));
         }
         if (app.setProcState != app.curProcState) {
             if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mCurOomAdjUid == app.uid) {
diff --git a/services/core/java/com/android/server/am/AppWarnings.java b/services/core/java/com/android/server/am/AppWarnings.java
index 806e95d..4b43bd9 100644
--- a/services/core/java/com/android/server/am/AppWarnings.java
+++ b/services/core/java/com/android/server/am/AppWarnings.java
@@ -81,7 +81,7 @@
         mUiContext = uiContext;
         mAmsHandler = new ConfigHandler(amsHandler.getLooper());
         mUiHandler = new UiHandler(uiHandler.getLooper());
-        mConfigFile = new AtomicFile(new File(systemDir, CONFIG_FILE_NAME));
+        mConfigFile = new AtomicFile(new File(systemDir, CONFIG_FILE_NAME), "warnings-config");
 
         readConfigFromFileAmsThread();
     }
diff --git a/services/core/java/com/android/server/am/CompatModePackages.java b/services/core/java/com/android/server/am/CompatModePackages.java
index 65c4a42..d84f487 100644
--- a/services/core/java/com/android/server/am/CompatModePackages.java
+++ b/services/core/java/com/android/server/am/CompatModePackages.java
@@ -82,7 +82,7 @@
 
     public CompatModePackages(ActivityManagerService service, File systemDir, Handler handler) {
         mService = service;
-        mFile = new AtomicFile(new File(systemDir, "packages-compat.xml"));
+        mFile = new AtomicFile(new File(systemDir, "packages-compat.xml"), "compat-mode");
         mHandler = new CompatHandler(handler.getLooper());
 
         FileInputStream fis = null;
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index a131db5..cb2957d 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -102,7 +102,7 @@
 # Report collection of global memory state
 30046 am_meminfo (Cached|2|2),(Free|2|2),(Zram|2|2),(Kernel|2|2),(Native|2|2)
 # Report collection of memory used by a process
-30047 am_pss (Pid|1|5),(UID|1|5),(Process Name|3),(Pss|2|2),(Uss|2|2),(SwapPss|2|2)
+30047 am_pss (Pid|1|5),(UID|1|5),(Process Name|3),(Pss|2|2),(Uss|2|2),(SwapPss|2|2),(Rss|2|2),(StatType|1|5),(ProcState|1|5),(TimeToCollect|2|2)
 
 # Attempting to stop an activity
 30048 am_stop_activity (User|1|5),(Token|1|5),(Component Name|3)
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index a50d069..08ee237 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -21,6 +21,7 @@
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.PrintWriter;
 import java.nio.ByteBuffer;
 
 import android.app.ActivityManager;
@@ -482,7 +483,7 @@
     public static final int PSS_MIN_TIME_FROM_STATE_CHANGE = 15*1000;
 
     // The maximum amount of time we want to go between PSS collections.
-    public static final int PSS_MAX_INTERVAL = 40*60*1000;
+    public static final int PSS_MAX_INTERVAL = 60*60*1000;
 
     // The minimum amount of time between successive PSS requests for *all* processes.
     public static final int PSS_ALL_INTERVAL = 20*60*1000;
@@ -497,7 +498,10 @@
     private static final int PSS_FIRST_BACKGROUND_INTERVAL = 20*1000;
 
     // The amount of time until PSS when a process first becomes cached.
-    private static final int PSS_FIRST_CACHED_INTERVAL = 30*1000;
+    private static final int PSS_FIRST_CACHED_INTERVAL = 20*1000;
+
+    // The amount of time until PSS when an important process stays in the same state.
+    private static final int PSS_SAME_PERSISTENT_INTERVAL = 20*60*1000;
 
     // The amount of time until PSS when the top process stays in the same state.
     private static final int PSS_SAME_TOP_INTERVAL = 5*60*1000;
@@ -509,7 +513,7 @@
     private static final int PSS_SAME_SERVICE_INTERVAL = 20*60*1000;
 
     // The amount of time until PSS when a cached process stays in the same state.
-    private static final int PSS_SAME_CACHED_INTERVAL = 30*60*1000;
+    private static final int PSS_SAME_CACHED_INTERVAL = 20*60*1000;
 
     // The amount of time until PSS when a persistent process first appears.
     private static final int PSS_FIRST_ASLEEP_PERSISTENT_INTERVAL = 1*60*1000;
@@ -543,7 +547,9 @@
     public static final int PROC_MEM_IMPORTANT = 2;
     public static final int PROC_MEM_SERVICE = 3;
     public static final int PROC_MEM_CACHED = 4;
+    public static final int PROC_MEM_NUM = 5;
 
+    // Map large set of system process states to
     private static final int[] sProcStateToProcMem = new int[] {
         PROC_MEM_PERSISTENT,            // ActivityManager.PROCESS_STATE_PERSISTENT
         PROC_MEM_PERSISTENT,            // ActivityManager.PROCESS_STATE_PERSISTENT_UI
@@ -567,138 +573,96 @@
     };
 
     private static final long[] sFirstAwakePssTimes = new long[] {
-        PSS_FIRST_PERSISTENT_INTERVAL,  // ActivityManager.PROCESS_STATE_PERSISTENT
-        PSS_FIRST_PERSISTENT_INTERVAL,  // ActivityManager.PROCESS_STATE_PERSISTENT_UI
-        PSS_FIRST_TOP_INTERVAL,         // ActivityManager.PROCESS_STATE_TOP
-        PSS_FIRST_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
-        PSS_FIRST_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
-        PSS_FIRST_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
-        PSS_FIRST_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
-        PSS_FIRST_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
-        PSS_FIRST_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_BACKUP
-        PSS_FIRST_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_SERVICE
-        PSS_FIRST_CACHED_INTERVAL,      // ActivityManager.PROCESS_STATE_RECEIVER
-        PSS_FIRST_CACHED_INTERVAL,      // ActivityManager.PROCESS_STATE_TOP_SLEEPING
-        PSS_FIRST_CACHED_INTERVAL,      // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
-        PSS_FIRST_CACHED_INTERVAL,      // ActivityManager.PROCESS_STATE_HOME
-        PSS_FIRST_CACHED_INTERVAL,      // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
-        PSS_FIRST_CACHED_INTERVAL,      // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
-        PSS_FIRST_CACHED_INTERVAL,      // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
-        PSS_FIRST_CACHED_INTERVAL,      // ActivityManager.PROCESS_STATE_CACHED_RECENT
-        PSS_FIRST_CACHED_INTERVAL,      // ActivityManager.PROCESS_STATE_CACHED_EMPTY
+        PSS_FIRST_PERSISTENT_INTERVAL,  // PROC_MEM_PERSISTENT
+        PSS_FIRST_TOP_INTERVAL,         // PROC_MEM_TOP
+        PSS_FIRST_BACKGROUND_INTERVAL,  // PROC_MEM_IMPORTANT
+        PSS_FIRST_BACKGROUND_INTERVAL,  // PROC_MEM_SERVICE
+        PSS_FIRST_CACHED_INTERVAL,      // PROC_MEM_CACHED
     };
 
     private static final long[] sSameAwakePssTimes = new long[] {
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_PERSISTENT
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_PERSISTENT_UI
-        PSS_SAME_TOP_INTERVAL,          // ActivityManager.PROCESS_STATE_TOP
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_BACKUP
-        PSS_SAME_SERVICE_INTERVAL,      // ActivityManager.PROCESS_STATE_SERVICE
-        PSS_SAME_SERVICE_INTERVAL,      // ActivityManager.PROCESS_STATE_RECEIVER
-        PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_TOP_SLEEPING
-        PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
-        PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_HOME
-        PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
-        PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
-        PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
-        PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_CACHED_RECENT
-        PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_CACHED_EMPTY
+        PSS_SAME_PERSISTENT_INTERVAL,   // PROC_MEM_PERSISTENT
+        PSS_SAME_TOP_INTERVAL,          // PROC_MEM_TOP
+        PSS_SAME_IMPORTANT_INTERVAL,    // PROC_MEM_IMPORTANT
+        PSS_SAME_SERVICE_INTERVAL,      // PROC_MEM_SERVICE
+        PSS_SAME_CACHED_INTERVAL,       // PROC_MEM_CACHED
     };
 
     private static final long[] sFirstAsleepPssTimes = new long[] {
-        PSS_FIRST_ASLEEP_PERSISTENT_INTERVAL,   // ActivityManager.PROCESS_STATE_PERSISTENT
-        PSS_FIRST_ASLEEP_PERSISTENT_INTERVAL,   // ActivityManager.PROCESS_STATE_PERSISTENT_UI
-        PSS_FIRST_ASLEEP_TOP_INTERVAL,          // ActivityManager.PROCESS_STATE_TOP
-        PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL,   // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
-        PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL,   // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
-        PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL,   // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
-        PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL,   // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
-        PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL,   // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
-        PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL,   // ActivityManager.PROCESS_STATE_BACKUP
-        PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL,   // ActivityManager.PROCESS_STATE_SERVICE
-        PSS_FIRST_ASLEEP_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_RECEIVER
-        PSS_FIRST_ASLEEP_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_TOP_SLEEPING
-        PSS_FIRST_ASLEEP_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
-        PSS_FIRST_ASLEEP_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_HOME
-        PSS_FIRST_ASLEEP_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
-        PSS_FIRST_ASLEEP_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
-        PSS_FIRST_ASLEEP_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
-        PSS_FIRST_ASLEEP_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_CACHED_RECENT
-        PSS_FIRST_ASLEEP_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_CACHED_EMPTY
+        PSS_FIRST_ASLEEP_PERSISTENT_INTERVAL,   // PROC_MEM_PERSISTENT
+        PSS_FIRST_ASLEEP_TOP_INTERVAL,          // PROC_MEM_TOP
+        PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL,   // PROC_MEM_IMPORTANT
+        PSS_FIRST_ASLEEP_BACKGROUND_INTERVAL,   // PROC_MEM_SERVICE
+        PSS_FIRST_ASLEEP_CACHED_INTERVAL,       // PROC_MEM_CACHED
     };
 
     private static final long[] sSameAsleepPssTimes = new long[] {
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_PERSISTENT
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_PERSISTENT_UI
-        PSS_SAME_TOP_INTERVAL,          // ActivityManager.PROCESS_STATE_TOP
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
-        PSS_SAME_IMPORTANT_INTERVAL,    // ActivityManager.PROCESS_STATE_BACKUP
-        PSS_SAME_SERVICE_INTERVAL,      // ActivityManager.PROCESS_STATE_SERVICE
-        PSS_SAME_SERVICE_INTERVAL,      // ActivityManager.PROCESS_STATE_RECEIVER
-        PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_TOP_SLEEPING
-        PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
-        PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_HOME
-        PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
-        PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
-        PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
-        PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_CACHED_RECENT
-        PSS_SAME_CACHED_INTERVAL,       // ActivityManager.PROCESS_STATE_CACHED_EMPTY
+        PSS_SAME_PERSISTENT_INTERVAL,   // PROC_MEM_PERSISTENT
+        PSS_SAME_TOP_INTERVAL,          // PROC_MEM_TOP
+        PSS_SAME_IMPORTANT_INTERVAL,    // PROC_MEM_IMPORTANT
+        PSS_SAME_SERVICE_INTERVAL,      // PROC_MEM_SERVICE
+        PSS_SAME_CACHED_INTERVAL,       // PROC_MEM_CACHED
     };
 
     private static final long[] sTestFirstPssTimes = new long[] {
-        PSS_TEST_FIRST_TOP_INTERVAL,        // ActivityManager.PROCESS_STATE_PERSISTENT
-        PSS_TEST_FIRST_TOP_INTERVAL,        // ActivityManager.PROCESS_STATE_PERSISTENT_UI
-        PSS_TEST_FIRST_TOP_INTERVAL,        // ActivityManager.PROCESS_STATE_TOP
-        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
-        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
-        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
-        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
-        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
-        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_BACKUP
-        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_SERVICE
-        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_RECEIVER
-        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_TOP_SLEEPING
-        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
-        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_HOME
-        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
-        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
-        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
-        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_RECENT
-        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // ActivityManager.PROCESS_STATE_CACHED_EMPTY
+        PSS_TEST_FIRST_TOP_INTERVAL,        // PROC_MEM_PERSISTENT
+        PSS_TEST_FIRST_TOP_INTERVAL,        // PROC_MEM_TOP
+        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // PROC_MEM_IMPORTANT
+        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // PROC_MEM_SERVICE
+        PSS_TEST_FIRST_BACKGROUND_INTERVAL, // PROC_MEM_CACHED
     };
 
     private static final long[] sTestSamePssTimes = new long[] {
-        PSS_TEST_SAME_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_PERSISTENT
-        PSS_TEST_SAME_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_PERSISTENT_UI
-        PSS_TEST_SAME_IMPORTANT_INTERVAL,   // ActivityManager.PROCESS_STATE_TOP
-        PSS_TEST_SAME_IMPORTANT_INTERVAL,   // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
-        PSS_TEST_SAME_IMPORTANT_INTERVAL,   // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
-        PSS_TEST_SAME_IMPORTANT_INTERVAL,   // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
-        PSS_TEST_SAME_IMPORTANT_INTERVAL,   // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
-        PSS_TEST_SAME_IMPORTANT_INTERVAL,   // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
-        PSS_TEST_SAME_IMPORTANT_INTERVAL,   // ActivityManager.PROCESS_STATE_BACKUP
-        PSS_TEST_SAME_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_SERVICE
-        PSS_TEST_SAME_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_RECEIVER
-        PSS_TEST_SAME_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_TOP_SLEEPING
-        PSS_TEST_SAME_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
-        PSS_TEST_SAME_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_HOME
-        PSS_TEST_SAME_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_LAST_ACTIVITY
-        PSS_TEST_SAME_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
-        PSS_TEST_SAME_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT
-        PSS_TEST_SAME_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_CACHED_RECENT
-        PSS_TEST_SAME_BACKGROUND_INTERVAL,  // ActivityManager.PROCESS_STATE_CACHED_EMPTY
+        PSS_TEST_SAME_BACKGROUND_INTERVAL,  // PROC_MEM_PERSISTENT
+        PSS_TEST_SAME_IMPORTANT_INTERVAL,   // PROC_MEM_TOP
+        PSS_TEST_SAME_IMPORTANT_INTERVAL,   // PROC_MEM_IMPORTANT
+        PSS_TEST_SAME_BACKGROUND_INTERVAL,  // PROC_MEM_SERVICE
+        PSS_TEST_SAME_BACKGROUND_INTERVAL,  // PROC_MEM_CACHED
     };
 
+    public static final class ProcStateMemTracker {
+        final int[] mHighestMem = new int[PROC_MEM_NUM];
+        int mTotalHighestMem = PROC_MEM_CACHED;
+        float mCurFactor = 1.0f;
+
+        int mPendingMemState;
+        int mPendingHighestMemState;
+        boolean mPendingSame;
+
+        public ProcStateMemTracker() {
+            for (int i = PROC_MEM_PERSISTENT; i < PROC_MEM_NUM; i++) {
+                mHighestMem[i] = PROC_MEM_NUM;
+            }
+            mPendingMemState = -1;
+        }
+
+        public void dumpLine(PrintWriter pw) {
+            pw.print("best=");
+            pw.print(mTotalHighestMem);
+            pw.print(" ");
+            pw.print(mCurFactor);
+            pw.print("x (");
+            for (int i = 0; i < PROC_MEM_NUM; i++) {
+                if (i != 0) {
+                    pw.print(", ");
+                }
+                pw.print(i);
+                pw.print("=");
+                pw.print(mHighestMem[i]);
+            }
+            pw.print(")");
+            if (mPendingMemState >= 0) {
+                pw.print(" / pending state=");
+                pw.print(mPendingMemState);
+                pw.print(" highest=");
+                pw.print(mPendingHighestMemState);
+                pw.print(" same=");
+                pw.print(mPendingSame);
+            }
+            pw.println();
+        }
+    }
+
     public static boolean procStatesDifferForMem(int procState1, int procState2) {
         return sProcStateToProcMem[procState1] != sProcStateToProcMem[procState2];
     }
@@ -707,16 +671,50 @@
         return test ? PSS_TEST_MIN_TIME_FROM_STATE_CHANGE : PSS_MIN_TIME_FROM_STATE_CHANGE;
     }
 
-    public static long computeNextPssTime(int procState, boolean first, boolean test,
+    public static void commitNextPssTime(ProcStateMemTracker tracker) {
+        if (tracker.mPendingMemState >= 0) {
+            tracker.mHighestMem[tracker.mPendingMemState] = tracker.mPendingHighestMemState;
+            tracker.mTotalHighestMem = tracker.mPendingHighestMemState;
+            if (tracker.mPendingSame) {
+                tracker.mCurFactor *= 1.5f;
+            } else {
+                tracker.mCurFactor = 1;
+            }
+            tracker.mPendingMemState = -1;
+        }
+    }
+
+    public static void abortNextPssTime(ProcStateMemTracker tracker) {
+        tracker.mPendingMemState = -1;
+    }
+
+    public static long computeNextPssTime(int procState, ProcStateMemTracker tracker, boolean test,
             boolean sleeping, long now) {
+        boolean first;
+        final int memState = sProcStateToProcMem[procState];
+        if (tracker != null) {
+            final int highestMemState = memState < tracker.mTotalHighestMem
+                    ? memState : tracker.mTotalHighestMem;
+            first = highestMemState < tracker.mHighestMem[memState];
+            tracker.mPendingMemState = memState;
+            tracker.mPendingHighestMemState = highestMemState;
+            tracker.mPendingSame = !first;
+        } else {
+            first = true;
+        }
         final long[] table = test
                 ? (first
-                        ? sTestFirstPssTimes
-                        : sTestSamePssTimes)
+                ? sTestFirstPssTimes
+                : sTestSamePssTimes)
                 : (first
-                        ? (sleeping ? sFirstAsleepPssTimes : sFirstAwakePssTimes)
-                        : (sleeping ? sSameAsleepPssTimes : sSameAwakePssTimes));
-        return now + table[procState];
+                ? (sleeping ? sFirstAsleepPssTimes : sFirstAwakePssTimes)
+                : (sleeping ? sSameAsleepPssTimes : sSameAwakePssTimes));
+        long delay = (long)(table[memState] * (tracker != null && !first
+                ? tracker.mCurFactor : 1.0f));
+        if (delay > PSS_MAX_INTERVAL) {
+            delay = PSS_MAX_INTERVAL;
+        }
+        return now + delay;
     }
 
     long getMemLevel(int adjustment) {
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 03e140d..1f60755 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -66,6 +66,8 @@
     final String processName;   // name of the process
     // List of packages running in the process
     final ArrayMap<String, ProcessStats.ProcessStateHolder> pkgList = new ArrayMap<>();
+    final ProcessList.ProcStateMemTracker procStateMemTracker
+            = new ProcessList.ProcStateMemTracker();
     UidRecord uidRecord;        // overall state of process's uid.
     ArraySet<String> pkgDeps;   // additional packages we have a dependency on
     IApplicationThread thread;  // the actual proc...  may be null only if
@@ -102,6 +104,7 @@
     int repProcState = PROCESS_STATE_NONEXISTENT; // Last reported process state
     int setProcState = PROCESS_STATE_NONEXISTENT; // Last set process state in process tracker
     int pssProcState = PROCESS_STATE_NONEXISTENT; // Currently requesting pss for
+    int pssStatType;            // The type of stat collection that we are currently requesting
     int savedPriority;          // Previous priority value if we're switching to non-SCHED_OTHER
     int renderThreadTid;        // TID for RenderThread
     boolean serviceb;           // Process currently is on the service B list
@@ -285,6 +288,7 @@
                 TimeUtils.formatDuration(lastActivityTime, nowUptime, pw);
                 pw.print(" lastPssTime=");
                 TimeUtils.formatDuration(lastPssTime, nowUptime, pw);
+                pw.print(" pssStatType="); pw.print(pssStatType);
                 pw.print(" nextPssTime=");
                 TimeUtils.formatDuration(nextPssTime, nowUptime, pw);
                 pw.println();
@@ -295,6 +299,8 @@
                 pw.print(" lastCachedPss="); DebugUtils.printSizeValue(pw, lastCachedPss*1024);
                 pw.print(" lastCachedSwapPss="); DebugUtils.printSizeValue(pw, lastCachedSwapPss*1024);
                 pw.println();
+        pw.print(prefix); pw.print("procStateMemTracker: ");
+        procStateMemTracker.dumpLine(pw);
         pw.print(prefix); pw.print("cached="); pw.print(cached);
                 pw.print(" empty="); pw.println(empty);
         if (serviceb) {
diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
index 5f9d616..2963c4f 100644
--- a/services/core/java/com/android/server/am/ProcessStatsService.java
+++ b/services/core/java/com/android/server/am/ProcessStatsService.java
@@ -220,8 +220,9 @@
     }
 
     public void writeStateLocked(boolean sync, final boolean commit) {
+        final long totalTime;
         synchronized (mPendingWriteLock) {
-            long now = SystemClock.uptimeMillis();
+            final long now = SystemClock.uptimeMillis();
             if (mPendingWrite == null || !mPendingWriteCommitted) {
                 mPendingWrite = Parcel.obtain();
                 mProcessStats.mTimePeriodEndRealtime = SystemClock.elapsedRealtime();
@@ -238,19 +239,19 @@
                 updateFile();
             }
             mLastWriteTime = SystemClock.uptimeMillis();
-            if (DEBUG) Slog.d(TAG, "Prepared write state in "
-                    + (SystemClock.uptimeMillis()-now) + "ms");
+            totalTime = SystemClock.uptimeMillis() - now;
+            if (DEBUG) Slog.d(TAG, "Prepared write state in " + now + "ms");
             if (!sync) {
                 BackgroundThread.getHandler().post(new Runnable() {
                     @Override public void run() {
-                        performWriteState();
+                        performWriteState(totalTime);
                     }
                 });
                 return;
             }
         }
 
-        performWriteState();
+        performWriteState(totalTime);
     }
 
     private void updateFile() {
@@ -259,7 +260,7 @@
         mLastWriteTime = SystemClock.uptimeMillis();
     }
 
-    void performWriteState() {
+    void performWriteState(long initialTime) {
         if (DEBUG) Slog.d(TAG, "Performing write to " + mFile.getBaseFile());
         Parcel data;
         AtomicFile file;
@@ -275,12 +276,15 @@
             mWriteLock.lock();
         }
 
+        final long startTime = SystemClock.uptimeMillis();
         FileOutputStream stream = null;
         try {
             stream = file.startWrite();
             stream.write(data.marshall());
             stream.flush();
             file.finishWrite(stream);
+            com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+                    "procstats", SystemClock.uptimeMillis() - startTime + initialTime);
             if (DEBUG) Slog.d(TAG, "Write completed successfully!");
         } catch (IOException e) {
             Slog.w(TAG, "Error writing process statistics", e);
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index e498666..5a37ee2 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -481,9 +481,9 @@
 
         maybeDeleteLegacyPendingInfoLocked(syncDir);
 
-        mAccountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
-        mStatusFile = new AtomicFile(new File(syncDir, "status.bin"));
-        mStatisticsFile = new AtomicFile(new File(syncDir, "stats.bin"));
+        mAccountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"), "sync-accounts");
+        mStatusFile = new AtomicFile(new File(syncDir, "status.bin"), "sync-status");
+        mStatisticsFile = new AtomicFile(new File(syncDir, "stats.bin"), "sync-stats");
 
         readAccountInfoLocked();
         readStatusLocked();
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index cbf46f8..1af03de 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -771,7 +771,8 @@
         private final AtomicFile mAtomicFile;
 
         public Injector() {
-            mAtomicFile = new AtomicFile(new File("/data/system/display-manager-state.xml"));
+            mAtomicFile = new AtomicFile(new File("/data/system/display-manager-state.xml"),
+                    "display-state");
         }
 
         public InputStream openRead() throws FileNotFoundException {
diff --git a/services/core/java/com/android/server/input/PersistentDataStore.java b/services/core/java/com/android/server/input/PersistentDataStore.java
index f67e0fd..372db41 100644
--- a/services/core/java/com/android/server/input/PersistentDataStore.java
+++ b/services/core/java/com/android/server/input/PersistentDataStore.java
@@ -82,7 +82,8 @@
     private boolean mDirty;
 
     public PersistentDataStore() {
-        mAtomicFile = new AtomicFile(new File("/data/system/input-manager-state.xml"));
+        mAtomicFile = new AtomicFile(new File("/data/system/input-manager-state.xml"),
+                "input-state");
     }
 
     public void saveIfNeeded() {
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index a24a4ac..f4bbf4c 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -29,6 +29,7 @@
 import android.os.Handler;
 import android.os.PersistableBundle;
 import android.os.Process;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.text.format.DateUtils;
 import android.util.ArraySet;
@@ -133,7 +134,7 @@
         File systemDir = new File(dataDir, "system");
         File jobDir = new File(systemDir, "job");
         jobDir.mkdirs();
-        mJobsFile = new AtomicFile(new File(jobDir, "jobs.xml"));
+        mJobsFile = new AtomicFile(new File(jobDir, "jobs.xml"), "jobs");
 
         mJobSet = new JobSet();
 
@@ -361,6 +362,7 @@
             int numSystemJobs = 0;
             int numSyncJobs = 0;
             try {
+                final long startTime = SystemClock.uptimeMillis();
                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
                 XmlSerializer out = new FastXmlSerializer();
                 out.setOutput(baos, StandardCharsets.UTF_8.name());
@@ -393,7 +395,7 @@
                 out.endDocument();
 
                 // Write out to disk in one fell swoop.
-                FileOutputStream fos = mJobsFile.startWrite();
+                FileOutputStream fos = mJobsFile.startWrite(startTime);
                 fos.write(baos.toByteArray());
                 mJobsFile.finishWrite(fos);
                 mDirtyOperations = 0;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 0e54768..f09de52 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -551,7 +551,7 @@
 
         mSuppressDefaultPolicy = suppressDefaultPolicy;
 
-        mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
+        mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"), "net-policy");
 
         mAppOps = context.getSystemService(AppOpsManager.class);
 
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistSettings.java b/services/core/java/com/android/server/net/watchlist/WatchlistSettings.java
index b78fe4d..f5ba889 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistSettings.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistSettings.java
@@ -77,7 +77,7 @@
 
     @VisibleForTesting
     protected WatchlistSettings(File xmlFile) {
-        mXmlFile = new AtomicFile(xmlFile);
+        mXmlFile = new AtomicFile(xmlFile, "net-watchlist");
         reloadSettings();
         if (mPrivacySecretKey == null) {
             // Generate a new secret key and save settings
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4c9da89..6a2b923 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1406,7 +1406,7 @@
                         AppGlobals.getPackageManager()),
                 new ConditionProviders(getContext(), mUserProfiles, AppGlobals.getPackageManager()),
                 null, snoozeHelper, new NotificationUsageStats(getContext()),
-                new AtomicFile(new File(systemDir, "notification_policy.xml")),
+                new AtomicFile(new File(systemDir, "notification_policy.xml"), "notification-policy"),
                 (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE),
                 getGroupHelper());
 
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 2041de6..4bc4a7e 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -228,7 +228,7 @@
             @NonNull final Installer installer) {
         super(context);
         mSettingsFile =
-            new AtomicFile(new File(Environment.getDataSystemDirectory(), "overlays.xml"));
+            new AtomicFile(new File(Environment.getDataSystemDirectory(), "overlays.xml"), "overlays");
         mPackageManager = new PackageManagerHelper();
         mUserManager = UserManagerService.getInstance();
         IdmapManager im = new IdmapManager(installer);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 16fae99..59f9dae 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -58,6 +58,7 @@
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SELinux;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.storage.StorageManager;
@@ -193,7 +194,8 @@
         mCallbacks = new Callbacks(mInstallThread.getLooper());
 
         mSessionsFile = new AtomicFile(
-                new File(Environment.getDataSystemDirectory(), "install_sessions.xml"));
+                new File(Environment.getDataSystemDirectory(), "install_sessions.xml"),
+                "package-session");
         mSessionsDir = new File(Environment.getDataSystemDirectory(), "install_sessions");
         mSessionsDir.mkdirs();
     }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 8ce412e..de74c30 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -1994,6 +1994,8 @@
         if (DEBUG_MU) {
             Log.i(TAG, "Writing package restrictions for user=" + userId);
         }
+        final long startTime = SystemClock.uptimeMillis();
+
         // Keep the old stopped packages around until we know the new ones have
         // been successfully written.
         File userPackagesStateFile = getUserPackagesStateFile(userId);
@@ -2127,6 +2129,9 @@
                     |FileUtils.S_IRGRP|FileUtils.S_IWGRP,
                     -1, -1);
 
+            com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+                    "package-user-" + userId, SystemClock.uptimeMillis() - startTime);
+
             // Done, all is good!
             return;
         } catch(java.io.IOException e) {
@@ -2388,6 +2393,8 @@
     void writeLPr() {
         //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
 
+        final long startTime = SystemClock.uptimeMillis();
+
         // Keep the old settings around until we know the new ones have
         // been successfully written.
         if (mSettingsFilename.exists()) {
@@ -2533,6 +2540,8 @@
             writePackageListLPr();
             writeAllUsersPackageRestrictionsLPr();
             writeAllRuntimePermissionsLPr();
+            com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
+                    "package", SystemClock.uptimeMillis() - startTime);
             return;
 
         } catch(java.io.IOException e) {
@@ -5131,7 +5140,8 @@
         }
 
         private void writePermissionsSync(int userId) {
-            AtomicFile destination = new AtomicFile(getUserRuntimePermissionsFile(userId));
+            AtomicFile destination = new AtomicFile(getUserRuntimePermissionsFile(userId),
+                    "package-perms-" + userId);
 
             ArrayMap<String, List<PermissionState>> permissionsForPackage = new ArrayMap<>();
             ArrayMap<String, List<PermissionState>> permissionsForSharedUser = new ArrayMap<>();
diff --git a/services/core/java/com/android/server/timezone/PackageStatusStorage.java b/services/core/java/com/android/server/timezone/PackageStatusStorage.java
index 251a277..04f0871 100644
--- a/services/core/java/com/android/server/timezone/PackageStatusStorage.java
+++ b/services/core/java/com/android/server/timezone/PackageStatusStorage.java
@@ -81,7 +81,7 @@
     private final AtomicFile mPackageStatusFile;
 
     PackageStatusStorage(File storageDir) {
-        mPackageStatusFile = new AtomicFile(new File(storageDir, "package-status.xml"));
+        mPackageStatusFile = new AtomicFile(new File(storageDir, "package-status.xml"), "timezone-status");
     }
 
     /**
diff --git a/services/core/java/com/android/server/tv/PersistentDataStore.java b/services/core/java/com/android/server/tv/PersistentDataStore.java
index 85a8829..8f2194c 100644
--- a/services/core/java/com/android/server/tv/PersistentDataStore.java
+++ b/services/core/java/com/android/server/tv/PersistentDataStore.java
@@ -91,7 +91,7 @@
                 throw new IllegalStateException("User dir cannot be created: " + userDir);
             }
         }
-        mAtomicFile = new AtomicFile(new File(userDir, "tv-input-manager-state.xml"));
+        mAtomicFile = new AtomicFile(new File(userDir, "tv-input-manager-state.xml"), "tv-input-state");
     }
 
     public boolean isParentalControlsEnabled() {
diff --git a/services/core/java/com/android/server/wm/DisplaySettings.java b/services/core/java/com/android/server/wm/DisplaySettings.java
index 7f79686..97b64dc 100644
--- a/services/core/java/com/android/server/wm/DisplaySettings.java
+++ b/services/core/java/com/android/server/wm/DisplaySettings.java
@@ -64,7 +64,7 @@
     public DisplaySettings() {
         File dataDir = Environment.getDataDirectory();
         File systemDir = new File(dataDir, "system");
-        mFile = new AtomicFile(new File(systemDir, "display_settings.xml"));
+        mFile = new AtomicFile(new File(systemDir, "display_settings.xml"), "wm-displays");
     }
 
     public void getOverscanLocked(String name, String uniqueId, Rect outRect) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PasswordBlacklist.java b/services/devicepolicy/java/com/android/server/devicepolicy/PasswordBlacklist.java
index 6a9b53a..a17a107 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PasswordBlacklist.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PasswordBlacklist.java
@@ -47,7 +47,7 @@
      * This is a lightweight operation to prepare variables but not perform any IO.
      */
     public PasswordBlacklist(File file) {
-        mFile = new AtomicFile(file);
+        mFile = new AtomicFile(file, "device-policy");
     }
 
     /**
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index 917e651..5f1f5e4 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -208,7 +208,7 @@
         mParentUser = user;
         mSettingsFile = new AtomicFile(new File(
                 Environment.getUserSystemDirectory(user.getIdentifier()),
-                "usb_device_manager.xml"));
+                "usb_device_manager.xml"), "usb-state");
 
         mDisablePermissionDialogs = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_disableUsbPermissionDialogs);