Android Automotive(五) CarService

Android Automotive(五) CarService

CarService は、システム フレームワーク レイヤーの Android Automotive のコア サービスです。これは SystemServer に似ており、サービス内の数十のサブサービスを管理します。

開始プロセス

CarService は SystemServer によって起動され、起動プロセスは次のようになります。

  1. SystemServer 启动CarServiceHelperService
  2. CarServiceHelperService は CarService をバインドします
  3. CarService は ICarImpl のインスタンスを作成し、init メソッドを呼び出します
  4. ICarImpl は他のサービスを開始します

SystemServerコード:frameworks/base/services/java/com/android/server/SystemServer.java

private static final String CAR_SERVICE_HELPER_SERVICE_CLASS =
    "com.android.internal.car.CarServiceHelperService";
private void startOtherServices() {
    
    
    mActivityManagerService.systemReady(() -> {
    
    
        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
    
    
            traceBeginAndSlog("StartCarServiceHelperService");
            mSystemServiceManager.startService(CAR_SERVICE_HELPER_SERVICE_CLASS);
            traceEnd();
        }
    });
}

CarServiceHelperServiceコード:frameworks/opt/car/services/src/com/android/internal/car/CarServiceHelperService.java

private static final String CAR_SERVICE_INTERFACE = "android.car.ICar";
public class CarServiceHelperService extends SystemService {
    
    

    @Override
    public void onStart() {
    
    
        Intent intent = new Intent();
        intent.setPackage("com.android.car");
        intent.setAction(CAR_SERVICE_INTERFACE);
        if (!getContext().bindServiceAsUser(intent, mCarServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM)) {
    
    
            Slog.wtf(TAG, "cannot start car service");
        }
        System.loadLibrary("car-framework-service-jni");
    }
} 
  1. SystemServer真ん中が活性化されActivityManagerService.systemReadyた後SystemServiceManagerCarServiceHelperService
  2. CarServiceHelperServiceバインディングCarService

CarServiceマニフェスト ファイル:packages/services/Car/service/AndroidManifest.xml

<service android:name=".CarService"
    android:singleUser="true">
    <intent-filter>
        <action android:name="android.car.ICar" />
    </intent-filter>
</service>
  1. の設定により、パッケージ名と の名前で実装およびバインドできCarServiceますAndroidManifestCarServiceHelperServiceactionCarService

CarServiceコード:packages/services/Car/service/src/com/android/car/CarService.java

private ICarImpl mICarImpl;
private IVehicle mVehicle;
@Override
public void onCreate() {
    
    
    Log.i(CarLog.TAG_SERVICE, "Service onCreate");
    mCanBusErrorNotifier = new CanBusErrorNotifier(this /* context */);
    mVehicle = getVehicle();
    EventLog.writeEvent(EventLogTags.CAR_SERVICE_CREATE, mVehicle == null ? 0 : 1);
    Log.i(CarLog.TAG_SERVICE, "Connected to " + mVehicleInterfaceName);
    EventLog.writeEvent(EventLogTags.CAR_SERVICE_CONNECTED, mVehicleInterfaceName);

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

    linkToDeath(mVehicle, mVehicleDeathRecipient);

    ServiceManager.addService("car_service", mICarImpl);
    SystemProperties.set("boot.car_service_created", "1");
    super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
    
    
    return mICarImpl;
}
  1. CarService には、mICarImpl と mVehicle という 2 つの重要な変数があります。
  2. mICarImpl は、ICar インターフェイスを実装し、アプリケーション層との通信に使用される AIDL サーバーです。
  3. mVehicle は、hal レイヤーとの通信用に HIDL を実装する VehicleHal サービス インターフェースです。

ICarImplコード:packages/services/Car/service/src/com/android/car/ICarImpl.java

private final VehicleHal mHal;
@VisibleForTesting
ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface,
         CanBusErrorNotifier errorNotifier, String vehicleInterfaceName,
         @Nullable CarUserService carUserService,
         @Nullable CarWatchdogService carWatchdogService) {
    
    
    mContext = serviceContext;
    mSystemInterface = systemInterface;
    mHal = new VehicleHal(serviceContext, vehicle);
    allServices.add(mCarWatchdogService);
    // Always put mCarExperimentalFeatureServiceController in last.
    addServiceIfNonNull(allServices, mCarExperimentalFeatureServiceController);
    mAllServices = allServices.toArray(new CarServiceBase[allServices.size()]);
}

@MainThread
void init() {
    
    
    mBootTiming = new TimingsTraceLog(VHAL_TIMING_TAG, Trace.TRACE_TAG_HAL);
    traceBegin("VehicleHal.init");
    mHal.init();
    traceEnd();
    traceBegin("CarService.initAllServices");
    for (CarServiceBase service : mAllServices) {
    
    
        service.init();
    }
    traceEnd();
}
  1. ICarImpl最初にVehicleHalオブジェクトを作成します。VehicleHalクラスはオブジェクトのCarServiceカプセル化であり、オブジェクトとのすべての相互作用はここで処理されます。また、他のサービスもここで初期化されます好き:Vehicle ServiceVehicleHalhalPowerHalService
  2. ICarImplすべてのサービスが作成され、mAllServices に追加されCarLocalServices变量中,mAllServices は後で使用されますinit
  3. initメソッド呼び出しVehicleHalinitメソッド初期化mHal.init()
  4. initメソッドはmAllServicesサービスをトラバースし、init各サービスのメソッドを呼び出して初期化します。

建築

ここに画像の説明を挿入

カーサービス

コード パス:packages/services/Car/service/src/com/android/car/CarService.java

サービスのストレージとして、CarService は実際には多くのことを行いませんが、主に次のようになります。

  • サービスプロセスを作成する
    これは Android アーキテクチャの機能で、CarService は Service を継承し、システムのバックグラウンドでサービスとして実行できます。

  • CrashTracker を作成し
    、Vehicle hal が 10 分以内に 10 回クラッシュすると、CarService で例外がスローされます。

    private final CrashTracker mVhalCrashTracker = new CrashTracker(
        10,  // Max crash count.
        10 * 60 * 1000,  // 10 minutes - sliding time window.
        () -> {
          
          
            if (IS_USER_BUILD) {
          
          
                Log.e(CarLog.TAG_SERVICE, "Vehicle HAL keeps crashing, notifying user...");
                mCanBusErrorNotifier.reportFailure(CarService.this);
            } else {
          
          
                throw new RuntimeException(
                    "Vehicle HAL crashed too many times in a given time frame");
            }
        }
    )
    
  • IVehicle インスタンスを取得する
    IVehicle は HIDL のインターフェイスであり、HAL レイヤーとの通信がこれを介して完了します

  • サブサービスの作成を完了し、サブサービスを初期化します。

public void onCreate() {
    
    
    Log.i(CarLog.TAG_SERVICE, "Service onCreate");
    mCanBusErrorNotifier = new CanBusErrorNotifier(this /* context */);
    mVehicle = getVehicle();
    EventLog.writeEvent(EventLogTags.CAR_SERVICE_CREATE, mVehicle == null ? 0 : 1);
    Log.i(CarLog.TAG_SERVICE, "Connected to " + mVehicleInterfaceName);
    EventLog.writeEvent(EventLogTags.CAR_SERVICE_CONNECTED, mVehicleInterfaceName);

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

    linkToDeath(mVehicle, mVehicleDeathRecipient);

    ServiceManager.addService("car_service", mICarImpl);
    SystemProperties.set("boot.car_service_created", "1");
    super.onCreate();
}
  1. mVehicle = getVehicle();VehicleServiceハードウェア抽象化レイヤーのインスタンスを取得getService旧バージョンに比べ、Stringパラメータが追加されています。

    private static IVehicle getVehicle() {
          
          
        final String instanceName = SystemProperties.get("ro.vehicle.hal", "default");
    
        try {
          
          
            return android.hardware.automotive.vehicle.V2_0.IVehicle.getService(instanceName);
        } catch (RemoteException e) {
          
          
            Log.e(CarLog.TAG_SERVICE, "Failed to get IVehicle/" + instanceName + " service", e);
        } catch (NoSuchElementException e) {
          
          
            Log.e(CarLog.TAG_SERVICE, "IVehicle/" + instanceName + " service not registered yet");
        }
        return null;
    }
    
  2. mICarImpl = new ICarImpl(thisICarImplオブジェクトの作成はCarServiceプロキシと同等であり、すべてのサービスの読み込みと管理はプロキシによって行われます。

  3. mICarImpl.init()サブサービスの初期化を完了する

  4. linkToDeath(mVehicle, mVehicleDeathRecipient);監視対象VehicleServiceプロセスのステータス。

  5. ServiceManager.addService("car_service", mICarImpl);自分自身を追加して、ServiceManager他のモジュールが取得できるようにします

ICarImpl

コード パス:

packages/services/Car/service/src/com/android/car/ICarImpl.java

ICarImpl は、アプリケーション層 AIDL と通信するサーバーである ICar.Stub を実装します。CarService のすべてのサービスの読み込みと初期化は、内部で完了します。アプリケーション層は実際には、このクラスを通じて関連サービスを取得する AIDL エージェントです。

関連するサービス オブジェクトを作成する

ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface,
         CanBusErrorNotifier errorNotifier, String vehicleInterfaceName,
         @Nullable CarUserService carUserService,
         @Nullable CarWatchdogService carWatchdogService) {
    
    
    mContext = serviceContext;
    mSystemInterface = systemInterface;
    mHal = new VehicleHal(serviceContext, vehicle);
    ......
    mCarPropertyService = new CarPropertyService(serviceContext, mHal.getPropertyHal());
    ......
    List<CarServiceBase> allServices = new ArrayList<>();

    allServices.add(mCarPropertyService);
    mAllServices = allServices.toArray(new CarServiceBase[allServices.size()]);
}

初期化

@MainThread
void init() {
    
    
    mBootTiming = new TimingsTraceLog(VHAL_TIMING_TAG, Trace.TRACE_TAG_HAL);
    traceBegin("VehicleHal.init");
    mHal.init();//初始化VehicleHal
    traceEnd();
    traceBegin("CarService.initAllServices");
    for (CarServiceBase service : mAllServices) {
    
    
        service.init();//各个子service调用init
    }
    traceEnd();
}

Initialize を実行しVehicleHal、各サブサービスがinitメソッドを呼び出せるようにします

サブサービスを取得する

getCarServiceサービス プロキシのインターフェイスを取得する

public static final String CABIN_SERVICE = "cabin";
public static final String HVAC_SERVICE = "hvac";
public static final String INFO_SERVICE = "info";
public static final String PROPERTY_SERVICE = "property";
public static final String SENSOR_SERVICE = "sensor";
public static final String VENDOR_EXTENSION_SERVICE = "vendor_extension";
@Override
public IBinder getCarService(String serviceName) {
    
    
        switch (serviceName) {
    
    
            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:
                return mCarPropertyService;
        }
}

上記のすべてのフィールドのインターフェースが返されますCarPropertyServiceが、ここを除きPROPERTY_SERVICE、他のフィールドの使用は推奨されません ( @deprecated)。

車プロパティ サービス

システムアプリケーション層とハードウェア抽象化層との間のデータ通信を車両属性で完結させる、車両属性管理サービス。PropertyHalServiceインターフェイス呼び出しによって特定の機能を実現する重要なメンバー変数がありますPropertyHalServiceCarPropertyServiceその機能は、主にクライアントによって登録されたリスナーを維持することです。CarPropertyService は車両プロパティの管理を担当し、上位層のアプリケーションが車両プロパティを処理しやすくします。

CarPropertyICarProperty.Stubシステムアプリケーションと通信するサーバーとして継承

public class CarPropertyService extends ICarProperty.Stub

ICarPropertyコード:packages/services/Car/car-lib/src/android/car/hardware/property/ICarProperty.aidl

package android.car.hardware.property;

import android.car.hardware.CarPropertyConfig;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.property.ICarPropertyEventListener;

/**
 * @hide
 */
interface ICarProperty {
    
    

    void registerListener(int propId, float rate, in ICarPropertyEventListener callback) = 0;

    void unregisterListener(int propId, in ICarPropertyEventListener callback) = 1;

    List<CarPropertyConfig> getPropertyList() = 2;

    CarPropertyValue getProperty(int prop, int zone) = 3;

    void setProperty(in CarPropertyValue prop, in ICarPropertyEventListener callback) = 4;

    String getReadPermission(int propId) = 5;

    String getWritePermission(int propId) = 6;
}

重要な属性の説明

private final Map<IBinder, Client> mClientMap = new ConcurrentHashMap<>();
private final Map<Integer, CarPropertyConfig<?>> mConfigs = new HashMap<>();
private final PropertyHalService mHal;
private boolean mListenerIsSet = false;
private final Map<Integer, List<Client>> mPropIdClientMap = new ConcurrentHashMap<>();
private final SparseArray<SparseArray<Client>> mSetOperationClientMap = new SparseArray<>();
private final HandlerThread mHandlerThread =
    CarServiceUtils.getHandlerThread(getClass().getSimpleName());
private final Handler mHandler = new Handler(mHandlerThread.getLooper());

  • mCientMaplistenerオブジェクトを格納するMap オブジェクトClientClient
    コールバック インターフェイスの補助クラスが維持されService、新しい登録ごとにcallbackClient オブジェクトが作成されます

    private class Client implements IBinder.DeathRecipient {
          
          
        private final ICarPropertyEventListener mListener;
        private final IBinder mListenerBinder;
        private final SparseArray<Float> mRateMap = new SparseArray<Float>();  
    }
    
  • mConfigsシステムがサポートするすべての車両属性を保存

  • mHal PropertyHalServiceインスタンス、hal と対話する処理ロジック

  • mPropIdClientMap登録された車両属性の保存に使用Client

  • mSetOperationClientMapset運用のための車両属性レコードの保存

CarPropertyService::registerListener

車両プロパティのリスナーを登録します。登録中に権限が検出されICarImpl.assertPermission(mContext, mHal.getReadPermission(propId));登録が成功するとすぐにコールバックが行われますmHandler.post(() -> getAndDispatchPropertyInitValue(propertyConfig, finalClient));
client.getListener().onEvent(events);

@Override
public void registerListener(int propId, float rate, ICarPropertyEventListener listener) {
    
    
    if (DBG) {
    
    
        Log.d(TAG, "registerListener: propId=0x" + toHexString(propId) + " rate=" + rate);
    }
    if (listener == null) {
    
    
        Log.e(TAG, "registerListener: Listener is null.");
        throw new IllegalArgumentException("listener cannot be null.");
    }

    IBinder listenerBinder = listener.asBinder();
    CarPropertyConfig propertyConfig;
    Client finalClient;
    synchronized (mLock) {
    
    
        propertyConfig = mConfigs.get(propId);
        if (propertyConfig == null) {
    
    
            // Do not attempt to register an invalid propId
            Log.e(TAG, "registerListener:  propId is not in config list: 0x" + toHexString(
                    propId));
            return;
        }
        ICarImpl.assertPermission(mContext, mHal.getReadPermission(propId));
        // Get or create the client for this listener
        Client client = mClientMap.get(listenerBinder);
        if (client == null) {
    
    
            client = new Client(listener);
        }
        client.addProperty(propId, rate);
        // Insert the client into the propId --> clients map
        List<Client> clients = mPropIdClientMap.get(propId);
        if (clients == null) {
    
    
            clients = new CopyOnWriteArrayList<Client>();
            mPropIdClientMap.put(propId, clients);
        }
        if (!clients.contains(client)) {
    
    
            clients.add(client);
        }
        // Set the HAL listener if necessary
        if (!mListenerIsSet) {
    
    
            mHal.setListener(this);
        }
        // Set the new rate
        if (rate > mHal.getSampleRate(propId)) {
    
    
            mHal.subscribeProperty(propId, rate);
        }
        finalClient = client;
    }

    // propertyConfig and client are NonNull.
    mHandler.post(() ->
            getAndDispatchPropertyInitValue(propertyConfig, finalClient));
}
private void getAndDispatchPropertyInitValue(CarPropertyConfig config, Client client) {
    
    
    List<CarPropertyEvent> events = new LinkedList<>();
    int propId = config.getPropertyId();
    if (config.isGlobalProperty()) {
    
    
        CarPropertyValue value = mHal.getProperty(propId, 0);
        if (value != null) {
    
    
            CarPropertyEvent event = new CarPropertyEvent(
                    CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE, value);
            events.add(event);
        }
    } else {
    
    
        for (int areaId : config.getAreaIds()) {
    
    
            CarPropertyValue value = mHal.getProperty(propId, areaId);
            if (value != null) {
    
    
                CarPropertyEvent event = new CarPropertyEvent(
                        CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE, value);
                events.add(event);
            }
        }
    }
    try {
    
    
        client.getListener().onEvent(events);
    } catch (RemoteException ex) {
    
    
        // If we cannot send a record, its likely the connection snapped. Let the binder
        // death handle the situation.
        Log.e(TAG, "onEvent calling failed: " + ex);
    }
}

CarPropertyService::unregisterListener

車両プロパティ リスナーの登録解除

@Override
public void unregisterListener(int propId, ICarPropertyEventListener listener) {
    
    
    if (DBG) {
    
    
        Log.d(TAG, "unregisterListener propId=0x" + toHexString(propId));
    }
    ICarImpl.assertPermission(mContext, mHal.getReadPermission(propId));
    if (listener == null) {
    
    
        Log.e(TAG, "unregisterListener: Listener is null.");
        throw new IllegalArgumentException("Listener is null");
    }

    IBinder listenerBinder = listener.asBinder();
    synchronized (mLock) {
    
    
        unregisterListenerBinderLocked(propId, listenerBinder);
    }
}

CarPropertyService::getPropertyList

車両属性のリストを取得する

@Override
public List<CarPropertyConfig> getPropertyList() {
    
    
    List<CarPropertyConfig> returnList = new ArrayList<CarPropertyConfig>();
    Set<CarPropertyConfig> allConfigs;
    synchronized (mLock) {
    
    
        allConfigs = new HashSet<>(mConfigs.values());
    }
    for (CarPropertyConfig c : allConfigs) {
    
    
        if (ICarImpl.hasPermission(mContext, mHal.getReadPermission(c.getPropertyId()))) {
    
    
            // Only add properties the list if the process has permissions to read it
            returnList.add(c);
        }
    }
    if (DBG) {
    
    
        Log.d(TAG, "getPropertyList returns " + returnList.size() + " configs");
    }
    return returnList;
}

CarPropertyService::getProperty

車両のプロパティを取得する

@Override
public CarPropertyValue getProperty(int prop, int zone) {
    
    
    synchronized (mLock) {
    
    
        if (mConfigs.get(prop) == null) {
    
    
            // Do not attempt to register an invalid propId
            Log.e(TAG, "getProperty: propId is not in config list:0x" + toHexString(prop));
            return null;
        }
    }
    ICarImpl.assertPermission(mContext, mHal.getReadPermission(prop));
    return mHal.getProperty(prop, zone);
}

CarPropertyService::setProperty

車両のプロパティを設定する

@Override
public void setProperty(CarPropertyValue prop, ICarPropertyEventListener listener) {
    
    
    int propId = prop.getPropertyId();
    checkPropertyAccessibility(propId);
    // need an extra permission for writing display units properties.
    if (mHal.isDisplayUnitsProperty(propId)) {
    
    
        ICarImpl.assertPermission(mContext, Car.PERMISSION_VENDOR_EXTENSION);
    }
    mHal.setProperty(prop);
    IBinder listenerBinder = listener.asBinder();
    synchronized (mLock) {
    
    
        Client client = mClientMap.get(listenerBinder);
        if (client == null) {
    
    
            client = new Client(listener);
        }
        updateSetOperationRecorder(propId, prop.getAreaId(), client);
    }
}

CarPropertyService::onPropertyChange

車両属性のコールバックを処理し、ハードウェア抽象化レイヤーで車両属性の変更をシステム アプリケーション レイヤーに通知します。

@Override
public void onPropertyChange(List<CarPropertyEvent> events) {
    
    
    Map<IBinder, Pair<ICarPropertyEventListener, List<CarPropertyEvent>>> eventsToDispatch =
            new HashMap<>();

    for (CarPropertyEvent event : events) {
    
    
        int propId = event.getCarPropertyValue().getPropertyId();
        List<Client> clients = mPropIdClientMap.get(propId);
        if (clients == null) {
    
    
            Log.e(TAG, "onPropertyChange: no listener registered for propId=0x"
                    + toHexString(propId));
            continue;
        }

        for (Client c : clients) {
    
    
            IBinder listenerBinder = c.getListenerBinder();
            Pair<ICarPropertyEventListener, List<CarPropertyEvent>> p =
                    eventsToDispatch.get(listenerBinder);
            if (p == null) {
    
    
                // Initialize the linked list for the listener
                p = new Pair<>(c.getListener(), new LinkedList<CarPropertyEvent>());
                eventsToDispatch.put(listenerBinder, p);
            }
            p.second.add(event);
        }
    }
    // Parse the dispatch list to send events
    for (Pair<ICarPropertyEventListener, List<CarPropertyEvent>> p: eventsToDispatch.values()) {
    
    
        try {
    
    
            p.first.onEvent(p.second);
        } catch (RemoteException ex) {
    
    
            // If we cannot send a record, its likely the connection snapped. Let binder
            // death handle the situation.
            Log.e(TAG, "onEvent calling failed: " + ex);
        }
    }
}

プロパティハルサービス

CarPropertyServiceハードウェア抽象化層との通信を扱うクラスは、主にこのツールクラスを利用してシステムフレームワーク層とハードウェア抽象化層のデータ構造を変換しますCarPropertyUtils

重要な属性の説明

private final LinkedList<CarPropertyEvent> mEventsToDispatch = new LinkedList<>();
@GuardedBy("mLock")
private final Map<Integer, CarPropertyConfig<?>> mMgrPropIdToCarPropConfig = new HashMap<>();
@GuardedBy("mLock")
private final SparseArray<VehiclePropConfig> mHalPropIdToVehiclePropConfig =
    new SparseArray<>();
// Only contains propId if the property Id is different in HAL and manager
private static final Map<Integer, Integer> PROPERTY_ID_HAL_TO_MANAGER = Map.of(
    VehicleProperty.VEHICLE_SPEED_DISPLAY_UNITS,
    VehiclePropertyIds.VEHICLE_SPEED_DISPLAY_UNITS);
// Only contains propId if the property Id is different in HAL and manager
private static final Map<Integer, Integer> PROPERTY_ID_MANAGER_TO_HAL = Map.of(
    VehiclePropertyIds.VEHICLE_SPEED_DISPLAY_UNITS,
    VehicleProperty.VEHICLE_SPEED_DISPLAY_UNITS);
private static final String TAG = "PropertyHalService";
private final VehicleHal mVehicleHal;
private final PropertyHalServiceIds mPropIds;

@GuardedBy("mLock")
private PropertyHalListener mListener;
@GuardedBy("mLock")
private Set<Integer> mSubscribedHalPropIds;
  • mEventsToDispatchレポートされるデータのリスト。このデータはCarPropertyServiceレポートに直接送信されます。このデザインは素晴らしいです。受信したデータはリストに保存され、データの損失を防ぎます。リスト全体が処理のために上位層に送信され、PropertyHalServiceデータのブロッキングが回避されます。

  • mProps車両属性の設定、takeSupportedProperties属性の追加はメソッドで行います。

  • mVehicleHal VehicleHalのインスタンス

  • mPropIdsPropertyHalServiceIdsシステムの車両属性の権限を保持するデータ クラスのインスタンス

    private final PropertyHalServiceIds mPropIds;
    
    public PropertyHalService(VehicleHal vehicleHal) {
          
          
        mPropIds = new PropertyHalServiceIds();
    }
    
    public String getReadPermission(int propId) {
          
          
        return mPropIds.getReadPermission(propId);
    }
    
    @Nullable
    public String getWritePermission(int propId) {
          
          
        return mPropIds.getWritePermission(propId);
    }
    
  • mSubscribedPropIds車両属性のコレクションを監視します。コレクションを使用すると、繰り返し登録の監視を効果的にブロックできます

PropertyHalService::getProperty

車両属性を取得し、ハードウェア抽象化レイヤーのデータ構造をシステム フレームワーク レイヤーのデータ構造に変換します。

public CarPropertyValue getProperty(int mgrPropId, int areaId) {
    
    
    int halPropId = managerToHalPropId(mgrPropId);
    if (!isPropertySupportedInVehicle(halPropId)) {
    
    
        throw new IllegalArgumentException("Invalid property Id : 0x" + toHexString(mgrPropId));
    }

    // CarPropertyManager catches and rethrows exception, no need to handle here.
    VehiclePropValue value = mVehicleHal.get(halPropId, areaId);
    if (isMixedTypeProperty(halPropId)) {
    
    
        VehiclePropConfig propConfig;
        synchronized (mLock) {
    
    
            propConfig = mHalPropIdToVehiclePropConfig.get(halPropId);
        }
        boolean containBooleanType = propConfig.configArray.get(1) == 1;
        return value == null ? null : toMixedCarPropertyValue(value,
                mgrPropId, containBooleanType);
    }
    return value == null ? null : toCarPropertyValue(value, mgrPropId);
}
  1. isPropertySupportedInVehicle(halPropId)この車両属性がサポートしているかどうかを判断する
  2. VehiclePropValue value = mVehicleHal.get(halPropId, areaId) VehicleHal車両属性を取得する
  3. toCarPropertyValue(value, mgrPropId)ハードウェア抽象化レイヤーのデータ構造をシステム フレームワーク レイヤーのデータ構造に変換します。

PropertyHalService::setProperty

車両属性を設定して、システム フレームワーク レイヤーのデータ構造をハードウェア抽象化レイヤーのデータ構造に変換します。

public void setProperty(CarPropertyValue prop) {
    
    
    int halPropId = managerToHalPropId(prop.getPropertyId());
    if (!isPropertySupportedInVehicle(halPropId)) {
    
    
        throw new IllegalArgumentException("Invalid property Id : 0x"
                + toHexString(prop.getPropertyId()));
    }

    VehiclePropValue halProp;
    if (isMixedTypeProperty(halPropId)) {
    
    
        // parse mixed type property value.
        VehiclePropConfig propConfig;
        synchronized (mLock) {
    
    
            propConfig = mHalPropIdToVehiclePropConfig.get(prop.getPropertyId());
        }
        int[] configArray = propConfig.configArray.stream().mapToInt(i->i).toArray();
        halProp = toMixedVehiclePropValue(prop, halPropId, configArray);
    } else {
    
    
        halProp = toVehiclePropValue(prop, halPropId);
    }
    // CarPropertyManager catches and rethrows exception, no need to handle here.
    mVehicleHal.set(halProp);
}
  1. int halPropId = managerToHalPropId(prop.getPropertyId())ハードウェア抽象化レイヤーで使用される車両属性 ID に変換されます
  2. toVehiclePropValue(prop, halPropId)システム フレーム レイヤーのデータ構造は、ハードウェア抽象化レイヤーのデータ構造に変換されます。
  3. mVehicleHal.set(halProp)VehicleHal車両のプロパティを設定する

PropertyHalService::onHalEvents

VehiclePropValue(ハードウェア抽象化層のデータ構造) から (システムフレームワーク層のデータ構造) への変換を完了しCarPropertyValueCarPropertyEventデータにカプセル化して上位層に通知します。

@Override
public void onHalEvents(List<VehiclePropValue> values) {
    
    
    PropertyHalListener listener;
    synchronized (mLock) {
    
    
        listener = mListener;
    }
    if (listener != null) {
    
    
        for (VehiclePropValue v : values) {
    
    
            if (v == null) {
    
    
                continue;
            }
            if (!isPropertySupportedInVehicle(v.prop)) {
    
    
                Log.e(TAG, "Property is not supported: 0x" + toHexString(v.prop));
                continue;
            }
            // Check payload if it is a userdebug build.
            if (Build.IS_DEBUGGABLE && !mPropIds.checkPayload(v)) {
    
    
                Log.e(TAG, "Drop event for property: " + v + " because it is failed "
                        + "in payload checking.");
                continue;
            }
            int mgrPropId = halToManagerPropId(v.prop);
            CarPropertyValue<?> propVal;
            if (isMixedTypeProperty(v.prop)) {
    
    
                // parse mixed type property value.
                VehiclePropConfig propConfig;
                synchronized (mLock) {
    
    
                    propConfig = mHalPropIdToVehiclePropConfig.get(v.prop);
                }
                boolean containBooleanType = propConfig.configArray.get(1) == 1;
                propVal = toMixedCarPropertyValue(v, mgrPropId, containBooleanType);
            } else {
    
    
                propVal = toCarPropertyValue(v, mgrPropId);
            }
            CarPropertyEvent event = new CarPropertyEvent(
                    CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE, propVal);
            mEventsToDispatch.add(event);
        }
        listener.onPropertyChange(mEventsToDispatch);
        mEventsToDispatch.clear();
    }
}

PropertyHalService::getPropertyList

getPropertyListビークル プロパティのリストを返します。これは、実際にはmPropsそれ自体が保持するオブジェクトです。CarPropertyService でも維持されますmConfigs

public Map<Integer, CarPropertyConfig<?>> getPropertyList() {
    
    
    if (mDbg) {
    
    
        Log.d(TAG, "getPropertyList");
    }
    return mProps;
}

ビークルハル

それらをすべて管理するために*halservice、これらのサービスは車両属性によるデータ通信を実現していますが、サポートされている車両属性は比較的独立しており、互いに影響を与えることはありません。現在含まれているサービスは次のとおりです。

  • PowerHalService
  • PropertyHalService
  • InputHalService
  • VmsHalService
  • DiagnosticHalService

VehicleHal継承されIVehicleCallback.Stub、ハードウェア抽象化レイヤーの HIDL コールバックを受け取ることができます。

VehicleHal::init

初期化してmAllProperties、HAL レイヤーから車両属性構成を取得し、マップに追加します。すべてのサブサービスを初期化します。

public void init() {
    
    
    fetchAllPropConfigs();//遍历所有属性,从hal层获取将属性加到mAllProperties对象中

    // PropertyHalService will take most properties, so make it big enough.
    ArrayList<VehiclePropConfig> configsForService = new ArrayList<>(mAllServices.size());
    for (int i = 0; i < mAllServices.size(); i++) {
    
    
        HalServiceBase service = mAllServices.get(i);
        int[] supportedProps =  service.getAllSupportedProperties();//获取子服务支持的车辆属性
        configsForService.clear();
        synchronized (mLock) {
    
    
            if (supportedProps.length == 0) {
    
    //这里是PropertyHalService
                for (Integer propId : mAllProperties.keySet()) {
    
    
                    if (service.isSupportedProperty(propId)) {
    
    
                        VehiclePropConfig config = mAllProperties.get(propId);
                        mPropertyHandlers.append(propId, service);
                        configsForService.add(config);
                    }
                }
            } else {
    
    //这里是其他
                for (int prop : supportedProps) {
    
    
                    VehiclePropConfig config = mAllProperties.get(prop);
                    if (config == null) {
    
    
                        continue;
                    }
                    mPropertyHandlers.append(prop, service);
                    configsForService.add(config);
                }
            }
        }
        service.takeProperties(configsForService);
        service.init();
    }
}
  1. fetchAllPropConfigsすべてのアトリビュートをトラバースし、ハードウェア レイヤから取得して、アトリビュートをmAllPropertiesオブジェクトに追加します

  2. getAllSupportedPropertiesサブサービスでサポートされている車両属性を取得する

  3. PropertyHalService上記の判断を下します

    public int[] getAllSupportedProperties() {
          
          
        return CarServiceUtils.EMPTY_INT_ARRAY;
    }
    private static final int[] EMPTY_INT_ARRAY = new int[0];
    
  4. mPropertyHandlers属性がサポートされていると判断した後、とに属性を設定しconfigsForServicemPropertyHandlers処理対象の車両属性とサブサービスを記録し、configsForService車両属性を記録します。VehiclePropConfig

  5. takePropertiesfw の構成がそれをサポートしているかどうかを確認するサブサービスを呼び出す方法、および構成は で定義されておりPropertyHalServiceIds.java、車両のプロパティで必要なシステム権限を定義します。

VehicleHal::get

getメソッドは車両属性を取得するために使用され、実際のエグゼキュータはHalClient

public VehiclePropValue get(int propertyId, int areaId) {
    
    
    if (DBG) {
    
    
        Log.i(CarLog.TAG_HAL, "get, property: 0x" + toHexString(propertyId)
                + ", areaId: 0x" + toHexString(areaId));
    }
    VehiclePropValue propValue = new VehiclePropValue();
    propValue.prop = propertyId;
    propValue.areaId = areaId;
    return mHalClient.getValue(propValue);
}

VehicleHal::セット

setメソッドは車両のプロパティを設定するために使用され、実際のエグゼキュータはHalClient

protected void set(VehiclePropValue propValue) {
    
    
    mHalClient.setValue(propValue);
}

VehicleHal::getAllPropConfigs

getAllPropConfigsこのメソッドは、ハードウェア抽象化レイヤーからすべての車両属性構成を取得するために使用されます

public Collection<VehiclePropConfig> getAllPropConfigs() {
    
    
    return mAllProperties.values();
}

VehicleHal::onPropertyEvent

onPropertyEventこのメソッドは、ハードウェア抽象化レイヤーから車両属性の変更を監視するために使用されます。

@Override
public void onPropertyEvent(ArrayList<VehiclePropValue> propValues) {
    
    
    synchronized (mLock) {
    
    
        for (VehiclePropValue v : propValues) {
    
    
            HalServiceBase service = mPropertyHandlers.get(v.prop);
            if(service == null) {
    
    
                Log.e(CarLog.TAG_HAL, "HalService not found for prop: 0x"
                    + toHexString(v.prop));
                continue;
            }
            service.getDispatchList().add(v);
            mServicesToDispatch.add(service);
            VehiclePropertyEventInfo info = mEventLog.get(v.prop);
            if (info == null) {
    
    
                info = new VehiclePropertyEventInfo(v);
                mEventLog.put(v.prop, info);
            } else {
    
    
                info.addNewEvent(v);
            }
        }
    }
    for (HalServiceBase s : mServicesToDispatch) {
    
    
        s.onHalEvents(s.getDispatchList());
        s.getDispatchList().clear();
    }
    mServicesToDispatch.clear();
}
  1. onPropertyEvent書き直された HIDL インターフェースIVehicleCallbackコード パス:automotive\vehicle\2.0\IVehicleCallback.hal

    package android.hardware.automotive.vehicle@2.0;
    
    interface IVehicleCallback {
          
          
    
        /**
         * Event callback happens whenever a variable that the API user has
         * subscribed to needs to be reported. This may be based purely on
         * threshold and frequency (a regular subscription, see subscribe call's
         * arguments) or when the IVehicle#set method was called and the actual
         * change needs to be reported.
         *
         * These callbacks are chunked.
         *
         * @param values that has been updated.
         */
        oneway onPropertyEvent(vec<VehiclePropValue> propValues);
    
        /**
         * This method gets called if the client was subscribed to a property using
         * SubscribeFlags::EVENTS_FROM_ANDROID flag and IVehicle#set(...) method was called.
         *
         * These events must be delivered to subscriber immediately without any
         * batching.
         *
         * @param value Value that was set by a client.
         */
        oneway onPropertySet(VehiclePropValue propValue);
    
        /**
         * Set property value is usually asynchronous operation. Thus even if
         * client received StatusCode::OK from the IVehicle::set(...) this
         * doesn't guarantee that the value was successfully propagated to the
         * vehicle network. If such rare event occurs this method must be called.
         *
         * @param errorCode - any value from StatusCode enum.
         * @param property - a property where error has happened.
         * @param areaId - bitmask that specifies in which areas the problem has
         *                 occurred, must be 0 for global properties
         */
        oneway onPropertySetError(StatusCode errorCode,
                                  int32_t propId,
                                  int32_t areaId);
    };
    
  2. 1 つはハードウェア抽象化レイヤーから取得されArrayList、リスト内の各車両属性がここでループされます。

  3. HalServiceBase service = mPropertyHandlers.get(v.prop);これは、通知が必要な現在の車両属性を取得するため子HalService、または車両属性を管理するサービスを取得するためです。

  4. service.getDispatchList().add(v)この車両属性を、このサービスを管理するディスパッチ リストに追加します。

  5. mServicesToDispatch.add(service);このサブサービスをサービス配布リストに追加します。

  6. s.onHalEvents(s.getDispatchList());事前に特定された車両属性を使用して、対応するサービスに配信操作を実行させることです。一般的なビークル プロパティのエグゼキュータは ですPropertyHalService

HalClient

同等のVehicleHalプロキシ クラスは、VehicleHalハードウェア アブストラクション レイヤーとやり取りするインターフェイスを定義しますが、実際の実装は実際には を介し​​て呼び出されますHalClientハードウェア抽象化レイヤーへのハンドルをHalClient保持します。VehicleService

HalClient::getAllPropConfigs

すべての車両属性構成を取得する

ArrayList<VehiclePropConfig> getAllPropConfigs() throws RemoteException {
    
    
    return mVehicle.getAllPropConfigs();
}

HalClient::サブスクライブ

車両プロパティの変更を購読する

public void subscribe(SubscribeOptions... options) throws RemoteException {
    
    
    mVehicle.subscribe(mInternalCallback, new ArrayList<>(Arrays.asList(options)));
}

HalClient::登録解除

車両プロパティのサブスクリプションをキャンセルする

public void unsubscribe(int prop) throws RemoteException {
    
    
    mVehicle.unsubscribe(mInternalCallback, prop);
}

HalClient::setValue

車両プロパティを設定する

public void setValue(VehiclePropValue propValue) {
    
    
    int status = invokeRetriable(() -> {
    
    
        try {
    
    
            return mVehicle.set(propValue);
        } catch (RemoteException e) {
    
    
            Log.e(TAG, getValueErrorMessage("set", propValue), e);
            return StatusCode.TRY_AGAIN;
        }
    }, mWaitCapMs, mSleepMs);

    if (StatusCode.INVALID_ARG == status) {
    
    
        throw new IllegalArgumentException(getValueErrorMessage("set", propValue));
    }

    if (StatusCode.OK != status) {
    
    
        Log.e(TAG, getPropertyErrorMessage("set", propValue, status));
        throw new ServiceSpecificException(status,
                "Failed to set property: 0x" + Integer.toHexString(propValue.prop)
                        + " in areaId: 0x" + Integer.toHexString(propValue.areaId));
    }
}

HalClient::getValue

車両プロパティを取得する

VehiclePropValue getValue(VehiclePropValue requestedPropValue) {
    
    
    final ObjectWrapper<VehiclePropValue> valueWrapper = new ObjectWrapper<>();
    int status = invokeRetriable(() -> {
    
    
        ValueResult res = internalGet(requestedPropValue);
        valueWrapper.object = res.propValue;
        return res.status;
    }, mWaitCapMs, mSleepMs);

    if (StatusCode.INVALID_ARG == status) {
    
    
        throw new IllegalArgumentException(getValueErrorMessage("get", requestedPropValue));
    }

    if (StatusCode.OK != status || valueWrapper.object == null) {
    
    
        // If valueWrapper.object is null and status is StatusCode.Ok, change the status to be
        // NOT_AVAILABLE.
        if (StatusCode.OK == status) {
    
    
            status = StatusCode.NOT_AVAILABLE;
        }
        Log.e(TAG, getPropertyErrorMessage("get", requestedPropValue, status));
        throw new ServiceSpecificException(status,
                "Failed to get property: 0x" + Integer.toHexString(requestedPropValue.prop)
                        + " in areaId: 0x" + Integer.toHexString(requestedPropValue.areaId));
    }

    return valueWrapper.object;
}
private ValueResult internalGet(VehiclePropValue requestedPropValue) {
    
    
    final ValueResult result = new ValueResult();
    try {
    
    
        mVehicle.get(requestedPropValue,
                (status, propValue) -> {
    
    
                    result.status = status;
                    result.propValue = propValue;
                });
    } catch (RemoteException e) {
    
    
        Log.e(TAG, getValueErrorMessage("get", requestedPropValue), e);
        result.status = StatusCode.TRY_AGAIN;
    }

    return result;
}

車のプロパティ構成

車両属性の属性構成は FW 層で使用され、VehiclePropConfigハードウェア抽象化層から変換されます。車両属性の基本情報を定義します。読み取りと書き込みの性質、タイプ、変更モードなどを含みます。

private final int mAccess;
private final int mAreaType;
private final int mChangeMode;
private final ArrayList<Integer> mConfigArray;
private final String mConfigString;
private final float mMaxSampleRate;
private final float mMinSampleRate;
private final int mPropertyId;
private final SparseArray<AreaConfig<T>> mSupportedAreas;
private final Class<T> mType;

車のプロパティユーティリティ

ハードウェア抽象化レイヤーのデータ構造とシステム フレームワーク レイヤーのデータ構造を相互に変換するツール クラス。

  • toCarPropertyValue
    換算VehiclePropValueとなりますCarPropertyValue(HAL→FW)

    static CarPropertyValue<?> toCarPropertyValue(
        VehiclePropValue halValue, int propertyId) 
    
  • toVehiclePropValue
    換算CarPropertyValueとなりますVehiclePropValue(HW->HAL)

    static VehiclePropValue toVehiclePropValue(CarPropertyValue carProp, int halPropId)
    
  • toCarPropertyConfig
    換算VehiclePropConfigとなりますCarPropertyConfig(HAL→FW)

    static CarPropertyConfig<?> toCarPropertyConfig(VehiclePropConfig p, int propertyId)
    

換算関係

方法 換算関係
toCarPropertyValue VehiclePropValue ->CarPropertyValue(fw)
toVehiclePropValue CarPropertyValue ->VehiclePropValue(hal)
toCarPropertyConfig VehiclePropConfig ->CarPropertyConfig(fw)

CarPropertyConfig は、特定の車両プロパティの情報です。Map の KEY に相当します。

CarPropertyValue は、車のプロパティによって返される値です。マップの値に相当します。

VehiclePropConfig と VehiclePropValue の定義は、実際には types.hal にあります。

CarPropertyValue 変数の対応

車のプロパティ値 VehiclePropValue
mPropertyIdint 小道具int32_t
mAreaIdint エリアIDint32_t
ステータスint スターテスint32_t
mTimestamplong タイムスタンプint64_t
m値T 価値RawValue

システム フレームワーク レイヤーの戻り値CarPropertyValueはジェネリック型であり、対応する型は属性の実際の定義に従って決定できます。RawValueハードウェア抽象化レイヤーの定義は、従来型の配列と文字列を定義するデータ構造です。

struct RawValue {
    
    
    vec<int32_t> int32Values;
    vec<float> floatValues;
    vec<int64_t> int64Values;
    vec<uint8_t> bytes;
    string stringValue;
};

データ型が配列でない場合は、配列の 0 番目の位置を占めて戻り、ブール型はint32Values.get(0) == 1

CarPropertyConfig 変数の対応

車のプロパティ構成 VehiclePropConfig
mAccessint アクセスVehiclePropertyAccess
エリアタイプint
mChangeModeint 変更モードVehiclePropertyChangeMode
mConfigArrayArrayList<Integer> configArrayvec<int32_t>
mConfigStringString configStringstring
mMaxSampleRatefloat maxSampleRatefloat
mMinSampleRatefloat 最小サンプルレートfloat
mPropertyIdint 小道具int32_t
mサポートエリアSparseArray<AreaConfig<T>> mSupportedAreas エリア構成vec<VehicleAreaConfig>
mタイプClass<T>

mType は、車両プロパティの定義に従って計算されます。Class<?> clazz = getJavaClass(p.prop & VehiclePropertyType.MASK)

PropertyHalServiceIds

PropertyHalService によってサポートされる車両プロパティを定義します。このクラスは、読み取りおよび書き込み権限をプロパティ ID にバインドします。車両属性の許可定義を取得するためのインターフェイス コード パスを提供します
packages/services/Car/service/src/com/android/car/hal/PropertyHalServiceIds.java

public class PropertyHalServiceIds {
    
    
    // Index (key is propertyId, and the value is readPermission, writePermission
    private final SparseArray<Pair<String, String>> mProps;

    public PropertyHalServiceIds() {
    
    
        mProps = new SparseArray<>();

        // Add propertyId and read/write permissions
        // 在构造函数中绑定权限
        mProps.put(VehicleProperty.DOOR_POS, new Pair<>(
                Car.PERMISSION_CONTROL_CAR_DOORS,
                Car.PERMISSION_CONTROL_CAR_DOORS));
        //......
    }
}
  • getReadPermission()読み取り権限を取得、戻り値は文字列

    public String getReadPermission(int propId) {
          
          
        Pair<String, String> p = mProps.get(propId);
        if (p != null) {
          
          
            // Property ID exists.  Return read permission.
            if (p.first == null) {
          
          
                Log.e(TAG, "propId is not available for reading : 0x" + toHexString(propId));
            }
            return p.first;
        } else if (isVendorProperty(propId)) {
          
          
            // if property is vendor property and do not have specific permission.
            return Car.PERMISSION_VENDOR_EXTENSION;
        } else {
          
          
            return null;
        }
    }
    
  • getWritePermission()書き込み権限を取得、戻り値は文字列

    public String getWritePermission(int propId) {
          
          
        Pair<String, String> p = mProps.get(propId);
        if (p != null) {
          
          
            // Property ID exists.  Return write permission.
            if (p.second == null) {
          
          
                Log.e(TAG, "propId is not writable : 0x" + toHexString(propId));
            }
            return p.second;
        } else if (isVendorProperty(propId)) {
          
          
            // if property is vendor property and do not have specific permission.
            return Car.PERMISSION_VENDOR_EXTENSION;
        } else {
          
          
            return null;
        }
    }
    
  • isSupportedProperty()車両属性がPropertyHalService既知のリストにあるかどうかを確認します

    public boolean isSupportedProperty(int propId) {
          
          
        // Property is in the list of supported properties
        return mProps.get(propId) != null || isVendorProperty(propId);
    }
    
    private static boolean isVendorProperty(int propId) {
          
          
        return (propId & VehiclePropertyGroup.MASK) == VehiclePropertyGroup.VENDOR;
    }
    

要約する

親切 例証する
カーサービス 車の主なサービス
ICarImpl 特定の Car の実装クラス
ビークルハル IVehicleCallback インターフェイスを実装し、各サブサービスを維持するクラス
プロパティハルサービス HAL層で取得したデータを加工し、FW層で利用する型に変換
HalClient IVehileインターフェースを保持し、エージェントが実際に動作
PropertyHalServiceIds サポートされている属性と権限を定義する
車のプロパティユーティリティ ツールクラス、FWレイヤーとHALレイヤーのデータを変換
車のプロパティ構成 車両属性構成情報
車プロパティ サービス 車両プロパティによって制御されるサブサービス
クライアント 車両プロパティの通知を購読するためのクラス

CarService作为主服务,通过ICarImpl类实现对子服务CarPropertyService的创建以及对VehicleHal的初始化。VehicleHal中完成对子服务们的初始化,并通过传入的IVehicle对象使得PropertyHalService获取系统支持的车辆属性,完成初始化操作。在PropertyHalService中创建HalClient对象完成对IVehicle接口的实际调用,并将从HAL层获取的数据类型转化成FW层使用数据类型。CarPropertyService持有PropertyHalService的引用,完成上下层的数据交互操作。对于APPLICATION注册的Listener,CarPropertyService使用Client对象进行维护,当订阅的数据发生变化进行通知,当首次注册时,会主动获取值并进行一次通知操作。

关联关系:CarPropertyManager --> ICarProperty --> CarPropertyService --> PropertyHalService --> VehicleHal

                                     |

| --------------------- | ----------------------------------------------- |
| CarService | Car的主服务 |
| ICarImpl | 具体Car的实现类 |
| VehicleHal | 实现IVehicleCallback接口的类,并维护各个子服务 |
| PropertyHalService | 处理HAL层获取到的数据并将其转化成FW层使用的类型 |
| HalClient | 持有IVehile接口,代理实际操作 |
| PropertyHalServiceIds | 定义支持的属性以及权限 |
| CarPropertyUtils | 工具类,转化FW层和HAL层数据 |
| CarPropertyConfig | 车辆属性配置信息 |
| CarPropertyService | 车辆属性控制的子服务 |
| Client | 车辆车辆属性订阅通知的类 |

CarService主なサービスとして、サブサービスの作成とサブサービスの初期化はICarImplクラスによって実現されますでサブサービスの初期化を完了し、受信オブジェクトを介してシステムでサポートされている車両属性を取得して、初期化操作を完了します。その中にオブジェクトを作成してインターフェイスへの実際の呼び出しを完了し、HAL 層から取得したデータ型を FW 層で使用されるデータ型に変換します。保持された参照は、上位層と下位層のデータ相互作用操作を完了します。APPLICATION で登録された Listener は、オブジェクトを使用してメンテナンスを行い、サブスクライブされたデータが変更されたときに通知され、初回登録時にアクティブに値を取得して通知操作を実行します。CarPropertyServiceVehicleHalVehicleHalIVehiclePropertyHalServicePropertyHalServiceHalClientIVehicleCarPropertyServicePropertyHalServiceCarPropertyServiceClient

関係: CarPropertyManager --> ICarProperty --> CarPropertyService --> PropertyHalService --> VehicleHal

おすすめ

転載: blog.csdn.net/Jun_P/article/details/127116727