mirror of
https://github.com/kavishdevar/librepods.git
synced 2026-04-30 10:05:28 +00:00
android: fix normal builds
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
package me.kavishdevar.librepods.utils
|
||||
|
||||
object NativeBridge {
|
||||
fun setSdpHook(enabled: Boolean) { }
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
package me.kavishdevar.librepods.utils
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import android.widget.ImageView
|
||||
import androidx.core.net.toUri
|
||||
import io.github.libxposed.api.XposedModule
|
||||
import io.github.libxposed.api.XposedModuleInterface.ModuleLoadedParam
|
||||
import io.github.libxposed.api.XposedModuleInterface.PackageLoadedParam
|
||||
|
||||
private const val TAG = "LibrePodsHook"
|
||||
|
||||
@SuppressLint("DiscouragedApi", "PrivateApi")
|
||||
class KotlinModule: XposedModule() {
|
||||
override fun onModuleLoaded(param: ModuleLoadedParam) {
|
||||
log(Log.INFO, TAG, "module initialized at :: ${param.processName}")
|
||||
log(Log.INFO, TAG, "framework: $frameworkName($frameworkVersionCode) API $apiVersion")
|
||||
}
|
||||
|
||||
override fun onPackageLoaded(param: PackageLoadedParam) {
|
||||
log(Log.INFO, TAG, "onPackageLoaded :: ${param.packageName}")
|
||||
|
||||
if (param.packageName == "com.google.android.bluetooth" || param.packageName == "com.android.bluetooth") {
|
||||
log(Log.INFO, TAG, "Bluetooth app detected, hooking l2c_fcr_chk_chan_modes")
|
||||
try {
|
||||
if (param.isFirstPackage) {
|
||||
log(Log.INFO, TAG, "Loading native library for Bluetooth hook")
|
||||
|
||||
NativeBridge.setSdpHook(getRemotePreferences("me.kavishdevar.librepods").getBoolean("vendor_id_hook", false))
|
||||
System.loadLibrary("l2c_fcr_hook")
|
||||
log(Log.INFO, TAG, "Native library loaded successfully")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
log(Log.ERROR, TAG, "Failed to load native library: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
if (param.packageName == "com.google.android.settings") {
|
||||
hookSettingsController(param, "com.google.android.settings.bluetooth.AdvancedBluetoothDetailsHeaderController")
|
||||
}
|
||||
|
||||
if (param.packageName == "com.android.settings") {
|
||||
hookSettingsController(param, "com.android.settings.bluetooth.AdvancedBluetoothDetailsHeaderController")
|
||||
}
|
||||
}
|
||||
|
||||
private fun hookSettingsController(param: PackageLoadedParam, className: String) {
|
||||
log(Log.INFO, TAG, "Settings app detected, hooking Bluetooth icon handling")
|
||||
try {
|
||||
val headerControllerClass = Class.forName(className, false, param.defaultClassLoader)
|
||||
val updateIconMethod = headerControllerClass.getDeclaredMethod(
|
||||
"updateIcon",
|
||||
ImageView::class.java,
|
||||
String::class.java
|
||||
)
|
||||
|
||||
hook(updateIconMethod).intercept { chain ->
|
||||
try {
|
||||
log(Log.INFO, TAG, "Bluetooth icon hook called with args: ${chain.args.joinToString(", ")}")
|
||||
val imageView = chain.args[0] as? ImageView
|
||||
val iconUri = chain.args[1] as? String
|
||||
|
||||
if (imageView == null || iconUri == null) {
|
||||
return@intercept chain.proceed()
|
||||
}
|
||||
|
||||
val uri = iconUri.toUri()
|
||||
if (!uri.toString().startsWith("android.resource://me.kavishdevar.librepods")) {
|
||||
return@intercept chain.proceed()
|
||||
}
|
||||
|
||||
log(Log.INFO, TAG, "Handling AirPods icon URI: $uri")
|
||||
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
try {
|
||||
val context = imageView.context
|
||||
val packageName = uri.authority ?: return@post
|
||||
val packageContext = context.createPackageContext(
|
||||
packageName,
|
||||
Context.CONTEXT_IGNORE_SECURITY
|
||||
)
|
||||
|
||||
val resPath = uri.pathSegments
|
||||
if (resPath.size >= 2 && resPath[0] == "drawable") {
|
||||
val resourceName = resPath[1]
|
||||
val resourceId = packageContext.resources.getIdentifier(
|
||||
resourceName, "drawable", packageName
|
||||
)
|
||||
|
||||
if (resourceId != 0) {
|
||||
val drawable = packageContext.resources.getDrawable(
|
||||
resourceId, packageContext.theme
|
||||
)
|
||||
imageView.setImageDrawable(drawable)
|
||||
imageView.alpha = 1.0f
|
||||
log(Log.INFO, TAG, "Successfully loaded icon from resource: $resourceName")
|
||||
} else {
|
||||
log(Log.ERROR, TAG, "Resource not found: $resourceName")
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
log(Log.ERROR, TAG, "Error loading resource from URI $uri: ${e.message}")
|
||||
}
|
||||
}
|
||||
null
|
||||
} catch (e: Exception) {
|
||||
log(Log.ERROR, TAG, "Error in Bluetooth icon hook: ${e.message}")
|
||||
chain.proceed()
|
||||
}
|
||||
}
|
||||
|
||||
log(Log.INFO, TAG, "Successfully hooked updateIcon method in Bluetooth settings")
|
||||
} catch (e: Exception) {
|
||||
log(Log.ERROR, TAG, "Failed to hook Bluetooth icon handler: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object NativeBridge {
|
||||
external fun setSdpHook(enabled: Boolean)
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package me.kavishdevar.librepods.utils
|
||||
|
||||
import android.content.Context
|
||||
import io.github.libxposed.service.XposedService
|
||||
import io.github.libxposed.service.XposedServiceHelper
|
||||
|
||||
object XposedServiceHolder {
|
||||
var service: XposedService? = null
|
||||
}
|
||||
|
||||
|
||||
object XposedInitializer: XposedServiceHelper.OnServiceListener {
|
||||
private var initialized = false
|
||||
|
||||
fun ensureInit(context: Context) {
|
||||
if (initialized) return
|
||||
initialized = true
|
||||
XposedServiceHelper.registerListener(this)
|
||||
}
|
||||
|
||||
override fun onServiceBind(service: XposedService) {
|
||||
XposedServiceHolder.service = service
|
||||
}
|
||||
|
||||
override fun onServiceDied(service: XposedService) {
|
||||
XposedServiceHolder.service = null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user