mirror of
https://github.com/kavishdevar/librepods.git
synced 2026-05-31 05:22:41 +00:00
android: fix rework ATT connection
This commit is contained in:
@@ -1143,7 +1143,7 @@ class AACPManager {
|
||||
)
|
||||
}
|
||||
|
||||
val socket = BluetoothConnectionManager.getCurrentSocket() ?: return false
|
||||
val socket = BluetoothConnectionManager.getAACPSocket() ?: return false
|
||||
|
||||
if (socket.isConnected) {
|
||||
socket.outputStream?.write(packet)
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package me.kavishdevar.librepods.bluetooth
|
||||
|
||||
import android.util.Log
|
||||
|
||||
private const val TAG = "ATTManagerv2"
|
||||
|
||||
// the random disconnects were because of ATT, apparently. seems like we will have to accept no notifications for external changes (mainly amplification in hearing aid)
|
||||
object ATTManagerv2 {
|
||||
fun readCharacteristic(handle: ATTHandles): ByteArray? {
|
||||
val socket = BluetoothConnectionManager.getATTSocket()?: return null
|
||||
try {
|
||||
// socket.connect()
|
||||
val input = socket.inputStream
|
||||
val output = socket.outputStream
|
||||
|
||||
val pdu = byteArrayOf(0x0A, handle.value.toByte(), 0x00)
|
||||
output.write(pdu)
|
||||
output.flush()
|
||||
Log.d(TAG, "writeRaw: ${pdu.joinToString(" ") { String.format("%02X", it) }}")
|
||||
val buffer = ByteArray(512)
|
||||
val len = input.read(buffer)
|
||||
if (len == -1) {
|
||||
throw IllegalStateException("End of stream reached")
|
||||
}
|
||||
val data = buffer.copyOfRange(0, len)
|
||||
// socket.close()
|
||||
if (data[0] != 0x0B.toByte()) {
|
||||
throw IllegalStateException("Invalid response: ${data.joinToString(" ") { String.format("%02X", it) }}")
|
||||
}
|
||||
Log.d(TAG, "readPDU: ${data.joinToString(" ") { String.format("%02X", it) }}")
|
||||
return data.copyOfRange(1, data.size)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error reading characteristic: ${e.message}")
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
fun writeCharacteristic(handle: ATTHandles, data: ByteArray) {
|
||||
val socket = BluetoothConnectionManager.getATTSocket()?: return
|
||||
try {
|
||||
// socket.connect()
|
||||
val input = socket.inputStream
|
||||
val output = socket.outputStream
|
||||
val pdu = byteArrayOf(0x12, handle.value.toByte(), 0x00) + data // 0x0 because LE
|
||||
output.write(pdu)
|
||||
output.flush()
|
||||
Log.d(TAG, "writeRaw: ${pdu.joinToString(" ") { String.format("%02X", it) }}")
|
||||
val buffer = ByteArray(512)
|
||||
val len = input.read(buffer)
|
||||
if (len == -1) {
|
||||
throw IllegalStateException("End of stream reached")
|
||||
}
|
||||
val resp = buffer.copyOfRange(0, len)
|
||||
// socket.close()
|
||||
if (!resp.contentEquals(byteArrayOf(0x13))) {
|
||||
throw IllegalStateException("Invalid response: ${resp.joinToString(" ") { String.format("%02X", it) }}")
|
||||
}
|
||||
Log.d(TAG, "readPDU: ${resp.joinToString(" ") { String.format("%02X", it) }}")
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Error writing characteristic: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,23 +18,22 @@
|
||||
|
||||
package me.kavishdevar.librepods.bluetooth
|
||||
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import android.bluetooth.BluetoothSocket
|
||||
import android.util.Log
|
||||
|
||||
object BluetoothConnectionManager {
|
||||
private const val TAG = "BluetoothConnectionManager"
|
||||
private var aacpSocket: BluetoothSocket? = null
|
||||
private var attSocket: BluetoothSocket? = null
|
||||
|
||||
private var currentSocket: BluetoothSocket? = null
|
||||
private var currentDevice: BluetoothDevice? = null
|
||||
|
||||
fun setCurrentConnection(socket: BluetoothSocket, device: BluetoothDevice) {
|
||||
currentSocket = socket
|
||||
currentDevice = device
|
||||
Log.d(TAG, "Current connection set to device: ${device.address}")
|
||||
fun setCurrentConnection(aacpSocket: BluetoothSocket?, attSocket: BluetoothSocket?) {
|
||||
BluetoothConnectionManager.aacpSocket = aacpSocket
|
||||
BluetoothConnectionManager.attSocket = attSocket
|
||||
}
|
||||
|
||||
fun getCurrentSocket(): BluetoothSocket? {
|
||||
return currentSocket
|
||||
fun getAACPSocket(): BluetoothSocket? {
|
||||
return aacpSocket
|
||||
}
|
||||
|
||||
fun getATTSocket(): BluetoothSocket? {
|
||||
return attSocket
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import me.kavishdevar.librepods.bluetooth.ATTHandles
|
||||
import me.kavishdevar.librepods.bluetooth.ATTManager
|
||||
import me.kavishdevar.librepods.bluetooth.ATTManagerv2
|
||||
import java.io.IOException
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
@@ -138,7 +139,7 @@ fun parseHearingAidSettingsResponse(data: ByteArray): HearingAidSettings? {
|
||||
}
|
||||
|
||||
fun sendHearingAidSettings(
|
||||
attManager: ATTManager,
|
||||
// attManager: ATTManager,
|
||||
hearingAidSettings: HearingAidSettings,
|
||||
debounceJob: MutableState<Job?>
|
||||
) {
|
||||
@@ -146,7 +147,7 @@ fun sendHearingAidSettings(
|
||||
debounceJob.value = CoroutineScope(Dispatchers.IO).launch {
|
||||
delay(100)
|
||||
try {
|
||||
val currentData = attManager.read(ATTHandles.HEARING_AID)
|
||||
val currentData = ATTManagerv2.readCharacteristic(ATTHandles.HEARING_AID)?: return@launch
|
||||
Log.d(TAG, "Current data before update: ${currentData.joinToString(" ") { String.format("%02X", it) }}")
|
||||
if (currentData.size < 104) {
|
||||
Log.w(TAG, "Current data size ${currentData.size} too small, cannot send settings")
|
||||
@@ -184,7 +185,7 @@ fun sendHearingAidSettings(
|
||||
|
||||
Log.d(TAG, "Sending updated settings: ${currentData.joinToString(" ") { String.format("%02X", it) }}")
|
||||
|
||||
attManager.write(ATTHandles.HEARING_AID, currentData)
|
||||
ATTManagerv2.writeCharacteristic(ATTHandles.HEARING_AID, currentData)
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
@@ -56,12 +56,14 @@ import me.kavishdevar.librepods.presentation.components.StyledToggle
|
||||
import me.kavishdevar.librepods.services.ServiceManager
|
||||
import me.kavishdevar.librepods.bluetooth.AACPManager
|
||||
import me.kavishdevar.librepods.bluetooth.ATTHandles
|
||||
import me.kavishdevar.librepods.bluetooth.ATTManagerv2
|
||||
import me.kavishdevar.librepods.data.HearingAidSettings
|
||||
import me.kavishdevar.librepods.data.parseHearingAidSettingsResponse
|
||||
import me.kavishdevar.librepods.data.sendHearingAidSettings
|
||||
import me.kavishdevar.librepods.presentation.viewmodel.AirPodsViewModel
|
||||
import java.io.IOException
|
||||
import kotlin.io.encoding.ExperimentalEncodingApi
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
private var debounceJob: MutableState<Job?> = mutableStateOf(null)
|
||||
private const val TAG = "HearingAidAdjustments"
|
||||
@@ -74,7 +76,7 @@ fun HearingAidAdjustmentsScreen(viewModel: AirPodsViewModel) {
|
||||
isSystemInDarkTheme()
|
||||
val verticalScrollState = rememberScrollState()
|
||||
val hazeState = remember { HazeState() }
|
||||
val attManager = ServiceManager.getService()?.attManager ?: throw IllegalStateException("ATTManager not available")
|
||||
// val attManager = ServiceManager.getService()?.attManager ?: throw IllegalStateException("ATTManager not available")
|
||||
|
||||
val state by viewModel.uiState.collectAsState()
|
||||
|
||||
@@ -175,20 +177,20 @@ fun HearingAidAdjustmentsScreen(viewModel: AirPodsViewModel) {
|
||||
ownVoiceAmplification = ownVoiceAmplification.floatValue
|
||||
)
|
||||
Log.d(TAG, "Updated settings: ${hearingAidSettings.value}")
|
||||
sendHearingAidSettings(attManager, hearingAidSettings.value, debounceJob)
|
||||
sendHearingAidSettings(hearingAidSettings.value, debounceJob)
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
Log.d(TAG, "Connecting to ATT...")
|
||||
try {
|
||||
attManager.enableNotifications(ATTHandles.HEARING_AID)
|
||||
attManager.registerListener(ATTHandles.HEARING_AID, hearingAidATTListener)
|
||||
// attManager.enableNotifications(ATTHandles.HEARING_AID)
|
||||
// attManager.registerListener(ATTHandles.HEARING_AID, hearingAidATTListener)
|
||||
|
||||
var parsedSettings: HearingAidSettings? = null
|
||||
for (attempt in 1..3) {
|
||||
initialReadAttempts.intValue = attempt
|
||||
try {
|
||||
val data = attManager.read(ATTHandles.HEARING_AID)
|
||||
val data = ATTManagerv2.readCharacteristic(ATTHandles.HEARING_AID) ?: return@LaunchedEffect
|
||||
parsedSettings = parseHearingAidSettingsResponse(data = data)
|
||||
if (parsedSettings != null) {
|
||||
Log.d(TAG, "Parsed settings on attempt $attempt")
|
||||
@@ -199,7 +201,7 @@ fun HearingAidAdjustmentsScreen(viewModel: AirPodsViewModel) {
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Read attempt $attempt failed: ${e.message}")
|
||||
}
|
||||
delay(200)
|
||||
delay(200.milliseconds)
|
||||
}
|
||||
|
||||
if (parsedSettings != null) {
|
||||
|
||||
@@ -62,6 +62,7 @@ import me.kavishdevar.librepods.R
|
||||
import me.kavishdevar.librepods.presentation.components.StyledScaffold
|
||||
import me.kavishdevar.librepods.services.ServiceManager
|
||||
import me.kavishdevar.librepods.bluetooth.ATTHandles
|
||||
import me.kavishdevar.librepods.bluetooth.ATTManagerv2
|
||||
import me.kavishdevar.librepods.data.HearingAidSettings
|
||||
import me.kavishdevar.librepods.data.parseHearingAidSettingsResponse
|
||||
import me.kavishdevar.librepods.data.sendHearingAidSettings
|
||||
@@ -73,17 +74,17 @@ private const val TAG = "HearingAidAdjustments"
|
||||
@Composable
|
||||
fun UpdateHearingTestScreen() {
|
||||
val verticalScrollState = rememberScrollState()
|
||||
val attManager = ServiceManager.getService()?.attManager
|
||||
if (attManager == null) {
|
||||
Text(
|
||||
text = stringResource(R.string.att_manager_is_null_try_reconnecting),
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(16.dp),
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
return
|
||||
}
|
||||
// val attManager = ServiceManager.getService()?.attManager
|
||||
// if (attManager == null) {
|
||||
// Text(
|
||||
// text = stringResource(R.string.att_manager_is_null_try_reconnecting),
|
||||
// modifier = Modifier
|
||||
// .fillMaxSize()
|
||||
// .padding(16.dp),
|
||||
// textAlign = TextAlign.Center
|
||||
// )
|
||||
// return
|
||||
// }
|
||||
|
||||
val backdrop = rememberLayerBackdrop()
|
||||
StyledScaffold(
|
||||
@@ -167,11 +168,11 @@ fun UpdateHearingTestScreen() {
|
||||
}
|
||||
|
||||
|
||||
DisposableEffect(Unit) {
|
||||
onDispose {
|
||||
attManager.unregisterListener(ATTHandles.HEARING_AID, hearingAidATTListener)
|
||||
}
|
||||
}
|
||||
// DisposableEffect(Unit) {
|
||||
// onDispose {
|
||||
// attManager.unregisterListener(ATTHandles.HEARING_AID, hearingAidATTListener)
|
||||
// }
|
||||
// }
|
||||
|
||||
LaunchedEffect(
|
||||
leftEQ.value,
|
||||
@@ -214,20 +215,20 @@ fun UpdateHearingTestScreen() {
|
||||
ownVoiceAmplification = ownVoiceAmplification.floatValue
|
||||
)
|
||||
Log.d(TAG, "Updated settings: ${hearingAidSettings.value}")
|
||||
sendHearingAidSettings(attManager, hearingAidSettings.value, debounceJob)
|
||||
sendHearingAidSettings(hearingAidSettings.value, debounceJob)
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
Log.d(TAG, "Connecting to ATT...")
|
||||
try {
|
||||
attManager.enableNotifications(ATTHandles.HEARING_AID)
|
||||
attManager.registerListener(ATTHandles.HEARING_AID, hearingAidATTListener)
|
||||
// attManager.enableNotifications(ATTHandles.HEARING_AID)
|
||||
// attManager.registerListener(ATTHandles.HEARING_AID, hearingAidATTListener)
|
||||
|
||||
var parsedSettings: HearingAidSettings? = null
|
||||
for (attempt in 1..3) {
|
||||
initialReadAttempts.intValue = attempt
|
||||
try {
|
||||
val data = attManager.read(ATTHandles.HEARING_AID)
|
||||
val data = ATTManagerv2.readCharacteristic(ATTHandles.HEARING_AID)?: byteArrayOf()
|
||||
parsedSettings = parseHearingAidSettingsResponse(data = data)
|
||||
if (parsedSettings != null) {
|
||||
Log.d(TAG, "Parsed settings on attempt $attempt")
|
||||
|
||||
@@ -40,6 +40,7 @@ import me.kavishdevar.librepods.billing.BillingManager
|
||||
import me.kavishdevar.librepods.bluetooth.AACPManager
|
||||
import me.kavishdevar.librepods.bluetooth.AACPManager.Companion.ControlCommandIdentifiers
|
||||
import me.kavishdevar.librepods.bluetooth.ATTHandles
|
||||
import me.kavishdevar.librepods.bluetooth.ATTManagerv2
|
||||
import me.kavishdevar.librepods.data.AirPodsInstance
|
||||
import me.kavishdevar.librepods.data.AirPodsModels
|
||||
import me.kavishdevar.librepods.data.AirPodsNotifications
|
||||
@@ -51,6 +52,7 @@ import me.kavishdevar.librepods.data.ControlCommandRepository
|
||||
import me.kavishdevar.librepods.data.StemAction
|
||||
import me.kavishdevar.librepods.data.XposedRemotePrefProvider
|
||||
import me.kavishdevar.librepods.services.AirPodsService
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
@Suppress("ArrayInDataClass")
|
||||
data class AirPodsUiState(
|
||||
@@ -530,13 +532,7 @@ class AirPodsViewModel(
|
||||
}
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
if (service.attManager?.socket?.isConnected != true) {
|
||||
service.attManager?.connect()
|
||||
}
|
||||
while (service.attManager?.socket?.isConnected != true) {
|
||||
delay(250)
|
||||
}
|
||||
service.attManager?.write(handle, value)
|
||||
ATTManagerv2.writeCharacteristic(handle, value)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
@@ -545,19 +541,14 @@ class AirPodsViewModel(
|
||||
|
||||
fun refreshATT() {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val loudSoundReduction =
|
||||
runCatching { service.attManager?.read(ATTHandles.LOUD_SOUND_REDUCTION) }.getOrNull()
|
||||
val loudSoundReductionEnabled = loudSoundReduction?.size?.let {
|
||||
if (it > 0) {
|
||||
val loudSoundReduction = ATTManagerv2.readCharacteristic(ATTHandles.LOUD_SOUND_REDUCTION) ?: byteArrayOf()
|
||||
val loudSoundReductionEnabled = if (loudSoundReduction.isNotEmpty()) {
|
||||
loudSoundReduction[0].toInt() == 1
|
||||
} else false
|
||||
}
|
||||
val transparencyData =
|
||||
runCatching { service.attManager?.read(ATTHandles.TRANSPARENCY) }.getOrNull()?: byteArrayOf()
|
||||
val hearingAidData =
|
||||
runCatching { service.attManager?.read(ATTHandles.HEARING_AID) }.getOrNull()?: byteArrayOf()
|
||||
} else false
|
||||
val transparencyData = ATTManagerv2.readCharacteristic(ATTHandles.TRANSPARENCY)?: byteArrayOf()
|
||||
val hearingAidData = ATTManagerv2.readCharacteristic(ATTHandles.HEARING_AID)?:byteArrayOf()
|
||||
_uiState.value = _uiState.value.copy(
|
||||
loudSoundReductionEnabled = loudSoundReductionEnabled == true,
|
||||
loudSoundReductionEnabled = loudSoundReductionEnabled,
|
||||
transparencyData = transparencyData,
|
||||
hearingAidData = hearingAidData
|
||||
)
|
||||
@@ -566,19 +557,9 @@ class AirPodsViewModel(
|
||||
|
||||
fun observeATT() {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
if (service.attManager?.socket?.isConnected != true) {
|
||||
service.attManager?.connect()
|
||||
}
|
||||
while (service.attManager?.socket?.isConnected != true) {
|
||||
delay(1000)
|
||||
}
|
||||
service.attManager?.enableNotifications(ATTHandles.LOUD_SOUND_REDUCTION)
|
||||
service.attManager?.enableNotifications(ATTHandles.TRANSPARENCY)
|
||||
service.attManager?.enableNotifications(ATTHandles.HEARING_AID)
|
||||
|
||||
while (true) {
|
||||
refreshATT()
|
||||
delay(15000)
|
||||
delay(15000.milliseconds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,7 @@ import java.nio.ByteOrder
|
||||
import java.time.LocalDateTime
|
||||
import kotlin.io.encoding.Base64
|
||||
import kotlin.io.encoding.ExperimentalEncodingApi
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
private const val TAG = "AirPodsService"
|
||||
|
||||
@@ -151,7 +152,6 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
var macAddress = ""
|
||||
var localMac = ""
|
||||
lateinit var aacpManager: AACPManager
|
||||
var attManager: ATTManager? = null
|
||||
var airpodsInstance: AirPodsInstance? = null
|
||||
var cameraActive = false
|
||||
private var disconnectedBecauseReversed = false
|
||||
@@ -654,6 +654,7 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
addAction("android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT")
|
||||
addAction("android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED")
|
||||
addAction("android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED")
|
||||
addAction("android.bluetooth.device.action.UUID")
|
||||
}
|
||||
|
||||
connectionReceiver = object : BroadcastReceiver() {
|
||||
@@ -691,8 +692,9 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
// isConnectedLocally = false
|
||||
popupShown = false
|
||||
updateNotificationContent(false)
|
||||
attManager?.disconnect()
|
||||
attManager = null
|
||||
aacpManager.disconnected()
|
||||
BluetoothConnectionManager.getATTSocket()?.close()
|
||||
BluetoothConnectionManager.setCurrentConnection(null, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2432,32 +2434,6 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
takeOver("music", manualTakeOverAfterReversed = true)
|
||||
}
|
||||
|
||||
val bluetoothManager = getSystemService(BluetoothManager::class.java)
|
||||
val bluetoothAdapter = bluetoothManager.adapter
|
||||
|
||||
bluetoothAdapter?.bondedDevices?.forEach { device ->
|
||||
device.fetchUuidsWithSdp()
|
||||
|
||||
if (device.uuids != null) {
|
||||
// Check for the AirPods service UUID
|
||||
val uuid = ParcelUuid.fromString("74ec2172-0bad-4d01-8f77-997b2be0722a")
|
||||
|
||||
if (device.uuids.contains(uuid)) {
|
||||
Log.d(TAG, "Found AirPods device: ${device.name} (${device.address})")
|
||||
|
||||
// Connect or do whatever you need
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
connectToSocket(bluetoothAdapter, device)
|
||||
}
|
||||
setMetadatas(device)
|
||||
macAddress = device.address
|
||||
sharedPreferences.edit {
|
||||
putString("mac_address", macAddress)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return START_STICKY
|
||||
}
|
||||
|
||||
@@ -2647,15 +2623,15 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
}
|
||||
|
||||
private fun createBluetoothSocket(
|
||||
adapter: BluetoothAdapter, device: BluetoothDevice, uuid: ParcelUuid
|
||||
adapter: BluetoothAdapter, device: BluetoothDevice, uuid: ParcelUuid, psm: Int
|
||||
): BluetoothSocket {
|
||||
val type = 3 // L2CAP
|
||||
val constructorSpecs = listOf(
|
||||
arrayOf(adapter, device, type, true, true, 0x1001, uuid), // A16QPR3
|
||||
arrayOf(device, type, true, true, 0x1001, uuid),
|
||||
arrayOf(device, type, 1, true, true, 0x1001, uuid),
|
||||
arrayOf(type, 1, true, true, device, 0x1001, uuid),
|
||||
arrayOf(type, true, true, device, 0x1001, uuid)
|
||||
arrayOf(adapter, device, type, true, true, psm, uuid), // A16QPR3
|
||||
arrayOf(device, type, true, true, psm, uuid),
|
||||
arrayOf(device, type, 1, true, true, psm, uuid),
|
||||
arrayOf(type, 1, true, true, device, psm, uuid),
|
||||
arrayOf(type, true, true, device, psm, uuid)
|
||||
)
|
||||
|
||||
val constructors = BluetoothSocket::class.java.declaredConstructors
|
||||
@@ -2701,7 +2677,7 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
val uuid: ParcelUuid = ParcelUuid.fromString("74ec2172-0bad-4d01-8f77-997b2be0722a")
|
||||
// if (!isConnectedLocally) {
|
||||
socket = try {
|
||||
createBluetoothSocket(adapter, device, uuid)
|
||||
createBluetoothSocket(adapter, device, uuid, 4097)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to create BluetoothSocket: ${e.message}")
|
||||
showSocketConnectionFailureNotification("Failed to create Bluetooth socket: ${e.localizedMessage}")
|
||||
@@ -2710,20 +2686,22 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
|
||||
try {
|
||||
runBlocking {
|
||||
withTimeout(5000L) {
|
||||
withTimeout(5000.milliseconds) {
|
||||
try {
|
||||
socket.connect()
|
||||
// isConnectedLocally = true
|
||||
this@AirPodsService.device = device
|
||||
|
||||
BluetoothConnectionManager.setCurrentConnection(socket, device)
|
||||
val xposedRemotePref = XposedRemotePrefProvider.create()
|
||||
if (xposedRemotePref.getBoolean("vendor_id_hook", false)) {
|
||||
if (attManager == null) {
|
||||
attManager = ATTManager(adapter, device)
|
||||
attManager!!.connect()
|
||||
}
|
||||
}
|
||||
val attSocket = if (xposedRemotePref.getBoolean("vendor_id_hook", false)) {
|
||||
createBluetoothSocket(
|
||||
adapter,
|
||||
device,
|
||||
ParcelUuid.fromString("00000000-0000-0000-0000-000000000000"),
|
||||
31
|
||||
)
|
||||
} else null
|
||||
attSocket?.connect()
|
||||
BluetoothConnectionManager.setCurrentConnection(socket, attSocket)
|
||||
|
||||
// Create AirPodsInstance from stored config if available
|
||||
if (airpodsInstance == null && config.airpodsModelNumber.isNotEmpty()) {
|
||||
@@ -2928,7 +2906,8 @@ class AirPodsService : Service(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
socket.close()
|
||||
// isConnectedLocally = false
|
||||
aacpManager.disconnected()
|
||||
attManager?.disconnect()
|
||||
BluetoothConnectionManager.getATTSocket()?.close()
|
||||
BluetoothConnectionManager.setCurrentConnection(null, null)
|
||||
updateNotificationContent(false)
|
||||
sendBroadcast(Intent(AirPodsNotifications.AIRPODS_DISCONNECTED).apply {
|
||||
setPackage(packageName)
|
||||
|
||||
Reference in New Issue
Block a user