Датчики AIDL HAL

Уровень абстракции оборудования датчиков (HAL) — это интерфейс между фреймворком датчиков Android и датчиками устройства, такими как акселерометр или гироскоп. Уровень HAL датчиков определяет функции, которые необходимо реализовать, чтобы фреймворк мог управлять датчиками.

Интерфейс Sensors AIDL HAL доступен на новых и обновлённых устройствах Android 13 и выше. Интерфейс Sensors AIDL HAL, основанный на Sensors HAL 2.1 , использует интерфейс AIDL HAL и поддерживает датчики отслеживания положения головы и инерциальные измерительные блоки с ограниченной осью.

Интерфейс AIDL HAL

Основным источником документации по HAL AIDL для датчиков является определение HAL в файле hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl .

Внедрение датчиков AIDL HAL

Для реализации HAL-модуля Sensors AIDL объект должен расширить интерфейс ISensors и реализовать все функции, определенные в hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl .

Инициализируйте HAL

Перед использованием HAL-компонента Sensors необходимо инициализировать с помощью фреймворка Android Sensor. Фреймворк вызывает функцию initialize() , чтобы передать HAL-компоненту Sensors три параметра: два дескриптора FMQ и один указатель на объект ISensorsCallback .

HAL использует первый дескриптор для создания FMQ событий, используемого для записи событий датчиков в фреймворк. HAL использует второй дескриптор для создания FMQ блокировки пробуждения, используемого для синхронизации при снятии HAL блокировки пробуждения для событий датчиков WAKE_UP . HAL должен сохранить указатель на объект ISensorsCallback , чтобы можно было вызвать необходимые функции обратного вызова.

Функция initialize() должна быть первой функцией, вызываемой при инициализации HAL датчиков.

Выставить доступные датчики

Чтобы получить список всех доступных статических датчиков устройства, используйте функцию getSensorsList() . Эта функция возвращает список датчиков, каждый из которых уникально идентифицируется своим идентификатором. Идентификатор данного датчика не должен меняться при перезапуске процесса, содержащего HAL-компонент Sensors. Идентификаторы могут меняться при перезагрузке устройства и системного сервера.

Если несколько датчиков имеют одинаковый тип датчика и свойство пробуждения, то первый датчик в списке называется датчиком по умолчанию и возвращается приложениям, использующим функцию getDefaultSensor(int sensorType, bool wakeUp) .

Устойчивость списка датчиков

После перезапуска HAL-системы Sensors, если данные, возвращаемые функцией getSensorsList() указывают на существенное изменение по сравнению со списком датчиков, полученным до перезапуска, фреймворк инициирует перезапуск среды выполнения Android. К существенным изменениям в списке датчиков относятся случаи, когда датчик с заданным идентификатором отсутствует или имеет изменившиеся атрибуты, а также когда добавляются новые датчики. Хотя перезапуск среды выполнения Android нарушает работу пользователя, он необходим, поскольку фреймворк Android больше не может соблюдать соглашение API Android о том, что статические (нединамические) датчики не изменяются в течение жизненного цикла приложения. Это также может помешать фреймворку восстановить активные запросы датчиков, сделанные приложениями. Поэтому поставщикам HAL рекомендуется предотвращать непредотвратимые изменения списка датчиков.

Для обеспечения стабильности работы с датчиками HAL должен детерминированно сопоставлять физический датчик устройства с его дескриптором. Хотя интерфейс HAL для датчиков не требует какой-либо конкретной реализации, разработчикам доступен ряд вариантов для выполнения этого требования.

Например, список датчиков можно отсортировать, используя комбинацию фиксированных атрибутов каждого датчика, таких как производитель, модель и тип датчика. Другой вариант основан на том, что набор статических датчиков устройства фиксирован на аппаратном уровне, поэтому HAL необходимо знать, когда все ожидаемые датчики завершили инициализацию, прежде чем возвращаться из getSensorsList() . Этот список ожидаемых датчиков можно скомпилировать в двоичный файл HAL или сохранить в файле конфигурации в файловой системе, а порядок их появления можно использовать для получения стабильных дескрипторов. Хотя оптимальное решение зависит от особенностей реализации вашего HAL, ключевым требованием является то, чтобы дескрипторы датчиков не менялись при перезапусках HAL.

Настроить датчики

Перед активацией датчика необходимо настроить его на период выборки и максимальную задержку передачи данных с помощью функции batch() .

Датчик должен иметь возможность перенастройки в любое время с помощью batch() без потери данных датчика.

Период выборки

Период выборки имеет разное значение в зависимости от типа настраиваемого датчика:

  • Непрерывно: события датчиков генерируются с постоянной частотой.
  • При изменении: события генерируются не быстрее периода выборки и могут генерироваться с более низкой скоростью, чем период выборки, если измеренное значение не изменяется.
  • Однократный: период выборки игнорируется.
  • Специальное предложение: Более подробную информацию см. в разделе Типы датчиков .

Информацию о взаимодействии между периодом выборки и режимами отчетности датчика см. в разделе Режимы отчетности .

Максимальная задержка отчетности

Максимальная задержка отчета устанавливает максимальное время в наносекундах, в течение которого события могут задерживаться и сохраняться в аппаратном FIFO перед записью в Event FMQ через HAL, пока SoC активен.

Нулевое значение означает, что события должны сообщаться сразу после их измерения, либо полностью пропуская FIFO, либо очищая FIFO, как только в FIFO появится одно событие от датчика.

Например, акселерометр, работающий на частоте 50 Гц с максимальной задержкой реагирования, равной нулю, вызывает прерывания 50 раз в секунду, когда SoC активен.

Если максимальная задержка передачи данных больше нуля, события датчика не обязательно должны передаваться сразу после их обнаружения. События могут временно храниться в аппаратном буфере FIFO и передаваться пакетами, при условии, что ни одно событие не задерживается более чем на максимальную задержку передачи данных. Все события, начиная с предыдущей партии, регистрируются и возвращаются одновременно. Это сокращает количество прерываний, отправляемых на SoC, и позволяет SoC переключиться в режим пониженного энергопотребления, пока датчик собирает и формирует пакеты данных.

С каждым событием связана временная метка. Задержка времени сообщения о событии не должна влиять на временную метку события. Временная метка должна быть точной и соответствовать времени физического события, а не времени сообщения о нём.

Дополнительную информацию и требования по отчетности о событиях датчиков с ненулевой максимальной задержкой отчетности см. в разделе Пакетирование .

Активировать датчики

Фреймворк включает и отключает датчики с помощью функции activate() . Перед активацией датчика фреймворк должен сначала настроить его с помощью функции batch() .

После деактивации датчика дополнительные события от этого датчика не должны записываться в Event FMQ.

Датчики смыва

Если датчик настроен на пакетную запись данных, фреймворк может принудительно сбросить пакетированные события датчика, вызвав функцию flush() . Это приводит к немедленной записи пакетированных событий датчика для указанного дескриптора в очередь событий (FMQ). Уровень HAL датчиков (HAL) должен добавить событие завершения сброса в конец событий датчика, записанных в результате вызова функции flush() .

Сброс происходит асинхронно (то есть эта функция должна вернуть значение немедленно). Если реализация использует один FIFO-буфер для нескольких датчиков, этот FIFO-буфер очищается, а событие завершения сброса добавляется только для указанного датчика.

Если у указанного датчика нет FIFO (буферизация невозможна) или FIFO был пуст на момент вызова, flush() всё равно должен выполниться успешно и отправить событие завершения очистки для этого датчика. Это относится ко всем датчикам, кроме датчиков одноразового действия.

Если flush() вызывается для одноразового датчика, то flush() должен возвращать BAD_VALUE и не генерировать событие завершения очистки.

Запись событий датчиков в FMQ

Event FMQ используется HAL датчиков для передачи событий датчиков в инфраструктуру датчиков Android.

Event FMQ — это синхронизированный FMQ, что означает, что любая попытка записать в FMQ больше событий, чем позволяет доступное пространство, приводит к ошибке записи. В этом случае HAL должен определить, следует ли записывать текущий набор событий двумя меньшими группами или записывать все события вместе, когда будет достаточно места.

Когда HAL датчиков записал необходимое количество событий датчиков в очередь событий FMQ, HAL датчиков должен уведомить фреймворк о готовности событий, записав бит EventQueueFlagBits::READ_AND_PROCESS в функцию EventFlag::wake в FMQ событий. Флаг EventFlag можно создать из FMQ событий с помощью функции EventFlag::createEventFlag и функции getEventFlagWord() FMQ событий.

HAL-компоненты Sensors AIDL поддерживают как write , так и writeBlocking в очереди событий (FMQ). Реализация по умолчанию содержит справочную информацию по использованию функции write . При использовании функции writeBlocking флаг readNotification должен быть установлен в значение EventQueueFlagBits::EVENTS_READ , которое устанавливается фреймворком при чтении событий из очереди событий (FMQ). Флаг уведомления о записи должен быть установлен в значение EventQueueFlagBits::READ_AND_PROCESS , что уведомляет фреймворк о записи событий в очередь событий (FMQ).

События WAKE_UP

События WAKE_UP — это события датчиков, которые вызывают пробуждение прикладного процессора (AP) и его немедленную обработку. При записи события WAKE_UP в FMQ событий, HAL датчиков должен установить блокировку пробуждения, чтобы система оставалась в состоянии бодрствования до тех пор, пока фреймворк не сможет обработать событие. При получении события WAKE_UP фреймворк устанавливает собственную блокировку пробуждения, позволяя HAL датчиков снять блокировку пробуждения. Для синхронизации момента снятия блокировки пробуждения HAL датчиков используйте FMQ блокировки пробуждения.

HAL датчиков должен прочитать Wake Lock FMQ, чтобы определить количество событий WAKE_UP , обработанных фреймворком. HAL должен снимать блокировку пробуждения для событий WAKE_UP только в том случае, если общее количество необработанных событий WAKE_UP равно нулю. После обработки событий датчиков фреймворк подсчитывает количество событий, помеченных как WAKE_UP , и записывает это число обратно в Wake Lock FMQ.

Платформа устанавливает уведомление о записи WakeLockQueueFlagBits::DATA_WRITTEN в Wake Lock FMQ каждый раз, когда она записывает данные в Wake Lock FMQ.

Динамические датчики

Динамические датчики — это датчики, которые физически не являются частью устройства, но могут использоваться в качестве входных данных для устройства, например, геймпад с акселерометром.

При подключении динамического датчика необходимо вызвать функцию onDynamicSensorConnected в ISensorsCallback из HAL-уровня Sensors. Это уведомит фреймворк о новом динамическом датчике и позволит управлять датчиком через фреймворк, а также получать его события от клиентов.

Аналогично, когда динамический датчик отключается, необходимо вызвать функцию onDynamicSensorDisconnected в ISensorsCallback , чтобы фреймворк мог удалить любой датчик, который больше недоступен.

Прямой канал

Прямой канал — это метод работы, при котором события датчиков записываются в определённую память, а не в Event FMQ, минуя Android Sensors Framework. Клиент, регистрирующий прямой канал, должен считывать события датчиков непосредственно из памяти, которая использовалась для его создания, и не будет получать их через фреймворк. Функция configDirectReport() аналогична функции batch() в обычном режиме работы и настраивает прямой канал отчётов.

Функции registerDirectChannel() и unregisterDirectChannel() создают или уничтожают новый прямой канал.

Режимы работы

Функция setOperationMode() позволяет фреймворку настроить датчик, чтобы он мог передавать данные с него. Это полезно для тестирования, особенно для алгоритмов, находящихся ниже уровня фреймворка.

Функция injectSensorData() обычно используется для передачи рабочих параметров в HAL-систему датчиков. Её также можно использовать для передачи событий датчика в конкретный датчик.

Проверка

Для проверки реализации HAL датчиков запустите тесты CTS и VTS датчиков.

тесты CTS

Тесты CTS датчиков доступны как в автоматизированных тестах CTS, так и в ручном приложении CTS Verifier.

Автоматизированные тесты находятся в каталоге cts/tests/sensor/src/android/hardware/cts . Они проверяют стандартные функции датчиков, такие как активация датчиков, пакетирование и частота событий датчиков.

Тесты CTS Verifier находятся в каталоге cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors . Эти тесты требуют ручного ввода данных оператором и гарантируют точность показаний датчиков.

Прохождение испытаний CTS имеет решающее значение для подтверждения того, что тестируемое устройство соответствует всем требованиям CDD.

тесты СУДС

Тесты VTS для HAL-системы датчиков AIDL находятся в папке hardware/interfaces/sensors/aidl/vts/ . Эти тесты гарантируют корректную реализацию HAL-системы датчиков и выполнение всех требований ISensors.aidl и ISensorsCallback.aidl .

Инициализируйте HAL

Функция initialize() должна поддерживаться для установления FMQ между фреймворком и HAL.

Выставить доступные датчики

В HAL-системе Sensors AIDL функция getSensorsList() должна возвращать одно и то же значение при загрузке одного устройства, даже при перезапуске HAL-системы Sensors. Новое требование к функции getSensorsList() заключается в том, что она должна возвращать одно и то же значение при загрузке одного устройства, даже при перезапуске HAL-системы Sensors. Это позволяет фреймворку попытаться восстановить соединения с датчиками после перезапуска системного сервера. Значение, возвращаемое функцией getSensorsList() может измениться после перезагрузки устройства.

Запись событий датчиков в FMQ

Вместо ожидания вызова poll() в HAL-уровне Sensors AIDL, HAL-уровень Sensors должен проактивно записывать события датчиков в Event FMQ при наличии таких событий. HAL также отвечает за запись корректных битов в EventFlag для выполнения чтения FMQ внутри фреймворка.

События WAKE_UP

В Sensors HAL 1.0 HAL мог снять блокировку пробуждения для любого события WAKE_UP при любом последующем вызове poll() после отправки WAKE_UP в poll() поскольку это означало, что фреймворк обработал все события датчиков и при необходимости получил блокировку пробуждения. Поскольку в Sensors AIDL HAL больше не уведомляется об обработке фреймворком событий, записанных в FMQ, блокировка пробуждения FMQ позволяет фреймворку сообщать HAL об обработке событий WAKE_UP .

В HAL-уровне AIDL датчиков блокировка пробуждения, обеспечиваемая HAL-уровнем датчиков для событий WAKE_UP должна начинаться с SensorsHAL_WAKEUP .

Динамические датчики

Динамические датчики возвращались с помощью функции poll() в Sensors HAL 1.0. Согласно требованиям HAL для Sensors AIDL, onDynamicSensorsConnected и onDynamicSensorsDisconnected в ISensorsCallback должны вызываться при каждом изменении подключений динамических датчиков. Эти обратные вызовы доступны как часть указателя ISensorsCallback , предоставляемого функцией initialize() .

Режимы работы

Должен поддерживаться режим DATA_INJECTION для датчиков WAKE_UP .

Поддержка нескольких HAL

Sensors AIDL HAL поддерживает несколько HAL с помощью фреймворка Sensors Multi-HAL . Подробности реализации см. в разделе «Портирование из Sensors HAL 2.1» .