Add compatibility mode.

This commit is contained in:
darken
2022-02-10 10:19:07 +01:00
parent 9b39240016
commit 324878d68d
7 changed files with 92 additions and 30 deletions
@@ -31,8 +31,20 @@ class BleScanner @Inject constructor(
@SuppressLint("MissingPermission") fun scan(
filters: Set<ScanFilter>,
scannerMode: ScannerMode,
compatMode: Boolean,
): Flow<List<BleScanResult>> = callbackFlow {
if (compatMode) log(TAG, WARN) { "Using compatibilityMode!" }
val adapter = bluetoothManager.adapter
val supportsOffloadFiltering = adapter.isOffloadedFilteringSupported.also {
log(TAG, if (it) DEBUG else WARN) { "isOffloadedFilteringSupported=$it" }
} && !compatMode
val supportsOffloadBatching = adapter.isOffloadedScanBatchingSupported.also {
log(TAG, if (it) DEBUG else WARN) { "isOffloadedScanBatchingSupported=$it" }
} && !compatMode
val scanner = bluetoothManager.scanner
val callback = object : ScanCallback() {
@@ -43,7 +55,13 @@ class BleScanner @Inject constructor(
lastScanAt = System.currentTimeMillis()
"onScanResult(delay=${delay}ms, callbackType=$callbackType, result=$result)"
}
trySend(listOf(BleScanResult.fromScanResult(result)))
val toSend = if (supportsOffloadFiltering || filters.isEmpty() || filters.any { it.matches(result) }) {
listOf(BleScanResult.fromScanResult(result))
} else {
log(TAG, VERBOSE) { "Manual filtering: No match for $result" }
emptyList()
}
trySend(toSend)
}
override fun onBatchScanResults(results: MutableList<ScanResult>) {
@@ -52,7 +70,19 @@ class BleScanner @Inject constructor(
lastScanAt = System.currentTimeMillis()
"onBatchScanResults(delay=${delay}ms, results=$results)"
}
trySend(results.map { BleScanResult.fromScanResult(it) })
val toSend = results
.filter { result ->
val passed = when {
supportsOffloadFiltering -> true
filters.isEmpty() -> true
else -> filters.any { it.matches(result) }
}
if (!passed) log(TAG, VERBOSE) { "Manually filtered $result" }
passed
}
.map { BleScanResult.fromScanResult(it) }
trySend(toSend)
}
override fun onScanFailed(errorCode: Int) {
@@ -60,6 +90,7 @@ class BleScanner @Inject constructor(
}
}
val settings = ScanSettings.Builder().apply {
setScanMode(
when (scannerMode) {
@@ -68,20 +99,24 @@ class BleScanner @Inject constructor(
ScannerMode.LOW_LATENCY -> ScanSettings.SCAN_MODE_LOW_LATENCY
}
)
if (adapter.isOffloadedScanBatchingSupported) {
when (scannerMode) {
ScannerMode.LOW_POWER -> setReportDelay(2000)
ScannerMode.BALANCED -> setReportDelay(1000)
ScannerMode.LOW_LATENCY -> setReportDelay(500)
}
} else {
log(TAG, WARN) { "isOffloadedScanBatchingSupported=false" }
if (supportsOffloadBatching) {
setReportDelay(
when (scannerMode) {
ScannerMode.LOW_POWER -> 2000L
ScannerMode.BALANCED -> 1000L
ScannerMode.LOW_LATENCY -> 500L
}
)
}
}.build()
log(TAG, VERBOSE) { "Settings created for offloaded filtering: $settings" }
val flushJob = launch {
log(TAG) { "Flush job launched" }
while (isActive) {
// Can undercut the minimum setReportDelay(), e.g. 5000ms on a Pixel5@12
log(TAG, VERBOSE) { "Flushing scan results." }
adapter.bluetoothLeScanner.flushPendingScanResults(callback)
when (scannerMode) {
ScannerMode.LOW_POWER -> break
@@ -91,19 +126,17 @@ class BleScanner @Inject constructor(
}
}
if (adapter.isOffloadedFilteringSupported) {
scanner.startScan(filters.toList(), settings, callback)
log(TAG, VERBOSE) { "BleScanner started (filters=$filters, settings=$settings)" }
} else {
log(TAG, WARN) { "isOffloadedFilteringSupported=false" }
scanner.startScan(callback)
log(TAG, VERBOSE) { "BleScanner started" }
}
scanner.startScan(
if (supportsOffloadFiltering) filters.toList() else listOf(ScanFilter.Builder().build()),
settings,
callback
)
log(TAG) { "BleScanner started (filters=$filters, settings=$settings)" }
awaitClose {
flushJob.cancel()
scanner.stopScan(callback)
log(TAG, INFO) { "BleScanner stopped" }
log(TAG) { "BleScanner stopped" }
}
}
.map { fakeBleData.maybeAddfakeData(it) }
@@ -34,6 +34,11 @@ class GeneralSettings @Inject constructor(
moshi
)
val compatibilityMode = preferences.createFlowPreference(
"core.compatibility.enabled",
false
)
val showAll = preferences.createFlowPreference(
"core.showall.enabled",
false
@@ -58,6 +63,7 @@ class GeneralSettings @Inject constructor(
override val preferenceDataStore: PreferenceDataStore = PreferenceStoreMapper(
monitorMode,
scannerMode,
compatibilityMode,
showAll,
minimumSignalQuality,
mainDeviceAddress,
@@ -10,6 +10,7 @@ import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.viewModels
import dagger.hilt.android.AndroidEntryPoint
import eu.darken.capod.BuildConfig
import eu.darken.capod.R
import eu.darken.capod.common.colorString
import eu.darken.capod.common.debug.logging.log
@@ -71,6 +72,7 @@ class OverviewFragment : Fragment3(R.layout.main_fragment) {
}
vm.listItems.observe2(ui) {
if (BuildConfig.DEBUG) toolbar.subtitle = "${it.size} items"
adapter.update(it)
}
@@ -61,19 +61,22 @@ class PodMonitor @Inject constructor(
log(TAG) { "Bluetooth is enabled" }
combine(
generalSettings.scannerMode.flow,
generalSettings.compatibilityMode.flow,
debugSettings.showUnfiltered.flow
) { mode, unfiltered -> mode to unfiltered }
.flatMapLatest { (mode, unfiltered) ->
val filters = if (unfiltered) {
setOf(getUnfilteredFilter())
} else {
ProximityPairing.getBleScanFilter()
}
bleScanner.scan(
filters = filters,
scannerMode = mode
).map { it.preFilterAndMap(mode) }
) { scannerMode, compatMode, unfiltered ->
Triple(scannerMode, compatMode, unfiltered)
}.flatMapLatest { (mode, compat, unfiltered) ->
val filters = if (unfiltered) {
setOf(getUnfilteredFilter())
} else {
ProximityPairing.getBleScanFilter()
}
bleScanner.scan(
filters = filters,
scannerMode = mode,
compatMode = compat,
).map { it.preFilterAndMap(mode) }
}
} else {
log(TAG, WARN) { "Bluetooth is currently disabled" }
flowOf(null)
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M12,2A9,9 0 0,0 3,11V22L6,19L9,22L12,19L15,22L18,19L21,22V11A9,9 0 0,0 12,2M9,8A2,2 0 0,1 11,10A2,2 0 0,1 9,12A2,2 0 0,1 7,10A2,2 0 0,1 9,8M15,8A2,2 0 0,1 17,10A2,2 0 0,1 15,12A2,2 0 0,1 13,10A2,2 0 0,1 15,8Z" />
</vector>
+2
View File
@@ -142,4 +142,6 @@
<string name="settings_blescanner_unfiltered_label">Unfiltered BLE data</string>
<string name="settings_blescanner_unfiltered_description">Remove any filters from the BLE scanner to show all broadcasted BLE data. Useful to add support for new headphone types.</string>
<string name="permission_required_title">The following permission is required:</string>
<string name="settings_compatibility_mode_label">Compatibility mode</string>
<string name="settings_compatibility_mode_description">Disable optimizations to improve compatibility. Try this if you are not seeing any data.</string>
</resources>
@@ -14,6 +14,12 @@
android:summary="@string/settings_scanner_mode_description"
android:title="@string/settings_scanner_mode_label" />
<CheckBoxPreference
android:icon="@drawable/ic_baseline_ghost_24"
android:key="core.compatibility.enabled"
android:summary="@string/settings_compatibility_mode_description"
android:title="@string/settings_compatibility_mode_label" />
<CheckBoxPreference
android:icon="@drawable/ic_baseline_devices_other_24"
android:key="core.showall.enabled"