155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn/*
255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * Copyright (C) 2008 The Android Open Source Project
355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn *
455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * you may not use this file except in compliance with the License.
655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * You may obtain a copy of the License at
755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn *
855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn *
1055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
1155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
1255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * See the License for the specific language governing permissions and
1455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn * limitations under the License.
1555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn */
1655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
1755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
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;
42a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwoodimport android.os.Vibrator;
43c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brownimport android.os.SystemVibrator;
44b104340496e3a531e26c8f428c808eca0e039f50San Mehatimport android.os.storage.IMountService;
456ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapuimport android.os.storage.IMountShutdownObserver;
46568cae571a3d74d1992176a21722e07b44e9a3c4Dianne Hackborn
4755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport com.android.internal.telephony.ITelephony;
48ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstromimport com.android.server.pm.PackageManagerService;
497304c343821309dd15f769b18f1de2fa43751573Jeff Brown
5055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.util.Log;
5155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornimport android.view.WindowManager;
5255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
5355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackbornpublic final class ShutdownThread extends Thread {
5455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    // constants
5555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    private static final String TAG = "ShutdownThread";
5655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    private static final int PHONE_STATE_POLL_SLEEP_MSEC = 500;
5755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    // maximum time we wait for the shutdown broadcast before going on.
5855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    private static final int MAX_BROADCAST_TIME = 10*1000;
596ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu    private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000;
60b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown    private static final int MAX_RADIO_WAIT_TIME = 12*1000;
61a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood
62a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood    // length of vibration before shutting down
63a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood    private static final int SHUTDOWN_VIBRATE_MS = 500;
6455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
6555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    // state tracking
6655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    private static Object sIsStartedGuard = new Object();
6755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    private static boolean sIsStarted = false;
6855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
696ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu    private static boolean mReboot;
7019caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn    private static boolean mRebootSafeMode;
716ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu    private static String mRebootReason;
726ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu
73f547d679c058ed00de78a32146d04b75254df7ecKenny Root    // Provides shutdown assurance in case the system_server is killed
74f547d679c058ed00de78a32146d04b75254df7ecKenny Root    public static final String SHUTDOWN_ACTION_PROPERTY = "sys.shutdown.requested";
75f547d679c058ed00de78a32146d04b75254df7ecKenny Root
7619caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn    // Indicates whether we are rebooting into safe mode
7719caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn    public static final String REBOOT_SAFEMODE_PROPERTY = "persist.sys.safemode";
7819caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn
7955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    // static instance of this thread
8055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    private static final ShutdownThread sInstance = new ShutdownThread();
817b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock
827b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
837b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
847b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
857b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock            .build();
867b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock
876ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu    private final Object mActionDoneSync = new Object();
886ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu    private boolean mActionDone;
8955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    private Context mContext;
90f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn    private PowerManager mPowerManager;
91cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson    private PowerManager.WakeLock mCpuWakeLock;
92cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson    private PowerManager.WakeLock mScreenWakeLock;
9355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    private Handler mHandler;
948b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson
958b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson    private static AlertDialog sConfirmDialog;
9655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
9755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    private ShutdownThread() {
9855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    }
9955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
1006ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu    /**
10155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn     * Request a clean shutdown, waiting for subsystems to clean up their
10255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn     * state etc.  Must be called from a Looper thread in which its UI
10355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn     * is shown.
1046ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu     *
10555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn     * @param context Context used to display the shutdown progress dialog.
1066ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu     * @param confirm true if user confirmation is needed before shutting down.
10755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn     */
10855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    public static void shutdown(final Context context, boolean confirm) {
10919caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn        mReboot = false;
11019caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn        mRebootSafeMode = false;
11119caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn        shutdownInner(context, confirm);
11219caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn    }
11319caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn
11419caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn    static void shutdownInner(final Context context, boolean confirm) {
11555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        // ensure that only one thread is trying to power down.
11655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        // any additional calls are just returned
117d67b236497d87223e8373d96c274c97cfbcab0cbMike Lockwood        synchronized (sIsStartedGuard) {
11855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            if (sIsStarted) {
11955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                Log.d(TAG, "Request to shutdown already running, returning.");
12055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                return;
12155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            }
12255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        }
12355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
124d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato        final int longPressBehavior = context.getResources().getInteger(
125d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato                        com.android.internal.R.integer.config_longPressOnPowerBehavior);
12619caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn        final int resourceId = mRebootSafeMode
12719caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn                ? com.android.internal.R.string.reboot_safemode_confirm
12819caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn                : (longPressBehavior == 2
12919caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn                        ? com.android.internal.R.string.shutdown_confirm_question
13019caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn                        : com.android.internal.R.string.shutdown_confirm);
131d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato
132d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato        Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior);
13355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
13455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        if (confirm) {
135d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato            final CloseDialogReceiver closer = new CloseDialogReceiver(context);
1368b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson            if (sConfirmDialog != null) {
1378b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson                sConfirmDialog.dismiss();
1388b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson            }
1398b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson            sConfirmDialog = new AlertDialog.Builder(context)
14019caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn                    .setTitle(mRebootSafeMode
14119caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn                            ? com.android.internal.R.string.reboot_safemode_title
14219caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn                            : com.android.internal.R.string.power_off)
143d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato                    .setMessage(resourceId)
14455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                    .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
14555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                        public void onClick(DialogInterface dialog, int which) {
14655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                            beginShutdownSequence(context);
14755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                        }
14855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                    })
14955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                    .setNegativeButton(com.android.internal.R.string.no, null)
15055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                    .create();
1518b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson            closer.dialog = sConfirmDialog;
1528b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson            sConfirmDialog.setOnDismissListener(closer);
1538b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson            sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
1548b4b63403a06e07dfc595aca45c778023bfec79bMattias Petersson            sConfirmDialog.show();
15555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        } else {
15655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            beginShutdownSequence(context);
15755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        }
15855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    }
15955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
160d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato    private static class CloseDialogReceiver extends BroadcastReceiver
161d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato            implements DialogInterface.OnDismissListener {
162d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato        private Context mContext;
163d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato        public Dialog dialog;
164d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato
165d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato        CloseDialogReceiver(Context context) {
166d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato            mContext = context;
167d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato            IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
168d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato            context.registerReceiver(this, filter);
169d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato        }
170d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato
171d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato        @Override
172d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato        public void onReceive(Context context, Intent intent) {
173d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato            dialog.cancel();
174d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato        }
175d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato
176d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato        public void onDismiss(DialogInterface unused) {
177d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato            mContext.unregisterReceiver(this);
178d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato        }
179d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato    }
180d208e709267f8af77690cb38dba2ae8e30ab5241Joe Onorato
1816ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu    /**
1826ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu     * Request a clean shutdown, waiting for subsystems to clean up their
1836ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu     * state etc.  Must be called from a Looper thread in which its UI
1846ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu     * is shown.
1856ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu     *
1866ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu     * @param context Context used to display the shutdown progress dialog.
1876ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu     * @param reason code to pass to the kernel (e.g. "recovery"), or null.
1886ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu     * @param confirm true if user confirmation is needed before shutting down.
1896ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu     */
1906ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu    public static void reboot(final Context context, String reason, boolean confirm) {
1916ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu        mReboot = true;
19219caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn        mRebootSafeMode = false;
1936ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu        mRebootReason = reason;
19419caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn        shutdownInner(context, confirm);
19519caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn    }
19619caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn
19719caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn    /**
19819caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn     * Request a reboot into safe mode.  Must be called from a Looper thread in which its UI
19919caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn     * is shown.
20019caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn     *
20119caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn     * @param context Context used to display the shutdown progress dialog.
20219caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn     * @param confirm true if user confirmation is needed before shutting down.
20319caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn     */
20419caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn    public static void rebootSafeMode(final Context context, boolean confirm) {
20519caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn        mReboot = true;
20619caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn        mRebootSafeMode = true;
20719caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn        mRebootReason = null;
20819caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn        shutdownInner(context, confirm);
2096ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu    }
2106ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu
21155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    private static void beginShutdownSequence(Context context) {
21255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        synchronized (sIsStartedGuard) {
213d67b236497d87223e8373d96c274c97cfbcab0cbMike Lockwood            if (sIsStarted) {
2148534a8e438ff35511051cf74f8f73d52c8b3b1f4Mathias Jeppsson                Log.d(TAG, "Shutdown sequence already running, returning.");
215d67b236497d87223e8373d96c274c97cfbcab0cbMike Lockwood                return;
216d67b236497d87223e8373d96c274c97cfbcab0cbMike Lockwood            }
21755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            sIsStarted = true;
21855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        }
21955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
22055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        // throw up an indeterminate system dialog to indicate radio is
22155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        // shutting down.
22255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        ProgressDialog pd = new ProgressDialog(context);
22355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        pd.setTitle(context.getText(com.android.internal.R.string.power_off));
22455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
22555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        pd.setIndeterminate(true);
22655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        pd.setCancelable(false);
22755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
22855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
22955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        pd.show();
23055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
23155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        sInstance.mContext = context;
232f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn        sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
233cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson
234cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson        // make sure we never fall asleep again
235cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson        sInstance.mCpuWakeLock = null;
236cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson        try {
237cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson            sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock(
238cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson                    PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu");
239cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson            sInstance.mCpuWakeLock.setReferenceCounted(false);
240cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson            sInstance.mCpuWakeLock.acquire();
241cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson        } catch (SecurityException e) {
242cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson            Log.w(TAG, "No permission to acquire wake lock", e);
243cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson            sInstance.mCpuWakeLock = null;
244cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson        }
245cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson
246cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson        // also make sure the screen stays on for better user experience
247cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson        sInstance.mScreenWakeLock = null;
248f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn        if (sInstance.mPowerManager.isScreenOn()) {
249f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn            try {
250cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson                sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock(
251cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson                        PowerManager.FULL_WAKE_LOCK, TAG + "-screen");
252cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson                sInstance.mScreenWakeLock.setReferenceCounted(false);
253cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson                sInstance.mScreenWakeLock.acquire();
254f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn            } catch (SecurityException e) {
255f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn                Log.w(TAG, "No permission to acquire wake lock", e);
256cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson                sInstance.mScreenWakeLock = null;
257f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn            }
258f99ae76533119f9fef111abef17a3a8fcb8f12a5Dianne Hackborn        }
259cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson
260cd4e4279804288a941c308b88df8bafa4f3f7458Mattias Larsson        // start the thread that initiates shutdown
26155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        sInstance.mHandler = new Handler() {
26255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        };
26355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        sInstance.start();
26455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    }
26555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
2666ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu    void actionDone() {
2676ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu        synchronized (mActionDoneSync) {
2686ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu            mActionDone = true;
2696ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu            mActionDoneSync.notifyAll();
27055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        }
27155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    }
2726ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu
27355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    /**
27455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn     * Makes sure we handle the shutdown gracefully.
27555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn     * Shuts off power regardless of radio and bluetooth state if the alloted time has passed.
27655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn     */
27755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    public void run() {
27855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        BroadcastReceiver br = new BroadcastReceiver() {
27955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            @Override public void onReceive(Context context, Intent intent) {
28055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                // We don't allow apps to cancel this, so ignore the result.
2816ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                actionDone();
28255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            }
28355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        };
284f547d679c058ed00de78a32146d04b75254df7ecKenny Root
285f547d679c058ed00de78a32146d04b75254df7ecKenny Root        /*
286f547d679c058ed00de78a32146d04b75254df7ecKenny Root         * Write a system property in case the system_server reboots before we
287f547d679c058ed00de78a32146d04b75254df7ecKenny Root         * get to the actual hardware restart. If that happens, we'll retry at
288f547d679c058ed00de78a32146d04b75254df7ecKenny Root         * the beginning of the SystemServer startup.
289f547d679c058ed00de78a32146d04b75254df7ecKenny Root         */
290f547d679c058ed00de78a32146d04b75254df7ecKenny Root        {
291f547d679c058ed00de78a32146d04b75254df7ecKenny Root            String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : "");
292f547d679c058ed00de78a32146d04b75254df7ecKenny Root            SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);
293f547d679c058ed00de78a32146d04b75254df7ecKenny Root        }
294f547d679c058ed00de78a32146d04b75254df7ecKenny Root
29519caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn        /*
29619caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn         * If we are rebooting into safe mode, write a system property
29719caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn         * indicating so.
29819caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn         */
29919caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn        if (mRebootSafeMode) {
30019caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn            SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1");
30119caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn        }
30219caadc08f09cc9f6665fbbb0d61e02861ce8562Dianne Hackborn
30355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        Log.i(TAG, "Sending shutdown broadcast...");
30455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
30555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        // First send the high-level shut down broadcast.
3066ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu        mActionDone = false;
307a81d7dace6e729a1f4f5dd3afc3d53c536e1996cMartin Wallgren        Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
308a81d7dace6e729a1f4f5dd3afc3d53c536e1996cMartin Wallgren        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
309a81d7dace6e729a1f4f5dd3afc3d53c536e1996cMartin Wallgren        mContext.sendOrderedBroadcastAsUser(intent,
3105ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn                UserHandle.ALL, null, br, mHandler, 0, null, null);
31155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
312098e58da93f304d7d7791f193c6237870b94989dMike Lockwood        final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
3136ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu        synchronized (mActionDoneSync) {
3146ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu            while (!mActionDone) {
315098e58da93f304d7d7791f193c6237870b94989dMike Lockwood                long delay = endTime - SystemClock.elapsedRealtime();
31655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                if (delay <= 0) {
31755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                    Log.w(TAG, "Shutdown broadcast timed out");
31855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                    break;
31955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                }
32055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                try {
3216ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                    mActionDoneSync.wait(delay);
32255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                } catch (InterruptedException e) {
32355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                }
32455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            }
32555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        }
32655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
32755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        Log.i(TAG, "Shutting down activity manager...");
32855280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
32955280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        final IActivityManager am =
33055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            ActivityManagerNative.asInterface(ServiceManager.checkService("activity"));
33155280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        if (am != null) {
33255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            try {
33355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn                am.shutdown(MAX_BROADCAST_TIME);
33455280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            } catch (RemoteException e) {
33555280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn            }
33655280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        }
33755280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn
338ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom        Log.i(TAG, "Shutting down package manager...");
339ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom
340ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom        final PackageManagerService pm = (PackageManagerService)
341ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom            ServiceManager.getService("package");
342ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom        if (pm != null) {
343ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom            pm.shutdown();
344ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom        }
345ff1ec4d9e7b7eb1b6303d147c796f8767ee6715bBrian Carlstrom
3469631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie        // Shutdown radios.
3479631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie        shutdownRadios(MAX_RADIO_WAIT_TIME);
3489631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie
3499f7f7cad0b1fd7b096d65faf4b2352204403257eSan Mehat        // Shutdown MountService to ensure media is in a safe state
3506ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu        IMountShutdownObserver observer = new IMountShutdownObserver.Stub() {
3516ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu            public void onShutDownComplete(int statusCode) throws RemoteException {
3526ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                Log.w(TAG, "Result code " + statusCode + " from MountService.shutdown");
3536ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                actionDone();
3546ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu            }
3556ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu        };
3566ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu
3576ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu        Log.i(TAG, "Shutting down MountService");
358b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown
3596ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu        // Set initial variables and time out time.
3606ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu        mActionDone = false;
361098e58da93f304d7d7791f193c6237870b94989dMike Lockwood        final long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME;
3626ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu        synchronized (mActionDoneSync) {
3636ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu            try {
364b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                final IMountService mount = IMountService.Stub.asInterface(
365b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        ServiceManager.checkService("mount"));
3666ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                if (mount != null) {
3676ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                    mount.shutdown(observer);
3686ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                } else {
3696ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                    Log.w(TAG, "MountService unavailable for shutdown");
3706ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                }
3716ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu            } catch (Exception e) {
3726ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                Log.e(TAG, "Exception during MountService shutdown", e);
3736ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu            }
3746ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu            while (!mActionDone) {
375098e58da93f304d7d7791f193c6237870b94989dMike Lockwood                long delay = endShutTime - SystemClock.elapsedRealtime();
3766ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                if (delay <= 0) {
3776ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                    Log.w(TAG, "Shutdown wait timed out");
3786ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                    break;
3796ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                }
3806ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                try {
3816ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                    mActionDoneSync.wait(delay);
3826ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                } catch (InterruptedException e) {
3836ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu                }
3846ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu            }
3856ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu        }
3866ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu
387f547d679c058ed00de78a32146d04b75254df7ecKenny Root        rebootOrShutdown(mReboot, mRebootReason);
388f547d679c058ed00de78a32146d04b75254df7ecKenny Root    }
389f547d679c058ed00de78a32146d04b75254df7ecKenny Root
390b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown    private void shutdownRadios(int timeout) {
391b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown        // If a radio is wedged, disabling it may hang so we do this work in another thread,
392b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown        // just in case.
393b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown        final long endTime = SystemClock.elapsedRealtime() + timeout;
394b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown        final boolean[] done = new boolean[1];
395b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown        Thread t = new Thread() {
396b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown            public void run() {
397b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                boolean nfcOff;
398b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                boolean bluetoothOff;
399b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                boolean radioOff;
400b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown
401b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                final INfcAdapter nfc =
402b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        INfcAdapter.Stub.asInterface(ServiceManager.checkService("nfc"));
403b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                final ITelephony phone =
404b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
4059631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie                final IBluetoothManager bluetooth =
4069631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie                        IBluetoothManager.Stub.asInterface(ServiceManager.checkService(
4079631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie                                BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE));
408b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown
409b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                try {
410b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    nfcOff = nfc == null ||
411b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                             nfc.getState() == NfcAdapter.STATE_OFF;
412b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    if (!nfcOff) {
413b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        Log.w(TAG, "Turning off NFC...");
414b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        nfc.disable(false); // Don't persist new state
415b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    }
416b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                } catch (RemoteException ex) {
417b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                Log.e(TAG, "RemoteException during NFC shutdown", ex);
418b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    nfcOff = true;
419b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                }
420b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown
421b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                try {
4229631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie                    bluetoothOff = bluetooth == null || !bluetooth.isEnabled();
423b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    if (!bluetoothOff) {
424b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        Log.w(TAG, "Disabling Bluetooth...");
425b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        bluetooth.disable(false);  // disable but don't persist new state
426b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    }
427b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                } catch (RemoteException ex) {
428b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
429b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    bluetoothOff = true;
430b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                }
431b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown
432b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                try {
433bd7723637b14d1895c043c2257f1cd9560322d4eNaveen Kalla                    radioOff = phone == null || !phone.needMobileRadioShutdown();
434b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    if (!radioOff) {
435bd7723637b14d1895c043c2257f1cd9560322d4eNaveen Kalla                        Log.w(TAG, "Turning off cellular radios...");
436bd7723637b14d1895c043c2257f1cd9560322d4eNaveen Kalla                        phone.shutdownMobileRadios();
437b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    }
438b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                } catch (RemoteException ex) {
439b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    Log.e(TAG, "RemoteException during radio shutdown", ex);
440b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    radioOff = true;
441b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                }
442b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown
443b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                Log.i(TAG, "Waiting for NFC, Bluetooth and Radio...");
444b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown
445b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                while (SystemClock.elapsedRealtime() < endTime) {
446b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    if (!bluetoothOff) {
447b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        try {
4489631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie                            bluetoothOff = !bluetooth.isEnabled();
449b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        } catch (RemoteException ex) {
450b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                            Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
451b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                            bluetoothOff = true;
452b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        }
453b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        if (bluetoothOff) {
454b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                            Log.i(TAG, "Bluetooth turned off.");
455b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        }
456b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    }
457b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    if (!radioOff) {
458b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        try {
459bd7723637b14d1895c043c2257f1cd9560322d4eNaveen Kalla                            radioOff = !phone.needMobileRadioShutdown();
460b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        } catch (RemoteException ex) {
461b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                            Log.e(TAG, "RemoteException during radio shutdown", ex);
462b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                            radioOff = true;
463b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        }
464b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        if (radioOff) {
465b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                            Log.i(TAG, "Radio turned off.");
466b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        }
467b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    }
468b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    if (!nfcOff) {
469b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        try {
470b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                            nfcOff = nfc.getState() == NfcAdapter.STATE_OFF;
471b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        } catch (RemoteException ex) {
472b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                            Log.e(TAG, "RemoteException during NFC shutdown", ex);
473b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                            nfcOff = true;
474b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        }
475bd7723637b14d1895c043c2257f1cd9560322d4eNaveen Kalla                        if (nfcOff) {
476b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                            Log.i(TAG, "NFC turned off.");
477b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        }
478b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    }
479b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown
480b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    if (radioOff && bluetoothOff && nfcOff) {
481b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        Log.i(TAG, "NFC, Radio and Bluetooth shutdown complete.");
482b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        done[0] = true;
483b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                        break;
484b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    }
485b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                    SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC);
486b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown                }
487b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown            }
488b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown        };
489b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown
490b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown        t.start();
491b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown        try {
492b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown            t.join(timeout);
493b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown        } catch (InterruptedException ex) {
494b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown        }
495b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown        if (!done[0]) {
496b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown            Log.w(TAG, "Timed out waiting for NFC, Radio and Bluetooth shutdown.");
497b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown        }
498b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown    }
499b8203719bd037b39d12413f54d546e9ecc9e4872Jeff Brown
500f547d679c058ed00de78a32146d04b75254df7ecKenny Root    /**
501f547d679c058ed00de78a32146d04b75254df7ecKenny Root     * Do not call this directly. Use {@link #reboot(Context, String, boolean)}
502f547d679c058ed00de78a32146d04b75254df7ecKenny Root     * or {@link #shutdown(Context, boolean)} instead.
503f547d679c058ed00de78a32146d04b75254df7ecKenny Root     *
504f547d679c058ed00de78a32146d04b75254df7ecKenny Root     * @param reboot true to reboot or false to shutdown
505f547d679c058ed00de78a32146d04b75254df7ecKenny Root     * @param reason reason for reboot
506f547d679c058ed00de78a32146d04b75254df7ecKenny Root     */
507f547d679c058ed00de78a32146d04b75254df7ecKenny Root    public static void rebootOrShutdown(boolean reboot, String reason) {
508f547d679c058ed00de78a32146d04b75254df7ecKenny Root        if (reboot) {
509f547d679c058ed00de78a32146d04b75254df7ecKenny Root            Log.i(TAG, "Rebooting, reason: " + reason);
510dbcf2d7482562eff45ac727cea799b37a260e399Nick Kralevich            PowerManagerService.lowLevelReboot(reason);
511dbcf2d7482562eff45ac727cea799b37a260e399Nick Kralevich            Log.e(TAG, "Reboot failed, will attempt shutdown instead");
512a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood        } else if (SHUTDOWN_VIBRATE_MS > 0) {
513a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood            // vibrate before shutting down
514c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown            Vibrator vibrator = new SystemVibrator();
51526e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick            try {
5167b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock                vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES);
51726e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick            } catch (Exception e) {
51826e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick                // Failure to vibrate shouldn't interrupt shutdown.  Just log it.
51926e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick                Log.w(TAG, "Failed to vibrate during shutdown.", e);
52026e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick            }
52126e9cf38b229b738b4e56c3e08be82a9c0f11e64Brad Fitzpatrick
522a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood            // vibrator is asynchronous so we need to wait to avoid shutting down too soon.
523a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood            try {
524a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood                Thread.sleep(SHUTDOWN_VIBRATE_MS);
525e331644cb570e74a8739cb21ffcc5875663ffa58Brad Fitzpatrick            } catch (InterruptedException unused) {
526a717f64ddcdce44379b24616333a58a6df2fcca5Mike Lockwood            }
5279f7f7cad0b1fd7b096d65faf4b2352204403257eSan Mehat        }
5289f7f7cad0b1fd7b096d65faf4b2352204403257eSan Mehat
5296ffce2e9a3c57634bb73f8ff133ca680f8070d5dSuchi Amalapurapu        // Shutdown power
53055280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn        Log.i(TAG, "Performing low-level shutdown...");
5317304c343821309dd15f769b18f1de2fa43751573Jeff Brown        PowerManagerService.lowLevelShutdown();
53255280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn    }
53355280a91884b9256e8db6af6a09f28b3feeaa9d8Dianne Hackborn}
534