02 - 主线程链路与前置依赖

维度 B:研究 SettingsApplication主线程上发生的所有初始化、前置依赖、MainThreadStartTask 全貌 关注点:attachBaseContextonCreate 链路、前置依赖组件、主线程任务、Intent 拦截、缓存机制、路由注解


一、主线程初始化清单(按执行顺序)

1.1 attachBaseContext 阶段

文件:app/src/main/java/com/android/car/settings/miauto/SettingsApplication.java:41-44

步骤操作说明
1.1super.attachBaseContext(base)调用 BaseApplication,父类初始化
1.2mApp = this保存 Application 全局引用,供 BaseApplication.getGlobalApp() 访问

1.2 BaseApplication.onCreate(base/.../common/BaseApplication.java:44-62)

步骤操作说明
2.1super.onCreate()Application 基类
2.2initOthers()initGlobalViewModel()通过 ViewModelProvider.AndroidViewModelFactory 创建 GlobalViewModel 单例,供跨页面数据共享

1.3 SettingsApplication.onCreate 前置依赖(SettingsApplication.java:47-60)

注释标注「MainThreadStartTask 和 AsyncThreadStartTask 都依赖的(前置条件)」

步骤操作文件:行号职责
3.1DfxManager.INSTANCE.init:49小米汽车 DFX(数据框架/体验)SDK 初始化
3.2MiCarSettingsExtKt.checkAppMatchRom:51ROM 匹配检查,见下方详解
3.3registerActivityLifecycleCallbacks(AppLifecycleTracker):53Activity 生命周期监听(logUIMode 排障)
3.4AutoDensityConfig.init(this):55自动密度适配(mi.car.autodensity)
3.5initLogging()MLog.init:56,:119-128日志系统初始化

1.4 AppStartTaskDispatcher.start()(SettingsApplication.java:62-65)

AppStartTaskDispatcher appStartTaskDispatcher = new AppStartTaskDispatcher();
appStartTaskDispatcher.setMainAppStartTask(new MainThreadStartTask(appStartTaskDispatcher, this));
appStartTaskDispatcher.setAsyncStartTask(new AsyncThreadStartTask(appStartTaskDispatcher, this));
appStartTaskDispatcher.start();  // 阻塞,直到 AsyncThreadStartTask 完成(最多 1000ms)

详见 01-启动框架与调度机制


二、前置依赖组件详解

2.1 checkAppMatchRom —— ROM 匹配检查

文件:base/settingsBaseUi/src/main/java/com/android/car/settings/common/MiCarSettingsExt.kt:81-86

fun checkAppMatchRom(stage: String? = null): Boolean {
    val isDcdApp: Boolean = BuildConfig.FLAVOR.contains("dcd")
    val isDcdRom = DeviceUtil.isDCDPlatform()
    MLog.d("check rom match at stage: $stage, isDcdApp = $isDcdApp, isDcdRom = $isDcdRom")
    return isDcdRom && isDcdApp || !isDcdRom && !isDcdApp
}

职责:确保 App 变体(DCD/XCD/global)与 ROM 平台匹配。DCD ROM 必须装 DCD App,否则功能异常。用于启动期快速发现装错包的问题。

2.2 AppLifecycleTracker —— UI 模式排障

文件:SettingsApplication.java:69-116

onActivityPreCreated 在 Activity 创建前后各打印一次 UI 模式:

MiCarSettings.logUIMode(TAG, " onActivityPreCreated before super", activity);
ActivityLifecycleCallbacks.super.onActivityPreCreated(activity, savedInstanceState);
MiCarSettings.logUIMode(TAG, " onActivityPreCreated after super", activity);

用途:出现 UI 模式(深色/浅色)与实际不符时,根据日志判定是系统问题还是应用问题。其他回调均为空实现。

2.3 initLogging —— MLog 配置

文件:SettingsApplication.java:119-128

LogConfiguration configuration = new LogConfiguration.Builder()
    .logLevel(LogLevel.DEBUG)
    .tag(SettingsConstant.TAG)
    .tab("    ")
    .tagFormat(LogConfiguration.TAG_FORMAT_APPEND)  // 一次性 tag 拼接
    .enableInnerLog(false)
    .withChannels(LogChannel.Android)
    .build();
MLog.init(configuration);

三、MainThreadStartTask.execute() 全貌(逐行核对)

文件:app/src/main/java/com/android/car/settings/miauto/MainThreadStartTask.java

类注释(:48):「主线程执行 dev分支耗时 71MS」 —— 这是开发者标注值;bugreport 实测 247ms(见 05)。

@Override
protected void execute() {                                   // :56
    mApplication.registerActivityLifecycleCallbacks(        // :57 注册 Intent 拦截回调
            new ActivityLifecycleCallbacks());
 
    /* 获取、监听车型配置字信息  耗时52Ms */               // :58-60 整块注释标 52ms
    {
        GlobalCarPropertyManager.init(mApplication);        // :62 全局 CarProperty 管理器
        LicenseControlMgr.getInstance()                     // :64-65 扩展 license 能力
                .setLicenseControl(MiCarLcsControlHelper.INSTANCE);
        VehiclePermanentListener.getInstance().init();      // :66 车辆属性监听器(注册~68个 propId)
        MiCarSettings.setConfigManager(CarConfigManager.INSTANCE); // :67 设置配置管理器
    }
 
    PreferenceVisibleStatusHelperWrapper.getInstance()      // :69-70 可见性管理器
            .setPreferenceVisibleStatusHandler(getHandler());
 
    initConnection();   // 必须在主线程执行,否则黑屏 27MS     // :72 蓝牙/热点/WiFi
    Router.getInstance().init(mApplication); // 0MS,有反射    // :74 路由表合并
    initInAsync();                                          // :76 二次派发(不受 latch 约束)
}

⚠️ 纠正常见误读:注释里的 52ms整个配置字块(:61-68 四行合计),不是 VehiclePermanentListener 单独。实测该块内 CarProperty 注册约 31ms(白皮书)。

3.1 Intent 拦截 ActivityLifecycleCallbacks(易被忽略的业务)

文件:MainThreadStartTask.java:126-188

这是 MainThreadStartTask 自己注册的 ActivityLifecycleCallbacks(与 SettingsApplication.AppLifecycleTracker 不同),在 onActivityCreated 中拦截 Intent 跳转:

public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    Intent intent = activity.getIntent();
    String newIntent = shouldInterceptAndNewIntent(action, data);  // 判断是否拦截
    if (newIntent != null) {
        activity.finish();
        activity.startActivity(new Intent(newIntent));   // 重定向到新 Intent
    }
}

拦截规则(shouldInterceptAndNewIntent,:162-187):

触发条件配置判定重定向目标
POSITION_ADJUST_ACTION + 后视镜调节 + 单后视镜车型!isSteeringAdjustEnabled && !isCfgWHudEnabled && !isCfgPHudEnabledMIRROR_ADJUST_ACTION
POSITION_ADJUST_ACTION + HUD 调节 + WHUD 使能 + WHUD 关闭isCfgWHudEnabled && !isHudSwitchEnable()HUD_SETTINGS_ACTION

作用:根据车型配置字(单/双后视镜、HUD 是否使能),把不适用的「位置调节」Intent 重定向到正确的子页面,避免进了空白页。

3.2 配置字块详解(:61-68)

组件文件职责
GlobalCarPropertyManagerbase/settingsVehicleLib/.../GlobalCarPropertyManager.kt:23-30全局单例管理 CarPropertyManager,SoftReference 持有,触发 VehicleControlManager 初始化
LicenseControlMgr.setLicenseControlcom.android.license.master扩展 license 查询能力,供其他 module 判断功能可见性
VehiclePermanentListener.initbase/settingsVehicleLib/.../VehiclePermanentListener.java:102-107配置信号映射 + 注册 ~68 个 CarProperty callback,为 Preference 可见性提供缓存,避免闪烁
MiCarSettings.setConfigManager-设置 CarConfigManager 单例

VehiclePermanentListener 缓存机制(:325-343):

public static CarPropertyValue getCachePropertyValue(int propertyId, int areaId) {
    CarPropertyValue v = mPropertyValueMap.get(getCachedPropertyKey(propertyId, areaId));  // 1.优先缓存
    if (v == null && getInstance().mCarPropertyManager.isConnected()) {
        v = getInstance().mCarPropertyManager.getProperty(propertyId, areaId);            // 2.缓存未命中查 CarService
    }
    return v;
}

此方法对接 SettingsApplication.getPropertyValue(:135),是 Application 级车辆属性缓存入口。

CarConfigManager CCP 缓存策略(base/settingsVehicleLib/.../CarConfigManager.kt:78-104):

  • CCP 静态配置字(出厂烧录,生命周期不变):默认走缓存
  • 动态运行时属性:必须 skipCache=true 跳过缓存

3.3 initConnection —— 蓝牙/热点/WiFi(:193-212)

private void initConnection() {
    // 与蓝牙模块同事确认,需要在进程初始化时就初始化 BtManager,否则会导致配对异常
    try { MiBluetoothUtils.getLocalBtManager(); }          // 蓝牙,实测 188ms!
    catch (Exception e) { MLog.e(e, "fail to init bt manager"); }
    try { HotspotUtils.INSTANCE.init(mApplication); }      // 热点,实测 22ms
    catch (Exception e) { MLog.e(e, "fail to init hotspot"); }
    try { MiCarWifiUtils.INSTANCE.init(mApplication); }    // WiFi
    catch (Exception e) { MLog.e(e, "fail to init wifi"); }
}

注释标 27ms,但实测蓝牙单项 188ms(LocalBluetoothManager 同步初始化含反射 CNFE,白皮书 72309-73148)。这是主线程最大热点。

观点冲突:注释称「必须主线程,否则黑屏」,但白皮书优化方案 C 建议挪到异步以省 ~210ms —— 需回归验证蓝牙配对稳定性。

3.4 initInAsync —— 二次派发盲区(:80-114)

不受 CountDownLatch 约束,onCreate 返回后仍在 ASYNC 线程池执行:

ThreadPoolUtils.ASYNC.execute(() -> {
    LicenseMasterManager.INSTANCE.addLicenseDataChangedListener(...);  // :89-95 license 变化监听
    LicenseMasterManager.INSTANCE.bindLicenseMaster(mApplication);     // :97 绑定 license 服务
    MisDeviceSDKUtils.INSTANCE.init();                                 // :99 MIS 设备 SDK
    // 网络共享状态检查/初始化                                          // :101-108
    ChildSeatSignalSync.INSTANCE.sync();                               // :111 儿童座椅状态同步到 ECU
});

其中 license 监听块(:84-96)有 AI(claude)生成标记(2026-05-14),先注册 listener 再 bind,避免首次 fetch 时 listener 未就绪。

3.5 Router.init —— 路由表合并(:74)

文件:settingsCommon/plugin/router/routerManager/.../Router.java:46-74

构造时反射调用编译期生成的 RouterHelper.merge() 合并路由表:

private Router() {
    try {
        Class clazz = Class.forName("com.android.car.settings.router.RouterHelper");
        Method method = clazz.getDeclaredMethod("merge");
        method.setAccessible(true);
        method.invoke(clazz);   // 合并路由表
    } catch (Exception e) { Log.i("Router", "merge router failed"); }
}
public void init(Application application) {
    initActivityLifecycle(application);   // 注册 Activity/Fragment 生命周期,分发 URI
}

@Module / @Modules 注解机制(SettingsApplication.java:28-35):

  • @Module(SettingsConstant.TAG) —— 标记模块名,同模块只注册一次
  • @Modules({TAG, TAG_AUTOPILOT, TAG_Light, ...}) —— 列举所有含 RouterProvider 的子模块
  • 编译期:注解处理器扫描 @Modules,生成 RouterHelper(含 merge() 方法)
  • 启动期:Router 反射调用 merge() 合并所有子模块路由表

四、主线程流程图

flowchart TD
    A["attachBaseContext"] --> B["super.attachBaseContext<br/>mApp=this"]
    B --> C["onCreate"]
    C --> D["BaseApplication.onCreate<br/>initGlobalViewModel"]
    D --> E["DfxManager.init"]
    E --> F["checkAppMatchRom<br/>(DCD/XCD 匹配)"]
    F --> G["AppLifecycleTracker 注册<br/>(logUIMode 排障)"]
    G --> H["AutoDensityConfig.init"]
    H --> I["initLogging MLog"]
    I --> J["dispatcher.start()"]
    J --> K["dispatchAppStartTask"]
    K --> L["MainThreadStartTask.execute(主线程)"]
    K -.->|"并行<br/>投递ASYNC"| M["AsyncThreadStartTask<br/>见 03"]

    L --> L1["registerActivityLifecycleCallbacks<br/>(Intent拦截:后视镜/HUD)"]
    L1 --> L2["配置字块 52ms★<br/>GlobalCarPropertyManager<br/>LicenseControlMgr<br/>VehiclePermanentListener.init<br/>setConfigManager"]
    L2 --> L3["PreferenceVisibleStatusHelperWrapper"]
    L3 --> L4["initConnection 27ms★<br/>蓝牙188ms/热点22ms/WiFi"]
    L4 --> L5["Router.init<br/>(反射 merge 路由表)"]
    L5 --> L6["initInAsync<br/>→ASYNC二次派发(不受latch)"]
    L6 --> N["await<br/>等异步完成(最多1000ms)"]
    M --> N
    N --> O["onCreate finish"]

    classDef hot fill:#ffe1e1,stroke:#cc0000
    class L2,L4 hot

五、主线程性能风险

风险位置实测耗时说明
🔴 蓝牙同步初始化initConnection:196188msLocalBluetoothManager 反射初始化,主线程最大热点
🔴 CarProperty 同步注册VehiclePermanentListener.init:66~31ms(Application)同步 binder,Activity 阶段更严重(893ms)
🟡 配置字块:61-6852ms(注释)首次连接 CarService 的 IPC 开销
🟡 Router 反射:740ms(注释)反射 RouterHelper.merge,有隐藏开销
🟡 反射 CNFE 噪声BroadcastSourceInfoHandler4ms+/次settingslib 裁剪遗留,每次启动抛 CNFE

优化方向(详见 05):

  • 蓝牙/热点挪异步(白皮书方案 C)
  • CarProperty 注册挪单线程 executor(白皮书方案 A,治本)

六、关键源码行号索引

组件文件:行号
SettingsApplication.onCreateSettingsApplication.java:47-67
前置依赖段SettingsApplication.java:49-56
AppLifecycleTrackerSettingsApplication.java:69-116
getPropertyValue(缓存入口)SettingsApplication.java:135-137
initLoggingSettingsApplication.java:119-128
BaseApplication.onCreateBaseApplication.java:44-62
MainThreadStartTask.executeMainThreadStartTask.java:56-77
Intent 拦截回调MainThreadStartTask.java:126-188
配置字块(52ms)MainThreadStartTask.java:61-68
initConnection(蓝牙/热点/WiFi)MainThreadStartTask.java:193-212
initInAsync(二次派发)MainThreadStartTask.java:80-114
VehiclePermanentListener 缓存VehiclePermanentListener.java:325-343
CarConfigManager CCP 缓存CarConfigManager.kt:78-104
Router.merge(反射)Router.java:46-62
checkAppMatchRomMiCarSettingsExt.kt:81-86
MiBluetoothUtilssettingsPage/micarConnectionSettings/.../bluetooth/MiBluetoothUtils.kt
HotspotUtilssettingsPage/micarConnectionSettings/.../hotspot/HotspotUtils.kt
MiCarWifiUtilssettingsPage/micarConnectionSettings/.../wifi/MiCarWifiUtils.kt