Android Automotive架构与流程:VehicleHAL,CarService,CarAPI,EVS

AOSP Automotive

Vehicle

Vehicle HAL架构

在这里插入图片描述
代码位置:

  • Car API:packages/services/Car/car-lib/
  • CarService:packages/services/Car/
  • Vehicle HAL:hardware/interfaces/automotive/vehicle/2.0/

安全性

Vehicle HAL 支持 3 个级别的数据访问安全性:

  • 仅限系统(由 vns_policy.xml 控制)
  • 允许拥有权限的应用访问(通过汽车服务)
  • 无需任何权限即可访问(通过汽车服务)

仅允许部分系统组件直接访问车辆属性,而车辆网络服务是把关程序。大多数应用需通过汽车服务的额外把关(例如,只有系统应用可以控制 HVAC,因为这需要仅授予系统应用的系统权限)。

常用汽车权限(前缀:android.car.permission.):
● [系统权限] ADJUST_CAR_CABIN 操作轿厢信息
● [系统签名] BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE
● [系统签名] BIND_CAR_INPUT_SERVICE
● [危险权限] CAR_ENERGY 访问车辆引擎类型
● [系统权限] CAR_IDENTIFICATION 汽车VIN码的访问
● [系统权限] CAR_MILEAGE 行驶里程访问
● [危险权限] CAR_SPEED 车速属性读取
● [系统权限] CAR_TIRES 轮胎相关属性的读写
● [普通权限] CAR_ENERGY_PORTS 油箱口或者充电口信息的访问
● [系统权限] CAR_ENGINE_DETAILED 访问发动机详细信息
● [系统权限] CAR_DYNAMICS_STATE 动态值访问
● [系统权限] CAR_VENDOR_EXTENSION 访问特殊的通信信道
● [系统权限] CAR_PROJECTION 允许访问car projection相关api
● [系统权限] CAR_MOCK_VEHICLE_HAL 允许模拟车身数据
● [普通权限] CAR_INFO 允许调用CarInfoManager API的权限
● [普通权限] CAR_EXTERIOR_ENVIRONMENT 读取车外温度的权限
● [系统权限] CAR_EXTERIOR_LIGHTS 读取外车灯信息的权限
● [普通权限] CAR_POWERTRAIN 读取动力传输系统信息的权限
● [系统权限] CAR_NAVIGATION_MANAGER 使用CarNavigationStatusManager API
● [系统权限] CAR_CONTROL_AUDIO_VOLUME 控制音量
● [系统权限] CAR_CONTROL_AUDIO_SETTINGS 音量设置
● [系统权限] CAR_DISPLAY_IN_CLUSTER 应用程序必须有此签名才能在仪表盘上显示
● [系统权限] CAR_DIAGNOSTICS 读取车辆诊断内容(包括客制化字段)
● [系统权限] CAR_DRIVING_STATE 访问CarDrivingStateService去获取驾驶状态
● [系统权限] CAR_INSTRUMENT_CLUSTER_CONTROL应用程序调用CarInstrumentClusterManager在仪表盘中启动Activity时需要此权限
● [系统权限] CLEAR_CAR_DIAGNOSTICS 清理车辆诊断信息
● [系统权限] CONTROL_APP_BLOCKING
● [系统权限] CONTROL_CAR_CLIMATE 操作空调
● [系统权限] CONTROL_CAR_DOORS 操作车门信息
● [系统权限] CONTROL_CAR_EXTERIOR_LIGHTS 控制外车灯信息
● [系统权限] CONTROL_CAR_WINDOWS 操作车窗信息
● [系统权限] CONTROL_CAR_MIRRORS 操作车辆后视镜信息
● [系统权限] CONTROL_CAR_SEATS 操作车辆座椅信息
● [系统权限] STORAGE_MONITORING
● [系统权限] VMS_PUBLISHER 访问VMS publisher API
● [系统权限] VMS_SUBSCRIBER 访问VMS subscriber API

调用流程

APP端

1.初始化CarAPI和具体的Manager

Car mCar = Car.createCar(getApplicationContext(), mClientListener);
mCar.connect();
private ServiceConnection mClientListener = new ServiceConnection() {
    
    
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
    
    
        try {
    
    
            Log.d(TAG,"MainActivity onServiceConnected...................iBinder = "+iBinder);
            mCarHvacManager = (CarHvacManager) mCar.getCarManager(Car.HVAC_SERVICE);
            mSensorManager =(CarSensorManager) mCar.getCarManager(Car.SENSOR_SERVICE);
            mMcuManager = (CarMcuManager) mCar.getCarManager(Car.CAR_MCU_SERVICE);
            mCarDYCabinManager = (CarDYCabinManager) mCar.getCarManager(Car.DYCABIN_SERVICE);
            mCarCabinManager = (CarCabinManager) mCar.getCarManager(Car.CABIN_SERVICE);
            mCarInfoManager = (CarInfoManager) mCar.getCarManager(Car.INFO_SERVICE);
            mCarPowerManager = (CarPowerManager) mCar.getCarManager(Car.POWER_SERVICE);
        } catch (CarNotConnectedException e) {
    
     e.printStackTrace(); }
    }
    @Override
    public void onServiceDisconnected(ComponentName componentName) {
    
     }
};
  1. Manager注册回调,然后通过onChangeEvent获取汽车属性值CarPropertyValue的改变:
mCarHvacManager.registerCallback(mHvacCallback);
private CarHvacEventCallback mHvacCallback = new CarHvacEventCallback() {
    
    
    @Override
    public void onChangeEvent(CarPropertyValue carPropertyValue) {
    
    
        //Log.d(TAG, "onChangeEvent id = " + toHexString(carPropertyValue.getPropertyId()));
        int value = -1;
        int areaId;
        switch (carPropertyValue.getPropertyId()) {
    
    
            case ID_HVAC_POWER_ON:
                value = (Integer)carPropertyValue.getValue();
                areaId = carPropertyValue.getAreaId();
                break;
            default:
                break;
        }
    }
    @Override
    public void onErrorEvent(int i, int i1) {
    
     }
};
  1. SET 和 GET,以HVAC空调为例:
mCarHvacManager.setIntProperty(ID_HVAC_LOCK_VENTILATION_ON, VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, HVAC_ON);
float temp = mCarHvacManager.getFloatProperty(ID_HVAC_TEMPERATURE_SET, SEAT_ROW_1_LEFT);

VehicleAreaType分为GLOBAL(全局)、WINDOW(车窗)、MIRROR(镜子)、SEAT(座椅)、DOOR(车门)、WHEEL(车轮)等:

enum VehicleArea : int32_t {
    
    
    GLOBAL      = 0x01000000,
    /** WINDOW maps to enum VehicleAreaWindow */
    WINDOW      = 0x03000000,
    /** MIRROR maps to enum VehicleAreaMirror */
    MIRROR      = 0x04000000,
    /** SEAT maps to enum VehicleAreaSeat */
    SEAT        = 0x05000000,
    /** DOOR maps to enum VehicleAreaDoor */
    DOOR        = 0x06000000,
    /** WHEEL maps to enum VehicleAreaWheel */
    WHEEL       = 0x07000000,
    /** IN_OUT_CAR maps to enum VehicleAreaInOutCar,车内外 */
    IN_OUT_CAR  = 0x08000000,

    MASK        = 0x0f000000,
};

CarAPI (car-lib:android.car.jar)

1.createCar:

public static Car createCar(Context context, ServiceConnection serviceConnectionListener, @Nullable Handler handler) {
    
    
    if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
    
    
        Log.e(CarLibLog.TAG_CAR, "FEATURE_AUTOMOTIVE not declared while android.car is used");
        return null;
    }
    try {
    
    
      return new Car(context, serviceConnectionListener, handler);
    } catch (IllegalArgumentException e) {
    
     // Expected when car service loader is not available.
    }
    return null;
}
  1. getCarManager(“serviceName”) -> createCarManager(“serviceName”, IBinder)
public Object getCarManager(String serviceName) throws CarNotConnectedException {
    
    
    CarManagerBase manager;
    ICar service = getICarOrThrow();
    synchronized (mCarManagerLock) {
    
    
        manager = mServiceMap.get(serviceName);
        if (manager == null) {
    
    
            try {
    
    
                    if(TBOX_SERVICE.equals(serviceName)){
    
    
                        manager = createCarManager(serviceName, null);
                        return  manager;
                    }
                IBinder binder = service.getCarService(serviceName);
                if (binder == null) {
    
    
                    Log.w(CarLibLog.TAG_CAR, "could not get binder for service:" + serviceName);
                    return null;
                }
                manager = createCarManager(serviceName, binder);
                if (manager == null) {
    
    
                    Log.w(CarLibLog.TAG_CAR, "could not create manager for service:" + serviceName);
                    return null;
                }
                mServiceMap.put(serviceName, manager);
            } catch (RemoteException e) {
    
    
                handleRemoteException(e);
            }
        }
    }
    return manager;
}
private CarManagerBase createCarManager(String serviceName, IBinder binder) throws CarNotConnectedException {
    
    
    CarManagerBase manager = null;
	Log.d("liueg", "------------------createCarManager()serviceName "+serviceName);
    switch (serviceName) {
    
    
        case AUDIO_SERVICE: manager = new CarAudioManager(binder, mContext, mEventHandler);break;
        case SENSOR_SERVICE: manager = new CarSensorManager(binder, mContext, mEventHandler);break;
		case DYSENSOR_SERVICE: manager = new CarDYSensorManager(binder, mContext, mEventHandler);break;
        case INFO_SERVICE: manager = new CarInfoManager(binder);break;
        case APP_FOCUS_SERVICE: manager = new CarAppFocusManager(binder, mEventHandler);break;
        case PACKAGE_SERVICE: manager = new CarPackageManager(binder, mContext);break;
        case CAR_NAVIGATION_SERVICE: manager = new CarNavigationStatusManager(binder);break;
        case CABIN_SERVICE: manager = new CarCabinManager(binder, mContext, mEventHandler);break;
        case DIAGNOSTIC_SERVICE: manager = new CarDiagnosticManager(binder, mContext, mEventHandler);break;
        case HVAC_SERVICE: manager = new CarHvacManager(binder, mContext, mEventHandler);break;
	    case DYHVAC_SERVICE: manager = new CarDYHvacManager(binder, mContext, mEventHandler);break;
        case POWER_SERVICE: manager = new CarPowerManager(binder, mContext, mEventHandler);break;
        case PROJECTION_SERVICE:manager = new CarProjectionManager(binder, mEventHandler);break;
        case PROPERTY_SERVICE: 
            manager = new CarPropertyManager(binder, mEventHandler, false, "CarPropertyManager");break;
        case VENDOR_EXTENSION_SERVICE: manager = new CarVendorExtensionManager(binder, mEventHandler);break;
        case CAR_INSTRUMENT_CLUSTER_SERVICE: 
            manager = new CarInstrumentClusterManager(binder, mEventHandler);break;
        case TEST_SERVICE:
            /* CarTestManager exist in static library. So instead of constructing it here,
             * only pass binder wrapper so that CarTestManager can be constructed outside. */
            manager = new CarTestManagerBinderWrapper(binder);break;
        case VMS_SUBSCRIBER_SERVICE: manager = new VmsSubscriberManager(binder); break;
        case BLUETOOTH_SERVICE: manager = new CarBluetoothManager(binder, mContext);break;
        case TBOX_SERVICE: manager = TboxManager.getInstance(); break;
        case STORAGE_MONITORING_SERVICE: manager = new CarStorageMonitoringManager(binder, mEventHandler); break;
        case CAR_DRIVING_STATE_SERVICE:
            manager = new CarDrivingStateManager(binder, mContext, mEventHandler);break;
        case CAR_UX_RESTRICTION_SERVICE:
            manager = new CarUxRestrictionsManager(binder, mContext, mEventHandler);break;
        case CAR_CONFIGURATION_SERVICE: manager = new CarConfigurationManager(binder);break;
		case CAR_MCU_SERVICE: manager = new CarMcuManager(binder, mContext, mEventHandler);break;
		case DYCABIN_SERVICE: manager = new CarDYCabinManager(binder, mContext, mEventHandler);break;
        default:break;
    }
    return manager;
}
  1. 具体的Manager -> 注册/反注册回调, set/get 属性CarProperty:
public final class CarHvacManager implements CarManagerBase {
    
    
    private void handleOnChangeEvent(CarPropertyValue value) {
    
    
        Collection<CarHvacEventCallback> callbacks;
        synchronized (this) {
    
     callbacks = new ArraySet<>(mCallbacks); }
        if (!callbacks.isEmpty()) {
    
    
            for (CarHvacEventCallback l: callbacks) {
    
    
                if (DBG) Log.d(TAG, "onChangeEvent value=" + value.toString());
                l.onChangeEvent(value);
            }
        }
    }
    private void handleOnErrorEvent(int propertyId, int zone) {
    
    
        Collection<CarHvacEventCallback> callbacks;
        synchronized (this) {
    
     callbacks = new ArraySet<>(mCallbacks); }
        if (!callbacks.isEmpty()) {
    
    
            for (CarHvacEventCallback l: callbacks) {
    
    
                l.onErrorEvent(propertyId, zone);
            }
        }
    }
    public CarHvacManager(IBinder service, Context context, Handler handler) {
    
    
        mCarPropertyMgr = new CarPropertyManager(service, handler, DBG, TAG);
    }
    public synchronized void registerCallback(CarHvacEventCallback callback)
            throws CarNotConnectedException {
    
    
        if (mCallbacks.isEmpty()) mListenerToBase = new CarPropertyEventListenerToBase(this);
        List<CarPropertyConfig> configs = getPropertyList();
        for (CarPropertyConfig c : configs) {
    
     // Register each individual propertyId
            mCarPropertyMgr.registerListener(mListenerToBase, c.getPropertyId(), 0);
        }
        mCallbacks.add(callback);
    }
    public synchronized void unregisterCallback(CarHvacEventCallback callback) {
    
    
        mCallbacks.remove(callback);
        try {
    
    
            List<CarPropertyConfig> configs = getPropertyList();
            for (CarPropertyConfig c : configs) {
    
     // Register each individual propertyId
                mCarPropertyMgr.unregisterListener(mListenerToBase, c.getPropertyId());
            }
        } catch (Exception e) {
    
     Log.e(TAG, "getPropertyList exception ", e); }
        if (mCallbacks.isEmpty()) {
    
    
            mCarPropertyMgr.unregisterListener(mListenerToBase);
            mListenerToBase = null;
        }
    }
    public List<CarPropertyConfig> getPropertyList() throws CarNotConnectedException {
    
    
        return mCarPropertyMgr.getPropertyList(mHvacPropertyIds);
    }
    public boolean isPropertyAvailable(@PropertyId int propertyId, int area) throws CarNotConnectedException {
    
    
        return mCarPropertyMgr.isPropertyAvailable(propertyId, area);
    }
    // GET
	// getBooleanProperty	->	mCarPropertyMgr.getBooleanProperty(propertyId, area);
	// getFloatProperty 	-> 	mCarPropertyMgr.getFloatProperty(propertyId, area);
	// getIntProperty 		-> 	mCarPropertyMgr.getIntProperty(propertyId, area);
    public boolean getBooleanProperty(@PropertyId int propertyId, int area)
            throws CarNotConnectedException {
    
    
        return mCarPropertyMgr.getBooleanProperty(propertyId, area);
    }
    // SET
	// setBooleanProperty	->	mCarPropertyMgr.setBooleanProperty(propertyId, area, val);
    // setFloatProperty	->	mCarPropertyMgr.setFloatProperty(propertyId, area, val);
	// setIntProperty		->	mCarPropertyMgr.setIntProperty(propertyId, area, val);
    public void setBooleanProperty(@PropertyId int propertyId, int area, boolean val)
            throws CarNotConnectedException {
    
    
        if (mHvacPropertyIds.contains(propertyId)) {
    
    
            mCarPropertyMgr.setBooleanProperty(propertyId, area, val);
        }
    }
}

CarService

  1. ICarImpl初始化多个Service,可通过getCarService返回对应的Service
public class CarService extends Service {
    
    
	IVehicle mVehicle = android.hardware.automotive.vehicle.V2_0.IVehicle.getService();
	ICarImpl mICarImpl = new ICarImpl(this,
                mVehicle,
                SystemInterface.Builder.defaultSystemInterface(this).build(),
                mCanBusErrorNotifier,
                mVehicleInterfaceName);
    mICarImpl.init();
}
public class ICarImpl extends ICar.Stub {
    
    
    public ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface,
            CanBusErrorNotifier errorNotifier, String vehicleInterfaceName) {
    
    
        mContext = serviceContext;
        mSystemInterface = systemInterface;
        mHal = new VehicleHal(vehicle);
        mVehicleInterfaceName = vehicleInterfaceName;
        mSystemActivityMonitoringService = new SystemActivityMonitoringService(serviceContext);
        mCarPowerManagementService = new CarPowerManagementService(mContext, mHal.getPowerHal(), systemInterface);
        mCarPropertyService = new CarPropertyService(serviceContext, mHal.getPropertyHal());
        mCarDrivingStateService = new CarDrivingStateService(serviceContext, mCarPropertyService);
        mCarUXRestrictionsService = new CarUxRestrictionsManagerService(serviceContext,
                mCarDrivingStateService, mCarPropertyService);
        mCarPackageManagerService = new CarPackageManagerService(serviceContext,
                mCarUXRestrictionsService, mSystemActivityMonitoringService);
        mCarInputService = new CarInputService(serviceContext, mHal.getInputHal());
        mCarProjectionService = new CarProjectionService(serviceContext, mCarInputService);
        mGarageModeService = new GarageModeService(mContext, mCarPowerManagementService);
        mAppFocusService = new AppFocusService(serviceContext, mSystemActivityMonitoringService);
        mCarAudioService = new CarAudioService(serviceContext, mCarPropertyService);
        mCarNightService = new CarNightService(serviceContext, mCarPropertyService);
        mInstrumentClusterService = new InstrumentClusterService(serviceContext, mAppFocusService, mCarInputService);
        mSystemStateControllerService = new SystemStateControllerService(serviceContext,
                mCarPowerManagementService, mCarAudioService, this);
        mPerUserCarServiceHelper = new PerUserCarServiceHelper(serviceContext);
        mCarBluetoothService = new CarBluetoothService(serviceContext, mCarPropertyService,
                mPerUserCarServiceHelper, mCarUXRestrictionsService);
        mVmsSubscriberService = new VmsSubscriberService(serviceContext, mHal.getVmsHal());
        mVmsPublisherService = new VmsPublisherService(serviceContext, mHal.getVmsHal());
        mCarDiagnosticService = new CarDiagnosticService(serviceContext, mHal.getDiagnosticHal());
        mCarStorageMonitoringService = new CarStorageMonitoringService(serviceContext, systemInterface);
        mCarConfigurationService = new CarConfigurationService(serviceContext, new JsonReaderImpl());
        mUserManagerHelper = new CarUserManagerHelper(serviceContext);
        mCarLocationService = new CarLocationService(mContext, mCarPowerManagementService,
                mCarPropertyService, mUserManagerHelper);
        addTboxService();
        addUpgradeService();
        // Be careful with order. Service depending on other service should be inited later.
        List<CarServiceBase> allServices = new ArrayList<>();
        allServices.add(mSystemActivityMonitoringService);
        allServices.add(mCarPowerManagementService);
        allServices.add(mCarPropertyService); // ★ CarPropertyService
        allServices.add(mCarDrivingStateService);
        allServices.add(mCarUXRestrictionsService);
        allServices.add(mCarPackageManagerService);
        allServices.add(mCarInputService);
        allServices.add(mGarageModeService);
        allServices.add(mAppFocusService);
        allServices.add(mCarAudioService);
        allServices.add(mCarNightService);
        allServices.add(mInstrumentClusterService);
        allServices.add(mCarProjectionService);
        allServices.add(mSystemStateControllerService);
        allServices.add(mCarBluetoothService);
        allServices.add(mCarDiagnosticService);
        allServices.add(mPerUserCarServiceHelper);
        allServices.add(mCarStorageMonitoringService);
        allServices.add(mCarConfigurationService);
        allServices.add(mVmsSubscriberService);
        allServices.add(mVmsPublisherService);
        if (mUserManagerHelper.isHeadlessSystemUser()) {
    
    
            mCarUserService = new CarUserService(serviceContext, mUserManagerHelper);
            allServices.add(mCarUserService);
        }
        allServices.add(mCarLocationService);
        mAllServices = allServices.toArray(new CarServiceBase[allServices.size()]);
    }
    @MainThread
    void init() {
    
    
        traceBegin("VehicleHal.init");
        mHal.init();
        traceEnd();
        traceBegin("CarService.initAllServices");
        for (CarServiceBase service : mAllServices) {
    
    
            service.init();
        }
        traceEnd();
    }
	@Override
    public IBinder getCarService(String serviceName) {
    
    
        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:
                assertAnyDiagnosticPermission(mContext);
                return mCarDiagnosticService;
            case Car.POWER_SERVICE:
                assertPowerPermission(mContext);
                return mCarPowerManagementService;
            case Car.CABIN_SERVICE:
            case Car.HVAC_SERVICE:
            case Car.INFO_SERVICE:
            case Car.PROPERTY_SERVICE:
            case Car.SENSOR_SERVICE:
            case Car.VENDOR_EXTENSION_SERVICE:
			case Car.DYHVAC_SERVICE:
			case Car.CAR_MCU_SERVICE:
			case Car.DYCABIN_SERVICE:
			case Car.DYSENSOR_SERVICE:
                return mCarPropertyService;  // ★ CarPropertyService
			... ...
		}
	}
}

public class VehicleHal extends IVehicleCallback.Stub {
    
    
    public VehicleHal(IVehicle vehicle) {
    
    
        final HandlerThread mHandlerThread = new HandlerThread("VEHICLE-HAL");
        mHandlerThread.start();
        // passing this should be safe as long as it is just kept and not used in constructor
        final PowerHalService mPowerHal = new PowerHalService(this);
        final PropertyHalService mPropertyHal = new PropertyHalService(this); // ★ PropertyHalService
        final InputHalService mInputHal = new InputHalService(this);
        final VmsHalService mVmsHal = new VmsHalService(this);
        DiagnosticHalService mDiagnosticHal = new DiagnosticHalService(this);
        final ArrayList<HalServiceBase> mAllServices = new ArrayList<>();
		mAllServices.addAll(Arrays.asList(mPowerHal,
                mInputHal,
                mPropertyHal,
                mDiagnosticHal,
                mVmsHal));

        volatile HalClient mHalClient = new HalClient(vehicle, mHandlerThread.getLooper(), this /*IVehicleCallback*/);
    }
}
  1. PropertyHalService通过getProperty、setProperty、subscribeProperty、unsubscribeProperty调用 VehicleHal:
public class PropertyHalService extends HalServiceBase {
    
    
    public Map<Integer, CarPropertyConfig<?>> getPropertyList() {
    
    
        return mProps;
    }
    @Nullable
    public CarPropertyValue getProperty(int mgrPropId, int areaId) {
    
    
        int halPropId = managerToHalPropId(mgrPropId);
        if (halPropId == NOT_SUPPORTED_PROPERTY) {
    
    
            throw new IllegalArgumentException("Invalid property Id : 0x" + toHexString(mgrPropId));
        }
        VehiclePropValue value = null;
        try {
    
    
            value = mVehicleHal.get(halPropId, areaId);
        } catch (PropertyTimeoutException e) {
    
    
            Log.e(CarLog.TAG_PROPERTY, "get, property not ready 0x" + toHexString(halPropId), e);
        }
        return value == null ? null : toCarPropertyValue(value, mgrPropId);
    }

    public void setProperty(CarPropertyValue prop) {
    
    
        int halPropId = managerToHalPropId(prop.getPropertyId());
        if (halPropId == NOT_SUPPORTED_PROPERTY) {
    
    
            throw new IllegalArgumentException("Invalid property Id : 0x" + toHexString(prop.getPropertyId()));
        }
        VehiclePropValue halProp = toVehiclePropValue(prop, halPropId);
        try {
    
    
            mVehicleHal.set(halProp);
        } catch (PropertyTimeoutException e) {
    
    
            Log.e(CarLog.TAG_PROPERTY, "set, property not ready 0x" + toHexString(halPropId), e);
            throw new RuntimeException(e);
        }
    }

    /**
     * Subscribe to this property at the specified update rate.
     */
    public void subscribeProperty(int propId, float rate) {
    
    
        if (mDbg) Log.d(TAG, "subscribeProperty propId=0x" + toHexString(propId) + ", rate=" + rate);
        int halPropId = managerToHalPropId(propId);
        if (halPropId == NOT_SUPPORTED_PROPERTY) {
    
    
            throw new IllegalArgumentException("Invalid property Id : 0x" + toHexString(propId));
        }
        // Validate the min/max rate
        CarPropertyConfig cfg = mProps.get(propId);
        if (rate > cfg.getMaxSampleRate()) {
    
    
            rate = cfg.getMaxSampleRate();
        } else if (rate < cfg.getMinSampleRate()) {
    
    
            rate = cfg.getMinSampleRate();
        }
        synchronized (mSubscribedPropIds) {
    
     mSubscribedPropIds.add(halPropId); }
        mVehicleHal.subscribeProperty(this, halPropId, rate);
    }
    public void unsubscribeProperty(int propId) {
    
    
        if (mDbg) Log.d(TAG, "unsubscribeProperty propId=0x" + toHexString(propId));
        int halPropId = managerToHalPropId(propId);
        if (halPropId == NOT_SUPPORTED_PROPERTY) {
    
    
            throw new IllegalArgumentException("Invalid property Id : 0x" + toHexString(propId));
        }
        synchronized (mSubscribedPropIds) {
    
    
            if (mSubscribedPropIds.contains(halPropId)) {
    
    
                mSubscribedPropIds.remove(halPropId);
                mVehicleHal.unsubscribeProperty(this, halPropId);
            }
        }
    }
    @Override
    public Collection<VehiclePropConfig> takeSupportedProperties(Collection<VehiclePropConfig> allProperties) {
    
    
        List<VehiclePropConfig> taken = new LinkedList<>();
        for (VehiclePropConfig p : allProperties) {
    
    
            if (mPropIds.isSupportedProperty(p.prop)) {
    
    
                CarPropertyConfig config = CarPropertyUtils.toCarPropertyConfig(p, p.prop);
                taken.add(p);
                mProps.put(p.prop, config);
            }
        }
        if (mDbg) Log.d(TAG, "takeSupportedProperties() took " + taken.size() + " properties");
        return taken;
    }
}

Vehicle

EVS

EVS,(Extended View System,扩展视图系统),包括以下系统组件:
在这里插入图片描述
代码路径:

  • APP:packages/services/Car/evs/
  • HAL:hardware/interfaces/automotive/evs/1.0/

编译目标:system/bin/evs_app
运行在init进程中,所以支持快速倒车

猜你喜欢

转载自blog.csdn.net/zhoumushui/article/details/108616162
今日推荐