Manually flash batch cache, in low latency modes to achieve lower scan result delays.

This commit is contained in:
darken
2022-01-18 12:27:41 +01:00
parent 8e563ac7bb
commit 220c358f5d
4 changed files with 36 additions and 18 deletions
@@ -11,11 +11,15 @@ import eu.darken.capod.common.debug.autoreport.DebugSettings
import eu.darken.capod.common.debug.logging.Logging.Priority.*
import eu.darken.capod.common.debug.logging.log
import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.main.core.ScannerMode
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import javax.inject.Inject
import javax.inject.Singleton
@@ -28,7 +32,7 @@ class BleScanner @Inject constructor(
fun scan(
filter: Set<ScanFilter> = ProximityPairing.getBleScanFilter(),
mode: Int = ScanSettings.SCAN_MODE_LOW_LATENCY,
scannerMode: ScannerMode = ScannerMode.LOW_POWER,
): Flow<List<BleScanResult>> = callbackFlow {
val adapter = bluetoothManager.adapter
val scanner = bluetoothManager.scanner
@@ -59,14 +63,36 @@ class BleScanner @Inject constructor(
}
val settings = ScanSettings.Builder().apply {
setScanMode(mode)
setScanMode(
when (scannerMode) {
ScannerMode.LOW_POWER -> ScanSettings.SCAN_MODE_LOW_POWER
ScannerMode.BALANCED -> ScanSettings.SCAN_MODE_BALANCED
ScannerMode.LOW_LATENCY -> ScanSettings.SCAN_MODE_LOW_LATENCY
}
)
if (adapter.isOffloadedScanBatchingSupported) {
setReportDelay(1000)
when (scannerMode) {
ScannerMode.LOW_POWER -> setReportDelay(5000)
ScannerMode.BALANCED -> setReportDelay(2500)
ScannerMode.LOW_LATENCY -> setReportDelay(500)
}
} else {
log(TAG, WARN) { "isOffloadedScanBatchingSupported=false" }
}
}.build()
val flushJob = launch {
while (isActive) {
// Can undercut the minimum setReportDelay(), e.g. 5000ms on a Pixel5@12
adapter.bluetoothLeScanner.flushPendingScanResults(callback)
when (scannerMode) {
ScannerMode.LOW_POWER -> break
ScannerMode.BALANCED -> delay(2500)
ScannerMode.LOW_LATENCY -> delay(500)
}
}
}
if (adapter.isOffloadedFilteringSupported) {
scanner.startScan(filter.toList(), settings, callback)
log(TAG, VERBOSE) { "BleScanner started (filter=$filter, settings=$settings)" }
@@ -77,8 +103,9 @@ class BleScanner @Inject constructor(
}
awaitClose {
log(TAG, INFO) { "BleScanner stopped" }
flushJob.cancel()
scanner.stopScan(callback)
log(TAG, INFO) { "BleScanner stopped" }
}
}
.map { origs ->
@@ -71,7 +71,7 @@ class BluetoothManager2 @Inject constructor(
suspend fun getBluetoothProfile(
profile: Int = BluetoothProfile.HEADSET
): BluetoothProfile2 = withContext(dispatcherProvider.IO) {
log(TAG) { "getBluetoothProfile(profile=$profile)" }
log(TAG, VERBOSE) { "getBluetoothProfile(profile=$profile)" }
suspendCancellableCoroutine {
val connectionState = AtomicBoolean(false)
@@ -97,7 +97,7 @@ class BluetoothManager2 @Inject constructor(
}
private fun connectedDevicesForProfile(profile: Int): Flow<Set<BluetoothDevice>> = callbackFlow {
log(TAG) { "connectedDevices(profile=$profile) starting" }
log(TAG, VERBOSE) { "connectedDevices(profile=$profile) starting" }
trySend(getBluetoothProfile(profile).connectedDevices)
val filter = IntentFilter().apply {
@@ -29,7 +29,7 @@ class GeneralSettings @Inject constructor(
val scannerMode = preferences.createFlowPreference(
"core.scanner.mode",
ScannerMode.LOW_LATENCY,
ScannerMode.LOW_POWER,
moshi
)
@@ -1,6 +1,5 @@
package eu.darken.capod.monitor.core
import android.bluetooth.le.ScanSettings
import eu.darken.capod.common.bluetooth.BleScanner
import eu.darken.capod.common.bluetooth.BluetoothManager2
import eu.darken.capod.common.coroutine.AppScope
@@ -10,7 +9,6 @@ import eu.darken.capod.common.debug.logging.log
import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.common.flow.replayingShare
import eu.darken.capod.main.core.GeneralSettings
import eu.darken.capod.main.core.ScannerMode
import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.PodFactory
import kotlinx.coroutines.CoroutineScope
@@ -35,17 +33,10 @@ class PodMonitor @Inject constructor(
private val cacheLock = Mutex()
val devices: Flow<List<PodDevice>> = generalSettings.scannerMode.flow
.flatMapLatest {
val mode = when (it) {
ScannerMode.LOW_POWER -> ScanSettings.SCAN_MODE_LOW_POWER
ScannerMode.BALANCED -> ScanSettings.SCAN_MODE_BALANCED
ScannerMode.LOW_LATENCY -> ScanSettings.SCAN_MODE_LOW_LATENCY
}
.flatMapLatest { scannerMode ->
bluetoothManager.isBluetoothEnabled.flatMapLatest { isBluetoothEnabled ->
if (isBluetoothEnabled) {
bleScanner.scan(
mode = mode
)
bleScanner.scan(scannerMode = scannerMode)
} else {
log(TAG, WARN) { "Bluetooth is current disabled" }
emptyFlow()