Android O изменяет архитектуру ОС Android, чтобы определить четкие интерфейсы между независимой от устройства платформой Android и кодом, зависящим от устройства и производителя. Android уже определяет многие такие интерфейсы в виде интерфейсов HAL, определенных как заголовки C в hardware/libhardware
. HIDL заменяет эти интерфейсы HAL стабильными интерфейсами с поддержкой версий, которые могут быть интерфейсами HIDL на стороне клиента и на стороне сервера на C ++ (описанном ниже) или Java .
Страницы в этом разделе описывают C ++ реализаций HIDL интерфейсов, включая информацию о файлах автоматически сгенерированных из HIDL .hal
файлов по hidl-gen
компилятору, как эти файлы упакованы, и как интегрировать эти файлы с C ++ код, использует их.
Реализации клиента и сервера
Интерфейсы HIDL имеют клиентские и серверные реализации:
- Клиент интерфейса HIDL - это код, который использует интерфейс, вызывая на нем методы.
- Сервер - это реализация интерфейса HIDL, который принимает вызовы от клиентов и возвращает результаты (при необходимости).
При переходе от libhardware
HAL к HIDL HAL реализация HAL становится сервером, а процесс, вызывающий HAL, становится клиентом. Реализации по умолчанию могут обслуживать как сквозные, так и объединенные в биндеры HAL и могут со временем меняться:
Рисунок 1. Ход разработки устаревших HAL.
Создание клиента HAL
Начните с включения библиотек HAL в make-файл:
- Сделайте:
LOCAL_SHARED_LIBRARIES += android.hardware.nfc@1.0
-
shared_libs: [ …, android.hardware.nfc@1.0 ]
:shared_libs: [ …, android.hardware.nfc@1.0 ]
Затем включите файлы заголовков HAL:
#include <android/hardware/nfc/1.0/IFoo.h> … // in code: sp<IFoo> client = IFoo::getService(); client->doThing();
Создание HAL-сервера
Чтобы создать реализацию HAL, у вас должны быть файлы .hal
, представляющие ваш HAL, и уже сгенерированные make-файлы для вашего HAL с помощью -Lmakefile
или -Landroidbp
на hidl-gen
( ./hardware/interfaces/update-makefiles.sh
делает это для внутренние файлы HAL и являются хорошей справочной информацией). При переносе HAL из libhardware
вы можете легко выполнить большую часть этой работы с помощью c2hal.
Чтобы создать файлы, необходимые для реализации вашего HAL:
PACKAGE=android.hardware.nfc@1.0 LOC=hardware/interfaces/nfc/1.0/default/ m -j hidl-gen hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport $PACKAGE hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces \ -randroid.hidl:system/libhidl/transport $PACKAGE
Для HAL на работу в проходном режими, вы должны иметь функцию HIDL_FETCH_IModuleName проживающую в /(system|vendor|...)/lib(64)?/hw/android.hardware.package@3.0-impl( OPTIONAL_IDENTIFIER ).so
где OPTIONAL_IDENTIFIER - это строка, определяющая реализацию сквозной передачи. Приведенные выше команды автоматически удовлетворяют требованиям режима сквозной передачи, которые также создают цель android.hardware.nfc@1.0-impl
, но можно использовать любое расширение. Например, android.hardware.nfc@1.0-impl-foo
использует -foo
чтобы отличаться.
Если HAL является дополнительной версией или расширением другого HAL, для имени этого двоичного файла следует использовать базовый HAL. Например, реализации android.hardware.graphics.mapper@2.1
должны по-прежнему находиться в двоичном android.hardware.graphics.mapper@2.0-impl( OPTIONAL_IDENTIFIER )
именем android.hardware.graphics.mapper@2.0-impl( OPTIONAL_IDENTIFIER )
. Обычно OPTIONAL_IDENTIFIER здесь включает фактическую версию HAL. Называя двоичный файл таким образом, клиенты версии 2.0 могут получать его напрямую, а клиенты версии 2.1 могут улучшать реализацию.
Затем заполните заглушки функциональностью и установите демон. Пример кода демона (поддерживающий сквозную передачу):
#include <hidl/LegacySupport.h> int main(int /* argc */, char* /* argv */ []) { return defaultPassthroughServiceImplementation<INfc>("nfc"); }
defaultPassthroughServiceImplementation
будет dlopen()
предоставленной библиотеки -impl
и предоставит ее как биндиризированный сервис. Пример кода демона (для чисто биндеризованной службы):
int main(int /* argc */, char* /* argv */ []) { // This function must be called before you join to ensure the proper // number of threads are created. The threadpool will never exceed // size one because of this call. ::android::hardware::configureRpcThreadpool(1 /*threads*/, true /*willJoin*/); sp<INfc> nfc = new Nfc(); const status_t status = nfc->registerAsService(); if (status != ::android::OK) { return 1; // or handle error } // Adds this thread to the threadpool, resulting in one total // thread in the threadpool. We could also do other things, but // would have to specify 'false' to willJoin in configureRpcThreadpool. ::android::hardware::joinRpcThreadpool(); return 1; // joinRpcThreadpool should never return }
Этот демон обычно живет в $PACKAGE + "-service-suffix"
(например, android.hardware.nfc@1.0-service
), но он может быть где угодно. Политика для определенного класса HAL - это атрибут hal_<module>
(например, hal_nfc)
. Этот атрибут должен применяться к демону, запускающему конкретный HAL (если один и тот же процесс обслуживает несколько HAL, к нему можно применить несколько атрибутов).