Try to improve getPackagesHoldingPermissions performance, fix logging

This commit is contained in:
frknkrc44 2025-09-27 19:53:20 +03:00
commit f13dff47c2
No known key found for this signature in database
GPG key ID: 784AE1CC0DCFD34F
5 changed files with 259 additions and 4 deletions

View file

@ -19,6 +19,7 @@ import icu.nullptr.hidemyapplist.xposed.hook.IFrameworkHook
import icu.nullptr.hidemyapplist.xposed.hook.PlatformCompatHook
import icu.nullptr.hidemyapplist.xposed.hook.PmsHookTarget28
import icu.nullptr.hidemyapplist.xposed.hook.PmsHookTarget30
import icu.nullptr.hidemyapplist.xposed.hook.PmsHookTarget31
import icu.nullptr.hidemyapplist.xposed.hook.PmsHookTarget33
import icu.nullptr.hidemyapplist.xposed.hook.PmsHookTarget34
import icu.nullptr.hidemyapplist.xposed.hook.PmsPackageEventsHook
@ -145,6 +146,8 @@ class HMAService(val pms: IPackageManager) : IHMAService.Stub() {
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.S) {
frameworkHooks.add(PmsHookTarget31(this))
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
frameworkHooks.add(PmsHookTarget30(this))
} else {
@ -222,15 +225,15 @@ class HMAService(val pms: IPackageManager) : IHMAService.Stub() {
if (caller == null || query == null) return 0
val appConfig = config.scope[caller] ?: return 0
if (!appConfig.hideInstallationSource) return 0
logD(TAG, "@shouldHideInstallationSource $caller -> $query")
logD(TAG, "@shouldHideInstallationSource $caller: $query")
if (caller == query && appConfig.excludeTargetInstallationSource) return 0
try {
val uid = Utils.getPackageUidCompat(pms, query, 0L, user.hashCode())
logD(TAG, "@shouldHideInstallationSource UID for $caller (${user.hashCode()}) -> $query: $uid")
logD(TAG, "@shouldHideInstallationSource UID for $caller, ${user.hashCode()}: $query, $uid")
if (uid < 0) return 0 // invalid package installation source request
} catch (e: Throwable) {
logD(TAG, "@shouldHideInstallationSource UID error for $caller (${user.hashCode()})", e)
logD(TAG, "@shouldHideInstallationSource UID error for $caller, ${user.hashCode()}", e)
return 0
}

View file

@ -17,7 +17,10 @@ class Utils4Xposed {
}
fun getCallingApps(service: HMAService): Array<String> {
val callingUid = Binder.getCallingUid()
return getCallingApps(service, Binder.getCallingUid())
}
fun getCallingApps(service: HMAService, callingUid: Int): Array<String> {
if (callingUid == Constants.UID_SYSTEM) return arrayOf()
return Utils.binderLocalScope {
service.pms.getPackagesForUid(callingUid)

View file

@ -1,9 +1,11 @@
package icu.nullptr.hidemyapplist.xposed.hook
import android.os.Binder
import android.os.Build
import androidx.annotation.RequiresApi
import com.github.kyuubiran.ezxhelper.utils.findConstructor
import com.github.kyuubiran.ezxhelper.utils.findMethod
import com.github.kyuubiran.ezxhelper.utils.findMethodOrNull
import com.github.kyuubiran.ezxhelper.utils.hookBefore
import com.github.kyuubiran.ezxhelper.utils.paramCount
import icu.nullptr.hidemyapplist.common.Constants
@ -50,6 +52,57 @@ class PmsHookTarget30(service: HMAService) : PmsHookTargetBase(service) {
override fun load() {
logI(TAG, "Load hook")
/*
findMethodOrNull("com.android.server.pm.PackageManagerService") {
name == "checkPermission"
}?.hookBefore { param ->
val targetApp = param.args[1] as String
val callingApps = Utils4Xposed.getCallingApps(service)
for (caller in callingApps) {
if (service.shouldHide(caller, targetApp)) {
logD(TAG, "@checkPermission - PkgMgr: insecure query from $caller to $targetApp")
param.result = PackageManager.PERMISSION_DENIED
service.filterCount++
return@hookBefore
}
}
}
findMethodOrNull("com.android.server.pm.permission.PermissionManagerService", findSuper = true) {
name == "checkPermission"
}?.hookBefore { param ->
val targetApp = param.args[1] as String
val callingApps = Utils4Xposed.getCallingApps(service)
for (caller in callingApps) {
if (service.shouldHide(caller, targetApp)) {
logD(TAG, "@checkPermission - PkgMgr: insecure query from $caller to $targetApp")
param.result = PackageManager.PERMISSION_DENIED
service.filterCount++
return@hookBefore
}
}
}
*/
findMethodOrNull("com.android.server.pm.PackageManagerService", findSuper = true) {
name == "getPackageSetting"
}?.hookBefore { param ->
val targetApp = param.args[0] as String
val callingUid = Binder.getCallingUid()
val callingApps = Utils4Xposed.getCallingApps(service, callingUid)
for (caller in callingApps) {
if (service.shouldHide(caller, targetApp)) {
logD(TAG, "@getPackageSetting - PkgMgr: insecure query from $caller to $targetApp")
param.result = null
service.filterCount++
return@hookBefore
}
}
}?.let {
hooks += it
}
hooks += findMethod("com.android.server.pm.AppsFilter") {
name == "shouldFilterApplication"
}.hookBefore { param ->

View file

@ -0,0 +1,152 @@
package icu.nullptr.hidemyapplist.xposed.hook
import android.os.Binder
import android.os.Build
import androidx.annotation.RequiresApi
import com.github.kyuubiran.ezxhelper.utils.findConstructor
import com.github.kyuubiran.ezxhelper.utils.findMethod
import com.github.kyuubiran.ezxhelper.utils.findMethodOrNull
import com.github.kyuubiran.ezxhelper.utils.hookBefore
import com.github.kyuubiran.ezxhelper.utils.paramCount
import icu.nullptr.hidemyapplist.common.Constants
import icu.nullptr.hidemyapplist.common.Constants.VENDING_PACKAGE_NAME
import icu.nullptr.hidemyapplist.common.Utils
import icu.nullptr.hidemyapplist.xposed.HMAService
import icu.nullptr.hidemyapplist.xposed.Utils4Xposed
import icu.nullptr.hidemyapplist.xposed.logD
import icu.nullptr.hidemyapplist.xposed.logE
import icu.nullptr.hidemyapplist.xposed.logI
@RequiresApi(Build.VERSION_CODES.S)
class PmsHookTarget31(service: HMAService) : PmsHookTargetBase(service) {
companion object {
private const val TAG = "PmsHookTarget31"
}
override val fakeSystemPackageInstallInfo: Any by lazy {
findConstructor(
"android.content.pm.InstallSourceInfo"
) {
paramCount == 4
}.newInstance(
null,
null,
null,
null,
)
}
override val fakeUserPackageInstallInfo: Any by lazy {
findConstructor(
"android.content.pm.InstallSourceInfo"
) {
paramCount == 4
}.newInstance(
VENDING_PACKAGE_NAME,
psSigningInfo,
VENDING_PACKAGE_NAME,
VENDING_PACKAGE_NAME,
)
}
override fun load() {
logI(TAG, "Load hook")
/*
findMethodOrNull("com.android.server.pm.PackageManagerService") {
name == "checkPermission"
}?.hookBefore { param ->
val targetApp = param.args[1] as String
val callingApps = Utils4Xposed.getCallingApps(service)
for (caller in callingApps) {
if (service.shouldHide(caller, targetApp)) {
logD(TAG, "@checkPermission - PkgMgr: insecure query from $caller to $targetApp")
param.result = PackageManager.PERMISSION_DENIED
service.filterCount++
return@hookBefore
}
}
}
findMethodOrNull("com.android.server.pm.permission.PermissionManagerService", findSuper = true) {
name == "checkPermission"
}?.hookBefore { param ->
val targetApp = param.args[0] as String
val callingApps = Utils4Xposed.getCallingApps(service)
for (caller in callingApps) {
if (service.shouldHide(caller, targetApp)) {
logD(TAG, "@checkPermission - PermMgr: insecure query from $caller to $targetApp")
param.result = PackageManager.PERMISSION_DENIED
service.filterCount++
return@hookBefore
}
}
}
*/
findMethodOrNull("com.android.server.pm.PackageManagerService\$ComputerTracker") {
name == "getPackageSetting"
}?.hookBefore { param ->
val targetApp = param.args[0] as String
val callingUid = Binder.getCallingUid()
val callingApps = Utils4Xposed.getCallingApps(service, callingUid)
for (caller in callingApps) {
if (service.shouldHide(caller, targetApp)) {
logD(TAG, "@getPackageSetting - Computer: insecure query from $caller to $targetApp")
param.result = null
service.filterCount++
return@hookBefore
}
}
}?.let {
hooks += it
}
findMethodOrNull("com.android.server.pm.PackageManagerService\$ComputerTracker") {
name == "getPackageSettingInternal"
}?.hookBefore { param ->
val targetApp = param.args[0] as String
val callingUid = param.args[1] as Int
val callingApps = Utils4Xposed.getCallingApps(service, callingUid)
for (caller in callingApps) {
if (service.shouldHide(caller, targetApp)) {
logD(TAG, "@getPackageSettingInternal - Computer: insecure query from $caller to $targetApp")
param.result = null
service.filterCount++
return@hookBefore
}
}
}?.let {
hooks += it
}
hooks += findMethod("com.android.server.pm.AppsFilter") {
name == "shouldFilterApplication"
}.hookBefore { param ->
runCatching {
val callingUid = param.args[0] as Int
if (callingUid == Constants.UID_SYSTEM) return@hookBefore
val callingApps = Utils.binderLocalScope {
service.pms.getPackagesForUid(callingUid)
} ?: return@hookBefore
val targetApp = Utils4Xposed.getPackageNameFromPackageSettings(param.args[2])
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()
}
}
super.load()
}
}

View file

@ -3,17 +3,24 @@ package icu.nullptr.hidemyapplist.xposed.hook
import android.content.pm.PackageManager
import android.os.Binder
import android.os.Build
import android.util.ArrayMap
import com.github.kyuubiran.ezxhelper.utils.findMethod
import com.github.kyuubiran.ezxhelper.utils.findMethodOrNull
import com.github.kyuubiran.ezxhelper.utils.hookAfter
import com.github.kyuubiran.ezxhelper.utils.hookBefore
import de.robv.android.xposed.XC_MethodHook
import de.robv.android.xposed.XposedHelpers
import icu.nullptr.hidemyapplist.common.Constants
import icu.nullptr.hidemyapplist.common.Constants.VENDING_PACKAGE_NAME
import icu.nullptr.hidemyapplist.common.Utils
import icu.nullptr.hidemyapplist.xposed.HMAService
import icu.nullptr.hidemyapplist.xposed.Utils4Xposed
import icu.nullptr.hidemyapplist.xposed.logD
import java.util.concurrent.atomic.AtomicReference
abstract class PmsHookTargetBase(protected val service: HMAService) : IFrameworkHook {
private val TAG by lazy { this::class.java.simpleName }
protected val hooks = mutableListOf<XC_MethodHook.Unhook>()
protected var lastFilteredApp: AtomicReference<String?> = AtomicReference(null)
@ -30,6 +37,43 @@ abstract class PmsHookTargetBase(protected val service: HMAService) : IFramework
abstract val fakeUserPackageInstallInfo: Any?
override fun load() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
hooks += findMethod("com.android.server.pm.ComputerEngine") {
name == "getPackageStates"
}.hookAfter { param ->
val callingUid = Binder.getCallingUid()
if (callingUid == Constants.UID_SYSTEM) return@hookAfter
val callingApps = Utils4Xposed.getCallingApps(service)
for (caller in callingApps) {
if (service.isHookEnabled(caller)) {
logD(TAG, "@getPackageStates: incoming query from $caller")
val result = param.result as ArrayMap<*, *>
val markedToRemove = mutableListOf<Any>()
for (pair in result.entries) {
val value = pair.value
val packageName = XposedHelpers.callMethod(value, "getPackageName") as String
if (service.shouldHide(caller, packageName)) {
markedToRemove.add(pair.key)
}
}
if (markedToRemove.isNotEmpty()) {
val copyResult = ArrayMap(result)
copyResult.removeAll(markedToRemove)
logD(TAG, "@getPackageStates: removed ${markedToRemove.size} entries from $caller; ${result.size}, ${copyResult.size}")
param.result = copyResult
service.filterCount++
return@hookAfter
}
}
}
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
findMethodOrNull(service.pms::class.java, findSuper = true) {
name == "getInstallSourceInfo"