Device: Show a Connect button when AirPods are not connected to this phone#489
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
When your AirPods are paired to multiple phones and audio is currently playing on a different phone, this phone can still see the AirPods nearby but can't access their settings. Until now the Device Settings screen just showed the basic info card and an empty body — confusing, with no explanation.
Now, in that state, a "Not connected" card appears below the device info with a Connect button. Tapping it asks Android to nudge a connection to the AirPods. If that's not available on your phone, the button instead opens the system Bluetooth settings so you can connect manually. Once the connection goes through, the card disappears and all AAP settings and controls become available as normal.
Technical Context
device.ble != null && !device.isAapConnected && device.address != null: BLE advertisements being live means the AirPods are actually nearby (the existingBlePodMonitor~20s eviction handles freshness). No AAP state (aap == null) means there's no BR/EDR classic socket — this automatically excludes the cold-start synthesis window whereaap != nullbut state isCONNECTING/HANDSHAKING. Requiring a bonded address excludes anonymous unpaired pods.BluetoothManager2.nudgeConnection()uses the hiddenBluetoothHeadset.connect()reflection API. On phones where this is blocked (missingMODIFY_PHONE_STATE),isNudgeAvailableflips tofalseand the button label/behavior switches to opening Bluetooth settings. All exception paths (SecurityExceptionfrom missingBLUETOOTH_CONNECTon API 31+, null adapter, reflection throws) fall through to the same settings-intent fallback so the button can never crash.BluetoothManager2.nudgeConnection(): the existing implementation discardedMethod.invoke()'s return value and always reported success.BluetoothHeadset.connect()actually returns a Boolean indicating whether the request was accepted; we now propagate it. This makesAutoConnect's log message accurate and makes the new "did the nudge get accepted?" check in the VM actually meaningful.forceConnect()usesMutableStateFlow<Boolean>.compareAndSetas a one-in-flight guard, and the button is disabled whileisForceConnectingis true — rapid double-taps can't spawn parallel connect attempts or duplicate settings-intent launches.DeviceSettingsViewModel.forceConnect()— all the exception containment and fallback logic lives there. The 7 new unit tests inDeviceSettingsViewModelTestcover each branch, including aCompletableDeferred-gated test that verifies the in-flight guard actually blocks a concurrent call.