CarService工作流程

文章详细阐述了Android车载系统中应用层如何通过CarAPI获取并使用CarService的过程,涉及到AIDL接口、IBinder对象、CarManager类以及服务的绑定和管理。通过Car.createCar()方法创建Car对象,然后通过getCarManager()获取特定服务的Manager,进一步调用服务API进行交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

应用层需要拿到不同的CarService

CarService中各个服务本质上是AIDL接口的实现类,属于Server端,而对应的Client端就需要一个IBinder对象来访问Server端的方法,这些IBinder对象在Car API中被封装在一个个XXXManager类中。

Car API与CarService中的服务,名称上存在对应关系,所以很好理解。例如:CarWatchdogManager对应CarWatchdogServiceCarMediaManager对应CarMediaService

以获取CarinputService为例:

应用层:主要看createCar()和getCarManager()

mCar = Car.createCar(this, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_WAIT_FOREVER,
                (car, ready) -> {
                    mCar = car;
                    if (ready) {
                        mCarInputManager =
                                (CarInputManager) mCar.getCarManager(Car.CAR_INPUT_SERVICE);
                        //INPUT_TYPE_ALL_INPUTS : 对KeyEvent事件的监听 测试命令adb shell cmd car_service inject-key 3
                        //INPUT_TYPE_CUSTOM_INPUT_EVENT : 对CustomInputEvent事件的监听 测试命令adb shell cmd car_service inject-custom-input -d 0 f10
                        //INPUT_TYPE_ROTARY_NAVIGATION : 对旋转事件的监听,测试命令adb shell cmd car_service inject-rotary
                        //不添加相应参数,则不对相应事件做监听,收不到相应事件的回调
                        mCarInputManager.requestInputEventCapture(
                                CarOccupantZoneManager.DISPLAY_TYPE_MAIN,
                                new int[]{CarInputManager.INPUT_TYPE_ALL_INPUTS,
                                        CarInputManager.INPUT_TYPE_CUSTOM_INPUT_EVENT,
                                        CarInputManager.INPUT_TYPE_ROTARY_NAVIGATION},
                                CarInputManager.CAPTURE_REQ_FLAGS_ALLOW_DELAYED_GRANT,
                                /* callback= */ this);
                        mEventHandler = new CustomInputEventListener(getApplicationContext(),
                                (CarAudioManager) mCar.getCarManager(Car.AUDIO_SERVICE),
                                (CarOccupantZoneManager) mCar.getCarManager(
                                        Car.CAR_OCCUPANT_ZONE_SERVICE),
                                this);
                    }
                });

客户端Car.java(Android13/packages/services/Car/car-lib/src/android/car/Car.java)

在createCar中通过ServiceManagerHelper.getService(CAR_SERVICE_BINDER_SERVICE_NAME)拿到CarService对象,创建Car对象实例并传入CarService,将CarService赋值给private ICar mService;

//Car.java

 public static Car createCar(@NonNull Context context,
            @Nullable Handler handler, long waitTimeoutMs,
            @NonNull CarServiceLifecycleListener statusChangeListener) {
        assertNonNullContext(context);
        Objects.requireNonNull(statusChangeListener);
        Car car = null;
        IBinder service = null;
        boolean started = false;
        int retryCount = 0;
        long maxRetryCount = 0;
        if (waitTimeoutMs > 0) {
            maxRetryCount = waitTimeoutMs / CAR_SERVICE_BINDER_POLLING_INTERVAL_MS;
            // at least wait once if it is positive value.
            if (maxRetryCount == 0) {
                maxRetryCount = 1;
            }
        }
        boolean isMainThread = Looper.myLooper() == Looper.getMainLooper();
        while (true) {
            service = ServiceManagerHelper.getService(CAR_SERVICE_BINDER_SERVICE_NAME);
            if (car == null) {
                // service can be still null. The constructor is safe for null service.
                car = new Car(context, ICar.Stub.asInterface(service), null, statusChangeListener,
                        handler);
            }
            if (service != null) {
                if (!started) {  // specialization for most common case : car service already ready
                    car.dispatchCarReadyToMainThread(isMainThread);
                    // Needs this for CarServiceLifecycleListener. Note that ServiceConnection
                    // will skip the callback as valid mService is set already.
                    car.startCarService();
                    return car;
                }
                // service available after starting.
                break;
            }
            if (!started) {
                car.startCarService();
                started = true;
            }
            retryCount++;
            if (waitTimeoutMs < 0 && retryCount >= CAR_SERVICE_BINDER_POLLING_MAX_RETRY
                    && retryCount % CAR_SERVICE_BINDER_POLLING_MAX_RETRY == 0) {
                // Log warning if car service is not alive even for waiting forever case.
                Log.w(TAG_CAR, "car_service not ready, waited for car service (ms):"
                                + retryCount * CAR_SERVICE_BINDER_POLLING_INTERVAL_MS,
                        new RuntimeException());
            } else if (waitTimeoutMs >= 0 && retryCount > maxRetryCount) {
                if (waitTimeoutMs > 0) {
                    Log.w(TAG_CAR, "car_service not ready, waited for car service (ms):"
                                    + waitTimeoutMs,
                            new RuntimeException());
                }
                return car;
            }

            try {
                Thread.sleep(CAR_SERVICE_BINDER_POLLING_INTERVAL_MS);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                Log.w(TAG_CAR, "interrupted", new RuntimeException());
                return car;
            }
        }
        // Can be accessed from mServiceConnectionListener in main thread.
        synchronized (car.mLock) {
            Log.w(TAG_CAR,
                    "waited for car_service (ms):"
                            + retryCount * CAR_SERVICE_BINDER_POLLING_INTERVAL_MS,
                    new RuntimeException());
            // ServiceConnection has handled everything.
            if (car.mService != null) {
                return car;
            }
            // mService check in ServiceConnection prevents calling
            // onLifecycleChanged. So onLifecycleChanged should be called explicitly
            // but do it outside lock.
            car.mService = ICar.Stub.asInterface(service);
            car.mConnectionState = STATE_CONNECTED;
        }
        car.dispatchCarReadyToMainThread(isMainThread);
        return car;
    }
//Car.java

private Car(Context context, @Nullable ICar service,
            @Nullable ServiceConnection serviceConnectionListener,
            @Nullable CarServiceLifecycleListener statusChangeListener,
            @Nullable Handler handler) {
        mContext = context;
        mEventHandler = determineEventHandler(handler);
        mMainThreadEventHandler = determineMainThreadEventHandler(mEventHandler);

        mService = service;
        if (service != null) {
            mConnectionState = STATE_CONNECTED;
        } else {
            mConnectionState = STATE_DISCONNECTED;
        }
        mServiceConnectionListenerClient = serviceConnectionListener;
        mStatusChangeCallback = statusChangeListener;
        // Store construction stack so that client can get help when it crashes when car service
        // crashes.
        if (serviceConnectionListener == null && statusChangeListener == null) {
            mConstructionStack = new RuntimeException();
        } else {
            mConstructionStack = null;
        }
    }

到此已经拿到了CarService对象,接下来只要调用getCarService根据serviceName拿到对应的XXXManager

应用层调用getCarManager具体实现:主要看mService.getCarService(serviceName)和createCarManagerLocked(serviceName, binder);

//Car.java


 @Nullable
    @AddedInOrBefore(majorVersion = 33)
    public Object getCarManager(String serviceName) {
        CarManagerBase manager;
        synchronized (mLock) {
            if (mService == null) {
                Log.w(TAG_CAR, "getCarManager not working while car service not ready");
                return null;
            }
            manager = mServiceMap.get(serviceName);
            if (manager == null) {
                try {
                    IBinder binder = mService.getCarService(serviceName);
                    if (binder == null) {
                        Log.w(TAG_CAR, "getCarManager could not get binder for service:"
                                + serviceName);
                        return null;
                    }
                    manager = createCarManagerLocked(serviceName, binder);
                    if (manager == null) {
                        Log.w(TAG_CAR, "getCarManager could not create manager for service:"
                                        + serviceName);
                        return null;
                    }
                    mServiceMap.put(serviceName, manager);
                } catch (RemoteException e) {
                    handleRemoteExceptionFromCarService(e);
                }
            }
        }
        return manager;
    }

通过调用mService(也就是CarService,在Android13中改为ICarimpl)的getCarService方法拿到想要的binder对象(例如mCarInputService)

//ICarImpl.java
//源码路径Android13/packages/services/Car/service/src/com/android/car/ICarImpl.java
public IBinder getCarService(String serviceName) {
        if (!mFeatureController.isFeatureEnabled(serviceName)) {
            Slogf.w(CarLog.TAG_SERVICE, "getCarService for disabled service:" + serviceName);
            return null;
        }
        switch (serviceName) {
            case Car.AUDIO_SERVICE:
                return mCarAudioService;
            case Car.APP_FOCUS_SERVICE:
                return mAppFocusService;
            case Car.PACKAGE_SERVICE:
                return mCarPackageManagerService;
            case Car.DIAGNOSTIC_SERVICE:
                CarServiceUtils.assertAnyDiagnosticPermission(mContext);
                return mCarDiagnosticService;
           ......
           ......
           
            case Car.CAR_INPUT_SERVICE:
                return mCarInputService;
           ;
            default:
                IBinder service = null;
                if (mCarExperimentalFeatureServiceController != null) {
                    service = mCarExperimentalFeatureServiceController.getCarService(serviceName);
                }
                if (service == null) {
                    Slogf.w(CarLog.TAG_SERVICE, "getCarService for unknown service:"
                            + serviceName);
                }
                return service;
        }
    }

通过再接着通过createCarManagerLocked传入对应的binder创建想要的xxxManager对象实例

//Car.java

private CarManagerBase createCarManagerLocked(String serviceName, IBinder binder) {
        CarManagerBase manager = null;
        switch (serviceName) {
            case AUDIO_SERVICE:
                manager = new CarAudioManager(this, binder);
                break;
            case SENSOR_SERVICE:
                manager = new CarSensorManager(this, binder);
                break;
            case INFO_SERVICE:
                manager = new CarInfoManager(this, binder);
                break;
            case APP_FOCUS_SERVICE:
                manager = new CarAppFocusManager(this, binder);
                break;
            case PACKAGE_SERVICE:
                manager = new CarPackageManager(this, binder);
                break;
            case CAR_OCCUPANT_ZONE_SERVICE:
                manager = new CarOccupantZoneManager(this, binder);
                break;
            case CAR_NAVIGATION_SERVICE:
                manager = new CarNavigationStatusManager(this, binder);
                break;
            case CABIN_SERVICE:
                manager = new CarCabinManager(this, binder);
                break;
            case DIAGNOSTIC_SERVICE:
                manager = new CarDiagnosticManager(this, binder);
                break;
            case HVAC_SERVICE:
                manager = new CarHvacManager(this, binder);
                break;
            case POWER_SERVICE:
                manager = new CarPowerManager(this, binder);
                break;
            case PROJECTION_SERVICE:
                manager = new CarProjectionManager(this, binder);
                break;
            ......
            ......
            default:
                // Experimental or non-existing
                String className = null;
                try {
                    className = mService.getCarManagerClassForFeature(serviceName);
                } catch (RemoteException e) {
                    handleRemoteExceptionFromCarService(e);
                    return null;
                }
                if (className == null) {
                    Log.e(TAG_CAR, "Cannot construct CarManager for service:" + serviceName
                            + " : no class defined");
                    return null;
                }
                manager = constructCarManager(className, binder);
                break;
        }
        return manager;
    }

然后client端的xxxManager(例如CarInputManager)就拿到了对应的server端的service对像(CarInputService)

//CarInputManager.java
//Android13/packages/services/Car/car-lib/src/android/car/input/CarInputManager.java

public CarInputManager(Car car, IBinder service) {
        super(car);
        mService = ICarInput.Stub.asInterface(service);
    }

这时就完成了应用层拿到想要的xxxManager对象,xxxManager拿到了xxxService对象,之后想要做具体的事情应用层只要调用xxManager提供的API,xxxManager再调用xxxService的api就行了

参考内容:

【Android R】车载 Android 核心服务 - CarService 解析 - 简书

Android Automotive(五) CarService_android car service_探求之路的博客-优快云博客

【IVI】Car.java获取Car相关服务和对应管理器_car_vendor_extension_xhBruce的博客-优快云博客

### 如何在汽车服务应用中模拟发送信号 #### 协议选择与技术栈概述 为了实现在汽车服务应用程序中模拟发送信号的功能,通常会采用特定的通信协议来确保可靠性和效率。对于车辆内部网络而言,CAN (Controller Area Network) 是最常用的总线标准之一[^1]。然而,在某些情况下也可能涉及到其他类型的无线或有线通信机制。 #### CAN 总线作为主要传输媒介 当考虑通过CAN总线进行消息传递时,可以利用MATLAB/Simulink工具箱来进行建模和仿真工作。Simulink提供了强大的模块库用于创建复杂的控制系统模型,并允许用户定义自定义函数以适应特殊需求。例如,可以通过编写S-Function来处理来自虚拟节点的数据流并将其注入到现有的CAN网络环境中。 #### 使用 Simulink 进行 BLE 仿真的经验借鉴 虽然上述提到的是针对智能家居环境下的BLE协议栈仿真案例,但是其中涉及的一些设计理念同样适用于构建车载系统的原型。比如,如果计划开发一款能够远程监控车辆状态的应用程序,则可能需要设计类似的分层架构——从物理层一直到高层API接口;同时还要考虑到诸如安全性、功耗等因素对整体性能的影响。 #### 实现方案的具体步骤说明 假设要在一个简单的场景下测试向服务器报告发动机温度这一功能: 1. **建立连接**:初始化客户端设备上的蓝牙适配器并与指定的服务端完成配对过程; 2. **准备数据包**:按照既定格式封装待传送的信息(如当前读数),这一步骤往往依赖于预先设定好的映射表; 3. **执行写入操作**:调用相应的方法把构造完毕后的字节序列推送到目标特征值位置上; 4. **接收反馈确认**:等待对方回应ACK/NACK标志位表明此次交互的结果是否成功。 ```python import bluetooth def send_signal(address, port=1): sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM) try: sock.connect((address, port)) temp_data = b'\x0A' # 假设这是表示10度Celsius的一个简单例子 sent_bytes = sock.send(temp_data) print(f"Sent {sent_bytes} bytes.") ack = sock.recv(1024) print("Received:", ack.decode()) finally: sock.close() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值