03 · 遮阳帘天幕与车顶密码专题
这是 Lock 模块最复杂的部分:5 类易混的”顶部覆盖物” + 车顶安全锁密码子系统 + DoorUnLockActivity。
一、5 类顶部覆盖物(必须先分清)
Lock 模块信号多(DIM_ROOF_TRANSMIT_LEVEL 引用 12 次最多),表面看”信号很多”,实际是 5 套独立机制并列:
| # | 类型 | 硬件本质 | 调节方式 | 关键信号 | 配置字 |
|---|---|---|---|---|---|
| 1 | 调光天幕 DIM_ROOF | 电致变色玻璃(无机械运动) | Tab 两档 | DIM_ROOF_TRANSMIT_LEVEL | WindowASM(DIMMING_ROOF/ELECTROCHROMIC) |
| 2 | 天窗遮阳帘 RoofSunShade | 物理卷帘(前天窗下) | 滑杆+长按点动 | SUN_SHADE_ADJ_HMI+SUN_SHADE_CURRENT_POSN | SunroofSunshade=ELECTRIC(E4U3 前) |
| 3 | 后排遮阳帘 RearSunShade | 物理卷帘(后窗) | 弹窗 SeekBar+一键+校准 | SUNSHADE_TARGET_POSITION+SUN_SHADE_LRN_SET | 同上(E4U3 后) |
| 4 | 车顶帐篷 RoofTent | 升降式车顶(Kunlun) | 跳外部 APP(密码保护) | Body.POWER_LIFTING_ROOF_* | isSunRoofSupported(E4U3 前) |
| 5 | 自动降悬架 | 悬架(非顶部) | 开关 | DrivingCtrl.EASY_ENTRY | isAutomaticSuspensionLoweringEnable(E4U3 后) |
二、调光天幕(DIM_ROOF)— Tab 两档非滑杆
调节方式
SmartSunRoofTabController 用 Tab 二选一(非连续滑杆):
LEVEL1= 最暗(遮光,POSITION_0)LEVEL5= 最透明(POSITION_1)
// SmartSunroofProperty.kt
POSITION_0(遮光) → setVehicleProperty(DIM_ROOF_TRANSMIT_LEVEL, LEVEL1, MiVehicleAreaBody.BOTTOM)
POSITION_1(透明) → setVehicleProperty(DIM_ROOF_TRANSMIT_LEVEL, LEVEL5, MiVehicleAreaBody.TOP)双分区 areaId
- 单分区:整体调
- 双分区:BOTTOM=前 / TOP=后(两块玻璃独立调),
SmartSunRoofSyncController控DIM_ROOF_TRANSMIT_SYNC(=Body.MULTIPLE_ZONE_SYNCHRONIZATION_SET)联动
500ms 延时校验(防中间态闪动)
用户点 Tab → 立即下发 setProperty
→ isInDelayCheck=true(500ms 屏蔽期,期间 onPropertyChanged 被忽略)
→ 500ms 后 Handler 主动 getProperty() 重新刷 UI
→ 若期间用户点了别的 Tab(mCurrentPosition 已变)就不刷
不可用原因
DIM_ROOF_SET_UNAVL_REASON:SYSFAULT→Toast;OVER_HEAT/HI_TEMPERATURE/LOW_TEMPERATURE→Dialog(跨进程拉 CarSafetyServiceSettings.ALERT_DIALOG)
三、天窗遮阳帘(物理卷帘)— 滑杆 + 长按点动
RoofSunShadePositionController(@PropertyRange(lower=0, upper=100))+ RoofSunShadeSliderPreference(中间滑杆 + 左右两个 MaterialButton)。
两条写入路径
A. 长按按钮(点动模式)——用 TouchListener 而非 ClickListener(需按下/松开两事件):
onLeftActionDown → setVehicleProperty(SUN_SHADE_ADJ_HMI, REARWARD) // 持续收起
onLeftActionUp → setVehicleProperty(SUN_SHADE_ADJ_HMI, IDLE) // 停
onRightActionDown → setVehicleProperty(SUN_SHADE_ADJ_HMI, FORWARD) // 持续展开
onRightActionUp → setVehicleProperty(SUN_SHADE_ADJ_HMI, IDLE) // 停B. 滑杆拖动(绝对位置):
onStopTrackingTouch → setCarPropertyWithoutDelayCheck(SUN_SHADE_CURRENT_POSN, sliderValue)
// ⚠️ SUN_SHADE_CURRENT_POSN 实际是 SUNSHADE_TARGET_POSITION(目标位置,命名陷阱)有级吸附:seekProgress = (seekProgress / stepSize) * stepSize,吸附到档位节点。
锁车自动关
RoofSunShadeAutoController 控 LOCK_CAR_CLOSE_SUN_SHADE_CONFIGURATION,7 种 disable reason(SYS_FLT/NOT_LERND/ANTY_PLAY/POWER_LOW/HIGH/THERMAL_HIGH/ANTI_TRAP_SYSTEM_REVERSE)。
四、后排遮阳帘 — 弹窗式 + 自学习校准
入口分流(CustomRearSunshadeCurtainPreferenceController)
点击入口 → 读 SUN_SHADE_LEARN_STATUS
UNKNOWN/NOT_LEARN/LEARN_FAILED → 跳校准页(RearSunshadeCalibrationDialog)
其他(已校准) → 跳调节页(RearSunshadeAdjustmentDialog)右侧副标题:自学习状态优先于开关状态,未校准显示橙色”Calibration required”。
调节弹窗(RearSunshadeAdjustmentFragment)
- SeekBar 拖动 →
SUNSHADE_TARGET_POSITION(绝对位置) - 一键展开/收起/停止 →
SUN_SHADE_STS(FULL_OPEN/FULL_CLS/CLOSE_STOP) - 1000ms 延迟刷新:写命令后主动延迟 1 秒再读
SUN_SHADE_STS(避免按钮闪烁) - 按钮显隐状态机:FULL_OPEN(禁展开)/ OPENING(变”停止”)/ CLOSING / FULL_CLS(禁收起)
自学习校准(RearSunshadeCalibrationFragment)— 必须长按
为什么需要校准? 物理遮阳帘电机位置计数器需建立基准点(0%/100% 实际位置)。断电/更换/防夹反转后位置失准,需”自学习”。校准期间电机从一端慢慢走到另一端记录端点。
交互流程(长按式,安全保护):
ACTION_DOWN → setProperty(SUN_SHADE_LRN_SET, SET) + showCalibratingProgress
(必须按住才校准,松手即停,防卡阻损坏)
ACTION_UP → setProperty(SUN_SHADE_LRN_SET, IDLE) + 读 SUN_SHADE_LEARN_STATUS
车端反馈:
LEARNING→ UI “Calibrating. Keep holding…”LEARN(完成)→ UI “Calibrated successfully”,3 秒后跳调节页
校准按钮可用性:SUN_SHADE_MANUAL_DISABLE_REASON == IDLE。
共用信号 areaId 区分
RearSunShadeAutoCloseController 与 RoofSunShadeAutoController 共用 LOCK_CAR_CLOSE_SUN_SHADE_CONFIGURATION,靠 areaId 区分前后遮阳帘。
⚠️ 遮阳帘无速度保护(行车可调),仅车顶帐篷有 P 挡保护。
五、车顶帐篷(RoofTentAdjustController,旧 E4U3 前)
- 信号:
Body.POWER_LIFTING_ROOF_MODULE_CURRENT_STATUS+_PERCENT_POSITION+DrivingCtrl.GEAR - P 挡保护(关键安全约束):
preference.isEnabled = isInGearPark(),非 P 挡置灰 + Toast - 密码安全锁:
RoofSafetyLockUtils.isEnabled && hasLocalPwd→ 校验(错误超限走账号验证)→ 进入(跳外部com.mi.car.launcher.SETTINGS_ROOF) - 右侧文本状态机:FULL_CLOSE→“Retracted” / FULL_OPEN→“Fully extended” / 部分→“N% extended”
六、升降车顶大组件(RoofPreferenceController,新 E4U3 后)
关注 13 个 Body.POWER_LIFTING_ROOF_ 信号*(开/升/降按钮 + 状态 + 位置 + 多种不可用原因 + 空间不足/车外有人/二段床提醒)。
- 长按/点按 open/fall/lift 按钮
- 二次确认弹窗(
RoofOptionConfirmDialog/RoofFallInspectConfirmDialog) - 中断弹窗(升顶空间不足、降顶车外有人等)
- 通过
Body.POWER_LIFTING_ROOF_*_COMMAND发命令
E4U3 前显示「车顶帐篷入口」(旧),E4U3 后显示「升降车顶大组件」(新),两者互斥。
七、车顶安全锁密码子系统(完整 PIN + MIS)
类似手套箱密码,防止误操作升降车顶。RoofSafetyLockController 用 Settings.Global(非车信号)。
密码整体流程
- 开启安全锁(
RoofSafetyLockController):- 错误超限 → 账号验证 → 重置 → 开启
- 无密码 → 拉设置密码页 → 成功后开启
- 有密码 → 直接开启
- 写入
Settings.Global[roof_safety_lock_enabled]=1+ 通知 MIS - 未登录时隐藏开关
- 进入车顶帐篷(
RoofTentAdjustController)前校验:- 开关开启 + 本地有密码 → 拉起
RoofPasswordCheckUtils→RoofPasswordDialogActivity→RoofPasswordFragment(4 位 PIN) - 错误次数累计到
roof_password_wrong_times,达上限触发账号验证(P 挡限制)
- 开关开启 + 本地有密码 → 拉起
- 密码存储:
Settings.Global[roof_password](SHA-256 哈希)+roof_password_salt
关键类
| 类 | 作用 |
|---|---|
RoofSafetyLockController | 开关(Settings.Global + ContentObserver) |
RoofPasswordEntryController | 设置/修改密码入口 |
RoofPasswordFragment | 4 位 PIN 输入(继承 BasePinPasswordFragment) |
RoofPasswordDialogActivity | 密码弹窗宿主(BaseConflictDialogActivity) |
RoofPasswordTools/RoofPasswordCheckUtils/RoofAccountVerifyUtils/RoofSafetyLockUtils | 工具类(存储/校验/账号验证/开关读写) |
MIS 安全服务通信(mis 包)
RoofSecurityNotifier(object)封装 MIS spec 事件:
notifySafetyLockSwitch→LiftingLoweringRoofSafetyLockSwitch属性notifyPasswordAttemptLimitStatus→...PasswordAttemptsExceededStatusnotifyPasswordVerification→Feedback...PasswordVerification事件notifyOwnerIdentityVerificationResult→FeedbackOwnerIdentityVerificationPopupResult
八、DoorUnLockActivity(车门解锁失败弹窗)
与门锁 Controller 几乎无直接关系——独立运行的全屏弹窗。
public class DoorUnLockActivity extends FragmentActivity implements CarPropertyManagerCallback- 触发:
android.settings.DOOR_UNLOCKIntent(外部系统在车门解锁失败/未关锁失败时发送,非用户点击) - Manifest:exported=true,launchMode=singleInstance,taskAffinity=
:screenClean,theme=DarkFullscreenTheme - 订阅:
Door.STATE(按 area 区分 4 门+尾门,切换图标)+Door.DOOR_NOT_CLOSED_LOCK_FAILED(CANCEL 时自动 finish) - 8 秒倒计时自动关闭(TIME_TO_DISMISS=8),onNewIntent 重置计时
- 海外保留状态栏(合规,AI(claude) 生成注释)
- 自己持有
SettingsCarPropertyManager,与门锁 Controller 不共享状态
九、右栏(DoorAndWindowLockRightFragment)
- 继承
BaseRightFragment,getInitCarModelImgRes()返回静态车模图micar_car_model_door_window_lock shouldListenViewScroll()=true,监听左滚- 核心业务:升降车顶显示态信号管理——当
pk_vehicle_control_roof_category可见时发Body.POWER_LIFT_ROOF_ADJUST_FLAG=POWER_LIFT_ROOF_ADJUST(通知底层”升降顶面板正在显示”),不可见发 IDLE DoorAndWindowLockRightFragmentController是空壳(仅 TAG)