--- sidebar_position: 1 --- # Architecture This part describes the architecture of native ADB and Web ADB, and why there are designed in this way. ## Native ADB Native ADB has three components:
``` ┌───────────────────────────────┐ ┌──────────────┐ │ │ │ │ │ ┌───────────┐ ┌────────┐ │ │ ┌──────────┐ │ │ │ ├─────► ├──┼──┼─► │ │ │ │ Client A │ │ │ │ │ │ Daemon A │ │ │ │ ◄─────┤ ◄──┼──┼─┤ │ │ │ └───────────┘ │ │ │ │ └──────────┘ │ │ │ │ │ │ │ │ ┌───────────┐ │ Server │ │ │ Device A │ │ │ ├─────► │ │ │ │ ┌──────────────┐ │ │ Client B │ │ │ │ └──────────────┘ │ │ │ │ ◄─────┤ │ │ │ ┌──────────┐ │ │ └───────────┘ │ ├──┼────────────────────┼─► │ │ │ │ │ │ │ │ Daemon B │ │ │ │ ◄──┼────────────────────┼─┤ │ │ │ Computer A └──▲──┬──┘ │ │ └──────────┘ │ │ │ │ │ │ │ └──────────────────────┼──┼─────┘ │ Device B │ │ │ │ │ ┌───────────────┐ │ │ └──────────────┘ │ │ │ │ │ ┌───────────┐ │ │ │ │ │ ├─┼──────┘ │ │ │ Client C │ │ │ │ │ ◄─┼─────────┘ │ └───────────┘ │ │ │ │ Computer B │ │ │ └───────────────┘ ```
### Client **Client** receives command line inputs, generates request packets, sends them to **server** over TCP. Because there can be multiple devices connected to the computer, **clients** add a "host prefix" to specify the device. ### Server **Server** is in the same binary as **client**, but runs in a separate process with different command line arguments. Usually **servers** are spawned by **clients** when they cannot find one on localhost. To manually spawn a **server**, use `adb server nodaemon`. By default, it binds to `localhost:5037`. It is also possible to use SSH tunnel to let **clients** connect to a **server** running on a remote machine. **Servers** are responsible for discovering and connecting to devices. They also handle packets from **clients**. Some packets should be processed by **server** itself (for example `adb devices`), it generates response packets and sends them to **client**. Others need to be forwarded to **daemons** (for example `adb shell`). It finds the specified **daemon** using the "host prefix", rewrites the packet to remove "host prefix", and finally sends it to the **daemon** over USB (libusb/WinUSB) or TCP. Because USB APIs only allow one connection to a device simultaneously, to use multiple CLI applications with one device, the **server** is required to multiplex the packets. ### Daemon **Daemon** runs on Android devices and emulators, it receives packets, handles them, and generates responses. Historically, because most device only has one USB port, **daemons** can only handle one connection. But even after ADB over Wi-Fi has been added, one **daemon** can still handle one TCP connection. ### Protocol All packets between **client-server** and **server-daemon** are in the ADB packet format, but as mentioned before, **client-server** packets contain an extra "host prefix". ADB packet format will be described in [packet](./packet.md) chapter, while "host prefix" will be described in [stream](./stream.md) chapter. ## Web ADB Web ADB reuses native ADB daemons, but there is no **client**/**server**: One application, one connection, to one device.
``` ┌──────────────────────────────────┐ ┌──────────────┐ │ │ │ │ │ ┌──────────┐ ┌─────────────┐ │ │ ┌──────────┐ │ │ │ ├────► ├──┼──┼─► │ │ │ │ Core A │ │ Backend A │ │ │ │ Daemon A │ │ │ │ ◄────┤ ◄──┼──┼─┤ │ │ │ └──────────┘ └─────────────┘ │ │ └──────────┘ │ │ │ │ │ │ │ │ Device A │ │ │ │ │ ┌──────────────┐ │ │ └──────────────┘ │ │ │ ┌──────────┐ ┌─────────────┐ │ │ ┌──────────┐ │ │ │ ├────► ├──┼────────────────────┼─► │ │ │ │ Core B │ │ Backend B │ │ │ │ Daemon B │ │ │ │ ◄────┤ ◄──┼────────────────────┼─┤ │ │ │ └──────────┘ └─────────────┘ │ │ └──────────┘ │ │ │ │ │ │ JavaScript Runtime │ │ Device B │ │ │ │ │ └──────────────────────────────────┘ └──────────────┘ ```
### Core **Core** is the `@yume-chan/adb` package. It generates data in ADB protocol, without "host prefix" (not needed because packets are directly sent to **daemons** via a **backend**). ### Backend One **backend** defines one method to transmit and receive ADB packets. There are already multiple backend implementations, for example `@yume-chan/adb-backend-usb` and `@yume-chan/adb-backend-ws`. One **core** instance requires one **backend** instance, so it only connects to one device. Because JavaScript runtimes are generally more isolated, sharing devices between multiple application is not a consideration. However, it is still very easy to share a **core** instance within a single application, and if a runtime has more privileges, sharing **core** using a custom protocol is also not impossible. Having Backend as an independent part also makes it extremely easy to port to other runtimes (Web Browsers, Node.js, Electron, etc.). Possible Backend implementations: * Web Browsers * WebUSB API (USB) * WebSocket + Custom WebSockify forwarder (TCP) * Node.js/Electron * Any USB libraries (USB) * `net` module (TCP) * WebSocket + Custom WebSockify forwarder (TCP) ## Comparison | | Native ADB | Web ADB | | -------------------------------- | -------------------------------------- | -------------------- | | Who implements all ADB commands? | Client | Core | | Who directly talks to device? | Server | Backend | | How does them talk internally? | TCP Socket (variation of ADB protocol) | JavaScript API calls |