Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1181,7 +1181,16 @@ class AACPManager(private val device: AppleDevice) {
val payload = data.command.payload.toByteArray()
val timestamp = Clock.System.now()
if (payload.size == 18) {
val heartRate = payload[1].toInt()
// unsigned: a signed read turns anything >= 128 bpm negative and drops it
val heartRate = payload[1].toInt() and 0xFF

// bit 0 of the last byte is set for the first few samples after the sensor starts (payload[2],
// which looks like a confidence value, is also very low then); those readings are unreliable,
// e.g. 169 bpm at rest, so skip them and stay in WAITING until the sensor settles
if (payload[17].toInt() and 0x01 != 0) {
Log.d(TAG, "skipping heart rate sample while the sensor is acquiring: ${payload.toHexString()}")
return
}

// same as healthconnect's datatype. 300 isn't possible anyway, but whatever
if (heartRate !in 1..300) {
Expand All @@ -1202,7 +1211,7 @@ class AACPManager(private val device: AppleDevice) {

Log.i(
TAG,
"hr: $heartRate bpm"
"hr: $heartRate bpm, payload: ${payload.toHexString()}"
)

val heartRateSample = HeartRateSample(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.getAndUpdate
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import me.kavishdevar.librepods.bluetooth.MacAddress
Expand Down Expand Up @@ -124,8 +125,13 @@ class AppleDevice(
}

override fun connect(): Boolean {
_connectionState.update {
ConnectionState.CONNECTING
// the service (ACL/UUID broadcasts) and the UI can both call connect(); only let one of them open a socket
val previousState = _connectionState.getAndUpdate {
if (it == ConnectionState.CONNECTING || it == ConnectionState.CONNECTED) it else ConnectionState.CONNECTING
}
if (previousState == ConnectionState.CONNECTING || previousState == ConnectionState.CONNECTED) {
Log.d(TAG, "connect() ignored, already $previousState")
return previousState == ConnectionState.CONNECTED
}

val success = aacp.connect() // && att.connect()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import android.os.BatteryManager
import android.os.Binder
import android.os.Build
import android.os.IBinder
import android.os.Looper
import android.os.ParcelUuid
import android.os.ext.SdkExtensions
import android.provider.Settings
Expand Down Expand Up @@ -308,6 +309,8 @@ class LibrePodsService: Service() {
}
}

// createDevice() already registered observers for this device; cancel them so each state change is handled once
deviceJobs[MacAddress(bluetoothDevice.address)]?.forEach { it.cancel() }
deviceJobs[MacAddress(bluetoothDevice.address)] = mutableListOf()

deviceJobs[MacAddress(bluetoothDevice.address)]?.add(observeAppleState(device))
Expand Down Expand Up @@ -676,7 +679,9 @@ class LibrePodsService: Service() {

Log.d(TAG, "updating island window")
if (islandWindow?.isVisible == true) {
islandWindow?.updateBattery(state.battery)
CoroutineScope(Dispatchers.Main).launch {
islandWindow?.updateBattery(state.battery)
}
}

Log.d(TAG, "updating notification")
Expand Down Expand Up @@ -919,6 +924,14 @@ class LibrePodsService: Service() {
reversed: Boolean = false,
otherDeviceName: String? = null
) {
// the island is a window, so it has to be added from the main thread (state observers run on IO)
if (Looper.myLooper() != Looper.getMainLooper()) {
CoroutineScope(Dispatchers.Main).launch {
showIsland(device, type, reversed, otherDeviceName)
}
return
}

Log.d(TAG, "Showing island window")

val state = device.state.value
Expand Down Expand Up @@ -1221,7 +1234,9 @@ class LibrePodsService: Service() {
}

if (new == EarPresence.NONE && islandWindow?.isVisible == true) {
islandWindow?.close()
CoroutineScope(Dispatchers.Main).launch {
islandWindow?.close()
}
}

var justEnabledA2dp = false
Expand Down