diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/HMAService.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/HMAService.kt index 4c1d72f..e2ff53a 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/HMAService.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/HMAService.kt @@ -118,7 +118,9 @@ class HMAService(val pms: IPackageManager) : IHMAService.Stub() { if (it.flags and ApplicationInfo.FLAG_SYSTEM != 0) it.packageName else null } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + frameworkHooks.add(PmsHookTarget34(this)) + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { frameworkHooks.add(PmsHookTarget33(this)) } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { frameworkHooks.add(PmsHookTarget30(this)) diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget34.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget34.kt new file mode 100644 index 0000000..a1559fd --- /dev/null +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/PmsHookTarget34.kt @@ -0,0 +1,95 @@ +package icu.nullptr.hidemyapplist.xposed.hook + +import android.annotation.TargetApi +import android.os.Binder +import android.os.Build +import com.github.kyuubiran.ezxhelper.utils.findMethod +import com.github.kyuubiran.ezxhelper.utils.findMethodOrNull +import com.github.kyuubiran.ezxhelper.utils.hookBefore +import de.robv.android.xposed.XC_MethodHook +import icu.nullptr.hidemyapplist.common.Constants +import icu.nullptr.hidemyapplist.xposed.* +import java.util.concurrent.atomic.AtomicReference + +@TargetApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) +class PmsHookTarget34(private val service: HMAService) : IFrameworkHook { + + companion object { + private const val TAG = "PmsHookTarget34" + } + + private val getPackagesForUidMethod by lazy { + findMethod("com.android.server.pm.Computer") { + name == "getPackagesForUid" + } + } + + private var hook: XC_MethodHook.Unhook? = null + private var exphook: XC_MethodHook.Unhook? = null + private var lastFilteredApp: AtomicReference = AtomicReference(null) + + @Suppress("UNCHECKED_CAST") + override fun load() { + logI(TAG, "Load hook") + hook = findMethod("com.android.server.pm.AppsFilterImpl", findSuper = true) { + name == "shouldFilterApplication" + }.hookBefore { param -> + runCatching { + val snapshot = param.args[0] + val callingUid = param.args[1] as Int + if (callingUid == Constants.UID_SYSTEM) return@hookBefore + val callingApps = Utils.binderLocalScope { + getPackagesForUidMethod.invoke(snapshot, callingUid) as Array? + } ?: return@hookBefore + val targetApp = Utils.getPackageNameFromPackageSettings(param.args[3]) // PackageSettings <- PackageStateInternal + for (caller in callingApps) { + if (service.shouldHide(caller, targetApp)) { + param.result = true + service.filterCount++ + val last = lastFilteredApp.getAndSet(caller) + if (last != caller) logI(TAG, "@shouldFilterApplication: query from $caller") + logD(TAG, "@shouldFilterApplication caller: $callingUid $caller, target: $targetApp") + return@hookBefore + } + } + }.onFailure { + logE(TAG, "Fatal error occurred, disable hooks", it) + unload() + } + } + // AOSP exploit - https://github.com/aosp-mirror/platform_frameworks_base/commit/5bc482bd99ea18fe0b4064d486b29d5ae2d65139 + // Only 14 QPR2+ has this method + exphook = findMethodOrNull("com.android.server.pm.PackageManagerService", findSuper = true) { + name == "getArchivedPackageInternal" + }?.hookBefore { param -> + runCatching { + val callingUid = Binder.getCallingUid() + if (callingUid == Constants.UID_SYSTEM) return@hookBefore + val callingApps = Utils.binderLocalScope { + service.pms.getPackagesForUid(callingUid) + } ?: return@hookBefore + val targetApp = param.args[0].toString() + for (caller in callingApps) { + if (service.shouldHide(caller, targetApp)) { + param.result = null + service.filterCount++ + val last = lastFilteredApp.getAndSet(caller) + if (last != caller) logI(TAG, "@getArchivedPackageInternal: query from $caller") + logD(TAG, "@getArchivedPackageInternal caller: $callingUid $caller, target: $targetApp") + return@hookBefore + } + } + }.onFailure { + logE(TAG, "Fatal error occurred, disable hooks", it) + unload() + } + } + } + + override fun unload() { + hook?.unhook() + hook = null + exphook?.unhook() + exphook = null + } +}