From 86a7fe21b195ef34a5e41236674a043fda9b7620 Mon Sep 17 00:00:00 2001 From: Ugo Yu Date: Wed, 2 Jun 2021 14:30:37 +0800 Subject: [PATCH] Broadcast Bluetooth state to OFF properly In current logic, we broadcast Bluetooth state OFF at BLE_ON state. However, if Bluetooth gets crashed, we won't have the chance to send OFF intent as we never get to BLE_ON. This change makes the BluetoothManagerService skips the OFF intent only if the previous state is a BLE state. Bug: 189271317 Test: manual Change-Id: I3936766ab8bdd45d59550dacb64bdc0323bb424d Merged-In: I3936766ab8bdd45d59550dacb64bdc0323bb424d --- .../server/BluetoothManagerService.java | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 992ef2657a655..8dcd9410a6b28 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -2452,6 +2452,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM); } + private boolean isBleState(int state) { + switch (state) { + case BluetoothAdapter.STATE_BLE_ON: + case BluetoothAdapter.STATE_BLE_TURNING_ON: + case BluetoothAdapter.STATE_BLE_TURNING_OFF: + return true; + } + return false; + } + private void bluetoothStateChangeHandler(int prevState, int newState) { boolean isStandardBroadcast = true; if (prevState == newState) { // No change. Nothing to do. @@ -2470,8 +2480,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { sendBluetoothServiceDownCallback(); unbindAndFinish(); sendBleStateChanged(prevState, newState); - // Don't broadcast as it has already been broadcast before - isStandardBroadcast = false; + + /* Currently, the OFF intent is broadcasted externally only when we transition + * from TURNING_OFF to BLE_ON state. So if the previous state is a BLE state, + * we are guaranteed that the OFF intent has been broadcasted earlier and we + * can safely skip it. + * Conversely, if the previous state is not a BLE state, it indicates that some + * sort of crash has occurred, moving us directly to STATE_OFF without ever + * passing through BLE_ON. We should broadcast the OFF intent in this case. */ + isStandardBroadcast = !isBleState(prevState); } else if (!intermediate_off) { // connect to GattService @@ -2524,6 +2541,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // Show prevState of BLE_ON as OFF to standard users prevState = BluetoothAdapter.STATE_OFF; } + if (DBG) { + Slog.d(TAG, + "Sending State Change: " + BluetoothAdapter.nameForState(prevState) + " > " + + BluetoothAdapter.nameForState(newState)); + } Intent intent = new Intent(BluetoothAdapter.ACTION_STATE_CHANGED); intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);