1. 创建自定义CarService模块

任务说明

在Android Automotive系统中,CarService是车辆相关功能的核心服务。本案例将实现一个自定义模块:继承CarServiceBase,通过注解注册到CarService中,使其能被系统通过Car管理器正常调用。最终通过编译产物和运行时服务注册日志验证模块已生效。

实现步骤

整个实现分为三个部分:定义AIDL接口、实现继承CarServiceBase的服务类、在CarService中注册该服务。以下代码基于Android 13 (API 33) Automotive源码结构。

1. 定义AIDL接口

创建文件:packages/services/Car/car-lib/src/android/car/ICustomCarService.aidl

package android.car;

interface ICustomCarService {
    String getCustomInfo();
    void setCustomInfo(String info);
}

2. 实现自定义CarService模块

创建文件:packages/services/Car/service/src/com/android/car/custom/CustomCarService.java

package com.android.car.custom;

import android.car.ICustomCarService;
import android.car.CarLibLog;
import android.car.systeminterface.SystemInterface;
import android.util.Log;
import com.android.car.CarServiceBase;
import com.android.car.CarServiceImpl;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;

/**
 * 自定义CarService模块示例
 * 演示如何继承CarServiceBase并注册到CarService中
 */
public class CustomCarService extends CarServiceBase implements ICustomCarService.Stub {
    private static final String TAG = "CustomCarService";
    private final CarServiceImpl mCarServiceImpl;

    @GuardedBy("this")
    private String mCustomInfo = "default_info";

    public CustomCarService(CarServiceImpl carServiceImpl) {
        mCarServiceImpl = carServiceImpl;
    }

    @Override
    public void init() {
        Log.i(TAG, "CustomCarService init");
        // 初始化逻辑,例如读取持久化配置
    }

    @Override
    public void release() {
        Log.i(TAG, "CustomCarService release");
        // 释放资源
    }

    @Override
    public String getCustomInfo() {
        synchronized (this) {
            return mCustomInfo;
        }
    }

    @Override
    public void setCustomInfo(String info) {
        Preconditions.checkStringNotEmpty(info, "info cannot be empty");
        synchronized (this) {
            mCustomInfo = info;
            Log.i(TAG, "setCustomInfo: " + info);
        }
    }
}

3. 注册到CarService

编辑文件:packages/services/Car/service/src/com/android/car/CarServiceImpl.java

在ICarImpl构造函数中注册服务,关键修改如下:

// 在文件顶部import区域添加
import com.android.car.custom.CustomCarService;

// 在ICarImpl类中添加成员变量
private final CustomCarService mCustomCarService;

// 在ICarImpl构造函数中,在现有服务初始化之后添加
mCustomCarService = new CustomCarService(CarServiceImpl.this);
mCustomCarService.init();
registerService(Car.CUSTOM_SERVICE, mCustomCarService);

同时需要在Car.java中定义服务名称常量,编辑packages/services/Car/car-lib/src/android/car/Car.java:

// 在Car类中,与其他SERVICE常量一起添加
public static final String CUSTOM_SERVICE = "custom_car_service";

4. 编译与验证

在Android源码根目录执行以下命令:

source build/envsetup.sh
lunch <your_automotive_target>
m -j32 car-lib car-service

编译成功后,将生成的system.img刷入设备或模拟器。启动后通过adb shell验证:

adb shell dumpsys car_service | grep -A 5 "CustomCarService"

预期输出应包含类似以下内容(示例输出,非实测结果):

CustomCarService:
    init called
    mCustomInfo: default_info

同时可通过以下命令验证服务可被正常调用:

adb shell cmd car_service call custom_car_service getCustomInfo

若返回default_info,说明服务已成功注册并响应调用。

验证判定标准

  • 编译无错误,car-service包成功生成
  • 设备启动后无异常崩溃日志
  • dumpsys car_service输出中包含CustomCarService且状态为已注册
  • 通过binder调用getCustomInfo能返回预期值

常见问题

  • 服务未注册:检查registerService调用是否在init()之后执行,且服务名称与Car.java中定义一致
  • 权限异常:确保调用方具有android.car.permission.CAR_SERVICE权限
  • 编译失败:确认AIDL文件已添加到car-lib的Android.bp或Android.mk的srcs列表中