android: fix ear detection when none are in use and either or both are worn

Music would start playing when neither are in ear, but even one is worn. This happens even when the music was not playing when they were removed (or, connected first)
This commit is contained in:
Kavish Devar
2025-05-10 20:11:20 +05:30
parent 9b96218fa9
commit 364a6f4b64
2 changed files with 30 additions and 34 deletions

View File

@@ -1468,39 +1468,36 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
) {
connectAudio(this@AirPodsService, device)
justEnabledA2dp = true
val bluetoothAdapter =
this@AirPodsService.getSystemService(
BluetoothManager::class.java
).adapter
bluetoothAdapter.getProfileProxy(
this@AirPodsService,
object : BluetoothProfile.ServiceListener {
override fun onServiceConnected(
profile: Int,
proxy: BluetoothProfile
) {
if (profile == BluetoothProfile.A2DP) {
val connectedDevices =
proxy.connectedDevices
if (connectedDevices.isNotEmpty()) {
MediaController.sendPlay()
}
val a2dpConnectionStateReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED") {
val state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_DISCONNECTED)
val previousState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_DISCONNECTED)
val device = intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)
Log.d("MediaController", "A2DP state changed: $previousState -> $state for device: ${device?.address}")
if (state == BluetoothProfile.STATE_CONNECTED &&
previousState != BluetoothProfile.STATE_CONNECTED &&
device?.address == this@AirPodsService.device?.address) {
Log.d("MediaController", "A2DP connected, sending play command")
MediaController.sendPlay()
MediaController.iPausedTheMedia = false
context.unregisterReceiver(this)
}
bluetoothAdapter.closeProfileProxy(
profile,
proxy
)
}
override fun onServiceDisconnected(
profile: Int
) {
}
},
BluetoothProfile.A2DP
)
}
}
val a2dpIntentFilter = IntentFilter("android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerReceiver(a2dpConnectionStateReceiver, a2dpIntentFilter, RECEIVER_EXPORTED)
} else {
registerReceiver(a2dpConnectionStateReceiver, a2dpIntentFilter)
}
} else if (newInEarData == listOf(false, false)) {
MediaController.sendPause(force = true)
disconnectAudio(this@AirPodsService, device)
}

View File

@@ -82,7 +82,6 @@ object MediaController {
if (configs != null && !iPausedTheMedia) {
Log.d("MediaController", "Seems like the user changed the state of media themselves, now I won't play until the ear detection pauses it.")
handler.postDelayed({
iPausedTheMedia = !audioManager.isMusicActive
userPlayedTheMedia = audioManager.isMusicActive
}, 7) // i have no idea why android sends an event a hundred times after the user does something.
}
@@ -98,9 +97,9 @@ object MediaController {
@Synchronized
fun sendPause(force: Boolean = false) {
Log.d("MediaController", "Sending pause with iPausedTheMedia: $iPausedTheMedia, userPlayedTheMedia: $userPlayedTheMedia")
if ((audioManager.isMusicActive && !userPlayedTheMedia) || force) {
iPausedTheMedia = true
Log.d("MediaController", "Sending pause with iPausedTheMedia: $iPausedTheMedia, userPlayedTheMedia: $userPlayedTheMedia, isMusicActive: ${audioManager.isMusicActive}, force: $force")
if ((audioManager.isMusicActive) && (!userPlayedTheMedia || force)) {
iPausedTheMedia = if (force) audioManager.isMusicActive else true
userPlayedTheMedia = false
audioManager.dispatchMediaKeyEvent(
KeyEvent(