手套箱 08 · 速查卡

一页纸速查,所有人用:排查/开发/台架自测手套箱问题前先把这页过一遍。细节推导过程见各专篇,本篇只给结论与命令。

基线声明:

  • 主锚点(W)=/home/zbc/car/fuben4_micarsettings/MiCarSettings-5458412,origin/dev @ 930be9145。本篇行号以此为准。
  • 出货对照=/home/zbc/car/pack_a17_cn_20260923(快照);平台源码=/home/zbc/pangu/xcd_xring_a17_fermi/vendor/micar。
  • 仓内别名:MiCarPropertyIds.DrivingCtrl.GLOVE_BOX = Peripheral.GLOVE_BOX,GLOVE_BOX_TYPE = Peripheral.GLOVE_BOX_LOCK_TYPE_CONFIG(MiCarPropertyIds.java:1485/:1487)。

0. 30 秒心智模型

flowchart TD
    A["点击开箱 Tab"] --> B{"已开?<br/>(GLOVE_BOX==OPEN)"}
    B -->|是| T1["Toast 请手动关闭"]
    B -->|否| C{"有密码?"}
    C -->|无| O["写 GLOVE_BOX=OPEN<br/>+ 埋点 54662 type=1"]
    C -->|有| D{"错误达 5 次?"}
    D -->|否| P["弹 4 位 PIN 框"] -->|验证通过| O2["写 OPEN + 54662 type=2"]
    D -->|是| AV["账号扫码验证<br/>content://mi.car.account"] -->|通过| O3["清零错误次数<br/>写 OPEN + 54662 type=2 + 54663"]
    P -->|错满 5 次| AV
    E["入口显隐"] -.只看.- F["配置字 0x6140b409==2(POWER)"]
    G["MIS 语音/远程"] --> H["GloveBoxNavigationHandler<br/>直写属性,不报 54662"]

一句话:写属性即开箱意图受理,不等回执;关箱只能手动物理合上,App 无「关」路径。

1. propId / 枚举一页纸表

属性hexdec权限(注解)枚举值平台出处
Peripheral.GLOVE_BOX0x6140b4071631630343VENDOR_EXTENSIONOpenClose:CLOSE=0 / OPEN=1Peripheral.java:572-580
Peripheral.GLOVE_BOX_MOTOR_CMD0x6140b4081631630344CAR_INFOGloveBoxMotorCmd:IDLE=0 / CLOCKWISE=1 / COUNTER_CLOCKWISE=2 / BREAK=3Peripheral.java:582-590, 枚举 :1414-1419
Peripheral.GLOVE_BOX_LOCK_TYPE_CONFIG0x6140b4091631630345CAR_INFOGloveBoxLockTypeConfig:MANUAL=1 / POWER=2Peripheral.java:592-600, 枚举 :1421-1424
Peripheral.GLOVE_BOX_UNAVL_REASON0x6140b40a1631630346CAR_INFOGloveBoxUnavlReason:IDLE=0 / NOT_DIS_ARMED=1 / ANTY_PLAY=2Peripheral.java:602-610, 枚举 :1426-1430
Body.GLOVE_BOX_BUTTON_STATUS(物理按键)0x614017811631590273CONTROL_CAR_FEATURESGloveBoxButtonStatus:ERROR=0 / NOT_PRESSED=1 / PRESSED=2 / NO_INFO=3Body.java:1841-1848, 枚举 :6948-6953
Driving.POWER_MODE(门控用)0x614072071631613447CAR_DRIVING_STATEPowerStatus:OFF=0 / AWAKE=1 / ACC=2 / RUN=3(ON=3、START=4 已 @Deprecated)Driving.java:2423-2430, 枚举 :10876-10885

判读要点:

  • GLOVE_BOX 只写 1(OPEN):业务上只有开箱没有关箱,写 0 无意义(openGloveBox 固定写 CommonParams.OpenClose.OPEN,GloveBoxController.kt:222-229)。
  • LOCK_TYPE_CONFIG 是入口总闸:非 POWER 整组移除(VehicleControlSettingsFragment.java:168-172),读取默认 MANUAL(CarConfigManager.kt:139-146)。
  • UNAVL_REASON 只在不可用时才有意义:1=未解锁(未解防)、2=防玩;0(IDLE)与未知值不弹 Toast(见 §5)。
  • 可用性事实标准 = 属性 status == STATUS_AVAILABLE,不是值本身(VehiclePropertyUtil.java:173-182)。
  • 物理按键唯一触发沿 = NOT_PRESSED(1) → PRESSED(2);电源判 ACC/Run 用 ==ACC || ==RUN,禁止 >=ACC(deprecated 的 START=4 会漏过)。
  • dec 值换算已逐个数验算:hex → dec 对照见上表,与 01 篇一致。

2. Settings.Global 三键与清零命令

存储三键(定义于 GloveBoxPasswordTools.kt:33-38,跟车存储,恢复出厂自动清除):

key内容说明
glove_box_passwordSHA-256 哈希非空 = 已设密码;哈希输入是 "[1, 2, 3, 4]" 形式的 IntArray 串(PinPasswordEncryptor.kt:93-100)
glove_box_password_salt时间戳盐System.currentTimeMillis,改密即换盐(PinPasswordEncryptor.kt:52-64)
glove_box_password_wrong_times连续错误次数≥5 锁定转账号验证(PWD_WRONG_MAX_TIMES=5,PinPasswordTools.kt:62)

密码常量一页纸:PIN 4 位(PinPasswordTools.kt:65),验证延迟 200ms(:68),事件 ID 0=CHECK_PWD 验证 / 1=SET_PWD 设置 / 2=CHANGE_PWD 修改 / 3=CHANGE_PWD_VERIFIED 已验证后修改(:50-59,即 param_event_id 取值 :44)。

# 查状态
adb shell settings get global glove_box_password              # null/空 = 未设密码
adb shell settings get global glove_box_password_wrong_times  # >=5 = 锁定中
# 清零锁定(台架高频):清键 + 杀进程,两步缺一不可
adb shell settings put global glove_box_password_wrong_times 0
adb shell am force-stop com.android.car.settings
# 清密码(恢复「无密码直开」)
adb shell settings put global glove_box_password ""
adb shell am force-stop com.android.car.settings

⚠️ wrong_times 残留坑:不清零就直接测「无密码开箱」,会被锁定分支拦去扫码页,误判为「代码改坏了」。

3. 台架命令速查

3.1 root 与通道判法

adb root && adb remount      # reboot 会掉 root
# 每批 mock 前必查:必须是 su:s0(u:r:shell:s0 会被 avc 拒)
adb shell "id | grep -o 'context=[^ ]*'"
# AIDL(fermi 等新车机):能看到 IVehicle/micar
adb shell dumpsys -l | grep -i vehicle
# 看不到则是 HIDL(mach/ampere 等老车机):
adb shell lshal | grep -i vehicle

3.2 mock 注入与复位

# AIDL 注入(fermi 实证):
adb shell dumpsys android.hardware.automotive.vehicle.IVehicle/micar \
    --mock_from_car <dec_propId> -a 0 --stat 0 -i <val>
# HIDL 注入(mach/ampere 实证):
adb shell lshal debug android.hardware.automotive.vehicle@2.0::IVehicle/default \
    --mock_from_car <dec_propId> -a 0 --stat 0 -i <val>

注入铁律(06 篇实证):

  1. 每批间隔 ≥0.25s;值必须翻转才触发 ON_CHANGE 回调(同值重注无效)。
  2. 配置字走 CarConfigManager 进程级静态缓存,mock 新值后必须 am force-stop com.android.car.settings 再开页,否则读到旧值(日志 hit cached pId)。
  3. vehicle_mock_data(底层持久化 SET 开关)按需开:
adb shell settings put --user 0 GLOBAL vehicle_mock_data 1   # 开:UI 不被台架 vehicled 回滚
adb shell settings put --user 0 GLOBAL vehicle_mock_data 0   # 复位铁律:重启不清,必须显式归 0
  1. 复位三件套:注回基值 + vehicle_mock_data 归 0 + force-stop。

手套箱入口最小配方(2026-10-19 mach 实证入口出现):

# LOCK_TYPE_CONFIG(dec 1631630345) 1→2(MANUAL→POWER)
adb shell lshal debug android.hardware.automotive.vehicle@2.0::IVehicle/default \
    --mock_from_car 1631630345 -a 0 --stat 0 -i 2
adb shell am force-stop com.android.car.settings
# 重进:车辆控制页 → 出现「手套箱」组
# 恢复:同命令 -i 1

3.3 密码页 root 直拉(跳过开箱主流程)

adb shell am start -n com.android.car.settings/.miauto.vehicle.glovebox.GloveBoxPasswordDialog \
    --ei param_event_id 0 --ez param_is_close_pwd false -f 0x10000000

param_event_id 取值 0/1/2/3 同 §2 事件表;该 Activity 是 singleInstance(模块 AndroidManifest.xml:31-34),重复拉起走 onNewIntent(GloveBoxPasswordDialog.kt:59-64)。

3.4 logcat 取证 grep 模式

adb logcat | grep -aE "GloveBox|6140b40|onDataVerifyFailed|reportOpenGloveBox|showAccountVerifyPage"
# bugreport 场景:
grep -aE "GloveBox|6140b40" bugreport-*.txt

4. 日志签名表

正常开箱五连(2026-10-19 mach 台架无密码车实测,逐行锚定,详见 03-开箱主流程源码精讲.md):

#日志签名出处
1#onTabClicked() on tab: Tab[打开手套箱, false, true]GloveBoxController.kt:117
2no password, open glove boxGloveBoxController.kt:267
3openGloveBox openType=1GloveBoxController.kt:223
4reportOpenGloveBox type=1(先于 #5,写完即报)VehicleControlReporter.kt:497
5>>> Done set propVal: 1 to propId: 0x6140b407, aId: ...VehicleControlManager.java:135

其他关键签名:

场景日志签名出处判读
台架回滚假象onDelayGetProp propId: 0x6140b407 + onDataVerifyFailed ... propVal: 1SettingsCarPropertyManager.kt:195/:199-201台架 vehicled 不持久 SET 的回读校验失败,≠开箱失败;解法 vehicle_mock_data 1,判定只信 App 日志
不可用 Toast 分流showGloveBoxSwitchUnavailableNotify: reason=NGloveBoxController.kt:290N=1 未解锁 / 2 防玩 / 其它看代客
达上限转扫码showAccountVerifyPage: pwd limit reachedGloveBoxController.kt:211随后应见账号验证拉起
MIS 受理onAction: specId=... → sendResponse: specId=..., code=100XGloveBoxNavigationHandler.kt:63/:1441001 成功 / 1002 需密码 / 1003 不支持 / 1004 达上限(:45-54)
密码验证拉起goToCheckPassword: event=N, isClosePwd=...PinPasswordCheckUtils.kt:139event 取值同 §2

5. 常见假象与误判表

误判真相证据
「onDataVerifyFailed = 开箱失败」台架 vehicled 不持久 SET 的回滚假象;实车以 MCU 执行为准SettingsCarPropertyManager.kt:193-203
「锁定解不掉,代码坏了」wrong_times 残留;settings put global glove_box_password_wrong_times 0 + force-stop§2 命令
「未登录账号没有密码设置入口 = bug」设计如此:Tab1(密码设置)显隐只跟账号登录态GloveBoxController.kt:86-96
「点了没 Toast = 点击没响应」reason 非 1/2 且非代客时走 Resources.ID_NULL 静默分支,现状如此GloveBoxController.kt:294-301
「mock 了值页面没变」同值重注不触发 ON_CHANGE;或 CarConfigManager 静态缓存未清(缺 force-stop)CarPropertyCacheManager.java:192-193(ON_CHANGE 注册)
「置灰还能点是 bug」故意:两 Tab 都 withAllowClickWhenDisabled(true),留点击弹原因 ToastVehicleBodyPropertyMap.kt:48/:61
「语音开箱也该有 54662 埋点」MIS 路径直写属性不过 Controller,不报 54662,是口径边界GloveBoxNavigationHandler.kt:125-131
「电源判断 >=ACC 就行」不行:START=4(deprecated)会被漏过/误纳,必须 ==ACC || ==RUNDriving.java:10876-10885
「远程能关手套箱」不能,信号链只有写 OPEN;关箱=手动物理合上GloveBoxController.kt:222-229
「密码存在 SP/私有文件」存 Settings.Global 三键,跟车存储,恢复出厂即清GloveBoxPasswordTools.kt:33-38
「GloveBoxButton 还在用」旧自定义 View,全仓零引用(死代码),别对着它改GloveBoxButton.kt(本仓 grep 无引用)

6. 文件清单

手套箱目录 settingsPage/VehicleBodyControl/.../miauto/vehicle/glovebox/(10 文件):

文件一句话角色
GloveBoxController.kt双 Tab 宿主:订阅 GLOVE_BOX+CAR_MODE_STATUS(:99-102),三分支分发 :261-278,统一开箱点 :222-229,原因 Toast :288-302
GloveBoxSettingsDialogActivity.kt密码管理弹窗:handleSwitchChange() 三态(达上限/未设/已设):145-186
GloveBoxPasswordDialog.kt密码框宿主 Activity,singleInstance + 冲突弹窗,onNewIntent :59-64
GloveBoxPasswordFragment.kt薄壳,继承 BasePinPasswordFragment(:22),只注入手套箱配置
GloveBoxPasswordTools.kt委托 PinPasswordTools,注入三键与广播 Action(:33-38)
GloveBoxPasswordCheckUtils.kt委托 PinPasswordCheckUtils,goToCheckPassword() :50-58
GloveBoxAccountVerifyUtils.kt车主验证入口 + P 挡前置闸(:45-57,忘记密码路径传 false 免 P 挡)
GloveBoxNavigationHandler.ktMIS 语音/远程受理,响应码 1001-1004(:45-54),发 CLOSE_SYSTEM_DIALOGS(:104-107)
GloveBoxModulePublishService.ktMIS 静态发布服务(模块 AndroidManifest.xml:9-28,keep_alive=false)
GloveBoxButton.kt死代码(旧自定义 View,无引用)

通用密码框架 base/settingsBaseUi/.../common/password/(与升降顶等共用,改前 grep 影响面):

文件一句话角色
PinPasswordTools.ktPIN 核心:输入/验证/存储/5 次锁定,事件常量 :50-59
PinPasswordEncryptor.ktSHA-256 + 时间戳盐,IntArray 串格式 :93-100
PinPasswordCheckUtils.kt拉起密码弹窗 + LocalBroadcast 单回调槽(mCallback :58,覆盖赋值 :147)
BasePinPasswordFragment.kt密码页框架:忘记密码入口 :264(免 P 挡)、达上限 :319(查 P 挡)

(同目录另有 PinPasswordConfig.kt 参数化配置、PinAccountVerifyUtils.kt 账号验证框架,合计 6 文件。)

属性通道 5 文件(base/settingsVehicleLib/.../,分层详解见 06-属性通道与台架mock.md):

文件一句话角色
GlobalCarPropertyManager.ktL0 入口单例(:16),getCarManager() :32
SettingsCarPropertyManager.ktL1 页面级:setCarProperty :430-487,SET 超时校验 :193-203(回滚假象发源地)
CarPropertyCacheManager.javaL2 缓存回放:注册即同步回调缓存值 callbackByCache :197-228
VehicleControlManager.javaL3 写入:setIntProperty 丢 ASYNC 线程池 :128-130,>>> Done set 日志 :135
CarConfigManager.kt配置字静态缓存:getGloveBoxLockType() :139-146(默认 MANUAL,mock 后必须 force-stop)

常驻监听宿主 VehiclePermanentListener.java:onPropertyManagerPrepared 重注册 + 回放离线队列 :103-115(物理按键常驻监听的挂点,方案见 07-物理按键扩展设计.md)。

7. 相关链接

需求与方案(飞书 wiki):

参考 change(Gerrit):

  • 161208:软按键开箱+密码流程主参考(Meego 2350608,MERGED)
  • 165854:不可用原因 Toast 映射(N801PROB-34263,MERGED)
  • 368053:开箱埋点引入(Meego 3860784,PS14 MERGED)

本地路径:

  • M 目录(一手资料):/home/zbc/下载/test/车机Feature/Meego 5458412/(docs/kb/research/test 子目录)
  • 台架自测场景:/home/zbc/下载/test/车机JIRA/.claude/skills/car-signal-mock-test/references/场景-手套箱入口与密码页.md
  • 台架方法论总库:同 skill 下 KNOWLEDGE.md / LESSONS.md

本库篇目:01 需求与信号契约 · 02 页面结构与门控 · 03 开箱主流程源码精讲 · 04 密码与账号验证体系 · 05 埋点体系 · 06 属性通道与台架mock · 07 物理按键扩展设计

8. 证据清单

文件行号区间说明
vendor/micar/.../support-lib/src/mi/car/config/Peripheral.java572-610, 1414-1430四个手套箱属性定义(0x407~0x40a)与三个枚举类
同目录 Body.java1841-1848, 6948-6953物理按键属性 GLOVE_BOX_BUTTON_STATUS 与 GloveBoxButtonStatus 枚举
同目录 Driving.java2423-2430, 10876-10885POWER_MODE=0x61407207 与 PowerStatus(START=4 deprecated)
W:.../miauto/vehicle/MiCarPropertyIds.java(settingsBaseLib)1485, 1487仓内别名 GLOVE_BOX / GLOVE_BOX_TYPE
W:.../glovebox/GloveBoxController.kt86-102, 117, 166-188, 210-229, 261-302, 305-332订阅集/三分支/统一开箱点/原因 Toast/账号广播
W:.../glovebox/GloveBoxNavigationHandler.kt45-54, 62-86, 104-131, 144MIS 响应码/受理/直写属性/关控制中心
W:.../glovebox/GloveBoxPasswordTools.kt33-38, 110-139Settings.Global 三键定义与锁定判断
W:.../glovebox/GloveBoxPasswordCheckUtils.kt25-58委托通用框架的拉起入口
W:.../glovebox/GloveBoxAccountVerifyUtils.kt45-57车主验证 + P 挡闸
W:.../glovebox/GloveBoxPasswordDialog.kt59-64singleInstance 下 onNewIntent 重载 Fragment
W:.../glovebox/GloveBoxSettingsDialogActivity.kt145-186, 193-199, 260-262密码管理三态与忘记密码埋点调用点
W:.../glovebox/GloveBoxModulePublishService.kt全文(21 行)MIS 静态发布,注册 NavigationHandler
W:.../glovebox/GloveBoxButton.kt全文旧自定义 View,全仓零引用(死代码判定)
W:VehicleBodyControl/src/main/AndroidManifest.xml9-34MIS 发布服务(keep_alive=false)与密码弹窗 singleInstance
W:base/.../common/password/PinPasswordTools.kt44-71param_event_id、事件 0-3、5 次/4 位/200ms 常量
W:base/.../common/password/PinPasswordEncryptor.kt52-64, 93-100SHA-256+盐与 IntArray 串格式
W:base/.../common/password/PinPasswordCheckUtils.kt54-58, 132-163单回调槽与 goToCheckPassword
W:base/.../common/password/BasePinPasswordFragment.kt264, 319忘记密码(免 P 挡)与达上限(查 P 挡)两个验证拉起点
W:base/.../track/VehicleControlReporter.kt38-42, 104-114, 495-505, 510-514source 常量、手套箱埋点常量与上报函数
W:base/.../track/TrackConstants.java309-313, 532-53654662/54663/54664 事件 ID 与 KEY_SOURCE
W:base/.../track/SettingsTrack.kt12-16OneTrack APP_ID=31000401514 / PROJECT_ID
W:base/.../miauto/vehicle/SettingsCarPropertyManager.kt193-203, 430-487SET 超时校验(回滚假象)与 setCarProperty 主流程
W:base/.../miauto/vehicle/VehicleControlManager.java128-141异步写入与 >>> Done set 日志
W:base/.../miauto/vehicle/CarPropertyCacheManager.java187-228首注册远端 + 缓存同步回放(ON_CHANGE)
W:base/.../miauto/vehicle/VehiclePropertyUtil.java165-182isPropertyAvailable = status==STATUS_AVAILABLE
W:base/.../miauto/CarConfigManager.kt139-146getGloveBoxLockType 静态缓存(默认 MANUAL)
W:base/.../miauto/VehiclePermanentListener.java103-115prepared 重注册 + 离线队列回放
W:base/.../miauto/vehicle/VehicleControlSettingsFragment.java168-172非 POWER 整组移除门控
W:base/.../miauto/vehicle/VehicleBodyPropertyMap.kt42-63双 Tab 工厂,withAllowClickWhenDisabled(true)
W:base/.../utils/AccountVerifyHelper.kt(settingsBaseLib)14, 64-76, 121-159content://mi.car.account、scene=glovebox_verify、qr_code
台架命令与回滚假象实证见 06-属性通道与台架mock.md §4-§5AIDL/HIDL 注入、vehicle_mock_data、2026-10-19 mach 实测