VHAL インターフェース

AIDL VHAL は android.hardware.automotive.vehicle namespace で定義されます。VHAL インターフェースは IVehicle.aidl で定義されます。特に指定されていない限り、すべてのメソッドを実装する必要があります。

メソッド
VehiclePropConfigs getAllPropConfigs()
この車両 HAL でサポートされているすべてのプロパティの設定のリストを返します。
VehiclePropConfigs getPropConfigs(in int[] props)
特定のプロパティ ID のプロパティの設定のリストを返します。
void getValues(IVehicleCallback callback, in GetValueRequests requests)
非同期で車両プロパティ値を取得します。非同期で GetValueRequest のバッチを処理します。結果はコールバックの onGetValues メソッド経由で送信されます。
void setValues(IVehicleCallback callback, in SetValueRequests requests)
非同期で車両プロパティ値を設定します。非同期で SetValueRequest のバッチを処理します。結果はコールバックの onSetValues メソッド経由で送信されます。
void subscribe(in IVehicleCallback callback, in SubscribeOptions[] options, int maxSharedMemoryFileCount)
指定されたオプションのプロパティ イベントに登録します。登録オプションには、プロパティ ID、プロパティ エリア ID、ヘルツ単位のサンプルレート(継続プロパティの場合)などがあります。maxSharedMemoryFileCount は使用されません。
void unsubscribe(in IVehicleCallback callback, in int[] propIds)
指定されたプロパティの以前に登録されたプロパティ イベントを登録解除します。
returnSharedMemory(in IVehicleCallback callback, long sharedMemoryId)
使用されず、NoOps として実装できます。

コールバックは IVehicleCallback.aidl で定義され、次のメソッドを含みます。

メソッド
oneway void onGetValues(in GetValueResults responses)
値の取得の結果を送信する、getValues 関数のコールバック。取得するいくつかの値の準備が完了すると呼び出されます。
oneway void onSetValues(in SetValueResults responses)
値の設定の結果を送信する、setValues 関数のコールバック。VHAL が一部のプロパティ設定リクエストの処理を完了すると呼び出されます。
oneway void onPropertyEvent(in VehiclePropValues propValues, int sharedMemoryFileCount)
プロパティ更新イベントのレポートのコールバック。
CONTINUOUS プロパティで、プロパティ イベントはヘルツ単位の登録サンプルレートまたは車両バスメッセージ頻度に基づき発生します。また、プロパティ イベントはプロパティのステータス変更で発生する場合もあります。たとえば、利用不可から利用可能に変更した場合が該当します。
ON_CHANGE プロパティの場合、プロパティ イベントはプロパティの値またはプロパティのステータスが変更されると発生します。
SharedMemoryFileCount は常に 0 です。
oneway void onPropertySetError(in VehiclePropErrors errors)
対応する設定リクエストがない、非同期でのプロパティ設定エラーのレポートのコールバック。エラーが発生している設定リクエストが判明している場合には、この代わりにエラー結果を含む onSetValues を使用する必要があります。

詳しくは、IVehicle.aidlIVehicleCallback.aidl をご覧ください。

VHAL 実装は VtsHalAutomotiveVehicle_TargetTest.cpp で VHAL VTS により検証されます。テストでは基本的なメソッドが正しく実装されているかどうか、サポートされているプロパティの設定が正しいかどうかを検証します。

車両プロパティ値

VehiclePropValue 構造を使用して、各プロパティの値を記述します。次の項目があります。

項目名 説明
timestamp イベントが発生した時刻を表し、SystemClock.elapsedRealtimeNano() クロックと同期されているタイムスタンプ。
prop この値のプロパティ ID。
areaid この値のエリア ID。エリアはエリア ID 構成に記載のあるサポートされているエリア、またはグローバル プロパティの 0 とする必要があります。
value 実際のプロパティ値を含むデータ構造。プロパティ タイプに基づき、この項目内の 1 つ以上の項目を使用して、実際の値を格納します。たとえば、value.int32Values の最初の要素は Int32 タイプ プロパティに使用されます。詳しくはプロパティの設定をご覧ください。

非同期 getValues と setValues

getValuessetValues オペレーションは非同期で実行されます。つまり、実際の取得または設定オペレーションが完了する前に、関数が返る可能性があります。オペレーションの結果(たとえば、getValues のプロパティ値、setValues の完了またはエラー ステータス)は引数として渡されるコールバック経由で送信されます。

実装ではリクエストを処理するバインダー スレッドで結果をブロックしてはいけません。代わりに、リクエスト キューにリクエストを格納し、別のハンドラ スレッドを使用して、リクエストを非同期で処理することをおすすめします。詳しくは、リファレンス実装をご覧ください。

図 1. 非同期プロセス

大規模な Parcelable

VehiclePropConfigsSetValueRequestsVehiclePropValues など XXXs という名前が付いた構造はすべて、LargeParcelable(またはStableLargeParcelable)と呼ばれます。それぞれはバインダー境界間でバインダー制限(LargeParcelable ライブラリ実装の 4 KB)を超過する可能性がある大規模なデータを渡す際に使用される値のリストを表しています。それぞれ同じような構造を持っており、次の項目が含まれます。

ガイダンス 説明
payloads 値のサイズがバインダー メモリ制限内に収まる場合の値のリスト、または空のリスト。
sharedMemoryFd 値のリストが大きすぎる場合にシリアル化されたペイロードを格納する、共有メモリファイルを指す null 値許容のファイル記述子。

たとえば、VehiclePropConfigs は次のように定義されます。

parcelable VehiclePropConfigs {
    // The list of vehicle property configs if they fit the binder memory
    // limitation.
    VehiclePropConfig[] payloads;
    // Shared memory file to store configs if they exceed binder memory
    // limitation. Created by VHAL, readable only at client. Client could keep
    // the fd opened or keep the FD mapped to access configs.
    @nullable ParcelFileDescriptor sharedMemoryFd;
}

VehiclePropConfigs には空でないペイロードまたは null 以外の sharedMemoryFd のどちらかが含まれます。

  • payloads が空でない場合は、実際のデータのリスト(プロパティの設定)を格納します。
  • sharedMemoryFd が null ではない場合は、共有メモリファイルを含みます。共有メモリファイルは VehiclePropConfigs のシリアル化された構造を格納します。構造は writeToParcel 関数を使用して、Parcel をシリアル化します。

VHAL の Java クライアントである車のサービスは、LargeParcelable のシリアル化とシリアル化解除を処理します。VHAL 実装とネイティブ クライアントの場合は、LargeParcelableLargeParcelable ライブラリ、または ParcelableUtils.h のライブラリの便利なラッパークラスを使用して、シリアル化とシリアル化解除を行う必要があります。

たとえば、バインダーから受け取った getValues に対するネイティブ クライアントの解析リクエストは、次のようになります。

// 'requests' are from the binder.
GetValueRequests requests;
expected, ScopedAStatus> deserializedResults = fromStableLargeParcelable(requests);
if (deserializedResults.ok()) {
    const std::vector& getValueRequests = deserializedResults.value().getObject()->payloads;
    // Use the getValueRequests.
  } else {
    // handle error.
}

バインダー経由で getValues の結果を送信する VHAL 実装の例は以下のとおりです。

std::vector results = getResults();
GetValueResults parcelableResults;
ScopedAStatus status = vectorToStableLargeParcelable(std::move(results), &parcelableResults);
if (status.isOk()) {
    // Send parcelableResults through callback.
} else {
    // Handle error.
}