Debugging software apps for Android-based designs using USB

Rajaram Regupathy, Cypress Semiconductor

December 20, 2014

Rajaram Regupathy, Cypress SemiconductorDecember 20, 2014

Editorial note: Excerpted from Unboxing Android: A hands on approach with real world examples by Rajaram Regupathy. The author takes you through the process of debugging software applications on Android-based mobile and Internet of Things devices by using the Universal Serial Bus (USB) to access the Android Debug Bridge.

Android Debug Bridge, popularly referred to as ADB, is the tool that Google provides along with the Android framework to facilitate debugging and managing an Android system. ADB uses USB or TCP as its transport layer to communicate with an Android-powered device. ADB works in a simple client/server architecture, and is made up of three key components, namely:

  • A server runs in the background of the host system and communicates between the client and the ADB daemon running on an emulator or device. The server also maintains details of the connected device along with its state.
  • A client on the host system that connects to the server, which can be an adb shell or adb logcat command that runs on a terminal to the Dalvik Debug Monitor Server
  • (DDMS) tool.
  • An ADB daemon that runs on the Android device/emulator as part of the Android USB framework and interacts with the server to help manage the Android-powered device.

It is important to note that on a host environment, the ADB server and the ADB client share the same binary in the host environment. Figure 1 illustrates how these three components fit in an ADB setup.



Figure 1. An ADB setup with its three key modules

One of the most commonly used ADB commands is the adb shell command. Assume that an Android device is connected to the host PC using USB with the Android Debug Bridge option enabled on the device by going to Settings ➤ Developer Options. In this scenario, the terminal where the ABD shell is running is the client, and the command invokes the ADB server adb on the host PC. The ADB server then talks to the host PC to the ADB daemon adbd on the Android device over the USB to service the shell commands.

Another example is the Dalvik Debug Monitor Server (DDMS) debugging tool, an eclipse plug-in tool that provides screen captures and logcat, and processes information for an Android device. The DDMS tool in the background relies on ADB’s services for its operations. In this setup, the DDMS tool is the client component of the ADB setup. Figure 2 illustrates the terminal and DDMS of an ADB setup.



Figure 2. A terminal/DDMS ADB setup

Setting Up ADB
Whether you are using Windows-based PC or a Linux workstation, to set up ADB on a host PC, the first step is to download the Android SDK.

Windows. When extracting the SDK, you can find the adb.exe tool in the adt-bundle-windows-x86-20130917\sdk\platform-tools folder. Since the SDK package does not update the PATH, you have to set the platform tools folder in the PATH environmental variable. This will allow you to run ADB from any location from a command prompt.

Now, connect an Android-powered device to the host PC with ADB enabled under Developer options. This should make the ADB function available to the host PC, and can be confirmed using a simple ADB command called adb devices. This command will print a list of all attached emulator/device instances. Sometimes, you may need to configure a USB vendor ID for the Android-powered device in a special file called adb_usb.ini.

This file will be created in the .android folder in the user’s home directory ($HOME) when installing the ADB setup. (For example, c:/Users/<user name>/.android for Windows7). If the folder has not been created yet, this folder has to be created along with the adb_usb.ini file. This setup is required because internally within the ABD host implementation, vendor IDs are matched (is_adb_interface) against a set of built-in vendor IDs, which are defined in system/core/adb/usb_vendors.c#builtInVendorIds. The ADB host implementation reads the INI file in order to update the vendor ID list, along with the existing built-in vendor ID list in system/core/adb/usb_ vendors.c (the usb_vendors_init function).

You can also set the ANDROID_SDK_HOME environmental variable if for some reason you want to place the .android folder in a different location. This environmental variable should be set to the path of the .android folder, which is read by the ADB implementation for the INI file path.

Linux. In Linux, the same rules apply, except in regard to how these rules are actually set. To enable ADB to be run from any location from a terminal, set the PATH environmental variable with the installation path.

   export PATH=${PATH}:/<>/android-sdk-linux/tools
   export PATH=${PATH}:/<>/android-sdk-linux/platform-tools


The .android/adb_usb.ini folder can be created in the user’s home folder to add any unsupported vendor IDs, just like with the Windows setup. The only difference in a Linux setup is that you have to provide permission for a normal user account to be able to access the ADB interface of the USB device. This can be achieved by adding udev rules, as discussed below, with execution permission in the /etc/udev/rules.d/androids.rules file.

   $ cat /etc/udev/rules.d/androids.rules 
   SUBSYSTEM=="usb", ATTR{idVendor}=="04B4", MODE="0666"


Now, when you run the adb devices command on the terminal, the Android device will be listed with a serial number.

If the ADB is not be detected even after going through the above mentioned steps, then In this situation, you might have to restart the ADB server by running the adb kill-server command.

ADB Protocols
Recall that there are two types of ADB commands. There are ADB commands whose information lies within the server, and there are ADB commands that require fetching information from the daemon on the Android-powered device by the ADB server. A command that is serviced within the server without communicating with the Android device is referred to as host service, and commands that are serviced after fetching information from the device through the daemon are termed local services.
In this section, we’ll explore the protocol involved in the host service and the local service, which is over a transport medium like USB.

Client <-> Server Protocol. In an ADB setup, the mode of communication between a client and a server is through standard socket programming over TCP. In this setup, the ADB server listens to TCP port 5037 of the host, to which the client has to send the request. The format of the request that the client has to send is shown in Figure 3.



Figure 3. The protocol packet format

The request from an ADB client should contain an initial four-byte field in ASCII and a payload. The payload generally starts with the prefix keyword host:, which indicates that the request is addressed to the server. Upon receiving the request, the server will reply with an OKAY or FAIL string to indicate the status of the request. That string is then followed by an optional payload containing the length and requested data. To better understand practically how the packets are seen on the socket, you can use a TCP port-monitoring tool like Wireshark or tcpdump. Figure 4 shows how a client’s request will look with various ADB commands.



Figure 4. Wiresharkdump showing client and server communication over TCP

Server <-> ADB daemon protocol. There are command requests from ABD clients that require information from the Android-powered device or emulator. The ADB server uses two types of transport, mostly depending on the type of setup. When a host is connected to a physical Android-powered device over USB, it uses USB as the transport, and in the case of an Android emulator, the transport is through TCP. The protocol is simple and straightforward; it simply has to forward the packet to and from the server. The command messages of the protocol layer consist of a 24-byte header followed by an optional payload, (each field size is four bytes), as shown here:

   struct message {
      unsigned command;     /* command identifier constant */
      unsigned arg0;        /* first argument */
      unsigned arg1;        /* second argument */
      unsigned data_length; /* length of payload (0 is allowed) */
      unsigned data_crc32;  /* crc32 of data payload */
      unsigned magic;       /* command ^ 0xffffffff */
   };

The message can contain any of the following commands with the data length, which indicates the payload length, and are generally quoted as a string of ASCII characters.

   #define A_SYNC 0x434e5953
   #define A_CNXN 0x4e584e43
   #define A_AUTH 0x48545541
   #define A_OPEN 0x4e45504f
   #define A_OKAY 0x59414b4f
   #define A_CLSE 0x45534c43
   #define A_WRTE 0x45545257


You can read more detailed information on the format of the command and services of the two protocols in the following files:

   system/core/adb/SERVICES.TXT

   system/core/adb/OVERVIEW.TXT

   system/core/adb/protocol.txt


After you gain an understanding of ADB protocols and their setup, the following section explores how this protocol is implemented in a host and an Android device environment. This section also covers activity sequences on how the information flows to and from the Android daemon in the Android USB framework.

< Previous
Page 1 of 3
Next >

Loading comments...