Loading services/core/java/com/android/server/MemoryPressureUtil.java 0 → 100644 +56 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server; import android.os.StrictMode; import android.util.Slog; import libcore.io.IoUtils; import java.io.File; import java.io.IOException; import java.io.StringWriter; /** * Utility method for memory pressure (PSI). */ public final class MemoryPressureUtil { private static final String FILE = "/proc/pressure/memory"; private static final String TAG = "MemoryPressure"; /** * @return a stanza about memory PSI to add to a report. */ public static String currentPsiState() { final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads(); StringWriter contents = new StringWriter(); try { if (new File(FILE).exists()) { contents.append("----- Output from /proc/pressure/memory -----\n"); contents.append(IoUtils.readFileAsString(FILE)); contents.append("----- End output from /proc/pressure/memory -----\n\n"); } } catch (IOException e) { Slog.e(TAG, "Could not read " + FILE, e); } finally { StrictMode.setThreadPolicy(savedPolicy); } return contents.toString(); } private MemoryPressureUtil(){} } services/core/java/com/android/server/SystemServerInitThreadPool.java +1 −1 Original line number Diff line number Diff line Loading @@ -175,6 +175,6 @@ public class SystemServerInitThreadPool { final ArrayList<Integer> pids = new ArrayList<>(); pids.add(Process.myPid()); ActivityManagerService.dumpStackTraces(pids, null, null, Watchdog.getInterestingNativePids()); Watchdog.getInterestingNativePids(), null); } } services/core/java/com/android/server/Watchdog.java +10 −4 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import com.android.server.wm.SurfaceAnimationThread; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; Loading Loading @@ -583,7 +584,7 @@ public class Watchdog extends Thread { ArrayList<Integer> pids = new ArrayList<Integer>(); pids.add(Process.myPid()); ActivityManagerService.dumpStackTraces(pids, null, null, getInterestingNativePids()); getInterestingNativePids(), null); waitedHalf = true; } continue; Loading @@ -609,16 +610,21 @@ public class Watchdog extends Thread { if (mPhonePid > 0) pids.add(mPhonePid); long anrTime = SystemClock.uptimeMillis(); StringBuilder report = new StringBuilder(); report.append(MemoryPressureUtil.currentPsiState()); ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(false); StringWriter tracesFileException = new StringWriter(); final File stack = ActivityManagerService.dumpStackTraces( pids, processCpuTracker, new SparseArray<>(), getInterestingNativePids()); pids, processCpuTracker, new SparseArray<>(), getInterestingNativePids(), tracesFileException); // Give some extra time to make sure the stack traces get written. // The system's been hanging for a minute, another second or two won't hurt much. SystemClock.sleep(5000); processCpuTracker.update(); String cpuInfo = processCpuTracker.printCurrentState(anrTime); report.append(processCpuTracker.printCurrentState(anrTime)); report.append(tracesFileException.getBuffer()); // Trigger the kernel to dump all blocked threads, and backtraces on all CPUs to the kernel log doSysRq('w'); Loading @@ -634,7 +640,7 @@ public class Watchdog extends Thread { if (mActivity != null) { mActivity.addErrorToDropBox( "watchdog", null, "system_server", null, null, null, subject, cpuInfo, stack, null); subject, report.toString(), stack, null); } FrameworkStatsLog.write(FrameworkStatsLog.SYSTEM_SERVER_WATCHDOG_OCCURRED, subject); Loading services/core/java/com/android/server/am/ActivityManagerService.java +17 −15 Original line number Diff line number Diff line Loading @@ -3851,10 +3851,11 @@ public class ActivityManagerService extends IActivityManager.Stub * @param firstPids of dalvik VM processes to dump stack traces for first * @param lastPids of dalvik VM processes to dump stack traces for last * @param nativePids optional list of native pids to dump stack crawls * @param logExceptionCreatingFile optional writer to which we log errors creating the file */ public static File dumpStackTraces(ArrayList<Integer> firstPids, ProcessCpuTracker processCpuTracker, SparseArray<Boolean> lastPids, ArrayList<Integer> nativePids) { ArrayList<Integer> nativePids, StringWriter logExceptionCreatingFile) { ArrayList<Integer> extraPids = null; Slog.i(TAG, "dumpStackTraces pids=" + lastPids + " nativepids=" + nativePids); Loading Loading @@ -3894,8 +3895,15 @@ public class ActivityManagerService extends IActivityManager.Stub // NOTE: We should consider creating the file in native code atomically once we've // gotten rid of the old scheme of dumping and lot of the code that deals with paths // can be removed. File tracesFile = createAnrDumpFile(tracesDir); if (tracesFile == null) { File tracesFile; try { tracesFile = createAnrDumpFile(tracesDir); } catch (IOException e) { Slog.w(TAG, "Exception creating ANR dump file:", e); if (logExceptionCreatingFile != null) { logExceptionCreatingFile.append("----- Exception creating ANR dump file -----\n"); e.printStackTrace(new PrintWriter(logExceptionCreatingFile)); } return null; } Loading @@ -3906,7 +3914,7 @@ public class ActivityManagerService extends IActivityManager.Stub @GuardedBy("ActivityManagerService.class") private static SimpleDateFormat sAnrFileDateFormat; private static synchronized File createAnrDumpFile(File tracesDir) { private static synchronized File createAnrDumpFile(File tracesDir) throws IOException { if (sAnrFileDateFormat == null) { sAnrFileDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS"); } Loading @@ -3914,18 +3922,12 @@ public class ActivityManagerService extends IActivityManager.Stub final String formattedDate = sAnrFileDateFormat.format(new Date()); final File anrFile = new File(tracesDir, "anr_" + formattedDate); try { if (anrFile.createNewFile()) { FileUtils.setPermissions(anrFile.getAbsolutePath(), 0600, -1, -1); // -rw------- return anrFile; } else { Slog.w(TAG, "Unable to create ANR dump file: createNewFile failed"); throw new IOException("Unable to create ANR dump file: createNewFile failed"); } } catch (IOException ioe) { Slog.w(TAG, "Exception creating ANR dump file:", ioe); } return null; } /** Loading services/core/java/com/android/server/am/ProcessRecord.java +11 −5 Original line number Diff line number Diff line Loading @@ -66,11 +66,13 @@ import com.android.internal.os.BatteryStatsImpl; import com.android.internal.os.ProcessCpuTracker; import com.android.internal.os.Zygote; import com.android.internal.util.FrameworkStatsLog; import com.android.server.MemoryPressureUtil; import com.android.server.wm.WindowProcessController; import com.android.server.wm.WindowProcessListener; import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; Loading Loading @@ -1581,6 +1583,8 @@ class ProcessRecord implements WindowProcessListener { info.append("Parent: ").append(parentShortComponentName).append("\n"); } StringBuilder report = new StringBuilder(); report.append(MemoryPressureUtil.currentPsiState()); ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true); // don't dump native PIDs for background ANRs unless it is the process of interest Loading Loading @@ -1608,19 +1612,20 @@ class ProcessRecord implements WindowProcessListener { // For background ANRs, don't pass the ProcessCpuTracker to // avoid spending 1/2 second collecting stats to rank lastPids. StringWriter tracesFileException = new StringWriter(); File tracesFile = ActivityManagerService.dumpStackTraces(firstPids, (isSilentAnr()) ? null : processCpuTracker, (isSilentAnr()) ? null : lastPids, nativePids); nativePids, tracesFileException); String cpuInfo = null; if (isMonitorCpuUsage()) { mService.updateCpuStatsNow(); synchronized (mService.mProcessCpuTracker) { cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime); report.append(mService.mProcessCpuTracker.printCurrentState(anrTime)); } info.append(processCpuTracker.printCurrentLoad()); info.append(cpuInfo); info.append(report); } report.append(tracesFileException.getBuffer()); info.append(processCpuTracker.printCurrentState(anrTime)); Loading @@ -1645,7 +1650,8 @@ class ProcessRecord implements WindowProcessListener { final ProcessRecord parentPr = parentProcess != null ? (ProcessRecord) parentProcess.mOwner : null; mService.addErrorToDropBox("anr", this, processName, activityShortComponentName, parentShortComponentName, parentPr, annotation, cpuInfo, tracesFile, null); parentShortComponentName, parentPr, annotation, report.toString(), tracesFile, null); if (mWindowProcessController.appNotResponding(info.toString(), () -> kill("anr", ApplicationExitInfo.REASON_ANR, true), Loading Loading
services/core/java/com/android/server/MemoryPressureUtil.java 0 → 100644 +56 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server; import android.os.StrictMode; import android.util.Slog; import libcore.io.IoUtils; import java.io.File; import java.io.IOException; import java.io.StringWriter; /** * Utility method for memory pressure (PSI). */ public final class MemoryPressureUtil { private static final String FILE = "/proc/pressure/memory"; private static final String TAG = "MemoryPressure"; /** * @return a stanza about memory PSI to add to a report. */ public static String currentPsiState() { final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads(); StringWriter contents = new StringWriter(); try { if (new File(FILE).exists()) { contents.append("----- Output from /proc/pressure/memory -----\n"); contents.append(IoUtils.readFileAsString(FILE)); contents.append("----- End output from /proc/pressure/memory -----\n\n"); } } catch (IOException e) { Slog.e(TAG, "Could not read " + FILE, e); } finally { StrictMode.setThreadPolicy(savedPolicy); } return contents.toString(); } private MemoryPressureUtil(){} }
services/core/java/com/android/server/SystemServerInitThreadPool.java +1 −1 Original line number Diff line number Diff line Loading @@ -175,6 +175,6 @@ public class SystemServerInitThreadPool { final ArrayList<Integer> pids = new ArrayList<>(); pids.add(Process.myPid()); ActivityManagerService.dumpStackTraces(pids, null, null, Watchdog.getInterestingNativePids()); Watchdog.getInterestingNativePids(), null); } }
services/core/java/com/android/server/Watchdog.java +10 −4 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import com.android.server.wm.SurfaceAnimationThread; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; Loading Loading @@ -583,7 +584,7 @@ public class Watchdog extends Thread { ArrayList<Integer> pids = new ArrayList<Integer>(); pids.add(Process.myPid()); ActivityManagerService.dumpStackTraces(pids, null, null, getInterestingNativePids()); getInterestingNativePids(), null); waitedHalf = true; } continue; Loading @@ -609,16 +610,21 @@ public class Watchdog extends Thread { if (mPhonePid > 0) pids.add(mPhonePid); long anrTime = SystemClock.uptimeMillis(); StringBuilder report = new StringBuilder(); report.append(MemoryPressureUtil.currentPsiState()); ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(false); StringWriter tracesFileException = new StringWriter(); final File stack = ActivityManagerService.dumpStackTraces( pids, processCpuTracker, new SparseArray<>(), getInterestingNativePids()); pids, processCpuTracker, new SparseArray<>(), getInterestingNativePids(), tracesFileException); // Give some extra time to make sure the stack traces get written. // The system's been hanging for a minute, another second or two won't hurt much. SystemClock.sleep(5000); processCpuTracker.update(); String cpuInfo = processCpuTracker.printCurrentState(anrTime); report.append(processCpuTracker.printCurrentState(anrTime)); report.append(tracesFileException.getBuffer()); // Trigger the kernel to dump all blocked threads, and backtraces on all CPUs to the kernel log doSysRq('w'); Loading @@ -634,7 +640,7 @@ public class Watchdog extends Thread { if (mActivity != null) { mActivity.addErrorToDropBox( "watchdog", null, "system_server", null, null, null, subject, cpuInfo, stack, null); subject, report.toString(), stack, null); } FrameworkStatsLog.write(FrameworkStatsLog.SYSTEM_SERVER_WATCHDOG_OCCURRED, subject); Loading
services/core/java/com/android/server/am/ActivityManagerService.java +17 −15 Original line number Diff line number Diff line Loading @@ -3851,10 +3851,11 @@ public class ActivityManagerService extends IActivityManager.Stub * @param firstPids of dalvik VM processes to dump stack traces for first * @param lastPids of dalvik VM processes to dump stack traces for last * @param nativePids optional list of native pids to dump stack crawls * @param logExceptionCreatingFile optional writer to which we log errors creating the file */ public static File dumpStackTraces(ArrayList<Integer> firstPids, ProcessCpuTracker processCpuTracker, SparseArray<Boolean> lastPids, ArrayList<Integer> nativePids) { ArrayList<Integer> nativePids, StringWriter logExceptionCreatingFile) { ArrayList<Integer> extraPids = null; Slog.i(TAG, "dumpStackTraces pids=" + lastPids + " nativepids=" + nativePids); Loading Loading @@ -3894,8 +3895,15 @@ public class ActivityManagerService extends IActivityManager.Stub // NOTE: We should consider creating the file in native code atomically once we've // gotten rid of the old scheme of dumping and lot of the code that deals with paths // can be removed. File tracesFile = createAnrDumpFile(tracesDir); if (tracesFile == null) { File tracesFile; try { tracesFile = createAnrDumpFile(tracesDir); } catch (IOException e) { Slog.w(TAG, "Exception creating ANR dump file:", e); if (logExceptionCreatingFile != null) { logExceptionCreatingFile.append("----- Exception creating ANR dump file -----\n"); e.printStackTrace(new PrintWriter(logExceptionCreatingFile)); } return null; } Loading @@ -3906,7 +3914,7 @@ public class ActivityManagerService extends IActivityManager.Stub @GuardedBy("ActivityManagerService.class") private static SimpleDateFormat sAnrFileDateFormat; private static synchronized File createAnrDumpFile(File tracesDir) { private static synchronized File createAnrDumpFile(File tracesDir) throws IOException { if (sAnrFileDateFormat == null) { sAnrFileDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS"); } Loading @@ -3914,18 +3922,12 @@ public class ActivityManagerService extends IActivityManager.Stub final String formattedDate = sAnrFileDateFormat.format(new Date()); final File anrFile = new File(tracesDir, "anr_" + formattedDate); try { if (anrFile.createNewFile()) { FileUtils.setPermissions(anrFile.getAbsolutePath(), 0600, -1, -1); // -rw------- return anrFile; } else { Slog.w(TAG, "Unable to create ANR dump file: createNewFile failed"); throw new IOException("Unable to create ANR dump file: createNewFile failed"); } } catch (IOException ioe) { Slog.w(TAG, "Exception creating ANR dump file:", ioe); } return null; } /** Loading
services/core/java/com/android/server/am/ProcessRecord.java +11 −5 Original line number Diff line number Diff line Loading @@ -66,11 +66,13 @@ import com.android.internal.os.BatteryStatsImpl; import com.android.internal.os.ProcessCpuTracker; import com.android.internal.os.Zygote; import com.android.internal.util.FrameworkStatsLog; import com.android.server.MemoryPressureUtil; import com.android.server.wm.WindowProcessController; import com.android.server.wm.WindowProcessListener; import java.io.File; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; Loading Loading @@ -1581,6 +1583,8 @@ class ProcessRecord implements WindowProcessListener { info.append("Parent: ").append(parentShortComponentName).append("\n"); } StringBuilder report = new StringBuilder(); report.append(MemoryPressureUtil.currentPsiState()); ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true); // don't dump native PIDs for background ANRs unless it is the process of interest Loading Loading @@ -1608,19 +1612,20 @@ class ProcessRecord implements WindowProcessListener { // For background ANRs, don't pass the ProcessCpuTracker to // avoid spending 1/2 second collecting stats to rank lastPids. StringWriter tracesFileException = new StringWriter(); File tracesFile = ActivityManagerService.dumpStackTraces(firstPids, (isSilentAnr()) ? null : processCpuTracker, (isSilentAnr()) ? null : lastPids, nativePids); nativePids, tracesFileException); String cpuInfo = null; if (isMonitorCpuUsage()) { mService.updateCpuStatsNow(); synchronized (mService.mProcessCpuTracker) { cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime); report.append(mService.mProcessCpuTracker.printCurrentState(anrTime)); } info.append(processCpuTracker.printCurrentLoad()); info.append(cpuInfo); info.append(report); } report.append(tracesFileException.getBuffer()); info.append(processCpuTracker.printCurrentState(anrTime)); Loading @@ -1645,7 +1650,8 @@ class ProcessRecord implements WindowProcessListener { final ProcessRecord parentPr = parentProcess != null ? (ProcessRecord) parentProcess.mOwner : null; mService.addErrorToDropBox("anr", this, processName, activityShortComponentName, parentShortComponentName, parentPr, annotation, cpuInfo, tracesFile, null); parentShortComponentName, parentPr, annotation, report.toString(), tracesFile, null); if (mWindowProcessController.appNotResponding(info.toString(), () -> kill("anr", ApplicationExitInfo.REASON_ANR, true), Loading