diff --git a/app/build.gradle b/app/build.gradle index d0bb4ece..65daca49 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,8 +12,8 @@ android { applicationId "com.tsng.hidemyapplist" minSdkVersion 24 targetSdkVersion 30 - versionCode 16 - versionName "1.4.1" + versionCode 17 + versionName "1.4.2" } buildTypes { diff --git a/app/src/main/cpp/NativeHooks.cpp b/app/src/main/cpp/NativeHooks.cpp index b50c90e1..517269c5 100644 --- a/app/src/main/cpp/NativeHooks.cpp +++ b/app/src/main/cpp/NativeHooks.cpp @@ -95,7 +95,9 @@ bool isHideFile(const char *path) { std::regex_search(path, std::regex("/storage/emulated/(.*)/TWRP"))) return true; if (tpl.HideAllApps && - std::regex_search(path, std::regex("/storage/emulated/(.*)/Android/data/"))) + (std::regex_search(path, std::regex("/storage/emulated/(.*)/Android/data/")) || + std::regex_search(path, std::regex("/data/data/")) || + std::regex_search(path, std::regex("/data/user/")))) return true; for (const auto &pkg : tpl.HideApps) if (strstr(path, pkg.c_str()) != nullptr) diff --git a/app/src/main/java/com/tsng/hidemyapplist/ui/AboutActivity.kt b/app/src/main/java/com/tsng/hidemyapplist/ui/AboutActivity.kt index bb7eaaa3..d4d3f226 100644 --- a/app/src/main/java/com/tsng/hidemyapplist/ui/AboutActivity.kt +++ b/app/src/main/java/com/tsng/hidemyapplist/ui/AboutActivity.kt @@ -29,11 +29,13 @@ class AboutActivity : AbsAboutActivity() { items.add(Card(getString(R.string.about_hook_differences_description))) items.add(Category(getString(R.string.about_developer))) - items.add(Contributor(R.drawable.avatar, "Dr.TSNG", "Developer", "https://github.com/Dr-TSNG")) + items.add(Contributor(R.drawable.about_author, "Dr.TSNG", "Developer", "https://github.com/Dr-TSNG")) items.add(Category(getString(R.string.about_support))) items.add(Card("Github Page\nhttps://github.com/Dr-TSNG/Hide-My-Applist")) items.add(Line()) + items.add(Card("Telegram Group\nhttps://t.me/HideMyApplist")) + items.add(Line()) items.add(Card("CoolMarket\nhttps://www.coolapk.com/u/1911298")) items.add(Category(getString(R.string.about_open_source))) diff --git a/app/src/main/java/com/tsng/hidemyapplist/xposed/hooks/PackageManagerService.kt b/app/src/main/java/com/tsng/hidemyapplist/xposed/hooks/PackageManagerService.kt index fc89b1b4..cfc03057 100644 --- a/app/src/main/java/com/tsng/hidemyapplist/xposed/hooks/PackageManagerService.kt +++ b/app/src/main/java/com/tsng/hidemyapplist/xposed/hooks/PackageManagerService.kt @@ -10,6 +10,7 @@ import com.tsng.hidemyapplist.JSONPreference import com.tsng.hidemyapplist.xposed.XposedUtils.Companion.APPNAME import com.tsng.hidemyapplist.xposed.XposedUtils.Companion.getRecursiveField import com.tsng.hidemyapplist.xposed.XposedUtils.Companion.ld +import com.tsng.hidemyapplist.xposed.XposedUtils.Companion.le import com.tsng.hidemyapplist.xposed.XposedUtils.Companion.li import com.tsng.hidemyapplist.xposed.XposedUtils.Companion.resultIllegal import com.tsng.hidemyapplist.xposed.XposedUtils.Companion.resultNo @@ -31,6 +32,7 @@ class PackageManagerService : IXposedHookLoadPackage { var initialized = false var data = JSONPreference() lateinit var context: Context + lateinit var mLock: Any fun receiveJson(str: String) { initialized = true @@ -76,21 +78,23 @@ class PackageManagerService : IXposedHookLoadPackage { override fun afterHookedMethod(param: MethodHookParam) { val callerUid = Binder.getCallingUid() if (callerUid < Process.FIRST_APPLICATION_UID) return - val callerName = XposedHelpers.callMethod(param.thisObject, "getNameForUid", callerUid) as String? - if (!isUseHook(callerName, hookName)) return - var isHidden = false - val iterator = (param.result as ParceledListSlice<*>).list.iterator() - val removed = mutableListOf() - while (iterator.hasNext()) { - val str = getRecursiveField(iterator.next(), pkgNameObjList) as String? - if (isToHide(callerName, str)) { - iterator.remove() - isHidden = true - if (data.DetailLog) removed.add(str!!) + synchronized(mLock) { + val callerName = XposedHelpers.callMethod(param.thisObject, "getNameForUid", callerUid) as String? + if (!isUseHook(callerName, hookName)) return + var isHidden = false + val iterator = (param.result as ParceledListSlice<*>).list.iterator() + val removed = mutableListOf() + while (iterator.hasNext()) { + val str = getRecursiveField(iterator.next(), pkgNameObjList) as String? + if (isToHide(callerName, str)) { + iterator.remove() + isHidden = true + if (data.DetailLog) removed.add(str!!) + } } + if (isHidden) li("@Hide PKMS caller: $callerName method: ${param.method.name}") + if (isHidden && data.DetailLog) ld("removeList $removed") } - if (isHidden) li("@Hide PKMS caller: $callerName method: ${param.method.name}") - if (isHidden && data.DetailLog) ld("removeList $removed") } }) } @@ -100,11 +104,13 @@ class PackageManagerService : IXposedHookLoadPackage { override fun beforeHookedMethod(param: MethodHookParam) { val callerUid = Binder.getCallingUid() if (callerUid < Process.FIRST_APPLICATION_UID) return - val callerName = XposedHelpers.callMethod(param.thisObject, "getNameForUid", callerUid) as String? - if (!isUseHook(callerName, hookName)) return - if (isToHide(callerName, param.args[0] as String?)) { - param.result = result - li("@Hide PKMS caller: $callerName method: ${param.method.name} param: ${param.args[0]}") + synchronized(mLock) { + val callerName = XposedHelpers.callMethod(param.thisObject, "getNameForUid", callerUid) as String? + if (!isUseHook(callerName, hookName)) return + if (isToHide(callerName, param.args[0] as String?)) { + param.result = result + li("@Hide PKMS caller: $callerName method: ${param.method.name} param: ${param.args[0]}") + } } } }) @@ -115,37 +121,39 @@ class PackageManagerService : IXposedHookLoadPackage { override fun beforeHookedMethod(param: MethodHookParam) { val callerUid = Binder.getCallingUid() if (callerUid < Process.FIRST_APPLICATION_UID) return - val callerName = XposedHelpers.callMethod(param.thisObject, "getNameForUid", callerUid) as String? - val arg = param.args[0] as String? ?: return - when { - /* 服务模式,执行自定义行为 */ - arg == "checkHMAServiceVersion" -> param.result = BuildConfig.VERSION_CODE.toString() - arg == "getPreference" -> param.result = data.toString() - arg.contains("providePreference") -> { - receiveJson(arg.split("#")[1]) - param.result = resultYes - } - arg.contains("callIsUseHook") -> { - val split = arg.split("#") - if (split.size != 3) param.result = resultIllegal - else param.result = if (isUseHook(split[1], split[2])) resultYes else resultNo - } - arg.contains("callIsToHide") -> { - val split = arg.split("#") - if (split.size != 3) param.result = resultIllegal - else param.result = if (isToHide(split[1], split[2])) resultYes else resultNo - } - arg.contains("callIsHideFile") -> { - val split = arg.split("#") - if (split.size != 3) param.result = resultIllegal - else param.result = if (isHideFile(split[1], split[2])) resultYes else resultNo - } - /* 非服务模式,正常hook */ - else -> { - if (!isUseHook(callerName, "API requests")) return - if (isToHide(callerName, param.args[0] as String?)) { - param.result = null - li("@Hide PKMS caller: $callerName method: ${param.method.name} param: ${param.args[0]}") + synchronized(mLock) { + val callerName = XposedHelpers.callMethod(param.thisObject, "getNameForUid", callerUid) as String? + val arg = param.args[0] as String? ?: return + when { + /* 服务模式,执行自定义行为 */ + arg == "checkHMAServiceVersion" -> param.result = BuildConfig.VERSION_CODE.toString() + arg == "getPreference" -> param.result = data.toString() + arg.contains("providePreference") -> { + receiveJson(arg.split("#")[1]) + param.result = resultYes + } + arg.contains("callIsUseHook") -> { + val split = arg.split("#") + if (split.size != 3) param.result = resultIllegal + else param.result = if (isUseHook(split[1], split[2])) resultYes else resultNo + } + arg.contains("callIsToHide") -> { + val split = arg.split("#") + if (split.size != 3) param.result = resultIllegal + else param.result = if (isToHide(split[1], split[2])) resultYes else resultNo + } + arg.contains("callIsHideFile") -> { + val split = arg.split("#") + if (split.size != 3) param.result = resultIllegal + else param.result = if (isHideFile(split[1], split[2])) resultYes else resultNo + } + /* 非服务模式,正常hook */ + else -> { + if (!isUseHook(callerName, "API requests")) return + if (isToHide(callerName, param.args[0] as String?)) { + param.result = null + li("@Hide PKMS caller: $callerName method: ${param.method.name} param: ${param.args[0]}") + } } } } @@ -155,7 +163,17 @@ class PackageManagerService : IXposedHookLoadPackage { /* 载入PackageManagerService */ override fun afterHookedMethod(param: MethodHookParam) { context = XposedHelpers.getObjectField(param.thisObject, "mContext") as Context - li("System hook installed") + try { //Android 11+ + mLock = XposedHelpers.getObjectField(param.thisObject, "mLock") + } catch (e: NoSuchFieldError) { + try { // Android 10- + mLock = XposedHelpers.getObjectField(param.thisObject, "mPackages") + } catch (e: NoSuchFieldError) { // Strange custom ROM, should not happen + le("Unknown mLock field, running with self lock") + mLock = Any() + } + } + li("System hook installed (Version ${BuildConfig.VERSION_CODE})") thread { li("Waiting for preference provider") while (!initialized) { @@ -191,21 +209,23 @@ class PackageManagerService : IXposedHookLoadPackage { override fun afterHookedMethod(param: MethodHookParam) { val callerUid = Binder.getCallingUid() if (callerUid < Process.FIRST_APPLICATION_UID) return - val callerName = XposedHelpers.callMethod(param.thisObject, "getNameForUid", callerUid) as String? - if (!isUseHook(callerName, "ID detections")) return - if (param.result != null) { - var change = false - val list = mutableListOf() - val removed = mutableListOf() - for (str in param.result as Array) - if (isToHide(callerName, str)) { - change = true - if (data.DetailLog) removed.add(str) - } else list.add(str) - if (change) { - param.result = list.toTypedArray() - li("@Hide PKMS caller: $callerName method: ${param.method.name}") - if (data.DetailLog) ld("removeList $removed") + synchronized(mLock) { + val callerName = XposedHelpers.callMethod(param.thisObject, "getNameForUid", callerUid) as String? + if (!isUseHook(callerName, "ID detections")) return + if (param.result != null) { + var change = false + val list = mutableListOf() + val removed = mutableListOf() + for (str in param.result as Array) + if (isToHide(callerName, str)) { + change = true + if (data.DetailLog) removed.add(str) + } else list.add(str) + if (change) { + param.result = list.toTypedArray() + li("@Hide PKMS caller: $callerName method: ${param.method.name}") + if (data.DetailLog) ld("removeList $removed") + } } } } diff --git a/app/src/main/res/drawable/about_author.png b/app/src/main/res/drawable/about_author.png new file mode 100644 index 00000000..86a325f5 Binary files /dev/null and b/app/src/main/res/drawable/about_author.png differ diff --git a/app/src/main/res/drawable/avatar.png b/app/src/main/res/drawable/avatar.png deleted file mode 100644 index 29f1a2cb..00000000 Binary files a/app/src/main/res/drawable/avatar.png and /dev/null differ diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 9cf9c841..af04e464 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -14,12 +14,9 @@ 新版本特性 请仔细阅读关于页面的使用帮助!\n - V1.4.1\n - [+] 更改System Hook入口函数\n - [+] 已初步实现Native hook(momo的检测方法太强了,暂时无法拦截)\n - V1.4\n - 由于降低了API版本,模块数据保存位置发生了改变,需要重新配置\n - [+] 现在Xposed API小于93的用户也能使用本模块了(包括太极阳)\n - [+] 添加排除Webview功能以避免内置浏览器崩溃\n + 提示:除了拦截文件检测外,不需要在EdXposed/LSPosed作用域中勾选目标APP\n + V1.4.2\n + [+] 修复一些卡开机/崩溃问题\n + [+] 已初步实现Native hook\n \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index efad7b70..b4dce27e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -14,12 +14,9 @@ New features Please read the about page carefully!\n - V1.4.1\n - [+] Changed System Hook initialization method\n - [+] Elementarily realizes Native hook (Still cannot bypass momo TWRP detection)\n - V1.4\n - Due to the downgrade of API version, the storage location of module data has changed and the templates need to be reconfigured\n - [+] Finally, users of Xposed API lower than 93 can also enjoy this module now\n - [+] Add exclude webview to prevent crashes of internal browsers\n + Tint: Except for intercepting file detections, there is no need to check target apps in EdXposed/LSPosed module scope\n + V1.4.2\n + [+] Fix crashes on some devices\n + [+] Elementarily realizes Native hook \ No newline at end of file