diff options
7 files changed, 438 insertions, 165 deletions
| diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index bf89fa6d89fe..4568525f8232 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -552,7 +552,7 @@ public final class ActivityThread {          private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";          // Formatting for checkin service - update version if row format changes -        private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 2; +        private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 3;          private void updatePendingConfiguration(Configuration config) {              synchronized (mPackages) { @@ -972,43 +972,48 @@ public final class ActivityThread {                  pw.print(memInfo.nativePss); pw.print(',');                  pw.print(memInfo.dalvikPss); pw.print(',');                  pw.print(memInfo.otherPss); pw.print(','); -                pw.print(memInfo.nativePss + memInfo.dalvikPss + memInfo.otherPss); pw.print(','); +                pw.print(memInfo.getTotalPss()); pw.print(','); -                // Heap info - proportional set size +                // Heap info - swappable set size                  pw.print(memInfo.nativeSwappablePss); pw.print(',');                  pw.print(memInfo.dalvikSwappablePss); pw.print(',');                  pw.print(memInfo.otherSwappablePss); pw.print(','); -                pw.print(memInfo.nativeSwappablePss + memInfo.dalvikSwappablePss + memInfo.otherSwappablePss); pw.print(','); +                pw.print(memInfo.getTotalSwappablePss()); pw.print(',');                  // Heap info - shared dirty                  pw.print(memInfo.nativeSharedDirty); pw.print(',');                  pw.print(memInfo.dalvikSharedDirty); pw.print(',');                  pw.print(memInfo.otherSharedDirty); pw.print(','); -                pw.print(memInfo.nativeSharedDirty + memInfo.dalvikSharedDirty -                        + memInfo.otherSharedDirty); pw.print(','); +                pw.print(memInfo.getTotalSharedDirty()); pw.print(',');                  // Heap info - shared clean                  pw.print(memInfo.nativeSharedClean); pw.print(',');                  pw.print(memInfo.dalvikSharedClean); pw.print(',');                  pw.print(memInfo.otherSharedClean); pw.print(','); -                pw.print(memInfo.nativeSharedClean + memInfo.dalvikSharedClean -                        + memInfo.otherSharedClean); pw.print(','); +                pw.print(memInfo.getTotalSharedClean()); pw.print(',');                  // Heap info - private Dirty                  pw.print(memInfo.nativePrivateDirty); pw.print(',');                  pw.print(memInfo.dalvikPrivateDirty); pw.print(',');                  pw.print(memInfo.otherPrivateDirty); pw.print(','); -                pw.print(memInfo.nativePrivateDirty + memInfo.dalvikPrivateDirty -                        + memInfo.otherPrivateDirty); pw.print(','); - +                pw.print(memInfo.getTotalPrivateDirty()); pw.print(',');                  // Heap info - private Clean                  pw.print(memInfo.nativePrivateClean); pw.print(',');                  pw.print(memInfo.dalvikPrivateClean); pw.print(',');                  pw.print(memInfo.otherPrivateClean); pw.print(','); -                pw.print(memInfo.nativePrivateClean + memInfo.dalvikPrivateClean -                        + memInfo.otherPrivateClean); pw.print(','); - +                pw.print(memInfo.getTotalPrivateClean()); pw.print(','); + +                // Heap info - other areas +                for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) { +                    pw.print(Debug.MemoryInfo.getOtherLabel(i)); pw.print(','); +                    pw.print(memInfo.getOtherPss(i)); pw.print(','); +                    pw.print(memInfo.getOtherSwappablePss(i)); pw.print(','); +                    pw.print(memInfo.getOtherSharedDirty(i)); pw.print(','); +                    pw.print(memInfo.getOtherSharedClean(i)); pw.print(','); +                    pw.print(memInfo.getOtherPrivateDirty(i)); pw.print(','); +                    pw.print(memInfo.getOtherPrivateClean(i)); pw.print(','); +                }                  // Object counts                  pw.print(viewInstanceCount); pw.print(','); diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp index f4cf2eeab021..8b7f3dd5fd3c 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -394,12 +394,16 @@ static jlong android_os_Debug_getPssPid(JNIEnv *env, jobject clazz, jint pid)      if (fp == 0) return 0;      while (true) { -        if (fgets(line, 1024, fp) == 0) { +        if (fgets(line, 1024, fp) == NULL) {              break;          } -        if (sscanf(line, "Pss: %d kB", &temp) == 1) { -            pss += temp; +        if (strncmp(line, "Pss: ", 5) == 0) { +            char* c = line + 5; +            while (*c != 0 && (*c < '0' || *c > '9')) { +                c++; +            } +            pss += atoi(c);          }      } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index e37eec615ea6..f201563239b9 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -30,6 +30,7 @@ import android.util.ArrayMap;  import com.android.internal.R;  import com.android.internal.annotations.GuardedBy;  import com.android.internal.app.IAppOpsService; +import com.android.internal.os.BackgroundThread;  import com.android.internal.os.BatteryStatsImpl;  import com.android.internal.os.ProcessStats;  import com.android.internal.os.TransferPipe; @@ -266,6 +267,20 @@ public final class ActivityManagerService extends ActivityManagerNative      // The minimum amount of time between successive GC requests for a process.      static final int GC_MIN_INTERVAL = 60*1000; +    // The minimum amount of time between successive PSS requests for a process. +    static final int PSS_MIN_INTERVAL = 2*60*1000; + +    // The amount of time we will sample PSS of the current top process while the +    // screen is on. +    static final int PSS_TOP_INTERVAL = 5*60*1000; + +    // The maximum amount of time for a process to be around until we will take +    // a PSS snapshot on its next oom change. +    static final int PSS_MAX_INTERVAL = 30*60*1000; + +    // The minimum amount of time between successive PSS requests for a process. +    static final int FULL_PSS_MIN_INTERVAL = 10*60*1000; +      // The rate at which we check for apps using excessive power -- 15 mins.      static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000; @@ -495,8 +510,17 @@ public final class ActivityManagerService extends ActivityManagerNative      /**       * List of processes that should gc as soon as things are idle.       */ -    final ArrayList<ProcessRecord> mProcessesToGc -            = new ArrayList<ProcessRecord>(); +    final ArrayList<ProcessRecord> mProcessesToGc = new ArrayList<ProcessRecord>(); + +    /** +     * Processes we want to collect PSS data from. +     */ +    final ArrayList<ProcessRecord> mPendingPssProcesses = new ArrayList<ProcessRecord>(); + +    /** +     * Last time we requested PSS data of all processes. +     */ +    long mLastFullPssTime = SystemClock.uptimeMillis();      /**       * This is the process holding what we currently consider to be @@ -1480,6 +1504,51 @@ public final class ActivityManagerService extends ActivityManagerNative          }      }; +    static final int COLLECT_PSS_BG_MSG = 1; + +    final Handler mBgHandler = new Handler(BackgroundThread.getHandler().getLooper()) { +        @Override +        public void handleMessage(Message msg) { +            switch (msg.what) { +            case COLLECT_PSS_BG_MSG: { +                int i=0; +                long start = SystemClock.uptimeMillis(); +                do { +                    ProcessRecord proc; +                    int oomAdj; +                    int pid; +                    synchronized (ActivityManagerService.this) { +                        if (i >= mPendingPssProcesses.size()) { +                            Slog.i(TAG, "Collected PSS of " + i + " processes in " +                                    + (SystemClock.uptimeMillis()-start) + "ms"); +                            mPendingPssProcesses.clear(); +                            return; +                        } +                        proc = mPendingPssProcesses.get(i); +                        if (proc.thread != null) { +                            oomAdj = proc.setAdj; +                            pid = proc.pid; +                            i++; +                        } else { +                            proc = null; +                            oomAdj = 0; +                            pid = 0; +                        } +                    } +                    if (proc != null) { +                        long pss = Debug.getPss(pid); +                        synchronized (ActivityManagerService.this) { +                            if (proc.thread != null && proc.setAdj == oomAdj && proc.pid == pid) { +                                proc.baseProcessTracker.addPss(pss, true); +                            } +                        } +                    } +                } while (true); +            } +            } +        } +    }; +      public static void setSystemProcess() {          try {              ActivityManagerService m = mSelf; @@ -3906,8 +3975,24 @@ public final class ActivityManagerService extends ActivityManagerNative          enforceNotIsolatedCaller("getProcessMemoryInfo");          Debug.MemoryInfo[] infos = new Debug.MemoryInfo[pids.length];          for (int i=pids.length-1; i>=0; i--) { +            ProcessRecord proc; +            int oomAdj; +            synchronized (this) { +                synchronized (mPidsSelfLocked) { +                    proc = mPidsSelfLocked.get(pids[i]); +                    oomAdj = proc != null ? proc.setAdj : 0; +                } +            }              infos[i] = new Debug.MemoryInfo();              Debug.getMemoryInfo(pids[i], infos[i]); +            if (proc != null) { +                synchronized (this) { +                    if (proc.thread != null && proc.setAdj == oomAdj) { +                        // Record this for posterity if the process has been stable. +                        proc.baseProcessTracker.addPss(infos[i].getTotalPss(), false); +                    } +                } +            }          }          return infos;      } @@ -3917,7 +4002,23 @@ public final class ActivityManagerService extends ActivityManagerNative          enforceNotIsolatedCaller("getProcessPss");          long[] pss = new long[pids.length];          for (int i=pids.length-1; i>=0; i--) { +            ProcessRecord proc; +            int oomAdj; +            synchronized (this) { +                synchronized (mPidsSelfLocked) { +                    proc = mPidsSelfLocked.get(pids[i]); +                    oomAdj = proc != null ? proc.setAdj : 0; +                } +            }              pss[i] = Debug.getPss(pids[i]); +            if (proc != null) { +                synchronized (this) { +                    if (proc.thread != null && proc.setAdj == oomAdj) { +                        // Record this for posterity if the process has been stable. +                        proc.baseProcessTracker.addPss(pss[i], false); +                    } +                } +            }          }          return pss;      } @@ -4350,7 +4451,7 @@ public final class ActivityManagerService extends ActivityManagerNative              thread.asBinder().linkToDeath(adr, 0);              app.deathRecipient = adr;          } catch (RemoteException e) { -            app.resetPackageList(); +            app.resetPackageList(mProcessTracker);              startProcessLocked(app, "link fail", processName);              return false;          } @@ -4442,7 +4543,7 @@ public final class ActivityManagerService extends ActivityManagerNative              // an infinite loop of restarting processes...              Slog.w(TAG, "Exception thrown during bind!", e); -            app.resetPackageList(); +            app.resetPackageList(mProcessTracker);              app.unlinkDeathRecipient();              startProcessLocked(app, "bind fail", processName);              return false; @@ -4630,8 +4731,19 @@ public final class ActivityManagerService extends ActivityManagerNative                          final int userId = mStartedUsers.keyAt(i);                          Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);                          intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); -                        broadcastIntentLocked(null, null, intent, -                                null, null, 0, null, null, +                        broadcastIntentLocked(null, null, intent, null, +                                new IIntentReceiver.Stub() { +                                    @Override +                                    public void performReceive(Intent intent, int resultCode, +                                            String data, Bundle extras, boolean ordered, +                                            boolean sticky, int sendingUser) { +                                        synchronized (ActivityManagerService.this) { +                                            requestPssAllProcsLocked(SystemClock.uptimeMillis(), +                                                    true); +                                        } +                                    } +                                }, +                                0, null, null,                                  android.Manifest.permission.RECEIVE_BOOT_COMPLETED,                                  AppOpsManager.OP_NONE, false, false, MY_PID, Process.SYSTEM_UID,                                  userId); @@ -10934,7 +11046,7 @@ public final class ActivityManagerService extends ActivityManagerNative          long uptime = SystemClock.uptimeMillis();          long realtime = SystemClock.elapsedRealtime(); -        if (procs.size() == 1 || isCheckinRequest) { +        if (!brief && !oomOnly && (procs.size() == 1 || isCheckinRequest)) {              dumpDetails = true;          } @@ -10960,17 +11072,24 @@ public final class ActivityManagerService extends ActivityManagerNative          long totalPss = 0; +        Debug.MemoryInfo mi = null;          for (int i = procs.size() - 1 ; i >= 0 ; i--) {              ProcessRecord r = procs.get(i); -            if (r.thread != null) { +            IApplicationThread thread; +            int oomAdj; +            synchronized (this) { +                thread = r.thread; +                oomAdj = r.setAdj; +            } +            if (thread != null) {                  if (!isCheckinRequest && dumpDetails) {                      pw.println("\n** MEMINFO in pid " + r.pid + " [" + r.processName + "] **");                      pw.flush();                  } -                Debug.MemoryInfo mi = null;                  if (dumpDetails) {                      try { -                        mi = r.thread.dumpMemInfo(fd, isCheckinRequest, true, dumpDalvik, innerArgs); +                        mi = null; +                        mi = thread.dumpMemInfo(fd, isCheckinRequest, true, dumpDalvik, innerArgs);                      } catch (RemoteException e) {                          if (!isCheckinRequest) {                              pw.println("Got RemoteException!"); @@ -10978,21 +11097,31 @@ public final class ActivityManagerService extends ActivityManagerNative                          }                      }                  } else { -                    mi = new Debug.MemoryInfo(); -                    Debug.getMemoryInfo(r.pid, mi); +                    if (mi == null) { +                        mi = new Debug.MemoryInfo(); +                    } +                    if (!brief && !oomOnly) { +                        Debug.getMemoryInfo(r.pid, mi); +                    } else { +                        mi.dalvikPss = (int)Debug.getPss(r.pid); +                    } +                } + +                final long myTotalPss = mi.getTotalPss(); + +                synchronized (this) { +                    if (r.thread != null && oomAdj == r.setAdj) { +                        // Record this for posterity if the process has been stable. +                        r.baseProcessTracker.addPss(myTotalPss, true); +                    }                  }                  if (!isCheckinRequest && mi != null) { -                    long myTotalPss = mi.getTotalPss();                      totalPss += myTotalPss;                      MemItem pssItem = new MemItem(r.processName + " (pid " + r.pid + ")",                              r.processName, myTotalPss, 0);                      procMems.add(pssItem); -                    synchronized (this) { -                        r.baseProcessTracker.addPss(myTotalPss); -                    } -                      nativePss += mi.nativePss;                      dalvikPss += mi.dalvikPss;                      otherPss += mi.otherPss; @@ -11070,7 +11199,7 @@ public final class ActivityManagerService extends ActivityManagerNative                              }                          }                          for (int j=0; j<miCat.subitems.size(); j++) { -                            MemItem mi = miCat.subitems.get(j); +                            MemItem memi = miCat.subitems.get(j);                              if (j > 0) {                                  if (outTag != null) {                                      outTag.append(" "); @@ -11080,10 +11209,10 @@ public final class ActivityManagerService extends ActivityManagerNative                                  }                              }                              if (outTag != null && miCat.id <= ProcessList.FOREGROUND_APP_ADJ) { -                                appendMemBucket(outTag, mi.pss, mi.shortLabel, false); +                                appendMemBucket(outTag, memi.pss, memi.shortLabel, false);                              }                              if (outStack != null) { -                                appendMemBucket(outStack, mi.pss, mi.shortLabel, true); +                                appendMemBucket(outStack, memi.pss, memi.shortLabel, true);                              }                          }                          if (outStack != null && miCat.id >= ProcessList.FOREGROUND_APP_ADJ) { @@ -11109,7 +11238,7 @@ public final class ActivityManagerService extends ActivityManagerNative              }              pw.println("Total PSS by OOM adjustment:");              dumpMemItems(pw, "  ", oomMems, false); -            if (!oomOnly) { +            if (!brief && !oomOnly) {                  PrintWriter out = categoryPw != null ? categoryPw : pw;                  out.println();                  out.println("Total PSS by category:"); @@ -11117,29 +11246,31 @@ public final class ActivityManagerService extends ActivityManagerNative              }              pw.println();              pw.print("Total PSS: "); pw.print(totalPss); pw.println(" kB"); -            final int[] SINGLE_LONG_FORMAT = new int[] { -                Process.PROC_SPACE_TERM|Process.PROC_OUT_LONG -            }; -            long[] longOut = new long[1]; -            Process.readProcFile("/sys/kernel/mm/ksm/pages_shared", -                    SINGLE_LONG_FORMAT, null, longOut, null); -            long shared = longOut[0] * ProcessList.PAGE_SIZE / 1024; -            longOut[0] = 0; -            Process.readProcFile("/sys/kernel/mm/ksm/pages_sharing", -                    SINGLE_LONG_FORMAT, null, longOut, null); -            long sharing = longOut[0] * ProcessList.PAGE_SIZE / 1024; -            longOut[0] = 0; -            Process.readProcFile("/sys/kernel/mm/ksm/pages_unshared", -                    SINGLE_LONG_FORMAT, null, longOut, null); -            long unshared = longOut[0] * ProcessList.PAGE_SIZE / 1024; -            longOut[0] = 0; -            Process.readProcFile("/sys/kernel/mm/ksm/pages_volatile", -                    SINGLE_LONG_FORMAT, null, longOut, null); -            long voltile = longOut[0] * ProcessList.PAGE_SIZE / 1024; -            pw.print("      KSM: "); pw.print(sharing); pw.print(" kB saved from shared "); -                    pw.print(shared); pw.println(" kB"); -            pw.print("           "); pw.print(unshared); pw.print(" kB unshared; "); -                    pw.print(voltile); pw.println(" kB volatile"); +            if (!brief) { +                final int[] SINGLE_LONG_FORMAT = new int[] { +                    Process.PROC_SPACE_TERM|Process.PROC_OUT_LONG +                }; +                long[] longOut = new long[1]; +                Process.readProcFile("/sys/kernel/mm/ksm/pages_shared", +                        SINGLE_LONG_FORMAT, null, longOut, null); +                long shared = longOut[0] * ProcessList.PAGE_SIZE / 1024; +                longOut[0] = 0; +                Process.readProcFile("/sys/kernel/mm/ksm/pages_sharing", +                        SINGLE_LONG_FORMAT, null, longOut, null); +                long sharing = longOut[0] * ProcessList.PAGE_SIZE / 1024; +                longOut[0] = 0; +                Process.readProcFile("/sys/kernel/mm/ksm/pages_unshared", +                        SINGLE_LONG_FORMAT, null, longOut, null); +                long unshared = longOut[0] * ProcessList.PAGE_SIZE / 1024; +                longOut[0] = 0; +                Process.readProcFile("/sys/kernel/mm/ksm/pages_volatile", +                        SINGLE_LONG_FORMAT, null, longOut, null); +                long voltile = longOut[0] * ProcessList.PAGE_SIZE / 1024; +                pw.print("      KSM: "); pw.print(sharing); pw.print(" kB saved from shared "); +                        pw.print(shared); pw.println(" kB"); +                pw.print("           "); pw.print(unshared); pw.print(" kB unshared; "); +                        pw.print(voltile); pw.println(" kB volatile"); +            }          }      } @@ -11236,6 +11367,7 @@ public final class ActivityManagerService extends ActivityManagerNative          }          mProcessesToGc.remove(app); +        mPendingPssProcesses.remove(app);          // Dismiss any open dialogs.          if (app.crashDialog != null && !app.forceCrashReport) { @@ -11254,7 +11386,7 @@ public final class ActivityManagerService extends ActivityManagerNative          app.crashing = false;          app.notResponding = false; -        app.resetPackageList(); +        app.resetPackageList(mProcessTracker);          app.unlinkDeathRecipient();          app.thread = null;          app.forcingToForeground = null; @@ -13749,6 +13881,41 @@ public final class ActivityManagerService extends ActivityManagerNative      }      /** +     * Schedule PSS collection of a process. +     */ +    void requestPssLocked(ProcessRecord proc, long now, boolean always) { +        if (!always && now < (proc.lastPssTime+PSS_MIN_INTERVAL)) { +            return; +        } +        if (mPendingPssProcesses.contains(proc)) { +            return; +        } +        proc.lastPssTime = now; +        if (mPendingPssProcesses.size() == 0) { +            mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG); +        } +        mPendingPssProcesses.add(proc); +    } + +    /** +     * Schedule PSS collection of all processes. +     */ +    void requestPssAllProcsLocked(long now, boolean always) { +        if (!always && now < (mLastFullPssTime+FULL_PSS_MIN_INTERVAL)) { +            return; +        } +        mLastFullPssTime = now; +        mPendingPssProcesses.ensureCapacity(mLruProcesses.size()); +        mPendingPssProcesses.clear(); +        for (int i=mLruProcesses.size()-1; i>=0; i--) { +            ProcessRecord app = mLruProcesses.get(i); +            app.lastPssTime = now; +            mPendingPssProcesses.add(app); +        } +        mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG); +    } + +    /**       * Ask a given process to GC right now.       */      final void performAppGcLocked(ProcessRecord app) { @@ -13959,6 +14126,7 @@ public final class ActivityManagerService extends ActivityManagerNative                              + " during " + realtimeSince);                      EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,                              app.processName, app.setAdj, "excessive wake lock"); +                    app.baseProcessTracker.reportExcessiveWake(app.pkgList);                      Process.killProcessQuiet(app.pid);                  } else if (doCpuKills && uptimeSince > 0                          && ((cputimeUsed*100)/uptimeSince) >= 50) { @@ -13971,6 +14139,7 @@ public final class ActivityManagerService extends ActivityManagerNative                              + " during " + uptimeSince);                      EventLog.writeEvent(EventLogTags.AM_KILL, app.userId, app.pid,                              app.processName, app.setAdj, "excessive cpu"); +                    app.baseProcessTracker.reportExcessiveCpu(app.pkgList);                      Process.killProcessQuiet(app.pid);                  } else {                      app.lastWakeTime = wtime; @@ -14012,11 +14181,23 @@ public final class ActivityManagerService extends ActivityManagerNative              app.setRawAdj = app.curRawAdj;          } +        if (app == TOP_APP && now > (app.lastPssTime+PSS_TOP_INTERVAL)) { +            requestPssLocked(app, now, true); +        } +          if (app.curAdj != app.setAdj) {              if (Process.setOomAdj(app.pid, app.curAdj)) {                  if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(                      TAG, "Set " + app.pid + " " + app.processName +                      " adj " + app.curAdj + ": " + app.adjType); +                if (app.setAdj == ProcessList.SERVICE_ADJ +                        && app.curAdj == ProcessList.SERVICE_B_ADJ) { +                    // If a service is dropping to the B list, it has been running for +                    // a while, take a PSS snapshot. +                    requestPssLocked(app, now, false); +                } else if (now > (app.lastPssTime+PSS_MAX_INTERVAL)) { +                    requestPssLocked(app, now, true); +                }                  app.setAdj = app.curAdj;                  app.setAdjChanged = true;                  if (!doingAll) { @@ -14406,6 +14587,9 @@ public final class ActivityManagerService extends ActivityManagerNative                  }              }          } +        if (allChanged) { +            requestPssAllProcsLocked(now, false); +        }          if (DEBUG_OOM_ADJ) {              Slog.d(TAG, "Did OOM ADJ in " + (SystemClock.uptimeMillis()-now) + "ms"); diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java index 561dd0f2d3f2..44b61d0daab6 100644 --- a/services/java/com/android/server/am/ActivityRecord.java +++ b/services/java/com/android/server/am/ActivityRecord.java @@ -222,7 +222,7 @@ final class ActivityRecord {                  if (lastLaunchTime == 0) pw.print("0");                  else TimeUtils.formatDuration(lastLaunchTime, now, pw);                  pw.println(); -        pw.print(prefix); pw.print(" haveState="); pw.print(haveState); +        pw.print(prefix); pw.print("haveState="); pw.print(haveState);                  pw.print(" icicle="); pw.println(icicle);          pw.print(prefix); pw.print("state="); pw.print(state);                  pw.print(" stopped="); pw.print(stopped); diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java index 8d981097370e..92a15231c2c5 100644 --- a/services/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/java/com/android/server/am/ActivityStackSupervisor.java @@ -1707,6 +1707,7 @@ public final class ActivityStackSupervisor {                  r.idle = true;                  if (allResumedActivitiesIdle()) {                      mService.scheduleAppGcsLocked(); +                    mService.requestPssLocked(r.app, SystemClock.uptimeMillis(), false);                  }                  if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {                      sendThumbnail = r.app.thread; diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java index e72656f8e3f1..365009ddf842 100644 --- a/services/java/com/android/server/am/ProcessRecord.java +++ b/services/java/com/android/server/am/ProcessRecord.java @@ -62,6 +62,7 @@ final class ProcessRecord {      boolean starting;           // True if the process is being started      long lastActivityTime;      // For managing the LRU list      long lruWeight;             // Weight for ordering in LRU list +    long lastPssTime;           // Last time we requested PSS data      int maxAdj;                 // Maximum OOM adjustment for this process      int cachedAdj;              // If cached, this is the adjustment to use      int clientCachedAdj;        // If empty but cached client, this is the adjustment to use @@ -112,7 +113,6 @@ final class ProcessRecord {      boolean reportLowMemory;    // Set to true when waiting to report low mem      boolean empty;              // Is this an empty background process?      boolean cached;             // Is this a cached process? -    int lastPss;                // Last pss size reported by app.      String adjType;             // Debugging: primary thing impacting oom_adj.      int adjTypeCode;            // Debugging: adj code to report to app.      Object adjSource;           // Debugging: option dependent object. @@ -180,7 +180,12 @@ final class ProcessRecord {          pw.print(prefix); pw.print("dir="); pw.print(info.sourceDir);                  pw.print(" publicDir="); pw.print(info.publicSourceDir);                  pw.print(" data="); pw.println(info.dataDir); -        pw.print(prefix); pw.print("packageList="); pw.println(pkgList); +        pw.print(prefix); pw.print("packageList={"); +        for (int i=0; i<pkgList.size(); i++) { +            if (i > 0) pw.print(", "); +            pw.print(pkgList.keyAt(i)); +        } +        pw.println("}");          pw.print(prefix); pw.print("compat="); pw.println(compat);          if (instrumentationClass != null || instrumentationProfileFile != null                  || instrumentationArguments != null) { @@ -198,7 +203,7 @@ final class ProcessRecord {          }          pw.print(prefix); pw.print("thread="); pw.println(thread);          pw.print(prefix); pw.print("pid="); pw.print(pid); pw.print(" starting="); -                pw.print(starting); pw.print(" lastPss="); pw.println(lastPss); +                pw.println(starting);          pw.print(prefix); pw.print("lastActivityTime=");                  TimeUtils.formatDuration(lastActivityTime, now, pw);                  pw.print(" lruWeight="); pw.print(lruWeight); @@ -220,7 +225,8 @@ final class ProcessRecord {                  pw.print(" systemNoUi="); pw.print(systemNoUi);                  pw.print(" trimMemoryLevel="); pw.println(trimMemoryLevel);          pw.print(prefix); pw.print("adjSeq="); pw.print(adjSeq); -                pw.print(" lruSeq="); pw.println(lruSeq); +                pw.print(" lruSeq="); pw.print(lruSeq); +                pw.print(" lastPssTime="); pw.println(lastPssTime);          if (hasShownUi || pendingUiClean || hasAboveClient) {              pw.print(prefix); pw.print("hasShownUi="); pw.print(hasShownUi);                      pw.print(" pendingUiClean="); pw.print(pendingUiClean); @@ -345,6 +351,7 @@ final class ProcessRecord {          curAdj = setAdj = -100;          persistent = false;          removed = false; +        lastPssTime = SystemClock.uptimeMillis();      }      public void setPid(int _pid) { @@ -451,21 +458,20 @@ final class ProcessRecord {              ProcessList plist) {          int state = this == TOP_APP ? ProcessTracker.STATE_TOP                  : plist.adjToTrackedState(setAdj); -        if (pkgList.size() > 0) { -            pkgList.valueAt(0).setState(state, memFactor, now, pkgList); -        } +        baseProcessTracker.setState(state, memFactor, now, pkgList);      }      /*       *  Delete all packages from list except the package indicated in info       */ -    public void resetPackageList() { +    public void resetPackageList(ProcessTracker tracker) {          long now = SystemClock.uptimeMillis(); -        if (pkgList.size() > 0) { -            pkgList.valueAt(0).setState(ProcessTracker.STATE_NOTHING, 0, now, pkgList); +        baseProcessTracker.setState(ProcessTracker.STATE_NOTHING, 0, now, pkgList); +        if (pkgList.size() != 1) { +            pkgList.clear(); +            pkgList.put(info.packageName, tracker.getProcessStateLocked( +                    info.packageName, info.uid, processName));          } -        pkgList.clear(); -        pkgList.put(info.packageName, baseProcessTracker);      }      public String[] getPackageList() { diff --git a/services/java/com/android/server/am/ProcessTracker.java b/services/java/com/android/server/am/ProcessTracker.java index 30470f1b69c6..82b2158d2e84 100644 --- a/services/java/com/android/server/am/ProcessTracker.java +++ b/services/java/com/android/server/am/ProcessTracker.java @@ -48,6 +48,11 @@ public final class ProcessTracker {      public static final int STATE_CACHED = 9;      public static final int STATE_COUNT = STATE_CACHED+1; +    static final int[] ALL_PROC_STATES = new int[] { STATE_PERSISTENT, STATE_TOP, +            STATE_FOREGROUND, STATE_VISIBLE, STATE_PERCEPTIBLE, STATE_BACKUP, +            STATE_SERVICE, STATE_HOME, STATE_PREVIOUS, STATE_CACHED +    }; +      public static final int PSS_SAMPLE_COUNT = 0;      public static final int PSS_MINIMUM = 1;      public static final int PSS_AVERAGE = 2; @@ -65,6 +70,10 @@ public final class ProcessTracker {      public static final int ADJ_SCREEN_ON = ADJ_SCREEN_MOD;      public static final int ADJ_COUNT = ADJ_SCREEN_ON*2; +    static final int[] ALL_SCREEN_ADJ = new int[] { ADJ_SCREEN_OFF, ADJ_SCREEN_ON }; +    static final int[] ALL_MEM_ADJ = new int[] { ADJ_MEM_FACTOR_NORMAL, ADJ_MEM_FACTOR_MODERATE, +            ADJ_MEM_FACTOR_LOW, ADJ_MEM_FACTOR_CRITICAL }; +      // Most data is kept in a sparse data structure: an integer array which integer      // holds the type of the entry, and the identifier for a long array that data      // exists in and the offset into the array to find it.  The constants below @@ -110,7 +119,7 @@ public final class ProcessTracker {      static final String[] STATE_TAGS = new String[] {              "p", "t", "f", "v", "t", -            "b", "s", "h", "v", "c" +            "b", "s", "h", "r", "c"      };      static final String CSV_SEP = "\t"; @@ -132,9 +141,14 @@ public final class ProcessTracker {          int mCurState = STATE_NOTHING;          long mStartTime; +        int mLastPssState = STATE_NOTHING; +        long mLastPssTime;          int[] mPssTable;          int mPssTableSize; +        int mNumExcessiveWake; +        int mNumExcessiveCpu; +          boolean mMultiPackage;          long mTmpTotalTime; @@ -145,7 +159,7 @@ public final class ProcessTracker {           */          public ProcessState(State state, String pkg, int uid, String name) {              mState = state; -            mCommonProcess = null; +            mCommonProcess = this;              mPackage = pkg;              mUid = uid;              mName = name; @@ -199,6 +213,8 @@ public final class ProcessTracker {                  pnew.mPssTableSize = mState.mFindTableSize;              }              */ +            pnew.mNumExcessiveWake = mNumExcessiveWake; +            pnew.mNumExcessiveCpu = mNumExcessiveCpu;              return pnew;          } @@ -208,30 +224,16 @@ public final class ProcessTracker {                  state += memFactor*STATE_COUNT;              } -            if (mCommonProcess != null) { -                // First update the common process. -                mCommonProcess.setState(state, now); -                if (!mCommonProcess.mMultiPackage) { -                    // This common process is for a single package, so it is shared -                    // with the per-package state.  Nothing more to do. -                    return; -                } +            // First update the common process. +            mCommonProcess.setState(state, now); + +            // If the common process is not multi-package, there is nothing else to do. +            if (!mCommonProcess.mMultiPackage) { +                return;              }              for (int ip=pkgList.size()-1; ip>=0; ip--) { -                ProcessState proc = pkgList.valueAt(ip); -                if (proc.mMultiPackage) { -                    // The array map is still pointing to a common process state -                    // that is now shared across packages.  Update it to point to -                    // the new per-package state. -                    proc = mState.mPackages.get(pkgList.keyAt(ip), -                            proc.mUid).mProcesses.get(proc.mName); -                    if (proc == null) { -                        throw new IllegalStateException("Didn't create per-package process"); -                    } -                    pkgList.setValueAt(ip, proc); -                } -                proc.setState(state, now); +                pullFixedProc(pkgList, ip).setState(state, now);              }          } @@ -258,7 +260,15 @@ public final class ProcessTracker {              }          } -        public void addPss(long pss) { +        public void addPss(long pss, boolean always) { +            if (!always) { +                if (mLastPssState == mCurState && SystemClock.uptimeMillis() +                        < (mLastPssTime+(30*1000))) { +                    return; +                } +            } +            mLastPssState = mCurState; +            mLastPssTime = SystemClock.uptimeMillis();              if (mCurState != STATE_NOTHING) {                  int idx = State.binarySearch(mPssTable, mPssTableSize, mCurState);                  int off; @@ -284,7 +294,8 @@ public final class ProcessTracker {                      if (longs[idx+PSS_MINIMUM] > pss) {                          longs[idx+PSS_MINIMUM] = pss;                      } -                    longs[idx+PSS_AVERAGE] = ((longs[idx+PSS_AVERAGE]*count)+pss)/(count+1); +                    longs[idx+PSS_AVERAGE] = (long)( ((longs[idx+PSS_AVERAGE]*(double)count)+pss) +                            / (count+1) );                      if (longs[idx+PSS_MAXIMUM] < pss) {                          longs[idx+PSS_MAXIMUM] = pss;                      } @@ -292,6 +303,45 @@ public final class ProcessTracker {              }          } +        public void reportExcessiveWake(ArrayMap<String, ProcessTracker.ProcessState> pkgList) { +            mCommonProcess.mNumExcessiveWake++; +            if (!mCommonProcess.mMultiPackage) { +                return; +            } + +            for (int ip=pkgList.size()-1; ip>=0; ip--) { +                pullFixedProc(pkgList, ip).mNumExcessiveWake++; +            } +        } + +        public void reportExcessiveCpu(ArrayMap<String, ProcessTracker.ProcessState> pkgList) { +            mCommonProcess.mNumExcessiveCpu++; +            if (!mCommonProcess.mMultiPackage) { +                return; +            } + +            for (int ip=pkgList.size()-1; ip>=0; ip--) { +                pullFixedProc(pkgList, ip).mNumExcessiveCpu++; +            } +        } + +        private ProcessState pullFixedProc(ArrayMap<String, ProcessTracker.ProcessState> pkgList, +                int index) { +            ProcessState proc = pkgList.valueAt(index); +            if (proc.mMultiPackage) { +                // The array map is still pointing to a common process state +                // that is now shared across packages.  Update it to point to +                // the new per-package state. +                proc = mState.mPackages.get(pkgList.keyAt(index), +                        proc.mUid).mProcesses.get(proc.mName); +                if (proc == null) { +                    throw new IllegalStateException("Didn't create per-package process"); +                } +                pkgList.setValueAt(index, proc); +            } +            return proc; +        } +          long getDuration(int state, long now) {              int idx = State.binarySearch(mDurationsTable, mDurationsTableSize, state);              long time = idx >= 0 ? mState.getLong(mDurationsTable[idx], 0) : 0; @@ -685,7 +735,7 @@ public final class ProcessTracker {          }      } -    static void dumpSingleTimeCsv(PrintWriter pw, String sep, long[] durations, +    static void dumpAdjTimesCheckin(PrintWriter pw, String sep, long[] durations,              int curState, long curStartTime, long now) {          for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {              for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) { @@ -694,8 +744,9 @@ public final class ProcessTracker {                  if (curState == state) {                      time += now - curStartTime;                  } -                pw.print(sep); -                pw.print(time); +                if (time != 0) { +                    printAdjTagAndValue(pw, state, time); +                }              }          }      } @@ -714,11 +765,11 @@ public final class ProcessTracker {          pw.print(",");          pw.print(serviceName);          pw.print(opCount); -        dumpSingleTimeCsv(pw, ",", durations, curState, curStartTime, now); +        dumpAdjTimesCheckin(pw, ",", durations, curState, curStartTime, now);          pw.println();      } -    long computeProcessTimeLocked(ProcessState proc, int[] screenStates, int[] memStates, +    static long computeProcessTimeLocked(ProcessState proc, int[] screenStates, int[] memStates,                  int[] procStates, long now) {          long totalTime = 0;          /* @@ -756,10 +807,7 @@ public final class ProcessTracker {                  PackageState state = procs.valueAt(iu);                  for (int iproc=0; iproc<state.mProcesses.size(); iproc++) {                      ProcessState proc = state.mProcesses.valueAt(iproc); -                    if (proc.mCommonProcess != null) { -                        proc = proc.mCommonProcess; -                    } -                    foundProcs.add(proc); +                    foundProcs.add(proc.mCommonProcess);                  }              }          } @@ -785,8 +833,8 @@ public final class ProcessTracker {          return outProcs;      } -    void dumpProcessState(PrintWriter pw, String prefix, ProcessState proc, int[] screenStates, -            int[] memStates, int[] procStates, long now) { +    static void dumpProcessState(PrintWriter pw, String prefix, ProcessState proc, +            int[] screenStates, int[] memStates, int[] procStates, long now) {          long totalTime = 0;          int printedScreen = -1;          for (int is=0; is<screenStates.length; is++) { @@ -833,7 +881,7 @@ public final class ProcessTracker {          }      } -    void dumpProcessPss(PrintWriter pw, String prefix, ProcessState proc, int[] screenStates, +    static void dumpProcessPss(PrintWriter pw, String prefix, ProcessState proc, int[] screenStates,              int[] memStates, int[] procStates) {          boolean printedHeader = false;          int printedScreen = -1; @@ -877,9 +925,17 @@ public final class ProcessTracker {                  }              }          } +        if (proc.mNumExcessiveWake != 0) { +            pw.print(prefix); pw.print("Killed for excessive wake locks: "); +                    pw.print(proc.mNumExcessiveWake); pw.println(" times"); +        } +        if (proc.mNumExcessiveCpu != 0) { +            pw.print(prefix); pw.print("Killed for excessive CPU use: "); +                    pw.print(proc.mNumExcessiveCpu); pw.println(" times"); +        }      } -    void dumpStateHeadersCsv(PrintWriter pw, String sep, int[] screenStates, +    static void dumpStateHeadersCsv(PrintWriter pw, String sep, int[] screenStates,              int[] memStates, int[] procStates) {          final int NS = screenStates != null ? screenStates.length : 1;          final int NM = memStates != null ? memStates.length : 1; @@ -911,7 +967,7 @@ public final class ProcessTracker {          }      } -    void dumpProcessStateCsv(PrintWriter pw, ProcessState proc, +    static void dumpProcessStateCsv(PrintWriter pw, ProcessState proc,              boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,              boolean sepProcStates, int[] procStates, long now) {          final int NSS = sepScreenStates ? screenStates.length : 1; @@ -946,7 +1002,7 @@ public final class ProcessTracker {          }      } -    void dumpProcessList(PrintWriter pw, String prefix, ArrayList<ProcessState> procs, +    static void dumpProcessList(PrintWriter pw, String prefix, ArrayList<ProcessState> procs,              int[] screenStates, int[] memStates, int[] procStates, long now) {          String innerPrefix = prefix + "  ";          for (int i=procs.size()-1; i>=0; i--) { @@ -966,7 +1022,7 @@ public final class ProcessTracker {          }      } -    void dumpProcessListCsv(PrintWriter pw, ArrayList<ProcessState> procs, +    static void dumpProcessListCsv(PrintWriter pw, ArrayList<ProcessState> procs,              boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,              boolean sepProcStates, int[] procStates, long now) {          pw.print("process"); @@ -1014,44 +1070,6 @@ public final class ProcessTracker {          return false;      } -    void dumpAllProcessState(PrintWriter pw, String prefix, ProcessState proc, long now) { -        long totalTime = 0; -        int printedScreen = -1; -        for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) { -            int printedMem = -1; -            for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) { -                for (int is=0; is<STATE_NAMES.length; is++) { -                    int bucket = is+(STATE_COUNT*(imem+iscreen)); -                    long time = proc.getDuration(bucket, now); -                    String running = ""; -                    if (proc.mCurState == bucket) { -                        running = " (running)"; -                    } -                    if (time != 0) { -                        pw.print(prefix); -                        printScreenLabel(pw, printedScreen != iscreen -                                ? iscreen : STATE_NOTHING); -                        printedScreen = iscreen; -                        printMemLabel(pw, printedMem != imem -                                ? imem : STATE_NOTHING); -                        printedMem = imem; -                        pw.print(STATE_NAMES[is]); pw.print(": "); -                        TimeUtils.formatDuration(time, pw); pw.println(running); -                        totalTime += time; -                    } -                } -            } -        } -        if (totalTime != 0) { -            pw.print(prefix); -            printScreenLabel(pw, STATE_NOTHING); -            printMemLabel(pw, STATE_NOTHING); -            pw.print("TOTAL      : "); -            TimeUtils.formatDuration(totalTime, pw); -            pw.println(); -        } -    } -      static int printArrayEntry(PrintWriter pw, String[] array, int value, int mod) {          int index = value/mod;          if (index >= 0 && index < array.length) { @@ -1062,20 +1080,32 @@ public final class ProcessTracker {          return value - index*mod;      } -    void printProcStateTag(PrintWriter pw, int state) { +    static void printProcStateTag(PrintWriter pw, int state) {          state = printArrayEntry(pw, ADJ_SCREEN_TAGS,  state, ADJ_SCREEN_MOD*STATE_COUNT);          state = printArrayEntry(pw, ADJ_MEM_TAGS,  state, STATE_COUNT);          printArrayEntry(pw, STATE_TAGS,  state, 1);      } -    void printProcStateTagAndValue(PrintWriter pw, int state, long value) { +    static void printAdjTag(PrintWriter pw, int state) { +        state = printArrayEntry(pw, ADJ_SCREEN_TAGS,  state, ADJ_SCREEN_MOD); +        printArrayEntry(pw, ADJ_MEM_TAGS,  state, 1); +    } + +    static void printProcStateTagAndValue(PrintWriter pw, int state, long value) {          pw.print(',');          printProcStateTag(pw, state);          pw.print(':');          pw.print(value);      } -    void dumpAllProcessStateCheckin(PrintWriter pw, ProcessState proc, long now) { +    static void printAdjTagAndValue(PrintWriter pw, int state, long value) { +        pw.print(','); +        printAdjTag(pw, state); +        pw.print(':'); +        pw.print(value); +    } + +    static void dumpAllProcessStateCheckin(PrintWriter pw, ProcessState proc, long now) {          boolean didCurState = false;          for (int i=0; i<proc.mDurationsTableSize; i++) {              int off = proc.mDurationsTable[i]; @@ -1092,7 +1122,7 @@ public final class ProcessTracker {          }      } -    void dumpAllProcessPssCheckin(PrintWriter pw, ProcessState proc, long now) { +    static void dumpAllProcessPssCheckin(PrintWriter pw, ProcessState proc) {          for (int i=0; i<proc.mPssTableSize; i++) {              int off = proc.mPssTable[i];              int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK; @@ -1154,7 +1184,7 @@ public final class ProcessTracker {          return finalRes;      } -    private void dumpHelp(PrintWriter pw) { +    static private void dumpHelp(PrintWriter pw) {          pw.println("Process stats (procstats) dump options:");          pw.println("    [--checkin|--csv] [csv-screen] [csv-proc] [csv-mem]");          pw.println("    [--reset] [-h] [<package.name>]"); @@ -1165,6 +1195,7 @@ public final class ProcessTracker {          pw.println("  --csv-proc: pers, top, fore, vis, precept, backup,");          pw.println("    service, home, prev, cached");          pw.println("  --reset: reset the stats, clearing all current data."); +        pw.println("  -a: print everything.");          pw.println("  -h: print this help text.");          pw.println("  <package.name>: optional name of package to filter output by.");      } @@ -1174,6 +1205,7 @@ public final class ProcessTracker {          boolean isCheckin = false;          boolean isCsv = false; +        boolean dumpAll = false;          String reqPackage = null;          boolean csvSepScreenStats = false;          int[] csvScreenStats = new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON}; @@ -1248,7 +1280,7 @@ public final class ProcessTracker {                      dumpHelp(pw);                      return;                  } else if ("-a".equals(arg)) { -                    // ignore +                    dumpAll = true;                  } else if (arg.length() > 0 && arg.charAt(0) == '-'){                      pw.println("Unknown option: " + arg);                      dumpHelp(pw); @@ -1332,8 +1364,6 @@ public final class ProcessTracker {                      if (NPROCS > 0 || NSRVS > 0) {                          if (!printedHeader) {                              pw.println("Per-Package Process Stats:"); -                            pw.print("  Num long arrays: "); pw.println(mState.mLongs.size()); -                            pw.print("  Next long entry: "); pw.println(mState.mNextLong);                              printedHeader = true;                          }                          pw.print("  * "); pw.print(pkgName); pw.print(" / "); @@ -1349,7 +1379,10 @@ public final class ProcessTracker {                          pw.print(proc.mDurationsTableSize);                          pw.print(" entries)");                          pw.println(":"); -                        dumpAllProcessState(pw, "        ", proc, now); +                        dumpProcessState(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ, +                                ALL_PROC_STATES, now); +                        dumpProcessPss(pw, "        ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ, +                                ALL_PROC_STATES);                      } else {                          pw.print("pkgproc,");                          pw.print(pkgName); @@ -1359,6 +1392,29 @@ public final class ProcessTracker {                          pw.print(state.mProcesses.keyAt(iproc));                          dumpAllProcessStateCheckin(pw, proc, now);                          pw.println(); +                        if (proc.mPssTableSize > 0) { +                            pw.print("pkgpss,"); +                            pw.print(pkgName); +                            pw.print(","); +                            pw.print(uid); +                            pw.print(","); +                            pw.print(state.mProcesses.keyAt(iproc)); +                            dumpAllProcessPssCheckin(pw, proc); +                            pw.println(); +                        } +                        if (proc.mNumExcessiveWake > 0 || proc.mNumExcessiveCpu > 0) { +                            pw.print("pkgkills,"); +                            pw.print(pkgName); +                            pw.print(","); +                            pw.print(uid); +                            pw.print(","); +                            pw.print(state.mProcesses.keyAt(iproc)); +                            pw.print(","); +                            pw.print(proc.mNumExcessiveWake); +                            pw.print(","); +                            pw.print(proc.mNumExcessiveCpu); +                            pw.println(); +                        }                      }                  }                  for (int isvc=0; isvc<NSRVS; isvc++) { @@ -1431,6 +1487,12 @@ public final class ProcessTracker {              pw.println("Run time Stats:");              dumpSingleTime(pw, "  ", mState.mMemFactorDurations, mState.mMemFactor,                      mState.mStartTime, now); +            if (dumpAll) { +                pw.println(); +                pw.println("Internal state:"); +                pw.print("  Num long arrays: "); pw.println(mState.mLongs.size()); +                pw.print("  Next long entry: "); pw.println(mState.mNextLong); +            }          } else {              ArrayMap<String, SparseArray<ProcessState>> procMap = mState.mProcesses.getMap();              for (int ip=0; ip<procMap.size(); ip++) { @@ -1452,13 +1514,24 @@ public final class ProcessTracker {                          pw.print(procName);                          pw.print(",");                          pw.print(uid); -                        dumpAllProcessPssCheckin(pw, state, now); +                        dumpAllProcessPssCheckin(pw, state); +                        pw.println(); +                    } +                    if (state.mNumExcessiveWake > 0 || state.mNumExcessiveCpu > 0) { +                        pw.print("kills,"); +                        pw.print(uid); +                        pw.print(","); +                        pw.print(procName); +                        pw.print(","); +                        pw.print(state.mNumExcessiveWake); +                        pw.print(","); +                        pw.print(state.mNumExcessiveCpu);                          pw.println();                      }                  }              }              pw.print("total"); -            dumpSingleTimeCsv(pw, ",", mState.mMemFactorDurations, mState.mMemFactor, +            dumpAdjTimesCheckin(pw, ",", mState.mMemFactorDurations, mState.mMemFactor,                      mState.mStartTime, now);              pw.println();          } |