20260703----Android14-----关于开发OTA APP的权限问题

1. 核心问题

在开发基于 Android 14 的 OTA 升级应用时,发现自定义 App 即使声明了系统权限并使用了平台签名,在调用 UpdateEngine 时依然崩溃,报错 DeadSystemException,并在 Logcat 中出现大量 SELinux 的 avc: denied 拒绝记录。

按常规逻辑,开发者通常会尝试通过修改系统源码增加 system_app 的 SE 权限(如 allow update_engine system_app:fd use;),但这种做法破坏了 AOSP 的原生安全策略,且在过认证(CTS/VTS)时极易失败。

2. 破案过程:原厂 App 的秘密

通过对比全志(Allwinner)和 Amlogic(晶晨)两大主流 SoC 芯片厂商自带的 OTA 升级应用,发现了惊人的统一性:

全志(Allwinner)原厂测试:

bash 复制代码
ps -AZ | grep com.softwinner.update

结果显示:

bash 复制代码
u:r:platform_app:s0:c512,c768  u0_a64  ... com.softwinner.update

Amlogic(晶晨)原厂测试:

bash 复制代码
ps -AZ | grep com.droidlogic.updater

结果显示:

bash 复制代码
u:r:platform_app:s0:c512,c768  u0_a42  ... com.droidlogic.updater

关键发现:

原厂升级 App 竟然都不是 system_app!

它们无一例外都运行在 platform_app 域。

3. 深度解析:为什么原厂不选 system_app?

身份 (Domain) 构成条件 SELinux 特性

system_app 平台签名 + sharedUserId="android.uid.system" 受 Google 原生 neverallow 严格限制,禁止向底层 Service 传递非标准路径的 FD。

platform_app 仅使用平台签名,不加系统 UID 厂商(SoC 供应商)通常会在 SDK 源码中为这个域预留"后门"权限。

真相: 芯片厂商在定制底层的 sepolicy 策略时,已经预先为 platform_app 授予了调用 update_engine 和传递文件句柄(FD)的权限。如果你强行将自己的 App 变成 system_app,反而会因为"身份不符"被拦截。

4. 实战结论:如何正确"借力"原厂权限?

在开发 OTA App 时,不需要去改系统源码加权限,只需要"伪装"成和原厂一样的身份:

  1. 放弃 system UID(最关键)
    在 AndroidManifest.xml 中删除以下配置:
bash 复制代码
<!-- 必须删掉这一行,否则你会进入 system_app 域 -->
android:sharedUserId="android.uid.system"
  1. 保持平台签名
    虽然放弃了系统 UID,但必须使用厂商提供的 platform.pk8 / platform.x509.pem 进行签名。
    只要有平台签名,应用就会自动运行在 platform_app 域。
    只要有平台签名,你申请的 android.permission.REBOOT 等高级权限依然有效。
  2. 结果验证
    重签安装后,通过 adb shell ps -AZ | grep 你的包名 确认。只要看到第一列是 u:r:platform_app:s0,你就已经站在了厂商预设的"特权通道"上,UpdateEngine 即可丝滑运行。
  3. 经验总结
    在 Android 系统开发中,遇到权限问题时:
    先看原厂怎么做:ps -AZ 是查看应用"真实身份"的神器。
    身份匹配 > 暴力加权:与其费劲去撸 SELinux 策略,不如直接更改 App 的身份,复用芯片厂商已经跑通的授权路径。
    平台 App 是最优解:对于 OTA 这种需要高权限但又涉及文件句柄传递的应用,平台签名 + 非系统 UID 的 platform_app 模式是兼容性最好的方案。
    💡 记录: 20260703 - 已在 Android 14 系统上验证,方案有效。