/** * Turn on or off the mobile radio. No connectivity will be possible while the radio is off. The * operation is a no-op if the radio is already in the desired state. * * @param turnOn {@code true} if the radio should be turned on, {@code false} if */ public boolean setRadio(boolean turnOn) { getPhoneService(false); /* * If the phone process has crashed in the past, we'll get a * RemoteException and need to re-reference the service. */ for (int retry = 0; retry < 2; retry++) { if (mPhoneService == null) { loge("Ignoring mobile radio request because could not acquire PhoneService"); break; } try { return mPhoneService.setRadio(turnOn); } catch (RemoteException e) { if (retry == 0) getPhoneService(true); } } loge("Could not set radio power to " + (turnOn ? "on" : "off")); return false; }
/** * Makes sure we handle the shutdown gracefully. Shuts off power regardless of radio and bluetooth * state if the alloted time has passed. */ public void run() { boolean bluetoothOff; boolean radioOff; BroadcastReceiver br = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // We don't allow apps to cancel this, so ignore the result. broadcastDone(); } }; Log.i(TAG, "Sending shutdown broadcast..."); // First send the high-level shut down broadcast. mBroadcastDone = false; mContext.sendOrderedBroadcast( new Intent(Intent.ACTION_SHUTDOWN), null, br, mHandler, 0, null, null); final long endTime = System.currentTimeMillis() + MAX_BROADCAST_TIME; synchronized (mBroadcastDoneSync) { while (!mBroadcastDone) { long delay = endTime - System.currentTimeMillis(); if (delay <= 0) { Log.w(TAG, "Shutdown broadcast timed out"); break; } try { mBroadcastDoneSync.wait(delay); } catch (InterruptedException e) { } } } Log.i(TAG, "Shutting down activity manager..."); final IActivityManager am = ActivityManagerNative.asInterface(ServiceManager.checkService("activity")); if (am != null) { try { am.shutdown(MAX_BROADCAST_TIME); } catch (RemoteException e) { } } final ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); final IBluetooth bluetooth = IBluetooth.Stub.asInterface( ServiceManager.checkService(BluetoothAdapter.BLUETOOTH_SERVICE)); final IMountService mount = IMountService.Stub.asInterface(ServiceManager.checkService("mount")); try { bluetoothOff = bluetooth == null || bluetooth.getBluetoothState() == BluetoothAdapter.STATE_OFF; if (!bluetoothOff) { Log.w(TAG, "Disabling Bluetooth..."); bluetooth.disable(false); // disable but don't persist new state } } catch (RemoteException ex) { Log.e(TAG, "RemoteException during bluetooth shutdown", ex); bluetoothOff = true; } try { radioOff = phone == null || !phone.isRadioOn(); if (!radioOff) { Log.w(TAG, "Turning off radio..."); phone.setRadio(false); } } catch (RemoteException ex) { Log.e(TAG, "RemoteException during radio shutdown", ex); radioOff = true; } Log.i(TAG, "Waiting for Bluetooth and Radio..."); // Wait a max of 32 seconds for clean shutdown for (int i = 0; i < MAX_NUM_PHONE_STATE_READS; i++) { if (!bluetoothOff) { try { bluetoothOff = bluetooth.getBluetoothState() == BluetoothAdapter.STATE_OFF; } catch (RemoteException ex) { Log.e(TAG, "RemoteException during bluetooth shutdown", ex); bluetoothOff = true; } } if (!radioOff) { try { radioOff = !phone.isRadioOn(); } catch (RemoteException ex) { Log.e(TAG, "RemoteException during radio shutdown", ex); radioOff = true; } } if (radioOff && bluetoothOff) { Log.i(TAG, "Radio and Bluetooth shutdown complete."); break; } SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC); } // Shutdown MountService to ensure media is in a safe state try { if (mount != null) { mount.shutdown(); } else { Log.w(TAG, "MountService unavailable for shutdown"); } } catch (Exception e) { Log.e(TAG, "Exception during MountService shutdown", e); } // shutdown power Log.i(TAG, "Performing low-level shutdown..."); Power.shutdown(); }