Android 8.0은 Android OS를 다시 설계하여 기기 독립적 Android 플랫폼과 기기별 코드 및 공급업체별 코드 간의 명확한 인터페이스를 정의합니다.
Android는 hardware/libhardware
에 C 헤더로 정의된 HAL 인터페이스의 형태로 이미 많은 인터페이스를 정의했습니다. HIDL은 이러한 HAL 인터페이스를 C++의 클라이언트 측 및 서버 측 HIDL 인터페이스 또는 아래 설명된 자바의 안정적인 버전 인터페이스로 대체했습니다.
HIDL 인터페이스는 기본적으로 네이티브 코드에서 사용하기 위한 것이므로 HIDL은 C ++에서 효율적인 코드를 자동 생성하는 데 중점을 둡니다. 하지만 일부 Android 하위 시스템(예 : 전화 통신)이 자바 HIDL 인터페이스를 가질 가능성이 높기 때문에 HIDL 인터페이스를 자바에서 직접 사용할 수 있어야 합니다.
이 섹션의 페이지는 HIDL 인터페이스의 자바 프런트엔드를 설명하고 서비스를 생성, 등록 및 사용하는 방법을 상세히 다루며 자바에서 작성된 HAL 및 HAL 클라이언트가 HIDL RPC 시스템과 상호작용하는 방법을 설명합니다.
클라이언트
다음은 서비스 이름은 default
이며 추가 서비스의 맞춤 서비스 이름은 second_impl
로 등록되어 있는 android.hardware.foo@1.0
패키지의 IFoo
인터페이스를 위한 클라이언트의 예입니다.
라이브러리 추가
이를 사용하려면 상응하는 HIDL 스터브 라이브러리에 종속 항목을 추가해야 합니다. 보통 이는 정적 라이브러리입니다.
// in Android.bp static_libs: [ "android.hardware.foo-V1.0-java", ], // in Android.mk LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java
이미 이러한 라이브러리에서 종속 항목을 가져오고 있다면 공유 연결을 사용할 수도 있습니다.
// in Android.bp libs: [ "android.hardware.foo-V1.0-java", ], // in Android.mk LOCAL_JAVA_LIBRARIES += android.hardware.foo-V1.0-java
Android 10에서 라이브러리를 추가할 때 추가적으로 고려할 사항
Android 10 이상을 타겟팅하는 시스템/공급업체 앱이 있는 경우 이러한 라이브러리를 정적으로 포함해야 합니다. 이전 앱의 경우 이전 동작은 그대로 유지됩니다. 또는 안정화 자바 API가 있는 기기에 설치된 맞춤 JAR의 HIDL 클래스만 사용할 수도 있습니다. 이 API는 기존의 시스템 앱용 uses-library
메커니즘을 통해 이용할 수 있습니다. 기기의 공간을 절약하려면 이 방법을 사용하는 것이 좋습니다. 자세한 내용은 자바 SDK 라이브러리 구현을 참조하세요.
Android 10부터 이 라이브러리의 '얕은' 버전을 사용할 수 있습니다. 이러한 버전에는 문제의 클래스가 있지만 종속 클래스는 포함되지 않습니다. 예를 들어 android.hardware.foo-V1.0-java-shallow
는 foo 패키지의 클래스를 포함하지만 모든 HIDL 인터페이스의 기본 클래스를 포함하는 android.hidl.base-V1.0-java
의 클래스는 포함하지 않습니다. 선호하는 인터페이스의 기본 클래스를 종속 항목으로 포함하는 라이브러리를 만드는 경우 다음을 사용할 수 있습니다.
// in Android.bp static_libs: [ "android.hardware.foo-V1.0-java-shallow", ], // in Android.mk LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java-shallow
또한 HIDL 기본 및 관리자 라이브러리는 더 이상 부트 클래스 경로에서 사용할 수 없습니다. 대신 jarjar
를 사용하여 새 네임스페이스로 이동하였습니다. HIDL을 사용하는 부팅 클래스 경로의 모듈은 코드의 중복을 피하고 시스템/공급업체 앱에서 숨겨진 API를 사용하도록 라이브러리의 얕은 변형을 사용하고 Android.bp
에 jarjar_rules: ":framework-jarjar-rules"
를 추가해야 합니다.
자바 소스 수정
이 서비스의 버전(@1.0
)은 하나뿐이므로 다음 코드는 이 버전만 검색합니다. 여러 버전의 서비스를 처리하는 방법은 인터페이스 확장을 참조하세요.
import android.hardware.foo.V1_0.IFoo; ... // retry to wait until the service starts up if it is in the manifest IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available IFoo anotherServer = IFoo.getService("second_impl", true /* retry */); server.doSomething(…);
서비스 제공
자바의 프레임워크 코드는 HAL에서 비동기 콜백을 수신하는 인터페이스를 제공해야 할 수 있습니다.
android.hardware.foo
패키지 버전 1.0의 IFooCallback
인터페이스는 다음 단계에 따라 자바에서 인터페이스를 구현할 수 있습니다.
- 인터페이스를 HIDL로 정의합니다.
/tmp/android/hardware/foo/IFooCallback.java
를 참조로 엽니다.- 자바 구현을 위한 새 모듈을 만듭니다.
- 추상 클래스
android.hardware.foo.V1_0.IFooCallback.Stub
를 검토한 다음 이를 확장하는 새 클래스를 작성하고 추상 메서드를 구현합니다.
자동 생성된 파일 보기
자동으로 생성된 파일을 보려면 다음을 실행합니다.
hidl-gen -o /tmp -Ljava \ -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport android.hardware.foo@1.0
이 명령어는 /tmp/android/hardware/foo/1.0
디렉터리를 생성합니다. hardware/interfaces/foo/1.0/IFooCallback.hal
파일의 경우 자바 인터페이스, 프록시 코드, 스터브를 캡슐화하는 /tmp/android/hardware/foo/1.0/IFooCallback.java
파일을 생성합니다. (프록시와 스터브는 인터페이스를 따라야 합니다.)
-Lmakefile
은 빌드 시 이 명령어를 실행하는 규칙을 생성하고 android.hardware.foo-V1.0-java
를 포함하여 적절한 파일에 링크할 수 있도록 합니다. 인터페이스로 가득한 프로젝트를 위해 이 작업을 자동으로 처리하는 스크립트는 hardware/interfaces/update-makefiles.sh
에 있습니다.
이 예에서 경로는 상대적입니다. 하드웨어/인터페이스는 게시하기 전에 HAL을 개발할 수 있도록 코드 트리에서 임시 디렉터리일 수 있습니다.
서비스 실행
HAL은 IFoo
인터페이스를 제공하며, 이 인터페이스는 IFooCallback
인터페이스를 통한 프레임워크로 비동기 콜백을 만들어야 합니다. IFooCallback
인터페이스는 검색 가능한 서비스로 이름이 등록되지 않습니다. 대신 IFoo
는 setFooCallback(IFooCallback x)
과 같은 메서드를 포함해야 합니다.
android.hardware.foo
패키지 버전 1.0에서 IFooCallback
을 설정하려면 android.hardware.foo-V1.0-java
를 Android.mk
에 추가하세요. 서비스를 실행하는 코드는 다음과 같습니다.
import android.hardware.foo.V1_0.IFoo; import android.hardware.foo.V1_0.IFooCallback.Stub; .... class FooCallback extends IFooCallback.Stub { // implement methods } .... // Get the service you will be receiving callbacks from. // This also starts the threadpool for your callback service. IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available .... // This must be a persistent instance variable, not local, // to avoid premature garbage collection. FooCallback mFooCallback = new FooCallback(); .... // Do this once to create the callback service and tell the "foo-bar" service server.setFooCallback(mFooCallback);
인터페이스 확장
어떤 서비스가 모든 기기에서 IFoo
인터페이스를 구현한다고 가정하면 이 서비스는 특정 기기에서 다음과 같이 확장 인터페이스 IBetterFoo
에 추가 기능을 구현하여 제공할 수 있습니다.
interface IFoo { ... }; interface IBetterFoo extends IFoo { ... };
이러한 확장 인터페이스를 인식하는 호출 코드에서는 castFrom()
자바 메서드를 사용하여 기본 인터페이스를 확장 인터페이스로 안전하게 전송할 수 있습니다.
IFoo baseService = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available IBetterFoo extendedService = IBetterFoo.castFrom(baseService); if (extendedService != null) { // The service implements the extended interface. } else { // The service implements only the base interface. }