AAOS 整体架构分析 —— 基于 Android 14

AAOS 整体架构分析 —— 基于 Android 14

说起来 AAOS(Android Automotive OS)跟咱们手机上用的 AOSP 虽然同根同源,但真要是做车载开发的,深入进去就会发现差别还是挺大的。车载场景下对稳定性、安全、多屏交互的要求跟手机完全不是一个量级。这篇文章就从 Android 14 的代码出发,把 AAOS 的整体架构掰开揉碎了聊一聊。

AAOS 和 AOSP 到底差在哪

先搞清楚一个基本问题:AAOS 本质上还是 Android,但它加了大量车载专属的 Service 和 HAL。

两者内核几乎一样,都是 Linux 内核 + Android 特有的一些驱动和机制(Binder、ashmem、ion 等)。真正的差别在上层:AAOS 多了一套车载专用的硬件抽象层(Vehicle HAL)、一套车载服务(CarService)、一堆车载应用(CarLauncher、CarSettings 等),以及一个完全不同的电源管理模型。

                     AOSP                              AAOS
        ┌──────────────────────┐       ┌──────────────────────────┐
        │  Launcher / Dialer   │       │  CarLauncher / CarUI     │
        │   (普通 Android App)  │       │   (车载定制 App)          │
        ├──────────────────────┤       ├──────────────────────────┤
        │   System Server      │       │   System Server          │
        │   (AMS/PMS/WMS...)   │       │   (AMS/PMS/WMS...)       │
        ├──────────────────────┤       ├──────────────────────────┤
        │                      │       │   CarService             │
        │                      │       │   (车载业务中枢)          │
        ├──────────────────────┤       ├──────────────────────────┤
        │   AudioFlinger       │       │   CarAudioService        │
        │   SurfaceFlinger     │       │   + 多Display扩展        │
        ├──────────────────────┤       ├──────────────────────────┤
        │   HAL (Camera/Audio) │       │   VHAL + 标准HAL         │
        ├──────────────────────┤       ├──────────────────────────┤
        │   Linux Kernel       │       │   Linux Kernel           │
        │   + Android 驱动      │       │   + 车载CAN驱动          │
        └──────────────────────┘       └──────────────────────────┘

AOSP 里的 system_server 管理着 ActivityManager、PackageManager 这些熟悉的 Service。而 AAOS 在 system_server 旁边又跑了一个独立的 CarService 进程,它是整个车载功能的中枢。两个进程通过 Binder 通信,CarService 会向 system_server 注册一些回调,但彼此是独立的。

从进程角度看一下启动流程:

init → Zygote → SystemServer (java)
                  ├─ ActivityManagerService
                  ├─ WindowManagerService
                  ├─ PackageManagerService
                  └─ ... 其他 AOSP Service
                  └─ CarServiceHelperService (轻量级桥接)
                         └─ bind → CarService (独立的 com.android.car 进程)
                                   ├─ VehicleHal
                                   ├─ CarPropertyService
                                   ├─ CarAudioService
                                   ├─ CarPowerManagementService
                                   ├─ CarUserService
                                   └─ ... 15+ 个子 Service

CarService 是怎么工作的

CarService 是一个 bound service,运行在 com.android.car 这个进程里。它的启动时机比普通应用早,但又在 system_server 之后。核心逻辑在 CarService.javaonStart() 方法里:

// packages/services/Car/service/src/com/android/car/CarService.java
public class CarService extends Service {
    private static final String TAG = "CarService";
    private final List<CarServiceBase> mServices = new ArrayList<>();
    private VehicleHal mVehicleHal;

    @Override
    public void onCreate() {
        super.onCreate();
        mVehicleHal = new VehicleHal(this);
        mServices.add(mVehicleHal);
        mServices.add(new CarPropertyService(mVehicleHal));
        mServices.add(new CarAudioService(this, mVehicleHal));
        mServices.add(new CarInfoService(this, mVehicleHal));
        mServices.add(new CarPowerManagementService(this, mVehicleHal));
        mServices.add(new CarUserService(this));
        mServices.add(new CarBluetoothService(this));
        mServices.add(new CarInputService(this));
        mServices.add(new CarPackageManagerService(this));
        mServices.add(new CarDiagnosticService(this, mVehicleHal));
        mServices.add(new CarDrivingStateService(this));
        mServices.add(new CarProjectionService(this));
        mServices.add(new CarMediaService(this));
        mServices.add(new CarNavigationService(this));
        mServices.add(new CarOccupantZoneService(this));
        mServices.add(new CarStorageMonitoringService(this));
        mServices.add(new CarTrustedDeviceService(this));
        mServices.add(new CarWatchdogService(this));
        // 按顺序初始化
        for (CarServiceBase service : mServices) {
            service.init();
        }
    }
}

这里有个细节:CarServiceBase 接口定义了 init()release() 两个方法,初始化的顺序是按照 mServices 列表的顺序来的。VehicleHal 必须是第一个,因为后面的 Service 几乎都依赖它。

CAV (Car API) 暴露给上层应用的方式是通过 Car 这个 Binder 客户端。应用通过 Car.createCar() 拿到 Car 实例,再通过 getCarManager() 获取具体的管理器:

// 应用侧使用示例
Car car = Car.createCar(context);
if (car != null && car.isConnected()) {
    CarAudioManager audioManager = (CarAudioManager) car.getCarManager(Car.AUDIO_SERVICE);
    CarInfoManager infoManager = (CarInfoManager) car.getCarManager(Car.INFO_SERVICE);
    CarPropertyManager propManager = (CarPropertyManager) car.getCarManager(Car.PROPERTY_SERVICE);
    // ...
}

这套接口跟 Android 原生的 Context.getSystemService() 很像,但走的完全是另一套 Binder 通道——应用在 com.android.car 进程这边,而 AOSP 的 Service 跑在 system_server 里。两者独立,但也有些桥接逻辑做了同步。

Vehicle HAL —— 连接 Android 和车的关键

VHAL(Vehicle HAL)是整个 AAOS 中最关键的一层。它抽象了车辆的所有属性(车速、车门状态、空调温度、续航里程等),每个属性用 VehicleProperty 来唯一标识。

HIDL 到 AIDL 的迁移

Android 14 的一个大变化是把 VHAL 从 HIDL 迁移到了 AIDL。之前 AAOS 从 Android 8 开始一直用 HIDL 定义车载属性接口,14 终于统一用 AIDL 了。这个迁移对上层影响不大,接口语义没变,但底层的 Binder 通信方式变了——HIDL 走的是 hwbinder,AIDL 走的是标准 binder。好处是以后 VHAL 的 debug 可以用标准的 Binder 工具(dumpsys、`binder’)来跟踪,不再需要单独的 hwservicemanager 那一套。

迁移前后对比一下:

Android 13 及之前:                 Android 14:
                                    
IVehicle.hal                       IVehicle.aidl
  (hwbinder + hwservicemanager)      (标准 binder)
                                    
VehicleHal.java                     VehicleHal.java
  ├─ connect HIDL service            ├─ connect AIDL service
  ├─ getAllPropConfigs()             ├─ getAllPropConfigs()
  ├─ get(...)                        ├─ get(...)
  └─ set(...)                        └─ set(...)

VHAL 的核心接口

VHAL 的核心接口定义在 hardware/interfaces/automotive/vehicle/aidl/ 下:

// hardware/interfaces/automotive/vehicle/aidl/IVehicle.aidl
package android.hardware.automotive.vehicle;

interface IVehicle {
    /**
     * 获取所有支持的车载属性配置
     */
    VehiclePropConfig[] getAllPropConfigs();

    /**
     * 读取某个属性的值
     * @param prop 属性 ID
     * @param areaId 区域 ID(比如左前车门、右前车门)
     */
    VehiclePropValue get(VehiclePropStatus status, int prop, int areaId);

    /**
     * 设置某个属性的值
     * @param value 要设置的值
     * @return VehiclePropStatus 操作结果
     */
    @nullable VehiclePropStatus set(VehiclePropValue value);

    /**
     * 订阅属性变化
     * @param listener 回调接口
     * @param subscriptions 订阅列表(属性 ID + 采样率)
     * @param maximumNumberOfValues 每次回调最多带多少个值
     */
    void subscribe(IVehicleCallback listener, SubscribeOptions[] subscriptions,
                   float maximumNumberOfValues);

    /**
     * 取消订阅
     */
    void unsubscribe(IVehicleCallback listener, int[] propIds);
}

再看看 VehiclePropConfig 的结构:

// hardware/interfaces/automotive/vehicle/aidl/VehiclePropConfig.aidl
package android.hardware.automotive.vehicle;

parcelable VehiclePropConfig {
    int prop;                    // 属性 ID,比如 VEHICLE_SPEED = 0x11200200
    int access;                  // 访问模式:读(0x01) / 写(0x02) / 读写(0x03)
    int changeMode;              // 变化通知模式
    int[] areaConfigs;           // 区域配置(支持多个 instance 的属性)
    int[] configArray;           // 厂商自定义配置
    String minSampleRate;        // 最小采样率
    String maxSampleRate;        // 最大采样率
}

数据流的完整链路

一次典型的属性读取流程:

CarPropertyManager.getProperty(VEHICLE_SPEED, areaId)
    │
    ▼
CarPropertyService (com.android.car 进程内)
    │  Binder AIDL 调用
    ▼
VehicleHal.java (CarService 内的封装层)
    │  Socket / 共享内存 / Vendor RPC
    ▼
VHAL 实现 (OEM 提供,C++ 进程)
    │
    ▼
CAN/Ethernet Driver → ECU → 车辆传感器

反过来属性变化通知的链路:

车辆传感器 → ECU → CAN Bus
    │
    ▼
VHAL 实现 (C++ native 进程)
    │  调用 IVehicleCallback.onPropertyEvent()
    ▼
VehicleHal.java
    │  通过 CarService 内部回调
    ▼
CarPropertyService
    │  调用 callback 或 broadcast
    ▼
应用层 onPropertyChangedListener

Android 14 对这条链路的优化是在 VHAL 到 CarService 之间加了一层缓冲——VehicleHal 会维护一个变化缓存队列,批量上报属性变化,减少了 Binder 调用的次数。之前高频率的属性(比如车速,每秒可能变化几十次),每个变化都发一个回调会占满 Binder 线程池。

常见的 VehicleProperty

AAOS 预定义了一千多个 VehicleProperty,常用的有这些:

// hardware/interfaces/automotive/vehicle/aidl/VehicleProperty.aidl
const int VEHICLE_SPEED = 0x11200200;           // 车速
const int ENGINE_RPM = 0x11200300;              // 发动机转速
const int FUEL_LEVEL = 0x11400400;              // 油量/电量百分比
const int DOOR_POS = 0x11500500;                // 车门状态
const int HVAC_TEMPERATURE_SET = 0x15400600;    // 空调设定温度
const int HVAC_FAN_SPEED = 0x16400700;          // 空调风速
const int GEAR_SELECTION = 0x11800800;          // 档位
const int PARKING_BRAKE_ON = 0x11600900;        // 手刹状态
const int TIRE_PRESSURE = 0x11400A00;           // 胎压

属性 ID 的编码规则:

0xAA BB CC DD
AA = 区域类型(01=全局, 11=座位, 15=车门, 16=车窗)
BB = 属性大类(12=运动信息, 14=能源, 15=车身, 16=HVAC)
CC = 属性小类
DD = 序号

音频架构 —— 比手机复杂太多了

手机上的音频架构很简单:谁会发声,谁拿到 AudioFocus 就行。但车里完全不一样——导航声、电话声、音乐声、警告声,每个都有自己的优先级和区域策略。

一来车里可能同时有好几个人在听不同的内容,二来有些音频(比如倒车雷达告警)优先级极高,必须能打断所有其他音频。

             ┌─────────────────────────────────────┐
             │           AudioPolicyManager        │
             │   (AOSP 的音频策略引擎)               │
             └──────────┬──────────────────────────┘
                        │
             ┌──────────▼──────────────────────────┐
             │        CarAudioService              │
             │  ┌──────────┐  ┌──────────────────┐  │
             │  │ Zone 1   │  │    Zone 2        │  │
             │  │ 驾驶位    │  │   副驾           │  │
             │  │ MUSIC    │  │  MUSIC/VIDEO     │  │
             │  │ NAV      │  │                  │  │
             │  │ CALL     │  │                  │  │
             │  └──────────┘  └──────────────────┘  │
             └──────────┬──────────────────────────┘
                        │
             ┌──────────▼──────────────────────────┐
             │        AudioFlinger                 │
             │   (混音 + 输出路由)                  │
             └──────────┬──────────────────────────┘
                        │
            ┌───────────┼───────────────┐
            ▼           ▼               ▼
        bus_device_1  bus_device_2   bus_device_3
        (驾驶位扬声器)  (副驾耳机)    (后座扬声器)

CarAudioService

CarAudioService 负责管理音频策略,它比 AOSP 的 AudioService 多了车特有的概念:

Audio Zone——车里不同座位算不同的 zone,每个 zone 有自己的音频策略。Android 14 支持最多 8 个 zone。

Context——音频的上下文类型,定义在 CarAudioContext 里:

// packages/services/Car/car-lib/src/android/car/media/CarAudioContext.java
public static final int INVALID     = -1;
public static final int MUSIC       = 0;   // 媒体播放
public static final int NAVIGATION  = 1;   // 导航播报
public static final int VOICE_COMMAND = 2; // 语音助手
public static final int CALL        = 3;   // 电话
public static final int ALARM       = 4;   // 闹钟
public static final int NOTIFICATION = 5;  // 通知
public static final int SYSTEM_SOUND = 6;  // 系统音效
public static final int EMERGENCY   = 7;   // 紧急告警
public static final int SAFETY      = 8;   // 安全提示(安全带、车门未关)
public static final int VEHICLE_STATUS = 9; // 车辆状态音(转向灯)
public static final int ANNOUNCEMENT = 10; // 语音播报

每个 Context 有固定的优先级高低,EMERGENCY > SAFETY > CALL > NAVIGATION > MUSIC。CarAudioService 在处理 AudioFocus 时会先根据 Context 决定优先级,同 Context 内才走 AOSP 标准的那套 focus 逻辑。

Android 14 的 CarAudioService 改用了 AudioManager.setPreferredDeviceForZone 来控制每个 zone 的输出设备:

// packages/services/Car/service/src/com/android/car/audio/CarAudioService.java
private void setupZoneDevices() {
    AudioManager audioManager = getSystemService(AudioManager.class);
    for (CarAudioZone zone : mCarAudioZones) {
        for (CarAudioContext context : zone.getAllContexts()) {
            AudioDeviceInfo device = zone.getDeviceForContext(context);
            if (device != null) {
                audioManager.setPreferredDeviceForZone(
                    zone.getId(), device, context.getAudioAttributes()
                );
            }
        }
    }
}

音频配置

OEM 通过 car_audio_configuration.xml 来定义音频拓扑。Android 14 把这个文件的格式也重构了,跟 AOSP 的 audio_policy_configuration.xml 做了合并:

<!-- packages/services/Car/service/res/values/car_audio_configuration.xml -->
<carAudioConfiguration version="2">
    <zones>
        <!-- 驾驶位 Zone -->
        <zone name="driver" volumeGroupNumber="1" occupantZoneId="0">
            <deviceHolder busNumber="1" address="bus_device_1">
                <contexts>
                    <context context="MUSIC" />
                    <context context="NAVIGATION" />
                    <context context="CALL" />
                    <context context="SAFETY" />
                </contexts>
            </deviceHolder>
        </zone>

        <!-- 副驾 Zone -->
        <zone name="passenger" volumeGroupNumber="2" occupantZoneId="1">
            <deviceHolder busNumber="2" address="bus_device_2">
                <contexts>
                    <context context="MUSIC" />
                    <context context="VOICE_COMMAND" />
                </contexts>
            </deviceHolder>
        </zone>
    </zones>

    <!-- 音量分组,每组单独的音量曲线 -->
    <volumeGroups>
        <group name="driver_group">
            <context context="MUSIC" />
            <context context="NAVIGATION" />
            <context context="CALL" />
        </group>
        <group name="passenger_group">
            <context context="MUSIC" />
            <context context="VOICE_COMMAND" />
        </group>
    </volumeGroups>
</carAudioConfiguration>

volumeGroupNumber 控制哪些 Context 共用一个音量滑块。比如驾驶位的 MUSIC 和 NAVIGATION 可能是独立控制的,而副驾可能只用同一路音量。

多屏显示

AAOS 的多屏方案跟平板的扩展屏完全是两码事。车内每个屏幕可能承担完全不同的功能:仪表盘显示车速和警告,中控屏做导航和设置,副驾屏看视频,后座屏打游戏。

Android 14 的 AAOS 多屏主要依赖这几个机制:

Display Policy

device_generic/car/display_settings.xml 里配置每块屏的类型和分辨率:

<!-- device/generic/car/display_settings.xml -->
<displaySettings>
    <!-- 中控屏(主屏) -->
    <displaySetting port="0" type="MAIN">
        <config width="1920" height="720" density="160" />
        <config width="1280" height="720" density="120" />
    </displaySetting>

    <!-- 仪表盘 -->
    <displaySetting port="1" type="CLUSTER">
        <config width="1920" height="360" density="120" />
        <config width="1280" height="240" density="80" />
    </displaySetting>

    <!-- 副驾屏 -->
    <displaySetting port="2" type="AUXILIARY">
        <config width="1280" height="720" density="160" />
    </displaySetting>
</displaySettings>

CLUSTER 类型就是给仪表盘用的。系统会为它单独创建一个 Display 实例,不走普通的 Activity 启动流程。仪表盘上跑的是一个定制版的 SystemUI,只渲染车速、转速、故障灯这些必要信息,不加载第三方应用。

多屏 HAL

Android 14 用 AIDL 的 IComposer 来实现多屏能力:

// hardware/interfaces/graphics/composer/aidl/IComposer.aidl
interface IComposer {
    Display createDisplay(DisplayAttribute attr);
    boolean updateDisplay(Display display);
    void destroyDisplay(int64_t displayId);
    // ...
}

每块物理屏幕对应一个 Display Id(从 0 开始编号)。WindowManager 会在 onDisplayAdded 时创建对应的 DisplayContent,然后走标准的 WMS 窗口管理逻辑。

有一点容易踩坑:不同屏幕之间的触摸事件是独立的。AAOS 用 InputDevice 来区分触摸源,每块屏幕对应不同的 InputDevice。WMS 会根据触摸事件携带的 deviceId 和 displayId 把事件路由到对应的窗口。Android 14 在 InputDispatcher 里给这块加了 trace log,可以通过 adb shell dumpsys input 看到每个事件的完整路由路径。

屏幕拓扑示意:

  ┌─────────────────────────┐
  │  仪表盘 (CLUSTER)       │
  │  1920x360, density 120  │
  │  Display ID: 1          │
  │  Input Device: /dev/input/event1 │
  │  只运行 ClusterSystemUI │
  └─────────────────────────┘

  ┌─────────────────────────────────┐
  │  中控屏 (MAIN)                  │
  │  1920x720, density 160          │
  │  Display ID: 0                  │
  │  Input Device: /dev/input/event0│
  │  运行所有 App                    │
  └─────────────────────────────────┘

  ┌───────────────────┐
  │  副驾屏 (AUX)     │
  │  Display ID: 2    │
  │  运行多媒体应用    │
  └───────────────────┘

电源管理

车载电源状态跟手机完全不一样。手机只有关机、休眠、唤醒三种状态,车里要考虑的多了去了:

  • ACC ON:车通了电但没发动
  • Engine ON:发动机/电机启动了
  • ACC OFF:熄火了但系统还在跑(比如还在导航)
  • SHUTDOWN:彻底关机
  • SLEEP:深度休眠,但可以被唤醒(比如遥控开车门)

Android 14 的 CarPowerManagementService 重写了状态机:

// packages/services/Car/service/src/com/android/car/power/CarPowerManagementService.java
public enum CarPowerState {
    STATE_OFF(0, "OFF"),
    STATE_ON(1, "ON"),
    STATE_SHUTDOWN_ONLY(2, "SHUTDOWN_ONLY"),
    STATE_SUSPEND(3, "SUSPEND"),
    STATE_SLEEP(4, "SLEEP"),
    STATE_SHUTDOWN_PREPARE(5, "SHUTDOWN_PREPARE"),
}

// 状态转换的主逻辑
private void handlePowerStateChange(CarPowerState newState) {
    switch (newState) {
        case STATE_SHUTDOWN_PREPARE:
            // 1. 通知所有 Service 准备关闭
            notifyServices(CarPowerPolicy.SHUTDOWN_PREPARE);
            // 2. 等待异步关闭完成(有超时)
            waitForShutdownCompletion(SHUTDOWN_TIMEOUT_MS);
            // 3. 写日志
            writeShutdownLog();
            break;
        case STATE_SUSPEND:
            // 1. 保存 Display 状态
            // 2. 挂起 SurfaceFlinger
            // 3. 通知 VHAL 进入休眠
            suspendHardware();
            break;
        case STATE_SLEEP:
            // 低功耗模式,网络和大部分外设关闭
            // 只保持 CAN 总线唤醒能力
            enterSleepMode();
            break;
    }
}

Android 14 新增了 STATE_SHUTDOWN_ONLY 状态,用于 OTA 升级后的强制重启场景。这个状态下不会进入 SUSPEND 或 SLEEP,直接走完整关机流程。

安全与权限

AAOS 的安全模型在 AOSP 基础上加了不少车载专有的东西。

SELinux 策略

CarService 跑在独立的 car_service domain 里,策略文件在 system/sepolicy/prebuilts/api/34.0/private/car_service.te

type car_service, domain;
type car_service_exec, exec_type, vendor_file_type, file_type;

init_daemon_domain(car_service)

# 允许访问 VHAL
allow car_service vehicle_hal:fd use;
allow car_service vehicle_hal:binder { call transfer };

# 允许读写车载属性数据库
allow car_service car_data_file:dir create_dir_perms;
allow car_service car_data_file:file create_file_perms;

# 不允许访问网络(CarService 不需要直接联网)
neverallow car_service self:udp_socket *;
neverallow car_service self:tcp_socket *;

注意那个 neverallow——CarService 进程默认没有任何网络访问权限。如果 OEM 需要在 CarService 里加联网逻辑(比如远程控车),得单独申请权限审查。

Car 权限系统

AAOS 有自己的一套权限系统,定义在 packages/services/Car/car-lib/ 里:

// packages/services/Car/car-lib/src/android/car/permission/CarPermissionManager.java
public class CarPermissionManager {
    // 车载专用权限列表
    public static final String CONTROL_CAR_INFO =
            "android.car.permission.CAR_CONTROL_INFO";
    public static final String CONTROL_AUDIO_VOLUME =
            "android.car.permission.CAR_CONTROL_AUDIO_VOLUME";
    public static final String CONTROL_ENERGY =
            "android.car.permission.CAR_CONTROL_ENERGY";
    public static final String CONTROL_ENERGY_PORTS =
            "android.car.permission.CAR_CONTROL_ENERGY_PORTS";
    public static final String CONTROL_ENGINE =
            "android.car.permission.CAR_CONTROL_ENGINE";
    public static final String CONTROL_SPEED =
            "android.car.permission.CAR_CONTROL_SPEED";
    public static final String CONTROL_HVAC =
            "android.car.permission.CAR_CONTROL_HVAC";
    public static final String CONTROL_CLUSTER_DISPLAY =
            "android.car.permission.CAR_CONTROL_CLUSTER_DISPLAY";

    // 检查权限
    public boolean checkCarPermission(String permission) {
        return mContext.checkCallingPermission(permission)
                == PackageManager.PERMISSION_GRANTED;
    }
}

Android 14 把这些权限的检查点从 CarService 下沉到了 VHAL 层。以前是 CarService 的每个方法里手动 checkCallingPermission,现在 VHAL 的 set() 方法会检查调用方的权限,粒度更细了。

Android 14 的其他重要变化

除了上面重点聊的几个,Android 14 在 AAOS 方向上还有几个值得关注的改动:

数字钥匙框架

Android 14 开始支持数字车钥匙框架(Digital Car Key),用的是 UWB + BLE 来做近场通信和测距。这套框架在 packages/services/Car/car-key/ 下:

frameworks/base/car-key/
├── aidl/
│   └── android/car/key/
│       ├── ICarKey.aidl
│       └── ICarKeyCallback.aidl
├── src/
│   └── android/car/key/
│       ├── CarKeyManager.java
│       └── CarKeyService.java

需要说明的是,它只是个框架层抽象,具体加密协议和认证流程让 OEM 自己实现。Google 在参考实现里用的是 Android Ready SE 的安全元件,但 OEM 也可以用自己选的 eSE 芯片。

Projection API

Android 14 改进了 CarProjectionManager,投屏帧率更可控,丢帧检测也加了系统日志。这层是给 Android Auto 无线连接用的底层 API,App 层直接用不到,但做系统集成的会接触到。

多用户

Android 14 的 CarUserService 完善了多用户切换的体验。车是共享设备,不同驾驶员有不同的配置(座椅位置、空调偏好、导航历史)。Android 14 改进了用户切换时 App 的状态保存和恢复——之前很多 App 在切换用户后会崩溃(因为没处理好 onConfigurationChange),14 里加了更严格的兼容性检测。

总结

AAOS 本质上是在 AOSP 的基础上,为了车载场景做了一整套横跨应用、框架、HAL、内核的扩展:

层级AOSPAAOS 扩展
应用层Launcher, SettingsCarLauncher, CarSettings, ClusterUI
框架层SystemServer, WMS, AMSCarService (15+ 子 Service)
音频AudioFlinger, AudioPolicyCarAudioService, Zone, Context
显示SurfaceFlinger, WMS多 Display Policy, Cluster
硬件抽象HAL (Camera/Audio)VHAL (AIDL, 1000+ 属性)
权限Android PermissionsCar 专属权限 + SELinux 策略
电源PowerManagerCarPowerManagement (Sleep/Suspend/Off)

VHAL 是数据通路,CarService 是业务中枢,音频和多屏是最复杂的两个子系统。Android 14 的主要变化体现在 AIDL 迁移、电源状态机重构、权限模型下沉到 VHAL 这几个方向。

说实话车载 Android 开发的坑不少,很多问题只能靠实际调试和读源码才能解决。如果这篇文章能让入门的同学少走点弯路,那就值了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值