Debugging software apps for Android-based designs using USB -

Debugging software apps for Android-based designs using USB


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-20130917sdkplatform-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//.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_ini t 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:




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.To understand the sequence of activities in a typical ADB setup, consider two simple ADB commands, namely adb devices and adb shell ls ,which will cover the two kinds of services an ADB client can encounter.Before using any of these services, the ADB protocol starts with theconnect command, which establishes the presence of the remote system.Both the host ADB and the ADB daemon send a connect message when theconnection is established. The connect command is attached with apayload that provides version, system identification, string, and themaximum data that the ADB connection can hold. Once this state isachieved, the ADB setup is ready for communication. Any command messagesent before this command is ignored.

Once the connection is established, a user can execute ADB commands. Figure 5 illustrates the flow of information when the adb devices and adb shell ls commands are executed. When the adb devices command is executed, you will notice that the ADB server responds tothe command locally, without contacting the ADB daemon. The ADB servermaintains information on the list of connected devices and their state,which it uses to respond to certain ADB commands, generally termed as“host services.”

Figure 5. A sequence of activities between the client, the server, and the daemon

Inthe next command setup, the command is served by the ADB daemon, andthe ADB server facilitates the command by initiating, and subsequentlyacting in, the pass-through mode. This command generally starts aservice within the ADB daemon or on the device the client interactswith. Figure 5 displays sequential activity for a non-interactivecommand. As an example, the adb shell ls command is illustrated.

Android ADB Architecture
TheADB framework, unlike the other Android USB framework functions, doesnot have a Java or JNI framework component. It also does not expose anyAPI for application development, as the ADB functionality is a developerdebugging framework. The ADB framework is a daemon implemented
in the C language running in the Android user space. This daemon is facilitated by the Android USB framework, namely UsbDeviceManager and UsbDebuggingManager . Figure 6 provides the building blocks of ADB framework within an Android powered device.

Figure 6. The building blocks of ADB inside an Android-powered device

The UsbDeviceManager in the ADB use case is used to enable and disable ADB functionality. The UsbDebuggingManager was introduced with the Jelly Bean 4.2 version of Android, when the RSA-based authentication feature was added for ADB. The UsbDebuggingManager java implementation can be found in the following directory along with the UsbService  framework: frameworks/base/services/java/com/android/server/usb/ . The UsbDebuggingManager opens a line to communicate with an ADB daemon and acts as an interfacebetween the user feedback on authentication and the ADB daemon.

Itcan be inferred from Figure 6 that the ADB daemon implementation relieson the Android kernel USB driver framework to send and receive messagesto an ADB server. The ADB daemon, which is a process that starts whenthe device boots up, is generally started from the init.rc script.

The ADB implementation can be located in the /system/core/adb folder of the Android framework. This folder contains theimplementation of both the ADB daemon and the ADB application that runson a host. These two applications share common files with code that isseparated by the ADB_HOST macro, including adb.c, transport.c , and transport_local.c .

Youmight also remember that the ADB executables share the same binary on ahost environment with the ADB client implementation. The ADB clientimplementation is implemented through the key files called commandline.c and adb_client.c. The source files in the system/core/adb arefor the ADB server and the ADB daemon. To determine the exact filesthat implement respective executables, the best place to look is the file, which generates the respective executables. The following is a snippet from the makefile:

   # adbd device daemon
   # =========================================================

   include $(CLEAR_VARS)


   # adb host tool
   # ================================================


As you can infer from the file list, the ADB daemon and the host executable (adb.exe )share common files, and there are files that are specific to bothimplementations. As discussed, the common files separate the respectiveimplementation by the ADB_HOST macro.

Example 1: Using JDB with ADB
AndroidADB integrates support for Java Debug Wire Protocol (JDWP), a protocolused for communication between a debugger and the virtual machine. Thissection provides a brief summary of the JDWP implementation and explainshow to use Java Debugger (JDB) with ADB. It all starts with an ADBdaemon starting a named Unix server socket called @vm-debug-control ,which a JDWP thread connects to when it starts. After a successfulconnection, the JDWP threads the PID of the process as a string of fourhexadecimal characters.

To connect a debugger, you can simply runthe adb forward tcp: jdwp: command with aninterested PID. This indicates the ADB daemon to share the socketdescriptor with the JDWP process. The JDWP process uses the descriptoras it passes through the connection to the debugger. The ADB JDWPimplementation is spread across dalvik/vm/jdwp/JdwpAdb.cpp  and system/core/adb/jdwp_service.c  for detailed study.

Nextyou’ll see how to get the list of PIDs that use a JDWP service, andthen explore how to connect to the debugger JDB. The first step is touse the adb jdwp command, which lists the PIDs that implement JDWP, asshown here:

   root@rajaram-pc:/home/rajaram# adb jdwp

Now connect JDB to the JDWP process using the adb forward command, as shown in the following snippet. Then you connect to JDB using jdb -attach localhost:port.

   root@rajaram-pc:/home/rajaram# adb forward tcp:8000 jdwp:1384
   root@rajaram-pc:/home/rajaram# jdb -attach localhost:8000
   Set uncaught java.lang.Throwable
   Set deferred uncaught java.lang.Throwable
   Initializing jdb …

       > threads
   Group system:
      (java.lang.Thread)0xc141b1e358 <8> FinalizerWatchdogDaemon
   cond. waiting
      (java.lang.Thread)0xc141b1e1a8 <7> FinalizerDaem cond. waiting

Once you’re connected with JDB, you can debug your application using the JDB commands.

Example 2: Backing Up Your Phone with ADB
Anotherkey feature of ADB is the ability to back up your Android device to ahost PC and then restore it on the device. This feature can be handy ifyou lose data from your Android device. The following command-linesnippet lists the various adb backup options:

adb backup [-f ] [-apk|-noapk] [-shared|-noshared] [-all] [-system|nosystem][]
      – write an archive of the device's data to .
   If no -f option is supplied then the data is written
   to “backup.ab” in the current directory.
   (-apk|-noapk enable/disable backup of the .apks themselves
     in the archive; the default is noapk.)
   (-shared|-noshared enable/disable backup of the device's
     shared storage / SD card contents; the default is noshared.)
   (-all means to back up all installed applications)
   (-system|-nosystem toggles whether -all automatically includes
     system applications; the default is to include system apps)
   (is the list of applications to be backed up. If
     the -all or -shared flags are passed, then the package
     list is optional. Applications explicitly given on the
     command line will be included even if -nosystem would
     ordinarily cause them to be omitted.)

Thebackup command provides an option to choose the type of data for backupor even ignore certain data. This backup mechanism requires userintervention on the Android device side, as it provides the user anoption to set a password for the backup and allow or deny the backupprocess, as shown in Figure 7.

Figure 7. User interface option in an Android device when the ABD backup command is executed.

To read more about software development on the Android platform, go to The basics of USB device development using the Android framework.

Rajaram Regupathy works as Principal Software Engineer with Cypress Semiconductor. He hasmore than 15 years of professional experience in developing firmwareand system software embedded products. He enjoys designing anddeveloping new technology products from scratch. He has patents inembedded domain and is also a senior ACM member and Linux and opensource enthusiast. He has published books on Linux USB stack programmingand other open source articles.

Used with permission fromApress Media LLC, a division of Springer Science+BusinessMedia.Publishing, Copyright 2014. This article was excerpted from Unboxing Android: A hands on approach with real world examples , by Rajaram Regupathy.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.