diff options
| author | Jeff Brown <jeffbrown@google.com> | 2012-05-11 19:32:56 -0700 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-05-11 19:32:56 -0700 |
| commit | 58770232216cd735afdfd3dd53151070e06de5ce (patch) | |
| tree | 502d189420768053f373e17e3bb634d0dfd33c8b /core/java/com | |
| parent | dca5fb9e7e193d6aed233e0650691675a56022a3 (diff) | |
| parent | 7304c343821309dd15f769b18f1de2fa43751573 (diff) | |
| download | frameworks_base-58770232216cd735afdfd3dd53151070e06de5ce.zip frameworks_base-58770232216cd735afdfd3dd53151070e06de5ce.tar.gz frameworks_base-58770232216cd735afdfd3dd53151070e06de5ce.tar.bz2 | |
Merge "Move power HAL interactions to PowerManagerService." into jb-dev
Diffstat (limited to 'core/java/com')
| -rw-r--r-- | core/java/com/android/internal/app/ShutdownThread.java | 484 |
1 files changed, 0 insertions, 484 deletions
diff --git a/core/java/com/android/internal/app/ShutdownThread.java b/core/java/com/android/internal/app/ShutdownThread.java deleted file mode 100644 index d867ff9..0000000 --- a/core/java/com/android/internal/app/ShutdownThread.java +++ /dev/null @@ -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(); - } -} |
