Log to dropbox if we fail to create an ANR stack trace file.

Some ANRs have no stack traces uploaded through dropbox. This appears to be because the file holding them was not created

So in the case where we can't create the file, add an exception message to the string part of the dropbox upload.

Change-Id: Ic06ac9c25974633905b1a0bfcfcef8ed833795e8
Bug: 148848039
Test: Manually threw exception in createAnrDumpFile() and triggered ANR.
diff --git a/services/core/java/com/android/server/SystemServerInitThreadPool.java b/services/core/java/com/android/server/SystemServerInitThreadPool.java
index 179780d..8f914fe 100644
--- a/services/core/java/com/android/server/SystemServerInitThreadPool.java
+++ b/services/core/java/com/android/server/SystemServerInitThreadPool.java
@@ -175,6 +175,6 @@
         final ArrayList<Integer> pids = new ArrayList<>();
         pids.add(Process.myPid());
         ActivityManagerService.dumpStackTraces(pids, null, null,
-                Watchdog.getInterestingNativePids());
+                Watchdog.getInterestingNativePids(), null);
     }
 }
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 8900eee..7797829 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -50,6 +50,7 @@
 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;
@@ -583,7 +584,7 @@
                             ArrayList<Integer> pids = new ArrayList<Integer>();
                             pids.add(Process.myPid());
                             ActivityManagerService.dumpStackTraces(pids, null, null,
-                                getInterestingNativePids());
+                                    getInterestingNativePids(), null);
                             waitedHalf = true;
                         }
                         continue;
@@ -610,15 +611,19 @@
 
             long anrTime = SystemClock.uptimeMillis();
             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);
+            StringBuilder report = new StringBuilder();
+            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');
@@ -634,7 +639,7 @@
                         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);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0d8eff5..676f40b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3851,10 +3851,11 @@
      * @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);
@@ -3894,8 +3895,15 @@
         // 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;
         }
 
@@ -3906,7 +3914,7 @@
     @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");
         }
@@ -3914,18 +3922,12 @@
         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");
-            }
-        } catch (IOException ioe) {
-            Slog.w(TAG, "Exception creating ANR dump file:", ioe);
+        if (anrFile.createNewFile()) {
+            FileUtils.setPermissions(anrFile.getAbsolutePath(), 0600, -1, -1); // -rw-------
+            return anrFile;
+        } else {
+            throw new IOException("Unable to create ANR dump file: createNewFile failed");
         }
-
-        return null;
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index e63da9b..86df794 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -71,6 +71,7 @@
 
 import java.io.File;
 import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -1608,19 +1609,21 @@
 
         // 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;
+        StringBuilder report = new StringBuilder();
         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));
 
@@ -1645,7 +1648,8 @@
         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),
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index 5b892f8..deaec0a 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -158,7 +158,8 @@
         }
 
         final File tracesFile = ActivityManagerService.dumpStackTraces(firstPids,
-                null /* processCpuTracker */, null /* lastPids */, nativePids);
+                null /* processCpuTracker */, null /* lastPids */, nativePids,
+                null /* logExceptionCreatingFile */);
         if (tracesFile != null) {
             tracesFile.renameTo(new File(tracesFile.getParent(), tracesFile.getName() + "_pre"));
         }