03 · 门开关业务流程图

车门业务有两条主线,交汇点都是「读写车辆信号 + 车门状态可视化」:

主线触发方入口典型场景
A · 设置页主动操作用户VehicleDoorToggleCtrlPreferenceController在锁车设置页点电动门开关
B · 离车提醒弹窗车端信号UnlockDoorTrigger(scene) → DoorUnLockActivity锁车时检测到门没关,弹窗提醒

主线 A:设置页主动开门(电动门)

sequenceDiagram
    autonumber
    participant User as 用户
    participant Ctrl as VehicleDoorToggleCtrlPreferenceController
    participant Base as CarPropertyMgrPreferenceController(基类)
    participant SCPM as SettingsCarPropertyManager
    participant VCM as VehicleControlManager
    participant Car as 车端

    Note over Ctrl: onCreateInternal 注册关心的信号<br/>POWER_OPERATED_DOOR_MOVING_STATUS 等

    User->>Ctrl: 点击电动门开关按钮
    Ctrl->>Ctrl: onClickButton 判断当前状态 [:100]
    Ctrl->>Ctrl: setVehiclePropertyByStatus 决定命令 [:110]

    Ctrl->>Base: setVehicleProperty(BUTTON_STATUS, ON/OFF/STOP, area)
    Base->>SCPM: setCarPropertyBySync(propId, value, area)
    SCPM->>SCPM: 埋点 + 连接检查 + 启动超时监控
    SCPM->>VCM: setIntPropertyBySync
    VCM->>Car: AOSP setProperty (异步线程)

    Car-->>VCM: 车端执行 + 回弹 MOVING_STATUS
    VCM-->>SCPM: onChangeEvent
    SCPM-->>Base: onPropertyChanged
    Base-->>Ctrl: onHandlePropertyChange [:150]
    Ctrl->>Ctrl: updateUI 更新按钮态(开/关/暂停) [:163]

    alt 不可用(高速/防玩/温度)
        Car-->>SCPM: DISABLE_REASON
        SCPM-->>Ctrl: onPropertyChanged
        Ctrl->>Ctrl: showToast 不可用原因 [:284]
    end

关键点

  • 命令下行用 POWER_OPERATED_DOOR_BUTTON_STATUS(ON/OFF/STOP),状态回读用 POWER_OPERATED_DOOR_MOVING_STATUS(6 态)。
  • 超时监控自动启动:车端不回弹会触发 onSetPropertyTimeout → 提示用户。
  • 不可用原因单独一个信号 POWER_OPERATED_DOOR_DISABLE_REASON,UI 弹对应 Toast。

主线 B:离车提醒弹窗(JIRA 1838/1839 场景)

sequenceDiagram
    autonumber
    participant Car as 车端 MCU
    participant VHAL as VHAL/CarPropertyService
    participant CPCM as CarPropertyCacheManager
    participant Trigger as UnlockDoorTrigger<br/>(com.micar.scene aar)
    participant Act as DoorUnLockActivity<br/>(本仓库 car.settings)
    participant SCPM as SettingsCarPropertyManager
    participant Handler as 8s 倒计时Handler

    Note over Car: 用户锁车,活体检测发现门没关
    Car->>VHAL: LockFltRemdForAlive(0x61403156) v=1 LOCK_FAIL
    VHAL->>CPCM: onChangeEvent
    CPCM->>Trigger: processSignal(v=1) [:79-86]
    Note over Trigger: 无 cooldown! 每次 v=1 都拉起 [:116-132]
    Trigger->>Act: startActivity(DoorUnLockActivity)

    Note over Act: onCreate [:57-83]
    Act->>Act: setContentView(lock_door_unlock_layout)<br/>⚠️ 5 门 ImageView 默认全 unlock(开态) [:59]
    Act->>SCPM: new SettingsCarPropertyManager + setCarManagerCallback(this) [:80-81]
    Act->>Handler: sendMessageDelayed 8s 倒计时 [:82]

    Act->>Act: onPropertyManagerPrepared [:86-89]
    Act->>SCPM: registerPropertyCallback(Door.STATE, LOCK_FAILED) [:88]

    Note over Car: 车端 Door.STATE(0x66403101) 6 area 回弹
    Car->>VHAL: Door.STATE 逐 area v=0/1
    VHAL->>CPCM: onChangeEvent (首注册异步,不 callbackByCache)
    loop 60ms 窗口逐门到达
        CPCM->>SCPM: onChangeEvent
        SCPM->>Act: onPropertyChanged [:98-147]
        Act->>Act: 按 area+value setImageResource [:110-138]
        Note over Act: ⚠️ 多帧切换 = 闪烁源(1839)
    end

    alt 8s 到点
        Handler->>Act: finish() [:47-49]
    else 收到 v=2 CANCEL
        Car->>VHAL: 0x61403156 v=2
        VHAL->>SCPM: onChangeEvent
        SCPM->>Act: onPropertyChanged(LOCK_FAILED, CANCEL) [:141]
        Act->>Act: finish() [:143]
    end

两条线交汇点

graph TD
    A["车端信号变化"] --> B["CarPropertyService / VHAL"]
    B --> C["CarPropertyCacheManager<br/>(单例,分发+缓存)"]
    C --> D["SettingsCarPropertyManager<br/>(per-Controller)"]
    D --> E1["主线A: VehicleDoorToggle...<br/>设置页刷新按钮态"]
    D --> E2["主线B: DoorUnLockActivity<br/>弹窗刷新车门图标"]
    F["用户操作设置页"] --> G["setCarPropertyBySync 下行"] 
    G --> D

主线 A 和 B 是两套独立的 UI,但共享底层 SettingsCarPropertyManager + CarPropertyCacheManager。区别:

  • A 是 PreferenceController(设置页内),用户主动触发,有预读onCreateInternal 就注册并刷新)。
  • B 是 Activity(弹窗),信号触发,无预读onCreatesetContentView,等 onPropertyManagerPrepared 异步注册)——这正是 JIRA 1839 闪烁的根因。

主线 B 的 Activity 生命周期(JIRA 1838 关联)

stateDiagram-v2
    [*] --> Created: onCreatebr/setContentView(默认5门全开)
    Created --> Prepared: onPropertyManagerPreparedbr/registerPropertyCallback
    Prepared --> Showing: 收到 onChangeEventbr/逐门 setImageResource
    Showing --> Showing: 8s 倒计时进行中
    Showing --> Finished: 8s 到点 finish()
    Showing --> Finished: 收到 v=2 CANCEL finish()
    Showing --> Finished: onStop finish() 【:158-161】
    Finished --> [*]
    Finished --> Created: 下次 v=1 又拉起br/(launchMode=singleInstance + onNewIntent 重置计时)

onStop → finish() + singleInstance:每次信号触发都是全新 onCreate,必走「默认全开 → 异步回弹」流程——这就是 JIRA 1839「必现」的机制原因。


相关:04-MANNPROB-1838-根因-弹窗弹两次.md05-MANNPROB-1839-根因-车门闪烁全开.md