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 1790237f7beb55dae79cdcba5271f96be778573737Tao Bao 184f8ecd80296508a1dc69d3f3a23fd91e962c2784Jeff Brownpackage com.android.server.power; 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; 260f42037eb7b5118015c2caca635538324ccf0ccffredcimport android.bluetooth.IBluetoothManager; 277b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlockimport android.media.AudioAttributes; 283bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogiimport android.nfc.NfcAdapter; 293bba8d0457408421a6468f03bbb36e9ff32b81cfSunil Jogiimport android.nfc.INfcAdapter; 3055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.content.BroadcastReceiver; 3155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.content.Context; 3255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.content.DialogInterface; 3355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.content.Intent; 34d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onoratoimport android.content.IntentFilter; 3555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.os.Handler; 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; 415ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle; 42bff46bac807ae8a9ebdc22c449a8d4f78711b4d2Benjamin Franzimport android.os.UserManager; 43a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwoodimport android.os.Vibrator; 44c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brownimport android.os.SystemVibrator; 45b104340496e3a531e26c8f428c808eca0e039f50San Mehatimport android.os.storage.IMountService; 466ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapuimport android.os.storage.IMountShutdownObserver; 4790237f7beb55dae79cdcba5271f96be778573737Tao Baoimport android.system.ErrnoException; 4890237f7beb55dae79cdcba5271f96be778573737Tao Baoimport android.system.Os; 49568cae571a3d74d1992176a21722e07b44e9a3c4Dianne Hackborn 5055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport com.android.internal.telephony.ITelephony; 51ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstromimport com.android.server.pm.PackageManagerService; 527304c343821309dd15f769b18f1de2fa43751573Jeff Brown 5355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.util.Log; 5455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.view.WindowManager; 5555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 5690237f7beb55dae79cdcba5271f96be778573737Tao Baoimport java.io.BufferedReader; 5790237f7beb55dae79cdcba5271f96be778573737Tao Baoimport java.io.File; 5890237f7beb55dae79cdcba5271f96be778573737Tao Baoimport java.io.FileReader; 5990237f7beb55dae79cdcba5271f96be778573737Tao Baoimport java.io.IOException; 6090237f7beb55dae79cdcba5271f96be778573737Tao Bao 6155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornpublic final class ShutdownThread extends Thread { 6255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // constants 6355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private static final String TAG = "ShutdownThread"; 6455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private static final int PHONE_STATE_POLL_SLEEP_MSEC = 500; 6555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // maximum time we wait for the shutdown broadcast before going on. 6655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private static final int MAX_BROADCAST_TIME = 10*1000; 676ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000; 68b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown private static final int MAX_RADIO_WAIT_TIME = 12*1000; 6990237f7beb55dae79cdcba5271f96be778573737Tao Bao private static final int MAX_UNCRYPT_WAIT_TIME = 15*60*1000; 7081dce6631396012e8b722bbed6d003f584800ae1Tao Bao // constants for progress bar. the values are roughly estimated based on timeout. 7181dce6631396012e8b722bbed6d003f584800ae1Tao Bao private static final int BROADCAST_STOP_PERCENT = 2; 7281dce6631396012e8b722bbed6d003f584800ae1Tao Bao private static final int ACTIVITY_MANAGER_STOP_PERCENT = 4; 7381dce6631396012e8b722bbed6d003f584800ae1Tao Bao private static final int PACKAGE_MANAGER_STOP_PERCENT = 6; 7481dce6631396012e8b722bbed6d003f584800ae1Tao Bao private static final int RADIO_STOP_PERCENT = 18; 7581dce6631396012e8b722bbed6d003f584800ae1Tao Bao private static final int MOUNT_SERVICE_STOP_PERCENT = 20; 76a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood 77a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood // length of vibration before shutting down 78a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood private static final int SHUTDOWN_VIBRATE_MS = 500; 7990237f7beb55dae79cdcba5271f96be778573737Tao Bao 8055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // state tracking 8155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private static Object sIsStartedGuard = new Object(); 8255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private static boolean sIsStarted = false; 8390237f7beb55dae79cdcba5271f96be778573737Tao Bao 8481dce6631396012e8b722bbed6d003f584800ae1Tao Bao // uncrypt status files 8590237f7beb55dae79cdcba5271f96be778573737Tao Bao private static final String UNCRYPT_STATUS_FILE = "/cache/recovery/uncrypt_status"; 8681dce6631396012e8b722bbed6d003f584800ae1Tao Bao private static final String UNCRYPT_PACKAGE_FILE = "/cache/recovery/uncrypt_file"; 8790237f7beb55dae79cdcba5271f96be778573737Tao Bao 886ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu private static boolean mReboot; 8919caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn private static boolean mRebootSafeMode; 9081dce6631396012e8b722bbed6d003f584800ae1Tao Bao private static boolean mRebootUpdate; 916ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu private static String mRebootReason; 926ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu 93f547d679c058ed00de78a32146d04b75254df7ecKenny Root // Provides shutdown assurance in case the system_server is killed 94f547d679c058ed00de78a32146d04b75254df7ecKenny Root public static final String SHUTDOWN_ACTION_PROPERTY = "sys.shutdown.requested"; 95f547d679c058ed00de78a32146d04b75254df7ecKenny Root 9619caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn // Indicates whether we are rebooting into safe mode 9719caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn public static final String REBOOT_SAFEMODE_PROPERTY = "persist.sys.safemode"; 9819caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn 9955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // static instance of this thread 10055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private static final ShutdownThread sInstance = new ShutdownThread(); 1017b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock 1027b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder() 1037b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) 1047b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) 1057b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock .build(); 1067b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock 1076ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu private final Object mActionDoneSync = new Object(); 1086ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu private boolean mActionDone; 10955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private Context mContext; 110f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn private PowerManager mPowerManager; 111cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson private PowerManager.WakeLock mCpuWakeLock; 112cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson private PowerManager.WakeLock mScreenWakeLock; 11355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private Handler mHandler; 1148b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson 1158b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson private static AlertDialog sConfirmDialog; 11690237f7beb55dae79cdcba5271f96be778573737Tao Bao private ProgressDialog mProgressDialog; 11790237f7beb55dae79cdcba5271f96be778573737Tao Bao 11855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private ShutdownThread() { 11955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 12090237f7beb55dae79cdcba5271f96be778573737Tao Bao 1216ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu /** 12255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * Request a clean shutdown, waiting for subsystems to clean up their 12355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * state etc. Must be called from a Looper thread in which its UI 12455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * is shown. 1256ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * 12655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * @param context Context used to display the shutdown progress dialog. 1276ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * @param confirm true if user confirmation is needed before shutting down. 12855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn */ 12955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn public static void shutdown(final Context context, boolean confirm) { 13019caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn mReboot = false; 13119caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn mRebootSafeMode = false; 13219caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn shutdownInner(context, confirm); 13319caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn } 13419caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn 13519caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn static void shutdownInner(final Context context, boolean confirm) { 13655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // ensure that only one thread is trying to power down. 13755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // any additional calls are just returned 138d67b236497d87223e8373d96c274c97cfbcab0cbMike Lockwood synchronized (sIsStartedGuard) { 13955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn if (sIsStarted) { 14055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.d(TAG, "Request to shutdown already running, returning."); 14155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn return; 14255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 14355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 14455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 145d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato final int longPressBehavior = context.getResources().getInteger( 146d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato com.android.internal.R.integer.config_longPressOnPowerBehavior); 14719caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn final int resourceId = mRebootSafeMode 14819caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn ? com.android.internal.R.string.reboot_safemode_confirm 14919caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn : (longPressBehavior == 2 15019caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn ? com.android.internal.R.string.shutdown_confirm_question 15119caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn : com.android.internal.R.string.shutdown_confirm); 152d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato 153d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior); 15455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 15555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn if (confirm) { 156d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato final CloseDialogReceiver closer = new CloseDialogReceiver(context); 1578b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson if (sConfirmDialog != null) { 1588b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson sConfirmDialog.dismiss(); 1598b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson } 1608b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson sConfirmDialog = new AlertDialog.Builder(context) 16119caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn .setTitle(mRebootSafeMode 16219caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn ? com.android.internal.R.string.reboot_safemode_title 16319caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn : com.android.internal.R.string.power_off) 164d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato .setMessage(resourceId) 16555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() { 16655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn public void onClick(DialogInterface dialog, int which) { 16755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn beginShutdownSequence(context); 16855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 16955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn }) 17055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn .setNegativeButton(com.android.internal.R.string.no, null) 17155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn .create(); 1728b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson closer.dialog = sConfirmDialog; 1738b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson sConfirmDialog.setOnDismissListener(closer); 1748b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); 1758b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson sConfirmDialog.show(); 17655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } else { 17755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn beginShutdownSequence(context); 17855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 17955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 18055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 181d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato private static class CloseDialogReceiver extends BroadcastReceiver 182d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato implements DialogInterface.OnDismissListener { 183d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato private Context mContext; 184d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato public Dialog dialog; 185d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato 186d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato CloseDialogReceiver(Context context) { 187d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato mContext = context; 188d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); 189d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato context.registerReceiver(this, filter); 190d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato } 191d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato 192d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato @Override 193d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato public void onReceive(Context context, Intent intent) { 194d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato dialog.cancel(); 195d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato } 196d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato 197d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato public void onDismiss(DialogInterface unused) { 198d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato mContext.unregisterReceiver(this); 199d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato } 200d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato } 201d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato 2026ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu /** 2036ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * Request a clean shutdown, waiting for subsystems to clean up their 2046ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * state etc. Must be called from a Looper thread in which its UI 2056ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * is shown. 2066ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * 2076ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * @param context Context used to display the shutdown progress dialog. 2086ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * @param reason code to pass to the kernel (e.g. "recovery"), or null. 2096ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu * @param confirm true if user confirmation is needed before shutting down. 2106ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu */ 2116ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu public static void reboot(final Context context, String reason, boolean confirm) { 2126ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu mReboot = true; 21319caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn mRebootSafeMode = false; 21481dce6631396012e8b722bbed6d003f584800ae1Tao Bao mRebootUpdate = false; 2156ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu mRebootReason = reason; 21619caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn shutdownInner(context, confirm); 21719caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn } 21819caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn 21919caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn /** 22019caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn * Request a reboot into safe mode. Must be called from a Looper thread in which its UI 22119caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn * is shown. 22219caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn * 22319caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn * @param context Context used to display the shutdown progress dialog. 22419caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn * @param confirm true if user confirmation is needed before shutting down. 22519caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn */ 22619caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn public static void rebootSafeMode(final Context context, boolean confirm) { 227bff46bac807ae8a9ebdc22c449a8d4f78711b4d2Benjamin Franz UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); 228bff46bac807ae8a9ebdc22c449a8d4f78711b4d2Benjamin Franz if (um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) { 229bff46bac807ae8a9ebdc22c449a8d4f78711b4d2Benjamin Franz return; 230bff46bac807ae8a9ebdc22c449a8d4f78711b4d2Benjamin Franz } 231bff46bac807ae8a9ebdc22c449a8d4f78711b4d2Benjamin Franz 23219caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn mReboot = true; 23319caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn mRebootSafeMode = true; 23481dce6631396012e8b722bbed6d003f584800ae1Tao Bao mRebootUpdate = false; 23519caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn mRebootReason = null; 23619caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn shutdownInner(context, confirm); 2376ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } 2386ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu 23955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn private static void beginShutdownSequence(Context context) { 24055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn synchronized (sIsStartedGuard) { 241d67b236497d87223e8373d96c274c97cfbcab0cbMike Lockwood if (sIsStarted) { 2428534a8e438ff35511051cf74f8f73d52c8b3b1f4Mathias Jeppsson Log.d(TAG, "Shutdown sequence already running, returning."); 243d67b236497d87223e8373d96c274c97cfbcab0cbMike Lockwood return; 244d67b236497d87223e8373d96c274c97cfbcab0cbMike Lockwood } 24555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn sIsStarted = true; 24655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 24755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 24881dce6631396012e8b722bbed6d003f584800ae1Tao Bao // Throw up a system dialog to indicate the device is rebooting / shutting down. 24955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn ProgressDialog pd = new ProgressDialog(context); 25081dce6631396012e8b722bbed6d003f584800ae1Tao Bao 25181dce6631396012e8b722bbed6d003f584800ae1Tao Bao // Path 1: Reboot to recovery and install the update 25281dce6631396012e8b722bbed6d003f584800ae1Tao Bao // Condition: mRebootReason == REBOOT_RECOVERY and mRebootUpdate == True 25381dce6631396012e8b722bbed6d003f584800ae1Tao Bao // (mRebootUpdate is set by checking if /cache/recovery/uncrypt_file exists.) 25481dce6631396012e8b722bbed6d003f584800ae1Tao Bao // UI: progress bar 25581dce6631396012e8b722bbed6d003f584800ae1Tao Bao // 25681dce6631396012e8b722bbed6d003f584800ae1Tao Bao // Path 2: Reboot to recovery for factory reset 25781dce6631396012e8b722bbed6d003f584800ae1Tao Bao // Condition: mRebootReason == REBOOT_RECOVERY 25881dce6631396012e8b722bbed6d003f584800ae1Tao Bao // UI: spinning circle only (no progress bar) 25981dce6631396012e8b722bbed6d003f584800ae1Tao Bao // 26081dce6631396012e8b722bbed6d003f584800ae1Tao Bao // Path 3: Regular reboot / shutdown 26181dce6631396012e8b722bbed6d003f584800ae1Tao Bao // Condition: Otherwise 26281dce6631396012e8b722bbed6d003f584800ae1Tao Bao // UI: spinning circle only (no progress bar) 2639bb765448df43d41e0a3edb7de1d1641c9251c35Guang Zhu if (PowerManager.REBOOT_RECOVERY.equals(mRebootReason)) { 26481dce6631396012e8b722bbed6d003f584800ae1Tao Bao mRebootUpdate = new File(UNCRYPT_PACKAGE_FILE).exists(); 26581dce6631396012e8b722bbed6d003f584800ae1Tao Bao if (mRebootUpdate) { 26681dce6631396012e8b722bbed6d003f584800ae1Tao Bao pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_update_title)); 26781dce6631396012e8b722bbed6d003f584800ae1Tao Bao pd.setMessage(context.getText( 26881dce6631396012e8b722bbed6d003f584800ae1Tao Bao com.android.internal.R.string.reboot_to_update_prepare)); 26981dce6631396012e8b722bbed6d003f584800ae1Tao Bao pd.setMax(100); 27081dce6631396012e8b722bbed6d003f584800ae1Tao Bao pd.setProgressNumberFormat(null); 27181dce6631396012e8b722bbed6d003f584800ae1Tao Bao pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 27281dce6631396012e8b722bbed6d003f584800ae1Tao Bao pd.setProgress(0); 27381dce6631396012e8b722bbed6d003f584800ae1Tao Bao pd.setIndeterminate(false); 27481dce6631396012e8b722bbed6d003f584800ae1Tao Bao } else { 27581dce6631396012e8b722bbed6d003f584800ae1Tao Bao // Factory reset path. Set the dialog message accordingly. 27681dce6631396012e8b722bbed6d003f584800ae1Tao Bao pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_reset_title)); 27781dce6631396012e8b722bbed6d003f584800ae1Tao Bao pd.setMessage(context.getText( 27881dce6631396012e8b722bbed6d003f584800ae1Tao Bao com.android.internal.R.string.reboot_to_reset_message)); 27981dce6631396012e8b722bbed6d003f584800ae1Tao Bao pd.setIndeterminate(true); 28081dce6631396012e8b722bbed6d003f584800ae1Tao Bao } 28190237f7beb55dae79cdcba5271f96be778573737Tao Bao } else { 28290237f7beb55dae79cdcba5271f96be778573737Tao Bao pd.setTitle(context.getText(com.android.internal.R.string.power_off)); 28381dce6631396012e8b722bbed6d003f584800ae1Tao Bao pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress)); 28481dce6631396012e8b722bbed6d003f584800ae1Tao Bao pd.setIndeterminate(true); 28590237f7beb55dae79cdcba5271f96be778573737Tao Bao } 28655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn pd.setCancelable(false); 28755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); 28855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 28955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn pd.show(); 29055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 29190237f7beb55dae79cdcba5271f96be778573737Tao Bao sInstance.mProgressDialog = pd; 29255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn sInstance.mContext = context; 293f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 294cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson 295cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson // make sure we never fall asleep again 296cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mCpuWakeLock = null; 297cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson try { 298cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock( 299cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu"); 300cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mCpuWakeLock.setReferenceCounted(false); 301cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mCpuWakeLock.acquire(); 302cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson } catch (SecurityException e) { 303cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson Log.w(TAG, "No permission to acquire wake lock", e); 304cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mCpuWakeLock = null; 305cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson } 306cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson 307cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson // also make sure the screen stays on for better user experience 308cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mScreenWakeLock = null; 309f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn if (sInstance.mPowerManager.isScreenOn()) { 310f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn try { 311cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock( 312cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson PowerManager.FULL_WAKE_LOCK, TAG + "-screen"); 313cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mScreenWakeLock.setReferenceCounted(false); 314cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mScreenWakeLock.acquire(); 315f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn } catch (SecurityException e) { 316f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn Log.w(TAG, "No permission to acquire wake lock", e); 317cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson sInstance.mScreenWakeLock = null; 318f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn } 319f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn } 320cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson 321cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson // start the thread that initiates shutdown 32255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn sInstance.mHandler = new Handler() { 32355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn }; 32455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn sInstance.start(); 32555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 32655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 3276ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu void actionDone() { 3286ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu synchronized (mActionDoneSync) { 3296ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu mActionDone = true; 3306ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu mActionDoneSync.notifyAll(); 33155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 33255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 3336ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu 33455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn /** 33555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * Makes sure we handle the shutdown gracefully. 33655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * Shuts off power regardless of radio and bluetooth state if the alloted time has passed. 33755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn */ 33855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn public void run() { 33955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn BroadcastReceiver br = new BroadcastReceiver() { 34055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn @Override public void onReceive(Context context, Intent intent) { 34155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // We don't allow apps to cancel this, so ignore the result. 3426ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu actionDone(); 34355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 34455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn }; 345f547d679c058ed00de78a32146d04b75254df7ecKenny Root 346f547d679c058ed00de78a32146d04b75254df7ecKenny Root /* 347f547d679c058ed00de78a32146d04b75254df7ecKenny Root * Write a system property in case the system_server reboots before we 348f547d679c058ed00de78a32146d04b75254df7ecKenny Root * get to the actual hardware restart. If that happens, we'll retry at 349f547d679c058ed00de78a32146d04b75254df7ecKenny Root * the beginning of the SystemServer startup. 350f547d679c058ed00de78a32146d04b75254df7ecKenny Root */ 351f547d679c058ed00de78a32146d04b75254df7ecKenny Root { 352f547d679c058ed00de78a32146d04b75254df7ecKenny Root String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : ""); 353f547d679c058ed00de78a32146d04b75254df7ecKenny Root SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason); 354f547d679c058ed00de78a32146d04b75254df7ecKenny Root } 355f547d679c058ed00de78a32146d04b75254df7ecKenny Root 35619caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn /* 35719caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn * If we are rebooting into safe mode, write a system property 35819caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn * indicating so. 35919caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn */ 36019caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn if (mRebootSafeMode) { 36119caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1"); 36219caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn } 36319caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn 36455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.i(TAG, "Sending shutdown broadcast..."); 36590237f7beb55dae79cdcba5271f96be778573737Tao Bao 36655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn // First send the high-level shut down broadcast. 3676ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu mActionDone = false; 368a81d7dace6e729a1f4f5dd3afc3d53c536e1996cMartin Wallgren Intent intent = new Intent(Intent.ACTION_SHUTDOWN); 369a81d7dace6e729a1f4f5dd3afc3d53c536e1996cMartin Wallgren intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 370a81d7dace6e729a1f4f5dd3afc3d53c536e1996cMartin Wallgren mContext.sendOrderedBroadcastAsUser(intent, 3715ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn UserHandle.ALL, null, br, mHandler, 0, null, null); 37290237f7beb55dae79cdcba5271f96be778573737Tao Bao 373098e58da93f304d7d7791f193c6237870b94989dMike Lockwood final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME; 3746ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu synchronized (mActionDoneSync) { 3756ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu while (!mActionDone) { 376098e58da93f304d7d7791f193c6237870b94989dMike Lockwood long delay = endTime - SystemClock.elapsedRealtime(); 37755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn if (delay <= 0) { 37855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.w(TAG, "Shutdown broadcast timed out"); 37955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn break; 38081dce6631396012e8b722bbed6d003f584800ae1Tao Bao } else if (mRebootUpdate) { 38181dce6631396012e8b722bbed6d003f584800ae1Tao Bao int status = (int)((MAX_BROADCAST_TIME - delay) * 1.0 * 38281dce6631396012e8b722bbed6d003f584800ae1Tao Bao BROADCAST_STOP_PERCENT / MAX_BROADCAST_TIME); 38381dce6631396012e8b722bbed6d003f584800ae1Tao Bao sInstance.setRebootProgress(status, null); 38455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 38555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn try { 38681dce6631396012e8b722bbed6d003f584800ae1Tao Bao mActionDoneSync.wait(Math.min(delay, PHONE_STATE_POLL_SLEEP_MSEC)); 38755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } catch (InterruptedException e) { 38855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 38955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 39055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 39181dce6631396012e8b722bbed6d003f584800ae1Tao Bao if (mRebootUpdate) { 39281dce6631396012e8b722bbed6d003f584800ae1Tao Bao sInstance.setRebootProgress(BROADCAST_STOP_PERCENT, null); 39381dce6631396012e8b722bbed6d003f584800ae1Tao Bao } 39490237f7beb55dae79cdcba5271f96be778573737Tao Bao 39555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.i(TAG, "Shutting down activity manager..."); 39690237f7beb55dae79cdcba5271f96be778573737Tao Bao 39755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn final IActivityManager am = 39855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn ActivityManagerNative.asInterface(ServiceManager.checkService("activity")); 39955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn if (am != null) { 40055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn try { 40155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn am.shutdown(MAX_BROADCAST_TIME); 40255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } catch (RemoteException e) { 40355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 40455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 40581dce6631396012e8b722bbed6d003f584800ae1Tao Bao if (mRebootUpdate) { 40681dce6631396012e8b722bbed6d003f584800ae1Tao Bao sInstance.setRebootProgress(ACTIVITY_MANAGER_STOP_PERCENT, null); 40781dce6631396012e8b722bbed6d003f584800ae1Tao Bao } 40855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn 409ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom Log.i(TAG, "Shutting down package manager..."); 410ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom 411ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom final PackageManagerService pm = (PackageManagerService) 412ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom ServiceManager.getService("package"); 413ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom if (pm != null) { 414ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom pm.shutdown(); 415ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom } 41681dce6631396012e8b722bbed6d003f584800ae1Tao Bao if (mRebootUpdate) { 41781dce6631396012e8b722bbed6d003f584800ae1Tao Bao sInstance.setRebootProgress(PACKAGE_MANAGER_STOP_PERCENT, null); 41881dce6631396012e8b722bbed6d003f584800ae1Tao Bao } 419ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom 4209631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie // Shutdown radios. 4219631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie shutdownRadios(MAX_RADIO_WAIT_TIME); 42281dce6631396012e8b722bbed6d003f584800ae1Tao Bao if (mRebootUpdate) { 42381dce6631396012e8b722bbed6d003f584800ae1Tao Bao sInstance.setRebootProgress(RADIO_STOP_PERCENT, null); 42481dce6631396012e8b722bbed6d003f584800ae1Tao Bao } 4259631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie 4269f7f7cad0b1fd7b096d65faf4b2352204403257eSan Mehat // Shutdown MountService to ensure media is in a safe state 4276ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu IMountShutdownObserver observer = new IMountShutdownObserver.Stub() { 4286ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu public void onShutDownComplete(int statusCode) throws RemoteException { 4296ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu Log.w(TAG, "Result code " + statusCode + " from MountService.shutdown"); 4306ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu actionDone(); 4316ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } 4326ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu }; 4336ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu 4346ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu Log.i(TAG, "Shutting down MountService"); 435b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown 4366ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu // Set initial variables and time out time. 4376ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu mActionDone = false; 438098e58da93f304d7d7791f193c6237870b94989dMike Lockwood final long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME; 4396ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu synchronized (mActionDoneSync) { 4406ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu try { 441b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown final IMountService mount = IMountService.Stub.asInterface( 442b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown ServiceManager.checkService("mount")); 4436ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu if (mount != null) { 4446ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu mount.shutdown(observer); 4456ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } else { 4466ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu Log.w(TAG, "MountService unavailable for shutdown"); 4476ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } 4486ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } catch (Exception e) { 4496ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu Log.e(TAG, "Exception during MountService shutdown", e); 4506ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } 4516ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu while (!mActionDone) { 452098e58da93f304d7d7791f193c6237870b94989dMike Lockwood long delay = endShutTime - SystemClock.elapsedRealtime(); 4536ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu if (delay <= 0) { 4546ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu Log.w(TAG, "Shutdown wait timed out"); 4556ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu break; 45681dce6631396012e8b722bbed6d003f584800ae1Tao Bao } else if (mRebootUpdate) { 45781dce6631396012e8b722bbed6d003f584800ae1Tao Bao int status = (int)((MAX_SHUTDOWN_WAIT_TIME - delay) * 1.0 * 45881dce6631396012e8b722bbed6d003f584800ae1Tao Bao (MOUNT_SERVICE_STOP_PERCENT - RADIO_STOP_PERCENT) / 45981dce6631396012e8b722bbed6d003f584800ae1Tao Bao MAX_SHUTDOWN_WAIT_TIME); 46081dce6631396012e8b722bbed6d003f584800ae1Tao Bao status += RADIO_STOP_PERCENT; 46181dce6631396012e8b722bbed6d003f584800ae1Tao Bao sInstance.setRebootProgress(status, null); 4626ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } 4636ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu try { 46481dce6631396012e8b722bbed6d003f584800ae1Tao Bao mActionDoneSync.wait(Math.min(delay, PHONE_STATE_POLL_SLEEP_MSEC)); 4656ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } catch (InterruptedException e) { 4666ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } 4676ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } 4686ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu } 46981dce6631396012e8b722bbed6d003f584800ae1Tao Bao if (mRebootUpdate) { 47081dce6631396012e8b722bbed6d003f584800ae1Tao Bao sInstance.setRebootProgress(MOUNT_SERVICE_STOP_PERCENT, null); 4716ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu 47281dce6631396012e8b722bbed6d003f584800ae1Tao Bao // If it's to reboot to install update, invoke uncrypt via init service. 47390237f7beb55dae79cdcba5271f96be778573737Tao Bao uncrypt(); 47490237f7beb55dae79cdcba5271f96be778573737Tao Bao } 47590237f7beb55dae79cdcba5271f96be778573737Tao Bao 476d3b371755df509cabbc5b4451df83309be5439b0riddle_hsu rebootOrShutdown(mContext, mReboot, mRebootReason); 477f547d679c058ed00de78a32146d04b75254df7ecKenny Root } 478f547d679c058ed00de78a32146d04b75254df7ecKenny Root 47981dce6631396012e8b722bbed6d003f584800ae1Tao Bao private void setRebootProgress(final int progress, final CharSequence message) { 48090237f7beb55dae79cdcba5271f96be778573737Tao Bao mHandler.post(new Runnable() { 48190237f7beb55dae79cdcba5271f96be778573737Tao Bao @Override 48290237f7beb55dae79cdcba5271f96be778573737Tao Bao public void run() { 48390237f7beb55dae79cdcba5271f96be778573737Tao Bao if (mProgressDialog != null) { 48490237f7beb55dae79cdcba5271f96be778573737Tao Bao mProgressDialog.setProgress(progress); 48581dce6631396012e8b722bbed6d003f584800ae1Tao Bao if (message != null) { 48681dce6631396012e8b722bbed6d003f584800ae1Tao Bao mProgressDialog.setMessage(message); 48781dce6631396012e8b722bbed6d003f584800ae1Tao Bao } 48890237f7beb55dae79cdcba5271f96be778573737Tao Bao } 48990237f7beb55dae79cdcba5271f96be778573737Tao Bao } 49090237f7beb55dae79cdcba5271f96be778573737Tao Bao }); 49190237f7beb55dae79cdcba5271f96be778573737Tao Bao } 49290237f7beb55dae79cdcba5271f96be778573737Tao Bao 49381dce6631396012e8b722bbed6d003f584800ae1Tao Bao private void shutdownRadios(final int timeout) { 494b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown // If a radio is wedged, disabling it may hang so we do this work in another thread, 495b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown // just in case. 496b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown final long endTime = SystemClock.elapsedRealtime() + timeout; 497b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown final boolean[] done = new boolean[1]; 498b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown Thread t = new Thread() { 499b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown public void run() { 500b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown boolean nfcOff; 501b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown boolean bluetoothOff; 502b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown boolean radioOff; 503b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown 504b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown final INfcAdapter nfc = 505b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown INfcAdapter.Stub.asInterface(ServiceManager.checkService("nfc")); 506b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown final ITelephony phone = 507b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); 5089631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie final IBluetoothManager bluetooth = 5099631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie IBluetoothManager.Stub.asInterface(ServiceManager.checkService( 5109631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE)); 511b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown 512b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown try { 513b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown nfcOff = nfc == null || 514b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown nfc.getState() == NfcAdapter.STATE_OFF; 515b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown if (!nfcOff) { 516b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown Log.w(TAG, "Turning off NFC..."); 517b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown nfc.disable(false); // Don't persist new state 518b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 519b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } catch (RemoteException ex) { 520b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown Log.e(TAG, "RemoteException during NFC shutdown", ex); 521b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown nfcOff = true; 522b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 523b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown 524b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown try { 5259631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie bluetoothOff = bluetooth == null || !bluetooth.isEnabled(); 526b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown if (!bluetoothOff) { 527b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown Log.w(TAG, "Disabling Bluetooth..."); 528b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown bluetooth.disable(false); // disable but don't persist new state 529b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 530b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } catch (RemoteException ex) { 531b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown Log.e(TAG, "RemoteException during bluetooth shutdown", ex); 532b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown bluetoothOff = true; 533b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 534b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown 535b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown try { 536bd7723637b14d1895c043c2257f1cd9560322d4eNaveen Kalla radioOff = phone == null || !phone.needMobileRadioShutdown(); 537b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown if (!radioOff) { 538bd7723637b14d1895c043c2257f1cd9560322d4eNaveen Kalla Log.w(TAG, "Turning off cellular radios..."); 539bd7723637b14d1895c043c2257f1cd9560322d4eNaveen Kalla phone.shutdownMobileRadios(); 540b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 541b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } catch (RemoteException ex) { 542b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown Log.e(TAG, "RemoteException during radio shutdown", ex); 543b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown radioOff = true; 544b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 545b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown 546b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown Log.i(TAG, "Waiting for NFC, Bluetooth and Radio..."); 547b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown 54881dce6631396012e8b722bbed6d003f584800ae1Tao Bao long delay = endTime - SystemClock.elapsedRealtime(); 54981dce6631396012e8b722bbed6d003f584800ae1Tao Bao while (delay > 0) { 55081dce6631396012e8b722bbed6d003f584800ae1Tao Bao if (mRebootUpdate) { 55181dce6631396012e8b722bbed6d003f584800ae1Tao Bao int status = (int)((timeout - delay) * 1.0 * 55281dce6631396012e8b722bbed6d003f584800ae1Tao Bao (RADIO_STOP_PERCENT - PACKAGE_MANAGER_STOP_PERCENT) / timeout); 55381dce6631396012e8b722bbed6d003f584800ae1Tao Bao status += PACKAGE_MANAGER_STOP_PERCENT; 55481dce6631396012e8b722bbed6d003f584800ae1Tao Bao sInstance.setRebootProgress(status, null); 55581dce6631396012e8b722bbed6d003f584800ae1Tao Bao } 55681dce6631396012e8b722bbed6d003f584800ae1Tao Bao 557b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown if (!bluetoothOff) { 558b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown try { 5599631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie bluetoothOff = !bluetooth.isEnabled(); 560b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } catch (RemoteException ex) { 561b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown Log.e(TAG, "RemoteException during bluetooth shutdown", ex); 562b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown bluetoothOff = true; 563b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 564b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown if (bluetoothOff) { 565b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown Log.i(TAG, "Bluetooth turned off."); 566b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 567b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 568b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown if (!radioOff) { 569b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown try { 570bd7723637b14d1895c043c2257f1cd9560322d4eNaveen Kalla radioOff = !phone.needMobileRadioShutdown(); 571b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } catch (RemoteException ex) { 572b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown Log.e(TAG, "RemoteException during radio shutdown", ex); 573b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown radioOff = true; 574b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 575b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown if (radioOff) { 576b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown Log.i(TAG, "Radio turned off."); 577b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 578b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 579b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown if (!nfcOff) { 580b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown try { 581b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown nfcOff = nfc.getState() == NfcAdapter.STATE_OFF; 582b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } catch (RemoteException ex) { 583b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown Log.e(TAG, "RemoteException during NFC shutdown", ex); 584b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown nfcOff = true; 585b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 586bd7723637b14d1895c043c2257f1cd9560322d4eNaveen Kalla if (nfcOff) { 587b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown Log.i(TAG, "NFC turned off."); 588b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 589b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 590b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown 591b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown if (radioOff && bluetoothOff && nfcOff) { 592b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown Log.i(TAG, "NFC, Radio and Bluetooth shutdown complete."); 593b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown done[0] = true; 594b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown break; 595b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 596b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC); 59781dce6631396012e8b722bbed6d003f584800ae1Tao Bao 59881dce6631396012e8b722bbed6d003f584800ae1Tao Bao delay = endTime - SystemClock.elapsedRealtime(); 599b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 600b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 601b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown }; 602b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown 603b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown t.start(); 604b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown try { 605b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown t.join(timeout); 606b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } catch (InterruptedException ex) { 607b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 608b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown if (!done[0]) { 609b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown Log.w(TAG, "Timed out waiting for NFC, Radio and Bluetooth shutdown."); 610b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 611b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown } 612b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown 613f547d679c058ed00de78a32146d04b75254df7ecKenny Root /** 614f547d679c058ed00de78a32146d04b75254df7ecKenny Root * Do not call this directly. Use {@link #reboot(Context, String, boolean)} 615f547d679c058ed00de78a32146d04b75254df7ecKenny Root * or {@link #shutdown(Context, boolean)} instead. 616f547d679c058ed00de78a32146d04b75254df7ecKenny Root * 617d3b371755df509cabbc5b4451df83309be5439b0riddle_hsu * @param context Context used to vibrate or null without vibration 618f547d679c058ed00de78a32146d04b75254df7ecKenny Root * @param reboot true to reboot or false to shutdown 619f547d679c058ed00de78a32146d04b75254df7ecKenny Root * @param reason reason for reboot 620f547d679c058ed00de78a32146d04b75254df7ecKenny Root */ 621d3b371755df509cabbc5b4451df83309be5439b0riddle_hsu public static void rebootOrShutdown(final Context context, boolean reboot, String reason) { 622f547d679c058ed00de78a32146d04b75254df7ecKenny Root if (reboot) { 623f547d679c058ed00de78a32146d04b75254df7ecKenny Root Log.i(TAG, "Rebooting, reason: " + reason); 624dbcf2d7482562eff45ac727cea799b37a260e399Nick Kralevich PowerManagerService.lowLevelReboot(reason); 625dbcf2d7482562eff45ac727cea799b37a260e399Nick Kralevich Log.e(TAG, "Reboot failed, will attempt shutdown instead"); 626d3b371755df509cabbc5b4451df83309be5439b0riddle_hsu } else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) { 627a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood // vibrate before shutting down 628d3b371755df509cabbc5b4451df83309be5439b0riddle_hsu Vibrator vibrator = new SystemVibrator(context); 62926e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick try { 6307b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES); 63126e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick } catch (Exception e) { 63226e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick // Failure to vibrate shouldn't interrupt shutdown. Just log it. 63326e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick Log.w(TAG, "Failed to vibrate during shutdown.", e); 63426e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick } 63526e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick 636a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood // vibrator is asynchronous so we need to wait to avoid shutting down too soon. 637a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood try { 638a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood Thread.sleep(SHUTDOWN_VIBRATE_MS); 639e331644cb570e74a8739cb21ffcc5875663ffa58Brad Fitzpatrick } catch (InterruptedException unused) { 640a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood } 6419f7f7cad0b1fd7b096d65faf4b2352204403257eSan Mehat } 6429f7f7cad0b1fd7b096d65faf4b2352204403257eSan Mehat 6436ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu // Shutdown power 64455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn Log.i(TAG, "Performing low-level shutdown..."); 6457304c343821309dd15f769b18f1de2fa43751573Jeff Brown PowerManagerService.lowLevelShutdown(); 64655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn } 64790237f7beb55dae79cdcba5271f96be778573737Tao Bao 64890237f7beb55dae79cdcba5271f96be778573737Tao Bao private void uncrypt() { 64990237f7beb55dae79cdcba5271f96be778573737Tao Bao Log.i(TAG, "Calling uncrypt and monitoring the progress..."); 65090237f7beb55dae79cdcba5271f96be778573737Tao Bao 65190237f7beb55dae79cdcba5271f96be778573737Tao Bao final boolean[] done = new boolean[1]; 65290237f7beb55dae79cdcba5271f96be778573737Tao Bao done[0] = false; 65390237f7beb55dae79cdcba5271f96be778573737Tao Bao Thread t = new Thread() { 65490237f7beb55dae79cdcba5271f96be778573737Tao Bao @Override 65590237f7beb55dae79cdcba5271f96be778573737Tao Bao public void run() { 65690237f7beb55dae79cdcba5271f96be778573737Tao Bao // Create the status pipe file to communicate with /system/bin/uncrypt. 65790237f7beb55dae79cdcba5271f96be778573737Tao Bao new File(UNCRYPT_STATUS_FILE).delete(); 65890237f7beb55dae79cdcba5271f96be778573737Tao Bao try { 65990237f7beb55dae79cdcba5271f96be778573737Tao Bao Os.mkfifo(UNCRYPT_STATUS_FILE, 0600); 66090237f7beb55dae79cdcba5271f96be778573737Tao Bao } catch (ErrnoException e) { 66190237f7beb55dae79cdcba5271f96be778573737Tao Bao Log.w(TAG, "ErrnoException when creating named pipe \"" + UNCRYPT_STATUS_FILE + 66290237f7beb55dae79cdcba5271f96be778573737Tao Bao "\": " + e.getMessage()); 66390237f7beb55dae79cdcba5271f96be778573737Tao Bao } 66490237f7beb55dae79cdcba5271f96be778573737Tao Bao 66590237f7beb55dae79cdcba5271f96be778573737Tao Bao SystemProperties.set("ctl.start", "uncrypt"); 66690237f7beb55dae79cdcba5271f96be778573737Tao Bao 66790237f7beb55dae79cdcba5271f96be778573737Tao Bao // Read the status from the pipe. 66890237f7beb55dae79cdcba5271f96be778573737Tao Bao try (BufferedReader reader = new BufferedReader( 66990237f7beb55dae79cdcba5271f96be778573737Tao Bao new FileReader(UNCRYPT_STATUS_FILE))) { 67090237f7beb55dae79cdcba5271f96be778573737Tao Bao 67181dce6631396012e8b722bbed6d003f584800ae1Tao Bao int lastStatus = Integer.MIN_VALUE; 67290237f7beb55dae79cdcba5271f96be778573737Tao Bao while (true) { 67390237f7beb55dae79cdcba5271f96be778573737Tao Bao String str = reader.readLine(); 67490237f7beb55dae79cdcba5271f96be778573737Tao Bao try { 67590237f7beb55dae79cdcba5271f96be778573737Tao Bao int status = Integer.parseInt(str); 67690237f7beb55dae79cdcba5271f96be778573737Tao Bao 67790237f7beb55dae79cdcba5271f96be778573737Tao Bao // Avoid flooding the log with the same message. 67881dce6631396012e8b722bbed6d003f584800ae1Tao Bao if (status == lastStatus && lastStatus != Integer.MIN_VALUE) { 67990237f7beb55dae79cdcba5271f96be778573737Tao Bao continue; 68090237f7beb55dae79cdcba5271f96be778573737Tao Bao } 68181dce6631396012e8b722bbed6d003f584800ae1Tao Bao lastStatus = status; 68290237f7beb55dae79cdcba5271f96be778573737Tao Bao 68390237f7beb55dae79cdcba5271f96be778573737Tao Bao if (status >= 0 && status < 100) { 68490237f7beb55dae79cdcba5271f96be778573737Tao Bao // Update status 68590237f7beb55dae79cdcba5271f96be778573737Tao Bao Log.d(TAG, "uncrypt read status: " + status); 68681dce6631396012e8b722bbed6d003f584800ae1Tao Bao // Scale down to [MOUNT_SERVICE_STOP_PERCENT, 100). 68781dce6631396012e8b722bbed6d003f584800ae1Tao Bao status = (int)(status * (100.0 - MOUNT_SERVICE_STOP_PERCENT) / 100); 68881dce6631396012e8b722bbed6d003f584800ae1Tao Bao status += MOUNT_SERVICE_STOP_PERCENT; 68981dce6631396012e8b722bbed6d003f584800ae1Tao Bao CharSequence msg = mContext.getText( 69081dce6631396012e8b722bbed6d003f584800ae1Tao Bao com.android.internal.R.string.reboot_to_update_package); 69181dce6631396012e8b722bbed6d003f584800ae1Tao Bao sInstance.setRebootProgress(status, msg); 69290237f7beb55dae79cdcba5271f96be778573737Tao Bao } else if (status == 100) { 69390237f7beb55dae79cdcba5271f96be778573737Tao Bao Log.d(TAG, "uncrypt successfully finished."); 69481dce6631396012e8b722bbed6d003f584800ae1Tao Bao CharSequence msg = mContext.getText( 69581dce6631396012e8b722bbed6d003f584800ae1Tao Bao com.android.internal.R.string.reboot_to_update_reboot); 69681dce6631396012e8b722bbed6d003f584800ae1Tao Bao sInstance.setRebootProgress(status, msg); 69790237f7beb55dae79cdcba5271f96be778573737Tao Bao break; 69890237f7beb55dae79cdcba5271f96be778573737Tao Bao } else { 69990237f7beb55dae79cdcba5271f96be778573737Tao Bao // Error in /system/bin/uncrypt. Or it's rebooting to recovery 70090237f7beb55dae79cdcba5271f96be778573737Tao Bao // to perform other operations (e.g. factory reset). 70190237f7beb55dae79cdcba5271f96be778573737Tao Bao Log.d(TAG, "uncrypt failed with status: " + status); 70290237f7beb55dae79cdcba5271f96be778573737Tao Bao break; 70390237f7beb55dae79cdcba5271f96be778573737Tao Bao } 70490237f7beb55dae79cdcba5271f96be778573737Tao Bao } catch (NumberFormatException unused) { 70590237f7beb55dae79cdcba5271f96be778573737Tao Bao Log.d(TAG, "uncrypt invalid status received: " + str); 70690237f7beb55dae79cdcba5271f96be778573737Tao Bao break; 70790237f7beb55dae79cdcba5271f96be778573737Tao Bao } 70890237f7beb55dae79cdcba5271f96be778573737Tao Bao } 70990237f7beb55dae79cdcba5271f96be778573737Tao Bao } catch (IOException unused) { 71090237f7beb55dae79cdcba5271f96be778573737Tao Bao Log.w(TAG, "IOException when reading \"" + UNCRYPT_STATUS_FILE + "\"."); 71190237f7beb55dae79cdcba5271f96be778573737Tao Bao } 71290237f7beb55dae79cdcba5271f96be778573737Tao Bao done[0] = true; 71390237f7beb55dae79cdcba5271f96be778573737Tao Bao } 71490237f7beb55dae79cdcba5271f96be778573737Tao Bao }; 71590237f7beb55dae79cdcba5271f96be778573737Tao Bao t.start(); 71690237f7beb55dae79cdcba5271f96be778573737Tao Bao 71790237f7beb55dae79cdcba5271f96be778573737Tao Bao try { 71890237f7beb55dae79cdcba5271f96be778573737Tao Bao t.join(MAX_UNCRYPT_WAIT_TIME); 71990237f7beb55dae79cdcba5271f96be778573737Tao Bao } catch (InterruptedException unused) { 72090237f7beb55dae79cdcba5271f96be778573737Tao Bao } 72190237f7beb55dae79cdcba5271f96be778573737Tao Bao if (!done[0]) { 72290237f7beb55dae79cdcba5271f96be778573737Tao Bao Log.w(TAG, "Timed out waiting for uncrypt."); 72390237f7beb55dae79cdcba5271f96be778573737Tao Bao } 72490237f7beb55dae79cdcba5271f96be778573737Tao Bao } 72555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn} 726