HIDL

Язык определения интерфейса HAL или HIDL (произносится «hide-l») - это язык описания интерфейса (IDL) для определения интерфейса между HAL и его пользователями. Он позволяет указывать типы и вызовы методов, собираемых в интерфейсы и пакеты. В более широком смысле HIDL - это система для обмена данными между кодовыми базами, которая может быть скомпилирована независимо. Начиная с Android 10, HIDL устарел, и Android переходит на использование AIDL повсюду.

HIDL предназначен для использования для межпроцессного взаимодействия (IPC). Связь между процессами называется Binderized . Для библиотек , которые должны быть связаны с процессом, Сквозной режим также доступен (не поддерживается в Java).

HIDL определяет структуры данных и сигнатуры методов, организованные в интерфейсах (аналогично классу), которые собираются в пакеты. Синтаксис HIDL покажется знакомым программистам на C ++ и Java, хотя и с другим набором ключевых слов. HIDL также использует аннотации в стиле Java.

Дизайн HIDL

Цель HIDL состоит в том, чтобы можно было заменить фреймворк без необходимости перестраивать HAL. , HAL будет построен поставщиками или SOC производителями и положить в /vendor раздел на устройстве, что позволяет рамки, в отдельном разделе, чтобы заменить ОТ без перекомпиляции Хальса.

Дизайн HIDL уравновешивает следующие проблемы:

  • Interoperability. Создавайте надежно взаимодействующие интерфейсы между процессами, которые могут быть скомпилированы с различными архитектурами, инструментами и конфигурациями сборки. Интерфейсы HIDL имеют версии и не могут быть изменены после публикации.
  • Эффективность. HIDL пытается минимизировать количество операций копирования. Данные, определенные HIDL, доставляются в код C ++ в структурах данных стандартной компоновки C ++, которые можно использовать без распаковки. HIDL также предоставляет интерфейсы с общей памятью, и, поскольку RPC по своей природе несколько медленны, HIDL поддерживает два способа передачи данных без использования вызова RPC: общая память и Fast Message Queue (FMQ).
  • Интуитивно. HIDL избегает колючие вопросы собственности памяти, используя только in параметрах RPC (см Определение Android Язык интерфейса (AIDL) ); значения, которые не могут быть эффективно возвращены из методов, возвращаются через функции обратного вызова. Ни передача данных в HIDL для передачи, ни получение данных из HIDL не изменяет владельца данных - право собственности всегда остается за вызывающей функцией. Данные должны сохраняться только на время вызываемой функции и могут быть уничтожены сразу после возврата из вызываемой функции.

Использование режима сквозной передачи

Чтобы обновить устройства, работающие под управлением более ранних версий Android, до Android O, вы можете обернуть как обычные (и устаревшие) HAL в новый интерфейс HIDL, который обслуживает HAL в биндеризованном и одном процессном (сквозном) режимах. Эта упаковка прозрачна как для HAL, так и для платформы Android.

Режим сквозной передачи доступен только для клиентов и реализаций C ++. Устройства, работающие под управлением более ранних версий Android, не имеют HAL, написанных на Java, поэтому Java HAL по своей сути биндеризированы.

Когда .hal файл компилируется, hidl-gen производит дополнительный сквозной файл заголовок BsFoo.h в дополнении к заголовкам , используемым для связующей связи; определяет заголовок функции будет dlopen ред. Поскольку сквозные HAL выполняются в том же процессе, в котором они вызываются, в большинстве случаев сквозные методы вызываются прямым вызовом функции (тот же поток). oneway методы работы в их собственном потоке , поскольку они не предназначены ждать HAL для их обработки (это означает любое HAL , который использует oneway методов в проходное режиме должен быть поточно-).

Учитывая IFoo.hal , BsFoo.h обертывание HIDL сгенерированных метод , чтобы обеспечить дополнительные функции (например, делая oneway операции выполняются в другом потоке). Этот файл похож на BpFoo.h , однако вместо передачи на вызовы IPC с использованием связующего вещества, требуемые функции непосредственно вызываются. Будущие реализации HALS может обеспечить несколько реализаций, например, FooFast HAL и HAL FooAccurate. В таких случаях, файл для каждой дополнительной реализации будет создан (например, PTFooFast.cpp и PTFooAccurate.cpp ).

Биндеризация транзитных HAL

Вы можете объединить реализации HAL, поддерживающие режим сквозной передачи. Учитывая HAL интерфейс abcd@MN::IFoo , два пакета созданы:

  • abcd@MN::IFoo-impl . Содержит реализацию HAL и обнажает функционировать IFoo* HIDL_FETCH_IFoo(const char* name) . На старых устройствах, этот пакет dlopen редактора и реализация конкретизируется с помощью HIDL_FETCH_IFoo . Вы можете создать базовый код , используя hidl-gen и -Lc++-impl и -Landroidbp-impl .
  • abcd@MN::IFoo-service . Открывает транзитный HAL и регистрирует себя как биндеризованную службу, позволяя использовать одну и ту же реализацию HAL как в сквозной, так и в биндеризованной.

Учитывая тип IFoo , вы можете вызвать sp<IFoo> IFoo::getService(string name, bool getStub) , чтобы получить доступ к экземпляру IFoo . Если getStub правда, getService попытки открыть HAL только в проходное режиме. Если getStub ложно, getService попытки найти binderized услуги; если это не удается, он пытается найти службу сквозной передачи. getStub параметр не должен использоваться только в defaultPassthroughServiceImplementation . (Устройства, запускаемые с Android O, являются полностью связанными устройствами, поэтому открытие службы в режиме сквозной передачи запрещено.)

Грамматика HIDL

По дизайну язык HIDL похож на C (но не использует препроцессор C). Все знаки препинания не описано ниже (кроме очевидного использования = и | ) является частью грамматики.

Примечание: Для получения дополнительной информации о стиле HIDL кода см Руководство по стилю коды .

  • /** */ указывает на документацию комментарий. Их можно применять только к объявлениям типа, метода, поля и значения перечисления.
  • /* */ Указывает на многострочный комментарий.
  • // указывает на комментарий до конца строки. Помимо // , новые строки такие же , как и любой другой пробел.
  • В примере грамматике ниже, текст от // до конца строки не является частью грамматики , но вместо того, чтобы комментарий по грамматике.
  • [empty] означает , что этот термин может быть пустым.
  • ? после буквального обозначения или термина означает, что это необязательно.
  • ... обозначает последовательность , содержащий ноль или более элементов с разделительным знаком , как указано. В HIDL нет вариативных аргументов.
  • Элементы последовательности разделяются запятыми.
  • Точка с запятой завершает каждый элемент, включая последний элемент.
  • ВЕРХНИЙ регистр - нетерминальный.
  • italics является маркером семейства , таким как integer или identifier (правила стандартного С синтаксического анализом).
  • constexpr является выражением постоянной стиль С (такие , как 1 + 1 и 1L << 3 ).
  • import_name представляет собой пакет или интерфейс имя, квалифицируется как описано в HIDL их версиями .
  • Строчные words являются лексемы , .

Пример:

ROOT =
    PACKAGE IMPORTS PREAMBLE { ITEM ITEM ... }  // not for types.hal
  | PACKAGE IMPORTS ITEM ITEM...  // only for types.hal; no method definitions

ITEM =
    ANNOTATIONS? oneway? identifier(FIELD, FIELD ...) GENERATES?;
  |  safe_union identifier { UFIELD; UFIELD; ...};
  |  struct identifier { SFIELD; SFIELD; ...};  // Note - no forward declarations
  |  union identifier { UFIELD; UFIELD; ...};
  |  enum identifier: TYPE { ENUM_ENTRY, ENUM_ENTRY ... }; // TYPE = enum or scalar
  |  typedef TYPE identifier;

VERSION = integer.integer;

PACKAGE = package android.hardware.identifier[.identifier[...]]@VERSION;

PREAMBLE = interface identifier EXTENDS

EXTENDS = <empty> | extends import_name  // must be interface, not package

GENERATES = generates (FIELD, FIELD ...)

// allows the Binder interface to be used as a type
// (similar to typedef'ing the final identifier)
IMPORTS =
   [empty]
  |  IMPORTS import import_name;

TYPE =
  uint8_t | int8_t | uint16_t | int16_t | uint32_t | int32_t | uint64_t | int64_t |
 float | double | bool | string
|  identifier  // must be defined as a typedef, struct, union, enum or import
               // including those defined later in the file
|  memory
|  pointer
|  vec<TYPE>
|  bitfield<TYPE>  // TYPE is user-defined enum
|  fmq_sync<TYPE>
|  fmq_unsync<TYPE>
|  TYPE[SIZE]

FIELD =
   TYPE identifier

UFIELD =
   TYPE identifier
  |  safe_union identifier { FIELD; FIELD; ...} identifier;
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SFIELD =
   TYPE identifier
  |  safe_union identifier { FIELD; FIELD; ...};
  |  struct identifier { FIELD; FIELD; ...};
  |  union identifier { FIELD; FIELD; ...};
  |  safe_union identifier { FIELD; FIELD; ...} identifier;
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SIZE =  // Must be greater than zero
     constexpr

ANNOTATIONS =
     [empty]
  |  ANNOTATIONS ANNOTATION

ANNOTATION =
  |  @identifier
  |  @identifier(VALUE)
  |  @identifier(ANNO_ENTRY, ANNO_ENTRY  ...)

ANNO_ENTRY =
     identifier=VALUE

VALUE =
     "any text including \" and other escapes"
  |  constexpr
  |  {VALUE, VALUE ...}  // only in annotations

ENUM_ENTRY =
     identifier
  |  identifier = constexpr

Терминология

В этом разделе используются следующие термины, относящиеся к HIDL:

связующий Указывает, что HIDL используется для удаленных вызовов процедур между процессами, реализованных через механизм, подобный Binder. Смотрите также PASSTHROUGH.
обратный вызов, асинхронный Интерфейс, обслуживаемый пользователем HAL, переданный в HAL (через метод HIDL) и вызываемый HAL для возврата данных в любое время.
обратный вызов, синхронный Возвращает данные из реализации метода HIDL сервера клиенту. Не используется для методов, возвращающих void или одно примитивное значение.
клиент Процесс, вызывающий методы определенного интерфейса. HAL или каркасный процесс может быть клиентом одного интерфейса и сервером другого. Смотрите также PASSTHROUGH.
расширяет Обозначает интерфейс, который добавляет методы и / или типы к другому интерфейсу. Интерфейс может расширять только один другой интерфейс. Может использоваться для приращения младшей версии в том же самом названии пакета или для нового пакета (например, расширения поставщика) для построения более старого пакета.
генерирует Указывает метод интерфейса, который возвращает значения клиенту. Чтобы вернуть одно непримитивное значение или несколько значений, создается синхронная функция обратного вызова.
интерфейс Сборник методов и видов. Переведен в класс на C ++ или Java. Все методы интерфейса вызываются в одном направлении: клиентский процесс вызывает методы, реализованные серверным процессом.
в одну сторону При применении к методу HIDL указывает, что метод не возвращает значений и не блокирует.
упаковка Коллекция интерфейсов и типов данных, разделяющих версию.
пройти через Режим HIDL , в которой сервер является разделяемой библиотекой, dlopen ред клиентом. В режиме сквозной передачи клиент и сервер - это один и тот же процесс, но разные кодовые базы. Используется только для переноса устаревших кодовых баз в модель HIDL. Смотрите также Binderized.
сервер Процесс, реализующий методы интерфейса. Смотрите также PASSTHROUGH.
транспорт Инфраструктура HIDL, которая перемещает данные между сервером и клиентом.
версия Версия пакета. Состоит из двух целых чисел - старшего и младшего. Приращения второстепенных версий могут добавлять (но не изменять) типы и методы.