summaryrefslogtreecommitdiffstats
path: root/services/java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java')
-rw-r--r--services/java/com/android/server/PowerManagerService.java87
-rw-r--r--services/java/com/android/server/ShutdownActivity.java3
-rw-r--r--services/java/com/android/server/SystemServer.java2
-rw-r--r--services/java/com/android/server/pm/ShutdownThread.java485
-rwxr-xr-xservices/java/com/android/server/wm/WindowManagerService.java19
5 files changed, 560 insertions, 36 deletions
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 289ab2a..2cc2704 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -17,8 +17,8 @@
package com.android.server;
import com.android.internal.app.IBatteryStats;
-import com.android.internal.app.ShutdownThread;
import com.android.server.am.BatteryStatsService;
+import com.android.server.pm.ShutdownThread;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
@@ -47,7 +47,6 @@ import android.os.IBinder;
import android.os.IPowerManager;
import android.os.LocalPowerManager;
import android.os.Message;
-import android.os.Power;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
@@ -71,6 +70,7 @@ import static android.provider.Settings.System.WINDOW_ANIMATION_SCALE;
import static android.provider.Settings.System.TRANSITION_ANIMATION_SCALE;
import java.io.FileDescriptor;
+import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
@@ -84,6 +84,12 @@ public class PowerManagerService extends IPowerManager.Stub
private static final String TAG = "PowerManagerService";
static final String PARTIAL_NAME = "PowerManagerService";
+ // Wake lock that ensures that the CPU is running. The screen might not be on.
+ private static final int PARTIAL_WAKE_LOCK_ID = 1;
+
+ // Wake lock that ensures that the screen is on.
+ private static final int FULL_WAKE_LOCK_ID = 2;
+
static final boolean DEBUG_SCREEN_ON = false;
private static final boolean LOG_PARTIAL_WL = false;
@@ -134,6 +140,10 @@ public class PowerManagerService extends IPowerManager.Stub
// Screen brightness should always have a value, but just in case...
private static final int DEFAULT_SCREEN_BRIGHTNESS = 192;
+ // Threshold for BRIGHTNESS_LOW_BATTERY (percentage)
+ // Screen will stay dim if battery level is <= LOW_BATTERY_THRESHOLD
+ private static final int LOW_BATTERY_THRESHOLD = 10;
+
// flags for setPowerState
private static final int ALL_LIGHTS_OFF = 0x00000000;
private static final int SCREEN_ON_BIT = 0x00000001;
@@ -175,8 +185,8 @@ public class PowerManagerService extends IPowerManager.Stub
// we should read them from the driver, but our current hardware returns 0
// for the initial value. Oops!
static final int INITIAL_SCREEN_BRIGHTNESS = 255;
- static final int INITIAL_BUTTON_BRIGHTNESS = Power.BRIGHTNESS_OFF;
- static final int INITIAL_KEYBOARD_BRIGHTNESS = Power.BRIGHTNESS_OFF;
+ static final int INITIAL_BUTTON_BRIGHTNESS = PowerManager.BRIGHTNESS_OFF;
+ static final int INITIAL_KEYBOARD_BRIGHTNESS = PowerManager.BRIGHTNESS_OFF;
private final int MY_UID;
private final int MY_PID;
@@ -296,6 +306,11 @@ public class PowerManagerService extends IPowerManager.Stub
private native void nativeInit();
private native void nativeSetPowerState(boolean screenOn, boolean screenBright);
private native void nativeStartSurfaceFlingerAnimation(int mode);
+ private static native void nativeAcquireWakeLock(int lock, String id);
+ private static native void nativeReleaseWakeLock(String id);
+ private static native int nativeSetScreenState(boolean on);
+ private static native void nativeShutdown();
+ private static native void nativeReboot(String reason) throws IOException;
/*
static PrintStream mLog;
@@ -515,14 +530,13 @@ public class PowerManagerService extends IPowerManager.Stub
MY_PID = Process.myPid();
Binder.restoreCallingIdentity(token);
- // XXX remove this when the kernel doesn't timeout wake locks
- Power.setLastUserActivityTimeout(7*24*3600*1000); // one week
-
// assume nothing is on yet
mUserState = mPowerState = 0;
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
+
+ nativeInit();
}
private ContentQueryMap mSettings;
@@ -541,11 +555,6 @@ public class PowerManagerService extends IPowerManager.Stub
mAttentionLight = lights.getLight(LightsService.LIGHT_ID_ATTENTION);
mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
- nativeInit();
- synchronized (mLocks) {
- updateNativePowerStateLocked();
- }
-
mInitComplete = false;
mScreenBrightnessAnimator = new ScreenBrightnessAnimator("mScreenBrightnessUpdaterThread",
Process.THREAD_PRIORITY_DISPLAY);
@@ -581,8 +590,6 @@ public class PowerManagerService extends IPowerManager.Stub
}
}
- nativeInit();
- Power.powerInitNative();
synchronized (mLocks) {
updateNativePowerStateLocked();
// We make sure to start out with the screen on due to user activity.
@@ -686,6 +693,26 @@ public class PowerManagerService extends IPowerManager.Stub
}
}
+ /**
+ * Low-level function turn the device off immediately, without trying
+ * to be clean. Most people should use
+ * {@link com.android.server.pm.internal.app.ShutdownThread} for a clean shutdown.
+ */
+ public static void lowLevelShutdown() {
+ nativeShutdown();
+ }
+
+ /**
+ * Low-level function to reboot the device.
+ *
+ * @param reason code to pass to the kernel (e.g. "recovery"), or null.
+ * @throws IOException if reboot fails for some reason (eg, lack of
+ * permission)
+ */
+ public static void lowLevelReboot(String reason) throws IOException {
+ nativeReboot(reason);
+ }
+
private class WakeLock implements IBinder.DeathRecipient
{
WakeLock(int f, IBinder b, String t, int u, int p) {
@@ -926,7 +953,7 @@ public class PowerManagerService extends IPowerManager.Stub
if (LOG_PARTIAL_WL) EventLog.writeEvent(EventLogTags.POWER_PARTIAL_WAKE_STATE, 1, tag);
}
}
- Power.acquireWakeLock(Power.PARTIAL_WAKE_LOCK,PARTIAL_NAME);
+ nativeAcquireWakeLock(PARTIAL_WAKE_LOCK_ID, PARTIAL_NAME);
}
if (diffsource) {
@@ -1010,7 +1037,7 @@ public class PowerManagerService extends IPowerManager.Stub
mPartialCount--;
if (mPartialCount == 0) {
if (LOG_PARTIAL_WL) EventLog.writeEvent(EventLogTags.POWER_PARTIAL_WAKE_STATE, 0, wl.tag);
- Power.releaseWakeLock(PARTIAL_NAME);
+ nativeReleaseWakeLock(PARTIAL_NAME);
}
}
// Unlink the lock from the binder.
@@ -1719,10 +1746,10 @@ public class PowerManagerService extends IPowerManager.Stub
+ " mSkippedScreenOn=" + mSkippedScreenOn);
}
mScreenBrightnessHandler.removeMessages(ScreenBrightnessAnimator.ANIMATE_LIGHTS);
- mScreenBrightnessAnimator.animateTo(Power.BRIGHTNESS_OFF, SCREEN_BRIGHT_BIT, 0);
+ mScreenBrightnessAnimator.animateTo(PowerManager.BRIGHTNESS_OFF, SCREEN_BRIGHT_BIT, 0);
}
}
- int err = Power.setScreenState(on);
+ int err = nativeSetScreenState(on);
if (err == 0) {
mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0);
if (mUseSoftwareAutoBrightness) {
@@ -1934,7 +1961,7 @@ public class PowerManagerService extends IPowerManager.Stub
private boolean batteryIsLow() {
return (!mIsPowered &&
- mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD);
+ mBatteryService.getBatteryLevel() <= LOW_BATTERY_THRESHOLD);
}
private boolean shouldDeferScreenOnLocked() {
@@ -2024,7 +2051,7 @@ public class PowerManagerService extends IPowerManager.Stub
nominalCurrentValue = mScreenBrightnessDim;
break;
case 0:
- nominalCurrentValue = Power.BRIGHTNESS_OFF;
+ nominalCurrentValue = PowerManager.BRIGHTNESS_OFF;
break;
case SCREEN_BRIGHT_BIT:
default:
@@ -2050,7 +2077,7 @@ public class PowerManagerService extends IPowerManager.Stub
// was dim
steps = (int)(ANIM_STEPS*ratio*scale);
}
- brightness = Power.BRIGHTNESS_OFF;
+ brightness = PowerManager.BRIGHTNESS_OFF;
} else {
if ((oldState & SCREEN_ON_BIT) != 0) {
// was bright
@@ -2101,13 +2128,13 @@ public class PowerManagerService extends IPowerManager.Stub
if (offMask != 0) {
if (mSpew) Slog.i(TAG, "Setting brightess off: " + offMask);
- setLightBrightness(offMask, Power.BRIGHTNESS_OFF);
+ setLightBrightness(offMask, PowerManager.BRIGHTNESS_OFF);
}
if (dimMask != 0) {
int brightness = mScreenBrightnessDim;
if ((newState & BATTERY_LOW_BIT) != 0 &&
- brightness > Power.BRIGHTNESS_LOW_BATTERY) {
- brightness = Power.BRIGHTNESS_LOW_BATTERY;
+ brightness > PowerManager.BRIGHTNESS_LOW_BATTERY) {
+ brightness = PowerManager.BRIGHTNESS_LOW_BATTERY;
}
if (mSpew) Slog.i(TAG, "Setting brightess dim " + brightness + ": " + dimMask);
setLightBrightness(dimMask, brightness);
@@ -2115,8 +2142,8 @@ public class PowerManagerService extends IPowerManager.Stub
if (onMask != 0) {
int brightness = getPreferredBrightness();
if ((newState & BATTERY_LOW_BIT) != 0 &&
- brightness > Power.BRIGHTNESS_LOW_BATTERY) {
- brightness = Power.BRIGHTNESS_LOW_BATTERY;
+ brightness > PowerManager.BRIGHTNESS_LOW_BATTERY) {
+ brightness = PowerManager.BRIGHTNESS_LOW_BATTERY;
}
if (mSpew) Slog.i(TAG, "Setting brightess on " + brightness + ": " + onMask);
setLightBrightness(onMask, brightness);
@@ -2198,8 +2225,8 @@ public class PowerManagerService extends IPowerManager.Stub
if (elapsed < duration) {
int delta = endValue - startValue;
newValue = startValue + delta * elapsed / duration;
- newValue = Math.max(Power.BRIGHTNESS_OFF, newValue);
- newValue = Math.min(Power.BRIGHTNESS_ON, newValue);
+ newValue = Math.max(PowerManager.BRIGHTNESS_OFF, newValue);
+ newValue = Math.min(PowerManager.BRIGHTNESS_ON, newValue);
} else {
newValue = endValue;
mInitialAnimation = false;
@@ -2249,7 +2276,7 @@ public class PowerManagerService extends IPowerManager.Stub
if (target != currentValue) {
final boolean doScreenAnim = (mask & (SCREEN_BRIGHT_BIT | SCREEN_ON_BIT)) != 0;
- final boolean turningOff = endValue == Power.BRIGHTNESS_OFF;
+ final boolean turningOff = endValue == PowerManager.BRIGHTNESS_OFF;
if (turningOff && doScreenAnim) {
// Cancel all pending animations since we're turning off
mScreenBrightnessHandler.removeCallbacksAndMessages(null);
@@ -2353,7 +2380,7 @@ public class PowerManagerService extends IPowerManager.Stub
private boolean isScreenTurningOffLocked() {
return (mScreenBrightnessAnimator.isAnimating()
- && mScreenBrightnessAnimator.endValue == Power.BRIGHTNESS_OFF);
+ && mScreenBrightnessAnimator.endValue == PowerManager.BRIGHTNESS_OFF);
}
private boolean shouldLog(long time) {
diff --git a/services/java/com/android/server/ShutdownActivity.java b/services/java/com/android/server/ShutdownActivity.java
index c9d4d01..d85abe6 100644
--- a/services/java/com/android/server/ShutdownActivity.java
+++ b/services/java/com/android/server/ShutdownActivity.java
@@ -22,7 +22,8 @@ import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Slog;
-import com.android.internal.app.ShutdownThread;
+
+import com.android.server.pm.ShutdownThread;
public class ShutdownActivity extends Activity {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 849281d..d9833ab 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -46,7 +46,6 @@ import android.util.Log;
import android.util.Slog;
import android.view.WindowManager;
-import com.android.internal.app.ShutdownThread;
import com.android.internal.os.BinderInternal;
import com.android.internal.os.SamplingProfilerIntegration;
import com.android.internal.widget.LockSettingsService;
@@ -56,6 +55,7 @@ import com.android.server.input.InputManagerService;
import com.android.server.net.NetworkPolicyManagerService;
import com.android.server.net.NetworkStatsService;
import com.android.server.pm.PackageManagerService;
+import com.android.server.pm.ShutdownThread;
import com.android.server.usb.UsbService;
import com.android.server.wm.WindowManagerService;
diff --git a/services/java/com/android/server/pm/ShutdownThread.java b/services/java/com/android/server/pm/ShutdownThread.java
new file mode 100644
index 0000000..1d6e068
--- /dev/null
+++ b/services/java/com/android/server/pm/ShutdownThread.java
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.server.pm;
+
+import android.app.ActivityManagerNative;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.IActivityManager;
+import android.app.ProgressDialog;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.IBluetooth;
+import android.nfc.NfcAdapter;
+import android.nfc.INfcAdapter;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.os.Vibrator;
+import android.os.SystemVibrator;
+import android.os.storage.IMountService;
+import android.os.storage.IMountShutdownObserver;
+
+import com.android.internal.telephony.ITelephony;
+import com.android.server.PowerManagerService;
+
+import android.util.Log;
+import android.view.WindowManager;
+
+public final class ShutdownThread extends Thread {
+ // constants
+ private static final String TAG = "ShutdownThread";
+ private static final int MAX_NUM_PHONE_STATE_READS = 24;
+ private static final int PHONE_STATE_POLL_SLEEP_MSEC = 500;
+ // maximum time we wait for the shutdown broadcast before going on.
+ private static final int MAX_BROADCAST_TIME = 10*1000;
+ private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000;
+
+ // length of vibration before shutting down
+ private static final int SHUTDOWN_VIBRATE_MS = 500;
+
+ // state tracking
+ private static Object sIsStartedGuard = new Object();
+ private static boolean sIsStarted = false;
+
+ private static boolean mReboot;
+ private static boolean mRebootSafeMode;
+ private static String mRebootReason;
+
+ // Provides shutdown assurance in case the system_server is killed
+ public static final String SHUTDOWN_ACTION_PROPERTY = "sys.shutdown.requested";
+
+ // Indicates whether we are rebooting into safe mode
+ public static final String REBOOT_SAFEMODE_PROPERTY = "persist.sys.safemode";
+
+ // static instance of this thread
+ private static final ShutdownThread sInstance = new ShutdownThread();
+
+ private final Object mActionDoneSync = new Object();
+ private boolean mActionDone;
+ private Context mContext;
+ private PowerManager mPowerManager;
+ private PowerManager.WakeLock mCpuWakeLock;
+ private PowerManager.WakeLock mScreenWakeLock;
+ private Handler mHandler;
+
+ private ShutdownThread() {
+ }
+
+ /**
+ * Request a clean shutdown, waiting for subsystems to clean up their
+ * state etc. Must be called from a Looper thread in which its UI
+ * is shown.
+ *
+ * @param context Context used to display the shutdown progress dialog.
+ * @param confirm true if user confirmation is needed before shutting down.
+ */
+ public static void shutdown(final Context context, boolean confirm) {
+ mReboot = false;
+ mRebootSafeMode = false;
+ shutdownInner(context, confirm);
+ }
+
+ static void shutdownInner(final Context context, boolean confirm) {
+ // ensure that only one thread is trying to power down.
+ // any additional calls are just returned
+ synchronized (sIsStartedGuard) {
+ if (sIsStarted) {
+ Log.d(TAG, "Request to shutdown already running, returning.");
+ return;
+ }
+ }
+
+ final int longPressBehavior = context.getResources().getInteger(
+ com.android.internal.R.integer.config_longPressOnPowerBehavior);
+ final int resourceId = mRebootSafeMode
+ ? com.android.internal.R.string.reboot_safemode_confirm
+ : (longPressBehavior == 2
+ ? com.android.internal.R.string.shutdown_confirm_question
+ : com.android.internal.R.string.shutdown_confirm);
+
+ Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior);
+
+ if (confirm) {
+ final CloseDialogReceiver closer = new CloseDialogReceiver(context);
+ final AlertDialog dialog = new AlertDialog.Builder(context)
+ .setTitle(mRebootSafeMode
+ ? com.android.internal.R.string.reboot_safemode_title
+ : com.android.internal.R.string.power_off)
+ .setMessage(resourceId)
+ .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ beginShutdownSequence(context);
+ }
+ })
+ .setNegativeButton(com.android.internal.R.string.no, null)
+ .create();
+ closer.dialog = dialog;
+ dialog.setOnDismissListener(closer);
+ dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+ dialog.show();
+ } else {
+ beginShutdownSequence(context);
+ }
+ }
+
+ private static class CloseDialogReceiver extends BroadcastReceiver
+ implements DialogInterface.OnDismissListener {
+ private Context mContext;
+ public Dialog dialog;
+
+ CloseDialogReceiver(Context context) {
+ mContext = context;
+ IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ context.registerReceiver(this, filter);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ dialog.cancel();
+ }
+
+ public void onDismiss(DialogInterface unused) {
+ mContext.unregisterReceiver(this);
+ }
+ }
+
+ /**
+ * Request a clean shutdown, waiting for subsystems to clean up their
+ * state etc. Must be called from a Looper thread in which its UI
+ * is shown.
+ *
+ * @param context Context used to display the shutdown progress dialog.
+ * @param reason code to pass to the kernel (e.g. "recovery"), or null.
+ * @param confirm true if user confirmation is needed before shutting down.
+ */
+ public static void reboot(final Context context, String reason, boolean confirm) {
+ mReboot = true;
+ mRebootSafeMode = false;
+ mRebootReason = reason;
+ shutdownInner(context, confirm);
+ }
+
+ /**
+ * Request a reboot into safe mode. Must be called from a Looper thread in which its UI
+ * is shown.
+ *
+ * @param context Context used to display the shutdown progress dialog.
+ * @param confirm true if user confirmation is needed before shutting down.
+ */
+ public static void rebootSafeMode(final Context context, boolean confirm) {
+ mReboot = true;
+ mRebootSafeMode = true;
+ mRebootReason = null;
+ shutdownInner(context, confirm);
+ }
+
+ private static void beginShutdownSequence(Context context) {
+ synchronized (sIsStartedGuard) {
+ if (sIsStarted) {
+ Log.d(TAG, "Shutdown sequence already running, returning.");
+ return;
+ }
+ sIsStarted = true;
+ }
+
+ // throw up an indeterminate system dialog to indicate radio is
+ // shutting down.
+ ProgressDialog pd = new ProgressDialog(context);
+ pd.setTitle(context.getText(com.android.internal.R.string.power_off));
+ pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
+ pd.setIndeterminate(true);
+ pd.setCancelable(false);
+ pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+
+ pd.show();
+
+ sInstance.mContext = context;
+ sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+
+ // make sure we never fall asleep again
+ sInstance.mCpuWakeLock = null;
+ try {
+ sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu");
+ sInstance.mCpuWakeLock.setReferenceCounted(false);
+ sInstance.mCpuWakeLock.acquire();
+ } catch (SecurityException e) {
+ Log.w(TAG, "No permission to acquire wake lock", e);
+ sInstance.mCpuWakeLock = null;
+ }
+
+ // also make sure the screen stays on for better user experience
+ sInstance.mScreenWakeLock = null;
+ if (sInstance.mPowerManager.isScreenOn()) {
+ try {
+ sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock(
+ PowerManager.FULL_WAKE_LOCK, TAG + "-screen");
+ sInstance.mScreenWakeLock.setReferenceCounted(false);
+ sInstance.mScreenWakeLock.acquire();
+ } catch (SecurityException e) {
+ Log.w(TAG, "No permission to acquire wake lock", e);
+ sInstance.mScreenWakeLock = null;
+ }
+ }
+
+ // start the thread that initiates shutdown
+ sInstance.mHandler = new Handler() {
+ };
+ sInstance.start();
+ }
+
+ void actionDone() {
+ synchronized (mActionDoneSync) {
+ mActionDone = true;
+ mActionDoneSync.notifyAll();
+ }
+ }
+
+ /**
+ * Makes sure we handle the shutdown gracefully.
+ * Shuts off power regardless of radio and bluetooth state if the alloted time has passed.
+ */
+ public void run() {
+ boolean nfcOff;
+ boolean bluetoothOff;
+ boolean radioOff;
+
+ BroadcastReceiver br = new BroadcastReceiver() {
+ @Override public void onReceive(Context context, Intent intent) {
+ // We don't allow apps to cancel this, so ignore the result.
+ actionDone();
+ }
+ };
+
+ /*
+ * Write a system property in case the system_server reboots before we
+ * get to the actual hardware restart. If that happens, we'll retry at
+ * the beginning of the SystemServer startup.
+ */
+ {
+ String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : "");
+ SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);
+ }
+
+ /*
+ * If we are rebooting into safe mode, write a system property
+ * indicating so.
+ */
+ if (mRebootSafeMode) {
+ SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1");
+ }
+
+ Log.i(TAG, "Sending shutdown broadcast...");
+
+ // First send the high-level shut down broadcast.
+ mActionDone = false;
+ mContext.sendOrderedBroadcast(new Intent(Intent.ACTION_SHUTDOWN), null,
+ br, mHandler, 0, null, null);
+
+ final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
+ synchronized (mActionDoneSync) {
+ while (!mActionDone) {
+ long delay = endTime - SystemClock.elapsedRealtime();
+ if (delay <= 0) {
+ Log.w(TAG, "Shutdown broadcast timed out");
+ break;
+ }
+ try {
+ mActionDoneSync.wait(delay);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ Log.i(TAG, "Shutting down activity manager...");
+
+ final IActivityManager am =
+ ActivityManagerNative.asInterface(ServiceManager.checkService("activity"));
+ if (am != null) {
+ try {
+ am.shutdown(MAX_BROADCAST_TIME);
+ } catch (RemoteException e) {
+ }
+ }
+
+ final INfcAdapter nfc =
+ INfcAdapter.Stub.asInterface(ServiceManager.checkService("nfc"));
+ final ITelephony phone =
+ ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
+ final IBluetooth bluetooth =
+ IBluetooth.Stub.asInterface(ServiceManager.checkService(
+ BluetoothAdapter.BLUETOOTH_SERVICE));
+ final IMountService mount =
+ IMountService.Stub.asInterface(
+ ServiceManager.checkService("mount"));
+
+ try {
+ nfcOff = nfc == null ||
+ nfc.getState() == NfcAdapter.STATE_OFF;
+ if (!nfcOff) {
+ Log.w(TAG, "Turning off NFC...");
+ nfc.disable(false); // Don't persist new state
+ }
+ } catch (RemoteException ex) {
+ Log.e(TAG, "RemoteException during NFC shutdown", ex);
+ nfcOff = true;
+ }
+
+ try {
+ bluetoothOff = bluetooth == null ||
+ bluetooth.getBluetoothState() == BluetoothAdapter.STATE_OFF;
+ if (!bluetoothOff) {
+ Log.w(TAG, "Disabling Bluetooth...");
+ bluetooth.disable(false); // disable but don't persist new state
+ }
+ } catch (RemoteException ex) {
+ Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
+ bluetoothOff = true;
+ }
+
+ try {
+ radioOff = phone == null || !phone.isRadioOn();
+ if (!radioOff) {
+ Log.w(TAG, "Turning off radio...");
+ phone.setRadio(false);
+ }
+ } catch (RemoteException ex) {
+ Log.e(TAG, "RemoteException during radio shutdown", ex);
+ radioOff = true;
+ }
+
+ Log.i(TAG, "Waiting for NFC, Bluetooth and Radio...");
+
+ // Wait a max of 32 seconds for clean shutdown
+ for (int i = 0; i < MAX_NUM_PHONE_STATE_READS; i++) {
+ if (!bluetoothOff) {
+ try {
+ bluetoothOff =
+ bluetooth.getBluetoothState() == BluetoothAdapter.STATE_OFF;
+ } catch (RemoteException ex) {
+ Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
+ bluetoothOff = true;
+ }
+ }
+ if (!radioOff) {
+ try {
+ radioOff = !phone.isRadioOn();
+ } catch (RemoteException ex) {
+ Log.e(TAG, "RemoteException during radio shutdown", ex);
+ radioOff = true;
+ }
+ }
+ if (!nfcOff) {
+ try {
+ nfcOff = nfc.getState() == NfcAdapter.STATE_OFF;
+ } catch (RemoteException ex) {
+ Log.e(TAG, "RemoteException during NFC shutdown", ex);
+ nfcOff = true;
+ }
+ }
+
+ if (radioOff && bluetoothOff && nfcOff) {
+ Log.i(TAG, "NFC, Radio and Bluetooth shutdown complete.");
+ break;
+ }
+ SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC);
+ }
+
+ // Shutdown MountService to ensure media is in a safe state
+ IMountShutdownObserver observer = new IMountShutdownObserver.Stub() {
+ public void onShutDownComplete(int statusCode) throws RemoteException {
+ Log.w(TAG, "Result code " + statusCode + " from MountService.shutdown");
+ actionDone();
+ }
+ };
+
+ Log.i(TAG, "Shutting down MountService");
+ // Set initial variables and time out time.
+ mActionDone = false;
+ final long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME;
+ synchronized (mActionDoneSync) {
+ try {
+ if (mount != null) {
+ mount.shutdown(observer);
+ } else {
+ Log.w(TAG, "MountService unavailable for shutdown");
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Exception during MountService shutdown", e);
+ }
+ while (!mActionDone) {
+ long delay = endShutTime - SystemClock.elapsedRealtime();
+ if (delay <= 0) {
+ Log.w(TAG, "Shutdown wait timed out");
+ break;
+ }
+ try {
+ mActionDoneSync.wait(delay);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ rebootOrShutdown(mReboot, mRebootReason);
+ }
+
+ /**
+ * Do not call this directly. Use {@link #reboot(Context, String, boolean)}
+ * or {@link #shutdown(Context, boolean)} instead.
+ *
+ * @param reboot true to reboot or false to shutdown
+ * @param reason reason for reboot
+ */
+ public static void rebootOrShutdown(boolean reboot, String reason) {
+ if (reboot) {
+ Log.i(TAG, "Rebooting, reason: " + reason);
+ try {
+ PowerManagerService.lowLevelReboot(reason);
+ } catch (Exception e) {
+ Log.e(TAG, "Reboot failed, will attempt shutdown instead", e);
+ }
+ } else if (SHUTDOWN_VIBRATE_MS > 0) {
+ // vibrate before shutting down
+ Vibrator vibrator = new SystemVibrator();
+ try {
+ vibrator.vibrate(SHUTDOWN_VIBRATE_MS);
+ } catch (Exception e) {
+ // Failure to vibrate shouldn't interrupt shutdown. Just log it.
+ Log.w(TAG, "Failed to vibrate during shutdown.", e);
+ }
+
+ // vibrator is asynchronous so we need to wait to avoid shutting down too soon.
+ try {
+ Thread.sleep(SHUTDOWN_VIBRATE_MS);
+ } catch (InterruptedException unused) {
+ }
+ }
+
+ // Shutdown power
+ Log.i(TAG, "Performing low-level shutdown...");
+ PowerManagerService.lowLevelShutdown();
+ }
+}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 2efcb8e..c90c0c7 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -34,7 +34,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import com.android.internal.app.IBatteryStats;
-import com.android.internal.app.ShutdownThread;
import com.android.internal.policy.PolicyManager;
import com.android.internal.policy.impl.PhoneWindowManager;
import com.android.internal.view.IInputContext;
@@ -48,6 +47,7 @@ import com.android.server.Watchdog;
import com.android.server.am.BatteryStatsService;
import com.android.server.input.InputFilter;
import com.android.server.input.InputManagerService;
+import com.android.server.pm.ShutdownThread;
import android.Manifest;
import android.app.ActivityManagerNative;
@@ -82,7 +82,6 @@ import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
-import android.os.Power;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
@@ -5025,6 +5024,18 @@ public class WindowManagerService extends IWindowManager.Stub
return mInputManager.monitorInput(inputChannelName);
}
+ // Called by window manager policy. Not exposed externally.
+ @Override
+ public void shutdown() {
+ ShutdownThread.shutdown(mContext, true);
+ }
+
+ // Called by window manager policy. Not exposed externally.
+ @Override
+ public void rebootSafeMode() {
+ ShutdownThread.rebootSafeMode(mContext, true);
+ }
+
public void setInputFilter(InputFilter filter) {
mInputManager.setInputFilter(filter);
}
@@ -8700,13 +8711,13 @@ public class WindowManagerService extends IWindowManager.Stub
mPowerManager.setScreenBrightnessOverride(-1);
} else {
mPowerManager.setScreenBrightnessOverride((int)
- (mInnerFields.mScreenBrightness * Power.BRIGHTNESS_ON));
+ (mInnerFields.mScreenBrightness * PowerManager.BRIGHTNESS_ON));
}
if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
mPowerManager.setButtonBrightnessOverride(-1);
} else {
mPowerManager.setButtonBrightnessOverride((int)
- (mInnerFields.mButtonBrightness * Power.BRIGHTNESS_ON));
+ (mInnerFields.mButtonBrightness * PowerManager.BRIGHTNESS_ON));
}
}
if (mInnerFields.mHoldScreen != mHoldingScreenOn) {