Skip to content

fix(redirect): 修复 HarmonyOS 上安装重定向被系统 Resolver 吞掉 - #31

Merged
Chimioo merged 1 commit into
Chimioo:mainfrom
waittide:fix/harmonyos-resolver-hijack
Oct 18, 2026
Merged

Chimioo merged 1 commit into
Chimioo:mainfrom
waittide:fix/harmonyos-resolver-hijack

Conversation

@waittide

Copy link
Copy Markdown
Contributor

问题

Fixes #7

在 HarmonyOS / EMUI(测试环境:DBY-W09 / HarmonyOS 4.2.0.208 / Android 12)上,InxLocker 的安装拦截看起来生效但结果被吞掉:日志显示 Intent 的 package 已被改成目标安装器,但系统最终仍启动 com.huawei.android.internal.app/.HwResolverActivity。

补充一点:issue 里贴的 NoSuchFieldException: No field mRequest in class LcOm/android/server/wm/HwActivityStarter; 是 V1.4(YukiHookAPI 时代,用 getDeclaredField 不回溯父类)的旧栈,V1.5 的 findField 递归实现已经让它不再出现。V1.5+ 在鸿蒙上的真实症状是这个 resolver 劫持。

根因

该 ROM 在 PMS 的 resolve 侧对安装类 Intent 强制注入自家 Resolver。实测矩阵(adb 逐条验证):

命令 结果
am start -a VIEW -t application/vnd.android.package-archive -d file:///sdcard/test.apk -p io.github.muntashirakon.AppManager ❌ HwResolverActivity
同上但 -p com.huawei.hinote(完全无关的包) ❌ HwResolverActivity
-n io.github.muntashirakon.AppManager/.apk.installer.PackageInstallerActivity(显式 component) ✅ 正常启动
cmd package query-activities --brief -a VIEW -t application/vnd.android.package-archive ✅ 正常返回 7 个候选

即:只给 package 不给 component 的安装类 Intent 永远到不了目标安装器,query 侧正常、resolve 侧被劫持。

修改

新增 app/src/main/java/io/github/chimio/inxlocker/util/ComponentResolver.kt:

  1. 先探测:用 resolveActivity 看系统会解析到谁
    • 解析到目标包 → 不动(正常 ROM 行为完全不变)
    • 解析不到 → 不动
    • 解析到非 OEM Resolver → 不动(AOSP 上多候选时的 ResolverActivity 仍交给用户选)
    • 解析到 *HwResolverActivity → 说明被劫持,进下一步
  2. 选候选:queryIntentActivities 取目标包 exported 的候选,按类名关键字打分
    • packageinstaller +100、install +50、intercept +20
    • scanner/viewer/explorer/details/manifest/share/settings/… −100
    • 得分 < 50 且候选 > 1 时放弃,不擅自替用户选择
  3. 下发显式 component,绕过 resolve 侧的劫持

配套改动:

  • IntentRedirector.kt — 在只设 package 之后尝试解析;同时把 normalizeAction() 提到解析之前,保证按最终的 VIEW 而非 INSTALL_PACKAGE 匹配候选
  • PrefsProvider.kt / HookEntry.kt / MainActivity.kt — 安装器/卸载器/强制组件变更与热重载时 ComponentResolver.invalidate()
  • IntentRedirector.kt 日志增加 - Target component:

性能

ActivityStarter.execute 执行时持有 mGlobalLock,所以结果按 package|action|type|scheme|categories 缓存 60 秒(上限 128 条),配置变更立即失效。

验证

release 版(minifyEnabled + shrinkResources)装到 DBY-W09 / HarmonyOS 4.2.0.208 实测:

I ComponentResolver: System resolved Intent {... pkg=io.github.muntashirakon.AppManager}
    to com.huawei.android.internal.app/HwResolverActivity, falling back to explicit component
I ComponentResolver: Pick io.github.muntashirakon.AppManager/.apk.installer.PackageInstallerActivity (score=150) from 6 candidate(s)
I InstallerRedirect: Using explicit component to bypass resolver hijack: ...
mResumedActivity: io.github.muntashirakon.AppManager/.apk.installer.PackageInstallerActivity

风险

改动只在「系统会解析到 OEM 自家 Resolver」时才生效,AOSP 路径的逻辑分支没有任何变化。仍建议在 AOSP 设备上回归一次。

- 现象: 鸿蒙 4.2 上 InxLocker 把安装 Intent 的 package 改成目标安装器后,
  系统仍无视 package 将其交给 com.huawei.android.internal.app.HwResolverActivity,
  重定向完全失效(issue Chimioo#7)。
- 根因: 该 ROM 在 PMS 的 resolve 侧对安装类 Intent 强制注入自家 Resolver,
  只给 package 而不给 component 的 Intent 永远到不了目标安装器;query 侧正常。
- 组件解析: 新增 ComponentResolver,先探测系统会解析到谁,仅在解析结果落在
  OEM 自家 Resolver 时才从 queryIntentActivities 的候选里挑出真正的安装入口
  并下发显式 component;AOSP 上解析正常时行为完全不变。
- 候选打分: 按类名关键字加权(packageinstaller/install/intercept)并对
  scanner/viewer/explorer 等无关界面降权,得分不足时不擅自替用户选择。
- 性能: 按 package/action/type/scheme/categories 缓存 60 秒,
  避免在持有 mGlobalLock 的 ActivityStarter.execute 里反复查询 PMS。
- action 规范化: 提前到解析之前,保证按最终的 VIEW 而非 INSTALL_PACKAGE 匹配候选。
- 缓存失效: 安装器/卸载器/强制组件配置变更与热重载时清空缓存。
@Chimioo
Chimioo merged commit ae279bd into Chimioo:main Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

鸿蒙4.2上无法正常工作

2 participants