Датчики HAL 2.0

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

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

Sensors 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 .

Датчики внедрения HAL 2.0 и HAL 2.1

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

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

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

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

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

Датчики HAL 2.0/2.1 поддерживают как 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 2.0 и функция injectSensorsData_2_1() в HAL 2.0 обычно используются для передачи рабочих параметров в HAL Sensors. Функция также может использоваться для внедрения событий датчика в определенный датчик.

Проверка

Для проверки реализации 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 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.1 с 2.0

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

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

Пример реализации собственных датчиков HAL 2.1 см. в Sensors.h .

Обновление до Sensors HAL 2.0 с версии 1.0

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

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

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

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

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

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

Вместо ожидания вызова poll() в Sensors HAL 2.0, 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 должен поддерживаться в Sensors HAL 2.0.

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

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