Google cam kết thúc đẩy công bằng chủng tộc cho Cộng đồng người da đen. Xem cách thực hiện.

HIDL Java

Trong Android 8.0, hệ điều hành Android đã được tái cấu trúc để 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 đã được xác định nhiều giao diện như vậy trong các hình thức của giao diện HAL, định nghĩa là header C trong hardware/libhardware . HIDL thay thế các giao diện HAL với ổn định, giao diện phiên bản, trong đó một trong hai có thể ở Java (được mô tả dưới đây) hoặc được khách hàng- và server-side giao diện HIDL trong C ++ .

Các giao diện HIDL được thiết kế để 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, giao diện HIDL cũng phải có sẵn để sử dụng trực tiếp từ Java, vì một số hệ thống con Android (chẳng hạn như Telephony) 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à một khách hàng

Đây là một ví dụ về một khách hàng cho một giao diện IFoo trong gói android.hardware.foo@1.0 được đăng ký dưới dạng 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ầ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 lấy 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ó hệ thống hoặc ứng dụng của nhà cung cấp nhắm mục tiêu Android 10 trở lên, bạn có thể đưa vào tĩnh các thư viện này. Bạn cũng có thể sử dụng (chỉ) lớp HIDL từ lọ tùy chỉnh cài đặt trên thiết bị với ổn định Java API làm sẵn bằng cách sử dụng hiện có uses-library cơ chế cho các ứng dụng hệ thống. Cách tiếp cận thứ hai giúp tiết kiệm dung lượng trên thiết bị. Để biết thêm chi tiết, xem Triển khai thư viện Java SDK . Đối với các ứng dụng cũ hơn, hành vi cũ được giữ nguyên.

Bắt đầu từ Android 10, các 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 học trong android.hidl.base-V1.0-java , chứa các lớp cơ sở của tất cả cá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 cơ sở và trình quản lý HIDL cũng không còn khả dụng trên đường dẫn khởi động cho ứng dụng (trước đây, chúng đôi khi được sử dụng làm API ẩn, do trình tải lớp đầu tiên dành cho đại biểu của Android). Thay vào đó, họ đã được chuyển thành một không gian tên mới với jarjar , và các ứng dụng mà sử dụng các (ứng dụng thiết priv) phải có bản sao riêng của họ. Mô-đun trên classpath boot dùng HIDL phải sử dụng cạn biến thể của các thư viện Java và thêm jarjar_rules: ":framework-jarjar-rules" để họ Android.bp sử dụng phiên bản của các thư viện này tồn tại trong classpath khởi động.

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, do đó, mã này lấy chỉ phiên bản đó. Xem phần mở rộng giao diện cho làm thế nào để 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 IFooCallback giao diện trong phiên bản 1.0 của android.hardware.foo gói, bạn có thể thực hiện giao diện của bạn trong Java sử dụ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 như một 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 các 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 pháp 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

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

-Lmakefile tạo ra các quy tắc mà chạy lệnh này ở thời gian xây dựng và cho phép bạn bao gồm android.hardware.foo-V1.0-java và liên kết chống lại các tập tin 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 đầ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 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 IFoo giao diện, mà phải làm cho callbacks không đồng bộ để khuôn khổ qua IFooCallback giao diện. Các IFooCallback giao diện không được đăng ký theo tên như một dịch vụ có thể phát hiện; thay vào đó, IFoo phải chứa một phương pháp như setFooCallback(IFooCallback x) .

Để thiết lập IFooCallback từ phiên bản 1.0 của android.hardware.foo gói, thêm android.hardware.foo-V1.0-java để 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 from which you will be receiving callbacks.
// 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ụng cụ phục vụ cho các IFoo giao diện trên tất cả các thiết bị, có thể là trên một thiết bị đặc biệt là các dịch vụ có thể cung cấp khả năng bổ sung thực hiện trong phần mở rộng giao diện IBetterFoo , như sau:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

Gọi mã ý thức của giao diện mở rộng có thể sử dụng castFrom() phương pháp Java để đúc một cách an toàn các giao diện cơ sở để giao diện mở rộng:

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