From 88f82c9d25900673339a67b89c4722aca1237e13 Mon Sep 17 00:00:00 2001 From: Wang Han <416810799@qq.com> Date: Tue, 1 Oct 2024 16:35:16 +0800 Subject: [PATCH] Rewrite hook for force mount data (#297) * Update dependencies * Rewrite hook for force mount data The previous hook point is for startViaZygote(), but the logic in ProcessList.java to determine whether a process is safe to apply force mount is complex, and current implementation has already caused issues. Change the hook point to PlatformCompat and force return true for all sdk level, then we can let system server apply the correct logic. Vold app data isolation does not have sdk level check, so don't touch it, unlink current code. --- .github/workflows/main.yml | 4 +-- .github/workflows/pull_request.yml | 4 +-- app/build.gradle.kts | 2 +- app/src/main/AndroidManifest.xml | 5 +++ .../hidemyapplist/util/PackageHelper.kt | 10 +++--- build.gradle.kts | 8 ++--- common/build.gradle.kts | 2 +- gradle/libs.versions.toml | 33 +++++++++---------- gradle/wrapper/gradle-wrapper.properties | 2 +- xposed/build.gradle.kts | 2 +- .../hidemyapplist/xposed/HMAService.kt | 2 +- .../hidemyapplist/xposed/UserService.kt | 2 +- ...goteArgsHook.kt => FrameworkCompatHook.kt} | 24 +++++++------- 13 files changed, 52 insertions(+), 48 deletions(-) rename xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/{ZygoteArgsHook.kt => FrameworkCompatHook.kt} (64%) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b2bee19..d859b97 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,11 +28,11 @@ jobs: - name: Gradle wrapper validation uses: gradle/wrapper-validation-action@v1 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: '17' + java-version: '21' - name: Write key if: github.event_name != 'pull_request' && github.ref == 'refs/heads/master' diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 4ae15f7..99d9ccd 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -22,10 +22,10 @@ jobs: - name: Gradle wrapper validation uses: gradle/wrapper-validation-action@v1 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v3 with: - java-version: '17' + java-version: '21' distribution: 'temurin' - name: Write properties diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3107530..b5915bd 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -27,7 +27,7 @@ android { } kotlin { - jvmToolchain(17) + jvmToolchain(21) } autoResConfig { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5720c53..62995f5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -16,6 +16,11 @@ android:label="@string/app_name" android:theme="@style/AppTheme"> + + diff --git a/app/src/main/java/icu/nullptr/hidemyapplist/util/PackageHelper.kt b/app/src/main/java/icu/nullptr/hidemyapplist/util/PackageHelper.kt index 268c2b5..4a4faf1 100644 --- a/app/src/main/java/icu/nullptr/hidemyapplist/util/PackageHelper.kt +++ b/app/src/main/java/icu/nullptr/hidemyapplist/util/PackageHelper.kt @@ -73,9 +73,11 @@ object PackageHelper { mutableMapOf().also { for (packageInfo in packages) { if (packageInfo.packageName in Constants.packagesShouldNotHide) continue - val label = pm.getApplicationLabel(packageInfo.applicationInfo).toString() - val icon = hmaApp.appIconLoader.loadIcon(packageInfo.applicationInfo) - it[packageInfo.packageName] = PackageCache(packageInfo, label, icon) + packageInfo.applicationInfo?.let { appInfo -> + val label = pm.getApplicationLabel(appInfo).toString() + val icon = hmaApp.appIconLoader.loadIcon(appInfo) + it[packageInfo.packageName] = PackageCache(packageInfo, label, icon) + } } } } @@ -110,6 +112,6 @@ object PackageHelper { } fun isSystem(packageName: String): Boolean = runBlocking { - packageCache.first()[packageName]!!.info.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0 + packageCache.first()[packageName]?.info?.applicationInfo?.flags?.and(ApplicationInfo.FLAG_SYSTEM) != 0 } } diff --git a/build.gradle.kts b/build.gradle.kts index 2861949..f73c345 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,16 +24,16 @@ val gitCommitCount = "git rev-list HEAD --count".execute().toInt() val gitCommitHash = "git rev-parse --verify --short HEAD".execute() val minSdkVer by extra(24) -val targetSdkVer by extra(34) -val buildToolsVer by extra("34.0.0") +val targetSdkVer by extra(35) +val buildToolsVer by extra("35.0.0") val appVerName by extra("3.2") val configVerCode by extra(90) val serviceVerCode by extra(96) val minBackupVerCode by extra(65) -val androidSourceCompatibility = JavaVersion.VERSION_17 -val androidTargetCompatibility = JavaVersion.VERSION_17 +val androidSourceCompatibility = JavaVersion.VERSION_21 +val androidTargetCompatibility = JavaVersion.VERSION_21 val localProperties = Properties() localProperties.load(file("local.properties").inputStream()) diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 24cad7e..b157aa9 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -25,7 +25,7 @@ android { } kotlin { - jvmToolchain(17) + jvmToolchain(21) } dependencies { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 333c371..2ab3c85 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,25 +1,25 @@ [versions] -agp = "8.3.2" -kotlin = "1.9.0" -rxhttp = "3.0.6" -hidden-api = "4.2.0" +agp = "8.6.1" +kotlin = "2.0.20" +rxhttp = "3.3.0" +hidden-api = "4.3.3" [plugins] agp-app = { id = "com.android.application", version.ref = "agp" } agp-lib = { id = "com.android.library", version.ref = "agp" } kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } -ksp = { id = "com.google.devtools.ksp", version = "1.9.0-1.0.11" } -gms = { id = "com.google.gms.google-services", version = "4.3.15" } -nav-safeargs-kotlin = { id = "androidx.navigation.safeargs.kotlin", version = "2.6.0" } +ksp = { id = "com.google.devtools.ksp", version = "2.0.20-1.0.25" } +gms = { id = "com.google.gms.google-services", version = "4.4.2" } +nav-safeargs-kotlin = { id = "androidx.navigation.safeargs.kotlin", version = "2.8.1" } autoresconfig = { id = "dev.rikka.tools.autoresconfig", version = "1.2.2" } materialthemebuilder = { id = "dev.rikka.tools.materialthemebuilder", version = "1.3.3" } refine = { id = "dev.rikka.tools.refine", version = "4.3.0" } [libraries] -androidx-navigation-fragment-ktx = { module = "androidx.navigation:navigation-fragment-ktx", version = "2.5.3" } -androidx-navigation-ui-ktx = { module = "androidx.navigation:navigation-ui-ktx", version = "2.5.3" } -androidx-preference-ktx = { module = "androidx.preference:preference-ktx", version = "1.2.0" } +androidx-navigation-fragment-ktx = { module = "androidx.navigation:navigation-fragment-ktx", version = "2.8.1" } +androidx-navigation-ui-ktx = { module = "androidx.navigation:navigation-ui-ktx", version = "2.8.1" } +androidx-preference-ktx = { module = "androidx.preference:preference-ktx", version = "1.2.1" } androidx-swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version = "1.1.0" } com-android-tools-build-apksig = { module = "com.android.tools.build:apksig", version.ref = "agp" } com-drakeet-about = { module = "com.drakeet.about:about", version = "2.5.2" } @@ -29,17 +29,16 @@ com-github-kyuubiran-ezxhelper = { module = "com.github.kyuubiran:EzXHelper", ve com-github-liujingxing-rxhttp = { module = "com.github.liujingxing.rxhttp:rxhttp", version.ref = "rxhttp" } com-github-liujingxing-rxhttp-compiler = { module = "com.github.liujingxing.rxhttp:rxhttp-compiler", version.ref = "rxhttp" } com-github-liujingxing-rxhttp-converter-serialization = { module = "com.github.liujingxing.rxhttp:converter-serialization", version.ref = "rxhttp" } -com-github-topjohnwu-libsu-core = { module = "com.github.topjohnwu.libsu:core", version = "5.0.3" } -com-google-android-material = { module = "com.google.android.material:material", version = "1.7.0" } -com-google-android-gms-play-services-ads = { module = "com.google.android.gms:play-services-ads", version = "22.2.0" } -com-google-firebase-firebase-analytics-ktx = { module = "com.google.firebase:firebase-analytics-ktx", version = "21.2.0" } -com-google-firebase-bom = { module = "com.google.firebase:firebase-bom", version = "32.1.1" } +com-github-topjohnwu-libsu-core = { module = "com.github.topjohnwu.libsu:core", version = "6.0.0" } +com-google-android-material = { module = "com.google.android.material:material", version = "1.12.0" } +com-google-android-gms-play-services-ads = { module = "com.google.android.gms:play-services-ads", version = "23.4.0" } +com-google-firebase-bom = { module = "com.google.firebase:firebase-bom", version = "33.3.0" } com-google-firebase-analytics-ktx = { module = "com.google.firebase:firebase-analytics-ktx" } -com-squareup-okhttp3 = { module = "com.squareup.okhttp3:okhttp", version = "4.10.0" } +com-squareup-okhttp3 = { module = "com.squareup.okhttp3:okhttp", version = "4.12.0" } de-robv-android-xposed-api = { module = "de.robv.android.xposed:api", version = "82" } dev-rikka-hidden-compat = { module = "dev.rikka.hidden:compat", version.ref = "hidden-api" } dev-rikka-hidden-stub = { module = "dev.rikka.hidden:stub", version.ref = "hidden-api" } dev-rikka-rikkax-material = { module = "dev.rikka.rikkax.material:material", version = "2.7.0" } dev-rikka-rikkax-material-preference = { module = "dev.rikka.rikkax.material:material-preference", version = "2.0.0" } -kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version = "1.5.1" } +kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version = "1.7.1" } me-zhanghai-android-appiconloader = { module = "me.zhanghai.android.appiconloader:appiconloader", version = "1.5.0" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a80b22c..df97d72 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/xposed/build.gradle.kts b/xposed/build.gradle.kts index 91e07ed..265e053 100644 --- a/xposed/build.gradle.kts +++ b/xposed/build.gradle.kts @@ -18,7 +18,7 @@ android { } kotlin { - jvmToolchain(17) + jvmToolchain(21) } afterEvaluate { 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 160ec1f..88996c5 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/HMAService.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/HMAService.kt @@ -116,7 +116,7 @@ class HMAService(val pms: IPackageManager) : IHMAService.Stub() { } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - frameworkHooks.add(ZygoteArgsHook(this)) + frameworkHooks.add(PlatformCompatHook(this)) } frameworkHooks.forEach(IFrameworkHook::load) diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/UserService.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/UserService.kt index a1e4019..6568967 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/UserService.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/UserService.kt @@ -54,7 +54,7 @@ object UserService { 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)) { + if (!Utils.verifyAppSignature(appPackage.applicationInfo?.sourceDir.toString())) { logE(TAG, "Fatal: App signature mismatch") return } diff --git a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/ZygoteArgsHook.kt b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/FrameworkCompatHook.kt similarity index 64% rename from xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/ZygoteArgsHook.kt rename to xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/FrameworkCompatHook.kt index 7b54126..71d77ec 100644 --- a/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/ZygoteArgsHook.kt +++ b/xposed/src/main/java/icu/nullptr/hidemyapplist/xposed/hook/FrameworkCompatHook.kt @@ -1,23 +1,22 @@ package icu.nullptr.hidemyapplist.xposed.hook import android.annotation.TargetApi +import android.content.pm.ApplicationInfo import android.os.Build import com.github.kyuubiran.ezxhelper.utils.findMethod import com.github.kyuubiran.ezxhelper.utils.hookBefore import de.robv.android.xposed.XC_MethodHook import icu.nullptr.hidemyapplist.common.CommonUtils -import icu.nullptr.hidemyapplist.common.Constants.* import icu.nullptr.hidemyapplist.xposed.HMAService import icu.nullptr.hidemyapplist.xposed.logE import icu.nullptr.hidemyapplist.xposed.logI @TargetApi(Build.VERSION_CODES.S) -class ZygoteArgsHook(private val service: HMAService) : IFrameworkHook { +class PlatformCompatHook(private val service: HMAService) : IFrameworkHook { companion object { - private const val TAG = "ZygoteArgsHook" + private const val TAG = "PlatformCompatHook" private val sAppDataIsolationEnabled = CommonUtils.isAppDataIsolationEnabled - private val sVoldAppDataIsolationEnabled = CommonUtils.isVoldAppDataIsolationEnabled } private var hook: XC_MethodHook.Unhook? = null @@ -26,19 +25,18 @@ class ZygoteArgsHook(private val service: HMAService) : IFrameworkHook { if (!service.config.forceMountData) return logI(TAG, "Load hook") logI(TAG, "App data isolation enabled: $sAppDataIsolationEnabled") - logI(TAG, "Vold app data isolation enabled: $sVoldAppDataIsolationEnabled") - hook = findMethod("android.os.ZygoteProcess") { - name == "startViaZygote" + hook = findMethod("com.android.server.compat.PlatformCompat") { + name == "isChangeEnabled" }.hookBefore { param -> runCatching { - val uid = param.args[2] as Int - if (uid == UID_SYSTEM) return@hookBefore - val apps = service.pms.getPackagesForUid(uid) ?: return@hookBefore + val changeId = param.args[0] as Long + val appInfo = param.args[1] as ApplicationInfo + if (changeId.toInt() != 143937733) return@hookBefore + val apps = service.pms.getPackagesForUid(appInfo.uid) ?: return@hookBefore for (app in apps) { if (service.isHookEnabled(app)) { - if (sAppDataIsolationEnabled) param.args[20] = true // boolean bindMountAppsData - if (sVoldAppDataIsolationEnabled) param.args[21] = true // boolean bindMountAppStorageDirs - logI(TAG, "@startViaZygote force mount data: $uid $app") + if (sAppDataIsolationEnabled) param.result = true + logI(TAG, "@startViaZygote force mount data: ${appInfo.uid} $app") return@hookBefore } }