Silicon Labs Android 15 Multiprotocol Host Application Support#
Foreword#
This document describes how to integrate and deploy Silicon Labs host applications for Android 15 multiprotocol systems.
For baseline Android Thread platform architecture, use the OpenThread guide: Build an Android Border Router.
This document does not cover AOSP project development fundamentals.
See also#
Overview#
In Android 15, Zigbee protocol control is relatively similar to other environments, while the Thread stack aligns with the conventional AOSP model:
framework and Connectivity services manage Thread APIs and lifecycle
ot-daemonhosts OpenThread Border Router functionalitya vendor Thread HAL service provides radio access
As in other Linux solutions, host applications communicate with a shared Multi-PAN RCP through CPC (cpcd), allowing Thread and Zigbee to run concurrently. For Android 15 support, a new host application, cpc-spinel-proxy, is included for compatibility with the default Thread HAL service, and to enable multi-PAN capabilities without modifying upstream ot-daemon configurations.
This guide assumes that the Android host is connected to a 15.4 enabled SiLabs processor running a project such as OpenThread Zigbee CMP - RCP UART.
Multiprotocol architecture#
Thread and Zigbee host stacks share one physical RCP. cpcd owns the host–RCP link and multiplexes Spinel traffic by interface ID (IID). Each protocol uses a dedicated IID on the same CPC instance (for example cpcd_0).
The Android Thread architecture remains aligned with AOSP; Silicon Labs integration adds a CPC-based transport layer between host applications and the RCP.
Shared radio path
Zigbee host path (iid=1) ──┐ ├──► cpcd ──► Multi-PAN 802.15.4 RCP Thread host path (iid=2) ──┘
Zigbee control path#
Zigbee host application (Z3Gateway) | EZSP | zigbeed | Spinel over CPC (iid=1) | cpcd | Multi-PAN 802.15.4 RCP
Thread control path#
ot-daemon does not connect to CPC directly. It uses the Thread HAL over binder; Spinel IIDs appear only on the HAL socket and on the CPC link behind the proxy.
Android framework / Connectivity | ot-daemon | threadnetwork_hal://binder | vendor.threadnetwork_hal | Unix socket (Spinel, host-iid 0) | cpc-spinel-proxy (translates host-iid 0 <-> CPC iid 2) | Spinel over CPC (iid=2) | cpcd | Multi-PAN 802.15.4 RCP
Spinel IID roles#
On a shared Multi-PAN RCP, each host application uses a dedicated CPC-side IID so cpcd can demultiplex Spinel traffic.
The RCP will also emit broadcast frames tagged with IID 0, which any interested host can subscribe to via iid-list=0.
This table shows a conventional multiprotocol host application routing scheme for Android:
Location | Expected Incoming IID | Expected Outgoing IID | Notes |
|---|---|---|---|
RCP | 1,2 | 0,1,2 | |
threadnetwork_hal | 0 | 0 | POSIX |
zigbeed | 0,1 | 1 | |
cpc-spinel-proxy | 0,2 | 0 | Frames from cpcd: incoming; frames from HAL: outgoing |
Note:
ot-daemonis configured by default to only send and receive Spinel frames on IID 0, which is used as the broadcast frame identifier for multiprotocol configurations.cpc-spinel-proxytranslates incoming and outgoing IID values for Thread frames to maintain this compatibility.
Host application roles in the multiprotocol stack#
Host application | Primary role | Typical interface |
|---|---|---|
| CPC daemon; owns RCP link and endpoint multiplexing |
|
| Thread HAL AIDL service for | Binder + |
| OpenThread Border Router (Tethering module) |
|
| Bridges HAL socket Spinel to CPC | Unix socket + |
| Zigbee host daemon over CPC Spinel |
|
| Zigbee gateway application |
|
CPC proxy application#
There are two specific differences with Thread integration in Android compared to other POSIX environments:
The OpenThread service on POSIX (
otbr_agent) is configured with multi-PAN RCP support, whileot-daemonon Android is not.The default Thread HAL service supports a Unix socket Spinel interface instead of a CPC-based Spinel interface.
The cpc-spinel-proxy project was added in SiSDK 2026.6 to address these differences. It relays frames between the Thread HAL socket and CPCd, and translates Spinel IIDs so the stock HAL (host-iid 0) can share a multi-PAN RCP with Zigbee on CPC iid 2.
For generation, build steps, command-line options, and runtime configuration, see Building cpc-spinel-proxy Locally.
Integration#
There are multiple ways of incorporating these external projects into an AOSP build, and guidance can depend on a particular project's specific details. The following sections provide high-level integration guidance.
Project generation#
Host application | Generation / build guide |
|---|---|
| Building cpc-spinel-proxy Locally — use OpenThread host ARM64 (Android 15 - NDK r27d) |
| Building Zigbeed & Z3Gateway Locally — use Zigbee ARM64 (Android 15 - NDK r27d) for Android 15 images |
| Building CPCd Locally — distributed separately from the SiSDK (cpc-daemon on GitHub) |
Building the applications#
There are two high-level strategies recommended to integrate these host applications into an AOSP system.
Prebuilding the host applications outside of AOSP through the use of the NDK is one option, which effectively treats the host applications as immutable from the perspective of AOSP; this option primarily involves updating the toolchain properties of the generated host application Makefile to point to the toolchain paths of an installed NDK (NDK r27d, API 35).
Incorporating the host applications into the AOSP build may be appropriate if wishing to consolidate build responsibility to within AOSP. The drawback to this approach is needing to create and maintain Android.bp blueprints for the projects. The .project.mak Makefile fragments can be useful for this purpose.
Consider project needs and build system needs when determining the most appropriate strategy.
Enable Thread services#
To enable the required Android services for thread networking, add the following packages to your device.mk:
PRODUCT_PACKAGES += \ com.android.hardware.threadnetwork \ cpcd \ libcpc \ cpc-spinel-proxy
Include zigbeed, Z3Gateway, and other Zigbee modules for multiprotocol products.
Project specific configuration#
For each host executable (cpcd, cpc-spinel-proxy, zigbeed, Z3Gateway, optional socat), define a vendor (or system_ext) domain, label the binary in file_contexts, and grant least-privilege access to: the RCP device (cpcd only), CPC socket trees under /data/vendor/cpcd/, the Thread spinel socket (proxy + hal_threadnetwork_default), and the Zigbee EZSP PTY devices under /dev/zigbee/ or devpts. Align init.rc user/group with socket modes (0660). Use audit2allow on first enforcing boot to close gaps; vendor policy cannot reference all system domains—extend system_ext/private only when platform rules require it (e.g. some zigbeed/Z3Gateway layouts).
When an existing service needs a new configuration (for example vendor.threadnetwork_hal with a spinel+socket:// URL), use an override init.rc fragment in /vendor/etc/init/ rather than editing the APEX-shipped service definition directly.
See Android SELinux Overview for more information on writing SELinux policies.
Recommended initialization order#
Start services closest to the RCP first. Each step should complete (or expose its socket/device) before the next service starts.
Step | Service | Depends on | Ready when |
|---|---|---|---|
1 |
| RCP device file enumeration (/dev/ttyACM) | CPC sockets under |
2 |
|
| HAL proxy Unix socket exists (for example |
3 |
| proxy socket | HAL registered; |
4 |
| Thread HAL | System or manual start; attaches via |
5 |
|
| EZSP interface available (PTY or configured device) |
6 |
|
| Gateway can open EZSP device |
ot-daemon may be started by the Android framework when Thread is enabled; steps 1–3 must be stable before Thread attach is attempted.
Verification#
After boot (or manual service start), confirm the stack from the host toward the RCP:
Process presence
adb shell ps -A | egrep 'cpcd|cpc-spinel-proxy|threadnetwork|ot-daemon|zigbeed|Z3Gateway'
CPC and proxy sockets
adb shell ls -laZ /data/vendor/cpcd/ adb shell ls -laZ /data/vendor/hardware/spinel-proxy.sock
Thread HAL and ot-daemon logs
adb logcat -s android.hardware.threadnetwork-service ot-daemon
Expect HAL “Open IThreadChip successfully” and ot-daemon logs showing HAL service acquisition before RCP reset/attach.
Thread functional check
adb shell ot-ctl state adb shell ot-ctl ifconfig up adb shell ot-ctl thread start adb shell ot-ctl state
Zigbee functional check
With zigbeed and Z3Gateway running, use the gateway CLI over adb shell per your product configuration (same EZSP workflow as on Linux; see Building Zigbeed & Z3Gateway Locally).
Runtime behavior#
Once an image has been built and all host applications are initialized and running, networking functionality can be exercised using adb shell.
With an adb connection, interact with the standard OpenThread CLI using ot-ctl while simultaneously exercising Zigbee through Z3Gateway.