mirror of
https://github.com/kavishdevar/librepods.git
synced 2026-03-15 10:42:29 +00:00
android: improve ble-based autoconnection
This commit is contained in:
@@ -213,6 +213,7 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
this@AirPodsService,
|
this@AirPodsService,
|
||||||
getSharedPreferences("settings", MODE_PRIVATE).getString("name", "AirPods Pro") ?: "AirPods"
|
getSharedPreferences("settings", MODE_PRIVATE).getString("name", "AirPods Pro") ?: "AirPods"
|
||||||
)
|
)
|
||||||
|
if (isConnectedLocally) return
|
||||||
val leftLevel = bleManager.getMostRecentStatus()?.leftBattery?: 0
|
val leftLevel = bleManager.getMostRecentStatus()?.leftBattery?: 0
|
||||||
val rightLevel = bleManager.getMostRecentStatus()?.rightBattery?: 0
|
val rightLevel = bleManager.getMostRecentStatus()?.rightBattery?: 0
|
||||||
val caseLevel = bleManager.getMostRecentStatus()?.caseBattery?: 0
|
val caseLevel = bleManager.getMostRecentStatus()?.caseBattery?: 0
|
||||||
@@ -243,24 +244,23 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onBatteryChanged(device: BLEManager.AirPodsStatus) {
|
override fun onBatteryChanged(device: BLEManager.AirPodsStatus) {
|
||||||
// if (!isConnectedLocally) {
|
if (isConnectedLocally) return
|
||||||
// val leftLevel = bleManager.getMostRecentStatus()?.leftBattery?: 0
|
val leftLevel = bleManager.getMostRecentStatus()?.leftBattery?: 0
|
||||||
// val rightLevel = bleManager.getMostRecentStatus()?.rightBattery?: 0
|
val rightLevel = bleManager.getMostRecentStatus()?.rightBattery?: 0
|
||||||
// val caseLevel = bleManager.getMostRecentStatus()?.caseBattery?: 0
|
val caseLevel = bleManager.getMostRecentStatus()?.caseBattery?: 0
|
||||||
// val leftCharging = bleManager.getMostRecentStatus()?.isLeftCharging
|
val leftCharging = bleManager.getMostRecentStatus()?.isLeftCharging
|
||||||
// val rightCharging = bleManager.getMostRecentStatus()?.isRightCharging
|
val rightCharging = bleManager.getMostRecentStatus()?.isRightCharging
|
||||||
// val caseCharging = bleManager.getMostRecentStatus()?.isCaseCharging
|
val caseCharging = bleManager.getMostRecentStatus()?.isCaseCharging
|
||||||
|
|
||||||
// batteryNotification.setBatteryDirect(
|
batteryNotification.setBatteryDirect(
|
||||||
// leftLevel = leftLevel,
|
leftLevel = leftLevel,
|
||||||
// leftCharging = leftCharging == true,
|
leftCharging = leftCharging == true,
|
||||||
// rightLevel = rightLevel,
|
rightLevel = rightLevel,
|
||||||
// rightCharging = rightCharging == true,
|
rightCharging = rightCharging == true,
|
||||||
// caseLevel = caseLevel,
|
caseLevel = caseLevel,
|
||||||
// caseCharging = caseCharging == true
|
caseCharging = caseCharging == true
|
||||||
// )
|
)
|
||||||
// updateBattery()
|
updateBattery()
|
||||||
// }
|
|
||||||
Log.d("AirPodsBLEService", "Battery changed")
|
Log.d("AirPodsBLEService", "Battery changed")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,6 +413,9 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
connectAudio(this@AirPodsService, device)
|
connectAudio(this@AirPodsService, device)
|
||||||
justEnabledA2dp = true
|
justEnabledA2dp = true
|
||||||
registerA2dpConnectionReceiver()
|
registerA2dpConnectionReceiver()
|
||||||
|
if (MediaController.getMusicActive()) {
|
||||||
|
MediaController.userPlayedTheMedia = true
|
||||||
|
}
|
||||||
} else if (newInEarData == listOf(false, false)) {
|
} else if (newInEarData == listOf(false, false)) {
|
||||||
MediaController.sendPause(force = true)
|
MediaController.sendPause(force = true)
|
||||||
if (config.disconnectWhenNotWearing) {
|
if (config.disconnectWhenNotWearing) {
|
||||||
@@ -434,7 +437,6 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
|
|
||||||
if (newInEarData.sorted() != inEarData.sorted()) {
|
if (newInEarData.sorted() != inEarData.sorted()) {
|
||||||
inEarData = newInEarData
|
inEarData = newInEarData
|
||||||
|
|
||||||
if (inEar == true) {
|
if (inEar == true) {
|
||||||
if (!justEnabledA2dp) {
|
if (!justEnabledA2dp) {
|
||||||
justEnabledA2dp = false
|
justEnabledA2dp = false
|
||||||
@@ -1674,8 +1676,19 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
@RequiresApi(Build.VERSION_CODES.R)
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
fun takeOver(takingOverFor: String) {
|
fun takeOver(takingOverFor: String) {
|
||||||
if (isConnectedLocally || !CrossDevice.isAvailable || bleManager.getMostRecentStatus()?.isLeftInEar == true || bleManager.getMostRecentStatus()?.isRightInEar == true) {
|
if (isConnectedLocally) {
|
||||||
Log.d("AirPodsService", "Already connected or not available for takeover")
|
Log.d("AirPodsService", "Already connected locally, skipping")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CrossDevice.isAvailable) {
|
||||||
|
Log.d("AirPodsService", "CrossDevice is available, continuing")
|
||||||
|
}
|
||||||
|
else if (bleManager.getMostRecentStatus()?.isLeftInEar == true || bleManager.getMostRecentStatus()?.isRightInEar == true) {
|
||||||
|
Log.d("AirPodsService", "At least one AirPod is in ear, continuing")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log.d("AirPodsService", "CrossDevice not available and AirPods not in ear, skipping")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1684,6 +1697,7 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
"call" -> config.takeoverWhenRingingCall
|
"call" -> config.takeoverWhenRingingCall
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shouldTakeOverPState) {
|
if (!shouldTakeOverPState) {
|
||||||
Log.d("AirPodsService", "Not taking over audio, phone state takeover disabled")
|
Log.d("AirPodsService", "Not taking over audio, phone state takeover disabled")
|
||||||
return
|
return
|
||||||
@@ -1704,6 +1718,12 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (takingOverFor == "music") {
|
||||||
|
Log.d("AirPodsService", "Pausing music so that it doesn't play through speakers")
|
||||||
|
MediaController.pausedForCrossDevice = true
|
||||||
|
MediaController.sendPause(true)
|
||||||
|
}
|
||||||
|
|
||||||
Log.d("AirPodsService", "Taking over audio")
|
Log.d("AirPodsService", "Taking over audio")
|
||||||
CrossDevice.sendRemotePacket(CrossDevicePackets.REQUEST_DISCONNECT.packet)
|
CrossDevice.sendRemotePacket(CrossDevicePackets.REQUEST_DISCONNECT.packet)
|
||||||
Log.d("AirPodsService", macAddress)
|
Log.d("AirPodsService", macAddress)
|
||||||
@@ -1810,7 +1830,7 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
aacpManager.sendSetFeatureFlagsPacket()
|
aacpManager.sendSetFeatureFlagsPacket()
|
||||||
aacpManager.sendNotificationRequest()
|
aacpManager.sendNotificationRequest()
|
||||||
Log.d("AirPodsService", "Requesting proximity keys")
|
Log.d("AirPodsService", "Requesting proximity keys")
|
||||||
aacpManager.sendRequestProximityKeys(AACPManager.Companion.ProximityKeyType.IRK.value)
|
aacpManager.sendRequestProximityKeys((AACPManager.Companion.ProximityKeyType.IRK.value + AACPManager.Companion.ProximityKeyType.ENC_KEY.value).toByte())
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
aacpManager.sendPacket(aacpManager.createHandshakePacket())
|
aacpManager.sendPacket(aacpManager.createHandshakePacket())
|
||||||
delay(200)
|
delay(200)
|
||||||
@@ -1818,7 +1838,7 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
delay(200)
|
delay(200)
|
||||||
aacpManager.sendNotificationRequest()
|
aacpManager.sendNotificationRequest()
|
||||||
delay(200)
|
delay(200)
|
||||||
aacpManager.sendRequestProximityKeys(AACPManager.Companion.ProximityKeyType.IRK.value)
|
aacpManager.sendRequestProximityKeys((AACPManager.Companion.ProximityKeyType.IRK.value+AACPManager.Companion.ProximityKeyType.ENC_KEY.value).toByte())
|
||||||
startHeadTracking()
|
startHeadTracking()
|
||||||
Handler(Looper.getMainLooper()).postDelayed({
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
aacpManager.sendPacket(aacpManager.createHandshakePacket())
|
aacpManager.sendPacket(aacpManager.createHandshakePacket())
|
||||||
|
|||||||
@@ -336,14 +336,16 @@ class BLEManager(private val context: Context) {
|
|||||||
val isLeftInEar = if (xorFactor) (status and 0x08) != 0 else (status and 0x02) != 0
|
val isLeftInEar = if (xorFactor) (status and 0x08) != 0 else (status and 0x02) != 0
|
||||||
val isRightInEar = if (xorFactor) (status and 0x02) != 0 else (status and 0x08) != 0
|
val isRightInEar = if (xorFactor) (status and 0x02) != 0 else (status and 0x08) != 0
|
||||||
|
|
||||||
val leftBatteryNibble = if (xorFactor) (podsBattery shr 4) and 0x0F else podsBattery and 0x0F
|
val isFlipped = !primaryLeft
|
||||||
val rightBatteryNibble = if (xorFactor) podsBattery and 0x0F else (podsBattery shr 4) and 0x0F
|
|
||||||
|
|
||||||
val caseBattery = (flagsCase shr 4) and 0x0F
|
val leftBatteryNibble = if (isFlipped) (podsBattery shr 4) and 0x0F else podsBattery and 0x0F
|
||||||
val flags = flagsCase and 0x0F
|
val rightBatteryNibble = if (isFlipped) podsBattery and 0x0F else (podsBattery shr 4) and 0x0F
|
||||||
|
|
||||||
val isRightCharging = if (xorFactor) (flags and 0x02) != 0 else (flags and 0x01) != 0
|
val caseBattery = flagsCase and 0x0F
|
||||||
val isLeftCharging = if (xorFactor) (flags and 0x01) != 0 else (flags and 0x02) != 0
|
val flags = (flagsCase shr 4) and 0x0F
|
||||||
|
|
||||||
|
val isLeftCharging = if (isFlipped) (flags and 0x02) != 0 else (flags and 0x01) != 0
|
||||||
|
val isRightCharging = if (isFlipped) (flags and 0x01) != 0 else (flags and 0x02) != 0
|
||||||
val isCaseCharging = (flags and 0x04) != 0
|
val isCaseCharging = (flags and 0x04) != 0
|
||||||
|
|
||||||
val lidOpen = ((lid shr 3) and 0x01) == 0
|
val lidOpen = ((lid shr 3) and 0x01) == 0
|
||||||
|
|||||||
@@ -88,11 +88,8 @@ object MediaController {
|
|||||||
userPlayedTheMedia = audioManager.isMusicActive
|
userPlayedTheMedia = audioManager.isMusicActive
|
||||||
}, 7) // i have no idea why android sends an event a hundred times after the user does something.
|
}, 7) // i have no idea why android sends an event a hundred times after the user does something.
|
||||||
}
|
}
|
||||||
Log.d("MediaController", "pausedforcrossdevice: $pausedForCrossDevice Ear detection status: ${ServiceManager.getService()?.earDetectionNotification?.status}, music active: ${audioManager.isMusicActive} and cross device available: ${CrossDevice.isAvailable}")
|
Log.d("MediaController", "pausedforcrossdevice: $pausedForCrossDevice")
|
||||||
if (!pausedForCrossDevice && audioManager.isMusicActive) {
|
if (!pausedForCrossDevice && audioManager.isMusicActive) {
|
||||||
Log.d("MediaController", "Pausing for cross device and taking over.")
|
|
||||||
sendPause(true)
|
|
||||||
pausedForCrossDevice = true
|
|
||||||
ServiceManager.getService()?.takeOver("music")
|
ServiceManager.getService()?.takeOver("music")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,6 +140,14 @@ object MediaController {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (!audioManager.isMusicActive) {
|
||||||
|
Log.d("MediaController", "Setting iPausedTheMedia to false")
|
||||||
|
iPausedTheMedia = false
|
||||||
|
}
|
||||||
|
if (pausedForCrossDevice) {
|
||||||
|
Log.d("MediaController", "Setting pausedForCrossDevice to false")
|
||||||
|
pausedForCrossDevice = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
|||||||
Reference in New Issue
Block a user