resolved conflicts for merge of 485d7a31 to master

Change-Id: I058e19af8732df44457bdc614ee810a642dc25e4
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 95343f9..dca873e 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -1109,6 +1109,18 @@
             }
         }
 
+        @Override
+        public int systemNotResponding(String message)
+                throws RemoteException {
+            synchronized (this) {
+                System.out.println("** ERROR: PROCESS NOT RESPONDING");
+                System.out.println("message: " + message);
+                System.out.println("#");
+                System.out.println("Allowing system to die.");
+                return -1;
+            }
+        }
+
         void killGdbLocked() {
             mGotGdbPrint = false;
             if (mGdbProcess != null) {
diff --git a/core/java/android/app/IActivityController.aidl b/core/java/android/app/IActivityController.aidl
index aca8305..952c900 100644
--- a/core/java/android/app/IActivityController.aidl
+++ b/core/java/android/app/IActivityController.aidl
@@ -58,4 +58,11 @@
      * immediately.
      */
     int appNotResponding(String processName, int pid, String processStats);
+
+    /**
+     * The system process watchdog has detected that the system seems to be
+     * hung.  Return 1 to continue waiting, or -1 to let it continue with its
+     * normal kill.
+     */
+    int systemNotResponding(String msg);
 }
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index e9e7551..7ffd30b 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -49,6 +49,11 @@
     private static final boolean FIND_POTENTIAL_LEAKS = false;
     private static final String TAG = "Binder";
 
+    /**
+     * Control whether dump() calls are allowed.
+     */
+    private static String sDumpDisabled = null;
+
     /* mObject is used by native code, do not remove or rename */
     private int mObject;
     private IInterface mOwner;
@@ -224,7 +229,23 @@
         }
         return null;
     }
-    
+
+    /**
+     * Control disabling of dump calls in this process.  This is used by the system
+     * process watchdog to disable incoming dump calls while it has detecting the system
+     * is hung and is reporting that back to the activity controller.  This is to
+     * prevent the controller from getting hung up on bug reports at this point.
+     * @hide
+     *
+     * @param msg The message to show instead of the dump; if null, dumps are
+     * re-enabled.
+     */
+    public static void setDumpDisabled(String msg) {
+        synchronized (Binder.class) {
+            sDumpDisabled = msg;
+        }
+    }
+
     /**
      * Default implementation is a stub that returns false.  You will want
      * to override this to do the appropriate unmarshalling of transactions.
@@ -269,7 +290,15 @@
         FileOutputStream fout = new FileOutputStream(fd);
         PrintWriter pw = new PrintWriter(fout);
         try {
-            dump(fd, pw, args);
+            final String disabled;
+            synchronized (Binder.class) {
+                disabled = sDumpDisabled;
+            }
+            if (disabled == null) {
+                dump(fd, pw, args);
+            } else {
+                pw.println(sDumpDisabled);
+            }
         } finally {
             pw.flush();
         }
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index 6a47243..92c35f8 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -16,6 +16,9 @@
 
 package com.android.server;
 
+import android.app.IActivityController;
+import android.os.Binder;
+import android.os.RemoteException;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.power.PowerManagerService;
 
@@ -89,6 +92,7 @@
     ActivityManagerService mActivity;
 
     int mPhonePid;
+    IActivityController mController;
 
     final Calendar mCalendar = Calendar.getInstance();
     int mMinScreenOff = MEMCHECK_DEFAULT_MIN_SCREEN_OFF;
@@ -260,6 +264,12 @@
         }
     }
 
+    public void setActivityController(IActivityController controller) {
+        synchronized (this) {
+            mController = controller;
+        }
+    }
+
     public void addMonitor(Monitor monitor) {
         synchronized (this) {
             if (isAlive()) {
@@ -549,6 +559,25 @@
                 dropboxThread.join(2000);  // wait up to 2 seconds for it to return.
             } catch (InterruptedException ignored) {}
 
+            IActivityController controller;
+            synchronized (this) {
+                controller = mController;
+            }
+            if (controller != null) {
+                Slog.i(TAG, "Reporting stuck state to activity controller");
+                try {
+                    Binder.setDumpDisabled("Service dumps disabled due to hung system process.");
+                    // 1 = keep waiting, -1 = kill system
+                    int res = controller.systemNotResponding(name);
+                    if (res >= 0) {
+                        Slog.i(TAG, "Activity controller requested to coninue to wait");
+                        waitedHalf = false;
+                        continue;
+                    }
+                } catch (RemoteException e) {
+                }
+            }
+
             // Only kill the process if the debugger is not attached.
             if (!Debug.isDebuggerConnected()) {
                 Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + name);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index c34b4ec..14529bb 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2920,6 +2920,7 @@
                         resumeOK = mController.activityResuming(next.packageName);
                     } catch (RemoteException e) {
                         mController = null;
+                        Watchdog.getInstance().setActivityController(null);
                     }
 
                     if (!resumeOK) {
@@ -3413,6 +3414,7 @@
                 if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
             } catch (RemoteException e) {
                 mController = null;
+                Watchdog.getInstance().setActivityController(null);
             }
         }
 
@@ -3516,6 +3518,7 @@
                 }
             } catch (RemoteException e) {
                 mController = null;
+                Watchdog.getInstance().setActivityController(null);
             }
         }
 
@@ -7569,6 +7572,7 @@
                 "setActivityController()");
         synchronized (this) {
             mController = controller;
+            Watchdog.getInstance().setActivityController(controller);
         }
     }
 
@@ -8932,6 +8936,7 @@
                     }
                 } catch (RemoteException e) {
                     mController = null;
+                    Watchdog.getInstance().setActivityController(null);
                 }
             }
 
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 4787a1e..ba14b3b 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -20,6 +20,7 @@
 
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.util.Objects;
+import com.android.server.Watchdog;
 import com.android.server.am.ActivityManagerService.ItemMatcher;
 import com.android.server.wm.AppTransition;
 import com.android.server.wm.TaskGroup;
@@ -2498,6 +2499,7 @@
                     resumeOK = controller.activityResuming(next.packageName);
                 } catch (RemoteException e) {
                     mService.mController = null;
+                    Watchdog.getInstance().setActivityController(null);
                 }
 
                 if (!resumeOK) {
@@ -3022,6 +3024,7 @@
                     moveOK = mService.mController.activityResuming(next.packageName);
                 } catch (RemoteException e) {
                     mService.mController = null;
+                    Watchdog.getInstance().setActivityController(null);
                 }
                 if (!moveOK) {
                     return false;