This page contains a summary of useful tools and related commands for debugging, tracing, and profiling native Android platform code. The pages within this section contain detailed information on other debugging tools for use during development of platform-level features.html
For example, you may learn how to explore system services with Dumpsys and evaluate network and RAM use. See the subpages for tools and methods not described below.java
When a dynamically-linked executable starts, several signal handlers are registered that connect to debuggerd
(or debuggerd64)
in the event that signal is sent to the process. The debuggerd
process dumps registers and unwinds the stack.python
It's possible for debuggerd
to attach only if nothing else is already attached. This means that using tools like strace
or gdb
will prevent debuggerd
from working. Also, if you call prctl(PR_SET_DUMPABLE, 0)
you can prevent debuggerd
from attaching. This can be useful if you wish to explicitly opt out of crash reporting.linux
Here is example output (with timestamps and extraneous information removed):android
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** Build fingerprint: 'Android/aosp_flounder/flounder:5.1.51/AOSP/enh08201009:eng/test-keys' Revision: '0' ABI: 'arm' pid: 1656, tid: 1656, name: crasher >>> crasher <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'some_file.c:123: some_function: assertion "false" failed' r0 00000000 r1 00000678 r2 00000006 r3 f70b6dc8 r4 f70b6dd0 r5 f70b6d80 r6 00000002 r7 0000010c r8 ffffffed r9 00000000 sl 00000000 fp ff96ae1c ip 00000006 sp ff96ad18 lr f700ced5 pc f700dc98 cpsr 400b0010 backtrace: #00 pc 00042c98 /system/lib/libc.so (tgkill+12) #01 pc 00041ed1 /system/lib/libc.so (pthread_kill+32) #02 pc 0001bb87 /system/lib/libc.so (raise+10) #03 pc 00018cad /system/lib/libc.so (__libc_android_abort+34) #04 pc 000168e8 /system/lib/libc.so (abort+4) #05 pc 0001a78f /system/lib/libc.so (__libc_fatal+16) #06 pc 00018d35 /system/lib/libc.so (__assert2+20) #07 pc 00000f21 /system/xbin/crasher #08 pc 00016795 /system/lib/libc.so (__libc_init+44) #09 pc 00000abc /system/xbin/crasher Tombstone written to: /data/tombstones/tombstone_06
This can be pasted into development/scripts/stack
to get a more detailed unwind with line number information (assuming the unstripped binaries can be found).c++
Some libraries on the system are built with LOCAL_STRIP_MODULE := keep_symbols
to provide usable backtraces directly from debuggerd
. This makes your library or executable slightly larger, but not nearly as large as an unstripped version.git
Note also the last line of debuggerd
output --- in addition to dumping a summary to the log, debuggerd
writes a full 「tombstone」 to disk. This contains a lot of extra information that can be helpful in debugging a crash, in particular the stack traces for all the threads in the crashing process (not just the thread that caught the signal) and a full memory map.github
If you don't have a specific crash that you're investigating right now, the platform source includes a tool for testing debuggerd
called crasher. If you mm
in system/core/debuggerd/
you'll get both a crasher
and a crasher64
on your path (the latter allowing you to test 64-bit crashes). Crasher can crash in a large number of interesting ways based on the command line arguments you provide. Use crasher --help
to see the currently supported selection.web
To introduce the difference pieces in a crash dump, let's work through the example above:chrome
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
The line of asterisks with spaces is helpful if you're searching a log for native crashes. The string "*** ***" rarely shows up in logs other than at the beginning of a native crash.
Build fingerprint: 'Android/aosp_flounder/flounder:5.1.51/AOSP/enh08201009:eng/test-keys'
The fingerprint lets you identify exactly which build the crash occurred on. This is exactly the same as the ro.build.fingerprint
system property.
Revision: '0'
The revision refers to the hardware rather than the software. This is usually unused but can be useful to help you automatically ignore bugs known to be caused by bad hardware. This is exactly the same as the ro.revision
system property.
ABI: 'arm'
The ABI is one of arm, arm64, mips, mips64, x86, or x86-64. This is mostly useful for the stack
script mentioned above, so that it knows what toolchain to use.
pid: 1656, tid: 1656, name: crasher >>> crasher <<<
This line identifies the specific thread in the process that crashed. In this case, it was the process' main thread, so the process ID and thread ID match. The first name is the thread name, and the name surrounded by >>> and <<< is the process name. For an app, the process name is typically the fully-qualified package name (such as com.facebook.katana), which is useful when filing bugs or trying to find the app in Google Play. The pid and tid can also be useful in finding the relevant log lines preceding the crash.
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
This line tells you which signal (SIGABRT) was received, and more about how it was received (SI_TKILL). The signals reported by debuggerd
are SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, and SIGTRAP. The signal-specific codes vary based on the specific signal.
Abort message: 'some_file.c:123: some_function: assertion "false" failed'
Not all crashes will have an abort message line, but aborts will. This is automatically gathered from the last line of fatal logcat output for this pid/tid, and in the case of a deliberate abort is likely to give an explanation of why the program killed itself.
r0 00000000 r1 00000678 r2 00000006 r3 f70b6dc8 r4 f70b6dd0 r5 f70b6d80 r6 00000002 r7 0000010c r8 ffffffed r9 00000000 sl 00000000 fp ff96ae1c ip 00000006 sp ff96ad18 lr f700ced5 pc f700dc98 cpsr 400b0010
The register dump shows the content of the CPU registers at the time the signal was received. (This section varies wildly between ABIs.) How useful these are will depend on the exact crash.
backtrace: #00 pc 00042c98 /system/lib/libc.so (tgkill+12) #01 pc 00041ed1 /system/lib/libc.so (pthread_kill+32) #02 pc 0001bb87 /system/lib/libc.so (raise+10) #03 pc 00018cad /system/lib/libc.so (__libc_android_abort+34) #04 pc 000168e8 /system/lib/libc.so (abort+4) #05 pc 0001a78f /system/lib/libc.so (__libc_fatal+16) #06 pc 00018d35 /system/lib/libc.so (__assert2+20) #07 pc 00000f21 /system/xbin/crasher #08 pc 00016795 /system/lib/libc.so (__libc_init+44) #09 pc 00000abc /system/xbin/crasher
The backtrace shows you where in the code we were at the time of crash. The first column is the frame number (matching gdb's style where the deepest frame is 0). The PC values are relative to the location of the shared library rather than absolute addresses. The next column is the name of the mapped region (which is usually a shared library or executable, but might not be for, say, JIT-compiled code). Finally, if symbols are available, the symbol that the PC value corresponds to is shown, along with the offset into that symbol in bytes. You can use this in conjunction with objdump(1)
to find the corresponding assembler instruction.
Tombstone written to: /data/tombstones/tombstone_06
This tells you where debuggerd
wrote extra information. debuggerd
will keep up to 10 tombstones, cycling through the numbers 00 to 09 and overwriting existing tombstones as necessary.
The tombstone contains the same information as the crash dump, plus a few extras. For example, it includes backtraces for all threads (not just the crashing thread), the floating point registers, raw stack dumps, and memory dumps around the addresses in registers. Most usefully it also includes a full memory map (similar to /proc/pid/maps
). Here's an annotated example from a 32-bit ARM process crash:
memory map: (fault address prefixed with --->) --->ab15f000-ab162fff r-x 0 4000 /system/xbin/crasher (BuildId: b9527db01b5cf8f5402f899f64b9b121)
There are two things to note here. The first is that this line is prefixed with "--->". The maps are most useful when your crash isn't just a null pointer dereference. If the fault address is small, it's probably some variant of a null pointer dereference. Otherwise looking at the maps around the fault address can often give you a clue as to what happened. Some possible issues that can be recognized by looking at the maps include:
The second thing to note is that executables and shared libraries files will show the BuildId (if present) in Android M and later, so you can see exactly which version of your code crashed. (Platform binaries include a BuildId by default since Android M. NDK r12 and later automatically pass -Wl,--build-id
to the linker too.)
ab163000-ab163fff r-- 3000 1000 /system/xbin/crasher ab164000-ab164fff rw- 0 1000 f6c80000-f6d7ffff rw- 0 100000 [anon:libc_malloc]
On Android the heap isn't necessarily a single region. Heap regions will be labeled [anon:libc_malloc]
.
f6d82000-f6da1fff r-- 0 20000 /dev/__properties__/u:object_r:logd_prop:s0 f6da2000-f6dc1fff r-- 0 20000 /dev/__properties__/u:object_r:default_prop:s0 f6dc2000-f6de1fff r-- 0 20000 /dev/__properties__/u:object_r:logd_prop:s0 f6de2000-f6de5fff r-x 0 4000 /system/lib/libnetd_client.so (BuildId: 08020aa06ed48cf9f6971861abf06c9d) f6de6000-f6de6fff r-- 3000 1000 /system/lib/libnetd_client.so f6de7000-f6de7fff rw- 4000 1000 /system/lib/libnetd_client.so f6dec000-f6e74fff r-x 0 89000 /system/lib/libc++.so (BuildId: 8f1f2be4b37d7067d366543fafececa2) (load base 0x2000) f6e75000-f6e75fff --- 0 1000 f6e76000-f6e79fff r-- 89000 4000 /system/lib/libc++.so f6e7a000-f6e7afff rw- 8d000 1000 /system/lib/libc++.so f6e7b000-f6e7bfff rw- 0 1000 [anon:.bss] f6e7c000-f6efdfff r-x 0 82000 /system/lib/libc.so (BuildId: d189b369d1aafe11feb7014d411bb9c3) f6efe000-f6f01fff r-- 81000 4000 /system/lib/libc.so f6f02000-f6f03fff rw- 85000 2000 /system/lib/libc.so f6f04000-f6f04fff rw- 0 1000 [anon:.bss] f6f05000-f6f05fff r-- 0 1000 [anon:.bss] f6f06000-f6f0bfff rw- 0 6000 [anon:.bss] f6f0c000-f6f21fff r-x 0 16000 /system/lib/libcutils.so (BuildId: d6d68a419dadd645ca852cd339f89741) f6f22000-f6f22fff r-- 15000 1000 /system/lib/libcutils.so f6f23000-f6f23fff rw- 16000 1000 /system/lib/libcutils.so f6f24000-f6f31fff r-x 0 e000 /system/lib/liblog.so (BuildId: e4d30918d1b1028a1ba23d2ab72536fc) f6f32000-f6f32fff r-- d000 1000 /system/lib/liblog.so f6f33000-f6f33fff rw- e000 1000 /system/lib/liblog.so
Typically a shared library will have three adjacent entries. One will be readable and executable (code), one will be read-only (read-only data), and one will be read-write (mutable data). The first column shows the address ranges for the mapping, the second column the permissions (in the usual Unix ls(1)
style), the third column the offset into the file (in hex), the fourth column the size of the region (in hex), and the fifth column the file (or other region name).
f6f34000-f6f53fff r-x 0 20000 /system/lib/libm.so (BuildId: 76ba45dcd9247e60227200976a02c69b) f6f54000-f6f54fff --- 0 1000 f6f55000-f6f55fff r-- 20000 1000 /system/lib/libm.so f6f56000-f6f56fff rw- 21000 1000 /system/lib/libm.so f6f58000-f6f58fff rw- 0 1000 f6f59000-f6f78fff r-- 0 20000 /dev/__properties__/u:object_r:default_prop:s0 f6f79000-f6f98fff r-- 0 20000 /dev/__properties__/properties_serial f6f99000-f6f99fff rw- 0 1000 [anon:linker_alloc_vector] f6f9a000-f6f9afff r-- 0 1000 [anon:atexit handlers] f6f9b000-f6fbafff r-- 0 20000 /dev/__properties__/properties_serial f6fbb000-f6fbbfff rw- 0 1000 [anon:linker_alloc_vector] f6fbc000-f6fbcfff rw- 0 1000 [anon:linker_alloc_small_objects] f6fbd000-f6fbdfff rw- 0 1000 [anon:linker_alloc_vector] f6fbe000-f6fbffff rw- 0 2000 [anon:linker_alloc] f6fc0000-f6fc0fff r-- 0 1000 [anon:linker_alloc] f6fc1000-f6fc1fff rw- 0 1000 [anon:linker_alloc_lob] f6fc2000-f6fc2fff r-- 0 1000 [anon:linker_alloc] f6fc3000-f6fc3fff rw- 0 1000 [anon:linker_alloc_vector] f6fc4000-f6fc4fff rw- 0 1000 [anon:linker_alloc_small_objects] f6fc5000-f6fc5fff rw- 0 1000 [anon:linker_alloc_vector] f6fc6000-f6fc6fff rw- 0 1000 [anon:linker_alloc_small_objects] f6fc7000-f6fc7fff rw- 0 1000 [anon:arc4random _rsx structure] f6fc8000-f6fc8fff rw- 0 1000 [anon:arc4random _rs structure] f6fc9000-f6fc9fff r-- 0 1000 [anon:atexit handlers] f6fca000-f6fcafff --- 0 1000 [anon:thread signal stack guard page]
Note that since Android 5.0 (Lollipop), the C library names most of its anonymous mapped regions so there are fewer mystery regions.
f6fcb000-f6fccfff rw- 0 2000 [stack:5081]
Regions named [stack:tid]
are the stacks for the given threads.
f6fcd000-f702afff r-x 0 5e000 /system/bin/linker (BuildId: 84f1316198deee0591c8ac7f158f28b7) f702b000-f702cfff r-- 5d000 2000 /system/bin/linker f702d000-f702dfff rw- 5f000 1000 /system/bin/linker f702e000-f702ffff rw- 0 2000 f7030000-f7030fff r-- 0 1000 f7031000-f7032fff rw- 0 2000 ffcd7000-ffcf7fff rw- 0 21000 ffff0000-ffff0fff r-x 0 1000 [vectors]
Whether you see [vector]
or [vdso]
depends on the architecture. ARM uses [vector], while all other architectures use [vdso].
To connect to an already-running app or native daemon, use gdbclient
.
Current versions of gdbclient just require the process ID (PID). So to debug a process with PID 1234, simply run:
$ gdbclient 1234
The script will set up port forwarding, start the appropriate gdbserver
on the device, start the appropriate gdb
on the host, configure gdb
to find symbols, and connect gdb
to the remote gdbserver
.
If you want to debug a process as it starts, you’ll need to use gdbserver
or gdbserver64
manually, but that’s easy too:
$ adb shell gdbserver :5039 /system/bin/my_test_app Process my_test_app created; pid = 3460 Listening on port 5039
Identify the app’s PID from the gdbserver
output, and then in another window:
$ gdbclient <app pid>
Then enter continue at the gdb
prompt.
Note that to debug a 64-bit process, you'll need to use gdbserver64
. The error messages from gdb
if you made the wrong choice are unhelpful (along the lines of Reply contains invalid hex digit 59
).
If you want debuggerd
to suspend crashed processes so you can attach gdb
, set the appropriate property:
$ adb shell setprop debug.db.uid 999999 # <= M $ adb shell setprop debug.debuggerd.wait_for_gdb true # > M
At the end of the usual crash output, debuggerd
will give you instructions on how to connect gdb
using the typical command:
$ gdbclient <pid>
If you don’t have symbols, sometimes gdb
will get confused about the instruction set it is disassembling (ARM or Thumb). The instruction set that is chosen as the default when symbol information is missing can be switched between ARM or Thumb like so:
$ set arm fallback-mode arm # or 'thumb'
The following steps show you how to use Valgrind on Android. This tool suite contains a number of tools including Memcheck for detecting memory-related errors in C and C++.
$ mmma -j6 external/valgrind
$ adb shell mkdir /data/local/tmp $ adb shell chmod 777 /data/local/tmp
$ adb shell setprop wrap.system_server "logwrapper valgrind" $ adb shell stop && adb shell start
/data/local/symbols
: $ adb shell mkdir /data/local/symbols $ adb push $OUT/symbols /data/local/symbols
out/target/product/XXXX/root/init.rc
and change:service example /system/bin/foo --arg1 --arg2
service example /system/bin/logwrapper /system/bin/valgrind /system/bin/foo --arg1 --arg2
boot.img
and reflash the device.See Systrace on developer.android.com for deriving execution times of applications and other Android system processes.
The Systrace tool helps analyze the performance of your application by capturing and displaying execution times of your applications processes and other Android system processes. The tool combines data from the Android kernel such as the CPU scheduler, disk activity, and application threads to generate an HTML report that shows an overall picture of an Android device’s system processes for a given period of time.
The Systrace tool is particularly useful in diagnosing display problems where an application is slow to draw or stutters while displaying motion or animation. For more information on how to use Systrace, see Analyzing UI Performance with Systrace.
In order to run Systrace, you must have Android SDK Tools 20 or later installed. You must also have Python installed and included in your development computer's execution path. In order to generate a trace, you must connect a device running Android 4.1 (API Level 16) or higher to your development system using a USB debugging connection.
The Systrace tool can be run either from one of the Android SDK's graphical user interface tools, or from the command line. The following sections describe how to run the tool using either of these methods.
The Systrace tool can be run from the Android Device Monitor.
To run the Systrace capture user interface:
The Systrace tool has different command line options for devices running Android 4.3 (API level 18) and higher versus devices running Android 4.2 (API level 17) and lower. The following sections describe the different command line options for each version.
The general syntax for running Systrace from the command line is as follows.
$ python systrace.py [options] [category1] [category2] ... [categoryN]
See the sections below for example Systrace sessions.
When you use Systrace on devices running Android 4.3 and higher, you can omit trace category tags to get the defaults, or you may manually specify tags for inclusion. Here is an example execution run that sets trace tags and generates a trace from a connected device.
$ cd android-sdk/platform-tools/systrace $ python systrace.py --time=10 -o mynewtrace.html sched gfx view wm
Tip: If you want to see the names of tasks in the trace output, you must include the sched
category in your command parameters.
The table below lists the Systrace command line options for devices running Android 4.3 (API level 18) and higher.
Option | Description |
---|---|
-h, --help |
Show the help message. |
-o <FILE> |
Write the HTML trace report to the specified file. |
-t N, --time=N |
Trace activity for N seconds. The default value is 5 seconds. |
-b N, --buf-size=N |
Use a trace buffer size of N kilobytes. This option lets you limit the total size of the data collected during a trace. |
-k <KFUNCS> |
Trace the activity of specific kernel functions, specified in a comma-separated list. |
-l, --list-categories |
List the available tracing category tags. Note: Trace categories can differ across devices. Tip: If you want to see the names of tasks in the trace output, you must include the |
-a <APP_NAME> |
Enable tracing for applications, specified as a comma-separated list of package names. The apps must contain tracing instrumentation calls from the Trace class. For more information, see Analyzing UI Performance with Systrace. |
--from-file=<FROM_FILE> |
Create the interactive Systrace report from a file, instead of running a live trace. |
-e <DEVICE_SERIAL> |
Conduct the trace on a specific connected device, identified by its device serial number. |
Using Systrace on the command line with devices running Android 4.2 and lower is typically a two-step process. You must first set the trace tags you want to capture and then run the trace. Here is an example execution run that sets trace tags and generates a trace from a connected device.
$ cd android-sdk/platform-tools/systrace $ python systrace.py --set-tags gfx,view,wm $ adb shell stop $ adb shell start $ python systrace.py --disk --time=10 -o mynewtrace.html
The table below lists the Systrace command line options for devices running Android 4.2 (API level 17) and lower.
Option | Description |
---|---|
-h, --help |
Show the help message. |
-o <FILE> |
Write the HTML trace report to the specified file. |
-t N, --time=N |
Trace activity for N seconds. The default value is 5 seconds. |
-b N, --buf-size=N |
Use a trace buffer size of N kilobytes. This option lets you limit the total size of the data collected during a trace. |
-d, --disk |
Trace disk input and output activity. This option requires root access on the device. |
-f, --cpu-freq |
Trace CPU frequency changes. Only changes to the CPU frequency are logged, so the initial frequency of the CPU when tracing starts is not shown. |
-i, --cpu-idle |
Trace CPU idle events. |
-l, --cpu-load |
Trace CPU load. This value is a percentage determined by the interactive CPU frequency governor. |
-s, --no-cpu-sched |
Prevent tracing of the CPU scheduler. This option allows for longer trace times by reducing the rate of data flowing into the trace buffer. |
-u, --bus-utilization |
Trace the bus utilization levels. This option requires root access on the device. |
-w, --workqueue |
Trace kernel work queues. This option requires root access on the device. |
--set-tags=<TAGS> |
Set the enabled trace tags in a comma separated list. The available tags are:
Note: When setting trace tags from the command line, you must stop and restart the framework ( |
You can set the trace tags for Systrace on your Android 4.2 and lower device by navigating to Settings > Developer options > Monitoring > Enable traces.
The table below lists the keyboard shortcuts that are available while viewing a Systrace trace HTML report.
Key | Description |
---|---|
w | Zoom into the trace timeline. |
s | Zoom out of the trace timeline. |
a | Pan left on the trace timeline. |
d | Pan right on the trace timeline. |
e | Center the trace timeline on the current mouse location. |
g | Show grid at the start of the currently selected task. |
Shift+g | Show grid at the end of the currently selected task. |
Right Arrow | Select the next event on the currently selected timeline. |
Left Arrow | Select the previous event on the currently selected timeline. |
AddressSanitizer (ASan) is a fast compiler-based tool for detecting memory bugs in native code. It is comparable to Valgrind (Memcheck tool), but, unlike it, ASan:
This document describes how to build and run parts of the Android platform with AddressSanitizer. If you are looking to build a standalone (i.e. SDK/NDK) application with AddressSanitizer, see the AddressSanitizerOnAndroid public project site instead.
AddressSanitizer consists of a compiler (external/clang
) and a runtime library (external/compiler-rt/lib/asan
).
Note: Use the current master branch to gain access to the SANITIZE_TARGET feature and the ability to build the entire Android platform with AddressSanitizer at once. Otherwise, you are limited to using LOCAL_SANITIZE
.
As a first step to building an ASan-instrumented binary, make sure that your code builds with Clang. This is done by adding LOCAL_CLANG:=true
to the build rules. Clang may find bugs in your code that GCC missed.
Add LOCAL_SANITIZE:=address
to the build rule of the executable. This requires: LOCAL_CLANG:=true
LOCAL_CLANG:=true LOCAL_SANITIZE:=address
When a bug is detected, ASan prints a verbose report both to the standard output and to logcat
and then crashes the process.
Due to the way ASan works, a library built with ASan cannot be used by an executable that's built without ASan.
Note: In runtime situations where an ASan library is loaded into an incorrect process, you will see unresolved symbol messages starting with _asan
or _sanitizer
.
To sanitize a shared library that is used in multiple executables, not all of which are built with ASan, you'll need two copies of the library. The recommended way to do this is to add the following to Android.mk
for the module in question:
LOCAL_CLANG:=true LOCAL_SANITIZE:=address LOCAL_MODULE_RELATIVE_PATH := asan
This puts the library in /system/lib/asan
instead of /system/lib
. Then, run your executable with: LD_LIBRARY_PATH=/system/lib/asan
For system daemons, add the following to the appropriate section of /init.rc
or /init.$device$.rc
.
setenv LD_LIBRARY_PATH /system/lib/asan
Warning: The LOCAL_MODULE_RELATIVE_PATH
setting moves your library to /system/lib/asan
, meaning that clobbering and rebuilding from scratch will result in the library missing from /system/lib
, and probably an unbootable image. That's an unfortunate limitation of the current build system. Don't clobber; do make -j $N
and adb sync
.
Verify the process is using libraries from /system/lib/asan
when present by reading /proc/$PID/maps
. If it's not, you may need to disable SELinux, like so:
$ adb root $ adb shell setenforce 0 # restart the process with adb shell kill $PID # if it is a system service, or may be adb shell stop; adb shell start.
AddressSanitizer uses a fast, frame-pointer-based unwinder to record a stack trace for every memory allocation and deallocation event in the program. Most of Android is built without frame pointers. As a result, you will often get only one or two meaningful frames. To fix this, either rebuild the library with ASan (recommended!), or with:
LOCAL_CFLAGS:=-fno-omit-frame-pointer LOCAL_ARM_MODE:=arm
Or set ASAN_OPTIONS=fast_unwind_on_malloc=0
in the process environment. The latter can be very CPU-intensive, depending on the load.
Initially, ASan reports contain references to offsets in binaries and shared libraries. There are two ways to obtain source file and line information:
/system/bin
. Llvm-symbolizer is built from sources in: third_party/llvm/tools/llvm-symbolizer
external/compiler-rt/lib/asan/scripts/symbolize.py
script.The second approach can provide more data (i.e. file:line locations) because of the availability of symbolized libraries on the host.
AddressSanitizer cannot see into Java code, but it can detect bugs in the JNI libraries. For that, you'll need to build the executable with ASan, which in this case is /system/bin/app_process(32|64
). This will enable ASan in all apps on the device at the same time, which is a bit stressful, but nothing that a 2GB RAM device cannot handle.
Add the usual LOCAL_CLANG:=true, LOCAL_SANITIZE:=address
to the app_process build rule in frameworks/base/cmds/app_process
. Ignore the app_process__asan
target in the same file for now (if it is still there at the time you read this). Edit the Zygote record in system/core/rootdir/init.zygote(32|64).rc
to add the following lines:
setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib setenv ASAN_OPTIONS allow_user_segv_handler=true
Build, adb sync, fastboot flash boot, reboot.
The approach in the previous section puts AddressSanitizer into every application in the system (actually, into every descendant of the Zygote process). It is possible to run only one (or several) applications with ASan, trading some memory overhead for slower application startup.
This can be done by starting your app with the 「wrap.」 property, the same one that’s used to run apps under Valgrind. The following example runs the Gmail app under ASan:
$ adb root $ adb shell setenforce 0 # disable SELinux $ adb shell setprop wrap.com.google.android.gm "asanwrapper"
In this context, asanwrapper rewrites /system/bin/app_process
to /system/bin/asan/app_process
, which is built with AddressSanitizer. It also adds /system/lib/asan
at the start of the dynamic library search path. This way ASan-instrumented libraries from /system/lib/asan
are preferred to normal libraries in /system/lib
when running with asanwrapper.
Again, if a bug is found, the app will crash, and the report will be printed to the log.
The master branch has support for building the entire Android platform with AddressSanitizer at once.
Run the following commands in the same build tree.
$ make -j42 $ make USE_CLANG_PLATFORM_BUILD:=true SANITIZE_TARGET=address -j42
In this mode, userdata.img
contains extra libraries and must be flashed to the device as well. Use the following command line:
$ fastboot flash userdata && fastboot flashall
At the moment of this writing, hammerhead-userdebug and shamu-userdebug boot to the UI in this mode.
This works by building two sets of shared libraries: normal in /system/lib
(the first make invocation), ASan-instrumented in /data/lib
(the second make invocation). Executables from the second build overwrite the ones from the first build. ASan-instrumented executables get a different library search path that includes /data/lib
before /system/lib
through the use of "/system/bin/linker_asan" in PT_INTERP.
The build system clobbers intermediate object directories when the $SANITIZE_TARGET
value has changed. This forces a rebuild of all targets while preserving installed binaries under /system/lib
.
Some targets cannot be built with ASan:
LOCAL_CLANG:=false
targetsLOCAL_SANITIZE:=undefined
; will not be ASan'd for SANITIZE_TARGET=address
Executables like these are skipped in the SANITIZE_TARGET build, and the version from the first make invocation is left in /system/bin
.
Libraries like this are simply built without ASan. They can contain some ASan code anyway from the static libraries they depend upon.
AddressSanitizerOnAndroid public project site
2=======================================================
If you run adb shell dumpsys
, you’ll get diagnostic output for all system services, which is usually more than you want. For more manageable output, specify the service you would like to examine.
For example, the following command:
$ adb shell dumpsys input
provides system data for input components such as touchscreens or built-in keyboards.
For a complete list of system services that you can use with dumpsys, try the following command:
$ adb shell dumpsys -l Currently running services: DockObserver SurfaceFlinger accessibility account activity alarm android.security.keystore appops appwidget assetatlas audio backup battery batteryproperties batterystats bluetooth_manager clipboard connectivity consumer_ir content country_detector cpuinfo dbinfo ...
Command-line options are different for different services. Here are a few common ones:
-h
to see the help text.-c
to view the data in a machine-friendly format.For details on some of the most commonly used dumpsys services, see the following articles:
3========================================================
See Malloc Debug and Native Memory Tracking using libc Callbacks for a thorough description of the debugging options available for native memory issues.
You can also use the Dalvik Debug Monitor Server (DDMS) to obtain a graphical view of Malloc Debug output.
To use DDMS, first turn on its native memory UI:
~/.android/ddms.cfg
native=true
Upon relaunching DDMS and selecting a process, you can switch to the new native allocation tab and populate it with a list of allocations. This is especially useful for debugging memory leaks.
Malloc debug is a method of debugging native memory problems. It can help detect memory corruption, memory leaks, and use after free issues.
This documentation describes how to enable this feature on Android N or later versions of the Android OS.
The documentation for malloc debug on older versions of Android is here.
In order to enable malloc debug, you must be able to set special system properties using the setprop command from the shell. This requires the ability to run as root on the device.
When malloc debug is enabled, it works by adding a shim layer that replaces the normal allocation calls. The replaced calls are:
malloc
free
calloc
realloc
posix_memalign
memalign
malloc_usable_size
On 32 bit systems, these two deprecated functions are also replaced:
pvalloc
valloc
Any errors detected by the library are reported in the log.
Malloc debug is controlled by individual options. Each option can be enabled individually, or in a group of other options. Every single option can be combined with every other option.
Enables a small buffer placed before the allocated data. This is an attempt to find memory corruption occuring to a region before the original allocation. On first allocation, this front guard is written with a specific pattern (0xaa). When the allocation is freed, the guard is checked to verify it has not been modified. If any part of the front guard is modified, an error will be reported in the log indicating what bytes changed.
If the backtrace option is also enabled, then any error message will include the backtrace of the allocation site.
If SIZE_BYTES is present, it indicates the number of bytes in the guard. The default is 32 bytes, the max bytes is 16384. SIZE_BYTES will be padded so that it is a multiple of 8 bytes on 32 bit systems and 16 bytes on 64 bit systems to make sure that the allocation returned is aligned properly.
This option adds a special header to all allocations that contains the guard and information about the original allocation.
Example error:
04-10 12:00:45.621 7412 7412 E malloc_debug: +++ ALLOCATION 0x12345678 SIZE 100 HAS A CORRUPTED FRONT GUARD 04-10 12:00:45.622 7412 7412 E malloc_debug: allocation[-32] = 0x00 (expected 0xaa) 04-10 12:00:45.622 7412 7412 E malloc_debug: allocation[-15] = 0x02 (expected 0xaa)
Enables a small buffer placed after the allocated data. This is an attempt to find memory corruption occuring to a region after the original allocation. On first allocation, this rear guard is written with a specific pattern (0xbb). When the allocation is freed, the guard is checked to verify it has not been modified. If any part of the rear guard is modified, an error will be reported in the log indicating what bytes changed.
If SIZE_BYTES is present, it indicates the number of bytes in the guard. The default is 32 bytes, the max bytes is 16384.
This option adds a special header to all allocations that contains information about the original allocation.
Example error:
04-10 12:00:45.621 7412 7412 E malloc_debug: +++ ALLOCATION 0x12345678 SIZE 100 HAS A CORRUPTED REAR GUARD 04-10 12:00:45.622 7412 7412 E malloc_debug: allocation[130] = 0xbf (expected 0xbb) 04-10 12:00:45.622 7412 7412 E malloc_debug: allocation[131] = 0x00 (expected 0xbb)
Enables both a front guard and a rear guard on all allocations.
If SIZE_BYTES is present, it indicates the number of bytes in both guards. The default is 32 bytes, the max bytes is 16384.
Enable capturing the backtrace of each allocation site. This option will slow down allocations by an order of magnitude. If the system runs too slowly with this option enabled, decreasing the maximum number of frames captured will speed the allocations up.
Note that any backtrace frames that occur within the malloc backtrace library itself are not recorded.
If MAX_FRAMES is present, it indicates the maximum number of frames to capture in a backtrace. The default is 16 frames, the maximumum value this can be set to is 256.
This option adds a special header to all allocations that contains the backtrace and information about the original allocation.
Enable capturing the backtrace of each allocation site. If the backtrace capture is toggled when the process receives the signal SIGRTMAX - 19 (which is 45 on most Android devices). When this option is used alone, backtrace capture starts out disabled until the signal is received. If both this option and the backtrace option are set, then backtrace capture is enabled until the signal is received.
If MAX_FRAMES is present, it indicates the maximum number of frames to capture in a backtrace. The default is 16 frames, the maximumum value this can be set to is 256.
This option adds a special header to all allocations that contains the backtrace and information about the original allocation.
Any allocation routine, other than calloc, will result in the allocation being filled with the value 0xeb. When doing a realloc to a larger size, the bytes above the original usable size will be set to 0xeb.
If MAX_FILLED_BYTES is present, it will only fill up to the specified number of bytes in the allocation. The default is to fill the entire allocation.
When an allocation is freed, fill it with 0xef.
If MAX_FILLED_BYTES is present, it will only fill up to the specified number of bytes in the allocation. The default is to fill the entire allocation.
This enables both the fill_on_alloc option and the fill_on_free option.
If MAX_FILLED_BYTES is present, it will only fill up to the specified number of bytes in the allocation. The default is to fill the entire allocation.
Add an extra amount to allocate for every allocation.
If XX is present, it is the number of bytes to expand the allocation by. The default is 16 bytes, the max bytes is 16384.
When a pointer is freed, do not free the memory right away, but add it to a list of freed allocations. In addition to being added to the list, the entire allocation is filled with the value 0xef, and the backtrace at the time of the free is recorded. The backtrace recording is completely separate from the backtrace option, and happens automatically if this option is enabled. By default, a maximum of 16 frames will be recorded, but this value can be changed using the free_track_backtrace_num_frames option. It can also be completely disabled by setting the option to zero. See the full description of this option below.
When the list is full, an allocation is removed from the list and is checked to make sure that none of the contents have been modified since being placed on the list. When the program terminates, all of the allocations left on the list are verified.
If ALLOCATION_COUNT is present, it indicates the total number of allocations in the list. The default is to record 100 freed allocations, the max allocations to record is 16384.
This option adds a special header to all allocations that contains information about the original allocation.
Example error:
04-15 12:00:31.304 7412 7412 E malloc_debug: +++ ALLOCATION 0x12345678 USED AFTER FREE 04-15 12:00:31.305 7412 7412 E malloc_debug: allocation[20] = 0xaf (expected 0xef) 04-15 12:00:31.305 7412 7412 E malloc_debug: allocation[99] = 0x12 (expected 0xef) 04-15 12:00:31.305 7412 7412 E malloc_debug: Backtrace at time of free: 04-15 12:00:31.305 7412 7412 E malloc_debug: #00 pc 00029310 /system/lib/libc.so 04-15 12:00:31.305 7412 7412 E malloc_debug: #01 pc 00021438 /system/lib/libc.so (newlocale+160) 04-15 12:00:31.305 7412 7412 E malloc_debug: #02 pc 000a9e38 /system/lib/libc++.so 04-15 12:00:31.305 7412 7412 E malloc_debug: #03 pc 000a28a8 /system/lib/libc++.so
In addition, there is another type of error message that can occur if an allocation has a special header applied, and the header is corrupted before the verification occurs. This is the error message that will be found in the log:
04-15 12:00:31.604 7412 7412 E malloc_debug: +++ ALLOCATION 0x12345678 HAS CORRUPTED HEADER TAG 0x1cc7dc00 AFTER FREE
This option only has meaning if free_track is set. It indicates how many backtrace frames to capture when an allocation is freed.
If MAX_FRAMES is present, it indicates the number of frames to capture. If the value is set to zero, then no backtrace will be captured when the allocation is freed. The default is to record 16 frames, the max number of frames to to record is 256.
Track all live allocations. When the program terminates, all of the live allocations will be dumped to the log. If the backtrace option was enabled, then the log will include the backtrace of the leaked allocations. This option is not useful when enabled globally because a lot of programs do not free everything before the program terminates.
This option adds a special header to all allocations that contains information about the original allocation.
Example leak error found in the log:
04-15 12:35:33.304 7412 7412 E malloc_debug: +++ APP leaked block of size 100 at 0x2be3b0b0 (leak 1 of 2) 04-15 12:35:33.304 7412 7412 E malloc_debug: Backtrace at time of allocation: 04-15 12:35:33.305 7412 7412 E malloc_debug: #00 pc 00029310 /system/lib/libc.so 04-15 12:35:33.305 7412 7412 E malloc_debug: #01 pc 00021438 /system/lib/libc.so (newlocale+160) 04-15 12:35:33.305 7412 7412 E malloc_debug: #02 pc 000a9e38 /system/lib/libc++.so 04-15 12:35:33.305 7412 7412 E malloc_debug: #03 pc 000a28a8 /system/lib/libc++.so 04-15 12:35:33.305 7412 7412 E malloc_debug: +++ APP leaked block of size 24 at 0x7be32380 (leak 2 of 2) 04-15 12:35:33.305 7412 7412 E malloc_debug: Backtrace at time of allocation: 04-15 12:35:33.305 7412 7412 E malloc_debug: #00 pc 00029310 /system/lib/libc.so 04-15 12:35:33.305 7412 7412 E malloc_debug: #01 pc 00021438 /system/lib/libc.so (newlocale+160) 04-15 12:35:33.305 7412 7412 E malloc_debug: #02 pc 000a9e38 /system/lib/libc++.so 04-15 12:35:33.305 7412 7412 E malloc_debug: #03 pc 000a28a8 /system/lib/libc++.so
Keep track of every allocation/free made on every thread and dump them to a file when the signal SIGRTMAX - 18 (which is 46 on most Android devices) is received.
If TOTAL_ENTRIES is set, then it indicates the total number of allocation/free records that can be retained. If the number of records reaches the TOTAL_ENTRIES value, then any further allocations/frees are not recorded. The default value is 8,000,000 and the maximum value this can be set to is 50,000,000.
Once the signal is received, and the current records are written to the file, all current records are deleted. Any allocations/frees occuring while the data is being dumped to the file are ignored.
NOTE: This option is not available until the O release of Android.
The allocation data is written in a human readable format. Every line begins with the THREAD_ID returned by gettid(), which is the thread that is making the allocation/free. If a new thread is created, no special line is added to the file. However, when a thread completes, a special entry is added to the file indicating this.
The thread complete line is:
THREAD_ID: thread_done 0x0
Example:
187: thread_done 0x0
Below is how each type of allocation/free call ends up in the file dump.
pointer = malloc(size)
THREAD_ID: malloc pointer size
Example:
186: malloc 0xb6038060 20
free(pointer)
THREAD_ID: free pointer
Example:
186: free 0xb6038060
pointer = calloc(nmemb, size)
THREAD_ID: calloc pointer nmemb size
Example:
186: calloc 0xb609f080 32 4
new_pointer = realloc(old_pointer, size)
THREAD_ID: realloc new_pointer old_pointer size
Example:
186: realloc 0xb609f080 0xb603e9a0 12
pointer = memalign(alignment, size)
THREAD_ID: memalign pointer alignment size
posix_memalign(&pointer, alignment, size)
THREAD_ID: memalign pointer alignment size
Example:
186: memalign 0x85423660 16 104
pointer = valloc(size)
THREAD_ID: memalign pointer 4096 size
Example:
186: memalign 0x85423660 4096 112
pointer = pvalloc(size)
THREAD_ID: memalign pointer 4096 SIZE_ROUNDED_UP_TO_4096
Example:
186: memalign 0x85423660 4096 8192
This option only has meaning if record_allocs is set. It indicates the file where the recorded allocations will be found.
If FILE_NAME is set, then it indicates where the record allocation data will be placed.
NOTE: This option is not available until the O release of Android.
There are a few other error messages that might appear in the log.
04-15 12:00:31.304 7412 7412 E malloc_debug: +++ ALLOCATION 0x12345678 USED AFTER FREE (free) 04-15 12:00:31.305 7412 7412 E malloc_debug: Backtrace of original free: 04-15 12:00:31.305 7412 7412 E malloc_debug: #00 pc 00029310 /system/lib/libc.so 04-15 12:00:31.305 7412 7412 E malloc_debug: #01 pc 00021438 /system/lib/libc.so (newlocale+160) 04-15 12:00:31.305 7412 7412 E malloc_debug: #02 pc 000a9e38 /system/lib/libc++.so 04-15 12:00:31.305 7412 7412 E malloc_debug: #03 pc 000a28a8 /system/lib/libc++.so 04-15 12:00:31.305 7412 7412 E malloc_debug: Backtrace at time of failure: 04-15 12:00:31.305 7412 7412 E malloc_debug: #00 pc 00029310 /system/lib/libc.so 04-15 12:00:31.305 7412 7412 E malloc_debug: #01 pc 00021438 /system/lib/libc.so (newlocale+160) 04-15 12:00:31.305 7412 7412 E malloc_debug: #02 pc 000a9e38 /system/lib/libc++.so 04-15 12:00:31.305 7412 7412 E malloc_debug: #03 pc 000a28a8 /system/lib/libc++.so
This indicates that code is attempting to free an already freed pointer. The name in parenthesis indicates that the application called the function free with the bad pointer.
For example, this message:
04-15 12:00:31.304 7412 7412 E malloc_debug: +++ ALLOCATION 0x12345678 USED AFTER FREE (realloc)
Would indicate that the application called the realloc function with an already freed pointer.
04-15 12:00:31.304 7412 7412 E malloc_debug: +++ ALLOCATION 0x12345678 HAS INVALID TAG 1ee7d000 (malloc_usable_size) 04-15 12:00:31.305 7412 7412 E malloc_debug: Backtrace at time of failure: 04-15 12:00:31.305 7412 7412 E malloc_debug: #00 pc 00029310 /system/lib/libc.so 04-15 12:00:31.305 7412 7412 E malloc_debug: #01 pc 00021438 /system/lib/libc.so (newlocale+160) 04-15 12:00:31.305 7412 7412 E malloc_debug: #02 pc 000a9e38 /system/lib/libc++.so 04-15 12:00:31.305 7412 7412 E malloc_debug: #03 pc 000a28a8 /system/lib/libc++.so
This indicates that a function (malloc_usable_size) was called with a pointer that is either not allocated memory, or that the memory of the pointer has been corrupted.
As with the other error message, the function in parenthesis is the function that was called with the bad pointer.
Enable backtrace tracking of all allocation for all processes:
adb shell stop adb shell setprop libc.debug.malloc.options backtrace adb shell start
Enable backtrace tracking for a specific process (ls):
adb shell setprop libc.debug.malloc.options backtrace adb shell setprop libc.debug.malloc.program ls adb shell ls
Enable backtrace tracking for the zygote and zygote based processes:
adb shell stop adb shell setprop libc.debug.malloc.program app_process adb shell setprop libc.debug.malloc.options backtrace adb shell start
Enable multiple options (backtrace and guards):
adb shell stop adb shell setprop libc.debug.malloc.options "\"backtrace guards\"" adb shell start
Enable malloc debug when multiple processes have the same name. This method can be used to enable malloc debug for only a very specific process if multiple processes have the same name.
Note: The double quotes in the adb shell command are necessary. Otherwise, the setprop command will fail since the backtrace guards options will look like two arguments instead of one.
adb shell # setprop libc.debug.malloc.env_enabled # setprop libc.debug.malloc.options backtrace # export LIBC_DEBUG_MALLOC_ENABLE 1 # ls
Enable malloc debug and dump the native allocation with backtraces to a file. This only works for zygote based java processes.
adb shell stop adb shell setprop libc.debug.malloc.options backtrace adb shell start adb shell am dumpheap -n <PID_TO_DUMP> /data/local/tmp/heap.txt
It is possible to use the backtrace_enable_on_signal option as well, but it must be enabled through the signal before the file will contain any data.
Malloc debug can be used to get information on all of the live allocations in a process. The libc library in Android exports two calls that can be used to gather this data from a process. This tracking can be enabled using either the backtrace option or the backtrace_enabled_on_signal option.
The function to gather the data:
extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overall_size, size_t* info_size, size_t* total_memory, size_t* backtrace_size);
info is set to a buffer allocated by the call that contains all of the allocation information. overall_size is set to the total size of the buffer returned. If this info_size value is zero, then there are no allocation being tracked. total_memory is set to the sum of all allocation sizes that are live at the point of the function call. This does not include the memory allocated by the malloc debug library itself. backtrace_size is set to the maximum number of backtrace entries that are present for each allocation.
In order to free the buffer allocated by the function, call:
extern "C" void free_malloc_leak_info(uint8_t* info);
size_t size_of_original_allocation size_t num_backtrace_frames uintptr_t pc1 uintptr_t pc2 uintptr_t pc3 . . .
The number of uintptr_t values is determined by the value backtrace_size as returned by the original call to get_malloc_leak_info. This value is not variable, it is the same for all the returned data. The value num_backtrace_frames contains the real number of frames found. The extra frames are set to zero. Each uintptr_t is a pc of the callstack. The calls from within the malloc debug library are automatically removed.
For 32 bit systems, size_t and uintptr_t are both 4 byte values.
For 64 bit systems, size_t and uintptr_t are both 8 byte values.
The total number of these structures returned in info is overall_size divided by info_size.
Note, the size value in each allocation data structure will have bit 31 set if this allocation was created in a process forked from the Zygote process. This helps to distinguish between native allocations created by the application.
Using the command adb shell dumpsys netstats detail
provides network usage statistics collected since the device booted up.
To view network usage statistics, run the following command:
$ adb shell dumpsys netstats detail
The set of information reported varies depending on the version of Android but consists of several sections:
Here is sample output for the active interfaces and active UID interfaces sections:
Active interfaces: iface=wlan0 ident=[{type=WIFI, subType=COMBINED, networkId="GoogleGuest"}] Active UID interfaces: iface=wlan0 ident=[{type=WIFI, subType=COMBINED, networkId="GoogleGuest"}]
This shows network statistics for the whole device. In most cases, the information in these two section is the same.
Here is sample output for the Dev statistics section:
Dev stats: Pending bytes: 170775 Complete history: ident=[[type=MOBILE_HIPRI, subType=COMBINED, subscriberId=311111...]] uid=-1 set=ALL tag=0x0 NetworkStatsHistory: bucketDuration=3600000 bucketStart=1406138400000 activeTime=3603995 rxBytes=19467 rxPackets=53 txBytes=7500 txPackets=61 operations=0 bucketStart=1406142000000 activeTime=20730 rxBytes=25403 rxPackets=66 txBytes=9140 txPackets=74 operations=0 bucketStart=1406145600000 activeTime=29161 rxBytes=9263 rxPackets=37 txBytes=5180 txPackets=38 operations=0 bucketStart=1406149200000 activeTime=9054 rxBytes=12387 rxPackets=31 txBytes=4052 txPackets=35 operations=0 ident=[[type=WIFI, subType=COMBINED, networkId="MySSID"]] uid=-1 set=ALL tag=0x0 NetworkStatsHistory: bucketDuration=3600000 bucketStart=1406138400000 activeTime=4811082 rxBytes=335913292 rxPackets=265144 txBytes=9729261 txPackets=117220 operations=0 bucketStart=1406142000000 activeTime=3513477 rxBytes=1193606876 rxPackets=956855 txBytes=29450792 txPackets=306634 operations=0 bucketStart=1406145600000 activeTime=3297986 rxBytes=729381849 rxPackets=586396 txBytes=24247211 txPackets=237438 operations=0 bucketStart=1406149200000 activeTime=3580941 rxBytes=57168575 rxPackets=51610 txBytes=5291167 txPackets=29260 operations=0 ident=[[type=WIFI, subType=COMBINED, networkId="MySecondSSID"]] uid=-1 set=ALL tag=0x0 NetworkStatsHistory: bucketDuration=3600000
UID stats: Pending bytes: 744 Complete history: ident=[[type=MOBILE_SUPL, subType=COMBINED, subscriberId=311111...], [type=MOBILE, subType=COMBINED, subscriberId=311111...]] uid=10007 set=DEFAULT tag=0x0 NetworkStatsHistory: bucketDuration=7200000 bucketStart=1406167200000 activeTime=7200000 rxBytes=4666 rxPackets=7 txBytes=1597 txPackets=10 operations=0 ident=[[type=WIFI, subType=COMBINED, networkId="MySSID"]] uid=10007 set=DEFAULT tag=0x0 NetworkStatsHistory: bucketDuration=7200000 bucketStart=1406138400000 activeTime=7200000 rxBytes=17086802 rxPackets=15387 txBytes=1214969 txPackets=8036 operations=28 bucketStart=1406145600000 activeTime=7200000 rxBytes=2396424 rxPackets=2946 txBytes=464372 txPackets=2609 operations=70 bucketStart=1406152800000 activeTime=7200000 rxBytes=200907 rxPackets=606 txBytes=187418 txPackets=739 operations=0 bucketStart=1406160000000 activeTime=7200000 rxBytes=826017 rxPackets=1126 txBytes=267342 txPackets=1175 operations=35
To find the UID for your application, you can run this command: adb shell dumpsys package <your package name>
. Then look for the line labeled userId
.
In our example, suppose we are trying to find network usage for our app 「com.example.myapp」. We would run the following command:
$ adb shell dumpsys package com.example.myapp | grep userId userId=10007 gids=[3003, 1028, 1015]
Looking at the dump above, we look for lines that have uid=10007. Two such lines exist, the first indicating a mobile connection, and the second a Wi-Fi connection. Underneath each line, the number of bytes and packets sent and received can be seen, bucketed into two-hour windows.
A bit more explanation:
set=DEFAULT
indicates foreground network usage, while set=BACKGROUND
indicates background usage. set=ALL
implies both.tag=0x0
indicates the socket tag associated with the traffic.rxBytes
and rxPackets
represent received bytes and received packets in the corresponding time interval.txBytes
and txPackets
represent sent (transmitted) bytes and sent packets in the corresponding time interval.
The procstats
tool is used to analyze application memory usage over time (versus at a particular snapshot in time, like meminfo
). Its state dump displays statistics about every application’s runtime, proportional set size (PSS) and unique set size (USS).
To get application memory usage stats for the last three hours, in human-readable form, run the following command:
$ adb shell dumpsys procstats --hours 3
As can be seen in the example below, percentages display what percentage of time the application was running, while the numbers following show PSS and USS as minPSS-avgPSS-maxPSS/minUSS-avgUSS-maxUSS over samples.
AGGREGATED OVER LAST 3 HOURS: * com.android.systemui / u0a20 / v22: TOTAL: 100% (109MB-126MB-159MB/108MB-125MB-157MB over 18) Persistent: 100% (109MB-126MB-159MB/108MB-125MB-157MB over 18) * com.android.nfc / 1027 / v22: TOTAL: 100% (17MB-17MB-17MB/16MB-16MB-16MB over 18) Persistent: 100% (17MB-17MB-17MB/16MB-16MB-16MB over 18) * android.process.acore / u0a4 / v22: TOTAL: 100% (14MB-15MB-15MB/14MB-14MB-14MB over 20) Imp Fg: 100% (14MB-15MB-15MB/14MB-14MB-14MB over 20) * com.google.android.inputmethod.latin / u0a56 / v21483: TOTAL: 100% (57MB-59MB-59MB/56MB-58MB-58MB over 19) Imp Fg: 100% (57MB-59MB-59MB/56MB-58MB-58MB over 19) * com.redbend.vdmc / 1001 / v1: TOTAL: 100% (9.5MB-9.6MB-9.7MB/8.8MB-8.9MB-9.0MB over 18) Persistent: 100% (9.5MB-9.6MB-9.7MB/8.8MB-8.9MB-9.0MB over 18) * com.android.phone / 1001 / v22: TOTAL: 100% (19MB-22MB-27MB/18MB-21MB-26MB over 18) Persistent: 100% (19MB-22MB-27MB/18MB-21MB-26MB over 18) * com.google.android.gms.persistent / u0a8 / v7319438: TOTAL: 100% (32MB-35MB-40MB/30MB-33MB-37MB over 19) Imp Fg: 100% (32MB-35MB-40MB/30MB-33MB-37MB over 19) * com.android.bluetooth / 1002 / v22: TOTAL: 100% (9.3MB-9.7MB-10MB/8.5MB-8.9MB-9.2MB over 19) Imp Fg: 100% (9.3MB-9.7MB-10MB/8.5MB-8.9MB-9.2MB over 19) * com.google.android.googlequicksearchbox:interactor / u0a22 / v300404573: TOTAL: 100% (3.4MB-3.5MB-3.6MB/2.8MB-2.8MB-2.8MB over 19) Imp Fg: 100% (3.4MB-3.5MB-3.6MB/2.8MB-2.8MB-2.8MB over 19) * com.google.process.gapps / u0a8 / v7306438: TOTAL: 100% (23MB-24MB-28MB/21MB-22MB-26MB over 19) Imp Fg: 100% (23MB-24MB-28MB/21MB-22MB-26MB over 19) * com.vito.lux / u0a84 / v237: TOTAL: 100% (32MB-48MB-83MB/31MB-47MB-82MB over 134) Imp Fg: 100% (32MB-48MB-83MB/31MB-47MB-82MB over 134) Service: 0.05% * system / 1000 / v22: TOTAL: 100% (79MB-85MB-102MB/78MB-83MB-100MB over 18) Persistent: 100% (79MB-85MB-102MB/78MB-83MB-100MB over 18) * com.rhapsody / u0a83 / v125: TOTAL: 100% (7.9MB-12MB-19MB/6.9MB-11MB-17MB over 15) Service: 100% (7.9MB-12MB-19MB/6.9MB-11MB-17MB over 15) Service Rs: 0.04% * com.qualcomm.qcrilmsgtunnel / 1001 / v22: TOTAL: 100% (2.5MB-2.6MB-2.7MB/1.7MB-1.8MB-1.9MB over 15) Service: 100% (2.5MB-2.6MB-2.7MB/1.7MB-1.8MB-1.9MB over 15) Service Rs: 0.13% * com.amazon.kindle / u0a82 / v1143472216: TOTAL: 100% (44MB-54MB-77MB/43MB-52MB-74MB over 17) Service: 100% (44MB-54MB-77MB/43MB-52MB-74MB over 17) Service Rs: 0.04% * com.outplaylab.VideoDiet2 / u0a93 / v21: TOTAL: 100% (2.8MB-3.1MB-4.0MB/2.0MB-2.2MB-3.0MB over 15) Service: 100% (2.8MB-3.1MB-4.0MB/2.0MB-2.2MB-3.0MB over 15) Service Rs: 0.03% * android.process.media / u0a6 / v800: TOTAL: 99% (4.6MB-5.9MB-8.1MB/3.4MB-4.7MB-6.7MB over 25) Imp Fg: 0.02% Service: 99% (4.6MB-5.9MB-8.1MB/3.4MB-4.7MB-6.7MB over 25) Service Rs: 0.02% (Cached): 0.94% * kr.sira.sound / u0a108 / v41: TOTAL: 77% (117MB-191MB-219MB/111MB-187MB-213MB over 68) Top: 77% (117MB-191MB-219MB/111MB-187MB-213MB over 68) (Last Act): 18% (58MB-127MB-161MB/53MB-123MB-158MB over 3) (Cached): 0.06% * com.google.android.gms / u0a8 / v7319438: TOTAL: 37% (41MB-45MB-57MB/38MB-42MB-53MB over 23) Top: 13% (41MB-46MB-57MB/39MB-42MB-53MB over 16) Imp Fg: 13% (41MB-44MB-47MB/39MB-41MB-44MB over 5) Imp Bg: 0.38% Service: 11% (42MB-42MB-42MB/38MB-38MB-38MB over 2) Receiver: 0.03% (Last Act): 2.0% (38MB-38MB-38MB/36MB-36MB-36MB over 1) (Cached): 61% (39MB-40MB-43MB/37MB-37MB-40MB over 28) * com.google.android.googlequicksearchbox / u0a22 / v300404573: TOTAL: 22% (129MB-153MB-162MB/125MB-149MB-156MB over 20) Top: 22% (129MB-153MB-162MB/125MB-149MB-156MB over 20) Imp Bg: 0.04% Receiver: 0.01% (Home): 78% (75MB-84MB-122MB/74MB-82MB-117MB over 12) * com.google.android.apps.thehub / u0a102 / v12: TOTAL: 21% (6.4MB-7.6MB-8.7MB/4.8MB-6.0MB-7.2MB over 2) Service: 21% (6.4MB-7.6MB-8.7MB/4.8MB-6.0MB-7.2MB over 2) * com.google.android.talk / u0a54 / v22314462: TOTAL: 9.3% Top: 0.04% Service: 9.3% Receiver: 0.01% (Last Act): 3.9% (69MB-70MB-71MB/67MB-68MB-69MB over 6) (Cached): 87% (42MB-53MB-77MB/40MB-51MB-74MB over 137) * com.google.android.apps.plus / u0a67 / v413836278: TOTAL: 8.2% (9.6MB-12MB-18MB/8.1MB-11MB-16MB over 3) Imp Bg: 0.10% Service: 8.0% (9.6MB-12MB-18MB/8.1MB-11MB-16MB over 3) Receiver: 0.05% (Cached): 59% (7.8MB-19MB-33MB/6.8MB-18MB-31MB over 22) * com.android.providers.calendar / u0a2 / v22: TOTAL: 3.5% (7.3MB-7.7MB-8.0MB/5.9MB-6.5MB-6.9MB over 10) Imp Bg: 0.32% Service: 3.2% (7.3MB-7.7MB-8.0MB/5.9MB-6.5MB-6.9MB over 10) Receiver: 0.01% (Cached): 69% (4.7MB-6.6MB-7.8MB/3.5MB-5.5MB-6.7MB over 23) * com.amazon.mShop.android / u0a104 / v5030102: TOTAL: 2.7% (25MB-40MB-47MB/24MB-37MB-43MB over 6) Service: 2.6% (25MB-40MB-47MB/24MB-37MB-43MB over 6) Receiver: 0.15% (Cached): 97% (25MB-33MB-48MB/24MB-31MB-44MB over 46) * com.google.android.gm / u0a70 / v51001620: TOTAL: 2.2% (209MB-209MB-209MB/203MB-203MB-203MB over 1) Top: 0.48% (209MB-209MB-209MB/203MB-203MB-203MB over 1) Imp Bg: 0.70% Service: 1.0% Receiver: 0.01% (Last Act): 0.02% (Cached): 94% (25MB-67MB-116MB/23MB-63MB-109MB over 61) * com.google.android.googlequicksearchbox:search / u0a22 / v300404573: TOTAL: 2.1% (66MB-66MB-66MB/63MB-63MB-63MB over 1) Top: 1.4% (66MB-66MB-66MB/63MB-63MB-63MB over 1) Imp Fg: 0.01% Service: 0.66% Receiver: 0.02% (Cached): 98% (52MB-59MB-79MB/50MB-56MB-77MB over 56) * com.google.android.calendar / u0a31 / v2015030452: TOTAL: 1.4% Imp Bg: 0.33% Service: 1.1% Receiver: 0.02% (Cached): 80% (7.4MB-12MB-17MB/5.8MB-9.8MB-14MB over 18) * com.android.vending / u0a16 / v80341100: TOTAL: 1.3% (88MB-154MB-220MB/85MB-151MB-217MB over 2) Top: 1.3% (88MB-154MB-220MB/85MB-151MB-217MB over 2) Service: 0.06% Receiver: 0.02% (Last Act): 4.4% (46MB-68MB-89MB/45MB-66MB-87MB over 2) (Cached): 11% (15MB-74MB-133MB/13MB-72MB-131MB over 2) * com.google.android.apps.photos / u0a65 / v5616: TOTAL: 0.94% Service: 0.90% Receiver: 0.04% (Cached): 80% (9.2MB-12MB-17MB/7.5MB-11MB-15MB over 20) * com.amazon.avod.thirdpartyclient / u0a107 / v451210: TOTAL: 0.52% Service: 0.49% Receiver: 0.03% (Cached): 97% (14MB-24MB-34MB/13MB-22MB-31MB over 40) * com.google.android.gms.wearable / u0a8 / v7319438: TOTAL: 0.51% Imp Fg: 0.47% Service: 0.04% (Cached): 65% (4.7MB-6.5MB-8.2MB/3.6MB-4.2MB-5.4MB over 10) * com.amazon.mShop.android.shopping / u0a103 / v5040011: TOTAL: 0.50% Service: 0.37% Receiver: 0.13% (Cached): 77% (13MB-17MB-21MB/11MB-15MB-19MB over 15) * com.google.android.gms:car / u0a8 / v7319438: TOTAL: 0.49% (7.1MB-7.1MB-7.1MB/4.3MB-4.3MB-4.3MB over 1) Top: 0.05% Imp Fg: 0.39% (7.1MB-7.1MB-7.1MB/4.3MB-4.3MB-4.3MB over 1) Service: 0.05% (Cached): 0.60% (6.6MB-6.6MB-6.6MB/3.6MB-3.6MB-3.6MB over 1) * com.amazon.mp3 / u0a92 / v4033010: TOTAL: 0.46% Service: 0.43% Receiver: 0.03% (Cached): 84% (12MB-16MB-23MB/9.7MB-14MB-21MB over 25) * com.android.chrome:privileged_process1 / u0a34 / v2272096: TOTAL: 0.43% Service: 0.04% Service Rs: 0.39% (Cached): 100% (2.9MB-4.0MB-4.9MB/1.7MB-2.9MB-3.9MB over 18) * com.google.android.dialer / u0a10 / v20100: TOTAL: 0.39% (93MB-93MB-93MB/89MB-89MB-89MB over 1) Top: 0.23% (93MB-93MB-93MB/89MB-89MB-89MB over 1) Imp Fg: 0.16% (Cached): 16% (5.0MB-31MB-57MB/4.1MB-29MB-54MB over 2) * com.google.android.apps.maps / u0a58 / v906101124: TOTAL: 0.38% Service: 0.33% Receiver: 0.05% (Cached): 69% (8.7MB-15MB-18MB/7.2MB-14MB-17MB over 8) * com.google.android.youtube / u0a80 / v101451214: TOTAL: 0.26% Service: 0.26% (Cached): 36% (15MB-22MB-29MB/13MB-19MB-27MB over 5) * com.google.android.apps.fitness / u0a45 / v2015109100: TOTAL: 0.26% Service: 0.23% Receiver: 0.02% (Cached): 82% (3.9MB-6.4MB-9.2MB/2.8MB-5.3MB-7.9MB over 19) * com.google.android.apps.enterprise.dmagent / u0a37 / v630: TOTAL: 0.06% Service: 0.06% Receiver: 0.01% (Cached): 2.2% (6.5MB-7.4MB-8.2MB/4.8MB-5.8MB-6.8MB over 2) * com.audible.application / u0a95 / v3068: TOTAL: 0.06% Receiver: 0.06% (Cached): 34% (14MB-16MB-19MB/11MB-14MB-17MB over 7) * com.android.defcontainer / u0a5 / v22: TOTAL: 0.06% Imp Fg: 0.06% (Cached): 0.12% * com.google.android.music:main / u0a60 / v1847: TOTAL: 0.04% Top: 0.01% Service: 0.02% Receiver: 0.01% (Cached): 9.8% (10MB-12MB-14MB/8.3MB-9.6MB-11MB over 2) * com.google.android.apps.magazines / u0a61 / v2015040100: TOTAL: 0.03% Top: 0.02% Receiver: 0.01% (Cached): 8.7% (12MB-14MB-16MB/9.7MB-11MB-13MB over 2) * com.google.android.videos / u0a77 / v37191: TOTAL: 0.03% Imp Fg: 0.01% Service: 0.02% (Cached): 1.3% (11MB-12MB-13MB/9.1MB-10MB-12MB over 2) * com.google.android.apps.books / u0a28 / v30336: TOTAL: 0.03% Imp Fg: 0.01% Service: 0.02% (Cached): 1.3% (7.9MB-9.6MB-11MB/6.3MB-8.0MB-9.7MB over 2) * com.google.android.keep / u0a71 / v3115: TOTAL: 0.02% Service: 0.01% Receiver: 0.01% (Cached): 11% (6.3MB-8.7MB-9.6MB/5.1MB-7.4MB-8.3MB over 4) * com.android.chrome / u0a34 / v2272096: TOTAL: 0.02% Service: 0.01% Receiver: 0.02% (Cached): 90% (5.1MB-70MB-96MB/3.4MB-66MB-92MB over 15) * com.google.android.apps.gcs / u0a94 / v14: TOTAL: 0.02% Service: 0.02% (Cached): 17% (5.8MB-5.9MB-6.0MB/4.6MB-4.7MB-4.8MB over 2) * com.android.chrome:privileged_process0 / u0a34 / v2272096: TOTAL: 0.02% Service: 0.01% Receiver: 0.01% (Cached): 73% (162MB-163MB-164MB/157MB-157MB-157MB over 13) * com.android.chrome:sandboxed_process12 / u0a34 / v2272096: TOTAL: 0.02% Service: 0.01% Receiver: 0.01% (Cached): 73% (48MB-49MB-51MB/46MB-47MB-50MB over 13) * com.google.android.apps.docs / u0a40 / v51410735: TOTAL: 0.01% Receiver: 0.01% (Cached): 0.45% (10MB-10MB-10MB/9.3MB-9.3MB-9.3MB over 1) * com.google.android.deskclock / u0a38 / v303: TOTAL: 0.01% Receiver: 0.01% (Cached): 82% (2.5MB-3.3MB-4.3MB/1.7MB-2.3MB-3.2MB over 13) * com.google.android.gm.exchange / u0a69 / v500065: TOTAL: 0.01% Imp Bg: 0.01% (Cached): 27% (3.3MB-3.7MB-3.9MB/2.2MB-2.7MB-2.9MB over 6) * com.android.cellbroadcastreceiver / u0a3 / v22: TOTAL: 0.01% Service: 0.01% (Cached): 1.1% (3.5MB-3.5MB-3.5MB/2.5MB-2.5MB-2.5MB over 1) * com.coulombtech / u0a106 / v26: TOTAL: 0.01% Receiver: 0.01% (Cached): 21% (4.9MB-5.0MB-5.2MB/3.8MB-3.9MB-4.1MB over 2) * com.softcoil.mms / u0a86 / v32: TOTAL: 0.01% (Cached): 0.25% * com.udemy.android / u0a91 / v38: TOTAL: 0.01% Receiver: 0.01% (Cached): 0.75% (9.8MB-9.8MB-9.8MB/8.5MB-8.5MB-8.5MB over 1) * com.qualcomm.timeservice / u0a76 / v22: (Cached): 16% (2.3MB-2.4MB-2.4MB/1.6MB-1.6MB-1.6MB over 4) * com.lge.SprintHiddenMenu / 1000 / v22: (Cached): 0.16% * com.android.chrome:sandboxed_process13 / u0a34 / v2272096: (Cached): 0.01% * com.google.android.partnersetup / u0a13 / v22: (Cached): 0.14% * com.android.musicfx / u0a15 / v10400: (Cached): 0.41% (2.5MB-2.5MB-2.5MB/1.6MB-1.6MB-1.6MB over 1) * com.android.chrome:sandboxed_process9 / u0a34 / v2272096: (Cached): 30% (34MB-34MB-34MB/32MB-32MB-32MB over 9) * com.android.chrome:sandboxed_process11 / u0a34 / v2272096: (Cached): 7.2% (56MB-56MB-56MB/54MB-54MB-54MB over 3) Run time Stats: SOff/Norm: +32m52s226ms SOn /Norm: +2h10m8s364ms Mod : +17s930ms TOTAL: +2h43m18s520ms Memory usage: Kernel : 265MB (38 samples) Native : 73MB (38 samples) Persist: 262MB (90 samples) Top : 190MB (325 samples) ImpFg : 204MB (569 samples) ImpBg : 754KB (345 samples) Service: 93MB (1912 samples) Receivr: 227KB (1169 samples) Home : 66MB (12 samples) LastAct: 30MB (255 samples) CchAct : 220MB (450 samples) CchCAct: 193MB (71 samples) CchEmty: 182MB (652 samples) Cached : 58MB (38 samples) Free : 60MB (38 samples) TOTAL : 1.9GB ServRst: 50KB (278 samples) Start time: 2015-04-08 13:44:18 Total elapsed time: +2h43m18s521ms (partial) libart.so