HAL 인터페이스 생성

프레임워크를 조건부로 컴파일하는 데 사용되는 모든 빌드 플래그를 설명하려면 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.bpAndroid.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입니다.