Merge "Revert "Predump the first PID in the ANR process""
diff --git a/core/java/com/android/internal/os/anr/AnrLatencyTracker.java b/core/java/com/android/internal/os/anr/AnrLatencyTracker.java
index 8580c0c..096d1cd 100644
--- a/core/java/com/android/internal/os/anr/AnrLatencyTracker.java
+++ b/core/java/com/android/internal/os/anr/AnrLatencyTracker.java
@@ -18,7 +18,6 @@
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
-
import static com.android.internal.os.TimeoutRecord.TimeoutKind;
import static com.android.internal.util.FrameworkStatsLog.ANRLATENCY_REPORTED__ANR_TYPE__BROADCAST_OF_INTENT;
import static com.android.internal.util.FrameworkStatsLog.ANRLATENCY_REPORTED__ANR_TYPE__CONTENT_PROVIDER_NOT_RESPONDING;
@@ -29,15 +28,12 @@
import static com.android.internal.util.FrameworkStatsLog.ANRLATENCY_REPORTED__ANR_TYPE__START_FOREGROUND_SERVICE;
import static com.android.internal.util.FrameworkStatsLog.ANRLATENCY_REPORTED__ANR_TYPE__UNKNOWN_ANR_TYPE;
-import android.annotation.IntDef;
import android.os.SystemClock;
import android.os.Trace;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -48,22 +44,6 @@
*/
public class AnrLatencyTracker implements AutoCloseable {
- /** Status of the early dumped pid. */
- @IntDef(value = {
- EarlyDumpStatus.UNKNOWN,
- EarlyDumpStatus.SUCCEEDED,
- EarlyDumpStatus.FAILED_TO_CREATE_FILE,
- EarlyDumpStatus.TIMED_OUT
- })
-
- @Retention(RetentionPolicy.SOURCE)
- private @interface EarlyDumpStatus {
- int UNKNOWN = 1;
- int SUCCEEDED = 2;
- int FAILED_TO_CREATE_FILE = 3;
- int TIMED_OUT = 4;
- }
-
private static final AtomicInteger sNextAnrRecordPlacedOnQueueCookieGenerator =
new AtomicInteger();
@@ -97,16 +77,7 @@
private int mAnrQueueSize;
private int mAnrType;
- private final AtomicInteger mDumpedProcessesCount = new AtomicInteger(0);
-
- private volatile @EarlyDumpStatus int mEarlyDumpStatus =
- EarlyDumpStatus.UNKNOWN;
- private volatile long mTempFileDumpingStartUptime;
- private volatile long mTempFileDumpingDuration = 0;
- private long mCopyingFirstPidStartUptime;
- private long mCopyingFirstPidDuration = 0;
- private long mEarlyDumpRequestSubmissionUptime = 0;
- private long mEarlyDumpExecutorPidCount = 0;
+ private int mDumpedProcessesCount = 0;
private long mFirstPidsDumpingStartUptime;
private long mFirstPidsDumpingDuration = 0;
@@ -117,7 +88,7 @@
private boolean mIsPushed = false;
private boolean mIsSkipped = false;
- private boolean mCopyingFirstPidSucceeded = false;
+
private final int mAnrRecordPlacedOnQueueCookie =
sNextAnrRecordPlacedOnQueueCookieGenerator.incrementAndGet();
@@ -140,15 +111,6 @@
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
- /**
- * Records the number of processes we are currently early-dumping, this number includes the
- * current ANR's main process.
- */
- public void earlyDumpRequestSubmittedWithSize(int currentProcessedPidCount) {
- mEarlyDumpRequestSubmissionUptime = getUptimeMillis();
- mEarlyDumpExecutorPidCount = currentProcessedPidCount;
- }
-
/** Records the placing of the AnrHelper.AnrRecord instance on the processing queue. */
public void anrRecordPlacingOnQueueWithSize(int queueSize) {
mAnrRecordPlacedOnQueueUptime = getUptimeMillis();
@@ -248,89 +210,48 @@
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
- /** Records the start of pid dumping to file. */
+ /** Records the start of pid dumping to file (subject and criticalEventSection). */
public void dumpingPidStarted(int pid) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dumpingPid#" + pid);
}
- /** Records the end of pid dumping to file. */
+ /** Records the end of pid dumping to file (subject and criticalEventSection). */
public void dumpingPidEnded() {
- mDumpedProcessesCount.incrementAndGet();
+ mDumpedProcessesCount++;
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
- /** Records the start of first pids dumping to file. */
+ /** Records the start of pid dumping to file (subject and criticalEventSection). */
public void dumpingFirstPidsStarted() {
mFirstPidsDumpingStartUptime = getUptimeMillis();
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dumpingFirstPids");
}
- /** Records the end of first pids dumping to file. */
+ /** Records the end of pid dumping to file (subject and criticalEventSection). */
public void dumpingFirstPidsEnded() {
mFirstPidsDumpingDuration = getUptimeMillis() - mFirstPidsDumpingStartUptime;
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
-
- /** Records the start of the copying of the pre-dumped first pid. */
- public void copyingFirstPidStarted() {
- mCopyingFirstPidStartUptime = getUptimeMillis();
- Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "copyingFirstPid");
- }
-
- /** Records the end of the copying of the pre-dumped first pid. */
- public void copyingFirstPidEnded(boolean copySucceeded) {
- mCopyingFirstPidDuration = getUptimeMillis() - mCopyingFirstPidStartUptime;
- mCopyingFirstPidSucceeded = copySucceeded;
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
- }
-
- /** Records the start of pre-dumping. */
- public void dumpStackTracesTempFileStarted() {
- mTempFileDumpingStartUptime = getUptimeMillis();
- Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dumpStackTracesTempFile");
- }
-
- /** Records the end of pre-dumping. */
- public void dumpStackTracesTempFileEnded() {
- mTempFileDumpingDuration = getUptimeMillis() - mTempFileDumpingStartUptime;
- if (mEarlyDumpStatus == EarlyDumpStatus.UNKNOWN) {
- mEarlyDumpStatus = EarlyDumpStatus.SUCCEEDED;
- }
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
- }
-
- /** Records file creation failure events in dumpStackTracesTempFile. */
- public void dumpStackTracesTempFileCreationFailed() {
- mEarlyDumpStatus = EarlyDumpStatus.FAILED_TO_CREATE_FILE;
- Trace.instant(TRACE_TAG_ACTIVITY_MANAGER, "dumpStackTracesTempFileCreationFailed");
- }
-
- /** Records timeout events in dumpStackTracesTempFile. */
- public void dumpStackTracesTempFileTimedOut() {
- mEarlyDumpStatus = EarlyDumpStatus.TIMED_OUT;
- Trace.instant(TRACE_TAG_ACTIVITY_MANAGER, "dumpStackTracesTempFileTimedOut");
- }
-
- /** Records the start of native pids dumping to file. */
+ /** Records the start of pid dumping to file (subject and criticalEventSection). */
public void dumpingNativePidsStarted() {
mNativePidsDumpingStartUptime = getUptimeMillis();
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dumpingNativePids");
}
- /** Records the end of native pids dumping to file . */
+ /** Records the end of pid dumping to file (subject and criticalEventSection). */
public void dumpingNativePidsEnded() {
mNativePidsDumpingDuration = getUptimeMillis() - mNativePidsDumpingStartUptime;
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
- /** Records the start of extra pids dumping to file. */
+ /** Records the start of pid dumping to file (subject and criticalEventSection). */
public void dumpingExtraPidsStarted() {
mExtraPidsDumpingStartUptime = getUptimeMillis();
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dumpingExtraPids");
}
- /** Records the end of extra pids dumping to file. */
+ /** Records the end of pid dumping to file (subject and criticalEventSection). */
public void dumpingExtraPidsEnded() {
mExtraPidsDumpingDuration = getUptimeMillis() - mExtraPidsDumpingStartUptime;
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
@@ -416,7 +337,7 @@
* Returns latency data as a comma separated value string for inclusion in ANR report.
*/
public String dumpAsCommaSeparatedArrayWithHeader() {
- return "DurationsV3: " + mAnrTriggerUptime
+ return "DurationsV2: " + mAnrTriggerUptime
/* triggering_to_app_not_responding_duration = */
+ "," + (mAppNotRespondingStartUptime - mAnrTriggerUptime)
/* app_not_responding_duration = */
@@ -449,22 +370,7 @@
/* anr_queue_size_when_pushed = */
+ "," + mAnrQueueSize
/* dump_stack_traces_io_time = */
- // We use copyingFirstPidUptime if we're dumping the durations list before the
- // first pids ie after copying the early dump stacks.
- + "," + ((mFirstPidsDumpingStartUptime > 0 ? mFirstPidsDumpingStartUptime
- : mCopyingFirstPidStartUptime) - mDumpStackTracesStartUptime)
- /* temp_file_dump_duration = */
- + "," + mTempFileDumpingDuration
- /* temp_dump_request_on_queue_duration = */
- + "," + (mTempFileDumpingStartUptime - mEarlyDumpRequestSubmissionUptime)
- /* temp_dump_pid_count_when_pushed = */
- + "," + mEarlyDumpExecutorPidCount
- /* first_pid_copying_time = */
- + "," + mCopyingFirstPidDuration
- /* early_dump_status = */
- + "," + mEarlyDumpStatus
- /* copying_first_pid_succeeded = */
- + "," + (mCopyingFirstPidSucceeded ? 1 : 0)
+ + "," + (mFirstPidsDumpingStartUptime - mDumpStackTracesStartUptime)
+ "\n\n";
}
@@ -543,7 +449,7 @@
/* anr_queue_size_when_pushed = */ mAnrQueueSize,
/* anr_type = */ mAnrType,
- /* dumped_processes_count = */ mDumpedProcessesCount.get());
+ /* dumped_processes_count = */ mDumpedProcessesCount);
}
private void anrSkipped(String method) {
diff --git a/core/tests/coretests/src/android/internal/os/anr/AnrLatencyTrackerTests.java b/core/tests/coretests/src/android/internal/os/anr/AnrLatencyTrackerTests.java
index 7d5a0364..4eea076 100644
--- a/core/tests/coretests/src/android/internal/os/anr/AnrLatencyTrackerTests.java
+++ b/core/tests/coretests/src/android/internal/os/anr/AnrLatencyTrackerTests.java
@@ -59,10 +59,7 @@
.thenReturn(175L)
.thenReturn(198L)
.thenReturn(203L)
- .thenReturn(209L)
- .thenReturn(211L)
- .thenReturn(212L)
- .thenReturn(220L);
+ .thenReturn(209L);
}
@Test
@@ -71,7 +68,6 @@
mLatencyTracker.appNotRespondingStarted();
mLatencyTracker.waitingOnAnrRecordLockStarted();
mLatencyTracker.waitingOnAnrRecordLockEnded();
- mLatencyTracker.earlyDumpRequestSubmittedWithSize(5);
mLatencyTracker.anrRecordPlacingOnQueueWithSize(3);
mLatencyTracker.appNotRespondingEnded();
@@ -94,16 +90,7 @@
mLatencyTracker.waitingOnProcLockStarted();
mLatencyTracker.waitingOnProcLockEnded();
- mLatencyTracker.dumpStackTracesTempFileStarted();
- mLatencyTracker.dumpingPidStarted(5);
-
mLatencyTracker.dumpStackTracesStarted();
- mLatencyTracker.copyingFirstPidStarted();
-
- mLatencyTracker.dumpingPidEnded();
- mLatencyTracker.dumpStackTracesTempFileEnded();
-
- mLatencyTracker.copyingFirstPidEnded(true);
mLatencyTracker.dumpingFirstPidsStarted();
mLatencyTracker.dumpingPidStarted(1);
mLatencyTracker.dumpingPidEnded();
@@ -124,7 +111,7 @@
mLatencyTracker.close();
assertThat(mLatencyTracker.dumpAsCommaSeparatedArrayWithHeader())
- .isEqualTo("DurationsV3: 50,5,33,11,112,4,2,4,6,5,1,10,5,10,3,9,11,129,5,8,1\n\n");
+ .isEqualTo("DurationsV2: 50,5,25,8,115,2,3,7,8,15,2,7,23,10,3,6\n\n");
verify(mLatencyTracker, times(1)).pushAtom();
}
@@ -134,7 +121,6 @@
mLatencyTracker.appNotRespondingStarted();
mLatencyTracker.waitingOnAnrRecordLockStarted();
mLatencyTracker.waitingOnAnrRecordLockEnded();
- mLatencyTracker.earlyDumpRequestSubmittedWithSize(5);
mLatencyTracker.anrRecordPlacingOnQueueWithSize(3);
mLatencyTracker.appNotRespondingEnded();
@@ -157,18 +143,7 @@
mLatencyTracker.waitingOnProcLockStarted();
mLatencyTracker.waitingOnProcLockEnded();
-
-
- mLatencyTracker.dumpStackTracesTempFileStarted();
- mLatencyTracker.dumpingPidStarted(5);
-
mLatencyTracker.dumpStackTracesStarted();
- mLatencyTracker.copyingFirstPidStarted();
-
- mLatencyTracker.dumpingPidEnded();
- mLatencyTracker.dumpStackTracesTempFileEnded();
-
- mLatencyTracker.copyingFirstPidEnded(true);
mLatencyTracker.dumpingFirstPidsStarted();
mLatencyTracker.dumpingPidStarted(1);
mLatencyTracker.dumpingPidEnded();
diff --git a/services/core/java/com/android/server/am/AnrHelper.java b/services/core/java/com/android/server/am/AnrHelper.java
index 8325858..16219cd 100644
--- a/services/core/java/com/android/server/am/AnrHelper.java
+++ b/services/core/java/com/android/server/am/AnrHelper.java
@@ -22,7 +22,6 @@
import android.content.pm.ApplicationInfo;
import android.os.SystemClock;
import android.os.Trace;
-import android.util.ArraySet;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
@@ -30,12 +29,8 @@
import com.android.internal.os.TimeoutRecord;
import com.android.server.wm.WindowProcessController;
-import java.io.File;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Set;
import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
@@ -64,19 +59,13 @@
/**
* The keep alive time for the threads in the helper threadpool executor
*/
- private static final int DEFAULT_THREAD_KEEP_ALIVE_SECOND = 10;
+ private static final int AUX_THREAD_KEEP_ALIVE_SECOND = 10;
private static final ThreadFactory sDefaultThreadFactory = r ->
new Thread(r, "AnrAuxiliaryTaskExecutor");
- private static final ThreadFactory sMainProcessDumpThreadFactory = r ->
- new Thread(r, "AnrMainProcessDumpThread");
@GuardedBy("mAnrRecords")
private final ArrayList<AnrRecord> mAnrRecords = new ArrayList<>();
-
- private final Set<Integer> mTempDumpedPids =
- Collections.synchronizedSet(new ArraySet<Integer>());
-
private final AtomicBoolean mRunning = new AtomicBoolean(false);
private final ActivityManagerService mService;
@@ -91,23 +80,17 @@
private int mProcessingPid = -1;
private final ExecutorService mAuxiliaryTaskExecutor;
- private final ExecutorService mEarlyDumpExecutor;
AnrHelper(final ActivityManagerService service) {
this(service, new ThreadPoolExecutor(/* corePoolSize= */ 0, /* maximumPoolSize= */ 1,
- /* keepAliveTime= */ DEFAULT_THREAD_KEEP_ALIVE_SECOND, TimeUnit.SECONDS,
- new LinkedBlockingQueue<>(), sDefaultThreadFactory),
- new ThreadPoolExecutor(/* corePoolSize= */ 0, /* maximumPoolSize= */ 2,
- /* keepAliveTime= */ DEFAULT_THREAD_KEEP_ALIVE_SECOND, TimeUnit.SECONDS,
- new LinkedBlockingQueue<>(), sMainProcessDumpThreadFactory));
+ /* keepAliveTime= */ AUX_THREAD_KEEP_ALIVE_SECOND, TimeUnit.SECONDS,
+ new LinkedBlockingQueue<>(), sDefaultThreadFactory));
}
@VisibleForTesting
- AnrHelper(ActivityManagerService service, ExecutorService auxExecutor,
- ExecutorService earlyDumpExecutor) {
+ AnrHelper(ActivityManagerService service, ExecutorService auxExecutor) {
mService = service;
mAuxiliaryTaskExecutor = auxExecutor;
- mEarlyDumpExecutor = earlyDumpExecutor;
}
void appNotResponding(ProcessRecord anrProcess, TimeoutRecord timeoutRecord) {
@@ -138,12 +121,6 @@
+ timeoutRecord.mReason);
return;
}
- if (!mTempDumpedPids.add(incomingPid)) {
- Slog.i(TAG,
- "Skip ANR being predumped, pid=" + incomingPid + " "
- + timeoutRecord.mReason);
- return;
- }
for (int i = mAnrRecords.size() - 1; i >= 0; i--) {
if (mAnrRecords.get(i).mPid == incomingPid) {
Slog.i(TAG,
@@ -152,24 +129,10 @@
return;
}
}
- // We dump the main process as soon as we can on a different thread,
- // this is done as the main process's dump can go stale in a few hundred
- // milliseconds and the average full ANR dump takes a few seconds.
- timeoutRecord.mLatencyTracker.earlyDumpRequestSubmittedWithSize(
- mTempDumpedPids.size());
- Future<File> firstPidDumpPromise = mEarlyDumpExecutor.submit(() -> {
- // the class AnrLatencyTracker is not generally thread safe but the values
- // recorded/touched by the Temporary dump thread(s) are all volatile/atomic.
- File tracesFile = StackTracesDumpHelper.dumpStackTracesTempFile(incomingPid,
- timeoutRecord.mLatencyTracker);
- mTempDumpedPids.remove(incomingPid);
- return tracesFile;
- });
-
timeoutRecord.mLatencyTracker.anrRecordPlacingOnQueueWithSize(mAnrRecords.size());
mAnrRecords.add(new AnrRecord(anrProcess, activityShortComponentName, aInfo,
- parentShortComponentName, parentProcess, aboveSystem, timeoutRecord,
- isContinuousAnr, firstPidDumpPromise));
+ parentShortComponentName, parentProcess, aboveSystem,
+ mAuxiliaryTaskExecutor, timeoutRecord, isContinuousAnr));
}
startAnrConsumerIfNeeded();
} finally {
@@ -256,7 +219,7 @@
}
}
- private class AnrRecord {
+ private static class AnrRecord {
final ProcessRecord mApp;
final int mPid;
final String mActivityShortComponentName;
@@ -265,14 +228,14 @@
final ApplicationInfo mAppInfo;
final WindowProcessController mParentProcess;
final boolean mAboveSystem;
+ final ExecutorService mAuxiliaryTaskExecutor;
final long mTimestamp = SystemClock.uptimeMillis();
final boolean mIsContinuousAnr;
- final Future<File> mFirstPidFilePromise;
AnrRecord(ProcessRecord anrProcess, String activityShortComponentName,
ApplicationInfo aInfo, String parentShortComponentName,
WindowProcessController parentProcess, boolean aboveSystem,
- TimeoutRecord timeoutRecord, boolean isContinuousAnr,
- Future<File> firstPidFilePromise) {
+ ExecutorService auxiliaryTaskExecutor, TimeoutRecord timeoutRecord,
+ boolean isContinuousAnr) {
mApp = anrProcess;
mPid = anrProcess.mPid;
mActivityShortComponentName = activityShortComponentName;
@@ -281,8 +244,8 @@
mAppInfo = aInfo;
mParentProcess = parentProcess;
mAboveSystem = aboveSystem;
+ mAuxiliaryTaskExecutor = auxiliaryTaskExecutor;
mIsContinuousAnr = isContinuousAnr;
- mFirstPidFilePromise = firstPidFilePromise;
}
void appNotResponding(boolean onlyDumpSelf) {
@@ -291,7 +254,7 @@
mApp.mErrorState.appNotResponding(mActivityShortComponentName, mAppInfo,
mParentShortComponentName, mParentProcess, mAboveSystem,
mTimeoutRecord, mAuxiliaryTaskExecutor, onlyDumpSelf,
- mIsContinuousAnr, mFirstPidFilePromise);
+ mIsContinuousAnr);
} finally {
mTimeoutRecord.mLatencyTracker.anrProcessingEnded();
}
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index 7788ea4..0f8871c 100644
--- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -287,7 +287,7 @@
String parentShortComponentName, WindowProcessController parentProcess,
boolean aboveSystem, TimeoutRecord timeoutRecord,
ExecutorService auxiliaryTaskExecutor, boolean onlyDumpSelf,
- boolean isContinuousAnr, Future<File> firstPidFilePromise) {
+ boolean isContinuousAnr) {
String annotation = timeoutRecord.mReason;
AnrLatencyTracker latencyTracker = timeoutRecord.mLatencyTracker;
Future<?> updateCpuStatsNowFirstCall = null;
@@ -334,6 +334,7 @@
Counter.logIncrement("stability_anr.value_skipped_anrs");
return;
}
+
// In case we come through here for the same app before completing
// this one, mark as anring now so we will bail out.
latencyTracker.waitingOnProcLockStarted();
@@ -367,9 +368,6 @@
firstPids.add(pid);
// Don't dump other PIDs if it's a background ANR or is requested to only dump self.
- // Note that the primary pid is added here just in case, as it should normally be
- // dumped on the early dump thread, and would only be dumped on the Anr consumer thread
- // as a fallback.
isSilentAnr = isSilentAnr();
if (!isSilentAnr && !onlyDumpSelf) {
int parentPid = pid;
@@ -500,7 +498,7 @@
File tracesFile = StackTracesDumpHelper.dumpStackTraces(firstPids,
isSilentAnr ? null : processCpuTracker, isSilentAnr ? null : lastPids,
nativePidsFuture, tracesFileException, firstPidEndOffset, annotation,
- criticalEventLog, auxiliaryTaskExecutor, firstPidFilePromise, latencyTracker);
+ criticalEventLog, auxiliaryTaskExecutor, latencyTracker);
if (isMonitorCpuUsage()) {
// Wait for the first call to finish
diff --git a/services/core/java/com/android/server/am/StackTracesDumpHelper.java b/services/core/java/com/android/server/am/StackTracesDumpHelper.java
index 2e99e97..9373328 100644
--- a/services/core/java/com/android/server/am/StackTracesDumpHelper.java
+++ b/services/core/java/com/android/server/am/StackTracesDumpHelper.java
@@ -41,7 +41,6 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -51,8 +50,6 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Supplier;
@@ -68,16 +65,11 @@
new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS");
static final String ANR_FILE_PREFIX = "anr_";
- static final String ANR_TEMP_FILE_PREFIX = "temp_anr_";
-
public static final String ANR_TRACE_DIR = "/data/anr";
+
private static final int NATIVE_DUMP_TIMEOUT_MS =
2000 * Build.HW_TIMEOUT_MULTIPLIER; // 2 seconds;
private static final int JAVA_DUMP_MINIMUM_SIZE = 100; // 100 bytes.
- // The time limit for a single process's dump
- private static final int TEMP_DUMP_TIME_LIMIT =
- 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER; // 10 seconds
-
/**
* If a stack trace dump file is configured, dump process stack traces.
@@ -93,8 +85,7 @@
Future<ArrayList<Integer>> nativePidsFuture, StringWriter logExceptionCreatingFile,
@NonNull Executor auxiliaryTaskExecutor, AnrLatencyTracker latencyTracker) {
return dumpStackTraces(firstPids, processCpuTracker, lastPids, nativePidsFuture,
- logExceptionCreatingFile, null, null, null, auxiliaryTaskExecutor, null,
- latencyTracker);
+ logExceptionCreatingFile, null, null, null, auxiliaryTaskExecutor, latencyTracker);
}
/**
@@ -108,7 +99,7 @@
AnrLatencyTracker latencyTracker) {
return dumpStackTraces(firstPids, processCpuTracker, lastPids, nativePidsFuture,
logExceptionCreatingFile, null, subject, criticalEventSection,
- auxiliaryTaskExecutor, null, latencyTracker);
+ auxiliaryTaskExecutor, latencyTracker);
}
/**
@@ -119,8 +110,7 @@
ProcessCpuTracker processCpuTracker, SparseBooleanArray lastPids,
Future<ArrayList<Integer>> nativePidsFuture, StringWriter logExceptionCreatingFile,
AtomicLong firstPidEndOffset, String subject, String criticalEventSection,
- @NonNull Executor auxiliaryTaskExecutor, Future<File> firstPidFilePromise,
- AnrLatencyTracker latencyTracker) {
+ @NonNull Executor auxiliaryTaskExecutor, AnrLatencyTracker latencyTracker) {
try {
if (latencyTracker != null) {
@@ -168,7 +158,7 @@
long firstPidEndPos = dumpStackTraces(
tracesFile.getAbsolutePath(), firstPids, nativePidsFuture,
- extraPidsFuture, firstPidFilePromise, latencyTracker);
+ extraPidsFuture, latencyTracker);
if (firstPidEndOffset != null) {
firstPidEndOffset.set(firstPidEndPos);
}
@@ -182,6 +172,7 @@
latencyTracker.dumpStackTracesEnded();
}
}
+
}
/**
@@ -189,8 +180,7 @@
*/
public static long dumpStackTraces(String tracesFile,
ArrayList<Integer> firstPids, Future<ArrayList<Integer>> nativePidsFuture,
- Future<ArrayList<Integer>> extraPidsFuture, Future<File> firstPidFilePromise,
- AnrLatencyTracker latencyTracker) {
+ Future<ArrayList<Integer>> extraPidsFuture, AnrLatencyTracker latencyTracker) {
Slog.i(TAG, "Dumping to " + tracesFile);
@@ -201,52 +191,33 @@
// We must complete all stack dumps within 20 seconds.
long remainingTime = 20 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
- // As applications are usually interested with the ANR stack traces, but we can't share
- // with them the stack traces other than their own stacks. So after the very first PID is
+ // As applications are usually interested with the ANR stack traces, but we can't share with
+ // them the stack traces other than their own stacks. So after the very first PID is
// dumped, remember the current file size.
long firstPidEnd = -1;
- // Was the first pid copied from the temporary file that was created in the predump phase?
- boolean firstPidTempDumpCopied = false;
-
- // First copy the first pid's dump from the temporary file it was dumped into earlier,
- // The first pid should always exist in firstPids but we check the size just in case.
- if (firstPidFilePromise != null && firstPids != null && firstPids.size() > 0) {
- final int primaryPid = firstPids.get(0);
- final long start = SystemClock.elapsedRealtime();
- firstPidTempDumpCopied = copyFirstPidTempDump(tracesFile, firstPidFilePromise,
- remainingTime, latencyTracker);
- final long timeTaken = SystemClock.elapsedRealtime() - start;
- remainingTime -= timeTaken;
- if (remainingTime <= 0) {
- Slog.e(TAG, "Aborting stack trace dump (currently copying primary pid" + primaryPid
- + "); deadline exceeded.");
- return firstPidEnd;
- }
- // We don't copy ANR traces from the system_server intentionally.
- if (firstPidTempDumpCopied && primaryPid != ActivityManagerService.MY_PID) {
- firstPidEnd = new File(tracesFile).length();
- }
- // Append the Durations/latency comma separated array after the first PID.
- if (latencyTracker != null) {
- appendtoANRFile(tracesFile,
- latencyTracker.dumpAsCommaSeparatedArrayWithHeader());
- }
- }
- // Next collect all of the stacks of the most important pids.
- if (firstPids != null) {
+ // First collect all of the stacks of the most important pids.
+ if (firstPids != null) {
if (latencyTracker != null) {
latencyTracker.dumpingFirstPidsStarted();
}
int num = firstPids.size();
- for (int i = firstPidTempDumpCopied ? 1 : 0; i < num; i++) {
+ for (int i = 0; i < num; i++) {
final int pid = firstPids.get(i);
// We don't copy ANR traces from the system_server intentionally.
final boolean firstPid = i == 0 && ActivityManagerService.MY_PID != pid;
+ if (latencyTracker != null) {
+ latencyTracker.dumpingPidStarted(pid);
+ }
+
Slog.i(TAG, "Collecting stacks for pid " + pid);
- final long timeTaken = dumpJavaTracesTombstoned(pid, tracesFile, remainingTime,
- latencyTracker);
+ final long timeTaken = dumpJavaTracesTombstoned(pid, tracesFile,
+ remainingTime);
+ if (latencyTracker != null) {
+ latencyTracker.dumpingPidEnded();
+ }
+
remainingTime -= timeTaken;
if (remainingTime <= 0) {
Slog.e(TAG, "Aborting stack trace dump (current firstPid=" + pid
@@ -330,8 +301,13 @@
}
for (int pid : extraPids) {
Slog.i(TAG, "Collecting stacks for extra pid " + pid);
- final long timeTaken = dumpJavaTracesTombstoned(pid, tracesFile, remainingTime,
- latencyTracker);
+ if (latencyTracker != null) {
+ latencyTracker.dumpingPidStarted(pid);
+ }
+ final long timeTaken = dumpJavaTracesTombstoned(pid, tracesFile, remainingTime);
+ if (latencyTracker != null) {
+ latencyTracker.dumpingPidEnded();
+ }
remainingTime -= timeTaken;
if (remainingTime <= 0) {
Slog.e(TAG, "Aborting stack trace dump (current extra pid=" + pid
@@ -354,99 +330,6 @@
return firstPidEnd;
}
- /**
- * Dumps the supplied pid to a temporary file.
- * @param pid the PID to be dumped
- * @param latencyTracker the latency tracker instance of the current ANR.
- */
- public static File dumpStackTracesTempFile(int pid, AnrLatencyTracker latencyTracker) {
- try {
- if (latencyTracker != null) {
- latencyTracker.dumpStackTracesTempFileStarted();
- }
-
- File tmpTracesFile;
- try {
- tmpTracesFile = File.createTempFile(ANR_TEMP_FILE_PREFIX, ".txt",
- new File(ANR_TRACE_DIR));
- Slog.d(TAG, "created ANR temporary file:" + tmpTracesFile.getAbsolutePath());
- } catch (IOException e) {
- Slog.w(TAG, "Exception creating temporary ANR dump file:", e);
- if (latencyTracker != null) {
- latencyTracker.dumpStackTracesTempFileCreationFailed();
- }
- return null;
- }
-
- Slog.i(TAG, "Collecting stacks for pid " + pid + " into temporary file "
- + tmpTracesFile.getName());
- if (latencyTracker != null) {
- latencyTracker.dumpingPidStarted(pid);
- }
- final long timeTaken = dumpJavaTracesTombstoned(pid, tmpTracesFile.getAbsolutePath(),
- TEMP_DUMP_TIME_LIMIT);
- if (latencyTracker != null) {
- latencyTracker.dumpingPidEnded();
- }
- if (TEMP_DUMP_TIME_LIMIT <= timeTaken) {
- Slog.e(TAG, "Aborted stack trace dump (current primary pid=" + pid
- + "); deadline exceeded.");
- tmpTracesFile.delete();
- if (latencyTracker != null) {
- latencyTracker.dumpStackTracesTempFileTimedOut();
- }
- return null;
- }
- if (DEBUG_ANR) {
- Slog.d(TAG, "Done with primary pid " + pid + " in " + timeTaken + "ms"
- + " dumped into temporary file " + tmpTracesFile.getName());
- }
- return tmpTracesFile;
- } finally {
- if (latencyTracker != null) {
- latencyTracker.dumpStackTracesTempFileEnded();
- }
- }
- }
-
- private static boolean copyFirstPidTempDump(String tracesFile, Future<File> firstPidFilePromise,
- long timeLimitMs, AnrLatencyTracker latencyTracker) {
-
- boolean copySucceeded = false;
- try (FileOutputStream fos = new FileOutputStream(tracesFile, true)) {
- if (latencyTracker != null) {
- latencyTracker.copyingFirstPidStarted();
- }
- final File tempfile = firstPidFilePromise.get(timeLimitMs, TimeUnit.MILLISECONDS);
- if (tempfile != null) {
- Files.copy(tempfile.toPath(), fos);
- // Delete the temporary first pid dump file
- tempfile.delete();
- copySucceeded = true;
- return copySucceeded;
- }
- return false;
- } catch (ExecutionException e) {
- Slog.w(TAG, "Failed to collect the first pid's predump to the main ANR file",
- e.getCause());
- return false;
- } catch (InterruptedException e) {
- Slog.w(TAG, "Interrupted while collecting the first pid's predump"
- + " to the main ANR file", e);
- return false;
- } catch (IOException e) {
- Slog.w(TAG, "Failed to read the first pid's predump file", e);
- return false;
- } catch (TimeoutException e) {
- Slog.w(TAG, "Copying the first pid timed out", e);
- return false;
- } finally {
- if (latencyTracker != null) {
- latencyTracker.copyingFirstPidEnded(copySucceeded);
- }
- }
- }
-
private static synchronized File createAnrDumpFile(File tracesDir) throws IOException {
final String formattedDate = ANR_FILE_DATE_FORMAT.format(new Date());
final File anrFile = new File(tracesDir, ANR_FILE_PREFIX + formattedDate);
@@ -523,21 +406,6 @@
Slog.w(TAG, "tombstone modification times changed while sorting; not pruning", e);
}
}
-
- private static long dumpJavaTracesTombstoned(int pid, String fileName, long timeoutMs,
- AnrLatencyTracker latencyTracker) {
- try {
- if (latencyTracker != null) {
- latencyTracker.dumpingPidStarted(pid);
- }
- return dumpJavaTracesTombstoned(pid, fileName, timeoutMs);
- } finally {
- if (latencyTracker != null) {
- latencyTracker.dumpingPidEnded();
- }
- }
- }
-
/**
* Dump java traces for process {@code pid} to the specified file. If java trace dumping
* fails, a native backtrace is attempted. Note that the timeout {@code timeoutMs} only applies
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 1c46dd6..7b9cc6f 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -5371,7 +5371,7 @@
if (app != null && app.getPid() > 0) {
ArrayList<Integer> firstPids = new ArrayList<Integer>();
firstPids.add(app.getPid());
- dumpStackTraces(tracesFile.getAbsolutePath(), firstPids, null, null, null, null);
+ dumpStackTraces(tracesFile.getAbsolutePath(), firstPids, null, null, null);
}
File lastTracesFile = null;
diff --git a/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java b/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java
index acdfee9..9578993 100644
--- a/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/AnrHelperTest.java
@@ -26,7 +26,6 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
@@ -49,10 +48,8 @@
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
@@ -66,9 +63,8 @@
private AnrHelper mAnrHelper;
private ProcessRecord mAnrApp;
- private ExecutorService mAuxExecutorService;
+ private ExecutorService mExecutorService;
- private Future<File> mEarlyDumpFuture;
@Rule
public ServiceThreadRule mServiceThreadRule = new ServiceThreadRule();
@@ -95,12 +91,9 @@
return mServiceThreadRule.getThread().getThreadHandler();
}
}, mServiceThreadRule.getThread());
- mAuxExecutorService = mock(ExecutorService.class);
- final ExecutorService earlyDumpExecutorService = mock(ExecutorService.class);
- mEarlyDumpFuture = mock(Future.class);
- doReturn(mEarlyDumpFuture).when(earlyDumpExecutorService).submit(any(Callable.class));
+ mExecutorService = mock(ExecutorService.class);
- mAnrHelper = new AnrHelper(service, mAuxExecutorService, earlyDumpExecutorService);
+ mAnrHelper = new AnrHelper(service, mExecutorService);
});
}
@@ -132,8 +125,8 @@
verify(mAnrApp.mErrorState, timeout(TIMEOUT_MS)).appNotResponding(
eq(activityShortComponentName), eq(appInfo), eq(parentShortComponentName),
- eq(parentProcess), eq(aboveSystem), eq(timeoutRecord), eq(mAuxExecutorService),
- eq(false) /* onlyDumpSelf */, eq(false) /*isContinuousAnr*/, eq(mEarlyDumpFuture));
+ eq(parentProcess), eq(aboveSystem), eq(timeoutRecord), eq(mExecutorService),
+ eq(false) /* onlyDumpSelf */, eq(false) /*isContinuousAnr*/);
}
@Test
@@ -146,7 +139,7 @@
processingLatch.await();
return null;
}).when(mAnrApp.mErrorState).appNotResponding(anyString(), any(), any(), any(),
- anyBoolean(), any(), any(), anyBoolean(), anyBoolean(), any());
+ anyBoolean(), any(), any(), anyBoolean(), anyBoolean());
final ApplicationInfo appInfo = new ApplicationInfo();
final TimeoutRecord timeoutRecord = TimeoutRecord.forInputDispatchWindowUnresponsive(
"annotation");
@@ -169,7 +162,7 @@
processingLatch.countDown();
// There is only one ANR reported.
verify(mAnrApp.mErrorState, timeout(TIMEOUT_MS).only()).appNotResponding(
- anyString(), any(), any(), any(), anyBoolean(), any(), eq(mAuxExecutorService),
- anyBoolean(), anyBoolean(), any());
+ anyString(), any(), any(), any(), anyBoolean(), any(), eq(mExecutorService),
+ anyBoolean(), anyBoolean());
}
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java
index d92b9f8..6350e22 100644
--- a/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ProcessRecordTests.java
@@ -203,6 +203,6 @@
processErrorState.appNotResponding(null /* activityShortComponentName */, null /* aInfo */,
null /* parentShortComponentName */, null /* parentProcess */,
false /* aboveSystem */, timeoutRecord, mExecutorService, false /* onlyDumpSelf */,
- false /*isContinuousAnr*/, null);
+ false /*isContinuousAnr*/);
}
}