diff options
8 files changed, 149 insertions, 79 deletions
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 @@ public final class ActivityThread { 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 @@ public final class ActivityThread { } 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 @@ interface IPowerManager 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 final class PowerManager { */ 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 @@ public final class BatteryService extends Binder { private long mDischargeStartTime; private int mDischargeStartLevel; + private boolean mUpdatesStopped; + private Led mLed; private boolean mSentLowBatteryBroadcast = false; @@ -231,7 +233,7 @@ public final class BatteryService extends Binder { 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 @@ public final class BatteryService extends Binder { 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 @@ public final class BatteryService extends Binder { 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 @@ public final class BatteryService extends Binder { 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 @@ public class ShutdownActivity extends Activity { 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 @@ public class Watchdog extends Thread { 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 @@ public final class PowerManagerService extends IPowerManager.Stub } /** - * 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 @@ public final class PowerManagerService extends IPowerManager.Stub 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 @@ public final class PowerManagerService extends IPowerManager.Stub 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 @@ public class BridgePowerManager implements IPowerManager { } @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. } |