Skip to content

Commit

Permalink
Fix possible deadlock in BLE
Browse files Browse the repository at this point in the history
  • Loading branch information
izivkov committed Mar 3, 2024
1 parent 6373c6f commit 1a5d91a
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 22 deletions.
12 changes: 8 additions & 4 deletions api/src/main/java/org/avmedia/gshockapi/ble/Connection.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.avmedia.gshockapi.ProgressEvents
import org.avmedia.gshockapi.WatchInfo
import org.avmedia.gshockapi.casio.MessageDispatcher

Expand All @@ -20,14 +21,14 @@ object Connection {
private var bleManager: IGShockManager? = null
private val scope = CoroutineScope(Dispatchers.IO)

private suspend fun connect() {
private suspend fun connect(device: BluetoothDevice) {

fun onConnected (name: String, address: String) {
WatchInfo.setNameAndModel(name.trimEnd('\u0000'))
WatchInfo.setAddress(address)
}

bleManager?.connect(::onConnected)
bleManager?.connect(device, ::onConnected)
}

fun disconnect() {
Expand Down Expand Up @@ -89,12 +90,15 @@ object Connection {
}
val bluetoothAdapter: BluetoothAdapter? = getDefaultAdapter()
val device: BluetoothDevice? = bluetoothAdapter?.getRemoteDevice(address)
if (device == null) {
ProgressEvents.onNext("ApiError", "Cannot obtain remote device")
return
}

if (bleManager == null) {
bleManager = IGShockManager(context)
}
bleManager?.setDevice(device as BluetoothDevice)
connect()
connect(device)
}

fun isBluetoothEnabled(context:Context): Boolean {
Expand Down
33 changes: 15 additions & 18 deletions api/src/main/java/org/avmedia/gshockapi/ble/IGShockManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@ enum class ConnectionState {
typealias onConnectedType = (String, String) -> Unit

interface GSHock {
suspend fun connect(onConnected: (String, String) -> Unit)
suspend fun connect(device: BluetoothDevice, onConnected: (String, String) -> Unit)
fun release()
fun setDataCallback(dataCallback: IDataReceived?)
fun enableNotifications()
suspend fun write(handle: Int, data: ByteArray)
abstract fun setDevice(device: BluetoothDevice)
abstract var connectionState: ConnectionState
}

Expand All @@ -52,8 +51,6 @@ private class GShockManagerImpl(

override fun initialize() {
super.initialize()
ProgressEvents.onNext("BleManagerInitialized")

setNotificationCallback(writeCharacteristic).with { _, data ->
Timber.i("Received data from characteristic: ${data.value}")

Expand All @@ -64,16 +61,13 @@ private class GShockManagerImpl(
}

enableNotifications(writeCharacteristic).enqueue()
}

override fun setDevice(device: BluetoothDevice) {
this.device = device
ProgressEvents.onNext("BleManagerInitialized")
}

@SuppressLint("MissingPermission")
private val scope = CoroutineScope(Dispatchers.IO)

override suspend fun connect(onConnected: onConnectedType) {
override suspend fun connect(device: BluetoothDevice, onConnected: onConnectedType) {
this.onConnected = onConnected

connect(device)
Expand All @@ -93,7 +87,9 @@ private class GShockManagerImpl(
cancelQueue()

// If the device was connected, we have to disconnect manually.
disconnect().enqueue()
if (wasConnected) {
disconnect().enqueue()
}
}

override fun setDataCallback(dataCallback: IDataReceived?) {
Expand Down Expand Up @@ -132,8 +128,16 @@ private class GShockManagerImpl(
connectionState = ConnectionState.DISCONNECTED
}

@SuppressLint("MissingPermission")
override fun onDeviceReady(device: BluetoothDevice) {
Timber.i("$device onDeviceReady!!!!!!")
Timber.i("$device DeviceReady!!!!!!")

onConnected(device.name, device.address)

// inform the caller that we have connected
ProgressEvents.onNext("ConnectionSetupComplete", device)
ProgressEvents.onNext("DeviceName", device.name)
ProgressEvents.onNext("DeviceAddress", device.address)
}

override fun onDeviceDisconnecting(device: BluetoothDevice) {
Expand All @@ -157,13 +161,6 @@ private class GShockManagerImpl(
writeCharacteristic = getCharacteristic(
CasioConstants.CASIO_ALL_FEATURES_CHARACTERISTIC_UUID,
)
onConnected(device.name, device.address)

// inform the caller that we have connected
ProgressEvents.onNext("ConnectionSetupComplete", device)
ProgressEvents.onNext("DeviceName", device.name)
ProgressEvents.onN