Membangun Router Pembatas Android

Lihat sumber di Android Code Search

Jika Anda bukan vendor chip Thread atau perangkat Android, Anda dapat berhenti membaca sekarang.

Dokumen ini memandu Anda melalui langkah-langkah untuk mem-build perangkat Border Router Thread berbasis Android baru dengan kode sumber AOSP terbaru. Dengan mengikuti dokumen ini, Anda akan mempelajari:

  1. arsitektur dan status dukungan Thread secara keseluruhan di Android
  2. cara membuat layanan Thread HAL Anda sendiri
  3. cara membuat perangkat Anda kompatibel dengan Google Home
  4. cara menguji Router Pembatas Thread

Jika Anda memerlukan dukungan, laporkan masalah di GitHub atau buka Diskusi jika ada pertanyaan.

Ringkasan

Stack Thread Android didasarkan pada OpenThread dan ot-br-posix yang bersifat open source oleh Google di GitHub. Dengan cara yang sama, OpenThread dikembangkan di repositori GitHub publik, sehingga stack Android Thread dikembangkan di codebase AOSP publik. Semua fitur dan perbaikan bug dikirimkan terlebih dahulu di AOSP. Hal ini memungkinkan vendor mulai mengadopsi versi Thread terbaru tanpa menunggu rilis Android reguler.

Arsitektur

Seluruh stack Thread Android terdiri dari dua komponen utama: stack Thread inti dalam partisi sistem generik dan layanan HAL Thread dalam partisi vendor. Vendor perangkat biasanya hanya perlu menangani dan mem-build layanan HAL.

android-thread-arch

Berikut adalah ringkasan singkat tentang cara kerja stack Thread Android: - Ada layanan sistem Thread Java di server sistem yang mengelola seluruh stack - menyediakan API sistem Thread, membuat antarmuka tunnel thread-wpan, mendaftarkan jaringan Thread ke layanan Konektivitas dan menerapkan fungsi Border Routing dan Advertising Proxy. - Stack Thread / OpenThread inti dihosting dalam proses native mandiri tanpa hak istimewa yang bernama ot-daemon. ot-daemon dikelola langsung oleh layanan sistem Java melalui API AIDL pribadi dan mengakses radio hardware Thread melalui Thread HAL API. - Layanan Thread HAL yang disediakan vendor HARUS mengimplementasikan Thread HAL API. Protokol ini biasanya berfungsi sebagai RCP dan mengimplementasikan protokol spinel.

Di mana kodenya?

Menyiapkan lingkungan pengembangan

Vendor perangkat Android yang telah membuat lingkungan pengembangan Android untuk perangkat dapat melewati bagian ini.

Jika Anda baru menggunakan ekosistem Android atau Anda adalah vendor silicon yang ingin membuat chip Thread Anda kompatibel dengan Android dan memberikan dukungan untuk vendor perangkat, lanjutkan membaca.

Ikuti codelab developer Android

Untuk menyiapkan lingkungan pengembangan Android untuk pertama kalinya, gunakan codelab berikut: https://source.android.com/docs/setup/start. Di akhir codelab ini, Anda akan dapat mem-build dan menjalankan simulasi perangkat Cuttlefish dari kode sumber.

Mem-build layanan HAL Thread

Mencoba Thread di Cuttlefish

Cuttlefish adalah perangkat virtual Android. Sebelum mulai mem-build layanan HAL Anda sendiri, sebaiknya coba Thread di Cuttlefish untuk memahami cara kerja HAL.

Layanan HAL Thread default disediakan di Cuttlefish dan diimplementasikan dengan RCP simulasi yang mentransmisikan dan menerima paket melalui soket UDP ke dan dari radio Thread (802.15.4) simulasi.

Di instance Cuttlefish, "ThreadNetworkDemoApp" sudah diinstal sebelumnya. Buka aplikasi tersebut untuk bergabung dengan perangkat Cuttlefish ke jaringan Thread default.

demoapp-screenshot

Ada juga alat command line ot-ctl dan ot-cli-ftd yang disediakan untuk mengonfigurasi jaringan Thread Anda untuk pengujian. Alat tersebut mendukung semua perintah CLI OpenThread yang mungkin sudah Anda kenal.

Anda dapat mencari log layanan HAL Thread Cuttlefish dengan:

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

Atau grep untuk log ot-daemon dengan:

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]

Layanan HAL Thread Cuttlefish menggunakan layanan HAL Thread default ditambah biner RCP simulasi OpenThread. Lihat bagian berikutnya untuk mengetahui cara kerjanya.

Layanan HAL default

Layanan HAL default disertakan bersama Thread HAL API. Layanan HAL default mendukung perangkat RCP simulasi dan nyata. Perangkat ini menerima URL perangkat RCP opsional dan jika URL tidak diberikan, perangkat akan ditetapkan secara default ke perangkat RCP yang disimulasikan.

Dalam file 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

Hal ini setara dengan:

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

Untuk perangkat RCP yang sebenarnya, perangkat ini mendukung antarmuka SPI dan UART, dan Anda dapat menentukan perangkat dengan skema spinel+spi://, spinel+hdlc+uart://, dan spinel+socket://.

Memahami APEX vendor

Serupa dengan stack Thread di modul utama Tethering, layanan HAL Thread default di Cuttlefish juga dikemas dalam modul APEX. Namun, ini adalah modul APEX vendor yang akan diinstal ke /vendor/apex/ (Artefak dalam modul akan diekstrak ke /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
    ],
}

Ada beberapa konfigurasi penting yang perlu Anda perhatikan atau ubah saat mem-build modul HAL APEX Anda sendiri:

  • file_contexts: Ini menjelaskan file biner / data yang dikirim dalam modul APEX ini atau file yang perlu diakses oleh layanan HAL (misalnya, perangkat RCP). Hal ini memungkinkan Anda menentukan aturan sepolicy tertentu untuk layanan HAL agar dapat mengakses perangkat RCP hardware.

  • binaries: File biner yang dikirim dalam modul APEX ini

  • threadnetwork-service.rc: Cara layanan HAL akan dimulai. Anda harus menentukan jalur perangkat RCP di sini.

  • android.hardware.thread_network.prebuilt.xml: Menentukan fitur hardware android.hardware.thread_network. Tindakan ini diperlukan agar sistem Android mengetahui bahwa perangkat Anda memiliki dukungan hardware Thread. Jika tidak, stack Android Thread tidak akan diaktifkan.

Membuat layanan HAL

Baik Anda adalah developer perangkat Android atau vendor silikon, Anda harus mengetahui cara mem-build firmware OT RCP untuk chip Thread. Petunjuk berikut mengasumsikan bahwa chip hardware telah dihubungkan dan divalidasi dengan benar.

Cara termudah untuk mem-build HAL APEX adalah dengan membuat APEX baru dengan biner dan prebuild dari HAL APEX default. Misalnya, jika perusahaan Anda adalah Banana dan perangkat RCP di perangkat Anda adalah /dev/ttyACM0, APEX HAL Thread Anda akan terlihat seperti ini:

  • 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

Jalur file di kolom pertama terkait dengan /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
  }

Dengan asumsi Anda membuat perangkat baru bernama Orange, direktori konfigurasi khusus perangkat Anda akan seperti:

device/banana/orange/threadnetwork/
    sepolicy/
    Android.bp
    file_contexts
    manifest.json
    threadnetwork-default.xml
    threadnetwork-service.rc

Lihat bagian berikutnya untuk mengetahui aturan sepolicy yang harus ditambahkan di subdirektori sepolicy/.

Aturan sepolicy untuk perangkat RCP

Secara default, layanan HAL Thread Anda tidak memiliki akses ke perangkat RCP (misalnya /dev/ttyACM0), aturan sepolicy kustom harus ditambahkan ke direktori sepolicy/.

Buat file sepolicy/threadnetwork_hal.te baru dengan konten di bawah:

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;

Menggabungkan

Sekarang Anda telah menyelesaikan hampir semua kebutuhan kode untuk menambahkan Thread. Langkah terakhir adalah menambahkan aturan sepolicy dan Thread HAL APEX ke image perangkat Anda.

Anda dapat melakukannya dengan menambahkan kode di bawah ke Makefile perangkat (misalnya, device.mk):

PRODUCT_PACKAGES += com.banana.hardware.threadnetwork
BOARD_SEPOLICY_DIRS += device/banana/orange/threadnetwork/sepolicy

Jika semuanya berfungsi, sekarang Anda akan dapat melihat log layanan Thread HAL yang mirip dengan:

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

Dan log ot-daemon akan terlihat seperti:

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

Penyesuaian

Modul utama Thread (sebenarnya merupakan bagian dari modul "Tethering") menyediakan beberapa konfigurasi yang dapat di-overlay yang dapat ditentukan oleh vendor untuk menyesuaikan perilaku stack. Lihat config_thread.xml untuk mengetahui daftar lengkapnya.

Biasanya, Anda harus menetapkan config_thread_border_router_default_enabled ke true untuk mengaktifkan perangkat sebagai Router Pembatas Thread, dan mengubah config_thread_vendor_name, config_thread_vendor_oui, dan config_thread_model_name ke nilai vendor atau produk Anda. Nilai tersebut akan disertakan dalam layanan mDNS _meshcop._udp yang selalu diiklankan oleh Thread Border Router.

Untuk menambahkan overlay, Anda perlu membuat target ConnectivityOverlayOrange runtime_resource_overlay baru untuk perangkat Orange. Buat direktori ConnectivityOverlay/ baru di bagian device/banana/orange/rro_overlays dan buat konten di bawah ini di dalamnya:

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:
  <bool name="config_thread_border_router_default_enabled">true</bool>
  <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>
  

Serupa dengan HAL APEX, Anda perlu menambahkan aplikasi overlay ke file device.mk:

PRODUCT_PACKAGES += \
    ConnectivityOverlayOrange</code>

Jika semuanya berfungsi, Anda akan melihat bahwa ot-daemon mencatat nama vendor dan model di awal log:

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

Kompatibel dengan Google Home

Selain itu, jika ingin membuat Border Router digunakan oleh ekosistem Google Home, Anda dapat menentukan konfigurasi ini di config_thread.xml:

<string-array name="config_thread_mdns_vendor_specific_txts">
  <item>vgh=1</item>
</string-array>

Pengujian

Perangkat Anda kini harus kompatibel dengan spesifikasi Border Router Thread 1.3+. Sebelum mengirimkannya ke program sertifikasi Thread, ada beberapa pengujian Android xTS yang harus dilakukan untuk memastikan kompatibilitas.

  • Pengujian VTS memastikan layanan Thread HAL berfungsi seperti yang diharapkan di perangkat Anda. Anda dapat menjalankan pengujian dengan perintah

    atest VtsHalThreadNetworkTargetTest

  • Pengujian CTS memastikan Thread API berfungsi seperti yang diharapkan di perangkat Anda. Anda dapat menjalankan pengujian dengan perintah

    atest CtsThreadNetworkTestCases

  • Pengujian integrasi memberikan jaminan kualitas yang lebih baik tentang cara kerja kode utama Thread di perangkat Anda. Anda dapat menjalankan pengujian dengan perintah

    atest ThreadNetworkIntegrationTests

Anda juga dapat menemukan petunjuk selengkapnya tentang cara menjalankan pengujian VTS/CTS/MTS dengan suite pengujian yang dirilis tersebut:

Menguji dengan aplikasi demo Thread

Serupa dengan perangkat Cuttlefish, Anda dapat menambahkan aplikasi demo Thread ke image sistem:

# ThreadNetworkDemoApp for testing
PRODUCT_PACKAGES_DEBUG += ThreadNetworkDemoApp

Perhatikan bahwa Anda hanya boleh menambahkannya ke varian debug / eng (misalnya, PRODUCT_PACKAGES_DEBUG) karena tidak boleh disertakan dalam build pengguna untuk konsumen akhir.