Google is committed to advancing racial equity for Black communities. See how.
本頁面由 Cloud Translation API 翻譯而成。
Switch to English

HIDL Java

Android 8.0重新設計了Android OS,以在獨立於設備的Android平台與特定於設備和供應商的代碼之間定義清晰的接口。 Android已經以HAL接口的形式定義了許多此類接口,這些接口在hardware/libhardware定義為C頭。 HIDL用穩定的版本化接口替換了這些HAL接口,這些接口可以使用Java(如下所述)或C ++中的客戶端和服務器端HIDL接口。

HIDL接口主要用於本機代碼,因此HIDL專注於自動生成C ++中的高效代碼。但是,HIDL接口也必須能夠直接從Java使用,因為某些Android子系統(例如Telephony)很可能具有Java HIDL接口。

本節中的頁面描述了HIDL接口的Java前端,詳細介紹瞭如何創建,註冊和使用服務,並解釋了用Java編寫的HAL和HAL客戶端如何與HIDL RPC系統交互。

成為客戶

這是android.hardware.foo@1.0包中接口IFoo的客戶端示例,該接口已註冊為服務名稱default和具有自定義服務名稱second_impl的其他服務。

添加庫

如果要使用它,則需要在相應的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及更高版本的系統/供應商應用,則必須靜態包含這些庫。對於較舊的應用程序,將保留舊的行為。另外,也可以僅使用安裝在設備上的自定義JAR中的HIDL類,並使用通過系統應用程序的現有uses-library機制提供的穩定Java API。為了節省設備空間,建議使用此方法。有關更多詳細信息,請參見實現Java SDK庫

從10開始,這些庫的“淺”版本也可用。這些包括相關的類,但不包括任何依賴類。例如, android.hardware.foo-V1.0-java-shallow在foo包中包含類,但在android.hidl.base-V1.0-java中不包括類,該類包含所有HIDL的基類接口。如果要創建的庫已經具有首選接口的基類作為依賴項,則可以使用以下庫:

// 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的引導類路徑上的模塊需要使用這些庫的淺變體,並在其Android.bp中添加jarjar_rules: ":framework-jarjar-rules" ,以避免重複的代碼並使系統/供應商應用使用隱藏的API 。

修改您的Java源代碼

該服務只有一個版本( @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(…);

提供服務

Java中的框架代碼可能需要服務接口才能從HAL接收異步回調。

對於android.hardware.foo軟件包1.0版中的IFooCallback接口,您可以使用以下步驟在Java中實現您的接口:

  1. 在HIDL中定義您的界面。
  2. 打開/tmp/android/hardware/foo/IFooCallback.java作為參考。
  3. 為您的Java實現創建一個新模塊。
  4. 檢查抽像類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 ,該文件封裝了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() Java方法將基本接口安全地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.
}