03 · 遮阳帘天幕与车顶密码专题

这是 Lock 模块最复杂的部分:5 类易混的”顶部覆盖物” + 车顶安全锁密码子系统 + DoorUnLockActivity。

一、5 类顶部覆盖物(必须先分清)

Lock 模块信号多(DIM_ROOF_TRANSMIT_LEVEL 引用 12 次最多),表面看”信号很多”,实际是 5 套独立机制并列

#类型硬件本质调节方式关键信号配置字
1调光天幕 DIM_ROOF电致变色玻璃(无机械运动)Tab 两档DIM_ROOF_TRANSMIT_LEVELWindowASM(DIMMING_ROOF/ELECTROCHROMIC)
2天窗遮阳帘 RoofSunShade物理卷帘(前天窗下)滑杆+长按点动SUN_SHADE_ADJ_HMI+SUN_SHADE_CURRENT_POSNSunroofSunshade=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_ENTRYisAutomaticSuspensionLoweringEnable(E4U3 后)

二、调光天幕(DIM_ROOF)— Tab 两档非滑杆

调节方式

SmartSunRoofTabControllerTab 二选一(非连续滑杆):

  • 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=后(两块玻璃独立调),SmartSunRoofSyncControllerDIM_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,吸附到档位节点。

锁车自动关

RoofSunShadeAutoControllerLOCK_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 区分

RearSunShadeAutoCloseControllerRoofSunShadeAutoController 共用 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)

类似手套箱密码,防止误操作升降车顶RoofSafetyLockControllerSettings.Global非车信号)。

密码整体流程

  1. 开启安全锁RoofSafetyLockController):
    • 错误超限 → 账号验证 → 重置 → 开启
    • 无密码 → 拉设置密码页 → 成功后开启
    • 有密码 → 直接开启
    • 写入 Settings.Global[roof_safety_lock_enabled]=1 + 通知 MIS
    • 未登录时隐藏开关
  2. 进入车顶帐篷RoofTentAdjustController)前校验:
    • 开关开启 + 本地有密码 → 拉起 RoofPasswordCheckUtilsRoofPasswordDialogActivityRoofPasswordFragment(4 位 PIN)
    • 错误次数累计到 roof_password_wrong_times,达上限触发账号验证(P 挡限制)
  3. 密码存储Settings.Global[roof_password](SHA-256 哈希)+ roof_password_salt

关键类

作用
RoofSafetyLockController开关(Settings.Global + ContentObserver)
RoofPasswordEntryController设置/修改密码入口
RoofPasswordFragment4 位 PIN 输入(继承 BasePinPasswordFragment)
RoofPasswordDialogActivity密码弹窗宿主(BaseConflictDialogActivity)
RoofPasswordTools/RoofPasswordCheckUtils/RoofAccountVerifyUtils/RoofSafetyLockUtils工具类(存储/校验/账号验证/开关读写)

MIS 安全服务通信(mis 包)

RoofSecurityNotifier(object)封装 MIS spec 事件:

  • notifySafetyLockSwitchLiftingLoweringRoofSafetyLockSwitch 属性
  • notifyPasswordAttemptLimitStatus...PasswordAttemptsExceededStatus
  • notifyPasswordVerificationFeedback...PasswordVerification 事件
  • notifyOwnerIdentityVerificationResultFeedbackOwnerIdentityVerificationPopupResult

八、DoorUnLockActivity(车门解锁失败弹窗)

与门锁 Controller 几乎无直接关系——独立运行的全屏弹窗。

public class DoorUnLockActivity extends FragmentActivity implements CarPropertyManagerCallback
  • 触发android.settings.DOOR_UNLOCK Intent(外部系统在车门解锁失败/未关锁失败时发送,非用户点击)
  • 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)

  • 继承 BaseRightFragmentgetInitCarModelImgRes() 返回静态车模图 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)