Google is committed to advancing racial equity for Black communities. See how.
This page was translated by the Cloud Translation API.
Switch to English

HIDL

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

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

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

HIDL дизайн

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

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

  • Совместимость . Создавайте надежно взаимодействующие интерфейсы между процессами, которые могут быть скомпилированы с использованием различных архитектур, инструментальных средств и конфигураций сборки. Интерфейсы 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 с помощью связывателя, непосредственно вызываются нужные функции. Будущие реализации HAL могут предоставить несколько реализаций, таких как FooFast HAL и FooAccurate HAL. В таких случаях будет создан файл для каждой дополнительной реализации (например, PTFooFast.cpp и PTFooAccurate.cpp ).

Биндеризация сквозных HAL

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

  • abcd@MN::IFoo-impl . Содержит реализацию HAL и предоставляет функцию IFoo* HIDL_FETCH_IFoo(const char* name) . На устаревших устройствах этот пакет dlopen и реализация HIDL_FETCH_IFoo с помощью 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 имеет значение false, getService пытается найти объединенную службу; если это не удается, он пытается найти службу сквозной передачи. Параметр getStub никогда не следует использовать, за исключением defaultPassthroughServiceImplementation . (Устройства, запускаемые с Android O, являются полностью связанными устройствами, поэтому открытие службы в режиме сквозной передачи запрещено.)

Грамматика HIDL

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

Примечание. Подробнее о стиле кода HIDL см. В Руководстве по стилям кода .

  • /** */ обозначает комментарий документации. Их можно применять только к объявлениям типа, метода, поля и значения перечисления.
  • /* */ обозначает многострочный комментарий.
  • // указывает комментарий до конца строки. За исключением // , новые строки такие же, как и любые другие пробелы.
  • В приведенном ниже примере грамматики текст от // до конца строки не является частью грамматики, а вместо этого является комментарием к грамматике.
  • [empty] означает, что термин может быть пустым.
  • ? после буквального обозначения или термина означает, что это необязательно.
  • ... указывает последовательность, содержащую ноль или более элементов с разделительной пунктуацией, как указано. В HIDL нет вариативных аргументов.
  • Элементы последовательности разделяются запятыми.
  • Точка с запятой завершает каждый элемент, включая последний элемент.
  • ВЕРХНИЙ регистр - нетерминальный.
  • italics - это семейство токенов, такое как integer или identifier (стандартные правила синтаксического анализа C).
  • constexpr - это константное выражение стиля C (например, 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. См. Также сквозную передачу .
обратный вызов, асинхронный Интерфейс, обслуживаемый пользователем HAL, переданный в HAL (через метод HIDL) и вызываемый HAL для возврата данных в любое время.
обратный вызов, синхронный Возвращает данные из реализации метода HIDL сервера клиенту. Не используется для методов, возвращающих void или одно примитивное значение.
клиент Процесс, вызывающий методы определенного интерфейса. HAL или каркасный процесс может быть клиентом одного интерфейса и сервером другого. См. Также сквозную передачу .
расширяет Указывает интерфейс, который добавляет методы и / или типы к другому интерфейсу. Интерфейс может расширять только один другой интерфейс. Может использоваться для приращения младшей версии в том же самом названии пакета или для нового пакета (например, расширения поставщика) для построения более старого пакета.
генерирует Указывает метод интерфейса, который возвращает значения клиенту. Чтобы вернуть одно непримитивное значение или несколько значений, создается синхронная функция обратного вызова.
интерфейс Сборник методов и видов. Переведен в класс на C ++ или Java. Все методы интерфейса вызываются в одном направлении: клиентский процесс вызывает методы, реализованные серверным процессом.
в одну сторону При применении к методу HIDL указывает, что метод не возвращает значений и не блокирует.
пакет Коллекция интерфейсов и типов данных, разделяющих версию.
пройти через Режим HIDL, в котором сервер является разделяемой библиотекой, dlopen клиентом. В режиме сквозной передачи клиент и сервер - это один и тот же процесс, но разные кодовые базы. Используется только для переноса устаревших кодовых баз в модель HIDL. См. Также Binderized .
сервер Процесс, реализующий методы интерфейса. См. Также сквозную передачу .
транспорт Инфраструктура HIDL, которая перемещает данные между сервером и клиентом.
версия Версия пакета. Состоит из двух целых чисел: большого и младшего. Приращения второстепенных версий могут добавлять (но не изменять) типы и методы.