Loading core/java/android/bluetooth/BluetoothAdapter.java +4 −2 Original line number Diff line number Diff line Loading @@ -1195,9 +1195,11 @@ public final class BluetoothAdapter { public boolean factoryReset() { try { mServiceLock.readLock().lock(); if (mService != null) { return mService.factoryReset(); if (mService != null && mService.factoryReset() && mManagerService != null && mManagerService.onFactoryReset()) { return true; } Log.e(TAG, "factoryReset(): Setting persist.bluetooth.factoryreset to retry later"); SystemProperties.set("persist.bluetooth.factoryreset", "true"); } catch (RemoteException e) { Log.e(TAG, "", e); Loading core/proto/android/bluetooth/enums.proto +1 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ enum EnableDisableReasonEnum { ENABLE_DISABLE_REASON_CRASH = 7; ENABLE_DISABLE_REASON_USER_SWITCH = 8; ENABLE_DISABLE_REASON_RESTORE_USER_SETTING = 9; ENABLE_DISABLE_REASON_FACTORY_RESET = 10; } enum DirectionEnum { Loading services/core/java/com/android/server/BluetoothManagerService.java +80 −34 Original line number Diff line number Diff line Loading @@ -73,11 +73,14 @@ import com.android.server.pm.UserRestrictionsUtils; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantReadWriteLock; Loading Loading @@ -257,6 +260,47 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } }; public boolean onFactoryReset() { // Wait for stable state if bluetooth is temporary state. int state = getState(); if (state == BluetoothAdapter.STATE_BLE_TURNING_ON || state == BluetoothAdapter.STATE_TURNING_ON || state == BluetoothAdapter.STATE_TURNING_OFF) { if (!waitForState(new HashSet<Integer>(Arrays.asList(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_ON)))) { return false; } } // Clear registered LE apps to force shut-off Bluetooth clearBleApps(); state = getState(); try { mBluetoothLock.readLock().lock(); if (mBluetooth == null) { return false; } if (state == BluetoothAdapter.STATE_BLE_ON) { addActiveLog( BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET, mContext.getPackageName(), false); mBluetooth.onBrEdrDown(); return true; } else if (state == BluetoothAdapter.STATE_ON) { addActiveLog( BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET, mContext.getPackageName(), false); mBluetooth.disable(); return true; } } catch (RemoteException e) { Slog.e(TAG, "Unable to shutdown Bluetooth", e); } finally { mBluetoothLock.readLock().unlock(); } return false; } private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) { @Override public void onChange(boolean unused) { Loading Loading @@ -1627,7 +1671,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // the previous Bluetooth process has exited. The // waiting period has three components: // (a) Wait until the local state is STATE_OFF. This // is accomplished by "waitForOnOff(false, true)". // is accomplished by // "waitForState(new HashSet<Integer>( // Arrays.asList(BluetoothAdapter.STATE_OFF)))". // (b) Wait until the STATE_OFF state is updated to // all components. // (c) Wait until the Bluetooth process exits, and Loading @@ -1637,7 +1683,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // message. On slower devices, that delay needs to be // on the order of (2 * SERVICE_RESTART_TIME_MS). // waitForOnOff(false, true); waitForState(new HashSet<Integer>(Arrays.asList( BluetoothAdapter.STATE_OFF))); Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); Loading @@ -1650,10 +1697,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); if (mEnable && mBluetooth != null) { waitForOnOff(true, false); waitForState(new HashSet<Integer>(Arrays.asList( BluetoothAdapter.STATE_ON))); mEnable = false; handleDisable(); waitForOnOff(false, false); waitForState(new HashSet<Integer>(Arrays.asList(BluetoothAdapter.STATE_OFF, BluetoothAdapter.STATE_TURNING_ON, BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_BLE_TURNING_ON, BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_BLE_TURNING_OFF))); } else { mEnable = false; handleDisable(); Loading Loading @@ -1782,9 +1835,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (!mEnable) { waitForOnOff(true, false); waitForState(new HashSet<Integer>(Arrays.asList( BluetoothAdapter.STATE_ON))); handleDisable(); waitForOnOff(false, false); waitForState(new HashSet<Integer>(Arrays.asList(BluetoothAdapter.STATE_OFF, BluetoothAdapter.STATE_TURNING_ON, BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_BLE_TURNING_ON, BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_BLE_TURNING_OFF))); } break; } Loading Loading @@ -1816,7 +1875,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { == BluetoothAdapter.STATE_OFF)) { if (mEnable) { Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting."); waitForOnOff(false, true); waitForState(new HashSet<Integer>(Arrays.asList( BluetoothAdapter.STATE_OFF))); Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); Loading Loading @@ -1939,7 +1999,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mState = BluetoothAdapter.STATE_TURNING_ON; } waitForOnOff(true, false); waitForState(new HashSet<Integer>(Arrays.asList( BluetoothAdapter.STATE_ON))); if (mState == BluetoothAdapter.STATE_TURNING_ON) { bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); Loading @@ -1954,7 +2015,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF); boolean didDisableTimeout = !waitForOnOff(false, true); boolean didDisableTimeout = !waitForState(new HashSet<Integer>(Arrays.asList( BluetoothAdapter.STATE_OFF))); bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_OFF); Loading Loading @@ -2206,12 +2269,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } /** * if on is true, wait for state become ON * if off is true, wait for state become OFF * if both on and off are false, wait for state not ON */ private boolean waitForOnOff(boolean on, boolean off) { private boolean waitForState(Set<Integer> states) { int i = 0; while (i < 10) { try { Loading @@ -2219,33 +2277,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mBluetooth == null) { break; } if (on) { if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) { return true; } } else if (off) { if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) { if (states.contains(mBluetooth.getState())) { return true; } } else { if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) { return true; } } } catch (RemoteException e) { Slog.e(TAG, "getState()", e); break; } finally { mBluetoothLock.readLock().unlock(); } if (on || off) { SystemClock.sleep(300); } else { SystemClock.sleep(50); } i++; } Slog.e(TAG, "waitForOnOff time out"); Slog.e(TAG, "waitForState " + states + " time out"); return false; } Loading Loading @@ -2306,7 +2350,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.getPackageName(), false); handleDisable(); waitForOnOff(false, true); waitForState(new HashSet<Integer>(Arrays.asList(BluetoothAdapter.STATE_OFF))); sendBluetoothServiceDownCallback(); Loading Loading @@ -2468,6 +2512,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return "USER_SWITCH"; case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING: return "RESTORE_USER_SETTING"; case BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET: return "FACTORY_RESET"; case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED: default: return "UNKNOWN[" + reason + "]"; } Loading Loading
core/java/android/bluetooth/BluetoothAdapter.java +4 −2 Original line number Diff line number Diff line Loading @@ -1195,9 +1195,11 @@ public final class BluetoothAdapter { public boolean factoryReset() { try { mServiceLock.readLock().lock(); if (mService != null) { return mService.factoryReset(); if (mService != null && mService.factoryReset() && mManagerService != null && mManagerService.onFactoryReset()) { return true; } Log.e(TAG, "factoryReset(): Setting persist.bluetooth.factoryreset to retry later"); SystemProperties.set("persist.bluetooth.factoryreset", "true"); } catch (RemoteException e) { Log.e(TAG, "", e); Loading
core/proto/android/bluetooth/enums.proto +1 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ enum EnableDisableReasonEnum { ENABLE_DISABLE_REASON_CRASH = 7; ENABLE_DISABLE_REASON_USER_SWITCH = 8; ENABLE_DISABLE_REASON_RESTORE_USER_SETTING = 9; ENABLE_DISABLE_REASON_FACTORY_RESET = 10; } enum DirectionEnum { Loading
services/core/java/com/android/server/BluetoothManagerService.java +80 −34 Original line number Diff line number Diff line Loading @@ -73,11 +73,14 @@ import com.android.server.pm.UserRestrictionsUtils; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantReadWriteLock; Loading Loading @@ -257,6 +260,47 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } }; public boolean onFactoryReset() { // Wait for stable state if bluetooth is temporary state. int state = getState(); if (state == BluetoothAdapter.STATE_BLE_TURNING_ON || state == BluetoothAdapter.STATE_TURNING_ON || state == BluetoothAdapter.STATE_TURNING_OFF) { if (!waitForState(new HashSet<Integer>(Arrays.asList(BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_ON)))) { return false; } } // Clear registered LE apps to force shut-off Bluetooth clearBleApps(); state = getState(); try { mBluetoothLock.readLock().lock(); if (mBluetooth == null) { return false; } if (state == BluetoothAdapter.STATE_BLE_ON) { addActiveLog( BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET, mContext.getPackageName(), false); mBluetooth.onBrEdrDown(); return true; } else if (state == BluetoothAdapter.STATE_ON) { addActiveLog( BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET, mContext.getPackageName(), false); mBluetooth.disable(); return true; } } catch (RemoteException e) { Slog.e(TAG, "Unable to shutdown Bluetooth", e); } finally { mBluetoothLock.readLock().unlock(); } return false; } private final ContentObserver mAirplaneModeObserver = new ContentObserver(null) { @Override public void onChange(boolean unused) { Loading Loading @@ -1627,7 +1671,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // the previous Bluetooth process has exited. The // waiting period has three components: // (a) Wait until the local state is STATE_OFF. This // is accomplished by "waitForOnOff(false, true)". // is accomplished by // "waitForState(new HashSet<Integer>( // Arrays.asList(BluetoothAdapter.STATE_OFF)))". // (b) Wait until the STATE_OFF state is updated to // all components. // (c) Wait until the Bluetooth process exits, and Loading @@ -1637,7 +1683,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // message. On slower devices, that delay needs to be // on the order of (2 * SERVICE_RESTART_TIME_MS). // waitForOnOff(false, true); waitForState(new HashSet<Integer>(Arrays.asList( BluetoothAdapter.STATE_OFF))); Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); Loading @@ -1650,10 +1697,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } mHandler.removeMessages(MESSAGE_RESTART_BLUETOOTH_SERVICE); if (mEnable && mBluetooth != null) { waitForOnOff(true, false); waitForState(new HashSet<Integer>(Arrays.asList( BluetoothAdapter.STATE_ON))); mEnable = false; handleDisable(); waitForOnOff(false, false); waitForState(new HashSet<Integer>(Arrays.asList(BluetoothAdapter.STATE_OFF, BluetoothAdapter.STATE_TURNING_ON, BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_BLE_TURNING_ON, BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_BLE_TURNING_OFF))); } else { mEnable = false; handleDisable(); Loading Loading @@ -1782,9 +1835,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (!mEnable) { waitForOnOff(true, false); waitForState(new HashSet<Integer>(Arrays.asList( BluetoothAdapter.STATE_ON))); handleDisable(); waitForOnOff(false, false); waitForState(new HashSet<Integer>(Arrays.asList(BluetoothAdapter.STATE_OFF, BluetoothAdapter.STATE_TURNING_ON, BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_BLE_TURNING_ON, BluetoothAdapter.STATE_BLE_ON, BluetoothAdapter.STATE_BLE_TURNING_OFF))); } break; } Loading Loading @@ -1816,7 +1875,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { == BluetoothAdapter.STATE_OFF)) { if (mEnable) { Slog.d(TAG, "Entering STATE_OFF but mEnabled is true; restarting."); waitForOnOff(false, true); waitForState(new HashSet<Integer>(Arrays.asList( BluetoothAdapter.STATE_OFF))); Message restartMsg = mHandler.obtainMessage(MESSAGE_RESTART_BLUETOOTH_SERVICE); mHandler.sendMessageDelayed(restartMsg, 2 * SERVICE_RESTART_TIME_MS); Loading Loading @@ -1939,7 +1999,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mState = BluetoothAdapter.STATE_TURNING_ON; } waitForOnOff(true, false); waitForState(new HashSet<Integer>(Arrays.asList( BluetoothAdapter.STATE_ON))); if (mState == BluetoothAdapter.STATE_TURNING_ON) { bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON); Loading @@ -1954,7 +2015,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON, BluetoothAdapter.STATE_TURNING_OFF); boolean didDisableTimeout = !waitForOnOff(false, true); boolean didDisableTimeout = !waitForState(new HashSet<Integer>(Arrays.asList( BluetoothAdapter.STATE_OFF))); bluetoothStateChangeHandler(BluetoothAdapter.STATE_TURNING_OFF, BluetoothAdapter.STATE_OFF); Loading Loading @@ -2206,12 +2269,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } /** * if on is true, wait for state become ON * if off is true, wait for state become OFF * if both on and off are false, wait for state not ON */ private boolean waitForOnOff(boolean on, boolean off) { private boolean waitForState(Set<Integer> states) { int i = 0; while (i < 10) { try { Loading @@ -2219,33 +2277,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mBluetooth == null) { break; } if (on) { if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) { return true; } } else if (off) { if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) { if (states.contains(mBluetooth.getState())) { return true; } } else { if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) { return true; } } } catch (RemoteException e) { Slog.e(TAG, "getState()", e); break; } finally { mBluetoothLock.readLock().unlock(); } if (on || off) { SystemClock.sleep(300); } else { SystemClock.sleep(50); } i++; } Slog.e(TAG, "waitForOnOff time out"); Slog.e(TAG, "waitForState " + states + " time out"); return false; } Loading Loading @@ -2306,7 +2350,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.getPackageName(), false); handleDisable(); waitForOnOff(false, true); waitForState(new HashSet<Integer>(Arrays.asList(BluetoothAdapter.STATE_OFF))); sendBluetoothServiceDownCallback(); Loading Loading @@ -2468,6 +2512,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return "USER_SWITCH"; case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING: return "RESTORE_USER_SETTING"; case BluetoothProtoEnums.ENABLE_DISABLE_REASON_FACTORY_RESET: return "FACTORY_RESET"; case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED: default: return "UNKNOWN[" + reason + "]"; } Loading