Датчики AIDL HAL

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

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

Интерфейс AIDL HAL

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

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

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

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

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

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

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

Отобразить доступные датчики

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

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

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

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

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

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

Настройка датчиков

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

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

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

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

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

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

Максимальная задержка передачи данных

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Интерфейс 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, Sensors HAL должен обеспечить блокировку пробуждения, чтобы гарантировать, что система останется в бодрствующем состоянии до тех пор, пока платформа не сможет обработать событие. После получения события WAKE_UP платформа обеспечивает свою собственную блокировку пробуждения, позволяя Sensors HAL освободить свою блокировку. Для синхронизации момента освобождения блокировки пробуждения Sensors HAL используйте Wake Lock FMQ.

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

Данная структура устанавливает уведомление о записи WakeLockQueueFlagBits::DATA_WRITTEN в очередь Wake Lock FMQ всякий раз, когда происходит запись данных в эту очередь.

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

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

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

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

Прямой канал

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

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

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

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

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

Валидация

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

Тесты CTS

Тесты Sensor 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-интерфейса Sensors AIDL находятся в папке hardware/interfaces/sensors/aidl/vts/ . Эти тесты гарантируют корректную реализацию HAL-интерфейса Sensors и надлежащее выполнение всех требований, указанных в ISensors.aidl и ISensorsCallback.aidl .

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

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

Отобразить доступные датчики

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

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

Вместо ожидания вызова функции poll() , в HAL-интерфейсе AIDL для датчиков 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 .

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

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

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

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

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

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

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