Chrome on Android has java and c/c++ code. Each “side” have its own set of tools for debugging. Here's some tips.
See also go/clankium/06-debugging-clank.
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>'
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
If this doesn‘t display the logs you’re looking for, try adb logcat
with your system adb
or the one in //third_party/android_sdk/
.
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.
build/android/screenshot.py /tmp/screenshot.png
Generate an Android Studio project, and then use Layout Inspector.
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
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.
While the app is running, use the wrapper script's lldb
command to enter into a lldb shell.
When running with lldb
attached, the app runs extremely slowly.
# Attaches to browser process. out/Default/bin/content_shell_apk lldb out/Default/bin/chrome_public_apk lldb # Attaches to gpu process. out/Default/bin/chrome_public_apk lldb --debug-process-name privileged_process0 # Attach to other processes ("chrome_public_apk ps" to show pids). out/Default/bin/chrome_public_apk lldb --pid $PID
NOT WORKING
This used to work with GDB, but the LLDB instructions have not been written. If you would like to take this on, please use: crbug/1266055.
# 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"
Once attached, lldb
will drop into a prompt. Set your breakpoints and run “c” to continue.
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
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 etc.
When debugging a failing test on the build waterfall, you can find the mapping file as follows:
.mapping
file for the APK used by the test (e.g., ChromePublic.apk.mapping
). Note that you may need to use the tools/luci-go/isolated
to download the mapping file if it's too big. The viewer will provide instructions for this.Googlers Only: For official build mapping files, see go/chromejavadeobfuscation.
Once you have a .mapping file:
# For a file: build/android/stacktrace/java_deobfuscate.py PROGUARD_MAPPING_FILE.mapping < FILE # For logcat: adb logcat | build/android/stacktrace/java_deobfuscate.py PROGUARD_MAPPING_FILE.mapping
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.
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/connect_lldb.sh --output-directory=out/Default --package-name=org.chromium.native_test
If you‘re developing on a non-rooted device such as a retail phone, security restrictions will prevent directly accessing the application’s data. However, as long as the app is built with debugging enabled, you can use adb shell run-as PACKAGENAME
to execute shell commands using the app's authorization, roughly equivalent to su $user
.
Non-Play-Store builds with is_official_build=false
will by default set android:debuggable="true"
in the app's manifest to allow debugging.
For exammple, for a Chromium build, run the following:
adb shell run-as org.chromium.chrome
If successful, this will silently wait for input without printing anything. It acts as a simple shell despite not showing the usual $
shell prompt. Just type commands and press RETURN to execute them.
The starting directory is the app's user data directory where user preferences and other profile data are stored.
pwd /data/user/0/org.chromium.chrome find -type f ./files/rList ./shared_prefs/org.chromium.chrome_preferences.xml
If you need to access the app‘s application data directory, you need to look up the obfuscated installation path since you don’t have read access to the /data/app/ directory. For example:
pm list packages -f org.chromium.chrome package:/data/app/~~ybTygSP5u72F9GN-3TMKXA==/org.chromium.chrome-zYY5mcB7YgB5pa3vfS3CBQ==/base.apk=org.chromium.chrome ls -l /data/app/~~ybTygSP5u72F9GN-3TMKXA==/org.chromium.chrome-zYY5mcB7YgB5pa3vfS3CBQ==/ total 389079 -rw-r--r-- 1 system system 369634375 2022-11-05 01:49 base.apk drwxr-xr-x 3 system system 3452 2022-11-05 01:49 lib -rw-r--r-- 1 system system 786666 2022-11-05 01:49 split_cablev2_authenticator.apk -rw-r--r-- 1 system system 21258500 2022-11-05 01:49 split_chrome.apk -rw-r--r-- 1 system system 1298934 2022-11-05 01:49 split_config.en.apk -rw-r--r-- 1 system system 413913 2022-11-05 01:49 split_dev_ui.apk -rw-r--r-- 1 system system 12432 2022-11-05 01:49 split_weblayer.apk