Skip to content

Commit 106b2f5

Browse files
committed
fix Bluetooth device sorting for large lists of Bluetooth devices
not doing IPC is remarkably quicker than doing it
1 parent dcb59bd commit 106b2f5

File tree

3 files changed

+37
-10
lines changed

3 files changed

+37
-10
lines changed

BetterBluetoothDeviceSort/build.gradle.kts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,7 @@ android {
1212
}
1313
}
1414

15-
dependencies {}
15+
dependencies {
16+
implementation(projects.logger)
17+
implementation(projects.reflection)
18+
}
Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package de.binarynoise.betterBluetoothDeviceSort
22

3-
import android.bluetooth.BluetoothAdapter
43
import android.bluetooth.BluetoothDevice
4+
import de.binarynoise.logger.Logger.log
5+
import de.binarynoise.reflection.cast
56
import de.robv.android.xposed.IXposedHookLoadPackage
67
import de.robv.android.xposed.XposedHelpers
78
import de.robv.android.xposed.callbacks.XC_LoadPackage
@@ -10,13 +11,36 @@ import de.robv.android.xposed.XC_MethodHook as MethodHook
1011
class Hook : IXposedHookLoadPackage {
1112

1213
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
13-
XposedHelpers.findAndHookMethod(BluetoothAdapter::class.java, "getMostRecentlyConnectedDevices", object : MethodHook() {
14-
override fun afterHookedMethod(param: MethodHookParam) {
15-
with(param) {
16-
@Suppress("UNCHECKED_CAST") val unsorted = result as MutableList<BluetoothDevice>
17-
unsorted.sortBy { a -> a.alias ?: a.name }
14+
15+
XposedHelpers.findAndHookMethod(
16+
"com.android.bluetooth.btservice.storage.DatabaseManager", lpparam.classLoader, "getMostRecentlyConnectedDevices",
17+
object : MethodHook() {
18+
override fun afterHookedMethod(param: MethodHookParam) {
19+
log("called getMostRecentlyConnectedDevices")
20+
with(param) {
21+
if (throwable != null || result == null) return
22+
@Suppress("UNCHECKED_CAST") val unsorted = result as MutableList<BluetoothDevice>
23+
log("${unsorted.size} devices")
24+
25+
val mAdapterService = XposedHelpers.getObjectField(param.thisObject, "mAdapterService")
26+
val mRemoteDevices = XposedHelpers.getObjectField(mAdapterService, "mRemoteDevices")
27+
val map = unsorted.associateWith { XposedHelpers.callMethod(mRemoteDevices, "getDeviceProperties", it) }
28+
29+
val mMetadataCache = XposedHelpers.getObjectField(param.thisObject, "mMetadataCache").cast<Map<String, *>>()
30+
val (bonded, others) = unsorted.partition { mMetadataCache.containsKey(it.address) }
31+
log("${bonded.size} bonded, ${others.size} others")
32+
33+
val comparator = Comparator.comparing<BluetoothDevice, String>({
34+
val properties = map[it] ?: return@comparing null
35+
(XposedHelpers.getObjectField(properties, "mAlias") ?: XposedHelpers.getObjectField(properties, "mName")).cast<String?>()
36+
}, Comparator.nullsLast(Comparator.naturalOrder<String>()))
37+
38+
result = bonded.toSortedSet(comparator).toMutableList() + others
39+
}
1840
}
19-
}
20-
})
41+
},
42+
)
43+
44+
log("Hooked getMostRecentlyConnectedDevices")
2145
}
2246
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<resources>
33
<string-array name="scope">
4-
<item>com.android.settings</item>
4+
<item>com.android.bluetooth</item>
55
</string-array>
66
</resources>

0 commit comments

Comments
 (0)