Multi-HAL для датчиков

Multi-HAL датчиков – это фреймворк, который позволяет HAL датчиков работать вместе с другими HAL датчиков. Многофункциональный HAL датчиков динамически загружает вспомогательные HAL датчиков, хранящиеся в виде динамических библиотек в разделе поставщика, и предоставляет им объект обратного вызова, который может обрабатывать отправку событий, а также получение и освобождение блокировки пробуждения. Суб-HAL датчиков – это HAL датчиков, встроенный в общий объект в разделе поставщика и используемый фреймворком multi-HAL. Эти вложенные HAL не зависят друг от друга или от кода многомодульного HAL, который содержит основную функцию для процесса.

Multi-HAL 2.1 для датчиков, доступный на устройствах с Android 11 или более поздней версией, – это итерация Multi-HAL 2.0 для датчиков, которая поддерживает загрузку дополнительных HAL, способных предоставлять тип датчика угла шарнира. Чтобы поддерживать этот тип датчика, вложенные HAL должны использовать API вложенных HAL, определенные в заголовке SubHal версии 2.1.

На устройствах с Android 13 или более поздней версии, на которых используется HAL-интерфейс AIDL для датчиков, можно использовать многоуровневую прокладку HAL, чтобы разрешить многоуровневую работу HAL. Подробнее о реализации многофункционального HAL датчиков с помощью HAL датчиков AIDL…

Различия между Sensors Multi-HAL 2 и Sensors HAL 2

В Multi-HAL 2 для датчиков, доступном на устройствах с Android 10 или более поздней версии, реализовано несколько абстракций поверх HAL 2 для датчиков, чтобы упростить взаимодействие с API HAL. В Sensors Multi-HAL 2 представлен класс HalProxy для реализации интерфейса Sensors HAL 2 и интерфейс V2_1/SubHal (или V2_0/SubHal), позволяющий HalProxy взаимодействовать с суб-HAL.

Интерфейс ISensorsSubHal отличается от интерфейса 2.1/ISensors.hal (или 2.0/ISensors.hal) следующим образом:

  • Метод initialize передает класс IHalProxyCallback вместо двух FMQ и ISensorsCallback.
  • Вложенные HAL должны реализовывать функцию отладки, которая предоставляет информацию для отладки в отчетах об ошибках.
  • Вложенные HAL должны реализовывать функцию имени, чтобы загруженный вложенный HAL можно было отличить от других вложенных HAL.

Основное различие между Sensors Multi-HAL 2 и Sensors HAL 2 заключается в функциях инициализации. Вместо FMQ интерфейс IHalProxyCallback предоставляет два метода: один для отправки событий датчиков в фреймворк датчиков, а другой – для создания блокировок пробуждения. Внутри Sensors Multi-HAL управляет всеми взаимодействиями с FMQ, чтобы обеспечить своевременную доставку событий датчиков для всех суб-HAL. Мы настоятельно рекомендуем использовать вложенные HAL-модули метод createScopedWakelock, чтобы делегировать задачу отслеживания времени ожидания запретов блокировки многомодульному HAL датчиков и централизовать использование запретов блокировки в одном общем запрете блокировки для всего многомодульного HAL датчиков. Это позволит свести к минимуму вызовы блокировки и разблокировки.

В Sensors Multi-HAL 2 также встроены некоторые функции безопасности. Он обрабатывает ситуации, когда очередь сообщений FMQ датчика заполнена или когда платформа датчиков Android перезапускается и состояние датчика необходимо сбросить. Кроме того, если события отправляются в класс HalProxy, но фреймворк датчиков не может принять их немедленно, многокомпонентный HAL датчиков может переместить события в фоновый поток, чтобы позволить продолжить работу во всех суб-HAL, пока события не будут отправлены.

Исходный код и пример реализации

Весь код Multi-HAL для датчиков доступен в hardware/interfaces/sensors/common/default/2.X/multihal/. Ниже приведены ссылки на некоторые ресурсы.

  • HalProxy.h: Объект HalProxy создается многоуровневой абстракцией HAL датчиков и обрабатывает передачу данных из подчиненных уровней абстракции HAL в платформу датчиков.
  • HalProxy.cpp: Реализация HalProxy содержит всю логику, необходимую для мультиплексирования связи между вложенными HAL и фреймворком датчиков.
  • SubHal.h. Интерфейс ISensorsSubHal определяет интерфейс, которому должны соответствовать дочерние HAL, чтобы быть совместимыми с HalProxy. Вложенный HAL реализует метод initialize, чтобы объект HalProxyCallback можно было использовать для postEvents и createScopedWakelock.

    Для реализаций Multi-HAL 2.0 используйте версию 2.0 SubHal.h.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/ – модульные тесты для проверки реализации HalProxy.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/: В этом примере реализации суб-HAL используются поддельные датчики для создания поддельных данных. Полезно для тестирования взаимодействия нескольких вложенных HAL на устройстве.

Реализация

В этом разделе описано, как реализовать Multi-HAL датчиков в следующих ситуациях:

Использовать Sensors Multi-HAL с Sensors AIDL HAL

Чтобы разрешить использование нескольких HAL с Sensors AIDL HAL, импортируйте модуль AIDL Multi-HAL shim layer, который находится в hardware/interfaces/sensors/aidl/default/multihal/. Модуль обрабатывает преобразование между типами определений HAL сенсоров AIDL и HIDL и определяет оболочку для многоуровневого интерфейса HAL, описанного в разделе Реализация многоуровневого HAL сенсоров 2.1. Промежуточный слой AIDL multi-HAL совместим с устройствами, на которых реализован Sensors Multi-HAL 2.1.

Многоуровневая прослойка AIDL HAL позволяет предоставлять доступ к датчикам отслеживания движений головы и ограниченной оси IMU в Sensors AIDL HAL. Чтобы использовать типы датчиков, определенные интерфейсом AIDL HAL, задайте поле type в структуре SensorInfo в реализации getSensorsList_2_1(). Это безопасно, поскольку целочисленные поля типа датчика в HAL датчиков AIDL и HIDL не пересекаются.

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

Чтобы реализовать Sensors Multi-HAL 2.1 на новом устройстве, выполните следующие действия:

  1. Реализуйте интерфейс ISensorsSubHal, как описано в SubHal.h.
  2. Реализуйте метод sensorsHalGetSubHal_2_1 в SubHal.h.
  3. Добавьте цель cc_library_shared, чтобы создать новый реализованный подслой HAL. При добавлении цели:

    1. Убедитесь, что целевой файл отправлен в раздел поставщика на устройстве.
    2. В файле конфигурации, расположенном по адресу /vendor/etc/sensors/hals.conf, добавьте путь к библиотеке в новой строке. При необходимости создайте файл hals.conf.

    Пример записи Android.bp для создания библиотеки sub-HAL можно найти в файле hardware/interfaces/sensors/common/default/2.X/multihal/tests/Android.bp.

  4. Удалите все записи android.hardware.sensors из файла manifest.xml, в котором содержится список поддерживаемых HAL на устройстве.

  5. Удалите все файлы сервиса android.hardware.sensors и service.rc из файла device.mk и добавьте android.hardware.sensors@2.1-service.multihal и android.hardware.sensors@2.1-service.multihal.rc в PRODUCT_PACKAGES.

При загрузке запускается HalProxy, ищет новый sub-HAL и инициализирует его, вызывая sensorsHalGetSubHal_2_1.

Перенос с Sensors Multi-HAL 2.0 на Multi-HAL 2.1

Чтобы перенести данные из Multi-HAL 2.0 в Multi-HAL 2.1, реализуйте интерфейс SubHal и перекомпилируйте свой суб-HAL.

Ниже перечислены различия между интерфейсами SubHal версий 2.0 и 2.1.

  • В IHalProxyCallback используются типы, созданные в версии 2.1 спецификации ISensors.hal.
  • Функция initialize() передает новый объект IHalProxyCallback вместо объекта из интерфейса SubHal версии 2.0.
  • Вместо getSensorsList и injectSensorData в суб-HAL должны быть реализованы getSensorsList_2_1 и injectSensorData_2_1, поскольку в этих методах используются новые типы, добавленные в спецификацию ISensors.hal версии 2.1.
  • Вложенные HAL должны предоставлять sensorsHalGetSubHal_2_1, а не sensorsHalGetSubHal, чтобы Multi-HAL воспринимал их как вложенные HAL версии 2.1.

Перенос из Sensors HAL 2.0

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

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

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

Передача событий датчиков в реализацию Multi-HAL

Вместо того чтобы отправлять события датчиков через FMQ, суб-HAL должен записывать их в IHalProxyCallback, когда они становятся доступны.

События WAKE_UP

В Sensors HAL 2.0 HAL может управлять блокировкой пробуждения для своей реализации. В Sensors Multi-HAL 2.0 вложенные HAL позволяют реализации Multi-HAL управлять запретами блокировки и запрашивать их получение, вызывая createScopedWakelock. Блокировка пробуждения с заблокированной областью действия должна быть получена и передана в postEvents при отправке событий пробуждения в реализацию Multi-HAL.

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

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

Порт из Sensors HAL 1.0

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

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

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

Как предоставить доступ к датчикам

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

Отправка событий датчика в реализацию Multi-HAL

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

События WAKE_UP

В Sensors HAL 1.0 HAL может управлять блокировкой пробуждения для своей реализации. В Sensors Multi-HAL 2.0 дочерние HAL позволяют реализации Multi-HAL управлять запретами блокировки и могут запрашивать запрет блокировки, вызывая createScopedWakelock. Блокировка пробуждения с заблокированной областью действия должна быть получена и передана в postEvents при отправке событий пробуждения в реализацию Multi-HAL.

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

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

Перенос из Sensors Multi-HAL 1.0

Чтобы перенести существующую реализацию из Sensors Multi-HAL 1.0, выполните следующие действия:

  1. Убедитесь, что конфигурация HAL датчиков находится в каталоге /vendor/etc/sensors/hals.conf. Возможно, вам потребуется переместить файл, расположенный по адресу /system/etc/sensors/hals.conf.
  2. Удалите все упоминания hardware/hardware.h и hardware/sensors.h, поскольку они не поддерживаются в HAL 2.0.
  3. Перенесите вложенные HAL портов, как описано в разделе Перенос из Sensors HAL 1.0.
  4. Назначьте Sensors Multi-HAL 2.0 в качестве HAL по умолчанию, выполнив шаги 3 и 4 в разделе Реализация Sensors Multi-HAL 2.0.

Проверка

Как запустить VTS

После интеграции одного или нескольких дополнительных HAL с Sensors Multi-Hal 2.1 используйте Vendor Test Suite (VTS), чтобы убедиться, что ваши реализации дополнительных HAL соответствуют всем требованиям, установленным интерфейсом Sensors HAL.

Чтобы запустить только тесты VTS для датчиков, когда VTS настроен на хост-компьютере, выполните следующие команды:

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_0Target && \
  vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_1Target

Если вы используете многоуровневую прослойку AIDL Multi-HAL, выполните команду VtsAidlHalSensorsTargetTest.

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsAidlHalSensorsTargetTest

Запустите модульные тесты

Модульные тесты в HalProxy_test.cpp проверяют HalProxy с помощью поддельных подсистем HAL, которые создаются в модульном тесте и не загружаются динамически. При создании нового суб-HAL эти тесты должны служить руководством по добавлению модульных тестов, которые проверяют правильность реализации нового суб-HAL.

Чтобы запустить тесты, выполните следующие команды:

cd $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests
atest

Тестирование с использованием подсистем HAL

Поддельные вложенные HAL – это фиктивные реализации интерфейса ISensorsSubHal. Вложенные HAL-модули предоставляют разные списки датчиков. Когда датчики активированы, они периодически отправляют автоматически сгенерированные события датчиков в HalProxy на основе интервалов, указанных в запросе датчика.

Имитированные суб-HAL можно использовать для тестирования того, как полный код Multi-HAL работает с другими суб-HAL, загруженными в систему, и для стресс-тестирования различных аспектов кода Sensors Multi-HAL.

Два поддельных суб-HAL доступны по адресу hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/.

Чтобы создать и отправить на устройство поддельные HAL, выполните следующие действия:

  1. Выполните следующие команды, чтобы создать и отправить на устройство три разных подмодуля HAL:

    $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests/
    mma
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
  2. Обновите конфигурацию HAL датчиков в /vendor/etc/sensors/hals.conf, указав пути к поддельным подсистемам HAL.

    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
    
  3. Перезапустите HalProxy и загрузите новые вложенные HAL, указанные в файле конфигурации.

    adb shell stop
    adb shell start

Отладка

Разработчики могут отлаживать фреймворк с помощью команды lshal. Чтобы запросить вывод отладочной информации из HAL датчиков, выполните следующую команду:

adb root
adb shell lshal debug android.hardware.sensors@2.1::ISensors/default

Информация о текущем состоянии HalProxy и его суб-HAL выводится в терминал. Ниже показан пример результата выполнения команды для объекта HalProxy и поддельных суб-HAL.

Internal values:
  Threads are running: true
  Wakelock timeout start time: 200 ms ago
  Wakelock timeout reset time: 73208 ms ago
  Wakelock ref count: 0
  # of events on pending write queue: 0
  # of non-dynamic sensors across all subhals: 8
  # of dynamic sensors across all subhals: 0
SubHals (2):
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2

Если значение # of events on pending write queue велико (1000 или больше), это означает, что в платформу датчиков нужно записать много событий. Это означает, что сервис датчиков заблокирован или произошел сбой и он не обрабатывает события датчиков, или что из суб-HAL недавно был отправлен большой пакет событий датчиков.

Если счетчик ссылок на запрет блокировки больше 0, это означает, что HalProxy получил запрет блокировки. Значение параметра должно быть больше 0, только если ScopedWakelock намеренно удерживается или если события пробуждения были отправлены в HalProxy и ещё не обработаны фреймворком датчиков.

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