Датчики AIDL HAL

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

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

Интерфейс 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 датчиков должен быть инициализирован фреймворком датчиков Android, прежде чем его можно будет использовать. Фреймворк вызывает функцию initialize() , чтобы предоставить HAL датчиков три параметра: два дескриптора FMQ и один указатель на объект ISensorsCallback .

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

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

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

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

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

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

После перезапуска Sensors HAL, если данные, возвращаемые 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() . Это приводит к тому, что пакетные события датчика для указанного дескриптора датчика немедленно записываются в Event FMQ. HAL датчиков должен добавить событие завершения очистки в конец событий датчика, которые записываются в результате вызова flush() .

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

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

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

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

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

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

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

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

События WAKE_UP

События WAKE_UP — это события датчиков, которые заставляют процессор приложений (AP) просыпаться и немедленно обрабатывать событие. Всякий раз, когда событие WAKE_UP записывается в Event 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 датчиков. Это уведомляет фреймворк о новом динамическом датчике и позволяет управлять датчиком через фреймворк и потреблять события датчика клиентами.

Аналогично, когда динамический датчик отключается, необходимо вызвать функцию 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.

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

В Sensors AIDL HAL функция getSensorsList() должна возвращать одно и то же значение во время загрузки одного устройства, даже при перезапусках Sensors HAL. Новое требование функции getSensorsList() заключается в том, что она должна возвращать одно и то же значение во время загрузки одного устройства, даже при перезапусках Sensors 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() поскольку это указывало на то, что фреймворк обработал все события датчика и получил блокировку пробуждения, если это было необходимо. Поскольку в Sensors AIDL HAL HAL больше не уведомляется, когда фреймворк обработал события, записанные в FMQ, FMQ блокировки пробуждения позволяет фреймворку связываться с HAL, когда он обработал события WAKE_UP .

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

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

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

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

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

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

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