Google is committed to advancing racial equity for Black communities. See how.
Эта страница переведена с помощью Cloud Translation API.
Switch to English

HIDL Java

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 для системных приложений. Это рекомендуемый подход для экономии места на устройстве. Дополнительные сведения см. В разделе « Реализация библиотеки SDK для Java» .

Начиная с версии 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, должны использовать неглубокие варианты этих библиотек, а также добавить jarjar_rules: ":framework-jarjar-rules" в свой Android.bp , чтобы избежать дублирования кода и использования скрытых 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.

Для интерфейса IFooCallback в версии 1.0 пакета android.hardware.foo вы можете реализовать свой интерфейс на 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) .

Чтобы настроить 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 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 {
   ...
};

Вызывающий код, осведомленный о расширенном интерфейсе, может использовать Java-метод castFrom() для безопасного 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.
}