Посмотреть исходный код в Android Code Search
Если вы не являетесь производителем устройств Android или поставщиком чипов Thread, вы можете прекратить чтение прямо сейчас.
В этом документе описаны шаги по созданию нового устройства Thread Border Router на базе Android с новейшим исходным кодом AOSP. Следуя этому документу, вы узнаете:
- общая архитектура и статус поддержки потоков в Android
- как создать свой собственный сервис Thread HAL
- как сделать ваше устройство совместимым с Google Home
- как протестировать маршрутизатор Thread Border Router
Если вам нужна поддержка, сообщите о проблеме на GitHub или откройте обсуждение, если у вас есть вопросы.
Обзор
Стек Android Thread основан на OpenThread и ot-br-posix
, исходный код которых открыт Google на GitHub. Точно так же, как OpenThread разрабатывается в публичном репозитории GitHub, так и стек Android Thread разрабатывается в общедоступной кодовой базе AOSP . Все функции и исправления ошибок сначала отправляются в AOSP. Это позволяет поставщикам начать внедрять последние версии Thread, не дожидаясь обычных выпусков Android.
Архитектура
Весь стек Android Thread состоит из двух основных компонентов: основного стека Thread в общем системном разделе и службы Thread HAL в разделе поставщика. Поставщикам устройств обычно нужно только позаботиться и создать службу HAL.
Вот краткое описание того, как работает стек Android Thread: - На системном сервере имеется системная служба Java Thread, которая управляет всем стеком - предоставляет системный API Thread, создает туннельный интерфейс thread-wpan
, регистрирует сеть Thread в службу подключения и реализует функции пограничной маршрутизации и рекламного прокси. — Основной стек Thread/OpenThread размещается в непривилегированном автономном собственном процессе, который называется ot-daemon
. ot-daemon
напрямую управляется системной службой Java через частные API AIDL и получает доступ к аппаратному радиомодулю Thread через API Thread HAL. - Предоставляемая поставщиком служба Thread HAL ДОЛЖНА реализовывать API Thread HAL. Обычно он работает как RCP и реализует шпинельный протокол.
Где код?
- Платформа/API и сервис Android Thread: https://cs.android.com/android/platform/superproject/main/+/main:packages/modules/Connectivity/thread/
- API Thread HAL и реализация службы по умолчанию: https://cs.android.com/android/platform/superproject/main/+/main:hardware/interfaces/threadnetwork/
- Импортированный репозиторий OpenThread: https://cs.android.com/android/platform/superproject/main/+/main:external/openthread/
- Импортированный репозиторий ot-br-posix: https://cs.android.com/android/platform/superproject/main/+/main:external/ot-br-posix/
Настройка среды разработки
Поставщики устройств Android, которые уже установили среду разработки Android для устройства, могут пропустить этот раздел.
Если вы новичок в экосистеме Android или являетесь поставщиком микросхем, который хочет сделать свой чип Thread совместимым с Android и обеспечить поддержку производителей устройств, продолжайте читать.
Следуйте кодовой лаборатории разработчиков Android
Чтобы впервые настроить среду разработки Android, используйте следующую кодовую лабораторию: https://source.android.com/docs/setup/start . В конце этой лабораторной работы вы сможете создать и запустить смоделированное устройство каракатицы из исходного кода.
Создайте свой сервис Thread HAL
Попробуйте нить в каракатице
Каракатица — это виртуальное устройство Android. Прежде чем приступать к созданию собственного сервиса HAL, лучше попробовать Thread в Cuttlefish, чтобы понять, как работает HAL.
Служба HAL Thread по умолчанию предоставляется в Cuttlefish и реализована с помощью имитируемого RCP , который передает пакеты через сокет UDP в и из имитируемого радиоканала Thread (802.15.4).
В экземпляре Cuttlefish предварительно установлено приложение «ThreadNetworkDemoApp». Откройте это приложение, чтобы подключить устройство «Каракатица» к сети Thread по умолчанию.
Также предусмотрены инструменты командной строки ot-ctl
и ot-cli-ftd
для настройки вашей сети Thread для тестирования. Эти инструменты поддерживают все команды OpenThread CLI, с которыми вы, возможно, уже знакомы.
Вы можете получить журналы службы HAL Cuttlefish Thread:
adb logcat | egrep -i threadnetwork-service
07-21 10:43:05.048 0 0 I init : Parsing file /apex/com.android.hardware.threadnetwork/etc/threadnetwork-service.rc...
07-21 10:59:27.233 580 580 W android.hardware.threadnetwork-service: ThreadChip binder is unlinked
07-21 10:59:27.233 580 580 I android.hardware.threadnetwork-service: Close IThreadChip successfully
07-21 10:59:27.385 580 580 I android.hardware.threadnetwork-service: Open IThreadChip successfully
Или grep для журналов ot-daemon:
adb logcat | egrep -i ot-daemon
07-21 10:43:48.741 0 0 I init : starting service 'ot-daemon'...
07-21 10:43:48.742 0 0 I init : Created socket '/dev/socket/ot-daemon/thread-wpan.sock', mode 660, user 1084, group 1084
07-21 10:43:48.762 0 0 I init : ... started service 'ot-daemon' has pid 2473
07-21 10:46:26.320 2473 2473 I ot-daemon: [I] P-Daemon------: Session socket is ready
07-21 10:46:30.290 2473 2473 W ot-daemon: [W] P-Daemon------: Daemon read: Connection reset by peer
07-21 10:48:07.264 2473 2473 I ot-daemon: [INFO]-BINDER--: Start joining...
07-21 10:48:07.267 2473 2473 I ot-daemon: [I] Settings------: Saved ActiveDataset
07-21 10:48:07.267 2473 2473 I ot-daemon: [I] DatasetManager: Active dataset set
07-21 10:48:07.273 2473 2473 I ot-daemon: [I] DnssdServer---: Started
07-21 10:48:07.273 2473 2473 I ot-daemon: [N] Mle-----------: Role disabled -> detached
07-21 10:48:07.273 2473 2473 I ot-daemon: [I] Mle-----------: AttachState Idle -> Start
07-21 10:48:07.273 2473 2473 I ot-daemon: [I] Notifier------: StateChanged (0x111fd11d) [Ip6+ Role LLAddr MLAddr KeySeqCntr Ip6Mult+ Channel PanId NetName ExtPanId ...
07-21 10:48:07.273 2473 2473 I ot-daemon: [I] Notifier------: StateChanged (0x111fd11d) ... NetworkKey PSKc SecPolicy NetifState ActDset]
Служба HAL Cuttlefish Thread использует службу HAL Thread по умолчанию, а также симулированный двоичный файл RCP OpenThread. О том, как она работает, см. в следующем разделе.
Служба HAL по умолчанию
Служба HAL по умолчанию включена вместе с API Thread HAL. Служба HAL по умолчанию поддерживает как смоделированные, так и реальные устройства RCP. Он получает дополнительный URL-адрес устройства RCP, и если URL-адрес не указан, по умолчанию используется имитируемое устройство RCP.
В файле hardware/interfaces/threadnetwork/aidl/default/threadnetwork-service.rc
:
service vendor.threadnetwork_hal /apex/com.android.hardware.threadnetwork/bin/hw/android.hardware.threadnetwork-service class hal user thread_network
Это эквивалентно:
service vendor.threadnetwork_hal /apex/com.android.hardware.threadnetwork/bin/hw/android.hardware.threadnetwork-service spinel+hdlc+forkpty:///apex/com.android.hardware.threadnetwork/bin/ot-rcp?forkpty-arg=1 class hal user thread_network
Для реальных устройств RCP он поддерживает интерфейсы SPI и UART, и вы можете указать устройство со схемой spinel+spi://
, spinel+hdlc+uart://
и spinel+socket://
соответственно.
Поймите поставщика APEX
Подобно стеку Thread в основном модуле Tethering, служба HAL Thread по умолчанию в Cuttlefish также упакована в модуль APEX. Но это модуль APEX поставщика, который будет установлен в /vendor/apex/
(артефакты в модуле будут разархивированы в /apex/com.android.hardware.threadnetwork/
).
apex { name: "com.android.hardware.threadnetwork", manifest: "manifest.json", file_contexts: "file_contexts", key: "com.android.hardware.key", certificate: ":com.android.hardware.certificate", updatable: false, vendor: true, binaries: [ "android.hardware.threadnetwork-service", "ot-rcp", ], prebuilts: [ "threadnetwork-default.xml", // vintf_fragment "threadnetwork-service.rc", // init_rc "android.hardware.thread_network.prebuilt.xml", // permission ], }
Есть несколько важных конфигураций, на которые вам необходимо обратить внимание или внести изменения при создании собственного модуля HAL APEX:
file_contexts
: описывает двоичные файлы/файлы данных, поставляемые в этом модуле APEX, или файлы, к которым служба HAL должна иметь доступ (например, устройство RCP). Это позволяет вам указать конкретные правила политики безопасности для вашей службы HAL для доступа к аппаратному устройству RCP.binaries
: двоичный файл, поставляемый в этом модуле APEX.threadnetwork-service.rc
: как будет запущена служба HAL. Здесь вам необходимо указать путь к устройству RCP.android.hardware.thread_network.prebuilt.xml
: определяет аппаратную функциюandroid.hardware.thread_network
. Это необходимо, чтобы система Android знала, что ваше устройство поддерживает аппаратную поддержку Thread. В противном случае стек Android Thread не будет включен.
Создайте свой сервис HAL
Независимо от того, являетесь ли вы разработчиком устройств Android или поставщиком микросхем, вы должны быть знакомы с созданием прошивки OT RCP для вашего чипа Thread. Следующие инструкции предполагают, что аппаратный чип правильно подключен и проверен.
Самый простой способ создать HAL APEX — создать новый APEX с двоичными файлами и предварительно созданными HAL APEX по умолчанию. Например, если ваша компания — Banana, а устройство RCP на вашем устройстве — /dev/ttyACM0
, ваш Thread HAL APEX будет выглядеть следующим образом:
-
Android.bp
:
prebuilt_etc { name: "banana-threadnetwork-service.rc", src: "banana-threadnetwork-service.rc", installable: false, } apex { name: "com.banana.android.hardware.threadnetwork", manifest: "manifest.json", file_contexts: "file_contexts", key: "com.android.hardware.key", certificate: ":com.android.hardware.certificate", updatable: false, vendor: true, binaries: [ "android.hardware.threadnetwork-service", ], prebuilts: [ "banana-threadnetwork-service.rc", "threadnetwork-default.xml", "android.hardware.thread_network.prebuilt.xml", ], }
-
file_contexts
:
(/.*)? u:object_r:vendor_file:s0 /etc(/.*)? u:object_r:vendor_configs_file:s0 /bin/hw/android\.hardware\.threadnetwork-service u:object_r:hal_threadnetwork_default_exec:s0 /dev/ttyACM0 u:object_r:threadnetwork_rcp_device:s0
Пути к файлам в первом столбце относятся к /apex/com.android.hardware.threadnetwork/
.
-
threadnetwork-service.rc
:
service vendor.threadnetwork_hal /apex/com.android.hardware.threadnetwork/bin/hw/android.hardware.threadnetwork-service spinel+hdlc+uart:///dev/ttyACM0?uart-baudrate=115200 class hal user root
-
manifest.json
:
{ "name": "com.android.hardware.threadnetwork", "version": 1 }
Предполагая, что вы создаете новое устройство с именем Orange, каталог конфигурации вашего устройства будет выглядеть так:
device/banana/orange/threadnetwork/ sepolicy/ Android.bp file_contexts manifest.json threadnetwork-default.xml threadnetwork-service.rc
В следующем разделе указано, какие правила sepolicy следует добавить в подкаталог sepolicy/
.
Правила Sepolicy для устройства RCP
По умолчанию ваша служба Thread HAL не имеет доступа к устройству RCP (например, /dev/ttyACM0
), пользовательские правила sepolicy необходимо добавить в каталог sepolicy/
.
Создайте новый файл sepolicy/threadnetwork_hal.te
со следующим содержимым:
type threadnetwork_rcp_device, dev_type; # Allows the Thread HAL service to read / write the Thread RCP device allow hal_threadnetwork_default threadnetwork_rcp_device:chr_file rw_file_perms;
Собрать вместе
Теперь вы закончили почти весь код, необходимый для добавления Thread, и последний шаг — добавить Thread HAL APEX и правила sepolicy в образ вашего устройства.
Вы можете сделать это, добавив приведенный ниже код в Makefile
вашего устройства (например, device.mk
):
PRODUCT_PACKAGES += com.banana.hardware.threadnetwork BOARD_SEPOLICY_DIRS += device/banana/orange/threadnetwork/sepolicy
Если все работает, теперь вы сможете увидеть журнал службы Thread HAL, похожий на:
adb logcat | egrep -i threadnetwork-service
08-13 13:26:41.751 477 477 I android.hardware.threadnetwork-service: ServiceName: android.hardware.threadnetwork.IThreadChip/chip0, Url: spinel+spi
08-13 13:26:41.751 477 477 I android.hardware.threadnetwork-service: Thread Network HAL is running
08-13 13:26:55.165 477 477 I android.hardware.threadnetwork-service: Open IThreadChip successfully
И лог ot-daemon
будет такой:
adb logcat -s ot-daemon
08-13 13:26:55.157 1019 1019 I ot-daemon: [NOTE]-AGENT---: Running OTBR_AGENT/Unknown
08-13 13:26:55.157 1019 1019 I ot-daemon: [NOTE]-AGENT---: Thread version: 1.3.0
08-13 13:26:55.157 1019 1019 I ot-daemon: [NOTE]-AGENT---: Thread interface: thread-wpan
08-13 13:26:55.157 1019 1019 I ot-daemon: [NOTE]-AGENT---: Backbone interface is not specified
08-13 13:26:55.157 1019 1019 I ot-daemon: [NOTE]-AGENT---: Radio URL: threadnetwork_hal://binder?none
08-13 13:26:55.157 1019 1019 I ot-daemon: [NOTE]-ILS-----: Infra link selected:
08-13 13:26:55.160 1019 1019 I ot-daemon: [I] Platform------: [HAL] Wait for getting the service android.hardware.threadnetwork.IThreadChip/chip0 ...
08-13 13:26:55.165 1019 1019 I ot-daemon: [I] Platform------: [HAL] Successfully got the service android.hardware.threadnetwork.IThreadChip/chip0
08-13 13:26:55.275 1019 1019 I ot-daemon: [I] P-RadioSpinel-: RCP reset: RESET_UNKNOWN
08-13 13:26:55.276 1019 1019 I ot-daemon: [I] P-RadioSpinel-: Software reset RCP successfully
08-13 13:26:55.277 1019 1019 I ot-daemon: [I] P-RadioSpinel-: RCP reset: RESET_POWER_ON
08-13 13:26:55.322 1019 1019 I ot-daemon: [I] ChildSupervsn-: Timeout: 0 -> 190
08-13 13:26:55.324 1019 1019 I ot-daemon: [I] RoutingManager: Initializing - InfraIfIndex:0
08-13 13:26:55.324 1019 1019 I ot-daemon: [I] InfraIf-------: Init infra netif 0
08-13 13:26:55.324 1019 1019 I ot-daemon: [I] Settings------: Read BrUlaPrefix fd7b:cc45:ff06::/48
08-13 13:26:55.324 1019 1019 I ot-daemon: [N] RoutingManager: BR ULA prefix: fd7b:cc45:ff06::/48 (loaded)
08-13 13:26:55.324 1019 1019 I ot-daemon: [I] RoutingManager: Generated local OMR prefix: fd7b:cc45:ff06:1::/64
08-13 13:26:55.324 1019 1019 I ot-daemon: [N] RoutingManager: Local on-link prefix: fdde:ad00:beef:cafe::/64
08-13 13:26:55.324 1019 1019 I ot-daemon: [I] RoutingManager: Enabling
Кастомизация
Основной модуль Thread (на самом деле это часть модуля «Привязка») предоставляет несколько накладываемых конфигураций , которые могут быть указаны поставщиками для настройки поведения стека. Полный список см. в config_thread.xml .
Обычно вам необходимо изменить config_thread_vendor_name
, config_thread_vendor_oui
и config_thread_model_name
на значения вашего поставщика или продукта. Эти значения будут включены в службу mDNS _meshcop._udp
, которая всегда объявляется пограничным маршрутизатором потоков.
Чтобы добавить наложение, вам необходимо создать новую цель ConnectivityOverlayOrange
runtime_resource_overlay для вашего устройства Orange. Создайте новый каталог ConnectivityOverlay/
в разделе device/banana/orange/rro_overlays
и создайте в нем следующее содержимое:
device/banana/orange/rro_overlays/ConnectivityOverlay/ res values config_thread.xml Android.bp AndroidManifest.xml
-
Android.bp
:
package { default_applicable_licenses: ["Android-Apache-2.0"], } runtime_resource_overlay { name: "ConnectivityOverlayOrange", manifest: "AndroidManifest.xml", resource_dirs: ["res"], certificate: "platform", product_specific: true, sdk_version: "current", }
-
AndroidManifest.xml
:
<!-- Orange overlays for the Connectivity module --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.banana.android.connectivity.resources.orange" android:versionCode="1" android:versionName="1.0"> <application android:hasCode="false" /> <!-- If your device uses google-signed mainline modules, the targetPackage needs to be "com.google.android.connectivity.resources", otherise, it should be "com.android.connectivity.resources" --> <overlay android:targetPackage="com.google.android.connectivity.resources" android:targetName="ServiceConnectivityResourcesConfig" android:isStatic="true" android:priority="1"/> </manifest>
-
config_thread.xml
:
<string translatable="false" name="config_thread_vendor_name">Banana Inc.</string> <string translatable="false" name="config_thread_vendor_oui">AC:DE:48</string> <string translatable="false" name="config_thread_model_name">Orange</string>
Как и в случае с HAL APEX, вам необходимо добавить приложение-оверлей в файл device.mk
:
PRODUCT_PACKAGES += \ ConnectivityOverlayOrange</code>
Если все работает, вы увидите, что ot-daemon
записывает имя производителя и модели в самом начале журнала:
adb logcat -s ot-daemon
07-22 15:31:37.693 1472 1472 I ot-daemon: [I] P-Daemon------: Session socket is ready
07-22 15:31:37.693 1472 1472 I ot-daemon: [I] Cli-----------: Input: state
07-22 15:31:37.693 1472 1472 I ot-daemon: [I] Cli-----------: Output: disabled
07-22 15:31:37.693 1472 1472 I ot-daemon: [I] Cli-----------: Output: Done
07-22 15:31:37.693 1472 1472 W ot-daemon: [W] P-Daemon------: Daemon read: Connection reset by peer
07-22 15:31:50.091 1472 1472 I ot-daemon: [I] P-Daemon------: Session socket is ready
07-22 15:31:50.091 1472 1472 I ot-daemon: [I] Cli-----------: Input: factoryreset
07-22 15:31:50.092 1472 1472 I ot-daemon: [I] Settings------: Wiped all info
07-22 15:31:50.092 1472 1472 I ot-daemon: [INFO]-ADPROXY-: Stopped
07-22 15:31:50.092 1472 1472 I ot-daemon: [INFO]-DPROXY--: Stopped
07-22 15:31:50.092 1472 1472 I ot-daemon: [INFO]-BA------: Stop Thread Border Agent
07-22 15:31:50.092 1472 1472 I ot-daemon: [INFO]-BA------: Unpublish meshcop service Banana Inc. Orange #4833._meshcop._udp.local
07-22 15:31:50.092 1472 1472 I ot-daemon: [INFO]-MDNS----: Removing service Banana Inc. Orange #4833._meshcop._udp
07-22 15:31:50.092 1472 1472 I ot-daemon: [INFO]-MDNS----: Unpublishing service Banana Inc. Orange #4833._meshcop._udp listener ID = 0
Будьте совместимы с Google Home
Кроме того, если вы хотите, чтобы ваш пограничный маршрутизатор использовался экосистемой Google Home, вы можете указать эту конфигурацию в config_thread.xml
:
<string-array name="config_thread_mdns_vendor_specific_txts"> <item>vgh=1</item> </string-array>
Тестирование
Теперь ваше устройство должно быть совместимо со спецификацией пограничного маршрутизатора Thread 1.3+. Прежде чем отправлять его в программу сертификации Thread, необходимо провести несколько тестов Android xTS, чтобы убедиться в совместимости.
Тест VTS гарантирует, что служба Thread HAL работает на вашем устройстве должным образом. Вы можете запустить тесты с помощью команды
atest VtsHalThreadNetworkTargetTest
Тест CTS гарантирует, что API-интерфейсы потоков работают на вашем устройстве должным образом. Вы можете запустить тесты с помощью команды
atest CtsThreadNetworkTestCases
Интеграционный тест обеспечивает более качественную гарантию того, как основной код Thread работает на вашем устройстве. Вы можете запустить тесты с помощью команды
atest ThreadNetworkIntegrationTests
Вы также можете найти дополнительные инструкции по запуску тестов VTS/CTS/MTS с помощью этих выпущенных наборов тестов:
- https://source.android.com/docs/core/tests/vts
- https://source.android.com/docs/compatibility/cts/run
- https://docs.partner.android.com/mainline/test/mts (для доступа к этой ссылке вам необходимо быть партнером)
Протестируйте с помощью демонстрационного приложения Thread
Как и в случае с устройством Cuttlefish, вы можете добавить демонстрационное приложение Thread в образ своей системы:
# ThreadNetworkDemoApp for testing PRODUCT_PACKAGES_DEBUG += ThreadNetworkDemoApp
Обратите внимание, что вам следует добавить его только в вариант debug/eng (например, PRODUCT_PACKAGES_DEBUG
), поскольку он не должен быть включен в пользовательскую сборку для конечных потребителей.