Add option for unfiltered BLE scan.

This commit is contained in:
darken
2022-01-31 19:20:39 +01:00
parent 08b76f3280
commit b2693c6e57
5 changed files with 59 additions and 10 deletions
@@ -1,5 +1,6 @@
package eu.darken.capod.common.bluetooth
import android.annotation.SuppressLint
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanFilter
import android.bluetooth.le.ScanResult
@@ -10,7 +11,6 @@ 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
@@ -28,9 +28,9 @@ class BleScanner @Inject constructor(
private val fakeBleData: FakeBleData,
) {
fun scan(
filter: Set<ScanFilter> = ProximityPairing.getBleScanFilter(),
scannerMode: ScannerMode = ScannerMode.LOW_POWER,
@SuppressLint("MissingPermission") fun scan(
filters: Set<ScanFilter>,
scannerMode: ScannerMode,
): Flow<List<BleScanResult>> = callbackFlow {
val adapter = bluetoothManager.adapter
val scanner = bluetoothManager.scanner
@@ -92,8 +92,8 @@ class BleScanner @Inject constructor(
}
if (adapter.isOffloadedFilteringSupported) {
scanner.startScan(filter.toList(), settings, callback)
log(TAG, VERBOSE) { "BleScanner started (filter=$filter, settings=$settings)" }
scanner.startScan(filters.toList(), settings, callback)
log(TAG, VERBOSE) { "BleScanner started (filters=$filters, settings=$settings)" }
} else {
log(TAG, WARN) { "isOffloadedFilteringSupported=false" }
scanner.startScan(callback)
@@ -23,9 +23,12 @@ class DebugSettings @Inject constructor(
val showFakeData = preferences.createFlowPreference("debug.fakedata.enabled", false)
val showUnfiltered = preferences.createFlowPreference("debug.blescanner.unfiltered.enabled", false)
override val preferenceDataStore: PreferenceDataStore = PreferenceStoreMapper(
isDebugModeEnabled,
showFakeData,
showUnfiltered,
)
}
@@ -1,10 +1,13 @@
package eu.darken.capod.monitor.core
import android.bluetooth.le.ScanFilter
import eu.darken.capod.common.bluetooth.BleScanResult
import eu.darken.capod.common.bluetooth.BleScanner
import eu.darken.capod.common.bluetooth.BluetoothManager2
import eu.darken.capod.common.coroutine.AppScope
import eu.darken.capod.common.debug.logging.Logging.Priority.*
import eu.darken.capod.common.debug.autoreport.DebugSettings
import eu.darken.capod.common.debug.logging.Logging.Priority.VERBOSE
import eu.darken.capod.common.debug.logging.Logging.Priority.WARN
import eu.darken.capod.common.debug.logging.asLog
import eu.darken.capod.common.debug.logging.log
import eu.darken.capod.common.debug.logging.logTag
@@ -13,6 +16,8 @@ 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 eu.darken.capod.pods.core.apple.protocol.ContinuityProtocol
import eu.darken.capod.pods.core.apple.protocol.ProximityPairing
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
@@ -29,6 +34,7 @@ class PodMonitor @Inject constructor(
private val podFactory: PodFactory,
private val generalSettings: GeneralSettings,
private val bluetoothManager: BluetoothManager2,
private val debugSettings: DebugSettings,
@AppScope private val appScope: CoroutineScope
) {
@@ -54,9 +60,20 @@ class PodMonitor @Inject constructor(
.flatMapLatest { isBluetoothEnabled ->
if (isBluetoothEnabled) {
log(TAG) { "Bluetooth is enabled" }
generalSettings.scannerMode.flow
.flatMapLatest { mode ->
bleScanner.scan(scannerMode = mode).map { it.preFilterAndMap(mode) }
combine(
generalSettings.scannerMode.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) }
}
} else {
log(TAG, WARN) { "Bluetooth is currently disabled" }
@@ -141,6 +158,27 @@ class PodMonitor @Inject constructor(
}
}
private fun getUnfilteredFilter(): ScanFilter {
val manufacturerData = ByteArray(2).apply {
this[0] = 0
this[1] = 0
}
val manufacturerDataMask = ByteArray(2).apply {
this[0] = 0
this[1] = 0
}
val builder = ScanFilter.Builder().apply {
setManufacturerData(
ContinuityProtocol.APPLE_COMPANY_IDENTIFIER,
manufacturerData,
manufacturerDataMask
)
}
return builder.build()
}
companion object {
private val TAG = logTag("Monitor", "PodMonitor")
}
+2
View File
@@ -139,4 +139,6 @@
<string name="permission_system_alert_window_description">Allow CAPod to draw over other apps to make the feature \"Show PopUp\" possible.</string>
<string name="last_seen_x">Last seen: %s</string>
<string name="first_seen_x">First seen: %s</string>
<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>
</resources>
@@ -18,4 +18,10 @@
android:summary="@string/settings_fake_data_description"
android:title="@string/settings_fake_data_label" />
<CheckBoxPreference
android:icon="@drawable/ic_baseline_devices_other_24"
android:key="debug.blescanner.unfiltered.enabled"
android:summary="@string/settings_blescanner_unfiltered_description"
android:title="@string/settings_blescanner_unfiltered_label" />
</PreferenceScreen>