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.
This commit is contained in:
parent
1b2a52ea94
commit
88f82c9d25
13 changed files with 52 additions and 48 deletions
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
|
|
@ -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'
|
||||
|
|
|
|||
4
.github/workflows/pull_request.yml
vendored
4
.github/workflows/pull_request.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ android {
|
|||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(17)
|
||||
jvmToolchain(21)
|
||||
}
|
||||
|
||||
autoResConfig {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,11 @@
|
|||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme">
|
||||
|
||||
<property
|
||||
android:name="android.adservices.AD_SERVICES_CONFIG"
|
||||
android:resource="@xml/gma_ad_services_config"
|
||||
tools:replace="android:resource" />
|
||||
|
||||
<activity
|
||||
android:name="icu.nullptr.hidemyapplist.ui.activity.AboutActivity"
|
||||
android:theme="@style/AppTheme.About" />
|
||||
|
|
|
|||
|
|
@ -73,9 +73,11 @@ object PackageHelper {
|
|||
mutableMapOf<String, PackageCache>().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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ android {
|
|||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(17)
|
||||
jvmToolchain(21)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
|
|
|
|||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ android {
|
|||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(17)
|
||||
jvmToolchain(21)
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
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.xposed.HMAService
|
||||
import icu.nullptr.hidemyapplist.xposed.logE
|
||||
import icu.nullptr.hidemyapplist.xposed.logI
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.S)
|
||||
class PlatformCompatHook(private val service: HMAService) : IFrameworkHook {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "PlatformCompatHook"
|
||||
private val sAppDataIsolationEnabled = CommonUtils.isAppDataIsolationEnabled
|
||||
}
|
||||
|
||||
private var hook: XC_MethodHook.Unhook? = null
|
||||
|
||||
override fun load() {
|
||||
if (!service.config.forceMountData) return
|
||||
logI(TAG, "Load hook")
|
||||
logI(TAG, "App data isolation enabled: $sAppDataIsolationEnabled")
|
||||
hook = findMethod("com.android.server.compat.PlatformCompat") {
|
||||
name == "isChangeEnabled"
|
||||
}.hookBefore { param ->
|
||||
runCatching {
|
||||
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.result = true
|
||||
logI(TAG, "@startViaZygote force mount data: ${appInfo.uid} $app")
|
||||
return@hookBefore
|
||||
}
|
||||
}
|
||||
}.onFailure {
|
||||
logE(TAG, "Fatal error occurred, disable hooks", it)
|
||||
unload()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun unload() {
|
||||
hook?.unhook()
|
||||
hook = null
|
||||
}
|
||||
|
||||
override fun onConfigChanged() {
|
||||
if (service.config.forceMountData) {
|
||||
if (hook == null) load()
|
||||
} else {
|
||||
if (hook != null) unload()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in a new issue