资讯动态

Android R生物识别配置下沉common的坑与正确姿势

发布时间:2026/10/16 3:37:29 来源:尧图企业网站定制
最近有个项目负责人跑来问我Android R里那个config_biometric_sensors能不能图省事放到 common 目录做统一定制他说的 common 不是 AOSP 里的 device/generic/common而是他自己厂商的公共配置目录类似vendor/xxx/common或device/xxx/common这种东西。这个问题听上去简单其实牵扯到框架配置的生效范围、生物识别安全等级和产品线设备的硬件差异。我先直接给结论仅仅为了少写两行配置就把 biometric 配置全量下沉到 common后面大概率要花更多时间填坑但如果有严格前提和覆盖纪律common 定制也不是完全不能用。下面我把这块配置的底层逻辑、实际踩过的坑以及一套更稳妥的落地方式完整说一遍给同样在 Android R 上做系统定制的朋友当个参考。1. 先搞清 config_biometric_sensors 到底在管什么1.1 这个配置的出身framework 层“宣布”设备有哪些生物识别能力在 Android R 里config_biometric_sensors定义在frameworks/base/core/res/res/values/config.xml严格来说是一个字符串数组默认通常为空数组不填任何实际的传感器条目。它的作用是在 framework 层“宣布”这台设备支持哪些生物识别传感器以及这些传感器各自的身份标识、识别模态指纹、人脸、虹膜、安全强度等等。BiometricService初始化的时候会通过 Resources 对象读取这个数组然后在系统内部构建出上层的生物识别能力表。注意“framework 层宣布”这几个字。它不是说“我检测到了什么硬件”而是“我认为这台设备应该暴露什么硬件能力给上层”。这个概念搞不清楚后面很多坑都压不住。以 Android R 的源码状态来看这个数组的每个条目通常会描述一个传感器 ID、模态、强度等级等信息。不同 Android 版本之间的字段顺序和编码格式还有差别Android 11 之后也陆续调整过相关定义。所以从某个分支 Copy 配置到另一个分支时一定要带版本标签不能只看文件名相同就直接搬。我见过有人把 Android 11 的条目原样塞进 Android R结果服务解析时直接忽略掉表现为“设置了指纹项但录入不了”那个排查过程相当折磨人。1.2 影响面比你想的大从设置菜单到支付鉴权都会跟着它走这个数组的消费端不止一个。系统设置的指纹菜单是否需要出现人脸录入入口是否展示锁屏界面的解锁方式组合以及应用调用BiometricPrompt时允许走哪一类认证都会参考这份“能力表”。换句话说配置里写了指纹人脸上层逻辑大概率就会把指纹和人脸都当作可用能力哪怕其中一个传感器物理上不存在。反过来配置里什么都不写也会导致指纹、人脸各项入口全部隐藏系统空有一套硬件但用户永远用不了。这也是为什么厂商定制时不能拍脑袋去覆盖它。它看起来就是一个普通的资源数组但实际上它是安全和功能之间的一个控制开关。你不定义功能不出现你定义错功能就会出现而且是以一种错误的安全等级出现。后面讲的两个坑本质上都是这个原因造成的。1.3 容易混淆的点它和 HAL 层枚举是两套事情硬件到底有没有通常看 HAL 层枚举。比如指纹 HAL 返回是否有空闲模板区域、人脸 HAL 返回感知状态但系统把哪些传感器实例化成对上层可见的能力却受 framework 资源配置的约束。很多人问我“我明明设备里没有前摄像头为什么设置里出现人脸选项”问题就出在这里——你在 Vendor 层查硬件它确实没有可在 framework 层已经被人为“宣布”有了。这就好比公司通讯录里还留着已经离职员工的座机分机号码前台按照通讯录转接电话当然永远没人接。能连通的前提是通讯录和真实工位一致config_biometric_sensors和真实硬件表也必须一致。所以在做任何 common 定制之前先想清楚一件事你定义的这套能力表要同时被多少台硬件配置完全不同的设备继承如果只有一两台且硬件一致那技术风险确实不大如果是一个产品线用那这个问题就必须认真对待。2. “common”目录不是保险箱不同设备的定制边界在哪里2.1 先看 common 在编译系统里的真实位置在 Android 编译系统里“common”这个概念并没有一个统一标准。常见的有几种形态device/vendor/common多个产品 mk 会 include 它vendor/vendor/common多平台共用某些厂商直接在build/make/target/product下面放厂商自己加的公共 makefile还有一类是通过PRODUCT_PACKAGE_OVERLAYS或PRODUCT_ENFORCE_RRO_TARGETS引入的公共 overlay 目录。如果你把config_biometric_sensors放到一个 public overlay 目录并且把它挂到PRODUCT_PACKAGE_OVERLAYS里那所有引用该 mk 的产品都会拿到这份配置。这里的问题在于它不像一个函数函数可以被调用范围限制资源叠加却是“全量继承”的。哪怕你只想让 A 产品用只要 A 和 B 共享了这份公共 mkB 就会一起继承除非 B 自己额外叠加了一层覆盖。在我接触过的项目里很多公共目录的命名非常宽泛比如common_config、shared_overlay里面塞了 UI 主题、开机动画、字体等资源。这些东西放错地方最多是风格不对不致命但 biometric 配置放错地方轻则设置界面出现幽灵入口重则安全等级被错误地放大。2.2 overlay 的叠加顺序产品层永远可以覆盖但前提是你记得覆盖Android 资源叠加的基本原则是越具体的配置优先级越高。一般来说产品专属 overlay 会覆盖厂商公共 overlay公共 overlay 会覆盖 AOSP 默认 framework 资源。也就是说就算 common 里写了一份错误的config_biometric_sensors你仍然可以在具体产品目录里再写一份正确的去覆盖它。听起来问题不大对吧问题在于“你记得覆盖”这件事本身。人不是常驻内存的程序一个产品可以保证覆盖但产品线有七八个产品每个产品每年又出两三个新 SKU谁能保证每一个都检查过我在某合作团队就见过一次公共 overlay 里放了一套支持指纹人脸虹膜的配置三个产品中有一个忘记在自身 mk 里覆盖结果那个产品启动后设置里出现了三个生物识别入口硬件实际只有指纹。拍照留档后这个 Bug 被下游客户直接打回丢脸丢得厉害。2.3 “默认值”思维的误区安全能力不适合有“默认”很多人觉得既然是 default那大家都用同一个值再按需覆盖不就行了。这个思路对于开机动画、默认语言、默认时区完全没问题但对生物识别配置来说非常危险。原因很简单默认值的受众是“大多数场景”而生物识别安全等级必须针对具体硬件精确设置。同样是“指纹”入门级的电容指纹模组和高端的超声波指纹模组在安全强度上可能是两个等级。如果你给它们同一个默认强认证等级等于让低安全传感器承担了高安全职责这在支付、保险柜、企业邮箱等场景下是直接的安全漏洞。所以我一直跟团队强调config_biometric_sensors不应该有“抄作业式”的默认值它应该是一个“必须逐设备确认”的硬性配置项。3. 把生物识别配置一刀切到 common 之后我遇到的两个实际坑3.1 坑一只有指纹的设备设置里出现了“人脸解锁”这个坑出现在某一次中低端产品线适配中代号就叫 A 系列吧。A 系列有两款产品A1 配置了指纹人脸A2 只有指纹属于成本导向的 SKU。当时项目主管为了减少重复配置把 A1 的完整config_biometric_sensors数组直接放进了公共 overlay想着 A2 反正没有人脸硬件系统会自动探测到没有人脸传感器然后隐藏入口。事实完全不是这样。A2 刷机后设置里的“生物识别”页面出现了“人脸解锁”入口点进去后一直卡在“录入准备中”反复提示失败。用户侧反馈是这个产品宣传页没提人脸功能系统里却出现了人脸入口体验非常差。我们当时排查的第一步先在 Vendor 层抓人脸 HAL 日志结果发现人脸服务根本没有初始化也没有对应的硬件节点。第二步去查上层 BiometricService 日志才发现它从 Resources 读到的数组里有人脸条目。第三步用资源反查工具看最终编译出来的 framework-res.apk确认config_biometric_sensors生效值确实包含了人脸。最后的修复很简单A2 自己的产品 overlay 里把数组覆盖成只有指纹。但排查过程整整花了一天多。因为第一反应总是怀疑 HAL 没配对完全没往公共 overlay 的方向想。这个坑告诉我们framework 配置一旦声明了某种能力上层 UI 就会直接暴露它不会先试探硬件是否真的存在。3.2 坑二不同安全等级的传感器被 common 串成了同一档位第二个坑比 UI 幽灵入口更隐蔽也更严重。某个厂商的旗舰和入门款共享了一套公共配置为了让旗舰的强生物识别能力完整表现出来公共 overlay 里把传感器强度统一配置成了“强认证”级别。结果入门款那颗低规格指纹传感器的等级也被抬上去了。表面上一切正常指纹录入、解锁、支付鉴权提示都出现了。直到安全团队抽查时发现入门款的指纹识别居然被系统当成了支付级强认证。按照 Android 生物识别框架的标准强认证指纹必须满足更严格的安全要求比如更高的认假率指标、更完善的防欺骗能力。入门款传感器根本没有达到这个水平系统却给了它一个高权限的身份。后续的结果不出意外整个配置被安全评估打回版本被迫重新适配。这个坑给所有想用 common 统一 biometric 配置的人提了个醒安全强度不是“有没有”的问题而是“够不够”的问题。你没法通过一个公共数组让不同规格的传感器拥有相同的安全性。硬件差异摆在那里调用端却会把它们一视同仁风险就直接被放大了。3.3 一次完整排查链路复盘你可以照着这个思路查如果你也遇到了“配置里有的能力硬件实际没有”的类似问题可以按以下链路排查复现问题。比如设置页面出现了异常生物识别入口点开会失败。先查 HAL 层到底有没有对应硬件。用adb shell dumpsys fingerprint、dumpsys face或者 Vendor 自带的诊断命令确认。如果 HAL 层没有再看 framework 层到底读到了什么。在设备上执行dumpsys biometric或dumpsys BiometricService观察服务注册的传感器描述。从设备上拉取编译产物中的 framework-res.apk用资源 dump 命令过滤config_biometric_sensors数组看生效值。确认生效值错误后根据编译日志反查这个覆盖值来自哪个 overlay 目录。到公共 overlay 目录里确认是不是把全产品线的配置写成一份了。最后在具体产品目录里新增独立 overlay覆盖为正确值重新编译验证。这套链路看起来很长但实际能帮你从“猜”变成“查”。我每次遇到 biometric 相关的诡异问题都强制自己走一遍省下来的时间远超判断的时间。4. 什么情况下 common 定制反而是正确的选择我的衡量标准4.1 可以用 common 的三个前提一件事全盘否定也不对。公共定制并非绝对不行关键在于前提条件是否成立。我总结下来这三个前提缺一不可。第一硬件完全同源。意思是产品线里所有产品的传感器类型、传感器数量、传感器位置、模组厂商都一致。不是说“都有指纹”就行而是指纹模组的供应商和型号也要相同。只有同源模组才有理由认为它们的安全表现是一致的。第二安全等级一致。即使模组型号一样不同产品也可能因为系统版本、底层驱动参数不同而呈现不同的安全表现。如果安全团队对每款产品单独评估过给出的等级都是同一个档位那 common 才安全。第三团队有覆盖纪律。所谓覆盖纪律就是每一个新产品创建时会强制检查是否覆盖了config_biometric_sensors。这个检查不能靠负责人记忆而是要有编译检查或清单流程。做不到这一点哪怕当前产品安全下一个 SKU 也会栽在同一个坑里。4.2 用自检清单代替拍脑袋如果你还在犹豫“要不要放 common”我建议直接用下面这张表判断判断维度适合放 common必须按设备定制传感器类型完全一致有指纹、人脸、虹膜差异传感器数量全部相同不同 SKU 有增减安全等级所有产品经评估为同一等级存在强、弱认证差异HAL 版本同平台同版本不同平台、不同驱动新增产品覆盖机制有自动检查或硬性评审靠人脑记忆业务场景同一市场同一合规要求有支付、企业级安全差异只要有一行落到了右边我就建议不要全量下沉到 common。哪怕最终决定还是要放也要用下一节说的“占位模板”方式而不是直接放真实能力。4.3 折中方案common 只放“安全占位”设备再覆盖真实能力如果产品线确实需要一份公共模板我的做法是把 common 里的config_biometric_sensors设成一个安全占位值。什么叫安全占位就是数组内容为空或者只声明一个最低能力不给强认证等级不声明具体传感器能力。这样做的逻辑是如果某个新产品的负责人忘记覆盖那这个产品呈现出来的状态是“没有生物识别功能”而不是“错误地开启了无法使用或过度授权的功能”。前者只是缺失特性影响可控后者则是功能错误甚至安全漏洞影响不可控。对于低频功能把默认值设计成“关闭”或“空”通常是最安全的。这其实和 Android 本身的很多安全配置思路是一致的默认最小暴露按需打开。5. Android R 里更稳妥的 biometric 配置分离方案与验证方法5.1 推荐目录结构与 MK 配置示例如果你确定要为每个产品分别配置 biometric我建议统一采用“公共占位 产品覆盖”的结构。假设你的厂商目录是vendor/example目录结构可以是这样vendor/example/ ├── common_overlay/ │ └── frameworks/base/core/res/res/values/config.xml ├── product_a/ │ ├── product_a.mk │ └── overlay/ │ └── frameworks/base/core/res/res/values/config.xml └── product_b/ ├── product_b.mk └── overlay/ └── frameworks/base/core/res/res/values/config.xml公共 overlay 里的config.xml内容只保留空数组或者按你产品线的最低能力占位。然后common_overlay通过一个公共 mk 挂到所有产品# vendor/example/common_overlay/common_overlay.mk PRODUCT_PACKAGE_OVERLAYS \ vendor/example/common_overlay具体产品的 mk 里再挂上自己的专属 overlay# vendor/example/product_a/product_a.mk PRODUCT_PACKAGE_OVERLAYS \ vendor/example/product_a/overlay这样做的关键是产品专属 overlay 的优先级高于公共 overlay所以就算公共 overlay 里写了错误配置产品也能覆盖回来。就算产品忘了覆盖因为公共层是空数组它最多表现为“没有生物识别功能”而不会出现幽灵入口或安全等级虚高的问题。这里要特别提醒一点每个产品的config.xml中只要涉及config_biometric_sensors就必须是完整的数组而不是增量补丁。资源叠加是整文件覆盖不是合并数组。你如果在产品 overlay 里只写新人脸条目不写指纹条目那指纹能力会直接消失。这是一个非常容易踩的坑。5.2 构建后验证别等上线才后悔代码改完不代表配置生效构建后一定要验证。我自己常用的方法分两步。第一步在编译输出目录里确认最终资源值。假设你的产品名是product_a编译完成后可以执行aapt2 dump resources \ out/target/product/product_a/system/framework/framework-res.apk \ | grep -A 10 config_biometric_sensors这个命令会把最终合并进 framework-res.apk 的config_biometric_sensors数组内容打印出来。你要人工检查一下里面列出的传感器类型、数量和你要给这台设备定义的能力是否完全一致。第二步烧机后确认运行时的服务注册状态。开机后执行adb shell dumpsys biometric或根据 ROM 情况执行adb shell dumpsys BiometricService看服务实际注册的传感器描述和硬件是否匹配。这一步能排除一个隐蔽情况资源值看起来是对的但服务因为其他原因只注册了部分传感器。只有资源值和运行值两边都对上配置才算真正生效。5.3 我的日常做法配置改动必须挂到产品验收用例里最后分享一个团队协作层面的经验。config_biometric_sensors这种配置光靠 code review 是不可能覆盖所有产品线变化的。因为它受硬件清单影响而硬件清单往往是产品经理和技术经理在另外一套文档里维护的跟代码仓库完全是两个系统。我现在做系统定制时会把 biometric 配置列进“产品验收用例”里。每一项配置变更都要对应一个可执行的验收检查例如设置界面出现的生物识别入口是否与硬件规格书一致每个入口是否能完成录入和解锁每个入口对应的安全等级是否与安全团队评估结论一致新产品加入产品线时有没有重新执行上面三条。把这些检查项固化到项目流程里之后“能不能放 common”就不再是个靠感觉回答的问题而是会变成“有没有满足前提”的问题。至少对我个人来说每次有项目负责人来问这个问题我都会先让团队把产品线的硬件规格表和安全评估报告拉出来对着表格检查一遍。这个过程既能把风险提前暴露也能帮大家建立对资源叠加机制的敬畏心。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑