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