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 和取樣率 (以 Hz 為單位,適用於連續資源)。未使用 maxSharedMemoryFileCount
void unsubscribe(in IVehicleCallback callback, in int[] propIds)
取消訂閱指定資源先前訂閱的資源事件。
returnSharedMemory(in IVehicleCallback callback, long sharedMemoryId)
未使用,可實作為無操作。

回呼是在 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 屬性,系統會根據訂閱取樣率 (Hz) 或車輛匯流排訊息頻率觸發房源事件。如果資源狀態有所變更,也可能會觸發資源事件。例如從「無法使用」變更為「可使用」。
對於 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 包含實際資源值的資料結構。根據屬性類型,這個欄位內會使用一或多個欄位來儲存實際值。舉例來說,value.int32Values 中的第一個元素用於 Int32 類型屬性。詳情請參閱「資源設定」。

非同步的 getValues 和 setValues

getValuessetValues 作業是以非同步方式執行,這表示函式可能會在實際的 get 或 set 作業完成前傳回。作業結果 (例如 getValues 的屬性值和 setValues 的成功或錯誤狀態) 會透過以引數形式傳遞的回呼傳遞。

實作不得在處理要求的繫結程式執行緒中阻斷結果。建議您改為將要求儲存在要求佇列中,並使用個別的處理常式執行緒來非同步處理要求。詳情請參閱「參考實作」。

圖 1. 非同步程序。

大型 Parcelable

所有名為 XXXs 的結構 (例如 VehiclePropConfigsSetValueRequestsVehiclePropValues) 都稱為 LargeParcelable (或 StableLargeParcelable)。每個結構都代表一組值,用於跨繫結器邊界傳遞可能超出繫結器限制 (在 LargeParcelable 程式庫實作中為 4 KB) 的大量資料。每個類別都有類似的結構定義,其中包含下列欄位。

指南 說明
payloads 當值大小符合繫結器記憶體限制時,會列出值清單,否則會列出空清單。
sharedMemoryFd 當值清單過大時,這個可為空值的檔案描述元會指向共用記憶體檔案,用於儲存序列化的酬載。

例如,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 包含非空白酬載或非空值的 sharedMemoryFd

  • 如果 payloads 非空白,則會儲存實際資料清單,也就是屬性設定。
  • 如果 sharedMemoryFd 不是空值,則包含共用記憶體檔案,用於儲存 VehiclePropConfigs 的序列化結構。這個結構會使用 writeToParcel 函式將 Parcel 序列化。

作為 VHAL 的 Java 用戶端,Car Service 會處理 LargeParcelable 的序列化和反序列化作業。針對 VHAL 實作項目和原生用戶端,LargeParcelable 應使用 LargeParcelable 程式庫或 ParcelableUtils.h 中程式庫的實用包裝函式類別,進行序列化和反序列化。

舉例來說,從 Binder 收到的 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.
}