Датчики AIDL HAL

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

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

Интерфейс AIDL HAL

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

Как реализовать HAL датчиков AIDL

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

Инициализация HAL

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

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

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

Как предоставить доступ к датчикам

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

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

Стабильность списка датчиков

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

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

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

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

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

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

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

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

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

Чтобы узнать больше о взаимодействии между периодом выборки и режимами передачи данных датчика, ознакомьтесь с разделом Режимы передачи данных.

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

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

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

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

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

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

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

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

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

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

Встраиваемые датчики

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

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

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

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

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

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

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

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

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

События WAKE_UP

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

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

При записи данных в очередь FMQ блокировки пробуждения фреймворк устанавливает уведомление о записи WakeLockQueueFlagBits::DATA_WRITTEN в очередь FMQ блокировки пробуждения.

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

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

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

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

Прямой канал

Прямой канал – это метод работы, при котором события датчиков записываются в определенную память, а не в очередь FMQ событий, минуя платформу датчиков Android. Клиент, который регистрирует прямой канал, должен считывать события датчика непосредственно из памяти, использованной для создания прямого канала, и не будет получать события датчика через фреймворк. Функция 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

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

Инициализация HAL

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

Как предоставить доступ к датчикам

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

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

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

События WAKE_UP

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

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

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

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

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

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

Поддержка нескольких уровней абстракции оборудования

Аппаратно-зависимый уровень (HAL) AIDL для датчиков поддерживает несколько HAL с помощью фреймворка Sensors Multi-HAL. Подробнее о переносе данных из Sensors HAL 2.1…