am cd09cb8f: am 6fb7fd3a: Merge "Fix issue #7267494, issue #7212347" into jb-mr1-dev

* commit 'cd09cb8fb79442aa22018db9134ef1ef22059360':
  Fix issue #7267494, issue #7212347
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index ef9f6d4..5f65f08 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4530,6 +4530,14 @@
 
             IContentProvider provider = pr.mProvider;
             IBinder jBinder = provider.asBinder();
+            if (!jBinder.isBinderAlive()) {
+                // The hosting process of the provider has died; we can't
+                // use this one.
+                Log.i(TAG, "Acquiring provider " + auth + " for user " + userId
+                        + ": existing object's process dead");
+                handleUnstableProviderDiedLocked(jBinder, true);
+                return null;
+            }
 
             // Only increment the ref count if we have one.  If we don't then the
             // provider is not reference counted and never needs to be released.
@@ -4670,33 +4678,37 @@
     }
 
     final void handleUnstableProviderDied(IBinder provider, boolean fromClient) {
-        synchronized(mProviderMap) {
-            ProviderRefCount prc = mProviderRefCountMap.get(provider);
-            if (prc != null) {
-                if (DEBUG_PROVIDER) Slog.v(TAG, "Cleaning up dead provider "
-                        + provider + " " + prc.holder.info.name);
-                mProviderRefCountMap.remove(provider);
-                if (prc.client != null && prc.client.mNames != null) {
-                    for (String name : prc.client.mNames) {
-                        ProviderClientRecord pr = mProviderMap.get(name);
-                        if (pr != null && pr.mProvider.asBinder() == provider) {
-                            Slog.i(TAG, "Removing dead content provider: " + name);
-                            mProviderMap.remove(name);
-                        }
+        synchronized (mProviderMap) {
+            handleUnstableProviderDiedLocked(provider, fromClient);
+        }
+    }
+
+    final void handleUnstableProviderDiedLocked(IBinder provider, boolean fromClient) {
+        ProviderRefCount prc = mProviderRefCountMap.get(provider);
+        if (prc != null) {
+            if (DEBUG_PROVIDER) Slog.v(TAG, "Cleaning up dead provider "
+                    + provider + " " + prc.holder.info.name);
+            mProviderRefCountMap.remove(provider);
+            if (prc.client != null && prc.client.mNames != null) {
+                for (String name : prc.client.mNames) {
+                    ProviderClientRecord pr = mProviderMap.get(name);
+                    if (pr != null && pr.mProvider.asBinder() == provider) {
+                        Slog.i(TAG, "Removing dead content provider: " + name);
+                        mProviderMap.remove(name);
                     }
                 }
-                if (fromClient) {
-                    // We found out about this due to execution in our client
-                    // code.  Tell the activity manager about it now, to ensure
-                    // that the next time we go to do anything with the provider
-                    // it knows it is dead (so we don't race with its death
-                    // notification).
-                    try {
-                        ActivityManagerNative.getDefault().unstableProviderDied(
-                                prc.holder.connection);
-                    } catch (RemoteException e) {
-                        //do nothing content provider object is dead any way
-                    }
+            }
+            if (fromClient) {
+                // We found out about this due to execution in our client
+                // code.  Tell the activity manager about it now, to ensure
+                // that the next time we go to do anything with the provider
+                // it knows it is dead (so we don't race with its death
+                // notification).
+                try {
+                    ActivityManagerNative.getDefault().unstableProviderDied(
+                            prc.holder.connection);
+                } catch (RemoteException e) {
+                    //do nothing content provider object is dead any way
                 }
             }
         }
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 557d3f3..6d6d147 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -37,7 +37,8 @@
     void nap(long time);
 
     boolean isScreenOn();
-    void reboot(String reason);
+    void reboot(boolean confirm, String reason, boolean wait);
+    void shutdown(boolean confirm, boolean wait);
     void crash(String message);
 
     void setStayOnSetting(int val);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index ae50ddb..fb02c0a 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -596,7 +596,7 @@
      */
     public void reboot(String reason) {
         try {
-            mService.reboot(reason);
+            mService.reboot(false, reason, true);
         } catch (RemoteException e) {
         }
     }
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index 0045f4a..40758d3 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -127,6 +127,8 @@
     private long mDischargeStartTime;
     private int mDischargeStartLevel;
 
+    private boolean mUpdatesStopped;
+
     private Led mLed;
 
     private boolean mSentLowBatteryBroadcast = false;
@@ -231,7 +233,7 @@
             Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
             intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            mContext.startActivity(intent);
+            mContext.startActivityAsUser(intent, UserHandle.CURRENT);
         }
     }
 
@@ -244,16 +246,18 @@
             Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
             intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            mContext.startActivity(intent);
+            mContext.startActivityAsUser(intent, UserHandle.CURRENT);
         }
     }
 
     private void updateLocked() {
-        // Update the values of mAcOnline, et. all.
-        native_update();
+        if (!mUpdatesStopped) {
+            // Update the values of mAcOnline, et. all.
+            native_update();
 
-        // Process the new values.
-        processValuesLocked();
+            // Process the new values.
+            processValuesLocked();
+        }
     }
 
     private void processValuesLocked() {
@@ -543,6 +547,9 @@
         synchronized (mLock) {
             if (args == null || args.length == 0 || "-a".equals(args[0])) {
                 pw.println("Current Battery Service state:");
+                if (mUpdatesStopped) {
+                    pw.println("  (UPDATES STOPPED -- use 'reset' to restart)");
+                }
                 pw.println("  AC powered: " + mAcOnline);
                 pw.println("  USB powered: " + mUsbOnline);
                 pw.println("  Wireless powered: " + mWirelessOnline);
@@ -554,35 +561,41 @@
                 pw.println("  voltage:" + mBatteryVoltage);
                 pw.println("  temperature: " + mBatteryTemperature);
                 pw.println("  technology: " + mBatteryTechnology);
-            } else if (false) {
-                // DO NOT SUBMIT WITH THIS TURNED ON
-                if (args.length == 3 && "set".equals(args[0])) {
-                    String key = args[1];
-                    String value = args[2];
-                    try {
-                        boolean update = true;
-                        if ("ac".equals(key)) {
-                            mAcOnline = Integer.parseInt(value) != 0;
-                        } else if ("usb".equals(key)) {
-                            mUsbOnline = Integer.parseInt(value) != 0;
-                        } else if ("wireless".equals(key)) {
-                            mWirelessOnline = Integer.parseInt(value) != 0;
-                        } else if ("status".equals(key)) {
-                            mBatteryStatus = Integer.parseInt(value);
-                        } else if ("level".equals(key)) {
-                            mBatteryLevel = Integer.parseInt(value);
-                        } else if ("invalid".equals(key)) {
-                            mInvalidCharger = Integer.parseInt(value);
-                        } else {
-                            update = false;
-                        }
-                        if (update) {
-                            processValuesLocked();
-                        }
-                    } catch (NumberFormatException ex) {
-                        pw.println("Bad value: " + value);
+            } else if (args.length == 3 && "set".equals(args[0])) {
+                String key = args[1];
+                String value = args[2];
+                try {
+                    boolean update = true;
+                    if ("ac".equals(key)) {
+                        mAcOnline = Integer.parseInt(value) != 0;
+                    } else if ("usb".equals(key)) {
+                        mUsbOnline = Integer.parseInt(value) != 0;
+                    } else if ("wireless".equals(key)) {
+                        mWirelessOnline = Integer.parseInt(value) != 0;
+                    } else if ("status".equals(key)) {
+                        mBatteryStatus = Integer.parseInt(value);
+                    } else if ("level".equals(key)) {
+                        mBatteryLevel = Integer.parseInt(value);
+                    } else if ("invalid".equals(key)) {
+                        mInvalidCharger = Integer.parseInt(value);
+                    } else {
+                        pw.println("Unknown set option: " + key);
+                        update = false;
                     }
+                    if (update) {
+                        mUpdatesStopped = true;
+                        processValuesLocked();
+                    }
+                } catch (NumberFormatException ex) {
+                    pw.println("Bad value: " + value);
                 }
+            } else if (args.length == 1 && "reset".equals(args[0])) {
+                mUpdatesStopped = false;
+                updateLocked();
+            } else {
+                pw.println("Dump current battery state, or:");
+                pw.println("  set ac|usb|wireless|status|level|invalid <value>");
+                pw.println("  reset");
             }
         }
     }
diff --git a/services/java/com/android/server/ShutdownActivity.java b/services/java/com/android/server/ShutdownActivity.java
index a4341b7..be65141 100644
--- a/services/java/com/android/server/ShutdownActivity.java
+++ b/services/java/com/android/server/ShutdownActivity.java
@@ -17,9 +17,13 @@
 package com.android.server;
 
 import android.app.Activity;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.IPowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.util.Slog;
 
 import com.android.server.power.ShutdownThread;
@@ -39,15 +43,27 @@
         mConfirm = intent.getBooleanExtra(Intent.EXTRA_KEY_CONFIRM, false);
         Slog.i(TAG, "onCreate(): confirm=" + mConfirm);
 
-        Handler h = new Handler();
-        h.post(new Runnable() {
+        Thread thr = new Thread("ShutdownActivity") {
+            @Override
             public void run() {
-                if (mReboot) {
-                    ShutdownThread.reboot(ShutdownActivity.this, null, mConfirm);
-                } else {
-                    ShutdownThread.shutdown(ShutdownActivity.this, mConfirm);
+                IPowerManager pm = IPowerManager.Stub.asInterface(
+                        ServiceManager.getService(Context.POWER_SERVICE));
+                try {
+                    if (mReboot) {
+                        pm.reboot(mConfirm, null, false);
+                    } else {
+                        pm.shutdown(mConfirm, false);
+                    }
+                } catch (RemoteException e) {
                 }
             }
-        });
+        };
+        thr.start();
+        finish();
+        // Wait for us to tell the power manager to shutdown.
+        try {
+            thr.join();
+        } catch (InterruptedException e) {
+        }
     }
 }
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index 1342250..8bbf923 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -305,7 +305,7 @@
     void rebootSystem(String reason) {
         Slog.i(TAG, "Rebooting system because: " + reason);
         PowerManagerService pms = (PowerManagerService) ServiceManager.getService("power");
-        pms.reboot(reason);
+        pms.reboot(false, reason, false);
     }
 
     /**
diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java
index c91fa3c..9a01022 100644
--- a/services/java/com/android/server/power/PowerManagerService.java
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -1602,22 +1602,39 @@
     }
 
     /**
-     * Reboot the device immediately, passing 'reason' (may be null)
+     * Reboot the device, passing 'reason' (may be null)
      * to the underlying __reboot system call.  Should not return.
      */
     @Override // Binder call
-    public void reboot(String reason) {
+    public void reboot(boolean confirm, String reason, boolean wait) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
 
         final long ident = Binder.clearCallingIdentity();
         try {
-            rebootInternal(reason);
+            rebootInternal(false, confirm, reason, wait);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
     }
 
-    private void rebootInternal(final String reason) {
+    /**
+     * Shutdown the devic, passing 'reason' (may be null)
+     * to the underlying __reboot system call.  Should not return.
+     */
+    @Override // Binder call
+    public void shutdown(boolean confirm, boolean wait) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            rebootInternal(true, confirm, null, wait);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void rebootInternal(final boolean shutdown, final boolean confirm,
+            final String reason, boolean wait) {
         if (mHandler == null || !mSystemReady) {
             throw new IllegalStateException("Too early to call reboot()");
         }
@@ -1625,7 +1642,11 @@
         Runnable runnable = new Runnable() {
             public void run() {
                 synchronized (this) {
-                    ShutdownThread.reboot(mContext, reason, false);
+                    if (shutdown) {
+                        ShutdownThread.shutdown(mContext, confirm);
+                    } else {
+                        ShutdownThread.reboot(mContext, reason, confirm);
+                    }
                 }
             }
         };
@@ -1636,11 +1657,13 @@
         mHandler.sendMessage(msg);
 
         // PowerManager.reboot() is documented not to return so just wait for the inevitable.
-        synchronized (runnable) {
-            while (true) {
-                try {
-                    runnable.wait();
-                } catch (InterruptedException e) {
+        if (wait) {
+            synchronized (runnable) {
+                while (true) {
+                    try {
+                        runnable.wait();
+                    } catch (InterruptedException e) {
+                    }
                 }
             }
         }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 5e23f24..1ccbc40 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -60,7 +60,12 @@
     }
 
     @Override
-    public void reboot(String arg0) throws RemoteException {
+    public void reboot(boolean confirm, String reason, boolean wait) {
+        // pass for now.
+    }
+
+    @Override
+    public void shutdown(boolean confirm, boolean wait) {
         // pass for now.
     }