ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Android 12 sensor_fusion脚本调试实战:adb与SELinux避坑指南

Android 12 sensor_fusion脚本调试实战:adb与SELinux避坑指南 Android 12原生系统上调试sensor_fusion测试脚本前前后后折腾了大半个月踩了不少坑也把常用的adb调试套路理顺了。这篇东西不写虚的全是实际调试中能直接拿来用的命令、思路和报错解法尤其针对Android 12上新增的一些权限和SELinux限制给正在做传感器相关测试、或者被脚本跑不起来搞得头疼的朋友一个参考。先说清楚这篇文章解决什么问题你要跑一个sensor_fusion相关的测试脚本但不知道脚本应该放在哪、怎么执行、日志去哪抓、权限怎么给更烦的是执行过程中冒出一堆莫名其妙的报错。这篇文章就是围绕这条链路从adb连接到脚本运行再到日志分析和常见异常处理完整走一遍并给出可以直接“抄作业”的解决方案。1. 先搞清楚sensor_fusion测试脚本到底在测什么1.1 传感器融合的业务背景sensor_fusion在Android系统里不是一个独立的app它涉及的是系统底层传感器HAL、传感器hal到framework之间的数据通路以及算法层面的加速度计、陀螺仪、磁力计等多路数据融合。这类测试脚本通常用于验证设备在静止、运动、旋转等场景下融合算法输出的姿态数据是否平滑、是否满足精度指标或者用于自动化老化测试长时间跑下来看传感器数据有没有漂移、卡死或异常跳变。从我接触的项目来看sensor_fusion测试脚本常见三种形态纯shell脚本、需要Python解释器的脚本、以及基于Android instrumentation的测试用例。不同形态的调试方式差异很大后面会分别展开。但不管哪种形态最终都绕不开adb这个调试通道因为脚本要被推送到设备上执行或者通过adb shell触发。1.2 脚本的典型组成和调试目标一个常见的手写sensor_fusion测试脚本通常包含这几部分设置传感器采样率、读取传感器数据可能是通过dumpsys sensorservice、sensor HAL节点或直接调用NDK接口、做算法处理或数据统计、记录异常日志。调这种脚本目标就三个跑起来、结果可信、日志能定位问题。需要特别提醒的是Android 12上传感器相关的测试脚本权限模型和执行环境都收紧了不少。以前可能直接 adb shell 进去敲几行命令就能跑通现在经常遇到permission denied、avc denied、甚至脚本根本无可执行权限的问题。这些不是脚本本身写错了而是系统安全策略变了得用对方法绕过或适配。2. Android 12带来的调试环境变化2.1 权限模型与包管理相关改动Android 12在传感器权限上做了一些收紧比如对传感器数据访问需要更精确的运行时权限声明对后台访问传感器数据加了限制部分传感器类型在后台进程拿不到数据。如果你的测试脚本是打包成apk通过am instrument跑的那manifest里的权限声明就要格外注意。常见的坑是明明在老的Android版本上跑得好好的换到Android 12上就SecurityException很大概率是缺少了对应的运行时权限或者没有在代码里动态申请。另外Android 12对前台服务启动限制更严格了如果你的测试脚本依赖一个后台服务来持续采集传感器数据可能被系统直接杀掉或者收不到数据。我之前遇到过一次脚本启动了SensorManager监听但log里什么都打不出来后来发现是服务被系统判定为后台限制需要改成前台服务或者用其他方式保持采集。2.2 adb调试方式的典型坑Android 12上的adb调试本身没有太大变化但有几个细节很容易被忽略。一个是adb root权限的问题很多定制系统或正式固件默认锁掉了adb root导致你无法直接访问/sys节点或者/data目录下的传感器节点。遇到这种情况先看 adb root 是否生效不生效就需要找工程固件或者利用设备的root方案否则后续的节点读写操作都会失败。另一个是adb授权问题。Android 12上新连接的设备默认是unauthorized状态需要在设备上弹窗确认授权。这个问题对测试工程师来说太常见了尤其是用usb hub同时接多台设备的时候经常出现弹窗被遮挡、授权超时的情况。后面详细介绍解决方案。3. 核心实操搭建调试链路并跑通脚本3.1 第一步确认设备连接与授权调试的第一件事永远是确认adb能看到设备而且状态是device。用 adb devices 看一眼正常会输出设备序列号和device状态。如果看到unauthorized就先检查手机上是否弹了“允许USB调试”的对话框确认一下。如果确认了还是unauthorized就用 adb kill-server 然后 adb start-server 重启adb服务再 adb devices 重新看。如果设备一直显示offline这种情况多半是adb版本太旧、USB线质量差或者USB接口供电不足。我处理过很多次换一根好的USB线、换个直连的USB口问题就解决了。还有一个容易被忽视的就是Android 12设备的USB调试模式需要在“开发者选项”里把“USB调试”和“USB安装”都打开部分设备还要关掉“监控ADB安装应用”这类安全选项。提示多设备调试建议给每台设备设置不同的adb端口用 adb -s 序列号 shell 指定设备操作避免命令发错设备导致误操作。3.2 第二步推送脚本到指定目录并赋权脚本不要直接放在/sdcard下跑因为Android 12对/sdcard的执行权限有限制即使你chmod x也不一定能执行。标准做法是推送到 /data/local/tmp/ 目录下这个目录专门放临时测试文件可读可写还可以加执行权限。adb push sensor_fusion_test.sh /data/local/tmp/ adb shell chmod 755 /data/local/tmp/sensor_fusion_test.sh如果脚本是Python写的设备上没有python解释器你就得在PC端跑或者用adb shell sh/exec的方式伪执行。我在实际项目中遇到比较多的情况是脚本是shell写的但里面有dos格式的换行符导致在设备上执行时报“bad interpreter”或者“not found”。这个问题防不胜防因为Windows下编辑的脚本经常自带\r\n而Linux/Android只认\n。解决办法也不难在PC上用dos2unix或者sed处理一下再push。3.3 第三步运行并抓取关键信息一切就绪后执行脚本优先用 sh 脚本路径 而不是直接 ./脚本路径这样即使用户态执行也不会因为可执行位缺失而报Permission denied。以shell脚本为例adb shell sh /data/local/tmp/sensor_fusion_test.sh跑起来不等于调试完事你还得知道传感器数据流是不是正常的。抓日志最常用的就是adb logcat但logcat的buffer非常嘈杂建议按关键字过滤一下比如传感器相关进程、Sensors HAL、SensorService相关的TAGadb logcat -c adb shell /data/local/tmp/sensor_fusion_test.sh adb logcat -d | grep -iE sensor|Sensors|SensorService|Fusion如果脚本需要长时间运行做老化测试建议加上输出重定向把运行的中间输出写到设备本地最后再pull到PC分析adb shell sh /data/local/tmp/sensor_fusion_test.sh /data/local/tmp/result.log 21 adb pull /data/local/tmp/result.log这里有个细节不管日志输出到哪个目录确保该目录有写权限。/data/local/tmp下正常没问题但如果脚本内部把日志写到了/system或/vendor下Android 12的分区只读机制会让你直接写失败报Read-only file system后面详细说。3.4 延伸通过am instrument跑测试用例的情况如果sensor_fusion测试脚本是打包成Android instrumentation测试的那执行方式就变成了am instrument还需要指定测试包名和类名adb shell am instrument -w -r -e class com.example.sensorfusion.MainTest com.example.sensorfusion.test/androidx.test.runner.AndroidJUnitRunner这种方式的优点是权限体系完全由应用和manifest管理跑起来更像真实场景。缺点也很明显Android 12对instrumentation有一些限制比如后台读取传感器数据可能被抑制manifest里targetSdkVersion不能太高否则动态权限处理必须到位。如果测试用例直接被系统杀掉优先看logcat里有没有am_kill相关的记录定位是内存问题还是权限问题。4. 常见报错对照与解决方案下面这块内容可以说是整个调试过程的精华部分每一个报错都是实际遇到过的我按层级分类整理方便大家直接对照排查。4.1 adb连接层报错报错1adb devices 显示 unauthorized这个报错概率极高。处理思路是先看设备屏幕有没有弹窗有就点允许。如果弹窗没出现在开发者选项里关掉再打开“USB调试”或者撤销所有USB调试授权后重连。还有一种比较隐蔽的情况就是你电脑上的adb公钥变了设备端还保留着旧授权导致每次都unauthorized。解决办法是拔掉USB线在设备上“撤销USB调试授权”重新插线后设备会重新弹窗确认。对无人值守的设备老化测试场景这步非常烦人建议直接做成自动化用adb -s 序列号 keygen生成固定密钥对并把公钥放到设备的 /data/misc/adb/adb_keys 里这样就不用每次弹窗确认了。报错2device offline设备显示offline先考虑adb服务状态和老旧进程。adb kill-server 和 adb start-server 重启一下基本能解决。其次是USB线或接口问题换线和接口。还有一个Android 12上特有的场景设备屏幕锁屏后自动断开adb。有的品牌定制系统有这个策略需要去开发者选项里打开“USB调试(安全设置)”或者关闭“锁屏后自动断开adb”。4.2 脚本执行层报错报错3sh: /data/local/tmp/sensor_fusion_test.sh: inaccessible or not found这个报错最容易让人懵因为文件明明存在。常见原因是脚本的换行符是CRLF或者脚本第一行的shebang路径写错了。比如写的是 #!/bin/bash但Android上不一定有/bin/bash只有/bin/sh所以会执行失败。解决办法是统一改成 #!/system/bin/sh 或者直接用 adb shell sh xxx.sh 方式执行绕开shebang问题。CRLF的话先在PC上用sed -i s/\r$// 清理再推送。报错4Permission denied如果文件存在、权限也给了755还是Permission denied就要看SELinux了。相比老版本Android 12的SELinux策略更严从shell上下文执行/data/local/tmp下的脚本通常是允许的但脚本内部如果写了/sys节点或/vendor下的文件就会触发avc denied。先通过 dmesg | grep avc 或者 logcat 里搜 avc 关键字找到具体被拒绝的type和目标然后要想办法放行策略或者选择合法的路径进行测试。注意生产环境不建议关闭SELinux即使能adb root也不建议 setenforce 0。这条命令虽然能临时规避大量avc报错但会让测试环境和实际使用环境的安全策略不一致导致测试结果失真而且有安全隐患。真要调试优先去查SELinux policy的配置方法。4.3 权限与SELinux层报错报错5avc: denied { read } for pidxxx scontextu:r:shell:s0 tcontextu:object_r:sysfs_sensors:s0这种报错基本都是脚本想读取/sys目录下的传感器节点但SELinux策略不允许。调试阶段可以先用adb shell setenforce 0临时验证是否是SELinux导致确认后用allow规则或者供应商的init脚本调整策略。另外检查一下你是不是在一直使用/sys节点而Framework层已经不走了。Android 12上很多传感器数据通过hidl/aidl HAL上报/sys节点读取只能是辅助手段如果sensor_fusion测试脚本强依赖节点读取建议考虑用dumpsys sensorservice输出数据。报错6Read-only file systemAndroid 12的系统分区是只读挂载的除非你remount否则根本没法往/system、/vendor写文件。如果脚本要生成配置文件就统一写/data/local/tmp如果真要改系统文件在可root的工程机上执行 adb root 然后 adb remount但remount之后改坏了系统分区会比较麻烦建议先做备份。生产机器不要随便remount这个操作跟系统升级挂钩容易把签名校验弄坏。4.4 测试结果分析层报错报错7logcat里完全没有传感器数据输出脚本跑完了结果文件是空的或者logcat里搜不到sensor相关的log。先看脚本有没有真正执行成功可以通过 lastlog、dumpsys activity 等确认进程有没有起来。然后确认传感器HAL是否正常用 adb shell dumpsys sensorservice 看服务是否在线、有哪些传感器注册。如果sensorservice崩溃重启多半是HAL层的问题需要抓tombstone和HAL日志进一步分析。报错8脚本超时或卡死sensor_fusion测试脚本最怕的就是无限等待传感器数据而Android 12在息屏状态下会暂停部分传感器的数据上报导致脚本一直等不到新数据。解决办法是亮屏状态下跑测试或者用 adb shell svc power stayon true 让屏幕保持常亮。如果是长时间老化测试还要注意Android 12的Doze模式进入Doze后会批量抑制非白名单应用的数据接收测试进程很可能被挂起。建议用 adb shell dumpsys deviceidle disable 临时禁掉Doze模式。5. 一些使用技巧和最后的经验除了上面的报错排查再分享几个平时用的顺手技巧。技巧1善用dumpsys sensorservice这个命令是排查传感器问题的神器。跑sensor_fusion测试脚本之前先执行 adb shell dumpsys sensorservice确认传感器列表、当前活动传感器、客户端的连接状态。跑完脚本后再执行一次对比前后的活跃连接和数据统计能快速判断脚本是否真的拿到了数据。adb shell dumpsys sensorservice | grep -A 20 Active sensors技巧2自动化跑批的推进建议多设备长期老化测试纯手工敲命令太累了。我现在习惯把整条链路做成一个PC端shell脚本依次执行设备连接检测、APK/脚本安装、进程拉起、日志抓取、结果拉取、设备重启。这样设备越多效率提升越明显。注意每台设备用序列号区分写入一个设备列表文件循环处理。技巧3区分可靠性与一致性测试如果是做sensor_fusion的精度验证就把脚本跑在稳定固定的温度环境和标准台架上保证数据的可对比性。如果是做老化可靠性测试就把脚本设计成连续运行加自动重启检查的模式关注数据是否跳变、算法是否发散、日志是否增长异常。这两种用途的脚本设计思路不同调试侧重点也不同别混在一起测。技巧4善用busybox辅助Android系统的工具箱功能比较精简很多Linux命令不支持。遇到脚本里使用了一些特殊命令比如timeout、seq、awk的高级用法在Android上大概率会报command not found。提前在PC上把命令检查一遍或者直接给设备装上busybox放到/data/local/tmp/然后 export PATH 指定到该目录能省掉不少兼容性上的麻烦。最后说点实在的在Android 12上调试sensor_fusion这类涉及底层传感器的测试脚本本质上拼的不是技术难度而是对系统权限模型和资源限制的熟悉程度。很多看着像是脚本语法或者adb连接的问题深挖下去都是SELinux策略、分区只读、Doze机制这些系统级的东西在起作用。建议各位在做传感器相关测试之前先把项目的SELinux模式、设备是否可root、系统分区是否可写这几件事摸清楚确认测试环境边界后再动手跑脚本能少走很多弯路。如果测试过程中遇到我这里没写到的报错重点去查dmesg和logcat里对应时间戳的kernel日志几乎所有底层被拒的原因都会在那里留下记录。
返回列表