Google cam kết thúc đẩy công bằng chủng tộc cho các cộng đồng Đen. Xem thế nào.
Trang này được dịch bởi Cloud Translation API.
Switch to English

HIDL Java

Android 8.0 đã kiến ​​trúc lại 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 nhà cung cấp và thiết bị. Android đã định nghĩa nhiều giao diện như vậy dưới dạng giao diện HAL, được định nghĩa là các 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ể bằng Java (được mô tả bên dưới) hoặc như các giao diện HIDL phía máy khách và máy chủ trong C ++ .

Các giao diện HIDL được dự định sẽ được sử dụng chủ yếu từ mã gốc và kết quả là HIDL tập trung vào việc tự động tạo mã hiệu quả trong C ++. Tuy nhiên, các 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 (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 Java cho giao diện HIDL, chi tiết cách tạo, đăng ký và sử dụng dịch vụ và giải thích cách các máy khách HAL và HAL được viết bằng Java tương tác với hệ thống RPC HIDL.

Là khách hàng

Đây là một ví dụ về ứng dụng khách cho giao diện IFoo trong gói android.hardware.foo@1.0 được đăng ký làm tên dịch vụ default 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ụ 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 bạn đã 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 bao gồm tĩnh các thư viện này. Đối với các ứng dụng cũ, hành vi cũ được bảo tồ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 hiện có cho các ứng dụng hệ thống. Để tiết kiệm không gian trên thiết bị, đây là phương pháp đượ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 các lớp trong câu hỏi nhưng không bao gồm bất kỳ các lớp phụ thuộc. 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 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

Các thư viện 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 vào một không gian tên mới với jarjar . Các mô-đun trên đường dẫn 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 họ để tránh mã trùng lặp và có ứ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 dịch vụ

Mã khung trong Java có thể cần phục vụ các giao diện để nhận các cuộc 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 tài liệu tham khảo.
  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à thực hiện các phương thức trừu tượng.

Xem các tập tin đượ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 này tạo tệp /tmp/android/hardware/foo/1.0/IFooCallback.java , đóng gói giao diện Java, mã proxy và sơ khai (cả 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 khi 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. Một kịch bản tự động thực hiện điều này cho một dự án có đầy đủ các giao diện có thể được tìm thấy 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 dưới 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ó.

Điều hành một dịch vụ

HAL cung cấp giao diện IFoo , phải thực hiện các cuộc gọi lại không đồng bộ tới khung trên 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);

Giao diện mở rộng

Giả sử một dịch vụ cụ thể thực hiện 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 tiện ích 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 Java castFrom() để 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.
}