Merge "Move power HAL interactions to PowerManagerService." into jb-dev
This commit is contained in:
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 android.os;
|
||||
|
||||
import java.io.IOException;
|
||||
import android.os.ServiceManager;
|
||||
|
||||
/**
|
||||
* Class that provides access to some of the power management functions.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public class Power
|
||||
{
|
||||
// can't instantiate this class
|
||||
private Power()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Wake lock that ensures that the CPU is running. The screen might
|
||||
* not be on.
|
||||
*/
|
||||
public static final int PARTIAL_WAKE_LOCK = 1;
|
||||
|
||||
/**
|
||||
* Wake lock that ensures that the screen is on.
|
||||
*/
|
||||
public static final int FULL_WAKE_LOCK = 2;
|
||||
|
||||
public static native void acquireWakeLock(int lock, String id);
|
||||
public static native void releaseWakeLock(String id);
|
||||
|
||||
/**
|
||||
* Brightness value for fully off
|
||||
*/
|
||||
public static final int BRIGHTNESS_OFF = 0;
|
||||
|
||||
/**
|
||||
* Brightness value for dim backlight
|
||||
*/
|
||||
public static final int BRIGHTNESS_DIM = 20;
|
||||
|
||||
/**
|
||||
* Brightness value for fully on
|
||||
*/
|
||||
public static final int BRIGHTNESS_ON = 255;
|
||||
|
||||
/**
|
||||
* Brightness value to use when battery is low
|
||||
*/
|
||||
public static final int BRIGHTNESS_LOW_BATTERY = 10;
|
||||
|
||||
/**
|
||||
* Threshold for BRIGHTNESS_LOW_BATTERY (percentage)
|
||||
* Screen will stay dim if battery level is <= LOW_BATTERY_THRESHOLD
|
||||
*/
|
||||
public static final int LOW_BATTERY_THRESHOLD = 10;
|
||||
|
||||
/**
|
||||
* Turn the screen on or off
|
||||
*
|
||||
* @param on Whether you want the screen on or off
|
||||
*/
|
||||
public static native int setScreenState(boolean on);
|
||||
|
||||
public static native int setLastUserActivityTimeout(long ms);
|
||||
|
||||
/**
|
||||
* Low-level function turn the device off immediately, without trying
|
||||
* to be clean. Most people should use
|
||||
* {@link android.internal.app.ShutdownThread} for a clean shutdown.
|
||||
*
|
||||
* @deprecated
|
||||
* @hide
|
||||
*/
|
||||
@Deprecated
|
||||
public static native void shutdown();
|
||||
|
||||
/**
|
||||
* 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 reboot(String reason) throws IOException
|
||||
{
|
||||
rebootNative(reason);
|
||||
}
|
||||
|
||||
private static native void rebootNative(String reason) throws IOException ;
|
||||
|
||||
public static native int powerInitNative();
|
||||
}
|
||||
@@ -197,7 +197,31 @@ public class PowerManager
|
||||
* Does not work with PARTIAL_WAKE_LOCKs.
|
||||
*/
|
||||
public static final int ON_AFTER_RELEASE = 0x20000000;
|
||||
|
||||
|
||||
/**
|
||||
* Brightness value to use when battery is low.
|
||||
* @hide
|
||||
*/
|
||||
public static final int BRIGHTNESS_LOW_BATTERY = 10;
|
||||
|
||||
/**
|
||||
* Brightness value for fully on.
|
||||
* @hide
|
||||
*/
|
||||
public static final int BRIGHTNESS_ON = 255;
|
||||
|
||||
/**
|
||||
* Brightness value for dim backlight.
|
||||
* @hide
|
||||
*/
|
||||
public static final int BRIGHTNESS_DIM = 20;
|
||||
|
||||
/**
|
||||
* Brightness value for fully off.
|
||||
* @hide
|
||||
*/
|
||||
public static final int BRIGHTNESS_OFF = 0;
|
||||
|
||||
/**
|
||||
* Class lets you say that you need to have the device on.
|
||||
* <p>
|
||||
|
||||
@@ -397,6 +397,9 @@ public interface WindowManagerPolicy {
|
||||
* Creates an input channel that will receive all input from the input dispatcher.
|
||||
*/
|
||||
public InputChannel monitorInput(String name);
|
||||
|
||||
public void shutdown();
|
||||
public void rebootSafeMode();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,484 +0,0 @@
|
||||
/*
|
||||
* 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.internal.app;
|
||||
|
||||
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.Power;
|
||||
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 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 {
|
||||
Power.reboot(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...");
|
||||
Power.shutdown();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user