ShutdownThread.java revision 3bba8d0457408421a6468f03bbb36e9ff32b81cf
155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn/* 255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * Copyright (C) 2008 The Android Open Source Project 355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * 455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); 555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * you may not use this file except in compliance with the License. 655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * You may obtain a copy of the License at 755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * 855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * 1055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * Unless required by applicable law or agreed to in writing, software 1155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, 1255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * See the License for the specific language governing permissions and 1455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * limitations under the License. 1555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn */ 1655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 1755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 1855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornpackage com.android.internal.app; 1955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 2055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.app.ActivityManagerNative; 21d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onoratoimport android.app.AlertDialog; 22d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onoratoimport android.app.Dialog; 2355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.app.IActivityManager; 2455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.app.ProgressDialog; 25bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.BluetoothAdapter; 26bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.bluetooth.IBluetooth; 273bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogiimport android.nfc.NfcAdapter; 283bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogiimport android.nfc.INfcAdapter; 2955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.content.BroadcastReceiver; 3055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.content.Context; 3155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.content.DialogInterface; 3255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.content.Intent; 33d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onoratoimport android.content.IntentFilter; 3455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.os.Handler; 356ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapuimport android.os.Power; 36f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackbornimport android.os.PowerManager; 3755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.os.RemoteException; 3855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.os.ServiceManager; 3955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.os.SystemClock; 40f547d679c058ed00de78a32146d04b75254df7ecKenny Rootimport android.os.SystemProperties; 41a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwoodimport android.os.Vibrator; 42b104340496e3a531e26c8f428c808eca0e039f50San Mehatimport android.os.storage.IMountService; 436ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapuimport android.os.storage.IMountShutdownObserver; 44568cae571a3d74d1992176a21722e07b44e9a3c4Dianne Hackborn 4555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport com.android.internal.telephony.ITelephony; 4655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.util.Log; 4755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.view.WindowManager; 4855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 4955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornpublic final class ShutdownThread extends Thread { 5055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // constants 5155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private static final String TAG = "ShutdownThread"; 523bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi private static final int MAX_NUM_PHONE_STATE_READS = 24; 5355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private static final int PHONE_STATE_POLL_SLEEP_MSEC = 500; 5455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // maximum time we wait for the shutdown broadcast before going on. 5555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private static final int MAX_BROADCAST_TIME = 10*1000; 566ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000; 57a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood 58a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood // length of vibration before shutting down 59a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood private static final int SHUTDOWN_VIBRATE_MS = 500; 6055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 6155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // state tracking 6255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private static Object sIsStartedGuard = new Object(); 6355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private static boolean sIsStarted = false; 6455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 656ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu private static boolean mReboot; 666ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu private static String mRebootReason; 676ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu 68f547d679c058ed00de78a32146d04b75254df7ecKenny Root // Provides shutdown assurance in case the system_server is killed 69f547d679c058ed00de78a32146d04b75254df7ecKenny Root public static final String SHUTDOWN_ACTION_PROPERTY = "sys.shutdown.requested"; 70f547d679c058ed00de78a32146d04b75254df7ecKenny Root 7155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // static instance of this thread 7255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private static final ShutdownThread sInstance = new ShutdownThread(); 7355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 746ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu private final Object mActionDoneSync = new Object(); 756ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu private boolean mActionDone; 7655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private Context mContext; 77f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn private PowerManager mPowerManager; 78cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson private PowerManager.WakeLock mCpuWakeLock; 79cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson private PowerManager.WakeLock mScreenWakeLock; 8055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private Handler mHandler; 8155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 8255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private ShutdownThread() { 8355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 8455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 856ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu /** 8655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * Request a clean shutdown, waiting for subsystems to clean up their 8755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * state etc. Must be called from a Looper thread in which its UI 8855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * is shown. 896ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * 9055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * @param context Context used to display the shutdown progress dialog. 916ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * @param confirm true if user confirmation is needed before shutting down. 9255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn */ 9355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn public static void shutdown(final Context context, boolean confirm) { 9455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // ensure that only one thread is trying to power down. 9555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // any additional calls are just returned 96d67b236497d87223e8373d96c274c97cfbcab0cbMike Lockwood synchronized (sIsStartedGuard) { 9755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn if (sIsStarted) { 9855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.d(TAG, "Request to shutdown already running, returning."); 9955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn return; 10055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 10155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 10255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 103d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato final int longPressBehavior = context.getResources().getInteger( 104d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato com.android.internal.R.integer.config_longPressOnPowerBehavior); 105d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato final int resourceId = longPressBehavior == 2 106d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato ? com.android.internal.R.string.shutdown_confirm_question 107d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato : com.android.internal.R.string.shutdown_confirm; 108d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato 109d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior); 11055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 11155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn if (confirm) { 112d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato final CloseDialogReceiver closer = new CloseDialogReceiver(context); 11355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn final AlertDialog dialog = new AlertDialog.Builder(context) 11455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn .setTitle(com.android.internal.R.string.power_off) 115d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato .setMessage(resourceId) 11655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() { 11755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn public void onClick(DialogInterface dialog, int which) { 11855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn beginShutdownSequence(context); 11955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 12055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn }) 12155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn .setNegativeButton(com.android.internal.R.string.no, null) 12255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn .create(); 123d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato closer.dialog = dialog; 124d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato dialog.setOnDismissListener(closer); 12555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); 12655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn dialog.show(); 12755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } else { 12855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn beginShutdownSequence(context); 12955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 13055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 13155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 132d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato private static class CloseDialogReceiver extends BroadcastReceiver 133d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato implements DialogInterface.OnDismissListener { 134d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato private Context mContext; 135d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato public Dialog dialog; 136d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato 137d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato CloseDialogReceiver(Context context) { 138d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato mContext = context; 139d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); 140d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato context.registerReceiver(this, filter); 141d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato } 142d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato 143d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato @Override 144d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato public void onReceive(Context context, Intent intent) { 145d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato dialog.cancel(); 146d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato } 147d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato 148d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato public void onDismiss(DialogInterface unused) { 149d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato mContext.unregisterReceiver(this); 150d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato } 151d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato } 152d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato 1536ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu /** 1546ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * Request a clean shutdown, waiting for subsystems to clean up their 1556ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * state etc. Must be called from a Looper thread in which its UI 1566ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * is shown. 1576ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * 1586ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * @param context Context used to display the shutdown progress dialog. 1596ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * @param reason code to pass to the kernel (e.g. "recovery"), or null. 1606ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * @param confirm true if user confirmation is needed before shutting down. 1616ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu */ 1626ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu public static void reboot(final Context context, String reason, boolean confirm) { 1636ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu mReboot = true; 1646ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu mRebootReason = reason; 1656ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu shutdown(context, confirm); 1666ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } 1676ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu 16855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private static void beginShutdownSequence(Context context) { 16955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn synchronized (sIsStartedGuard) { 170d67b236497d87223e8373d96c274c97cfbcab0cbMike Lockwood if (sIsStarted) { 1718534a8e438ff35511051cf74f8f73d52c8b3b1f4Mathias Jeppsson Log.d(TAG, "Shutdown sequence already running, returning."); 172d67b236497d87223e8373d96c274c97cfbcab0cbMike Lockwood return; 173d67b236497d87223e8373d96c274c97cfbcab0cbMike Lockwood } 17455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn sIsStarted = true; 17555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 17655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 17755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // throw up an indeterminate system dialog to indicate radio is 17855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // shutting down. 17955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn ProgressDialog pd = new ProgressDialog(context); 18055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn pd.setTitle(context.getText(com.android.internal.R.string.power_off)); 18155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress)); 18255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn pd.setIndeterminate(true); 18355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn pd.setCancelable(false); 18455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); 18555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 18655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn pd.show(); 18755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 18855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn sInstance.mContext = context; 189f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 190cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson 191cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson // make sure we never fall asleep again 192cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mCpuWakeLock = null; 193cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson try { 194cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock( 195cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu"); 196cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mCpuWakeLock.setReferenceCounted(false); 197cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mCpuWakeLock.acquire(); 198cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson } catch (SecurityException e) { 199cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson Log.w(TAG, "No permission to acquire wake lock", e); 200cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mCpuWakeLock = null; 201cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson } 202cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson 203cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson // also make sure the screen stays on for better user experience 204cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mScreenWakeLock = null; 205f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn if (sInstance.mPowerManager.isScreenOn()) { 206f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn try { 207cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock( 208cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson PowerManager.FULL_WAKE_LOCK, TAG + "-screen"); 209cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mScreenWakeLock.setReferenceCounted(false); 210cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mScreenWakeLock.acquire(); 211f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn } catch (SecurityException e) { 212f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn Log.w(TAG, "No permission to acquire wake lock", e); 213cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mScreenWakeLock = null; 214f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn } 215f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn } 216cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson 217cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson // start the thread that initiates shutdown 21855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn sInstance.mHandler = new Handler() { 21955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn }; 22055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn sInstance.start(); 22155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 22255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 2236ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu void actionDone() { 2246ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu synchronized (mActionDoneSync) { 2256ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu mActionDone = true; 2266ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu mActionDoneSync.notifyAll(); 22755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 22855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 2296ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu 23055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn /** 23155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * Makes sure we handle the shutdown gracefully. 23255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * Shuts off power regardless of radio and bluetooth state if the alloted time has passed. 23355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn */ 23455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn public void run() { 2353bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi boolean nfcOff; 23655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn boolean bluetoothOff; 23755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn boolean radioOff; 23855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 23955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn BroadcastReceiver br = new BroadcastReceiver() { 24055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn @Override public void onReceive(Context context, Intent intent) { 24155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // We don't allow apps to cancel this, so ignore the result. 2426ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu actionDone(); 24355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 24455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn }; 245f547d679c058ed00de78a32146d04b75254df7ecKenny Root 246f547d679c058ed00de78a32146d04b75254df7ecKenny Root /* 247f547d679c058ed00de78a32146d04b75254df7ecKenny Root * Write a system property in case the system_server reboots before we 248f547d679c058ed00de78a32146d04b75254df7ecKenny Root * get to the actual hardware restart. If that happens, we'll retry at 249f547d679c058ed00de78a32146d04b75254df7ecKenny Root * the beginning of the SystemServer startup. 250f547d679c058ed00de78a32146d04b75254df7ecKenny Root */ 251f547d679c058ed00de78a32146d04b75254df7ecKenny Root { 252f547d679c058ed00de78a32146d04b75254df7ecKenny Root String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : ""); 253f547d679c058ed00de78a32146d04b75254df7ecKenny Root SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason); 254f547d679c058ed00de78a32146d04b75254df7ecKenny Root } 255f547d679c058ed00de78a32146d04b75254df7ecKenny Root 25655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.i(TAG, "Sending shutdown broadcast..."); 25755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 25855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // First send the high-level shut down broadcast. 2596ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu mActionDone = false; 26055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn mContext.sendOrderedBroadcast(new Intent(Intent.ACTION_SHUTDOWN), null, 26155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn br, mHandler, 0, null, null); 26255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 263098e58da93f304d7d7791f193c6237870b94989dMike Lockwood final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME; 2646ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu synchronized (mActionDoneSync) { 2656ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu while (!mActionDone) { 266098e58da93f304d7d7791f193c6237870b94989dMike Lockwood long delay = endTime - SystemClock.elapsedRealtime(); 26755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn if (delay <= 0) { 26855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.w(TAG, "Shutdown broadcast timed out"); 26955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn break; 27055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 27155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn try { 2726ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu mActionDoneSync.wait(delay); 27355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } catch (InterruptedException e) { 27455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 27555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 27655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 27755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 27855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.i(TAG, "Shutting down activity manager..."); 27955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 28055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn final IActivityManager am = 28155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn ActivityManagerNative.asInterface(ServiceManager.checkService("activity")); 28255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn if (am != null) { 28355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn try { 28455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn am.shutdown(MAX_BROADCAST_TIME); 28555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } catch (RemoteException e) { 28655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 28755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 28855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 2893bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi final INfcAdapter nfc = 2903bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi INfcAdapter.Stub.asInterface(ServiceManager.checkService("nfc")); 29155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn final ITelephony phone = 29255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); 293bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly final IBluetooth bluetooth = 294bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pelly IBluetooth.Stub.asInterface(ServiceManager.checkService( 295f242b7b931898856bcbcb7ec36cacf43098ba544Nick Pelly BluetoothAdapter.BLUETOOTH_SERVICE)); 2969f7f7cad0b1fd7b096d65faf4b2352204403257eSan Mehat final IMountService mount = 2979f7f7cad0b1fd7b096d65faf4b2352204403257eSan Mehat IMountService.Stub.asInterface( 2989f7f7cad0b1fd7b096d65faf4b2352204403257eSan Mehat ServiceManager.checkService("mount")); 2993bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi 3003bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi try { 3013bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi nfcOff = nfc == null || 3023bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi nfc.getState() == NfcAdapter.STATE_OFF; 3033bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi if (!nfcOff) { 3043bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi Log.w(TAG, "Turning off NFC..."); 3053bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi nfc.disable(false); // Don't persist new state 3063bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi } 3073bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi } catch (RemoteException ex) { 3083bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi Log.e(TAG, "RemoteException during NFC shutdown", ex); 3093bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi nfcOff = true; 3103bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi } 3113bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi 31255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn try { 31355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn bluetoothOff = bluetooth == null || 314de893f550301a60274e87aa8168225e7a7a42184Nick Pelly bluetooth.getBluetoothState() == BluetoothAdapter.STATE_OFF; 31555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn if (!bluetoothOff) { 31655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.w(TAG, "Disabling Bluetooth..."); 31755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn bluetooth.disable(false); // disable but don't persist new state 31855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 31955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } catch (RemoteException ex) { 32055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.e(TAG, "RemoteException during bluetooth shutdown", ex); 32155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn bluetoothOff = true; 32255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 32355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 32455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn try { 32555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn radioOff = phone == null || !phone.isRadioOn(); 32655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn if (!radioOff) { 32755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.w(TAG, "Turning off radio..."); 32855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn phone.setRadio(false); 32955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 33055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } catch (RemoteException ex) { 33155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.e(TAG, "RemoteException during radio shutdown", ex); 33255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn radioOff = true; 33355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 33455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 3353bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi Log.i(TAG, "Waiting for NFC, Bluetooth and Radio..."); 33655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 33755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // Wait a max of 32 seconds for clean shutdown 33855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn for (int i = 0; i < MAX_NUM_PHONE_STATE_READS; i++) { 33955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn if (!bluetoothOff) { 34055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn try { 34155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn bluetoothOff = 342de893f550301a60274e87aa8168225e7a7a42184Nick Pelly bluetooth.getBluetoothState() == BluetoothAdapter.STATE_OFF; 34355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } catch (RemoteException ex) { 34455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.e(TAG, "RemoteException during bluetooth shutdown", ex); 34555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn bluetoothOff = true; 34655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 34755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 34855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn if (!radioOff) { 34955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn try { 35055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn radioOff = !phone.isRadioOn(); 35155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } catch (RemoteException ex) { 35255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.e(TAG, "RemoteException during radio shutdown", ex); 35355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn radioOff = true; 35455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 35555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 3563bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi if (!nfcOff) { 3573bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi try { 3583bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi nfcOff = nfc.getState() == NfcAdapter.STATE_OFF; 3593bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi } catch (RemoteException ex) { 3603bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi Log.e(TAG, "RemoteException during NFC shutdown", ex); 3613bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi nfcOff = true; 3623bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi } 3633bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi } 3643bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi 3653bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi if (radioOff && bluetoothOff && nfcOff) { 3663bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogi Log.i(TAG, "NFC, Radio and Bluetooth shutdown complete."); 36755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn break; 36855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 36955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC); 37055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 37155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 3729f7f7cad0b1fd7b096d65faf4b2352204403257eSan Mehat // Shutdown MountService to ensure media is in a safe state 3736ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu IMountShutdownObserver observer = new IMountShutdownObserver.Stub() { 3746ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu public void onShutDownComplete(int statusCode) throws RemoteException { 3756ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu Log.w(TAG, "Result code " + statusCode + " from MountService.shutdown"); 3766ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu actionDone(); 3776ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } 3786ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu }; 3796ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu 3806ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu Log.i(TAG, "Shutting down MountService"); 3816ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu // Set initial variables and time out time. 3826ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu mActionDone = false; 383098e58da93f304d7d7791f193c6237870b94989dMike Lockwood final long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME; 3846ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu synchronized (mActionDoneSync) { 3856ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu try { 3866ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu if (mount != null) { 3876ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu mount.shutdown(observer); 3886ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } else { 3896ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu Log.w(TAG, "MountService unavailable for shutdown"); 3906ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } 3916ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } catch (Exception e) { 3926ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu Log.e(TAG, "Exception during MountService shutdown", e); 3936ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } 3946ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu while (!mActionDone) { 395098e58da93f304d7d7791f193c6237870b94989dMike Lockwood long delay = endShutTime - SystemClock.elapsedRealtime(); 3966ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu if (delay <= 0) { 3976ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu Log.w(TAG, "Shutdown wait timed out"); 3986ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu break; 3996ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } 4006ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu try { 4016ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu mActionDoneSync.wait(delay); 4026ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } catch (InterruptedException e) { 4036ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } 4046ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } 4056ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } 4066ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu 407f547d679c058ed00de78a32146d04b75254df7ecKenny Root rebootOrShutdown(mReboot, mRebootReason); 408f547d679c058ed00de78a32146d04b75254df7ecKenny Root } 409f547d679c058ed00de78a32146d04b75254df7ecKenny Root 410f547d679c058ed00de78a32146d04b75254df7ecKenny Root /** 411f547d679c058ed00de78a32146d04b75254df7ecKenny Root * Do not call this directly. Use {@link #reboot(Context, String, boolean)} 412f547d679c058ed00de78a32146d04b75254df7ecKenny Root * or {@link #shutdown(Context, boolean)} instead. 413f547d679c058ed00de78a32146d04b75254df7ecKenny Root * 414f547d679c058ed00de78a32146d04b75254df7ecKenny Root * @param reboot true to reboot or false to shutdown 415f547d679c058ed00de78a32146d04b75254df7ecKenny Root * @param reason reason for reboot 416f547d679c058ed00de78a32146d04b75254df7ecKenny Root */ 417f547d679c058ed00de78a32146d04b75254df7ecKenny Root public static void rebootOrShutdown(boolean reboot, String reason) { 418f547d679c058ed00de78a32146d04b75254df7ecKenny Root if (reboot) { 419f547d679c058ed00de78a32146d04b75254df7ecKenny Root Log.i(TAG, "Rebooting, reason: " + reason); 4206ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu try { 421f547d679c058ed00de78a32146d04b75254df7ecKenny Root Power.reboot(reason); 4226ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } catch (Exception e) { 4236ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu Log.e(TAG, "Reboot failed, will attempt shutdown instead", e); 4249f7f7cad0b1fd7b096d65faf4b2352204403257eSan Mehat } 425a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood } else if (SHUTDOWN_VIBRATE_MS > 0) { 426a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood // vibrate before shutting down 427a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood Vibrator vibrator = new Vibrator(); 42826e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick try { 42926e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick vibrator.vibrate(SHUTDOWN_VIBRATE_MS); 43026e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick } catch (Exception e) { 43126e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick // Failure to vibrate shouldn't interrupt shutdown. Just log it. 43226e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick Log.w(TAG, "Failed to vibrate during shutdown.", e); 43326e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick } 43426e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick 435a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood // vibrator is asynchronous so we need to wait to avoid shutting down too soon. 436a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood try { 437a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood Thread.sleep(SHUTDOWN_VIBRATE_MS); 438e331644cb570e74a8739cb21ffcc5875663ffa58Brad Fitzpatrick } catch (InterruptedException unused) { 439a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood } 4409f7f7cad0b1fd7b096d65faf4b2352204403257eSan Mehat } 4419f7f7cad0b1fd7b096d65faf4b2352204403257eSan Mehat 4426ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu // Shutdown power 44355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.i(TAG, "Performing low-level shutdown..."); 44455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Power.shutdown(); 44555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 44655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn} 447