프레임워크를 조건부로 컴파일하는 데 사용되는 모든 빌드 플래그를 설명하려면 HIDL을 사용해야 합니다. 관련 빌드 플래그는 그룹화하여 단일 .hal
파일에 포함해야 합니다. HIDL을 사용하여 구성 항목을 지정하면 다음과 같은 이점을 얻을 수 있습니다.
- 버전 관리(새 구성 항목을 추가하려면 공급업체/OEM에서 HAL을 명시적으로 확장해야 함)
- 문서화
- SELinux로 액세스 제어
- 구성 항목 상태 점검 시 공급업체 테스트 도구 모음 활용(범위 확인, 항목 간의 상호 종속 항목 확인 등)
- C++ 및 자바의 자동 생성된 API
프레임워크에서 사용하는 빌드 플래그 식별
먼저 프레임워크를 조건부로 컴파일하는 데 사용되는 빌드 구성을 식별한 다음 사용하지 않는 구성을 포기하여 세트를 축소합니다. 예를 들어 surfaceflinger
에는 다음과 같은 빌드 플래그 세트가 식별됩니다.
TARGET_USES_HWC2
TARGET_BOARD_PLATFORM
TARGET_DISABLE_TRIPLE_BUFFERING
TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS
NUM_FRAMEBUFFER_SURFACE_BUFFERS
TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK
VSYNC_EVENT_PHASE_OFFSET_NS
SF_VSYNC_EVENT_PHASE_OFFSET_NS
PRESENT_TIME_OFFSET_FROM_VSYNC_NS
MAX_VIRTUAL_DISPLAY_DIMENSION
HAL 인터페이스 생성
하위 시스템의 빌드 구성은 HAL 인터페이스를 통해 액세스되고 구성 값을 제공하는 인터페이스는 HAL 패키지 android.hardware.configstore
(현재 버전 1.0)에서 그룹화됩니다.
예를 들어 surfaceflinger
의 HAL 인터페이스 파일을 만들려면 hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal
에서 다음을 실행합니다.
package android.hardware.configstore@1.0; interface ISurfaceFlingerConfigs { // TO-BE-FILLED-BELOW };
.hal
파일을 만들면 hardware/interfaces/update-makefiles.sh
를 실행하여 Android.bp
및 Android.mk
파일에 새 .hal
파일을 추가합니다.
빌드 플래그에 함수 추가
각 빌드 플래그와 관련하여 새 함수를 인터페이스에 추가합니다. 예를 들어 hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal
에서 다음을 실행합니다.
interface ISurfaceFlingerConfigs { disableTripleBuffering() generates(OptionalBool ret); forceHwcForVirtualDisplays() generates(OptionalBool ret); enum NumBuffers: uint8_t { USE_DEFAULT = 0, TWO = 2, THREE = 3, }; numFramebufferSurfaceBuffers() generates(NumBuffers ret); runWithoutSyncFramework() generates(OptionalBool ret); vsyncEventPhaseOffsetNs generates (OptionalUInt64 ret); presentTimeOffsetFromSyncNs generates (OptionalUInt64 ret); maxVirtualDisplayDimension() generates(OptionalInt32 ret); };
함수를 추가하는 경우
- 이름이 간결해야 합니다. makefile 변수 이름을 함수 이름으로 변환하지 않도록 조심하고
TARGET_
및BOARD_
접두사가 더 이상 필요하지 않다는 점에 유의합니다. - 의견을 추가해야 합니다. 개발자가 구성 항목의 용도, 구성 항목에 따른 프레임워크 동작의 변화, 유효한 값과 기타 관련 정보를 이해할 수 있도록 돕습니다.
함수 반환 유형은 Optional[Bool|String|Int32|UInt32|Int64|UInt64]
일 수 있습니다. 유형은 동일한 디렉터리의 types.hal
에 정의되고 값이 HAL에서 지정되는지 나타내는 필드로 프리미티브 값을 래핑합니다. HAL에서 지정되지 않으면 기본값이 사용됩니다.
struct OptionalString { bool specified; string value; };
필요한 경우 구성 항목 유형을 가장 적절하게 나타내는 enum을 정의하고 이 enum을 반환 유형으로 사용합니다. 위 예에서 NumBuffers
enum은 유효한 값의 수를 제한하기 위해 정의됩니다. 이러한 맞춤 데이터 유형을 정의하는 경우 값이 HAL에서 지정되는지 여부를 나타내는 필드나 enum 값(예: USE_DEFAULT
)을 추가합니다.
굳이 단일 빌드 플래그가 HIDL에서 단일 함수가 되어야 할 필요는 없습니다. 모듈 소유자는 밀접하게 연관된 빌드 플래그를 구조로 집계하고 이 구조를 반환하는 함수를 보유할 수 있습니다(이렇게 할 경우 함수 호출 횟수를 줄일 수 있음).
예를 들어 hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal
에서 빌드 플래그 두 개를 단일 구조체로 집계하는 옵션은 다음과 같습니다.
interface ISurfaceFlingerConfigs { // other functions here struct SyncConfigs { OptionalInt64 vsyncEventPhaseoffsetNs; OptionalInt64 presentTimeoffsetFromSyncNs; }; getSyncConfigs() generates (SyncConfigs ret); // other functions here };
단일 HAL 함수의 대안
모든 빌드 플래그에 단일 HAL 함수를 사용하는 것의 대안으로 HAL 인터페이스에서는 getBoolean(string
key)
및 getInteger(string key)
와 같은 간단한 함수도 제공합니다. 실제 key=value
쌍은 별도의 파일에 저장되며 HAL 서비스에서는 이러한 파일을 읽거나 파싱하여 값을 제공합니다.
이러한 접근 방식은 쉽게 정의할 수 있지만 HIDL(향상된 버전 관리, 간편한 문서화, 액세스 제어)에서 제공하는 이점을 내포하지 않으므로 권장되지는 않습니다.
단일 및 다중 인터페이스
구성 항목과 관련된 HAL 인터페이스 디자인에는 두 가지 옵션이 표시됩니다.
- 모든 구성 항목에 적용되는 단일 인터페이스
- 각각 관련 구성 항목 세트에 적용되는 다중 인터페이스
단일 인터페이스는 훨씬 편리하지만 구성 항목이 계속해서 단일 파일에 추가될 경우 관리가 어려울 수 있습니다. 또한 액세스 제어가 세분화되지 않으므로 인터페이스에 대한 액세스를 부여받은 프로세스가 모든 구성 항목을 읽을 수 있습니다(부분적인 구성 항목 세트에 대한 액세스는 부여할 수 없음). 액세스가 부여되지 않은 경우에는 구성 파일을 읽을 수 없습니다.
이러한 문제를 감안하여 Android는 관련 구성 항목 그룹에 단일 HAL 인터페이스를 포함하는 다중 인터페이스를 사용합니다. 예를 들어 surfaceflinger
관련 구성 항목의 경우 ISurfaceflingerConfigs
, 블루투스 관련 구성 항목의 경우 IBluetoothConfigs
입니다.