Some optimizations and fixes

- Avoid HMA wake up at background due to uid listener
- Add appUid checker for register to detect mismatching package name changes
- Remove signature verifier codes
- Other fixes and improvements
This commit is contained in:
frknkrc44 2025-09-26 21:50:31 +03:00
commit 62677a7bd8
No known key found for this signature in database
GPG key ID: 784AE1CC0DCFD34F
3 changed files with 44 additions and 88 deletions

View file

@ -1,16 +1,13 @@
import com.android.ide.common.signing.KeystoreHelper
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import java.io.PrintStream
import java.util.Locale
plugins {
alias(libs.plugins.agp.lib)
alias(libs.plugins.refine)
alias(libs.plugins.kotlin)
}
val appPackageName: String by rootProject.extra
android {
namespace = "org.frknkrc44.hma_oss.xposed"
namespace = "$appPackageName.xposed"
buildFeatures {
buildConfig = false
@ -21,51 +18,10 @@ kotlin {
jvmToolchain(21)
}
afterEvaluate {
//noinspection WrongGradleMethod
android.libraryVariants.forEach { variant ->
val variantCapped = variant.name.replaceFirstChar { it.titlecase(Locale.ROOT) }
val variantLowered = variant.name.lowercase(Locale.ROOT)
val outSrcDir = layout.buildDirectory.dir("generated/source/signInfo/${variantLowered}")
val outSrc = outSrcDir.get().file("icu/nullptr/hidemyapplist/Magic.java")
val signInfoTask = tasks.register("generate${variantCapped}SignInfo") {
outputs.file(outSrc)
doLast {
val sign = android.buildTypes[variantLowered].signingConfig
outSrc.asFile.parentFile.mkdirs()
val certificateInfo = KeystoreHelper.getCertificateInfo(
sign?.storeType,
sign?.storeFile,
sign?.storePassword,
sign?.keyPassword,
sign?.keyAlias
)
PrintStream(outSrc.asFile).apply {
println("package icu.nullptr.hidemyapplist;")
println("public final class Magic {")
print("public static final byte[] magicNumbers = {")
val bytes = certificateInfo.certificate.encoded
print(bytes.joinToString(",") { it.toString() })
println("};")
println("}")
}
}
}
variant.registerJavaGeneratingTask(signInfoTask, outSrcDir.get().asFile)
val kotlinCompileTask = tasks.findByName("compile${variantCapped}Kotlin") as KotlinCompile
kotlinCompileTask.dependsOn(signInfoTask)
val srcSet = objects.sourceDirectorySet("magic", "magic").srcDir(outSrcDir)
kotlinCompileTask.source(srcSet)
}
}
dependencies {
implementation(projects.common)
implementation(libs.androidx.annotation.jvm)
implementation(libs.com.android.tools.build.apksig)
implementation(libs.com.github.kyuubiran.ezxhelper)
implementation(libs.dev.rikka.hidden.compat)
compileOnly(libs.de.robv.android.xposed.api)

View file

@ -28,19 +28,18 @@ object UserService {
if (uid != appUid) return
try {
val provider = ActivityManagerApis.getContentProviderExternal(Constants.PROVIDER_AUTHORITY, 0, null, null)
if (provider == null) {
logE(TAG, "Failed to get provider")
return
assert (provider != null) {
"Failed to get provider"
}
val extras = Bundle()
extras.putBinder("binder", HMAService.instance)
val reply = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val attr = AttributionSource.Builder(1000).setPackageName("android").build()
provider.call(attr, Constants.PROVIDER_AUTHORITY, "", null, extras)
provider?.call(attr, Constants.PROVIDER_AUTHORITY, "", null, extras)
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R) {
provider.call("android", null, Constants.PROVIDER_AUTHORITY, "", null, extras)
provider?.call("android", null, Constants.PROVIDER_AUTHORITY, "", null, extras)
} else {
provider.call("android", Constants.PROVIDER_AUTHORITY, "", null, extras)
provider?.call("android", Constants.PROVIDER_AUTHORITY, "", null, extras)
}
if (reply == null) {
logE(TAG, "Failed to send binder to app")
@ -54,14 +53,19 @@ object UserService {
}
fun register(pms: IPackageManager) {
logI(TAG, "Initialize HMAService - Version ${BuildConfig.SERVICE_VERSION}")
logI(TAG, "Initialize HMAService - Version ${BuildConfig.APP_VERSION_NAME}")
val service = HMAService(pms)
appUid = Utils.getPackageUidCompat(service.pms, Constants.APP_PACKAGE_NAME, 0, 0)
val appPackage = Utils.getPackageInfoCompat(service.pms, Constants.APP_PACKAGE_NAME, 0, 0)
if (!Utils.verifyAppSignature(appPackage.applicationInfo?.sourceDir.toString())) {
logE(TAG, "Fatal: App signature mismatch")
try {
appUid = Utils.getPackageUidCompat(service.pms, BuildConfig.APP_PACKAGE_NAME, 0, 0)
assert(appUid >= 0) {
"App UID cannot be -1 or lower"
}
} catch (e: Throwable) {
logE(TAG, "Fatal: Cannot get package details\nCompile this app from source with your changes", e)
return
}
logD(TAG, "Client uid: $appUid")
logI(TAG, "Register observer")
@ -69,7 +73,7 @@ object UserService {
ActivityManagerApis.registerUidObserver(
uidObserver,
ActivityManagerHidden.UID_OBSERVER_ACTIVE,
ActivityManagerHidden.PROCESS_STATE_UNKNOWN,
ActivityManagerHidden.PROCESS_STATE_TOP,
null
)
}

View file

@ -16,13 +16,15 @@ import icu.nullptr.hidemyapplist.xposed.logI
class ActivityHook(private val service: HMAService) : IFrameworkHook {
companion object {
private const val TAG = "ActivityHook"
private val fakeReturnCode = getStaticIntField(
findClass(
"android.app.ActivityManager",
InitFields.ezXClassLoader
),
"START_INTENT_NOT_RESOLVED"
)
private val fakeReturnCode by lazy {
getStaticIntField(
findClass(
"android.app.ActivityManager",
InitFields.ezXClassLoader
),
"START_INTENT_NOT_RESOLVED"
)
}
}
private var hook: XC_MethodHook.Unhook? = null