Android Automotive之Car API

这个Demo APP只有一个Activity,如下:

package com.example.demoapp;
import android.os.Bundle;
import android.app.Activity;
import android.car.Car;
import android.car.hardware.cabin.CarCabinManager;
import android.car.hardware.CarPropertyConfig;
import java.util.List;
public class MainActivity extends Activity {
    private CarCabinManager mCarCabinManager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
    }
     @Override
    protected void onResume(){
        super.onResume();
        Car mCar = Car.createCar(this);
        
        mCarCabinManager =
                (CarCabinManager) mCar.getCarManager(Car.CABIN_SERVICE);
                
        List<CarPropertyConfig> mList = mCarCabinManager.getPropertyList();
        
        android.util.Log.d("debug_car","mCarCabinManager = :"+mCarCabinManager+",mList.size = :"+mList.size());
    }
}

代码很简单,在onResume时通过createCar创建Car实例,然后就可以通过其getCarManager获取各种manager,有了manager就可以访问汽车的各种数据以及状态

Car.createCar

    public static Car createCar(Context context) {
        return createCar(context, (Handler) null);
    }

    @Nullable
    public static Car createCar(Context context, @Nullable Handler handler) {
        assertNonNullContext(context);
        Car car = null;
        IBinder service = null;
        boolean started = false;
        int retryCount = 0;
        while (true) {
            service = ServiceManager.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 /*serviceConnectionListener*/, null /*statusChangeListener*/, handler);
            }
            if (service != null) {
                if (!started) {  // specialization for most common case.
                    // Do this to crash client when car service crashes.
                    car.startCarService();
                    return car;
                }
                break;
            }
            if (!started) {
                car.startCarService();
                started = true;
            }
            retryCount++;
            if (retryCount > CAR_SERVICE_BINDER_POLLING_MAX_RETRY) {
                Log.e(TAG_CAR, "cannot get car_service, waited for car service (ms):"
                                + CAR_SERVICE_BINDER_POLLING_INTERVAL_MS
                                * CAR_SERVICE_BINDER_POLLING_MAX_RETRY,
                        new RuntimeException());
                return null;
            }
            try {
                Thread.sleep(CAR_SERVICE_BINDER_POLLING_INTERVAL_MS);
            } catch (InterruptedException e) {
                Log.e(CarLibLog.TAG_CAR, "interrupted while waiting for car_service",
                        new RuntimeException());
                return null;
            }
        }
        // Can be accessed from mServiceConnectionListener in main thread.
        synchronized (car) {
            if (car.mService == null) {
                car.mService = ICar.Stub.asInterface(service);
                Log.w(TAG_CAR,
                        "waited for car_service (ms):"
                                + CAR_SERVICE_BINDER_POLLING_INTERVAL_MS * retryCount,
                        new RuntimeException());
            }
            car.mConnectionState = STATE_CONNECTED;
        }
        return car;
    }
 

Car提供了多个createCar的重载方法,原理都差不多,看其中一个即可,上面的代码逻辑很简单,有两个目的,1. 向ServiceManager获取名为"car_service"的binder服务。 2. new出一个Car实例。

首先来看步骤一,这里会死循环的获取"car_service"服务,尝试次数为100,其中每次间隔50ms,

CarService被绑定之后,其onCreate方法中初始化了"car_service”,并将其注册到了ServiceManager

 @Override
    public void onCreate() {
       ...

        mICarImpl = new ICarImpl(this,
                mVehicle,
                SystemInterface.Builder.defaultSystemInterface(this).build(),
                mCanBusErrorNotifier,
                mVehicleInterfaceName);
        mICarImpl.init();

        ServiceManager.addService("car_service", mICarImpl);
        ...
        super.onCreate();
    }

    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;
        }
    }

determineEventHandler和determineMainThreadEventHandler这两个方法用来保证Car内部的Handler不能为空并且必须是运行在主线程,mService保存了"car_service"的binder代理对象,mServiceConnectionListenerClient用作通知APP端CarService已经启动,此回调可以为空。
Car构造方法中还有个比较重要的变量mConnectionState,用来描述当前客户端与"car_service"的连接状态,有三个状态值:断开连接,正在连接,已经连接

    private static final int STATE_DISCONNECTED = 0;
    private static final int STATE_CONNECTING = 1;
    private static final int STATE_CONNECTED = 2;
  /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = "STATE_", value = {
            STATE_DISCONNECTED,
            STATE_CONNECTING,
            STATE_CONNECTED,
    })

到此Car.createCar就看完了,其核心就两点,1. 要获取"car_service",将其代理对象保存在Car的成员变量mService中,以便后续使用,2. 实例化Car对象。

其实前面还有个方法startCarService没看,这是因为此方法的目的同样是“获取"car_service",将其代理对象保存在Car的成员变量mService中”,只不过用的是绑定服务的方式,如果失败会最多尝试20次。

接着回到前面的Demo APP,Car创建完成之后就可以拿Car对象获取各个相关manager,我们这里获取的是名为"cabin"的manager:

Car.getCarManager

    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;
    }
mServiceMap是一个缓存集合,如果这里面已经有要求的manager则直接返回,否则需要创建,mService刚刚才看了,保存了"car_service"服务的client端,所以这里实际是去ICarImpl中根据字符串名称"cabin"获取其Binder服务:

ICarImpl.getCarService

    @Override
    public IBinder getCarService(String serviceName) {
        if (!mFeatureController.isFeatureEnabled(serviceName)) {
            Log.w(CarLog.TAG_SERVICE, "getCarService for disabled service:" + serviceName);
            return null;
        }
        switch (serviceName) {
            ...
            
            case Car.CABIN_SERVICE:
                return mCarPropertyService;
                
            ...
            case Car.BLUETOOTH_SERVICE:
                return mCarBluetoothService;
            ...
            default:
                IBinder service = null;
                if (mCarExperimentalFeatureServiceController != null) {
                    service = mCarExperimentalFeatureServiceController.getCarService(serviceName);
                }
                if (service == null) {
                    Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:"
                            + serviceName);
                }
                return service;
        }
    }
这里面有很多service,都是在ICarImpl构造方法中创建的,我们"cabin"就拿到了CarPropertyService这个服务,再回到前面createCarManagerLocked方法:

Car.createCarManagerLocked

    @Nullable
    private CarManagerBase createCarManagerLocked(String serviceName, IBinder binder) {
        CarManagerBase manager = null;
        switch (serviceName) {
            ...
            case CABIN_SERVICE:
                manager = new CarCabinManager(this, binder);
                break;
            ...
            default:
                ...
                break;
        }
        return manager;
    }
new了一个CarCabinManager

    public CarCabinManager(Car car, IBinder service) {
        super(car);
        ICarProperty mCarPropertyService = ICarProperty.Stub.asInterface(service);
        mCarPropertyMgr = new CarPropertyManager(car, mCarPropertyService);
    }

得到CarPropertyService代理端,并构造CarPropertyManager。

到这里我们可以发现,Car这个类仅仅作为外界的访问入口,它内部主要还是依靠ICarImpl这个Binder服务来获取各种manager,而各种manager又作为访问service的入口,这些service才是实现汽车具体业务逻辑的核心。

比如我们Demo APP中用到的mCarCabinManager.getPropertyList()方法,其具体实现在CarPropertyService中,但最终的实现都会绕到vehicle hal中的getPropConfigs中。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/qq_34211365/article/details/117658801


————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/qq_34211365/article/details/117658801

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值