Sensors HAL 2.0

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

Sensors HAL 2.0 доступен в Android 10 и более поздних версиях для новых и обновленных устройств. HAL 2.0 для датчиков основан на HAL 1.0 для датчиков, но имеет несколько ключевых отличий, которые не позволяют ему быть обратно совместимым. В Sensors HAL 2.0 для отправки событий датчиков из HAL в платформу датчиков Android используются очереди быстрых сообщений (FMQ).

HAL 2.1 для датчиков доступен в Android 11 и более поздних версиях для новых и обновленных устройств. Sensors HAL 2.1 – это версия Sensors HAL 2.0, в которой добавлен тип датчика HINGE_ANGLE и обновлены различные методы для поддержки типа HINGE_ANGLE.

Интерфейс HAL 2.1

Основной источник документации по Sensors HAL 2.1 находится в определении HAL по адресу hardware/interfaces/sensors/2.1/ISensors.hal. Если требования на этой странице и на странице ISensors.hal противоречат друг другу, следуйте требованиям на странице ISensors.hal.

Интерфейс HAL 2.0

Основной источник документации по Sensors HAL 2.0 находится в определении HAL по адресу hardware/interfaces/sensors/2.0/ISensors.hal. Если требования на этой странице и на странице ISensors.hal противоречат друг другу, следуйте требованиям на странице ISensors.hal.

Как реализовать Sensors HAL 2.0 и HAL 2.1

Чтобы реализовать Sensors HAL 2.0 или 2.1, объект должен расширить интерфейс ISensors и реализовать все функции, определенные в 2.0/ISensors.hal или 2.1/ISensors.hal.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Если максимальная задержка передачи данных больше нуля, события датчиков не обязательно передавать сразу после обнаружения. События могут временно храниться в аппаратном 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 можно создать из Event FMQ с помощью EventFlag::createEventFlag и функции getEventFlagWord() Event FMQ.

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

События WAKE_UP

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

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

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

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

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

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

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

Прямой канал

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

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

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

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

Функции injectSensorData() и injectSensorsData_2_1() в HAL 2.0 обычно используются для передачи рабочих параметров в 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 для Sensors HAL 2.0 находятся в каталоге hardware/interfaces/sensors/2.0/vts. Тесты VTS для HAL датчиков 2.1 находятся в каталоге hardware/interfaces/sensors/2.1/vts. Эти тесты позволяют убедиться, что HAL датчиков реализован правильно и что все требования, указанные в ISensors.hal и ISensorsCallback.hal, выполнены.

Как перейти с Sensors HAL 2.0 на 2.1

При переходе с версии 2.0 на 2.1 реализация HAL должна включать методы initialize_2_1(), getSensorsList_2_1() и injectSensorsData_2_1(), а также типы HAL 2.1. Эти методы должны соответствовать требованиям, описанным выше для HAL 2.0.

Поскольку HAL промежуточных версий должны поддерживать все функции предыдущих HAL, HAL 2.1 должны поддерживать инициализацию в качестве HAL 2.0. Чтобы избежать сложностей, связанных с поддержкой обеих версий HAL, настоятельно рекомендуем использовать Multi-HAL 2.1.

Пример реализации HAL датчиков версии 2.1 можно найти в файле Sensors.h.

Как перейти с Sensors HAL 1.0 на 2.0

При переходе с версии 1.0 на 2.0 убедитесь, что ваша реализация HAL соответствует следующим требованиям.

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

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

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

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

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

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

События WAKE_UP

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

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

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

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

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

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

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

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