summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ActivityThread.java62
-rw-r--r--core/java/android/os/IPowerManager.aidl3
-rw-r--r--core/java/android/os/PowerManager.java2
-rw-r--r--services/java/com/android/server/BatteryService.java79
-rw-r--r--services/java/com/android/server/ShutdownActivity.java30
-rw-r--r--services/java/com/android/server/Watchdog.java2
-rw-r--r--services/java/com/android/server/power/PowerManagerService.java43
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java7
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.
}