Google 致力于为黑人社区推动种族平等。查看具体举措
Trang này được dịch bởi Cloud Translation API.
Switch to English

HIDL Java

Android 8.0 đã tái cấu trúc hệ điều hành Android để xác định các giao diện rõ ràng giữa nền tảng Android độc lập với thiết bị và mã dành riêng cho thiết bị và nhà cung cấp. Android đã định nghĩa nhiều giao diện như vậy ở dạng giao diện HAL, được định nghĩa là tiêu đề C trong hardware/libhardware . HIDL đã thay thế các giao diện HAL này bằng các giao diện ổn định, có phiên bản, có thể là trong Java (được mô tả bên dưới) hoặc là giao diện HIDL phía máy khách và phía máy chủ trong C ++ .

Các giao diện HIDL nhằm mục đích sử dụng chủ yếu từ mã gốc và do đó HIDL tập trung vào việc tự động tạo mã hiệu quả trong C ++. Tuy nhiên, giao diện HIDL cũng phải có thể được sử dụng trực tiếp từ Java vì một số hệ thống con Android (chẳng hạn như Telephony) rất có thể sẽ có giao diện HIDL Java.

Các trang trong phần này mô tả giao diện người dùng Java cho các giao diện HIDL, trình bày chi tiết cách tạo, đăng ký và sử dụng các dịch vụ cũng như giải thích cách các ứng dụng khách HAL và HAL được viết bằng Java tương tác với hệ thống HIDL RPC.

Là khách hàng

Đây là một ví dụ về một ứng dụng khách cho IFoo giao diện trong gói android.hardware.foo@1.0 được đăng ký làm default tên dịch vụ và một dịch vụ bổ sung với tên dịch vụ tùy chỉnh second_impl .

Thêm thư viện

Bạn cần thêm các phần phụ thuộc vào thư viện sơ khai HIDL tương ứng nếu bạn muốn sử dụng nó. Thông thường, đây là một thư viện tĩnh:

// in Android.bp
static_libs: [ "android.hardware.foo-V1.0-java", ],
// in Android.mk
LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java

Nếu bạn biết rằng bạn đang kéo các phụ thuộc vào các thư viện này, bạn cũng có thể sử dụng liên kết được chia sẻ:

// in Android.bp
libs: [ "android.hardware.foo-V1.0-java", ],
// in Android.mk
LOCAL_JAVA_LIBRARIES += android.hardware.foo-V1.0-java

Cân nhắc bổ sung để thêm thư viện trong Android 10

Nếu bạn có ứng dụng hệ thống / nhà cung cấp nhắm mục tiêu Android 10 trở lên, bạn phải đưa vào tĩnh các thư viện này. Đối với các ứng dụng cũ hơn, hành vi cũ được giữ nguyên. Ngoài ra, có thể chỉ sử dụng các lớp HIDL từ các JAR tùy chỉnh được cài đặt trên thiết bị với các API Java ổn định được cung cấp bằng cách uses-library cơ chế uses-library hiện có cho các ứng dụng hệ thống. Để tiết kiệm dung lượng trên thiết bị, đây là cách tiếp cận được khuyến nghị. Để biết thêm chi tiết, hãy xem Triển khai Thư viện SDK Java .

Bắt đầu từ 10, phiên bản "nông" của các thư viện này cũng có sẵn. Chúng bao gồm lớp được đề cập nhưng không bao gồm bất kỳ lớp phụ thuộc nào. Ví dụ: android.hardware.foo-V1.0-java-shallow bao gồm các lớp trong gói foo, nhưng không bao gồm các lớp trong android.hidl.base-V1.0-java , chứa lớp cơ sở của tất cả HIDL các giao diện. Nếu bạn đang tạo một thư viện đã có sẵn các lớp cơ sở của giao diện ưa thích dưới dạng phụ thuộc, bạn có thể sử dụng như sau:

// 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

Thư viện trình quản lý và cơ sở HIDL cũng không còn có sẵn trên đường dẫn khởi động. Thay vào đó, chúng đã được chuyển sang một không gian tên mới với jarjar . Các mô-đun trên classpath khởi động sử dụng HIDL cần sử dụng các biến thể nông của các thư viện đó cũng như thêm jarjar_rules: ":framework-jarjar-rules" vào Android.bp của chúng để tránh mã trùng lặp và ứng dụng hệ thống / nhà cung cấp sử dụng API ẩn .

Sửa đổi nguồn Java của bạn

Chỉ có một phiên bản ( @1.0 ) của dịch vụ này, vì vậy mã này chỉ truy xuất phiên bản đó. Xem phần mở rộng giao diện để biết cách xử lý nhiều phiên bản khác nhau của dịch vụ.

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(…);

Cung cấp một dịch vụ

Mã khung trong Java có thể cần cung cấp các giao diện để nhận các lệnh gọi lại không đồng bộ từ HAL.

Đối với giao diện IFooCallback trong phiên bản 1.0 của gói android.hardware.foo , bạn có thể triển khai giao diện của mình trong Java bằng các bước sau:

  1. Xác định giao diện của bạn trong HIDL.
  2. Mở /tmp/android/hardware/foo/IFooCallback.java làm tham chiếu.
  3. Tạo một mô-đun mới để triển khai Java của bạn.
  4. Kiểm tra lớp trừu tượng android.hardware.foo.V1_0.IFooCallback.Stub , sau đó viết một lớp mới để mở rộng nó và triển khai các phương thức trừu tượng.

Xem các tệp được tạo tự động

Để xem các tệp được tạo tự động, hãy chạy:

hidl-gen -o /tmp -Ljava \
  -randroid.hardware:hardware/interfaces \
  -randroid.hidl:system/libhidl/transport android.hardware.foo@1.0

Các lệnh này tạo thư mục /tmp/android/hardware/foo/1.0 . Đối với hardware/interfaces/foo/1.0/IFooCallback.hal tệp hardware/interfaces/foo/1.0/IFooCallback.hal , điều này tạo ra tệp /tmp/android/hardware/foo/1.0/IFooCallback.java , đóng gói giao diện Java, mã proxy và các bản gốc (cả hai proxy và sơ khai phù hợp với giao diện).

-Lmakefile tạo các quy tắc chạy lệnh này tại thời điểm xây dựng và cho phép bạn bao gồm android.hardware.foo-V1.0-java và liên kết với các tệp thích hợp. Bạn có thể tìm thấy tập lệnh tự động thực hiện việc này cho một dự án có đầy đủ các giao diện tại hardware/interfaces/update-makefiles.sh . Các đường dẫn trong ví dụ này là tương đối; phần cứng / giao diện có thể là một thư mục tạm thời trong cây mã của bạn để cho phép bạn phát triển HAL trước khi xuất bản nó.

Chạy một dịch vụ

HAL cung cấp giao diện IFoo , giao diện này phải thực hiện các lệnh gọi lại không đồng bộ tới khuôn khổ qua giao diện IFooCallback . Giao diện IFooCallback không được đăng ký theo tên như một dịch vụ có thể khám phá; thay vào đó, IFoo phải chứa một phương thức như setFooCallback(IFooCallback x) .

Để thiết lập IFooCallback từ phiên bản 1.0 của gói android.hardware.foo , hãy thêm android.hardware.foo-V1.0-java vào Android.mk . Mã để chạy dịch vụ là:

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);

Phần mở rộng giao diện

Giả sử một dịch vụ nhất định triển khai giao diện IFoo trên tất cả các thiết bị, có thể trên một thiết bị cụ thể, dịch vụ có thể cung cấp các khả năng bổ sung được triển khai trong phần mở rộng giao diện IBetterFoo , như sau:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

Gọi mã nhận biết về giao diện mở rộng có thể sử dụng phương thức castFrom() Java để truyền giao diện cơ sở sang giao diện mở rộng một cách an toàn:

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.
}