nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 1 | # Android Debugging Instructions |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 2 | Chrome on Android has java and c/c++ code. Each "side" have its own set of tools |
| 3 | for debugging. Here's some tips. |
| 4 | |
| 5 | [TOC] |
| 6 | |
Victor Hugo Vianna Silva | 12ddacb | 2020-09-18 01:29:25 | [diff] [blame] | 7 | ## Instructions for Google Employees |
| 8 | |
| 9 | See also |
| 10 | [go/clankium/06-debugging-clank](https://goto.google.com/clankium/06-debugging-clank). |
| 11 | |
agrieve | e453b98f | 2018-10-22 14:17:17 | [diff] [blame] | 12 | ## Launching |
| 13 | You can run the app by using one of the wrappers. |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 14 | |
| 15 | ```shell |
agrieve | e453b98f | 2018-10-22 14:17:17 | [diff] [blame] | 16 | # Installs, launches, and enters logcat. |
| 17 | out/Default/bin/content_shell_apk run --args='--disable-fre' 'data:text/html;utf-8,<html>Hello World!</html>' |
| 18 | # Launches without first installing. Does not show logcat. |
| 19 | out/Default/bin/chrome_public_apk launch --args='--disable-fre' 'data:text/html;utf-8,<html>Hello World!</html>' |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 20 | ``` |
| 21 | |
agrieve | e453b98f | 2018-10-22 14:17:17 | [diff] [blame] | 22 | ## Logging |
John Palmer | 046f987 | 2021-05-24 01:24:56 | [diff] [blame] | 23 | [Chromium logging from LOG(INFO)](https://chromium.googlesource.com/chromium/src/+/main/docs/android_logging.md) |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 24 | etc., is directed to the Android logcat logging facility. You can filter the |
| 25 | messages, e.g. view chromium verbose logging, everything else at warning level |
| 26 | with: |
| 27 | |
| 28 | ```shell |
agrieve | e453b98f | 2018-10-22 14:17:17 | [diff] [blame] | 29 | # Shows a coloured & filtered logcat. |
| 30 | out/Default/bin/chrome_public_apk logcat [-v] # Use -v to show logs for other processes |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 31 | ``` |
| 32 | |
David Van Cleve | e0021d3 | 2020-01-29 16:02:58 | [diff] [blame] | 33 | If this doesn't display the logs you're looking for, try `adb logcat` with your system `adb` |
| 34 | or the one in `//third_party/android_sdk/`. |
| 35 | |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 36 | ### Warnings for Blink developers |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 37 | * **Do not use fprintf or printf debugging!** This does not |
Chris Harrelson | 66168c07 | 2025-01-06 18:42:10 | [diff] [blame] | 38 | redirect to adb logcat. Use `LOG(ERROR)` etc. instead. |
| 39 | See also the "Get Blink code to output to the adb log" section. |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 40 | |
| 41 | * Redirecting stdio to logcat, as documented |
| 42 | [here](https://developer.android.com/studio/command-line/logcat.html#viewingStd), |
Chris Harrelson | 66168c07 | 2025-01-06 18:42:10 | [diff] [blame] | 43 | has a bad side-effect in that it breaks `adb_install.py`. See |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 44 | [here for details](http://stackoverflow.com/questions/28539676/android-adb-fails-to-install-apk-to-nexus-5-on-windows-8-1). |
| 45 | |
agrieve | e453b98f | 2018-10-22 14:17:17 | [diff] [blame] | 46 | ## Take a Screenshot |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 47 | ```shell |
| 48 | build/android/screenshot.py /tmp/screenshot.png |
| 49 | ``` |
| 50 | |
agrieve | e453b98f | 2018-10-22 14:17:17 | [diff] [blame] | 51 | ## Inspecting the View Hierarchy |
| 52 | Generate an [Android Studio](android_studio.md) project, and then use |
| 53 | [Layout Inspector](https://developer.android.com/studio/debug/layout-inspector). |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 54 | |
| 55 | ## Debugging Java |
Andrew Grieve | 4fe9974 | 2017-11-23 19:43:16 | [diff] [blame] | 56 | For both apk and test targets, pass `--wait-for-java-debugger` to the wrapper |
| 57 | scripts. |
| 58 | |
| 59 | Examples: |
| 60 | |
| 61 | ```shell |
| 62 | # Install, launch, and wait: |
| 63 | out/Default/bin/chrome_public_apk run --wait-for-java-debugger |
| 64 | |
| 65 | # Launch, and have GPU process wait rather than Browser process: |
| 66 | out/Default/bin/chrome_public_apk launch --wait-for-java-debugger --debug-process-name privileged_process0 |
| 67 | |
| 68 | # Have Renderers wait: |
| 69 | out/Default/bin/chrome_public_apk launch --args="--renderer-wait-for-java-debugger" |
| 70 | |
| 71 | # Have tests wait: |
| 72 | out/Default/bin/run_chrome_public_test_apk --wait-for-java-debugger |
| 73 | out/Default/bin/run_chrome_junit_tests --wait-for-java-debugger # Specify custom port via --debug-socket=9999 |
| 74 | ``` |
| 75 | |
| 76 | ### Android Studio |
| 77 | * Open Android Studio ([instructions](android_studio.md)) |
| 78 | * Click "Run"->"Attach debugger to Android process" (see |
Wei-Yin Chen (陳威尹) | 0f8750b3 | 2017-12-08 21:42:15 | [diff] [blame] | 79 | [here](https://developer.android.com/studio/debug/index.html) for more). |
agrieve | e453b98f | 2018-10-22 14:17:17 | [diff] [blame] | 80 | * Click "Run"->"Attach to Local Process..." for Robolectric junit tests. |
Andrew Grieve | f18950601 | 2022-06-20 18:48:45 | [diff] [blame] | 81 | * If this fails, you likely need to follow [these instructions](https://stackoverflow.com/questions/21114066/attach-intellij-idea-debugger-to-a-running-java-process). |
Andrew Grieve | 4fe9974 | 2017-11-23 19:43:16 | [diff] [blame] | 82 | |
estevenson | 8c9318ff | 2017-03-10 22:16:35 | [diff] [blame] | 83 | ### Eclipse |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 84 | * In Eclipse, make a debug configuration of type "Remote Java Application". |
| 85 | Choose a "Name" and set "Port" to `8700`. |
| 86 | |
| 87 | * Make sure Eclipse Preferences > Run/Debug > Launching > "Build (if required) |
| 88 | before launching" is unchecked. |
| 89 | |
| 90 | * Run Android Device Monitor: |
| 91 | |
| 92 | ```shell |
Yun Liu | f57cceaf | 2019-03-18 21:31:23 | [diff] [blame] | 93 | third_party/android_sdk/public/tools/monitor |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 94 | ``` |
| 95 | |
| 96 | * Now select the process you want to debug in Device Monitor (the port column |
| 97 | should now mention 8700 or xxxx/8700). |
| 98 | |
| 99 | * Run your debug configuration, and switch to the Debug perspective. |
| 100 | |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 101 | ## Debugging C/C++ |
Andrew Grieve | b445bdfb | 2023-11-27 16:35:28 | [diff] [blame] | 102 | While the app is running, use the wrapper script's `lldb` command to enter into a |
| 103 | lldb shell. |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 104 | |
Andrew Grieve | b445bdfb | 2023-11-27 16:35:28 | [diff] [blame] | 105 | When running with `lldb` attached, the app runs **extremely slowly**. |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 106 | |
| 107 | ```shell |
Andrew Grieve | 4fe9974 | 2017-11-23 19:43:16 | [diff] [blame] | 108 | # Attaches to browser process. |
Andrew Grieve | b445bdfb | 2023-11-27 16:35:28 | [diff] [blame] | 109 | out/Default/bin/content_shell_apk lldb |
| 110 | out/Default/bin/chrome_public_apk lldb |
Andrew Grieve | 4fe9974 | 2017-11-23 19:43:16 | [diff] [blame] | 111 | |
| 112 | # Attaches to gpu process. |
Andrew Grieve | b445bdfb | 2023-11-27 16:35:28 | [diff] [blame] | 113 | out/Default/bin/chrome_public_apk lldb --debug-process-name privileged_process0 |
Andrew Grieve | 4fe9974 | 2017-11-23 19:43:16 | [diff] [blame] | 114 | |
| 115 | # Attach to other processes ("chrome_public_apk ps" to show pids). |
Andrew Grieve | b445bdfb | 2023-11-27 16:35:28 | [diff] [blame] | 116 | out/Default/bin/chrome_public_apk lldb --pid $PID |
Stefan Zager | e2b55cc | 2019-10-04 19:57:54 | [diff] [blame] | 117 | ``` |
| 118 | |
agrieve | e453b98f | 2018-10-22 14:17:17 | [diff] [blame] | 119 | ### Using Visual Studio Code |
agrieve | e453b98f | 2018-10-22 14:17:17 | [diff] [blame] | 120 | |
Andrew Grieve | b445bdfb | 2023-11-27 16:35:28 | [diff] [blame] | 121 | **NOT WORKING** |
agrieve | e453b98f | 2018-10-22 14:17:17 | [diff] [blame] | 122 | |
Andrew Grieve | b445bdfb | 2023-11-27 16:35:28 | [diff] [blame] | 123 | This used to work with GDB, but the LLDB instructions have not been written. If |
| 124 | you would like to take this on, please use: |
| 125 | [crbug/1266055](https://bugs.chromium.org/p/chromium/issues/detail?id=1266055). |
agrieve | e453b98f | 2018-10-22 14:17:17 | [diff] [blame] | 126 | |
Andrew Grieve | 4fe9974 | 2017-11-23 19:43:16 | [diff] [blame] | 127 | ### Waiting for Debugger on Early Startup |
agrieve | e453b98f | 2018-10-22 14:17:17 | [diff] [blame] | 128 | ```shell |
| 129 | # Install, launch, and wait: |
| 130 | out/Default/bin/chrome_public_apk run --args="--wait-for-debugger" |
| 131 | # Launch, and have GPU process wait rather than Browser process: |
| 132 | out/Default/bin/chrome_public_apk launch --args="--wait-for-debugger-children=gpu-process" |
| 133 | # Or for renderers: |
| 134 | out/Default/bin/chrome_public_apk launch --args="--wait-for-debugger-children=renderer" |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 135 | ``` |
| 136 | |
Andrew Grieve | b445bdfb | 2023-11-27 16:35:28 | [diff] [blame] | 137 | #### With Command-line LLDB |
| 138 | Once attached, `lldb` will drop into a prompt. Set your breakpoints and run "c" to |
agrieve | e453b98f | 2018-10-22 14:17:17 | [diff] [blame] | 139 | continue. |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 140 | |
| 141 | ## Symbolizing Crash Stacks and Tombstones (C++) |
| 142 | |
| 143 | If a crash has generated a tombstone in your device, use: |
| 144 | |
| 145 | ```shell |
| 146 | build/android/tombstones.py --output-directory out/Default |
| 147 | ``` |
| 148 | |
| 149 | If you have a stack trace (from `adb logcat`) that needs to be symbolized, copy |
| 150 | it into a text file and symbolize with the following command (run from |
| 151 | `${CHROME_SRC}`): |
| 152 | |
| 153 | ```shell |
| 154 | third_party/android_platform/development/scripts/stack --output-directory out/Default [tombstone file | dump file] |
| 155 | ``` |
| 156 | |
| 157 | `stack` can also take its input from `stdin`: |
| 158 | |
| 159 | ```shell |
| 160 | adb logcat -d | third_party/android_platform/development/scripts/stack --output-directory out/Default |
| 161 | ``` |
| 162 | |
| 163 | Example: |
| 164 | |
| 165 | ```shell |
| 166 | third_party/android_platform/development/scripts/stack --output-directory out/Default ~/crashlogs/tombstone_07-build231.txt |
| 167 | ``` |
| 168 | |
| 169 | ## Deobfuscating Stack Traces (Java) |
| 170 | |
| 171 | You will need the ProGuard mapping file that was generated when the application |
| 172 | that crashed was built. When building locally, these are found in: |
| 173 | |
| 174 | ```shell |
| 175 | out/Default/apks/ChromePublic.apk.mapping |
agrieve | a350dbdb | 2017-07-05 15:27:17 | [diff] [blame] | 176 | etc. |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 177 | ``` |
| 178 | |
Sami Kyostila | 3269af1 | 2019-07-02 19:02:45 | [diff] [blame] | 179 | When debugging a failing test on the build waterfall, you can find the mapping |
| 180 | file as follows: |
| 181 | |
| 182 | 1. Open buildbot page for the failing build (e.g., |
| 183 | https://ci.chromium.org/p/chrome/builders/ci/android-go-perf/1234). |
| 184 | 2. Open the swarming page for the failing shard (e.g., shard #3). |
| 185 | 3. Click on "Isolated Inputs" to locate the files the shard used to run the |
| 186 | test. |
| 187 | 4. Download the `.mapping` file for the APK used by the test (e.g., |
| 188 | `ChromePublic.apk.mapping`). Note that you may need to use the |
Takuto Ikuta | 93b8eb80 | 2020-01-30 12:11:28 | [diff] [blame] | 189 | `tools/luci-go/isolated` to download the mapping file if it's too big. The |
| 190 | viewer will provide instructions for this. |
Sami Kyostila | 3269af1 | 2019-07-02 19:02:45 | [diff] [blame] | 191 | |
Andrew Grieve | abcac41a | 2019-08-14 17:16:18 | [diff] [blame] | 192 | **Googlers Only**: For official build mapping files, see |
| 193 | [go/chromejavadeobfuscation](https://goto.google.com/chromejavadeobfuscation). |
| 194 | |
Andrew Grieve | 17a5965 | 2020-03-19 18:14:53 | [diff] [blame] | 195 | Once you have a .mapping file: |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 196 | |
| 197 | ```shell |
agrieve | a350dbdb | 2017-07-05 15:27:17 | [diff] [blame] | 198 | # For a file: |
Andrew Grieve | 17a5965 | 2020-03-19 18:14:53 | [diff] [blame] | 199 | build/android/stacktrace/java_deobfuscate.py PROGUARD_MAPPING_FILE.mapping < FILE |
agrieve | a350dbdb | 2017-07-05 15:27:17 | [diff] [blame] | 200 | # For logcat: |
Andrew Grieve | 17a5965 | 2020-03-19 18:14:53 | [diff] [blame] | 201 | adb logcat | build/android/stacktrace/java_deobfuscate.py PROGUARD_MAPPING_FILE.mapping |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 202 | ``` |
| 203 | |
Chris Harrelson | 66168c07 | 2025-01-06 18:42:10 | [diff] [blame] | 204 | ## Get Blink code to output to the adb log |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 205 | |
| 206 | In your build environment: |
| 207 | |
| 208 | ```shell |
| 209 | adb root |
| 210 | adb shell stop |
| 211 | adb shell setprop log.redirect-stdio true |
| 212 | adb shell start |
| 213 | ``` |
| 214 | |
Chris Harrelson | 66168c07 | 2025-01-06 18:42:10 | [diff] [blame] | 215 | In the source itself, use `LOG(ERROR),` `LOG(INFO)`, etc. whenever you need to |
| 216 | output a message, and it will be automatically redirected to adb logcat. |
| 217 | Running `adb logcat chromium:E`, for example, will show all log lines from |
| 218 | `LOG(ERROR)` (plus others that match "chromium"). |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 219 | |
Andrew Grieve | b445bdfb | 2023-11-27 16:35:28 | [diff] [blame] | 220 | ## Debug unit tests with LLDB |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 221 | |
| 222 | To run unit tests use the following command: |
| 223 | |
| 224 | ```shell |
jbudorick | 6a94be3 | 2017-05-11 22:38:43 | [diff] [blame] | 225 | out/Debug/bin/run_test_name -f <test_filter_if_any> --wait-for-debugger -t 6000 |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 226 | ``` |
| 227 | |
| 228 | That command will cause the test process to wait until a debugger is attached. |
| 229 | |
| 230 | To attach a debugger: |
| 231 | |
| 232 | ```shell |
Andrew Grieve | b445bdfb | 2023-11-27 16:35:28 | [diff] [blame] | 233 | build/android/connect_lldb.sh --output-directory=out/Default --package-name=org.chromium.native_test |
nyquist | c75738d | 2016-09-13 19:25:01 | [diff] [blame] | 234 | ``` |
Klaus Weidner | ffc475b8 | 2022-11-04 17:55:08 | [diff] [blame] | 235 | |
| 236 | ## Examine app data on a non-rooted device |
| 237 | |
| 238 | If you're developing on a non-rooted device such as a retail phone, security restrictions |
| 239 | will prevent directly accessing the application's data. However, as long as the app is |
| 240 | built with debugging enabled, you can use `adb shell run-as PACKAGENAME` to execute |
| 241 | shell commands using the app's authorization, roughly equivalent to `su $user`. |
| 242 | |
| 243 | Non-Play-Store builds with `is_official_build=false` will by default set |
| 244 | `android:debuggable="true"` in the app's manifest to allow debugging. |
| 245 | |
| 246 | For exammple, for a Chromium build, run the following: |
| 247 | |
| 248 | ``` |
| 249 | adb shell run-as org.chromium.chrome |
| 250 | ``` |
| 251 | |
| 252 | If successful, this will silently wait for input without printing anything. |
| 253 | It acts as a simple shell despite not showing the usual `$ ` shell prompt. |
| 254 | Just type commands and press RETURN to execute them. |
| 255 | |
| 256 | The starting directory is the app's user data directory where user preferences and other |
| 257 | profile data are stored. |
| 258 | |
| 259 | ``` |
| 260 | pwd |
| 261 | /data/user/0/org.chromium.chrome |
| 262 | |
| 263 | find -type f |
| 264 | ./files/rList |
| 265 | ./shared_prefs/org.chromium.chrome_preferences.xml |
| 266 | ``` |
| 267 | |
| 268 | If you need to access the app's application data directory, you need to look up the |
| 269 | obfuscated installation path since you don't have read access to the */data/app/* directory. |
| 270 | For example: |
| 271 | |
| 272 | ``` |
| 273 | pm list packages -f org.chromium.chrome |
| 274 | package:/data/app/~~ybTygSP5u72F9GN-3TMKXA==/org.chromium.chrome-zYY5mcB7YgB5pa3vfS3CBQ==/base.apk=org.chromium.chrome |
| 275 | |
| 276 | ls -l /data/app/~~ybTygSP5u72F9GN-3TMKXA==/org.chromium.chrome-zYY5mcB7YgB5pa3vfS3CBQ==/ |
| 277 | total 389079 |
| 278 | -rw-r--r-- 1 system system 369634375 2022-11-05 01:49 base.apk |
| 279 | drwxr-xr-x 3 system system 3452 2022-11-05 01:49 lib |
Klaus Weidner | ffc475b8 | 2022-11-04 17:55:08 | [diff] [blame] | 280 | -rw-r--r-- 1 system system 786666 2022-11-05 01:49 split_cablev2_authenticator.apk |
| 281 | -rw-r--r-- 1 system system 21258500 2022-11-05 01:49 split_chrome.apk |
| 282 | -rw-r--r-- 1 system system 1298934 2022-11-05 01:49 split_config.en.apk |
| 283 | -rw-r--r-- 1 system system 413913 2022-11-05 01:49 split_dev_ui.apk |
| 284 | -rw-r--r-- 1 system system 12432 2022-11-05 01:49 split_weblayer.apk |
Andrew Grieve | b445bdfb | 2023-11-27 16:35:28 | [diff] [blame] | 285 | ``` |