mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-14 18:26:11 -04:00
Add compatibility mode.
This commit is contained in:
@@ -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>
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user