Remote Application Debug on Android* OS





Remote Android* OS Application Debug

 

Android* Debug Bridge

The Android Debug Bridge (ADB) is a command line tool that handles debug communication between a debugger on the host (usually GDB* or DDMS* (Dalvik* Debug Monitor Server) as well as ADT) and an Android* image running on the target. The target image could be running on device emulation or running on a physical development device, which you communicate with via USB-OTG (On-The-Go) or USB-to-Ethernet dongle. In short, ADB is the glue that makes application debug on Android* possible.

The device you are connecting to or emulating could cover a wide range of form factors. Typically it would be a smartphone or tablet. It could however just as well be a medical tablet or an embedded device in industry, home energy management, warehousing or any number of intelligent systems applications.

Setting up the Android Debug Bridge to allow remote debugging of an Intel® AtomTM Processor based platform does not differ very much from debugging on other architectures.

First you will need the Android* SDK including ADB* installed on the development host. Instructions for this can be found at http://developer.android.com/sdk/installing.html.

Setting up ADB*

If your target image is running on a physical device the first thing that needs to be done is to include USB-OTG or USB-to-Ethernet support. For USB-to-Ethernet support a kernel configuration change and rebuild is required. Your OEM will provide you with the necessary information if desired.

The standard method for remote application debug is to use the existing USB-OTG interface of most Android devices. The setup is described in quite some detail at the Android* developer website: http://developer.android.com/guide/developing/device.html.

The key steps as outlined there are

1.      Declare your application as "debuggable" in your Android Manifest.

When using Eclipse, you can skip this step, because running your app directly from the Eclipse IDE automatically enables debugging.

In the AndroidManifest.xml file, add android:debuggable="true" to the <application> element.

Note: If you manually enable debugging in the manifest file, be sure to disable it before you build for release (your published application should usually not be debuggable).

2.      Turn on "USB Debugging" on your device.

On the device, go to Settings > Applications > Development and enable USB debugging (on an Android 4.0 device, the setting is located in Settings > Developer options).

3.      Set up your system to detect your device.

o   If you're developing on Windows, you need to install a USB driver for adb. For an installation guide and links to OEM drivers, see the OEM USB Drivers document.

o   If you're developing on Mac OS* X, it just works. Skip this step.

o   If you're developing on Ubuntu* Linux*, you need to add a udev rules file that contains a USB configuration for each type of device you want to use for development. In the rules file, each device manufacturer is identified by a unique vendor ID, as specified by the ATTR{idVendor} property. For a list of vendor IDs, see USB Vendor IDs, below. To set up device detection on Ubuntu Linux:

Log in as root and create this file: /etc/udev/rules.d/51-android.rules.

Use this format to add each vendor to the file:
SUBSYSTEM=="usb", ATTR{idVendor}=="<vendor id>", MODE="0666", GROUP="plugdev"

Note: The rule syntax may vary slightly depending on your environment. Consult the udev documentation for your system as needed. For an overview of rule syntax, see this guide to writing udev rules.

Now execute:
chmod a+r /etc/udev/rules.d/51-android.rules

When plugged in over USB, can verify that your device is connected by executing adb devices from your SDK platform-tools/ directory. If connected, you'll see the device name listed as a "device."

With the Android OS booted on the CDK connect a USB-OTG cable to the (USB mini b) port on the CDK and the other end of the cable (USB A) to your development host. 

If everything is working you should be able to run the following command to see the attached device:

$ adb devices

* daemon not running. starting it now *

* daemon started successfully *

List of devices attached

0123456789ABCDEF  device                                                       

Note: To see which device name is assigned to this connection on the Linux dev. host you can look at dmesg to find the address of the "usb-storage: device found at <num>" and then do an "ls -l /dev/bus/usb/*" listing to find that number.

 

ADB on Windows*

Download and install Eclipse Classic from http://www.eclipse.org/downloads/   

Download the Android* SDK package for Windows* from http://developer.android.com/sdk/index.html. (android-sdk_r18-windows.zip, or installer_r18-windows.exe).

After installing the Android* SDK, adb.exe will be located at <install-dir>\android-sdk\platform-tools

 

ADB Host-Client Communication

Thus far we focused on installing ADB on the development host. In reality it is a client-server program that includes three components:

A client, which runs on your development machine. You can invoke a client from a shell by issuing an adb command. Other Android tools such as the ADT plugin and DDMS also create adb clients.

A server, which runs as a background process on your development machine. The server manages communication between the client and the adb daemon running on an emulator or device.

A daemon, which runs as a background process on each emulator or device instance. 

When you start an adb client, the client first checks whether there is an adb server process already running. If there isn't, it starts the server process. When the server starts, it binds to local TCP port 5037 and listens for commands sent from adb clients-all adb clients use port 5037 to communicate with the adb server.

The server then sets up connections to all running emulator/device instances. It locates emulator/device instances by scanning odd-numbered ports in the range 5555 to 5585, the range used by emulators/devices. Where the server finds an adb daemon, it sets up a connection to that port. Note that each emulator/device instance acquires a pair of sequential ports - an even-numbered port for console connections and an odd-numbered port for adb connections. For example:

 Emulator 1, console: 5554

 Emulator 1, adb: 5555

 Emulator 2, console: 5556

 Emulator 2, adb: 5557 ...

As shown, the emulator instance connected to adb on port 5555 is the same as the instance whose console listens on port 5554.

Once the server has set up connections to all emulator instances, you can use adb commands to control and access those instances. Because the server manages connections to emulator/device instances and handles commands from multiple adb clients, you can control any emulator/device instance from any client (or from a script).

 

Startup ADB 

Type "adb shell". You will get a # sign to indicate connection is successful.

$ adb shell

 

Key ADB Device Commands 

The commands listed below help to transfer the debuggee application onto the target device or emulation from the command line. This can be very helpful, especially if no ssh terminal connection is available.

  adb push <local> <remote>    - copy file/dir to device

  adb pull <remote> [<local>]  - copy file/dir from device

  adb sync [ <directory> ]     - copy host->device only if changed

                                 (-l means list but don't copy)

                                 (see 'adb help all')

  adb shell                    - run remote shell interactively

  adb shell <command>          - run remote shell command<

  adb emu <command>            - run emulator console command<

  adb logcat [ <filter-spec> ] - View device log

  adb forward <local> <remote> - forward socket connections forward specs are one of:<tcp:<port>>

                                  localabstract:<unix domain socket name>

                                  localreserved:<unix domain socket name>

                                  localfilesystem:<unix domain socket name>

                                   dev:<character device name>

                                   jdwp:<process pid> (remote only)

  adb jdwp                     - list PIDs of processes hosting a JDWP transport

  adb install [-l] [-r] [-s] <file> - push this package file to the device and install it

                                 ('-l' means forward-lock the app)

                                 ('-r' means reinstall the app, keeping its data)

                                 ('-s' means install on SD card instead of internal storage)

  adb uninstall [-k] <package> - remove this app package from device

                                 ('-k' means keep the data and cache directories)

More details on adb setup and usage can be found at  http://developer.android.com/guide/developing/tools/adb.html

 

Debugging C/C++ native code with GDB* - The GNU Project Debugger 

When debugging with GDB, gdbserver running on the device is used to handle debug communication, however you may still be using a an underlying USB-to-Ethernet dongle driver with ADB to handle to communication transport layer on which gdbserver communicates via tcp/ip protocol with GDB running on the development host.

There is a gdbclient application that sets up the debug communication environment and launches gdbserver on the debuggee device.

usage: gdbclient EXECUTABLE :PORT [PROG_PATH]

EXECUTABLE  executable name (default app_process)

PORT  commection port (default :1234)

PROG_PATH   executable full path on target (ex /system/bin/mediaserver)

If PROG_PATH is set, gdclient tries to launch gdbserver and attach it to the running PROG_PATH

Launching gdbserver explicitly the following command can be used 

# gdbserver :1234 --attach 269

Attached; pid = 269

Listening on port 1234

 

The step by step debug session launch instructions below illustrate how ADB is still underlying the debug communication even if GDB and not ADT or DDMS are used for debug. Let us assume that port 1234 is being used.

Launch process:

gdbserver :1234 /system/bin/executable

 or attach to an existing process:

gdbserver :1234 --attach pid

On your workstation, forward port 1234 to the device with adb:

adb forward tcp:1234 tcp:1234


Start a special version of gdb that lives in the "prebuilt" area of the source tree:

prebuilt/Linux/toolchain-eabi-4.x.x/bin/i686-android-linux-gdb (for Linux)

prebuilt/darwin-x86/toolchain-eabi-4.x.x/bin/i686-android-linux-gdb (for Darwin)

 

If you can't find either special version of gdb, run find prebuilt -name i686-android-linux-gdbin your source tree to find and run the latest version. 

Make sure to use the copy of the executable in the symbols directory, not the primary android directory, because the one in the primary directory has been stripped of its symbol information. 

In GDB, Tell GDB where to find the shared libraries that will get loaded:

set solib-absolute-prefix /absolute-source-path/out/target/product/product-name/symbols

set solib-search-path /absolute-source-path/out/target/product/product-name/symbols/system/lib

absolute-source-path is the path to your source tree.

 

Make sure you specify the correct directories - GDB may not tell you if you make a mistake.

Connect to the device by issuing the GDB command:

(gdb) target remote :1234

The :1234 tells gdb to connect to the localhost port 1234, which is bridged to the device by adb. 

Now you can start debugging native C/C++ code running on Android* with GDB the same way you are used to.

Please see the GDB* - The GNU Project Debugger documentation for details.

 

Using the ADT* Plugin for Eclipse* to debug Android* applications

For Intel® Architecture based devices the setup process does not vary significantly to what is described at http://developer.android.com/sdk/eclipse-adt.html#installing

The ADT* plugin provides full Eclipse* IDE integrated application debug for Intel® architecture based emulators as well as target devices. It provides two different debug perspectives with different feature sets.

You can switch between either one as needed and they both provide different strengths when debugging applications.



The Debug Perspective in Eclipse* 

The Debug Perspective in Eclipse gives you access to the following tabs:

Debug - Displays previously and currently debugged Android applications and its currently running threads

Variables - When breakpoints are set, displays variable values during code execution

Breakpoints - Displays a list of the set breakpoints in your application code

LogCat - Allows you to view system log messages in real time. The LogCat tab is also available in the DDMS perspective.

 

You can access the Debug Perspective by clicking Window > Open Perspective > Debug. Refer to the appropriate documentation for the Eclipse debugger for more information.

 

The DDMS Perspective

The DDMS Perspective in Eclipse lets you access all of the features of DDMS from within the Eclipse IDE. The following sections of DDMS are available to you:

Devices - Shows the list of devices and AVDs that are connected to ADB.

Emulator Control - Lets you carry out device functions.

LogCat - Lets you view system log messages in real time.

Threads - Shows currently running threads within a VM.

Heap - Shows heap usage for a VM.

Allocation Tracker - Shows the memory allocation of objects.

File Explorer - Lets you explore the device's file system.

 

Application Runtime Environment for Debug

The difference when debugging an Android* application targeted for an Intel® architecture based device comes in when setting up the debug target device.

Selecting the target device using the Android* Virtual Device Manager that is part of the Android* SDK, you go to Window>AVD Manager in the Eclipse* IDE's pulldown menu. There you need to make sure to select Intel Atom as the EABI target for the OS image and the device emulation.

avd_intel.jpg

If you followed the steps outlined at the beginning of the article for setting up ADB* and establishing a debug bridge to a physical device you will see a device chooser entry in the Eclipse IDE from which you can pick the target for application deployment and debug.

device_chooser.jpg

Beyond that debugging an Android* application targeted for Intel® architecture is indeed not different then debugging an Android* application that targets ARM* architecture. 

Everything outlined at http://developer.android.com/guide/developing/debugging/index.html applies.