Уровень абстракции оборудования датчиков (HAL) — это интерфейс между фреймворком датчиков Android и датчиками устройства, такими как акселерометр или гироскоп. Уровень 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
Основной источник документации по датчикам HAL 2.1 находится в определении HAL в файле hardware/interfaces/sensors/2.1/ISensors.hal . В случае конфликта требований между этой страницей и ISensors.hal
, используйте требования из ISensors.hal
.
Интерфейс HAL 2.0
Основной источник документации по датчикам 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 использует первый дескриптор для создания FMQ событий, используемого для записи событий датчиков в фреймворк. HAL использует второй дескриптор для создания FMQ блокировки пробуждения, используемого для синхронизации при снятии HAL блокировки пробуждения для событий датчиков WAKE_UP
. HAL должен сохранить указатель на объект ISensorsCallback
, чтобы можно было вызвать необходимые функции обратного вызова.
Функция initialize()
или initialize_2_1()
должна быть первой функцией, вызываемой при инициализации HAL датчиков.
Выставить доступные датчики
Чтобы получить список всех доступных статических датчиков устройства, используйте функцию getSensorsList()
в HAL 2.0 и функцию getSensorsList_2_1()
в HAL 2.1. Эта функция возвращает список датчиков, каждый из которых уникально идентифицируется своим идентификатором. Идентификатор данного датчика не должен меняться при перезапуске процесса, содержащего HAL-объект Sensors. Идентификаторы могут меняться при перезагрузке устройства и системного сервера.
Если несколько датчиков имеют одинаковый тип датчика и свойство пробуждения, то первый датчик в списке называется датчиком по умолчанию и возвращается приложениям, использующим функцию getDefaultSensor(int sensorType, bool wakeUp)
.
Устойчивость списка датчиков
После перезапуска 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()
. Это приводит к немедленной записи пакетированных событий датчика для указанного дескриптора в очередь событий (FMQ). Уровень HAL датчиков (HAL) должен добавить событие завершения сброса в конец событий датчика, записанных в результате вызова функции flush()
.
Сброс происходит асинхронно (то есть эта функция должна вернуть значение немедленно). Если реализация использует один FIFO-буфер для нескольких датчиков, этот FIFO-буфер очищается, а событие завершения сброса добавляется только для указанного датчика.
Если у указанного датчика нет FIFO (буферизация невозможна) или FIFO был пуст на момент вызова, flush()
всё равно должен выполниться успешно и отправить событие завершения очистки для этого датчика. Это относится ко всем датчикам, кроме датчиков одноразового действия.
Если flush()
вызывается для одноразового датчика, то flush()
должен возвращать BAD_VALUE
и не генерировать событие завершения очистки.
Запись событий датчиков в FMQ
Event FMQ используется HAL датчиков для передачи событий датчиков в инфраструктуру датчиков Android.
Event FMQ — это синхронизированный FMQ, что означает, что любая попытка записать в FMQ больше событий, чем позволяет доступное пространство, приводит к ошибке записи. В этом случае HAL должен определить, следует ли записывать текущий набор событий двумя меньшими группами или записывать все события вместе, когда будет достаточно места.
Когда HAL датчиков записал необходимое количество событий датчиков в очередь событий FMQ, HAL датчиков должен уведомить фреймворк о готовности событий, записав бит EventQueueFlagBits::READ_AND_PROCESS
в функцию EventFlag::wake
в FMQ событий. Флаг EventFlag можно создать из FMQ событий с помощью функции EventFlag::createEventFlag
и функции getEventFlagWord()
FMQ событий.
Датчики HAL 2.0/2.1 поддерживают как write
, так и writeBlocking
в очереди событий (FMQ). Реализация по умолчанию содержит справочную информацию по использованию функции write
. При использовании функции writeBlocking
флаг readNotification
должен быть установлен в значение EventQueueFlagBits::EVENTS_READ
, которое устанавливается фреймворком при чтении событий из очереди событий (FMQ). Флаг уведомления о записи должен быть установлен в значение EventQueueFlagBits::READ_AND_PROCESS
, что уведомляет фреймворк о записи событий в очередь событий (FMQ).
События WAKE_UP
События WAKE_UP
— это события датчиков, которые вызывают пробуждение прикладного процессора (AP) и его немедленную обработку. При записи события WAKE_UP
в 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-уровня Sensors. Это уведомит фреймворк о новом динамическом датчике и позволит управлять датчиком через фреймворк, а также получать его события от клиентов.
Аналогично, когда динамический датчик отключается, необходимо вызвать функцию onDynamicSensorDisconnected
в ISensorsCallback
, чтобы фреймворк мог удалить любой датчик, который больше недоступен.
Прямой канал
Прямой канал — это метод работы, при котором события датчиков записываются в определённую память, а не в Event FMQ, минуя Android Sensors Framework. Клиент, регистрирующий прямой канал, должен считывать события датчиков непосредственно из памяти, которая использовалась для его создания, и не будет получать их через фреймворк. Функция configDirectReport()
аналогична функции batch()
в обычном режиме работы и настраивает прямой канал отчётов.
Функции registerDirectChannel()
и unregisterDirectChannel()
создают или уничтожают новый прямой канал.
Режимы работы
Функция setOperationMode()
позволяет фреймворку настроить датчик, чтобы он мог передавать данные с него. Это полезно для тестирования, особенно для алгоритмов, находящихся ниже уровня фреймворка.
Функция injectSensorData()
в HAL 2.0 и функция 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 для датчиков 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
При обновлении с версии 2.0 до Sensors HAL 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 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, HAL Sensors должен проактивно записывать события датчиков в Event FMQ при наличии таких событий. HAL также отвечает за запись корректных битов в EventFlag
для инициирования чтения FMQ внутри фреймворка.
События WAKE_UP
В Sensors HAL 1.0 HAL мог снять блокировку пробуждения для любого события WAKE_UP
при любом последующем вызове poll()
после отправки WAKE_UP
в poll()
поскольку это означало, что фреймворк обработал все события датчиков и при необходимости получил блокировку пробуждения. Поскольку в Sensors HAL 2.0 HAL больше не знает, когда фреймворк обработал события, записанные в FMQ, блокировка пробуждения 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
Sensors HAL 2.0 и 2.1 поддерживают многоканальный HAL с помощью фреймворка Sensors Multi-HAL . Подробности реализации см. в разделе «Перенос из Sensors HAL 1.0» .