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