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)
사용되지 않으며 노옵스(no-ops)로 구현될 수 있습니다.

콜백은 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) 또는 차량 버스 메시지 빈도에 따라 발생합니다. 속성 이벤트는 속성의 상태가 변경되는 경우에도 발생할 수 있습니다. 예를 들어 unavailable에서 available로 변경되는 경우입니다.
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라는 모든 구조(예: VehiclePropConfigs, SetValueRequests, VehiclePropValues)는 LargeParcelable(또는 StableLargeParcelable)이라고 합니다. 각각은 바인더 경계 전반에서 바인더 제한(LargeParcelable 라이브러리 구현에서는 4KB)을 초과할 수 있는 큰 데이터를 전달하는 데 사용된 값의 목록을 나타냅니다. 각각 다음 필드가 포함된 유사한 구조 정의를 포함합니다.

가이드 설명
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.
}