В Android 8.0 операционная система Android была переработана, чтобы определить четкие интерфейсы между аппаратно-независимой платформой Android и кодом, зависящим от устройства и поставщика. Android уже определил множество таких интерфейсов в форме интерфейсов HAL, определенных как заголовки C в hardware/libhardware
. HIDL заменил эти интерфейсы HAL стабильными интерфейсами с поддержкой версий, которые могут быть либо на Java (описано ниже), либо быть интерфейсами HIDL на стороне клиента и сервера на C++ .
Интерфейсы HIDL предназначены для использования в основном из собственного кода, и в результате HIDL ориентирован на автоматическое создание эффективного кода на C++. Однако интерфейсы HIDL также должны быть доступны для использования непосредственно из Java, поскольку некоторые подсистемы Android (например, телефония) имеют интерфейсы Java HIDL.
На страницах этого раздела описывается интерфейс Java для интерфейсов HIDL, подробно описано, как создавать, регистрировать и использовать службы, а также объясняется, как HAL и клиенты HAL, написанные на Java, взаимодействуют с системой HIDL RPC.
Пример клиента
Это пример клиента для интерфейса IFoo
в пакете android.hardware.foo@1.0
, который зарегистрирован как имя службы 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 или более поздней версии, вы можете статически включить эти библиотеки. Вы также можете использовать (только) классы HIDL из пользовательских JAR-файлов, установленных на устройстве, со стабильными API-интерфейсами Java, доступными с использованием существующего механизма uses-library
для системных приложений. Последний подход экономит место на устройстве. Дополнительные сведения см. в разделе «Реализация библиотеки Java SDK» . Для старых приложений старое поведение сохраняется.
Начиная с Android 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 также больше не доступны в пути к классам загрузки для приложений (ранее они иногда использовались в качестве скрытого API из-за загрузчика классов Android с делегированием). Вместо этого они были перемещены в новое пространство имен с помощью jarjar
, и приложения, которые их используют (обязательно приватные приложения), должны иметь свои отдельные копии. Модули в пути к классам загрузки, использующие HIDL, должны использовать поверхностные варианты этих библиотек Java и добавлять jarjar_rules: ":framework-jarjar-rules"
в свой Android.bp
, чтобы использовать версию этих библиотек, существующую в пути к классам загрузки.
Измените исходный код 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.
Для интерфейса IFooCallback
в версии 1.0 пакета android.hardware.foo
вы можете реализовать свой интерфейс на Java, выполнив следующие шаги:
- Определите свой интерфейс в HIDL.
- Откройте
/tmp/android/hardware/foo/IFooCallback.java
в качестве ссылки. - Создайте новый модуль для вашей реализации 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
, который инкапсулирует интерфейс Java, код прокси и заглушки (оба прокси-сервера и заглушки соответствуют интерфейсу).
-Lmakefile
генерирует правила, которые запускают эту команду во время сборки, и позволяют вам включать android.hardware.foo-V1.0-java
и ссылаться на соответствующие файлы. Сценарий, который автоматически делает это для проекта, полного интерфейсов, можно найти по адресу hardware/interfaces/update-makefiles.sh
. Пути в этом примере являются относительными; Аппаратное обеспечение/интерфейсы могут быть временным каталогом в вашем дереве кода, чтобы вы могли разработать HAL перед его публикацией.
Запустить службу
HAL предоставляет интерфейс IFoo
, который должен выполнять асинхронные обратные вызовы к платформе через интерфейс IFooCallback
. Интерфейс IFooCallback
не зарегистрирован по имени как обнаруживаемая служба; вместо этого IFoo
должен содержать такой метод, как setFooCallback(IFooCallback x)
.
Чтобы настроить IFooCallback
из версии 1.0 пакета android.hardware.foo
, добавьте 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 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);
Расширения интерфейса
Предполагая, что данная служба реализует интерфейс IFoo
на всех устройствах, возможно, что на конкретном устройстве служба может предоставлять дополнительные возможности, реализованные в расширении интерфейса IBetterFoo
, а именно:
interface IFoo { ... }; interface IBetterFoo extends IFoo { ... };
Вызов кода, знающего о расширенном интерфейсе, может использовать 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. }