Android Debugging Instructions

Chrome on Android has java and c/c++ code. Each “side” have its own set of tools for debugging. Here's some tips.

Launching

You can run the app by using one of the wrappers.

# Installs, launches, and enters logcat.
out/Default/bin/content_shell_apk run --args='--disable-fre' 'data:text/html;utf-8,<html>Hello World!</html>'
# Launches without first installing. Does not show logcat.
out/Default/bin/chrome_public_apk launch --args='--disable-fre' 'data:text/html;utf-8,<html>Hello World!</html>'

Logging

Chromium logging from LOG(INFO) etc., is directed to the Android logcat logging facility. You can filter the messages, e.g. view chromium verbose logging, everything else at warning level with:

# Shows a coloured & filtered logcat.
out/Default/bin/chrome_public_apk logcat [-v]  # Use -v to show logs for other processes

Warnings for Blink developers

  • Do not use fprintf or printf debugging! This does not redirect to logcat.

  • Redirecting stdio to logcat, as documented here, has a bad side-effect that it breaks adb_install.py. See here for details.

Take a Screenshot

build/android/screenshot.py /tmp/screenshot.png

Inspecting the View Hierarchy

Generate an Android Studio project, and then use Layout Inspector.

Debugging Java

For both apk and test targets, pass --wait-for-java-debugger to the wrapper scripts.

Examples:

# Install, launch, and wait:
out/Default/bin/chrome_public_apk run --wait-for-java-debugger

# Launch, and have GPU process wait rather than Browser process:
out/Default/bin/chrome_public_apk launch --wait-for-java-debugger --debug-process-name privileged_process0

# Have Renderers wait:
out/Default/bin/chrome_public_apk launch --args="--renderer-wait-for-java-debugger"

# Have tests wait:
out/Default/bin/run_chrome_public_test_apk --wait-for-java-debugger
out/Default/bin/run_chrome_junit_tests --wait-for-java-debugger  # Specify custom port via --debug-socket=9999

Android Studio

  • Open Android Studio (instructions)
  • Click “Run”->“Attach debugger to Android process” (see here for more).
  • Click “Run”->“Attach to Local Process...” for Robolectric junit tests.

Eclipse

  • In Eclipse, make a debug configuration of type “Remote Java Application”. Choose a “Name” and set “Port” to 8700.

  • Make sure Eclipse Preferences > Run/Debug > Launching > “Build (if required) before launching” is unchecked.

  • Run Android Device Monitor:

    third_party/android_sdk/public/tools/monitor
    
  • Now select the process you want to debug in Device Monitor (the port column should now mention 8700 or xxxx/8700).

  • Run your debug configuration, and switch to the Debug perspective.

Debugging C/C++

While the app is running, use the wrapper script's gdb command to enter into a gdb shell.

When running with gdb attached, the app runs extremely slowly.

# Attaches to browser process.
out/Default/bin/content_shell_apk gdb
out/Default/bin/chrome_public_apk gdb

# Attaches to gpu process.
out/Default/bin/chrome_public_apk gdb --debug-process-name privileged_process0

# Attach to other processes ("chrome_public_apk ps" to show pids).
out/Default/bin/chrome_public_apk gdb --pid $PID

When connecting, gdb will complain of not being able to load a lot of libraries. This happens because of java code. The following messages are all expected:

Connecting to :5039...
warning: Could not load shared library symbols for 211 libraries, e.g. /system/framework/arm/boot.oat.
Use the "info sharedlibrary" command to see the complete listing.
Do you need "set solib-search-path" or "set sysroot"?
Failed to read a valid object file image from memory.

Using Visual Studio Code

While the app is running, run the gdb command with --ide:

out/Default/bin/content_shell_apk gdb --ide

Once the script has done its thing (generally ~1 second after the initial time its used), open vscode.md and ensure you have the Android launch entry.

Connect via the IDE's launch entry. Connecting takes 30-40 seconds.

When troubleshooting, it's helpful to enable engine logging.

Known Issues:

  • Pretty printers are not working properly.

Waiting for Debugger on Early Startup

# Install, launch, and wait:
out/Default/bin/chrome_public_apk run --args="--wait-for-debugger"
# Launch, and have GPU process wait rather than Browser process:
out/Default/bin/chrome_public_apk launch --args="--wait-for-debugger-children=gpu-process"
# Or for renderers:
out/Default/bin/chrome_public_apk launch --args="--wait-for-debugger-children=renderer"

With an IDE

Once gdb attaches, the app will resume execution, so you must set your breakpoint before attaching.

With Command-line GDB

Once attached, gdb will drop into a prompt. Set your breakpoints and run “c” to continue.

Symbolizing Crash Stacks and Tombstones (C++)

If a crash has generated a tombstone in your device, use:

build/android/tombstones.py --output-directory out/Default

If you have a stack trace (from adb logcat) that needs to be symbolized, copy it into a text file and symbolize with the following command (run from ${CHROME_SRC}):

third_party/android_platform/development/scripts/stack --output-directory out/Default [tombstone file | dump file]

stack can also take its input from stdin:

adb logcat -d | third_party/android_platform/development/scripts/stack --output-directory out/Default

Example:

third_party/android_platform/development/scripts/stack --output-directory out/Default ~/crashlogs/tombstone_07-build231.txt

Deobfuscating Stack Traces (Java)

You will need the ProGuard mapping file that was generated when the application that crashed was built. When building locally, these are found in:

out/Default/apks/ChromePublic.apk.mapping
out/Default/apks/ChromeModernPublic.apk.mapping
etc.

Build the java_deobfuscate tool:

ninja -C out/Default java_deobfuscate

Then run it via:

# For a file:
out/Default/bin/java_deobfuscate PROGUARD_MAPPING_FILE.mapping < FILE
# For logcat:
adb logcat | out/Default/bin/java_deobfuscate PROGUARD_MAPPING_FILE.mapping

Get WebKit code to output to the adb log

In your build environment:

adb root
adb shell stop
adb shell setprop log.redirect-stdio true
adb shell start

In the source itself, use fprintf(stderr, "message"); whenever you need to output a message.

Debug unit tests with GDB

To run unit tests use the following command:

out/Debug/bin/run_test_name -f <test_filter_if_any> --wait-for-debugger -t 6000

That command will cause the test process to wait until a debugger is attached.

To attach a debugger:

build/android/adb_gdb --output-directory=out/Default --package-name=org.chromium.native_test

After attaching gdb to the process you can use it normally. For example:

(gdb) break main
Breakpoint 1 at 0x9750793c: main. (2 locations)
(gdb) continue