05 - 启动时序与性能全景

维度 E:从时间轴与性能视角,梳理 SettingsApplication 冷启动完整时序、线程模型、耗时分布、风险点与优化方向 关联:启动慢白屏分析-20260626.md(bugreport 实测权威来源)


一、完整启动时序

sequenceDiagram
    participant Zygote as Zygote
    participant Main as 主线程
    participant ASYNC as ASYNC线程池<br/>ThreadPoolUtils.ASYNC
    participant Disp as AppStartTaskDispatcher
    participant MainTask as MainThreadStartTask
    participant AsyncTask as AsyncThreadStartTask
    participant Car as Car服务

    Zygote->>Main: fork 进程
    activate Main
    Main->>Main: attachBaseContext (mApp=this)
    Main->>Main: BaseApplication.onCreate<br/>(initGlobalViewModel)
    Main->>Main: DfxManager.init
    Main->>Main: checkAppMatchRom
    Main->>Main: AppLifecycleTracker 注册
    Main->>Main: AutoDensityConfig.init
    Main->>Main: initLogging (MLog)

    rect rgb(200, 220, 240)
        Note over Main,ASYNC: onCreate 启动调度器
        Main->>Disp: new + setMain + setAsync + start()
        Disp->>Disp: new CountDownLatch(1)

        par 并行启动
            Disp->>ASYNC: execute(AsyncThreadStartTask)
            activate ASYNC
            AsyncTask->>AsyncTask: SettingsTrack 4ms
            AsyncTask->>AsyncTask: VoiceAssist 6ms
            AsyncTask->>AsyncTask: 账号同步 5ms
            AsyncTask->>AsyncTask: VoiceSearch 0ms
            AsyncTask->>Car: initHudConfig 17ms
            AsyncTask->>AsyncTask: Link+MQTT+AudioControl 19ms
            AsyncTask->>AsyncTask: TrackTrigger / UserSwitchCleaner
            Note over ASYNC: 异步总 ~61ms(注释)
            AsyncTask->>Disp: markFinish → countDown()
            deactivate ASYNC
        and
            Disp->>MainTask: run()
            activate Main
            MainTask->>MainTask: ActivityLifecycleCallbacks<br/>(Intent 拦截)
            MainTask->>Car: 配置字块 52ms(注释)<br/>CarProperty 注册~31ms(实测)
            MainTask->>Car: initConnection<br/>蓝牙188ms+热点22ms(实测)
            MainTask->>MainTask: Router.init (反射)
            Note over Main: 主线程实测 247ms<br/>(注释标 71ms)
            deactivate Main
        end

        Disp->>Disp: await(1000ms)
        alt 正常(异步先完成)
            ASYNC-->>Disp: latch 归零,返回
        else 超时(异步>1000ms)
            Note over Disp: 强制返回,异步继续后台跑
        end
    end

    Main->>Main: Log "onCreate finish"
    deactivate Main

    Note over Main,ASYNC: onCreate 返回后,二次派发任务仍在跑
    Main->>ASYNC: initInAsync (License/MisDevice/儿童座椅)
    ASYNC->>ASYNC: refreshModeList / updateAvmCarProperties

二、线程模型

2.1 三类执行域

graph TB
    subgraph Main["主线程(受 await 阻塞)"]
        M1[BaseApplication.onCreate]
        M2["前置依赖<br/>DfxManager/checkAppMatchRom<br/>AppLifecycleTracker/AutoDensity/initLogging"]
        M3["MainThreadStartTask.execute<br/>实测247ms★"]
        M4[await 阻塞 ≤1000ms]
    end

    subgraph Async["ASYNC 线程池(受 latch 约束)"]
        A1["AsyncThreadStartTask.execute<br/>~61ms(注释)"]
        A2[→ countDown 释放 latch]
    end

    subgraph Blind["二次派发盲区(不受 latch 约束)"]
        B1["MainThreadStartTask.initInAsync<br/>License绑定/MisDevice/儿童座椅"]
        B2["refreshModeList"]
        B3["updateAvmCarProperties"]
        B4["VoiceSearch 加载缓存"]
        B5["TrackTrigger 打点"]
    end

    M1 --> M2 --> M3 --> M4
    A1 --> A2 --> M4
    M4 --> Done["onCreate finish"]
    M3 -.->|"execute 内 ASYNC.execute"| B1
    A1 -.->|"内部 ASYNC.execute"| B2
    A1 -.-> B3
    A1 -.-> B4
    A1 -.-> B5

    classDef hot fill:#ffe1e1,stroke:#cc0000
    class M3 hot

2.2 关键发现:二次派发盲区

受 CountDownLatch 约束的只有 AsyncThreadStartTask.execute() 方法体本身。

不受约束的二次派发(在 execute 内部再 ThreadPoolUtils.ASYNC.execute(...)ThreadUtils.postOnBackgroundThread):

  • MainThreadStartTask.initInAsync()(:80-114):License 绑定、MisDevice、网络共享检查、儿童座椅同步
  • AsyncThreadStartTask 内部:SteeringModeViewModel.refreshModeList()(:116)、AvmSwitchSyncHelper.updateAvmCarProperties()(:147)
  • VoiceSearchManager.initSearchManager:异步加载缓存
  • TrackTrigger.init:postOnBackgroundThread

后果:onCreate 返回(甚至首屏渲染)后,这些任务可能仍在跑 → 若访问尚未就绪的资源,存在竞态风险。

2.3 ThreadPoolUtils.ASYNC 线程池

文件:base/settingsBaseLib/.../uitls/ThreadPoolUtils.java:19-22

ThreadPoolExecutor(0, Integer.MAX_VALUE, 60s, SynchronousQueue, "ThreadPoolUtils async thread")

CachedThreadPool 变体:0 核心、无界最大、不缓冲直接移交。无界最大线程数在高并发二次派发时有线程爆炸风险(白皮书历史 ANR 链底曾涉及 ThreadPoolUtils 线程)。


三、耗时瀑布(注释 vs 实测对照)

3.1 主线程耗时对照表(关键)

阶段/项代码注释标注bugreport 实测(权威)差异说明
前置依赖(Dfx/Rom/Density/Log)未标~30ms-
配置字块(:61-68)52msCarProperty 注册 ~31ms实测仅 CarProperty 部分
initConnection(蓝牙+热点+WiFi)27ms蓝牙 188ms + 热点 22ms ≈ 210ms🔴 实测是注释的 7.8 倍
Router.init0ms-反射开销未计
反射 CNFE 噪声-4ms+/次BroadcastSourceInfoHandler
MainThreadStartTask 总计71ms247ms🔴 实测是注释的 3.5 倍

实测工况放大因素(白皮书):

  • 驾驶员切换触发的新用户冷启动(非常驻进程重启)
  • CPU 95°C / thermal level-3,大核砍 17%
  • 30+ user14 进程并发抢 AMS 锁(AM binder 528ms)

3.2 异步任务耗时(仅注释,无独立实测)

标注耗时
SettingsTrack4ms
VoiceAssist6ms
账号同步块5ms
VoiceSearch0ms
initHudConfig17ms
Link+MQTT+AudioControl19ms
TrackTrigger/UserSwitchCleaner(含合计)
AsyncThreadStartTask 总~61ms

3.3 Gantt 瀑布

gantt
    title SettingsApplication 冷启动耗时瀑布(示意,基于注释+实测)
    dateFormat X
    axisFormat %L ms

    section 主线程(实测247ms)
    前置依赖                 :0, 30
    配置字块CarProperty      :30, 61
    蓝牙initConnection       :61, 249
    热点WiFi                 :249, 271
    Router反射               :271, 275
    await等异步              :275, 276

    section ASYNC线程池(注释~61ms)
    SettingsTrack            :30, 34
    VoiceAssist              :34, 40
    账号同步                 :40, 45
    VoiceSearch              :45, 45
    initHudConfig            :45, 62
    Link+MQTT+AudioControl   :62, 81
    TrackTrigger/UserSwitch  :81, 91
    countDown                :91, 91

    section 二次派发盲区(onCreate后)
    initInAsync-License       :276, 360
    refreshModeList           :91, 200
    updateAvmCarProperties    :91, 200

主线程 ~276ms vs 异步 ~91ms:异步先完成,countDown 后主线程仍卡在蓝牙初始化。主线程是绝对瓶颈


四、CountDownLatch 约束模型

文件:AppStartTaskDispatcher.java

// :33 创建 latch(mNeedWaitCount=1,仅 AsyncThreadStartTask)
mCountDownLatch = new CountDownLatch(mNeedWaitCount.get());
// :75 await 阻塞,超时 1000ms
mCountDownLatch.await(mAllTaskWaitTimeOut, TimeUnit.MILLISECONDS);
// :93 异步完成后 countDown
if (ifNeedWait(absStartTask)) mCountDownLatch.countDown();

约束范围:

受约束(在 execute 方法体内同步执行)不受约束(二次派发)
SettingsTrack.initMainThreadStartTask.initInAsync
VoiceAssistProvider.initializeSteeringModeViewModel.refreshModeList
账号同步 init/registerAvmSwitchSyncHelper.updateAvmCarProperties
initHudConfigVoiceSearchManager.loadCacheWidgets
Link+MQTT+AudioControlTrackTrigger(postOnBackgroundThread)
TrackTrigger.init 本体
UserSwitchCleanerManager.addListener
→ markAsyncThreadStartTaskFinish → countDown

五、风险点清单

#风险位置影响触发条件
R1🔴 主线程 CarProperty 同步注册MainThreadStartTask:66 / CarPropertyCacheManager:192主线程阻塞;Activity 阶段 44 个 callback 893ms 白屏冷启动/用户切换
R2🔴 蓝牙同步初始化 188msMainThreadStartTask.initConnection:196主线程阻塞LocalBluetoothManager 反射
R3🟡 CountDownLatch 超时 1000msAppStartTaskDispatcher:75异步卡死时主线程阻塞 1sAsyncTask 卡死/线程池饱和
R4🟡 二次派发盲区MainThreadStartTask:80 / AsyncThreadStartTask:116,147onCreate 返回后竞态,访问未就绪资源时序竞争
R5🟡 ASYNC 线程池无界ThreadPoolUtils:19高并发线程爆炸大量二次派发
R6🟡 run() 无异常捕获AbsStartTask:14-17execute 抛异常则 countDown 不执行,主线程阻塞至超时任务异常
R7🟢 MQTT/HUD 同步阻塞异步线程AsyncThreadStartTask:94,98异步线程响应变慢服务慢

六、优化建议(按性价比)

方案改动点收益风险优先级
A 治本CarPropertyCacheManager.registerPropertyCallback(:192) 扔单线程 executor;onChangeEvent 处 runOnUiThread 切回App 31ms→3ms,Activity 893ms→~30ms中(确认回调线程语义)🔴 高
B 消白屏CarPropertyMgrPreferenceController.onPostCreateInternal(:521) 的 setCarManagerCallback 改 DecorView.post{}Displayed 1675ms→~500ms低(首帧用 Application cache 兜底)🔴 高
C 主线程减负VehiclePermanentListener.init / 蓝牙 getLocalBtManager(188ms) / HotspotUtils(22ms) 挪进 initInAsync 或 AsyncTask主线程省 ~240ms低-中(回归蓝牙配对/车控可见性)🔴 高
D 降低 latch 超时WAIT_TIME 1000ms → 300ms异常时少阻塞中(需验证异步最长耗时)🟡 中
E 收编二次派发initInAsync 等纳入 latch 约束消除竞态🟡 中
F 限制线程池ASYNC 核心 2-4 + 有界队列防线程爆炸🟡 中
G run() 加 try-finallyAbsStartTask:14 异常仍 countDown防超时阻塞🟡 中
H 代码卫生BroadcastSourceInfoHandler 反射 CNFE;修日志保真代码卫生🟢 低

推荐落地:A + B + C 三刀,主线程阻塞从 ~1.2s 压到 <100ms,Displayed 从 1675ms 降到 ~400-500ms。

⚠️ 方案 A 注意:registerCallback 走子线程后,onChangeEvent 落在 CarService binder 接收线程,业务 callback 若假设主线程,需在 dispatch 处统一 runOnUiThread。 ⚠️ 方案 C 注意:initConnection 注释称「必须主线程,否则黑屏」(蓝牙配对异常),挪异步前需与蓝牙模块确认回归。


七、与「启动慢白皮书」的关联

白皮书发现本全景对应
Application.onCreate 主线程阻塞 247msMainThreadStartTask 实测(注释 71ms)
68 个 CarProperty 注册(Application 阶段)31msVehiclePermanentListener.init:66
44 个 CarProperty 批量注册(Activity 阶段)893msCarPropertyCacheManager:192(非启动期,但同根因)
蓝牙 getLocalBtManager 188msMainThreadStartTask.initConnection:196
历史 09:06 ANR 50s 卡死同「主线程/worker 同步 car binder」模式,ThreadPoolUtils 线程
病根一行 CarPropertyCacheManager:192方案 A 改点
方案 C 改点 MainThreadStartTask:62,66本全景 R1/R2

本全景的增量价值:白皮书聚焦 Activity 阶段白屏(893ms),本全景补充了 Application 阶段的完整框架机制、线程模型、二次派发盲区、latch 约束边界 —— 二者互补。


八、关键源码行号索引

文件行号说明
SettingsApplication.java47-67onCreate 完整流程
62-65dispatcher 构造与启动
AppStartTaskDispatcher.java13WAIT_TIME=1000
29-36start()
33 / 75 / 93latch 创建/await/countDown
AbsStartTask.java14-17run()(无 try-catch)
ThreadPoolUtils.java19-22ASYNC 无界线程池
MainThreadStartTask.java48类注释「71MS」
56-77execute()
61-68配置字块(52ms,含 CarProperty 注册)
72initConnection(蓝牙 188ms)
80-114initInAsync(二次派发盲区)
193-212initConnection 实现
AsyncThreadStartTask.java64类注释「61MS」
74-108execute()
116, 147二次派发 ASYNC.execute
VehiclePermanentListener.java102-107 / 111init / registerPropertyCallback
CarPropertyCacheManager.java192🔴 病根:主线程同步 registerCallback

九、总结

  • 时序:进程 fork → attachBaseContext → onCreate 前置 → dispatcher.start() → 并行(MainThreadStartTask 主线程 + AsyncThreadStartTask 异步)→ await → onCreate finish
  • 线程模型:主线程 + ASYNC(latch 约束)+ 二次派发盲区(不受约束)
  • 瓶颈:主线程 initConnection(蓝牙 188ms)+ CarProperty 注册;注释严重低估耗时(71ms vs 实测 247ms)
  • 优化:A(CarProperty 异步化,治本)+ B(post 延迟首帧)+ C(蓝牙/热点挪异步)