如何在设备无屏幕的情况下确认升级成功或失败?

解读

国内无屏 Android 设备(OTT 盒子、智能音箱、车载中控、IoT 模组、POS 机)量产时,既不能让用户看屏幕,也不能插 USB 线,只能靠系统自身在“黑盒”状态里给出确定性结果。面试官想确认两点:

  1. 你是否熟悉 Android 升级全链路(A/B 无缝、Recovery、update_engine、BootControl HAL、vbmeta 验证)。
  2. 你是否能在没有屏幕、没有 ADB 的“现场”里,给出可量产、可回捞、可灰度的方案。
    因此回答必须围绕“本地自证+远端可验证”双通道展开,兼顾工厂老化房、售后返修、OTA 灰度三种场景。

知识点

  1. A/B 无缝升级机制:update_engine 把 payload 写到 slot B,写完后设置 bootable 标志,重启时 bootloader 切换槽位,首次进入 Android 后标记 SUCCESSFUL。
  2. 升级结果持久化位置:
    /misc/ota 或 /metadata/ota 存放 update_engine 的 last_status、last_error_code;
    /data/ota/log 保存详细日志;
    SettingsProvider 中 ota_success 字段。
  3. 硬件“心跳”通道:
    LED 三色灯、蜂鸣器、马达、UART 串口、CAN 报文、以太网广播包、Wi-Fi SoftAP beacon 里打 tag。
  4. 工厂老化脚本:通过串口或 adb-over-tcp 轮询 getprop | grep ota,30 秒内必须读到 ro.boot.slot_suffix 切换且 ota_result=SUCCESS。
  5. 售后黑盒日志回捞:
    开机 5 分钟内如果未标记 SUCCESS,则把 /data/ota/log 压缩成 .gz,通过 MQTT 上报到厂商 OTA 后台;
    同时把 last_error_code 映射成 2 位十六进制写入 NFC 标签,维修人员手机碰一碰即可读。
  6. 灰度熔断:后台统计同一版本 error_code=20(哈希树校验失败)超过 3‰,自动停灰度并回滚 slot。

答案

量产方案分三步:
第一步,本地自证。升级包里预埋一个 post-install 脚本,由 update_engine 在切换槽位前执行,把版本号、CRC、时间戳写入 /misc/ota_result;首次启动 init.rc 里启动一个 ota_mon 服务,若 30 秒内检测到 ro.boot.ota_success=1,则点亮绿色 LED 2 秒并写 /data/ota/flag=SUCCESS;否则红灯快闪 3 次,蜂鸣器 1 长 2 短,同时把 last_error_code 写入 NFC 标签。

第二步,远端可验证。ota_mon 继续把结果封装成 128 字节 UDP 广播包(含 SN、版本、结果、CRC),工厂老化房上位机统一采集;若设备带 4G,则通过 MQTT 主题 /device/<sn>/ota 上报,后台 Dashboard 实时刷新。

第三步,异常回捞。如果连续 3 次重启仍无法进入新系统,bootloader 自动回退原槽位,并把 rollback_reason 写入 misc 分区;维修人员拆机后串口输入 fastboot oem dump_ota_log 即可拉取完整日志,无需屏幕。

一句话总结:用 LED/蜂鸣器做现场“眼睛”,用 misc 分区和 MQTT 做事后“黑匣子”,实现无屏场景下的升级结果可感知、可回捞、可灰度熔断。

拓展思考

  1. 如果设备连 LED 都没有,仅有一颗 SOC GPIO,如何在一元硬币大小的 PCB 上让产线工人肉眼区分结果?
    答:把 GPIO 做成 1 Hz 方波输出,用工厂测试治具的光敏探头读取脉冲数:成功 5 个脉冲,失败 10 个脉冲,零成本。

  2. 国内运营商要求 OTT 盒子升级失败率<0.3%,如何在大规模灰度阶段提前发现?
    答:在 update_engine 里插桩,把每 5% 进度点的写入耗时、温度、电压作为特征向量上报,后台用孤立森林算法实时异常检测,30 秒内即可触发停灰度。