手套箱 03 · 开箱主流程源码精讲
基线声明
- W(主锚点,行号以此为准):
/home/zbc/car/fuben4_micarsettings/MiCarSettings-5458412,origin/dev @930be9145。- 出货对照:
/home/zbc/car/pack_a17_cn_20260923快照,GloveBoxController.kt与 W 逐字节一致(diff无输出,见第 7 节)。- 平台源码:
/home/zbc/pangu/xcd_xring_a17_fermi/vendor/micar(属性常量定义)。- 主类:
settingsPage/VehicleBodyControl/src/main/java/com/android/car/settings/miauto/vehicle/glovebox/GloveBoxController.kt,全文 341 行。
本篇回答一个问题:用户点击「打开手套箱」之后,每一行代码做了什么。 页面拓扑与门控全景见 02-页面结构与门控.md,本篇只贴代码与日志。
1. 类骨架:一个 Controller,两个 Tab
GloveBoxController(GloveBoxController.kt:54-341)继承 BaseVehicleButtonIconToggleGroupPropController,用 2 列 ButtonIconTogglePreference 布局:
| Tab 索引 | 常量定义 | 用途 | 点击后入口 |
|---|---|---|---|
| 0 | TAB_INDEX_GLOVE_BOX_SWITCH(GloveBoxController.kt:73) | 手套箱开关 | showGloveBoxSwitchClick(tab)(:119) |
| 1 | TAB_INDEX_GLOVE_BOX_PASSWORD_SET(:76) | 密码设置入口 | startActivity(GloveBoxSettingsDialogActivity)(:130-132) |
生命周期钩子只有三个(:140-158):
onCreateInternal()(:140-148):put 双列配置PREFERENCE_TAB_ITEM_COLUMN_SIZE(:142 与 :146 重复 put 两次,历史遗留的无效重复)、设置 assistView 标题(:145)、registerReceiver()(:147,见 2.8)。onStartInternal()(:150-153)调setGloveBoxPwdSettingEntryVisibility():未登录账号时隐藏「密码设置」Tab(:86-96,AccountUtils.isUserLogin判断在 :88)。onDestroyInternal()(:155-158)注销账号广播接收器。
2. 逐段拆解
2.1 getPropertyIdSet():只订阅两个属性
override fun getPropertyIdSet() = ArraySet<Int>().apply {
add(MiCarPropertyIds.DrivingCtrl.GLOVE_BOX)
add(Driving.CAR_MODE_STATUS)
}(照抄 GloveBoxController.kt:99-102)
MiCarPropertyIds.DrivingCtrl.GLOVE_BOX是Peripheral.GLOVE_BOX的别名(MiCarPropertyIds.java:1485);平台定义在Peripheral.java:576-580:0x407 | MI_CAR | GLOBAL | INT32 | PERIPHERAL,即完整 ID0x6140b407(行尾注释明示),值枚举CommonParams.OpenClose。Driving.CAR_MODE_STATUS用于驾驶模式(代客)联动,见 2.3。- 不订阅
Peripheral.GLOVE_BOX_UNAVL_REASON(0x6140b40a,Peripheral.java:606-610):不可用原因只在点击不可用按钮时即时读取(见 2.5),该设计沿用自参考 change 165854(见其第 3 节)。
2.2 initLocalVehicleControls():双 Tab 与「disabled 也可点击」
override fun initLocalVehicleControls() {
super.initLocalVehicleControls()
mSupportedCtrls.clear()
mSupportedCtrls.add(VehicleBodyPropertyMap.createGloveBoxSwitchCtrl()
.withOnClickListener { tab: Tab<*> ->
MLog.d("%s #onTabClicked() on tab: %s", implClassName, tab)
if (tab.isAvailable) {
showGloveBoxSwitchClick(tab)
} else {
showGloveBoxSwitchUnavailableNotify()
}
}
)
mSupportedCtrls.add(VehicleBodyPropertyMap.createGloveBoxPasswordSetCtrl()
.withOnClickListener { tab: Tab<*> ->
MLog.d("%s #onTabClicked() on tab: %s", implClassName, tab)
if (tab.isAvailable) {
context.startActivity(
Intent(context, GloveBoxSettingsDialogActivity::class.java)
)
} else {
MiCarToastUtils.showToast(R.string.glove_box_fail_valet_mode)
}
}
)
}(照抄 GloveBoxController.kt:111-138)
关键设计在控件工厂里——VehicleBodyPropertyMap.kt:42-50(W 已读核实):
fun createGloveBoxSwitchCtrl(): VehicleQuickCtrl<*> {
return VehicleQuickCtrl<Any?>(
MiCarPropertyIds.DrivingCtrl.GLOVE_BOX,
R.drawable.ic_glove_box_switch, R.string.glove_box_switch
)
.withDefault(CommonParams.OpenClose.OPEN)
.withAllowClickWhenDisabled(true)
.withTabFlag(TabKeyMapHelper.TAB_FLAG_GLOVE_BOX_SWITCH)
}(照抄 VehicleBodyPropertyMap.kt:42-50)
withAllowClickWhenDisabled(true)(:48)是整条不可用提示链成立的前提:按钮置灰时点击事件依然送达,于是 :118-122 的二分流才有机会执行——可用走业务(2.4),不可用走原因 Toast(2.5)。密码设置入口同理(VehicleBodyPropertyMap.kt:55-63,:61 同样允许),其不可用时统一弹 glove_box_fail_valet_mode(GloveBoxController.kt:134)。两个控件共用 GLOVE_BOX 属性做 Tab 状态源,默认值不同:开关 Tab 默认 OPEN(:47),密码 Tab 默认 false(:60)。
2.3 onHandlePropertyChange():属性回调如何刷 UI
override fun onHandlePropertyChange(
propertyValue: MiCarPropertyValue<*>?,
shouldUpdateUI: Boolean
) {
if (preference.buttons.isEmpty()) return
// 更新手套箱开关状态
val gloveBoxStatus = getProperty(MiCarPropertyIds.DrivingCtrl.GLOVE_BOX)
val gloveBoxSwitchTab: Tab<*>? = preference.buttons[TAB_INDEX_GLOVE_BOX_SWITCH]
MLog.tag(TAG).d("onPropertyChanged: gloveBoxStatus=$gloveBoxStatus")
gloveBoxSwitchTab?.isAvailable = VehiclePropertyUtil.isPropertyAvailable(gloveBoxStatus)
gloveBoxSwitchTab?.mIsSelected = VehiclePropertyUtil
.getIntPropertyValue(gloveBoxStatus) == CommonParams.OpenClose.OPEN
// ... 后半段(:180-186):代客模式下密码设置入口置灰,isAvailable = !isValetMode && carMode == NORMAL
refreshUi()
}(截取照抄 GloveBoxController.kt:166-188,省略 :180-186 密码入口段)
两个工具函数的实际语义(VehiclePropertyUtil.java,W 已读核实):isPropertyAvailable(:173-182)——null → false、命中 mock unavailable → false、否则要求 status == STATUS_AVAILABLE,所以属性超时/丢失时 Tab 置灰但仍可点击(配合 2.2);getIntPropertyValue(:55-71)——null → 0,Number 取 intValue,Boolean 映射 Sts_On/Sts_Off。mIsSelected 即「箱体当前为 OPEN」= 属性值等于 CommonParams.OpenClose.OPEN(:177-178)。密码入口可用条件(:185)是双重判断:!isValetMode && carMode == NORMAL。
2.4 showGloveBoxSwitchClick():三分支决策
这是点击「打开手套箱」后真正的业务分发点(:261-278):
private fun showGloveBoxSwitchClick(tab: Tab<*>) {
if (tab.mIsSelected) {
MiCarToastUtils.showToast(R.string.glove_box_close_notice)
} else {
if (GloveBoxPasswordTools.getLocalPwd().isNullOrEmpty()) {
// 未设置密码
MLog.tag(TAG).d("no password, open glove box")
openGloveBox()
} else if (GloveBoxPasswordTools.isPwdLimit()) {
MLog.tag(TAG).d("open password is limit")
showAccountVerifyPage()
} else {
MLog.d("open password page ${this::class.java.name}")
// 打开密码输入页面
showPasswordCheckDialog()
}
}
}(照抄 GloveBoxController.kt:261-278)
| 分支 | 条件 | 动作 | 代码行 |
|---|---|---|---|
| 已打开 | tab.mIsSelected == true | Toast「请手动关闭手套箱」,不发开箱指令 | :262-263 |
| 无密码 | getLocalPwd().isNullOrEmpty() | 直接 openGloveBox()(默认 openType=1) | :265-268 |
| 错误达上限 | isPwdLimit() == true | showAccountVerifyPage() 走车主验证 | :269-271 |
| 有密码未达上限 | else | showPasswordCheckDialog() 弹密码输入 | :272-275 |
协作接口(本篇只画接口,细节归 04 篇):
GloveBoxPasswordTools.getLocalPwd():Settings.Global 里的密码哈希,无密码为null(GloveBoxPasswordTools.kt:110,委托PinPasswordTools,配置见 :24-41)。GloveBoxPasswordTools.isPwdLimit():错误次数是否达上限(GloveBoxPasswordTools.kt:135-139)。showPasswordCheckDialog()(:196-203)调GloveBoxPasswordCheckUtils.goToCheckPassword(context, INPUT_EVENT_CHECK_PWD) { if (it) openGloveBox(GLOVE_BOX_OPEN_WITH_PASSWORD) };签名在 GloveBoxPasswordCheckUtils.kt:50-58,拉起GloveBoxPasswordDialog用广播回结果。
2.5 showGloveBoxSwitchUnavailableNotify():不可用原因 → Toast
private fun showGloveBoxSwitchUnavailableNotify() {
val reason = getIntProperty(Peripheral.GLOVE_BOX_UNAVL_REASON)
MLog.tag(TAG).i("showGloveBoxSwitchUnavailableNotify: reason=$reason")
val strRes = when (reason) {
Peripheral.GloveBoxUnavlReason.NOT_DIS_ARMED -> R.string.glove_box_fail_need_unlock
Peripheral.GloveBoxUnavlReason.ANTY_PLAY -> R.string.glove_box_fail_anty_play
else -> {
if (AccountUtils.isValetMode(context)) R.string.glove_box_fail_valet_mode
else Resources.ID_NULL
}
}
if (strRes != Resources.ID_NULL) {
MiCarToastUtils.showToast(strRes)
}
}(照抄 GloveBoxController.kt:288-302)
注意三点:
- 触发时读原因(:289),不依赖订阅缓存——与 2.1 的「不订阅 UNAVL_REASON」呼应。
else分支(:294-297):只有代客模式才弹glove_box_fail_valet_mode;其它一切未知 reason(含 IDLE、信号丢失)映射为Resources.ID_NULL,静默不弹。枚举IDLE=0x0 / NOT_DIS_ARMED=0x1 / ANTY_PLAY=0x2见平台 Peripheral.java:1426-1430。这是 165854 留下的已知语义,不是「信号丢失必有提示」。strRes != Resources.ID_NULL才 showToast(:299-301)。完整映射表见第 4 节。
2.6 openGloveBox():写完即报,不等回执
/** 发送开箱车辆属性指令 */
private fun openGloveBox(openType: Int = TrackValues.GLOVE_BOX_OPEN_NO_PASSWORD) {
MLog.tag(TAG).d("openGloveBox openType=$openType")
setVehicleProperty(
MiCarPropertyIds.DrivingCtrl.GLOVE_BOX,
CommonParams.OpenClose.OPEN
)
reportGloveBoxOpenTrack(openType)
}(照抄 GloveBoxController.kt:221-229)
默认 openType=1(无密码开箱),常量 GLOVE_BOX_OPEN_NO_PASSWORD = 1、GLOVE_BOX_OPEN_WITH_PASSWORD = 2 在 VehicleControlReporter.kt:106/:108。
setVehicleProperty(propId, value) 两参版本来自基类 CarPropertyMgrPreferenceController.java:606-615(INVALID_PROP_ID 直接 false,否则 setCarProperty(propertyId, propVal))。此后链路:
SettingsCarPropertyManager.setCarProperty(:429-487)::436先回调reportOneTrackWhenSetProperty;Int 分支:446-449默认isSync=false走异步;:483startTimeOutMonitor启动回读校验超时监视。VehicleControlManager.setIntProperty(:128-130):丢进ThreadPoolUtils.ASYNC,主线程立即返回;异步线程里setIntPropertyBySync(:132-141)下发 vehicled,成功后打:135的>>> Done set propVal: %d to propId: %s, aId: %d。
「写完即报」语义由此成立:openGloveBox 里 setVehicleProperty(:224-227)只是把写请求排进线程池,主线程下一行就执行 reportGloveBoxOpenTrack(openType)(:228)。埋点不等平台回执、不等回读确认、不关心 vehicled 是否受理——所以实测日志里 reportOpenGloveBox type=1 打在 Done set propVal 之前(见第 3 节)。
2.7 reportGloveBoxOpenTrack():埋点收口
private fun reportGloveBoxOpenTrack(openType: Int) {
try {
VehicleControlReporter.reportOpenGloveBox(openType)
} catch (e: Exception) {
MLog.tag(TAG).i("reportGloveBoxOpenTrack error: ${e.message}")
}
}(照抄 GloveBoxController.kt:235-241)
VehicleControlReporter.reportOpenGloveBox(VehicleControlReporter.kt:495-505)::497 先打 reportOpenGloveBox type=$type 日志,再 TrackEvent.create(Event.CLICK, TIP_OPEN_GLOVE_BOX) 携带 KEY_GLOVE_BOX_OPEN_TYPE=type 与车辆控制 Tab 的 instanceId 上报。try/catch 保证埋点 SDK 异常绝不影响开箱主链。
2.8 账号广播注册(含 API 33 导出标志)
onCreateInternal 调 registerReceiver()(:147),实现:
private fun registerReceiver() {
if (mLoginReceiver == null) {
mLoginReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
setGloveBoxPwdSettingEntryVisibility()
}
}
}
val intentFilter = IntentFilter().apply {
addAction(CarSettingsJump.UserAccount.USER_DATA_CHANGED)
addAction(CarSettingsJump.UserAccount.LOGIN_ACCOUNTS_POST_CHANGED)
}
// AI(claude) auto generated at 2026-08-24 BEGIN
// 用途: API 33+ 动态注册广播接收器必须声明导出标志
if (Build.VERSION.SDK_INT >= 33) {
BaseApplication.getGlobalApp().applicationContext.registerReceiver(
mLoginReceiver, intentFilter,
CarSettingsJump.UserAccount.USER_PERMISSION, null,
0x2 /* RECEIVER_EXPORTED */
)
} else {
BaseApplication.getGlobalApp().applicationContext.registerReceiver(
mLoginReceiver, intentFilter,
CarSettingsJump.UserAccount.USER_PERMISSION, null
)
}
}(照抄 GloveBoxController.kt:305-332)
- 监听两个 action:
USER_DATA_CHANGED/LOGIN_ACCOUNTS_POST_CHANGED(:314-315),收到即重算密码入口可见性(:309)。 - API 33+ 走五参
registerReceiver并显式传0x2 (RECEIVER_EXPORTED)(:320-325);33 以下走四参带权限版本(:326-331)。广播带USER_PERMISSION签名权限,导出无外部滥用面。配对的unregisterReceiver()在 :335-340,置空mLoginReceiver防重复注销。与出货快照的关系见第 7 节。
3. 「写完即报」实证:2026-10-19 mach 台架日志逐行对照
2026-10-19 mach 台架(无密码车辆)实测点击「打开手套箱」的日志序列,逐行锚定代码:
| # | 日志行 | 出处 | 说明 |
|---|---|---|---|
| 1 | ... #onTabClicked() on tab: Tab[打开手套箱, false, true] | GloveBoxController.kt:117 | withOnClickListener 首行无条件打。Tab 三元组:mIsSelected=false(未开)、isAvailable=true → 进 :119 showGloveBoxSwitchClick |
| 2 | no password, open glove box | GloveBoxController.kt:267 | :265 GloveBoxPasswordTools.getLocalPwd().isNullOrEmpty() 为 true(GloveBoxPasswordTools.kt:110),:262 的 mIsSelected 判断已为 false |
| 3 | openGloveBox openType=1 | GloveBoxController.kt:223 | 默认参数 GLOVE_BOX_OPEN_NO_PASSWORD=1(:222;常量 VehicleControlReporter.kt:106) |
| 4 | reportOpenGloveBox type=1 | VehicleControlReporter.kt:497 | 由 :228 → :237 触发。先于 #5:setVehicleProperty 只把写请求丢进 ThreadPoolUtils.ASYNC(VehicleControlManager.java:128-130),主线程立刻走到埋点 |
| 5 | >>> Done set propVal: 1 to propId: 0x6140b407, aId: ... | VehicleControlManager.java:135 | 异步线程内 setIntPropertyBySync(:132-141)下发成功。0x6140b407 = Peripheral.GLOVE_BOX(Peripheral.java:576-580),propVal=1 = CommonParams.OpenClose.OPEN |
| 6 | onDataVerifyFailed propId: 0x6140b407, ..., propVal: 1(回读 v=0) | SettingsCarPropertyManager.kt:199-201 | setCarProperty 在 :483 起的超时监视到期,handlePropertyTimeout(:193-203)发现 set 值 1 与缓存回读值 0 不等(:198),回调 onDataVerifyFailed |
第 6 行是台架 vehicled 不持久 SET 的回滚假象:台架 vehicled 对 GLOVE_BOX 写请求受理后不持久(随后回滚为 0),App 侧回读校验必然失败。它不表示开箱失败,实车链路以 MCU 执行为准;mock 与台架判定边界详见 06-属性通道与台架mock.md。
一句话总结:UI 层认为「写到 vehicled 的 Binder 接口」即完成,埋点同刻上报;属性真实状态完全依赖后续 onHandlePropertyChange 回读刷新,两者解耦。
4. 不可用原因映射表
showGloveBoxSwitchUnavailableNotify(:288-302)全量分支:
reason(Peripheral.GLOVE_BOX_UNAVL_REASON 回读值) | 枚举值(Peripheral.java:1426-1430) | 代码行 | Toast 资源 | 文案(zh-rCN) |
|---|---|---|---|---|
NOT_DIS_ARMED | 0x1 | :292 | R.string.glove_box_fail_need_unlock | 「请解锁车辆后重试」 |
ANTY_PLAY | 0x2 | :293 | R.string.glove_box_fail_anty_play | 「操作过于频繁,请稍后再试」 |
| 其它 + 代客模式 | 任意 | :294-295 | R.string.glove_box_fail_valet_mode | 代客模式不可用提示 |
其它 + 非代客(含 IDLE=0x0、未知值、信号丢失) | — | :296 | Resources.ID_NULL | 静默,不弹 Toast(:299 拦截) |
文案出处见 参考change-165854.md 第 1 节(该 change 首次建立此映射并沿用至今,中文文案为其 commit 中字符串证据)。
5. 错误达上限 → 车主验证:本篇只画入口与回调
showGloveBoxSwitchClick 第二分支(:269-271)进入 showAccountVerifyPage(:210-219):
private fun showAccountVerifyPage() {
MLog.tag(TAG).i("showAccountVerifyPage: pwd limit reached")
GloveBoxAccountVerifyUtils.openVerifyPage {
if (it) {
GloveBoxPasswordTools.setPwdWrongTimes(0)
openGloveBox(TrackValues.GLOVE_BOX_OPEN_WITH_PASSWORD)
reportGloveBoxForgotPasswordTrack()
}
}
}(照抄 GloveBoxController.kt:210-219)
入口侧 GloveBoxAccountVerifyUtils.openVerifyPage(GloveBoxAccountVerifyUtils.kt:45-57)有一个手套箱特有的前置闸:默认检查 P 挡——getIntProperty(Driving.GEAR, ...) != Gear.PARK 时(:50-51)弹 glove_box_fail_pwd_limit 并返回 false(:53-54),验证页不起;P 挡才委托通用 PinAccountVerifyUtils.openVerifyPage(:56)。
验证通过(it == true)回调里按固定顺序做三件事:setPwdWrongTimes(0) 清零错误计数(:214 → GloveBoxPasswordTools.kt:126-129);openGloveBox(GLOVE_BOX_OPEN_WITH_PASSWORD) 以 openType=2 开箱并埋点(:215);reportGloveBoxForgotPasswordTrack() 上报忘记密码验证成功事件(:216 → :246-252 → VehicleControlReporter.kt:510-519,Event.EXECUTE)。
扫码验证页内部(Intent action、confirm_scene=glovebox_verify、结果广播)归 04 篇,本篇不展开。
6. 开箱主流程时序图
sequenceDiagram autonumber actor 用户 participant Ctrl as "GloveBoxController" participant Pwd as "PasswordTools / PasswordCheckUtils" participant Acct as "GloveBoxAccountVerifyUtils" participant Base as "CarPropertyMgr... / SettingsCarPropertyManager" participant VCM as "VehicleControlManager(异步)" participant Rpt as "VehicleControlReporter" participant VHAL as "vehicled / VHAL" 用户->>Ctrl: 点击「打开手套箱」 Note over Ctrl: isAvailable=false 时走<br/>showGloveBoxSwitchUnavailableNotify(:121) Ctrl->>Ctrl: showGloveBoxSwitchClick(tab)(:261) alt 已打开 Ctrl->>用户: Toast 请手动关闭(:263) else 无密码 Ctrl->>Pwd: getLocalPwd()=null(:265) Ctrl->>Ctrl: openGloveBox(openType=1)(:268) else 错误达上限 Ctrl->>Acct: showAccountVerifyPage()(:271) Acct-->>Ctrl: 回调 true(P挡闸 :50-55) Ctrl->>Pwd: setPwdWrongTimes(0)(:214) Ctrl->>Ctrl: openGloveBox(openType=2)(:215) Ctrl->>Rpt: reportGloveBoxForgotPasswordSuccess()(:216) else 有密码 Ctrl->>Pwd: goToCheckPassword(CHECK_PWD)(:275) Pwd-->>Ctrl: 回调 true Ctrl->>Ctrl: openGloveBox(openType=2)(:201) end Ctrl->>Base: setVehicleProperty(GLOVE_BOX, OPEN)(:224) Base->>VCM: setCarProperty→setIntProperty 入ASYNC线程(:128-130)<br/>同时 startTimeOutMonitor(:483) Ctrl->>Rpt: reportGloveBoxOpenTrack(openType)(:228) Note over Ctrl,Rpt: 写完即报:埋点日志先于 Done VCM->>VHAL: setIntProperty 下发(:134) VCM->>VCM: Done set propVal: 1 to 0x6140b407(:135) VHAL-->>Base: 属性回读 / 超时 alt 回读 != set值(台架不持久假象) Base->>Ctrl: onDataVerifyFailed(propVal=1)(:199-201) else 正常回读 OPEN Base->>Ctrl: onHandlePropertyChange(:166) Ctrl->>用户: Tab 刷新 mIsSelected=true(:177-178) end
7. dev 与出货快照差异表
对比对象:W(dev @ 930be9145)vs pack_a17_cn_20260923,同路径 GloveBoxController.kt。
| 区段 | dev(W) | 出货快照 | 差异 |
|---|---|---|---|
| 全文 | 341 行 | 341 行 | diff 无任何输出,两版逐字节一致 |
registerReceiver()(:305-332) | 含 API 33+ RECEIVER_EXPORTED(0x2)五参分支(:320-325)+ 四参带权限分支(:326-331) | 同左 | 无差异。出货版已包含 API33 导出标志适配,注释 AI(claude) auto generated at 2026-08-24(:318)同样存在 |
结论:本篇所有行号对 dev 与 0923 出货包同样适用,不存在「出货版缺 RECEIVER_EXPORTED」的分叉。
8. 证据清单
| 文件(绝对路径) | 行号区间 | 一句话说明 |
|---|---|---|
/home/zbc/car/fuben4_micarsettings/MiCarSettings-5458412/settingsPage/VehicleBodyControl/src/main/java/com/android/car/settings/miauto/vehicle/glovebox/GloveBoxController.kt | :54-341(全文已读) | 主类:双 Tab、三分支开箱、原因 Toast、埋点、账号广播注册 |
同上(出货)/home/zbc/car/pack_a17_cn_20260923/settingsPage/VehicleBodyControl/src/main/java/com/android/car/settings/miauto/vehicle/glovebox/GloveBoxController.kt | 全文 | 与 dev diff 完全一致 |
/home/zbc/car/fuben4_micarsettings/MiCarSettings-5458412/settingsPage/VehicleBodyControl/src/main/java/com/android/car/settings/miauto/vehicle/VehicleBodyPropertyMap.kt | :42-50, :55-63 | createGloveBoxSwitchCtrl / createGloveBoxPasswordSetCtrl,withAllowClickWhenDisabled(true) 在 :48/:61 |
/home/zbc/car/fuben4_micarsettings/MiCarSettings-5458412/base/settingsVehicleLib/src/main/java/com/android/car/settings/miauto/vehicle/VehiclePropertyUtil.java | :173-182, :55-71 | isPropertyAvailable(状态可用判定)、getIntPropertyValue(null→0) |
/home/zbc/car/fuben4_micarsettings/MiCarSettings-5458412/base/settingsVehicleLib/src/main/java/com/android/car/settings/miauto/common/CarPropertyMgrPreferenceController.java | :606-615 | 两参 setVehicleProperty,委托 setCarProperty |
/home/zbc/car/fuben4_micarsettings/MiCarSettings-5458412/base/settingsVehicleLib/src/main/java/com/android/car/settings/miauto/vehicle/SettingsCarPropertyManager.kt | :429-487, :193-203 | setCarProperty(isSync=false 异步 + :483 超时监视);handlePropertyTimeout/onDataVerifyFailed 回读校验日志 :199-201 |
/home/zbc/car/fuben4_micarsettings/MiCarSettings-5458412/base/settingsVehicleLib/src/main/java/com/android/car/settings/miauto/vehicle/VehicleControlManager.java | :128-141 | setIntProperty 丢 ThreadPoolUtils.ASYNC;>>> Done set propVal 日志 :135 |
/home/zbc/car/fuben4_micarsettings/MiCarSettings-5458412/base/settingsBaseLib/src/main/java/com/android/micar/settings/track/VehicleControlReporter.kt | :106, :108, :495-505, :510-519 | openType 常量 1/2;reportOpenGloveBox(:497 日志);reportGloveBoxForgotPasswordSuccess |
/home/zbc/car/fuben4_micarsettings/MiCarSettings-5458412/base/settingsBaseLib/src/main/java/com/android/car/settings/miauto/vehicle/MiCarPropertyIds.java | :1485 | DrivingCtrl.GLOVE_BOX = Peripheral.GLOVE_BOX |
/home/zbc/pangu/xcd_xring_a17_fermi/vendor/micar/packages/services/MiVehicleService/support-lib/src/mi/car/config/Peripheral.java | :576-580, :606-610, :1426-1430 | GLOVE_BOX=0x6140b407、GLOVE_BOX_UNAVL_REASON=0x6140b40a、GloveBoxUnavlReason IDLE/NOT_DIS_ARMED/ANTY_PLAY |
/home/zbc/car/fuben4_micarsettings/MiCarSettings-5458412/settingsPage/VehicleBodyControl/src/main/java/com/android/car/settings/miauto/vehicle/glovebox/GloveBoxPasswordTools.kt | :24-41, :110, :126-129, :135-139 | 密码工具委托 PinPasswordTools;getLocalPwd/setPwdWrongTimes/isPwdLimit |
/home/zbc/car/fuben4_micarsettings/MiCarSettings-5458412/settingsPage/VehicleBodyControl/src/main/java/com/android/car/settings/miauto/vehicle/glovebox/GloveBoxPasswordCheckUtils.kt | :50-58 | goToCheckPassword 接口签名 |
/home/zbc/car/fuben4_micarsettings/MiCarSettings-5458412/settingsPage/VehicleBodyControl/src/main/java/com/android/car/settings/miauto/vehicle/glovebox/GloveBoxAccountVerifyUtils.kt | :45-57 | openVerifyPage 的 P 挡前置闸 |
/home/zbc/下载/test/车机Feature/Meego 5458412/kb/参考change-161208.md | 全文 | 开箱主流程与密码链的来源演进(Meego 2350608) |
/home/zbc/下载/test/车机Feature/Meego 5458412/kb/参考change-165854.md | 全文 | 不可用原因 → Toast 映射与中英文案出处 |
| 2026-10-19 mach 台架实测日志序列 | 任务给定,逐行见第 3 节 | 「写完即报」与台架回滚假象的实证(截图佐证:Meego 5458412/test/screenshots/打开手套箱点击后-mach-20261019.png) |