手套箱知识库 · 总索引

小米智能座舱 MiCarSettings ·「车辆控制」页 →「手套箱」(软按键开箱 + 密码手套箱 + 物理按键扩展)全解

基线声明

  • 主锚 W(行号以此为准):/home/zbc/car/fuben4_micarsettings/MiCarSettings-5458412 @ origin/dev = 930be9145e06a0a390d5982b6d713dc381004f7c(2026-10-17,本地分支 feature/meego-5458412-glovebox-button)
  • 出货对照:/home/zbc/car/pack_a17_cn_20260923(pack_a17_cn_20260923 快照,判包新旧/行号对照用)
  • 平台源码:/home/zbc/pangu/xcd_xring_a17_fermi/vendor/micar(MiVehicleService / support-lib,属性与枚举定义权威源)
  • ⚠️ 手套箱模块全部 Kotlin(.kt),但入口 Fragment 是 VehicleControlSettingsFragment.java、属性写通道是 VehicleControlManager.java、埋点常量在 TrackConstants.java —— 检索必须同时覆盖 .java 与 .kt,纯单语 grep 会漏一半
  • 需求:Meego 5458412(手套箱物理按键);目标车型 Mann 28A/E4(feynman)+ Modena L 27C/E4U3(fermi),均 A17;开发提测 2026-10-20~10-22,合入 DDL 2026-10-23
  • 建立日期:2026-10-19(01~07 篇全部为带 file:line 证据的源码实证篇)

1. 这个功能是什么(30 秒版)

设置 → 车辆控制 →「手套箱」:CarUiTabLayout 两个并排图标 Tab——左「打开手套箱」,右「手套箱密码设置」。

  • 开箱(软按键):点击后向车控属性 Peripheral.GLOVE_BOX(0x6140B407)写入 OPEN(1),手套箱电动弹开。只有”开”没有”关”的下发——关箱是用户手动物理合上的;已开状态再点只弹「请手动关闭」Toast。
  • 密码手套箱:可选开启 4 位数字 PIN。设密码后开箱必须先输对密码;输错 5 次锁定,锁定后必须做**车主账号验证(扫二维码)**才能开。
  • 对外能力:语音助手(「打开手套箱」)/手机 App 远程开箱,走 MIS 总线,由 GloveBoxModulePublishService 发布、GloveBoxNavigationHandler 受理(响应码 1001 成功 / 1002 需密码 / 1003 不支持 / 1004 达上限)。
  • 物理按键(本库新增主题,Meego 5458412):车侧新增物理按键,CAN 信号 GlvBoxBtnSts(0x2:Psd 按下)经平台属性 Body.GLOVE_BOX_BUTTON_STATUS(0x61401781)上报;Settings 侧常驻监听,只在 NOT_PRESSED→PRESSED 边沿触发,复用软按键同一条开箱流(门控→密码→写属性→埋点),前置条件 ACC/Run 电源挡位,依旧只开不关。交付边界仅 HMI(MiCarSettings):按键采集/卡滞 20s/电释放锁 = SC12 他组,密码协作 = SC49。

五个容易被忽视的设计点,也是历史问题的全部来源:

  1. 不是按车型写死显隐,而是按配置字动态显隐:车控配置 GLOVE_BOX_LOCK_TYPE_CONFIG == POWER(2)(电动手套箱)时入口才存在,否则整组从页面移除(VehicleControlSettingsFragment.java:168-172,读取默认 MANUAL,CarConfigManager.kt:139-146)。
  2. 密码存在 Settings.Global 而非 SharedPreferences:glove_box_password / glove_box_password_salt / glove_box_password_wrong_times 三键,SHA-256(时间戳盐+密码)哈希,跟车存储、恢复出厂即清;每次改密换盐,旧哈希自动失效。
  3. 账号验证不是跳页面,而是 ContentProvider call:contentResolver.call("content://mi.car.account", "confirm", scene="glovebox_verify", style="qr_code"),且默认要求 P 挡(忘记密码分支唯一例外,传 isNeedCheckGear=false 跳过)。
  4. 写完即报语义:openGloveBox 先 setVehicleProperty(GLOVE_BOX, OPEN) 紧接上报埋点,不等车控回执(GloveBoxController.kt:222-229;SET 丢 ThreadPoolUtils.ASYNC,VehicleControlManager.java:128-130)——埋点语义是「意图已受理」,不是「手套箱已开」。
  5. 可用性事实标准 = 属性状态 + 原因属性双件套:Tab 可用性看 GLOVE_BOX 属性的 STATUS_AVAILABLE(VehiclePropertyUtil.isPropertyAvailable,:173-182),不可用原因由 GLOVE_BOX_UNAVL_REASON(0=Idle / 1=NotDisArmed / 2=AntyPlay)解释并弹对应 Toast;物理按键侧 GlvBoxDcdFcnAvl/GlvBoxDcdDiRsn 两个 CAN 信号在 vendor/micar 全树 grep 为零,映射实现不可见,列为底层确认项(01 篇)。

2. 文档导航

篇目适合谁一句话内容
01-需求与信号契约所有人 · 物理按键起点Meego 5458412 需求边界、三个 CAN 信号(GlvBoxBtnSts / GlvBoxDcdFcnAvl / GlvBoxDcdDiRsn)与五个平台属性的取值契约、可用性事实标准、三个底层确认项
02-页面结构与门控新手挂载链(XML key → Fragment 移除机制 → Controller → 双 Tab 注册)+ 三道门控(配置字 POWER / 属性 STATUS_AVAILABLE / 账号与代客)+ Tab 三态语义表
03-开箱主流程源码精讲进阶 · 核心篇GloveBoxController.kt 逐段精讲:双 Tab 初始化 / 属性回调 / 三分支决策(已开 Toast、无密码直开、锁定扫码、弹密码框)/ 原因 Toast / openGloveBox 写完即报 / 账号广播注册
04-密码与账号验证体系进阶Settings.Global 三键与 SHA-256+盐、四事件同页分流、Dialog→Fragment→Tools→CheckUtils 四层架构、5 次锁定与扫码解锁、MIS 语音入口、台架 root 直拉命令
05-埋点体系数据/测试54662 开箱(CLICK)/ 54663 忘记密码(EXECUTE)/ 54664 密码操作(EXECUTE)字段语义全表;写完即报口径边界(MIS 不上报 54662);物理按键 source 扩展铁律
06-属性通道与台架mock测试/自测三层属性通道(SettingsCarPropertyManager / CarPropertyCacheManager / VehicleControlManager)+ 常驻监听 VehiclePermanentListener;SET 超时校验与台架回滚假象;lshal mock 操作手册与手套箱配方
07-物理按键扩展设计开发 · 方案D1~D8 架构决策、NOT_PRESSED→PRESSED 边沿状态机全转换表、五级门控+写前复查、并发语义(后请求覆盖前请求)、6 文件改动清单、E/G/F/R 测试矩阵
08-速查卡所有人一页纸速查:propId/枚举、Settings.Global 三键、台架命令、日志签名、常见假象表

📦 旧系列已归档:archive/ 下的 01-功能与页面结构.md、02-开箱业务流与密码生命周期.md、03-源码精讲.md、04-信号链路与属性.md、05-MIS语音远程与对外暴露.md、06-演进历史与问题单.md、07-埋点与测试.md 为旧系列(fuben31_micarsettings 基线,2026-10-20 建),保留作历史参考与 MIS/演进史细节补充;本目录 00~08 为新系列(W=origin/dev@930be9145 基线重建),门控/流程/埋点/台架结论以新系列为准;引用旧系列行号时注意基线差异。

3. 人类学习路线

flowchart LR
    A["01 需求与信号契约<br/>做什么、信号与属性是什么"] --> B["02 页面结构与门控<br/>入口在哪、谁能看见"]
    B --> C["03 开箱主流程源码精讲<br/>点了以后发生什么(核心)"]
    C --> D["04 密码与账号验证<br/>PIN 怎么存/验/锁/解"]
    C --> E["05 埋点体系<br/>数据口径与 source 扩展"]
    F["06 属性通道与台架 mock"] -.自测/注入.-> C
    G["07 物理按键扩展设计"] -.开发前必读.-> A
    G -.复用同一条开箱流.-> C
    H["08 速查卡(旧)"] -.贯穿.-> B
  • 只想了解功能/排查「不显示、置灰、不可用 Toast」:02 + 01 §可用性
  • 分析「点不开、密码不弹、锁定、扫码失败」:03 + 04
  • 分析「语音/远程开箱」:04 §MIS 入口 + 05 §口径边界(MIS 不上报 54662)
  • 做物理按键开发/评审:01 → 07,改码前必读 03(委托点)与 05(埋点铁律)
  • 台架自测:06 配方先行,mach 已实证入口+密码页(2026-10-19/20)

4. 速览:四条链路一张图

flowchart TD
    subgraph UI["① 设置页软按键(本仓)"]
        A1["车辆控制页 双Tab"] --> A2{"点击开箱 Tab"}
        A2 -->|"已开(mIsSelected)"| A3["Toast 请手动关闭"]
        A2 -->|"无密码"| A4["openGloveBox 写 GLOVE_BOX=OPEN<br/>写完即报 54662 type=1"]
        A2 -->|"有密码"| A5["GloveBoxPasswordDialog 4位PIN"]
        A5 -->|"正确"| A6["openGloveBox type=2"]
        A5 -->|"错5次"| A7["账号扫码验证<br/>content://mi.car.account"]
        A7 -->|"通过"| A6
    end
    subgraph PHY["② 物理按键(Meego 5458412,新增)"]
        P1["车侧按键"] -->|"CAN GlvBoxBtnSts 0x2:Psd"| P2["属性 GLOVE_BOX_BUTTON_STATUS<br/>0x61401781"]
        P2 -->|"常驻监听 NOT_PRESSED→PRESSED 边沿"| P3{"五级门控<br/>电源ACC/Run·配置字·可用性·代客·密码"}
        P3 -->|"通过,复用软按键开箱流"| A4
    end
    subgraph MIS["③ 语音/远程(MIS 总线)"]
        B1["语音助手/手机App"] --> B2["GloveBoxNavigationHandler"]
        B2 -->|"无密码直开"| B3["直写属性 回1001<br/>不上报54662"]
        B2 -->|"有密码"| B4["拉起密码页 回1002"]
        B2 -->|"已锁定"| B5["拉起账号验证 回1004"]
        B2 -->|"非POWER配置"| B6["回1003 不支持"]
    end
    subgraph VHAL["④ 信号层(平台 vendor/micar)"]
        C1["GLOVE_BOX 0x6140B407 RW<br/>只写 OPEN=1"]
        C2["GLOVE_BOX_LOCK_TYPE_CONFIG 0x409 RO<br/>MANUAL=1/POWER=2 入口门控"]
        C3["GLOVE_BOX_UNAVL_REASON 0x40A RO<br/>0/1/2 原因Toast"]
    end
    A4 --> C1
    A6 --> C1
    B3 --> C1
    A1 -.显隐.- C2
    A2 -.不可用Toast.- C3

5. AI 使用指引

你要干什么必读
分析「入口不显示 / 置灰 / 不可用 Toast」类问题02(三道门控链)+ 01 §可用性事实标准;台架复核按 06 配方(mock 0x409=2 + force-stop)
分析「点击无反应 / 弹错 Toast / 开箱流程」类问题03(三分支决策 + 写完即报)+ 06(属性通道与回滚假象)
分析「密码 / 锁定 / 扫码验证 / wrong_times 残留」类问题04(含台架 root 直拉与清零命令)
埋点口径核对 / 数据对不上 / 54662 缺数05(写完即报语义;MIS 路径不上报 54662 是边界不是 bug)
台架自测 / mock 注入 / 判「onDataVerifyFailed」06(判定只信 App 日志;vehicled 不持久 SET 回滚是假象,vehicle_mock_data 1 解法)
物理按键开发 / 方案评审 / 改码01 + 07;改码落点前必读 03(Controller 委托点)与 05(source 不可变捕获铁律);软按键零回归约束在 07 §并发与 §对照矩阵
判断出货包是否带某修复出货对照 pack_a17_cn_20260923 快照 diff(02/03 篇方法);gerrit MERGED 不可信,只对 origin 实例 + grep 实证

三条纪律:

  1. 本库所有 file:line 均以 W(fuben4 @ origin/dev 930be9145) 为基线;在出货快照或其他分支核对时行号可能漂移,以符号定位为准(±3 内算吻合)。
  2. 引用任何 file:line 前必须先用 Read 打开该文件核实符号确实存在;没读过的文件只写路径不带行号。本篇 §5 与证据清单所列条目均已抽查或标注核实出处。
  3. 台架现象判定只信 App 日志;onDataVerifyFailed 在台架大概率是 vehicled 不持久 SET 的回滚假象(06 篇实证),不要当成 App bug 修。

6. 关键数字一页纸

6.1 propId 表(平台 Peripheral.java / Body.java / Driving.java,javap+源码双实证)

语义常量propId(hex / dec)权限取值枚举
开箱执行属性Peripheral.GLOVE_BOX0x6140B407 / 1631630343READ_WRITEOpenClose{ CLOSE=0, OPEN=1 },App 只写 OPEN
电机命令(监测)Peripheral.GLOVE_BOX_MOTOR_CMD0x6140B408 / 1631630344READGloveBoxMotorCmd{ IDLE=0, CLOCKWISE=1, COUNTER_CLOCKWISE=2, BREAK=3 }
锁类型配置字(入口门控)Peripheral.GLOVE_BOX_LOCK_TYPE_CONFIG0x6140B409 / 1631630345READ{ MANUAL=1, POWER=2 },POWER 才显示入口
不可用原因(Toast)Peripheral.GLOVE_BOX_UNAVL_REASON0x6140B40A / 1631630346READGloveBoxUnavlReason{ IDLE=0, NOT_DIS_ARMED=1, ANTY_PLAY=2 }
物理按键状态(新增)Body.GLOVE_BOX_BUTTON_STATUS0x61401781 / 1631590273READGloveBoxButtonStatus{ ERROR=0, NOT_PRESSED=1, PRESSED=2, NO_INFO=3 },唯一触发沿 1→2
电源挡位(物理按键前置)Driving.POWER_MODE0x61407207READPowerStatus{ OFF=0, AWAKE=1, ACC=2, RUN=3, START=4(Deprecated) } —— 前置判 `==ACC
车辆模式(代客门控)Driving.CAR_MODE_STATUS0x6140720BREADCarModeStatus.NORMAL=0,非 NORMAL 密码入口置灰

源码锚点:Peripheral.java:576 / 586 / 596 / 606(短 ID 0x407~0x40a);Body.java:1844(0x781);Driving.java:2426(POWER_MODE=0x207)、:10876-10885(PowerStatus 枚举)。五属性全部 GLOBAL + ON_CHANGE + initialValue=0(01 篇)。

6.2 存储三键与密码常量(Settings.Global,跟车存储,恢复出厂即清)

key / 常量值 / 含义
glove_box_passwordSHA-256(salt + 密码) 哈希;被哈希串是 IntArray 串如 "[1, 2, 3, 4]"
glove_box_password_salt时间戳盐(System.currentTimeMillis),改密换盐
glove_box_password_wrong_times错误次数;上限 PWD_WRONG_MAX_TIMES=5 触发锁定
密码长度 / 延迟PWD_MAX_LENGTH=4,DELAY_TIMES=200L
四事件INPUT_EVENT_CHECK_PWD=0 / SET_PWD=1 / CHANGE_PWD=2 / CHANGE_PWD_VERIFIED=3

锚点:PinPasswordTools.kt:50-68(常量区,本篇抽查);哈希实现 PinPasswordEncryptor.kt:52-64,93-100(04 篇)。

6.3 埋点三事件(OneTrack,APP_ID 31000401514,PROJECT_ID xiaomiev-cockpit-intl)

事件ID类型关键字段调用点
TIP_OPEN_GLOVE_BOX1147.1.0.1.54662CLICKtype:1=无密码 / 2=验证后;tab_instance_idGloveBoxController.openGloveBox 唯一上报点(写完即报)
TIP_GLOVE_BOX_FORGOT_PASSWORD_SUCCESS1147.0.0.0.54663EXECUTE—Controller + DialogActivity 双调用点(两条业务路径非重复)
TIP_GLOVE_BOX_PASSWORD_OPERATION1147.0.0.0.54664EXECUTEtype:1=设置 / 2=关闭 / 3=修改密码操作三处

KEY_SOURCE="source" 常量已存在(TrackConstants.java:533-534)但手套箱协议未定;物理按键扩展铁律:source 不可变捕获穿透异步回调、最终开箱点只报一次、禁 type=3(05 篇)。锚点:VehicleControlReporter.kt:106-108(openType 常量)、reportOpenGloveBox 约 :494-503(本篇抽查)。

6.4 日志签名三条(排障先认这三行)

签名出处含义
>>> Done set propVal: 1 to propId: 0x6140b407VehicleControlManager.java:135(setIntPropertyBySync)开箱属性已写入(异步线程),不代表手套箱已开
onDelayGetProp / onDataVerifyFailed propId: 0x6140b407SettingsCarPropertyManager.kt:193-203(handlePropertyTimeout)SET 超时校验未等到回值——台架 vehicled 不持久 SET 的回滚假象,06 篇 mach 实测;解法 settings put --user 0 GLOBAL vehicle_mock_data 1
reportOpenGloveBox type=VehicleControlReporter.kt 约 :497埋点已上报(紧随写属性,不等回执)

附:属性回调签名 onPropertyChanged: gloveBoxStatus=(GloveBoxController.kt:175,本篇抽查)。

6.5 台架命令四条(06 篇全录,mach 实证)

# ① mock 配置字 POWER(2) 让入口显示(十进制 propId,间隔≥0.25s,值要变化)
lshal debug android.hardware.automotive.vehicle@2.0::IVehicle/default --mock_from_car 1631630345 -a 0 --stat 0 -i 2
am force-stop com.android.car.settings   # 重进车辆控制页生效
 
# ② vehicled 持久 SET(消除回滚假象;重启不清,用完必须显式归 0)
settings put --user 0 GLOBAL vehicle_mock_data 1
 
# ③ 密码页 root 直拉(--ei param_event_id:0=验证 1=设置 2=修改 3=已验证后修改)
am start -n com.android.car.settings/.miauto.vehicle.glovebox.GloveBoxPasswordDialog --ei param_event_id 0
 
# ④ 清锁定残留
settings put global glove_box_password_wrong_times 0 && am force-stop com.android.car.settings

root 判别:adb shell "id | grep -o 'context=[^ ]*'" 须 su:s0;通道判法:dumpsys -l | grep -i vehicle 有 IVehicle/micar 为 AIDL,否则 HIDL 用 lshal(06 篇)。

7. 关联知识库

  • 00-能量回收-README.md —— 同风格车设知识库;属性 mock、台架自测、「写完即报/下发覆盖」时序认知与本库互通
  • 00-蜂窝网络-README.md —— 「平台受理/执行分离恒 true」认知同样适用于本功能:写属性成功 ≠ 执行完成
  • 05-车辆接口层与IPC.md —— CarProperty 读写 / binder 链路底层,本功能 setVehicleProperty 的通道基石(车技车设根目录)

8. 基线与纪律

  1. 主锚:/home/zbc/car/fuben4_micarsettings/MiCarSettings-5458412 @ origin/dev 930be9145e06a0a390d5982b6d713dc381004f7c;出货对照 /home/zbc/car/pack_a17_cn_20260923;平台 /home/zbc/pangu/xcd_xring_a17_fermi/vendor/micar。
  2. 行号以 W 为准;出货快照与平台树的行号仅对照不锚定。跨分支核对时以符号(函数名/常量名)定位,±3 行内漂移视为吻合。
  3. kt/java 双语检索:手套箱模块 .kt,入口 Fragment / 属性通道 / 埋点常量 .java;grep 必须 -include='*.kt' -include='*.java' 双罩。
  4. file:line 纪律:引用前先 Read 核实;没读过的文件写路径不带行号或标【未核实】。禁止编造代码内容,引代码照抄原文。
  5. 出货判定纪律:判包新旧看 committer 时间 + 预置快照 diff;Gerrit 「MERGED」标签不可信,只对 origin 实例 + grep 实证(02/03 篇 diff 方法)。
  6. 性能/台架判定纪律:只信 App 日志;onDataVerifyFailed 台架回滚假象已实证(06 篇);mock 后必须复位(配置字归原值 + vehicle_mock_data 0)。

证据清单

文件行号区间说明核实
vendor/micar/.../mi/car/config/Peripheral.java:576 / :586 / :596 / :606四个手套箱属性短 ID(0x407~0x40a)本篇抽查
vendor/micar/.../mi/car/config/Body.java:1844GLOVE_BOX_BUTTON_STATUS = 0x781本篇抽查
vendor/micar/.../mi/car/config/Driving.java:2426, :10876-10885POWER_MODE=0x207;PowerStatus OFF/AWAKE/ACC/RUN/START=0/1/2/3/4本篇抽查
W .../glovebox/GloveBoxController.kt:99-102, :173-186, :222-229, :261-278监听 2 属性;可用性/代客门控;openGloveBox 写完即报;三分支决策本篇抽查
W VehicleControlSettingsFragment.java:168-172POWER != getGloveBoxLockType() 即整组移除本篇抽查
W .../common/password/PinPasswordTools.kt:50-68事件常量 0~3、PWD_WRONG_MAX_TIMES=5、PWD_MAX_LENGTH=4、DELAY_TIMES=200L本篇抽查
W VehicleControlManager.java:128-136setIntProperty 丢 ThreadPoolUtils.ASYNC;>>> Done set propVal 日志 :135本篇抽查
W SettingsCarPropertyManager.kt:193-203handlePropertyTimeout / onDelayGetProp / onDataVerifyFailed(回滚假象源头)本篇抽查
W VehicleControlReporter.kt:106-108, 约:494-503openType 常量 1/2;reportOpenGloveBox(54662,CLICK)本篇抽查
W TrackConstants.java:533-534KEY_SOURCE="source" 已存在本篇抽查
W CarConfigManager.kt:139-146getGloveBoxLockType 读取与默认 MANUAL01/02 篇核实
W VehiclePropertyUtil.java:173-182isPropertyAvailable = status==STATUS_AVAILABLE;mock 注入点 :165-17001/02/07 篇核实
W .../glovebox/GloveBoxAccountVerifyUtils.kt + AccountVerifyHelper.kt:45-57; :121-159P 挡前置闸;content://mi.car.account call 扫码(scene=glovebox_verify)03/04 篇核实
W .../glovebox/GloveBoxNavigationHandler.kt:45-54, :104-107, :125-131MIS 响应码 1001-1004;CLOSE_SYSTEM_DIALOGS;直写属性不上报 5466204/05/07 篇核实
W VehiclePermanentListener.java:103-115, :305-313常驻监听 prepared 重注册与分发(物理按键宿主)06/07 篇核实
W CarPropertyCacheManager.java:197-228callbackByCache 注册即回放(:222 同步 onChangeEvent)06 篇核实
W VehicleBodyPropertyMap.kt:42-63双 Tab 工厂;withAllowClickWhenDisabled(true)(置灰可点击前提)02/03 篇核实
W PinPasswordEncryptor.kt:52-64, :93-100SHA-256(salt+pwd),salt=currentTimeMillis04 篇核实