Android Framework常用工具及LOG调试方法

时间:2024-05-21 19:59:28

概述  

    Framework开发是一项非常繁琐复杂的工作,需要阅读大量的源代码,分析及其多的LOG信息来定位错误位置。这个时候如果使用一些工具或者知道如何定位重要LOG信息,就可以使一些复杂的工作变的简单很多,使我们分析问题的效率变得更快,不再为阅读大量的源代码而感到一筹莫展。本文将针对一些场景讲解如何分析系统LOG信息,如何添加LOG定位错误信息,以及常用工具以及使用方法。

常用工具

HierarchyViewer

      HierarchyViewer是随Android SDK发布的工具,位置在sdktools文件夹下,名为hierarchyviewer。它是Android自带的非常有用而且使用简单的工具,能够让我们从可视化的角度直观地获得UI布局设计结构和各种属性的信息,帮助我们优化布局设计。打开HierarchyViewer后我们可以看到当前view的布局,如下图所示。

Android Framework常用工具及LOG调试方法

DDMS

       DDMS 的全称是Dalvik Debug Monitor Service,是 Android 开发环境中的Dalvik虚拟机调试监控服务。它为我们提供例如:为测试设备截屏,针对特定的进程查看正在运行的线程以及堆信息、Logcat、广播状态信息、模拟电话呼叫、接收SMS、虚拟地理坐标等等。DDMS打开界面如下:

Android Framework常用工具及LOG调试方法

左侧的Devices一栏会列出已连接的设备,点击设备名称左侧三角符号图标会列出该设备运行中的进程的app包名。

Android Framework常用工具及LOG调试方法

模拟按键

使用命令adb shell input keyevent + 对应的键值,可以模拟对应的操作。手机系统中主要的键值如下:

[java] view plain copy
  1. /** Key code constant: Home key. 
  2.  * This key is handled by the framework and is never delivered to applications. */  
  3. public static final int KEYCODE_HOME            = 3;    //Home键  
  4. /** Key code constant: Back key. */  
  5. public static final int KEYCODE_BACK            = 4;    //Back键  
  6. /** Key code constant: Call key. */  
  7. public static final int KEYCODE_CALL            = 5;    //打电话  
  8. /** Key code constant: End Call key. */  
  9. public static final int KEYCODE_ENDCALL         = 6;    //挂断电话  
  10. /** Key code constant: Volume Up key. 
  11.  * Adjusts the speaker volume up. */  
  12. public static final int KEYCODE_VOLUME_UP       = 24;   //调大声音  
  13. /** Key code constant: Volume Down key. 
  14.  * Adjusts the speaker volume down. */  
  15. public static final int KEYCODE_VOLUME_DOWN     = 25;   //调小声音  
  16. /** Key code constant: Power key. */  
  17. public static final int KEYCODE_POWER           = 26;   //电源键  
  18. /** Key code constant: Camera key. 
  19.  * Used to launch a camera application or take pictures. */  
  20. public static final int KEYCODE_CAMERA          = 27;     //相机按键  
  21. /** Key code constant: Clear key. */  
  22. public static final int KEYCODE_CLEAR           = 28;     //清理  
  23. /** Key code constant: Space key. */  
  24. public static final int KEYCODE_SPACE           = 62;     //空格键  
  25. /** Key code constant: Backspace key. 
  26.  * Deletes characters before the insertion point, unlike {@link #KEYCODE_FORWARD_DEL}. */  
  27. public static final int KEYCODE_DEL             = 67;     //删除键  
  28. /** Key code constant: Menu key. */  
  29. public static final int KEYCODE_MENU            = 82;      //菜单键  

当我们要模拟power键亮灭屏事件就可以执行下面命令:

[java] view plain copy
  1. adb shell input keyevent 26  

模拟别的按键事件同理。

而adb shell getevent / adb shell sendevent是发送对应的事件,包括触屏,按键等事件。

am命令

      有时候我们在调试系统时可以在终端使用am命令来发送广播,打开Activity,启动Service等操作,十分方便。am的详细操作如下,我们可以通过adb shell am + 对应命令,就可操作。

[java] view plain copy
  1. usage: am [subcommand] [options]  
  2. usage: am start [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>]  
  3.                [--sampling INTERVAL] [-R COUNT] [-S]  
  4.                [--track-allocation] [--user <USER_ID> | current] <INTENT> //可以通过该命令启动对应Activity  
  5.        am startservice [--user <USER_ID> | current] <INTENT>   //启动服务  
  6.        am stopservice [--user <USER_ID> | current] <INTENT>    //停止服务  
  7.        am force-stop [--user <USER_ID> | all | current] <PACKAGE>  //通过包名强制停止应用  
  8.        am kill [--user <USER_ID> | all | current] <PACKAGE>  //根据进程号杀死进程  
  9.        am kill-all                                           //杀掉所有后台进程  
  10.        am broadcast [--user <USER_ID> | all | current] <INTENT>  //发送广播  
  11.        am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]  
  12.                [--user <USER_ID> | current]  
  13.                [--no-window-animation] [--abi <ABI>] <COMPONENT>  
  14.        am profile start [--user <USER_ID> current] [--sampling INTERVAL] <PROCESS> <FILE> //抓取traceview  
  15.        am profile stop [--user <USER_ID> current] [<PROCESS>]      //停止抓取traceview  
  16.        am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>  
  17.        am set-debug-app [-w] [--persistent] <PACKAGE>  
  18.        am clear-debug-app  
  19.        am set-watch-heap <PROCESS> <MEM-LIMIT>  
  20.        am clear-watch-heap  
  21.        am bug-report [--progress]  
  22.        am monitor [--gdb <port>]  
  23.        am hang [--allow-restart]  
  24.        am restart                             //重启应用  
  25.        am idle-maintenance  
  26.        am screen-compat [on|off] <PACKAGE>  
  27.        am package-importance <PACKAGE>  
  28.        am to-uri [INTENT]  
  29.        am to-intent-uri [INTENT]  
  30.        am to-app-uri [INTENT]  
  31.        am switch-user <USER_ID>  
  32.        am start-user <USER_ID>  
  33.        am unlock-user <USER_ID> [TOKEN_HEX]  
  34.        am stop-user [-w] [-f] <USER_ID>  
  35.        am stack start <DISPLAY_ID> <INTENT>           
  36.        am stack movetask <TASK_ID> <STACK_ID> [true|false]  //stack相关  
  37.        am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>  
  38.        am stack resize-animated <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>  
  39.        am stack resize-docked-stack <LEFT,TOP,RIGHT,BOTTOM> [<TASK_LEFT,TASK_TOP,TASK_RIGHT,TASK_BOTTOM>]  
  40.        am stack size-docked-stack-test: <STEP_SIZE> <l|t|r|b> [DELAY_MS]  
  41.        am stack move-top-activity-to-pinned-stack: <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>  
  42.        am stack positiontask <TASK_ID> <STACK_ID> <POSITION>  
  43.        am stack list                                    //列出系统中的所有stack     
  44.        am stack info <STACK_ID>                         //stack信息  
  45.        am stack remove <STACK_ID>                       //移除stack  
  46.        am task lock <TASK_ID>  
  47.        am task lock stop                           
  48.        am task resizeable <TASK_ID> [0 (unresizeable) | 1 (crop_windows) | 2 (resizeable) | 3 (resizeable_and_pipable)]  
  49.        am task resize <TASK_ID> <LEFT,TOP,RIGHT,BOTTOM>  
  50.        am task drag-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS]   
  51.        am task size-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS]   
  52.        am get-config  
  53.        am suppress-resize-config-changes <true|false>  
  54.        am set-inactive [--user <USER_ID>] <PACKAGE> true|false  
  55.        am get-inactive [--user <USER_ID>] <PACKAGE>  
  56.        am send-trim-memory [--user <USER_ID>] <PROCESS>  
  57.                [HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|RUNNING_CRITICAL|COMPLETE]  
  58.        am get-current-user  
  59.   
  60. am start: start an Activity.  Options are:    //启动Activity详细使用方法  
  61.     -D: enable debugging  
  62.     -N: enable native debugging  
  63.     -W: wait for launch to complete  
  64.     --start-profiler <FILE>: start profiler and send results to <FILE>  
  65.     --sampling INTERVAL: use sample profiling with INTERVAL microseconds  
  66.         between samples (use with --start-profiler)  
  67.     -P <FILE>: like above, but profiling stops when app goes idle  
  68.     -R: repeat the activity launch <COUNT> times.  Prior to each repeat,  
  69.         the top activity will be finished.  
  70.     -S: force stop the target app before starting the activity  
  71.     --track-allocation: enable tracking of object allocations  
  72.     --user <USER_ID> | current: Specify which user to run as; if not  
  73.         specified then run as the current user.  
  74.     --stack <STACK_ID>: Specify into which stack should the activity be put.  
  75. am startservice: start a Service.  Options are:  
  76.     --user <USER_ID> | current: Specify which user to run as; if not  
  77.         specified then run as the current user.  
  78.   
  79. am stopservice: stop a Service.  Options are:  
  80.     --user <USER_ID> | current: Specify which user to run as; if not  
  81.         specified then run as the current user.  
  82.   
  83. am force-stop: force stop everything associated with <PACKAGE>.  
  84.     --user <USER_ID> | all | current: Specify user to force stop;  
  85.         all users if not specified.  
  86.   
  87. am kill: Kill all processes associated with <PACKAGE>.  Only kills.  
  88.   processes that are safe to kill -- that is, will not impact the user  
  89.   experience.  
  90.     --user <USER_ID> | all | current: Specify user whose processes to kill;  
  91.         all users if not specified.  
  92.   
  93. am kill-all: Kill all background processes.  
  94.   
  95. am broadcast: send a broadcast Intent.  Options are:  
  96.     --user <USER_ID> | all | current: Specify which user to send to; if not  
  97.         specified then send to all users.  
  98.     --receiver-permission <PERMISSION>: Require receiver to hold permission.  
  99.   
  100. am instrument: start an Instrumentation.  Typically this target <COMPONENT>  
  101.   is the form <TEST_PACKAGE>/<RUNNER_CLASS> or only <TEST_PACKAGE> if there   
  102.   is only one instrumentation.  Options are:  
  103.     -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT).  Use with  
  104.         [-e perf true] to generate raw output for performance measurements.  
  105.     -e <NAME> <VALUE>: set argument <NAME> to <VALUE>.  For test runners a  
  106.         common form is [-e <testrunner_flag> <value>[,<value>...]].  
  107.     -p <FILE>: write profiling data to <FILE>  
  108.     -w: wait for instrumentation to finish before returning.  Required for  
  109.         test runners.  
  110.     --user <USER_ID> | current: Specify user instrumentation runs in;  
  111.         current user if not specified.  
  112.     --no-window-animation: turn off window animations while running.  
  113.     --abi <ABI>: Launch the instrumented process with the selected ABI.  
  114.         This assumes that the process supports the selected ABI.  
  115.   
  116. am trace-ipc: Trace IPC transactions.  
  117.   start: start tracing IPC transactions.  
  118.   stop: stop tracing IPC transactions and dump the results to file.  
  119.     --dump-file <FILE>: Specify the file the trace should be dumped to.  
  120.   
  121. am profile: start and stop profiler on a process.  The given <PROCESS> argument  
  122.   may be either a process name or pid.  Options are:  
  123.     --user <USER_ID> | current: When supplying a process name,  
  124.         specify user of process to profile; uses current user if not specified.  
  125.   
  126. am dumpheap: dump the heap of a process.  The given <PROCESS> argument may  
  127.   be either a process name or pid.  Options are:  
  128.     -n: dump native heap instead of managed heap  
  129.     --user <USER_ID> | current: When supplying a process name,  
  130.         specify user of process to dump; uses current user if not specified.  
  131.   
  132. am set-debug-app: set application <PACKAGE> to debug.  Options are:  
  133.     -w: wait for debugger when application starts  
  134.     --persistent: retain this value  
  135.   
  136. am clear-debug-app: clear the previously set-debug-app.  
  137.   
  138. am set-watch-heap: start monitoring pss size of <PROCESS>, if it is at or  
  139.     above <HEAP-LIMIT> then a heap dump is collected for the user to report  
  140.   
  141. am clear-watch-heap: clear the previously set-watch-heap.  
  142.   
  143. am bug-report: request bug report generation; will launch a notification  
  144.     when done to select where it should be delivered. Options are:   
  145.    --progress: will launch a notification right away to show its progress.  
  146.   
  147. am monitor: start monitoring for crashes or ANRs.  
  148.     --gdb: start gdbserv on the given port at crash/ANR  
  149.   
  150. am hang: hang the system.  
  151.     --allow-restart: allow watchdog to perform normal system restart  
  152.   
  153. am restart: restart the user-space system.  
  154.   
  155. am idle-maintenance: perform idle maintenance now.  
  156.   
  157. am screen-compat: control screen compatibility mode of <PACKAGE>.  
  158.   
  159. am package-importance: print current importance of <PACKAGE>.  
  160.   
  161. am to-uri: print the given Intent specification as a URI.  
  162.   
  163. am to-intent-uri: print the given Intent specification as an intent: URI.  
  164.   
  165. am to-app-uri: print the given Intent specification as an android-app: URI.  
  166.   
  167. am switch-user: switch to put USER_ID in the foreground, starting  
  168.   execution of that user if it is currently stopped.  
  169.   
  170. am start-user: start USER_ID in background if it is currently stopped,  
  171.   use switch-user if you want to start the user in foreground.  
  172.   
  173. am stop-user: stop execution of USER_ID, not allowing it to run any  
  174.   code until a later explicit start or switch to it.  
  175.   -w: wait for stop-user to complete.  
  176.   -f: force stop even if there are related users that cannot be stopped.  
  177.   
  178. am stack start: start a new activity on <DISPLAY_ID> using <INTENT>.  
  179.   
  180. am stack movetask: move <TASK_ID> from its current stack to the top (true) or   bottom (false) of <STACK_ID>.  
  181.   
  182. am stack resize: change <STACK_ID> size and position to <LEFT,TOP,RIGHT,BOTTOM>.  
  183.   
  184. am stack resize-docked-stack: change docked stack to <LEFT,TOP,RIGHT,BOTTOM>  
  185.    and supplying temporary different task bounds indicated by  
  186.    <TASK_LEFT,TOP,RIGHT,BOTTOM>  
  187.   
  188. am stack size-docked-stack-test: test command for sizing docked stack by  
  189.    <STEP_SIZE> increments from the side <l>eft, <t>op, <r>ight, or <b>ottom  
  190.    applying the optional [DELAY_MS] between each step.  
  191.   
  192. am stack move-top-activity-to-pinned-stack: moves the top activity from  
  193.    <STACK_ID> to the pinned stack using <LEFT,TOP,RIGHT,BOTTOM> for the  
  194.    bounds of the pinned stack.  
  195.   
  196. am stack positiontask: place <TASK_ID> in <STACK_ID> at <POSITION>  
  197. am stack list: list all of the activity stacks and their sizes.  
  198.   
  199. am stack info: display the information about activity stack <STACK_ID>.  
  200.   
  201. am stack remove: remove stack <STACK_ID>.  
  202.   
  203. am task lock: bring <TASK_ID> to the front and don't allow other tasks to run.  
  204.   
  205. am task lock stop: end the current task lock.  
  206.   
  207. am task resizeable: change resizeable mode of <TASK_ID>.  
  208.    0 (unresizeable) | 1 (crop_windows) | 2 (resizeable) | 3 (resizeable_and_pipable)  
  209.   
  210. am task resize: makes sure <TASK_ID> is in a stack with the specified bounds.  
  211.    Forces the task to be resizeable and creates a stack if no existing stack  
  212.    has the specified bounds.  
  213.   
  214. am task drag-task-test: test command for dragging/moving <TASK_ID> by  
  215.    <STEP_SIZE> increments around the screen applying the optional [DELAY_MS]  
  216.    between each step.  
  217.   
  218. am task size-task-test: test command for sizing <TASK_ID> by <STEP_SIZE>   increments within the screen applying the optional [DELAY_MS] between  
  219.    each step.  
  220.   
  221. am get-config: retrieve the configuration and any recent configurations  
  222.   of the device.  
  223. am suppress-resize-config-changes: suppresses configuration changes due to  
  224.   user resizing an activity/task.  
  225.   
  226. am set-inactive: sets the inactive state of an app.  
  227.   
  228. am get-inactive: returns the inactive state of an app.  
  229.   
  230. am send-trim-memory: send a memory trim event to a <PROCESS>.  
  231.   
  232. am get-current-user: returns id of the current foreground user.  
  233.   
  234.   
  235. <INTENT> specifications include these flags and arguments:  
  236.     [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]  
  237.     [-c <CATEGORY> [-c <CATEGORY>] ...]  
  238.     [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]  
  239.     [--esn <EXTRA_KEY> ...]  
  240.     [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]  
  241.     [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]  
  242.     [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]  
  243.     [--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...]  
  244.     [--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]  
  245.     [--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>]  
  246.     [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]  
  247.         (mutiple extras passed as Integer[])  
  248.     [--eial <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]  
  249.         (mutiple extras passed as List<Integer>)  
  250.     [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]  
  251.         (mutiple extras passed as Long[])  
  252.     [--elal <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]  
  253.         (mutiple extras passed as List<Long>)  
  254.     [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]  
  255.         (mutiple extras passed as Float[])  
  256.     [--efal <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]  
  257.         (mutiple extras passed as List<Float>)  
  258.     [--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]  
  259.         (mutiple extras passed as String[]; to embed a comma into a string,  
  260.          escape it using "\,")  
  261.     [--esal <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]  
  262.         (mutiple extras passed as List<String>; to embed a comma into a string,  
  263.          escape it using "\,")  
  264.     [--f <FLAG>]  
  265.     [--grant-read-uri-permission] [--grant-write-uri-permission]  
  266.     [--grant-persistable-uri-permission] [--grant-prefix-uri-permission]  
  267.     [--debug-log-resolution] [--exclude-stopped-packages]  
  268.     [--include-stopped-packages]  
  269.     [--activity-brought-to-front] [--activity-clear-top]  
  270.     [--activity-clear-when-task-reset] [--activity-exclude-from-recents]  
  271.     [--activity-launched-from-history] [--activity-multiple-task]  
  272.     [--activity-no-animation] [--activity-no-history]  
  273.     [--activity-no-user-action] [--activity-previous-is-top]  
  274.     [--activity-reorder-to-front] [--activity-reset-task-if-needed]  
  275.     [--activity-single-top] [--activity-clear-task]  
  276.     [--activity-task-on-home]  
  277.     [--receiver-registered-only] [--receiver-replace-pending]  
  278.     [--receiver-foreground]  
  279.     [--selector]  
  280.     [<URI> | <PACKAGE> | <COMPONENT>]  

pm命令

当要查询系统中某个应用是否存在,或者存在路径,就可以根据对应的包名来查找对应的apk信息。
[java] view plain copy
  1. usage: pm path [--user USER_ID] PACKAGE  
  2.        pm dump PACKAGE                       //dump某个apk  
  3.        pm install [-lrtsfd] [-i PACKAGE] [--user USER_ID] [PATH]  //安装应用  
  4.        pm install-create [-lrtsfdp] [-i PACKAGE] [-S BYTES]  
  5.                [--install-location 0/1/2]  
  6.                [--force-uuid internal|UUID]  
  7.        pm install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH]  
  8.        pm install-commit SESSION_ID  
  9.        pm install-abandon SESSION_ID  
  10.        pm uninstall [-k] [--user USER_ID] PACKAGE            //卸载应用  
  11.        pm set-installer PACKAGE INSTALLER                    //设置installer  
  12.        pm move-package PACKAGE [internal|UUID]               //移除package  
  13.        pm move-primary-storage [internal|UUID]  
  14.        pm clear [--user USER_ID] PACKAGE                     //清除应用信息  
  15.        pm enable [--user USER_ID] PACKAGE_OR_COMPONENT  
  16.        pm disable [--user USER_ID] PACKAGE_OR_COMPONENT  
  17.        pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT  
  18.        pm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT  
  19.        pm default-state [--user USER_ID] PACKAGE_OR_COMPONENT  
  20.        pm hide [--user USER_ID] PACKAGE_OR_COMPONENT  
  21.        pm unhide [--user USER_ID] PACKAGE_OR_COMPONENT  
  22.        pm grant [--user USER_ID] PACKAGE PERMISSION  
  23.        pm revoke [--user USER_ID] PACKAGE PERMISSION  
  24.        pm reset-permissions                                //重置权限  
  25.        pm set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}  
  26.        pm get-app-link [--user USER_ID] PACKAGE  
  27.        pm set-install-location [0/auto] [1/internal] [2/external]   //设置安装路径  
  28.        pm get-install-location                                     获取安装路径  
  29.        pm set-permission-enforced PERMISSION [true|false]  
  30.        pm trim-caches DESIRED_FREE_SPACE [internal|UUID]  
  31.        pm create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral] [--guest] USER_NAME  
  32.        pm remove-user USER_ID  
  33.        pm get-max-users  
  34.   
  35. NOTE: 'pm list' commands have moved! Run 'adb shell cmd package'  
  36.   to display the new commands.   //使用adb shell pm list packages -f获取系统中所有apk的安装路径  
  37.   
  38. pm path: print the path to the .apk of the given PACKAGE. //adb shell path +包名,获取apk路径  
  39.   
  40. pm dump: print system state associated with the given PACKAGE.  
  41.   
  42. pm install: install a single legacy package  
  43. pm install-create: create an install session  
  44.     -l: forward lock application  
  45.     -r: replace existing application  
  46.     -t: allow test packages  
  47.     -i: specify the installer package name  
  48.     -s: install application on sdcard  
  49.     -f: install application on internal flash  
  50.     -d: allow version code downgrade (debuggable packages only)  
  51.     -p: partial application install  
  52.     -g: grant all runtime permissions  
  53.     -S: size in bytes of entire session  
  54.   
  55. pm install-write: write a package into existing session; path may  
  56.   be '-' to read from stdin  
  57.     -S: size in bytes of package, required for stdin  
  58.   
  59. pm install-commit: perform install of fully staged session  
  60. pm install-abandon: abandon session  
  61.   
  62. pm set-installer: set installer package name  
  63.   
  64. pm uninstall: removes a package from the system. Options:  
  65.     -k: keep the data and cache directories around after package removal.  
  66.   
  67. pm clear: deletes all data associated with a package.  
  68.   
  69. pm enable, disable, disable-user, disable-until-used, default-state:  
  70.   these commands change the enabled state of a given package or  
  71.   component (written as "package/class").  
  72.   
  73. pm grant, revoke: these commands either grant or revoke permissions  
  74.     to apps. The permissions must be declared as used in the app's  
  75.     manifest, be runtime permissions (protection level dangerous),  
  76.     and the app targeting SDK greater than Lollipop MR1.  
  77.   
  78. pm reset-permissions: revert all runtime permissions to their default state.  
  79.   
  80. pm get-install-location: returns the current install location.  
  81.     0 [auto]: Let system decide the best location  
  82.     1 [internal]: Install on internal device storage  
  83.     2 [external]: Install on external media  
  84.   
  85. pm set-install-location: changes the default install location.  
  86.   NOTE: this is only intended for debugging; using this can cause  
  87.   applications to break and other undersireable behavior.  
  88.     0 [auto]: Let system decide the best location  
  89.     1 [internal]: Install on internal device storage  
  90.     2 [external]: Install on external media  
  91.   
  92. pm trim-caches: trim cache files to reach the given free space.  
  93.   
  94. pm create-user: create a new user with the given USER_NAME,  
  95.   printing the new user identifier of the user.  
  96.   
  97. pm remove-user: remove the user with the given USER_IDENTIFIER,  
  98.   deleting all data associated with that user  

dumpsys

该命令用于打印出当前系统信息,默认打印出设备中所有service的信息,可以在命令后面加指定的service name

可以通过adb shell dumpsys + services可以打印出对应系统service的dump信息。可以将某个模块详细信息输出到控制台,可以更加直观的分析。

例如要打印Activity的dump信息:adb shell dumpsys activity

[java] view plain copy
  1. Currently running services:  
  2.   AtCmdFwd  
  3.   DockObserver  
  4.   SurfaceFlinger     //重要  
  5.   accessibility  
  6.   account  
  7.   activity          //重要  
  8.   alarm             //重要  
  9.   android.security.keystore  
  10.   android.service.gatekeeper.IGateKeeperService  
  11.   appops  
  12.   appwidget  
  13.   assetatlas  
  14.   audio           //重要  
  15.   backup     
  16.   battery         //重要  
  17.   batteryproperties  
  18.   batterystats  
  19.   bluetooth_manager  
  20.   carrier_config  
  21.   clipboard  
  22.   cneservice  
  23.   com.qualcomm.location.izat.IzatService  
  24.   com.qualcomm.qti.qseeproxy  
  25.   commontime_management  
  26.   connectivity  
  27.   connectivity_metrics_logger  
  28.   connmetrics  
  29.   consumer_ir  
  30.   content  
  31.   contexthub_service  
  32.   country_detector  
  33.   cpuinfo         
  34.   dbinfo  
  35.   device_policy  
  36.   deviceidle  
  37.   devicestoragemonitor  
  38.   diskstats  
  39.   display       //重要  
  40.   display.qservice  
  41.   dpmservice  
  42.   dreams  
  43.   drm.drmManager  
  44.   dropbox  
  45.   eSEPowerManagerService  
  46.   ethernet  
  47.   extphone  
  48.   gfxinfo  
  49.   gpu         //重要  
  50.   graphicsstats  
  51.   hardware_properties  
  52.   imms  
  53.   ims  
  54.   input       //重要  
  55.   input_method  //重要  
  56.   iphonesubinfo  
  57.   isms  
  58.   isub  
  59.   jobscheduler  
  60.   launcherapps  
  61.   location  
  62.   lock_settings  
  63.   mdtp  
  64.   media.audio_flinger  
  65.   media.audio_policy  
  66.   media.camera  
  67.   media.camera.proxy  
  68.   media.codec  
  69.   media.drm  
  70.   media.extractor  
  71.   media.player  
  72.   media.radio  
  73.   media.resource_manager  
  74.   media.sound_trigger_hw  
  75.   media_projection  
  76.   media_router  
  77.   media_session  
  78.   meminfo       //输出内存相关,重要  
  79.   midi  
  80.   mount          
  81.   netd  
  82.   netd_listener  
  83.   netpolicy  
  84.   netstats  
  85.   network_management  
  86.   network_score  
  87.   network_time_update_service  
  88.   notification  
  89.   okay_property  
  90.   otadexopt  
  91.   package          //重要  
  92.   permission  
  93.   persistent_data_block  
  94.   phone  
  95.   pinner  
  96.   power           //电源管理,重要  
  97.   print  
  98.   processinfo  
  99.   procstats  
  100.   qti.ims.connectionmanagerservice  
  101.   qti.ims.ext  
  102.   qtitetherservice  
  103.   recovery  
  104.   regionalization  
  105.   restrictions  
  106.   rttmanager  
  107.   samplingprofiler  
  108.   scheduling_policy  
  109.   search  
  110.   sensorservice  
  111.   serial  
  112.   servicediscovery  
  113.   shortcut  
  114.   simphonebook  
  115.   soundtrigger  
  116.   statusbar  
  117.   telecom  
  118.   telephony.registry  
  119.   textservices  
  120.   trust  
  121.   uimode  
  122.   updatelock  
  123.   usagestats  
  124.   usb  
  125.   user  
  126.   vendor.qcom.PeripheralManager  
  127.   vibrator  
  128.   voiceinteraction  
  129.   vrmanager  
  130.   wallpaper     //重要  
  131.   webviewupdate  
  132.   wifi  
  133.   wifip2p  
  134.   wifiscanner  
  135.   window         //Windows管理信息,重要  

wakelock

       wakelock主要是系统为上层提供控制屏幕亮度显示,以及cpu唤醒的一个接口。我们可以通过上面学习的dumpsys命令来查看系统此时存在那些wakelock。

adb shell dumpsys power

[java] view plain copy
  1. Wake Locks: size=1  
  2.   SCREEN_BRIGHT_WAKE_LOCK        'WindowManager' ON_AFTER_RELEASE ACQ=-1s234ms (uid=1000 pid=1495 ws=WorkSource{1000})  

       此时系统只有一个wakelock,类型为SCREEN_BRIGHT_WAKE_LOCK,所属模块为WIndowManager。下面讲解一下如何使用wakelock。

[java] view plain copy
  1. PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); //获取PowerManager  
  2. sWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK   //使用power创建一个新的wakelock,执行类型  
  3.         | PowerManager.ACQUIRE_CAUSES_WAKEUP  
  4.         | PowerManager.ON_AFTER_RELEASE, TAG);  
  5. sWakeLock.acquire();                                    //使wakelock起作用,当不需要时使用release释放wakelock  

   任何应用程序使用WakeLock,必须要求android.permission.WAKE_LOCK许可在应用程序的清单上使用<uses-permission>元素。下面为我们可以调用的公共方法。

[java] view plain copy
  1. Public Methods  
  2. void acquire() --->当你创建这个WakeLock时,确保这个设备按照你的要求保持唤醒的状态。  
  3. void acquire(long timeout) --->当你创建这个WakeLock时,确保这个设备按照你的要求保持唤醒的状态。  
  4. void isHeld()  
  5. void release() ---> 按照你的要求释放cpu或屏幕。  
  6. void setReferenceCounted(boolean value)--->如果需要使用引用计数,则将value设置为true。默认设置为                                                               true,表示当用户申请多少次锁时,就必须释放多少次。  
  7. void setWorkSource(WorkSource ws)  
  8. String toString() --->返回一个简洁的字符串用来将这个对象描述为人们可读懂的。  
  9. void Finalize() --->当垃圾收集器检测到该实例不再运行调用。  

wakelock有不同的类型,我们可以根据需要选择不同的wakelock类型。

Flag Value CPU Screen Keyboard
PARTIAL_WAKE_LOCK On Off   Off
SCREEN_DIM_WAKE_LOCK On  Dim Off
SCREEN_BRIGHT_WAKE_LOCK On Bright Off
FULL_WAKE_LOCK On Bright Bright
      如果你持有的partial wakelock,CPU将继续运行,不论何时,即使当用户按下电源按钮。对于所有其他wakelocks,但用户使用电源按钮时,系统将进入睡眠,cpu将不再继续运行。
PARTIAL_WAKE_LOCK:保持CPU 运转,屏幕和键盘灯有可能是关闭的。
SCREEN_DIM_WAKE_LOCK:保持CPU 运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯
SCREEN_BRIGHT_WAKE_LOCK:保持CPU 运转,允许保持屏幕高亮显示,允许关闭键盘灯
FULL_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度
ACQUIRE_CAUSES_WAKEUP:正常唤醒锁实际上并不打开照明。相反,一旦打开他们会一直仍然保持(例如来世user的activity)。当获得wakelock,这个标志会使屏幕或/和键盘立即打开。一个典型的使用就是可以立即看到那些对用户重要的通知。
ON_AFTER_RELEASE:设置了这个标志,当wakelock释放时用户activity计时器会被重置,导致照明持续一段时间。如果你在wacklock条件中循环,这个可以用来减少闪烁

  我们可以创建多个锁,并hold它,即使对同一类型,也如此,对于某类型的wakelock只要有一个被hold,那么它所对应的电源状态(illumination),就将不会超时,将被延续(hold).在上表中我们把越往下的,称为更高一级的wakelocks.当高级和低级wakelocks相遇的时候,高级起作用。在上面的flag上还再加上如下的2个flag,但是他们和PARTIAL_WAKE_LOCK.组合没任何意义ACQUIRE_CAUSES_WAKEUP默认情况下wake locks并不是马上开启CPU或Screen或Keyboard的(对于Screen是Dim或Bright,Keyboard是Bright. wake locks只是在被开启后(比如用户的活动),让设备延续(保存)你设定开启的状态. 但是如果加上ACQUIRE_CAUSES_WAKEUP就可以让Screen或Keyboar没开启的情况,马上开启它们。 典型的应用就是在收到一个重要的notifications时,需要马上点亮屏幕。

addr2line

在分析framework稳定性问题时会遇到Native crash的发生,而Native crash与java crash的堆栈信息不同。下面是一段Native 堆栈的片段。
[java] view plain copy
  1. 03-19 14:58:50.034   319  3145 D kevin_Render: #01 pc 0005f8a5  /system/lib/libmediaplayerservice.so (android::NuPlayer::Renderer::setAnchorTime(long longlong longlong long, bool)+72)  
  2. 03-19 14:58:50.034   319  3145 D kevin_Render: #02 pc 000618c5  /system/lib/libmediaplayerservice.so (android::NuPlayer::Renderer::onNewAudioMediaTime(long long)+88)  
  3. 03-19 14:58:50.035   319  3145 D kevin_Render: #03 pc 00062249  /system/lib/libmediaplayerservice.so (android::NuPlayer::Renderer::onDrainAudioQueue()+764)  
  4. 03-19 14:58:50.035   319  3145 D kevin_Render: #04 pc 00062ec3  /system/lib/libmediaplayerservice.so (android::NuPlayer::Renderer::onMessageReceived(android::sp<android::AMessage> const&)+866)  
  5. 03-19 14:58:50.035   319  3145 D kevin_Render: #05 pc 0000d12d  /system/lib/libstagefright_foundation.so (android::ALooperRoster::deliverMessage(android::sp<android::AMessage> const&)+164)  
  6. 03-19 14:58:50.035   319  3145 D kevin_Render: #06 pc 0000cac1  /system/lib/libstagefright_foundation.so (android::ALooper::loop()+216)  
  7. 03-19 14:58:50.035   319  3145 D kevin_Render: #07 pc 00010977  /system/lib/libutils.so (android::Thread::_threadLoop(void*)+110)  
  8. 03-19 14:58:50.035   319  3145 D kevin_Render: #08 pc 00016f5b  /system/lib/libc.so (__pthread_start(void*)+30)  
  9. 03-19 14:58:50.035   319  3145 D kevin_Render: #09 pc 00014f7b  /system/lib/libc.so (__start_thread+6)  
根据上面的堆栈,我们并不能看到具体哪个函数,哪行代码出现了问题,这个时候我们就需要解析Native函数的地址值,如上面 00062ec3这样的符号,我们需要通过addr2line来进行解析。我们可以使用linux系统提供的addr2line命令,也可以使用源代码sdk中的工具。具体命令如下:
addr2line -e out/target/product/项目名/symbols/system/lib/libxxx.so -f -C <addr> 
如果我们想要解析03行的地址值00062249
[java] view plain copy
  1. kevin@kevin-All-Series:~/work/$ addr2line -e out/target/product/miki8163_9003/symbols/system/lib/libmediaplayerservice.so -f -C 00062249  
  2. android::NuPlayer::Renderer::onDrainAudioQueue()  
  3. /home/kevin/work/source/sm8163/sm8163/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp:868  
解析后我们看到该行代码属于函数android::NuPlayer::Renderer::onDrainAudioQueue(),在NuPlayerRenderer.cpp的868行,这样就十分方便了。

meminfo

当我们查询系统的内存信息除了使用dumpsys命令,还可以直接使用adb shell cat /proc/meminfo
[java] view plain copy
  1. kevin@kevin-All-Series:~/work$ adb shell cat /proc/meminfo  
  2. MemTotal:        1844152 kB       //内存的总大小  
  3. MemFree:           41364 kB       //空闲内存  
  4. MemAvailable:     230892 kB       //可用的内存  
  5. Buffers:            3520 kB         
  6. Cached:           230312 kB       //缓存  
  7. SwapCached:         6484 kB  
  8. Active:           538568 kB  
  9. Inactive:         257680 kB  
  10. Active(anon):     426264 kB  
  11. Inactive(anon):   144884 kB  
  12. Active(file):     112304 kB  
  13. Inactive(file):   112796 kB  
  14. Unevictable:         256 kB  
  15. Mlocked:             256 kB  
  16. SwapTotal:        524284 kB  
  17. SwapFree:            156 kB  
  18. Dirty:                44 kB      //脏页  
  19. Writeback:             0 kB  
  20. AnonPages:        559864 kB  
  21. Mapped:           216980 kB  
  22. Shmem:              8608 kB  
  23. Slab:             354744 kB  
  24. SReclaimable:      56820 kB  
  25. SUnreclaim:       297924 kB  
  26. KernelStack:       35488 kB  
  27. PageTables:        34172 kB  
  28. NFS_Unstable:          0 kB  
  29. Bounce:                0 kB  
  30. WritebackTmp:          0 kB  
  31. CommitLimit:     1446360 kB  
  32. Committed_AS:   63267272 kB  
  33. VmallocTotal:   244318144 kB  
  34. VmallocUsed:      116780 kB  
  35. VmallocChunk:   244056036 kB  

fastboot

      Android系统编译后会生成很多的image文件,我们可以通过刷机工具将image烧制到手机中,我们也可以使用fastboot命令很方便的将image文件烧制到系统中。下面为fastboot的使用方法:

1.开机状态下执行

adb reboot bootloader(执行命令后系统会关机重启,进入fastboot模式)

2.烧写system.img

fastboot flash system system.img

如果要烧制boot.img,那么就执行fastboot flash boot boot.img,其他image也一样。

3.重启

fastboot reboot

简单几步就可以快速将我们编译出来的文件烧制到手机中。

bootchart

      bootchart是一个用于linux启动过程性能分析的开源软件工具,在系统启动过程自动收集CPU占用率、进程等信息,并以图形方式显示分析结果,可用作指导优化系统启动过程。bootchart详细使用说明请参考《Android7.0 bootchart工具使用说明

LOG分析

      在调试Android系统时如果要实时的查看输出的log信息就可以使用adb logcat -vthreadtime或者adb logcat在终端输出需要的log信息,在5.1及其之前的版本需要adb logcat后需要加上-vthreadtime 意思是将输出时间以及进程线程信息,5.1之后的版本系统自动添加了时间与进程线程信息,直接用adb logcat就可以。

    而更多的时候我们需要分析log文件,也就是在系统运行时会将log信息输出在log文件中,以便在出现问题时让开发人员进行分析,下面讲几个场景的关键LOG信息。

开机LOG

     在分析开机log时通过根据开机流程进行分段分析,这里省略bootloader中log,首先从执行kernel完成分析,到启动launcher分析结束,来看其中执行了那些过程,如果开机流程出现问题,就可以定位哪个流程出现问题。

[plain] view plain copy
  1. //开始启动init进程,也就是kernel启动完成,取时间戳2.172934s,为启动kernel所耗时.  
  2. [01-01 08:30:04.349] <13>[    2.172934] c5 init: init started!  
  3.   
  4. //开始启动zygote,使用时间戳相减4.281027-2.172934计算出启动init进程到启动zygote耗时2.1s.  
  5. [01-01 08:30:04.367] <13>[    4.281027] c0 init: Starting service 'zygote'...  
  6.   
  7. //进入zygote,由于kernel时间与android不能相减,所以无法计算启动zygote到进入zygote所花费时间.  
  8. A001-01 08:30:05.036  2810  2810 D AndroidRuntime: >>>>>> START com.android.internal.os.ZygoteInit uid 0 <<<<<<  
  9.   
  10. //进入SystemServer,使用android时间08:30:08.629-08:30:05.036 获得,从进入zygote到SystemServer耗时  
  11. A101-01 08:30:08.629  3285  3285 I SystemServer: Entered the Android system server!  
  12.   
  13. //开始初始化Package, 使用android时间相减,获取进入SystemServer到初始化Package的耗时.  
  14. A101-01 08:30:09.021  3285  3285 I SystemServer: Package Manager  
  15. //扫描解析应用耗时,可以直接获取1.544 seconds  
  16. A101-01 08:30:10.813  3285  3285 I PackageManager: Time to scan packages: 1.544 seconds  
  17.   
  18. //开始执行network systemReady函数,使用android时间相减,获取初始化Package完成到开始执行network systemReady函数的耗时.  
  19. A101-01 08:30:14.285  3285  3285 D NetworkManagement: enabling bandwidth control  
  20.   
  21. //network执行完相关命令,使用android时间相减,获取执行network执行相关命令耗时.  
  22. A101-01 08:30:15.475  3285  3285 I SystemServiceManager: Starting phase 600  
  23.   
  24. //启动launcher, 使用android时间相减,获取执行network命令完成,到启动launcher耗时  
  25. A101-01 08:30:15.915  3285  3285 I ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.android.launcher3/.Launcher} from uid 0 on display 0  

关机LOG

      在分析关机log时,是从长按power键,点击确认关机,到灭屏震动关机。关机主要经过的流程为发送关机广播,关闭AMS,PMS,关闭移动数据,卸载sd卡等流程,最后调用power往底层系统配置中写入对应的信息,底层读取信息,进行关机。

[plain] view plain copy
  1. //按确认键,开始关机  
  2. 01-01 12:49:10.410  1147  1226 I ShutdownThread: shutdown goto shutdownInner  
  3.   
  4. //发送关机广播,使用android时间相减,获得关机到发送关机广播之间耗时  
  5. 01-01 12:49:10.498  1147  2504 I ShutdownThread: Sending shutdown broadcast...  
  6.   
  7. //开始shutdown activity manager, 使用android时间相减,获得关机广播处理耗时  
  8. 01-01 12:49:10.637  1147  2504 I ShutdownThread: Shutting down activity manager...  
  9.   
  10.  //开始关闭蜂窝网,使用android时间相减,获得开机shutdown activity manager到关闭蜂窝网耗时  
  11. 01-01 12:49:10.746  1147  2522 W ShutdownThread: Turning off cellular radios...       
  12.   
  13.  //开始关闭Radio,获得关闭蜂窝网到开始关闭Radio耗时  
  14. 01-01 12:49:10.753  1147  2522 I ShutdownThread: Waiting for NFC, Bluetooth and Radio...  
  15.   
  16. //关闭Radio完成,使用android时间相减,获得关闭Radio耗时,该流程可能耗时较长.重点  
  17. 01-01 12:49:11.255  1147  2522 I ShutdownThread: NFC, Radio and Bluetooth shutdown complete.  
  18.   
  19. //开始关闭MountService,使用android时间相减,获得关闭Radio完成到关闭MountService耗时.  
  20. 01-01 12:49:11.257  1147  2504 I ShutdownThread: Shutting down MountService  
  21.   
  22. //关闭MountService完成,使用android时间相减,获得关闭MountService耗时.该流程可能耗时较长.重点  
  23. 01-01 12:49:11.268  1147  1304 W ShutdownThread: Result code 0 from MountService.shutdown  
  24.   
  25. //调用底层接口,关机完成.  
  26. 01-01 12:49:11.776  1147  2504 I ShutdownThread: Performing low-level shutdown...  

首启动应用LOG

      在分析分析应用启动问题时,我们通常分析event log信息,使用命令adb logcat -b events,其中的log信息主要为应用的生命周期信息。通过查看生命周期信息来分析,应用是否行为异常。

首次启动

[plain] view plain copy
  1. //开始启动activity  
  2. 07-29 10:26:57.033  1173  1995 I am_create_activity: [0,102422011,29,com.android.dialer/.DialtactsActivity,android.intent.action.MAIN,NULL,NULL,270532608]  
  3.   
  4. //launcher pause完成。  
  5. 07-29 10:26:57.109  2009  2009 I am_on_paused_called: [0,com.android.launcher3.Launcher]  
  6.   
  7. //进程开始创建,与开始启动activity时间相减,获得准备工作耗时.           
  8. 07-29 10:26:57.142  1173  1996 I am_proc_start: [0,5164,10038,com.android.dialer,activity,com.android.dialer/.DialtactsActivity]  
  9.   
  10. //进程bound完成,与进程创建之间这个过程可以理解为进程创建的时间。为创建进程耗时.  
  11. 07-29 10:26:57.195  1173  1404 I am_proc_bound: [0,5164,com.android.dialer]  
  12.   
  13. //ams向应用发消息进行启动activity操作  
  14. 07-29 10:26:57.199  1173  1404 I am_restart_activity: [0,102422011,29,com.android.dialer/.DialtactsActivity]  
  15.   
  16. //activity resume执行完成,与restart_activity之间这个可以理解为Activity的生命周期执行时间。为生命周期耗时  
  17. 07-29 10:26:57.394  5164  5164 I am_on_resume_called: [0,com.android.dialer.DialtactsActivity]  
  18.   
  19. //这里activity显示完成,当前Activity显示过程644ms,整个显示过程644ms。  
  20. //从activity resume完成到这个log之间可以理解为广义上的绘制过程(measure,layout,draw,render)。  
  21. 07-29 10:26:57.757  1173  1356 I am_activity_launch_time: [0,102422011,com.android.dialer/.DialtactsActivity,644,644]  

非首次启动

[plain] view plain copy
  1. //开始启动activity,到launcher pause完成。  
  2. 01-01 13:26:59.645  1162  1733 I am_create_activity: [0,233918075,10,com.android.messaging/.ui.conversationlist.ConversationListActivity,android.intent.action.MAIN,NULL,NULL,270532608]  
  3.   
  4. //launcher pause完成。  
  5.  07-29 10:26:57.109  2009  2009 I am_on_paused_called: [0,com.android.launcher3.Launcher]  
  6.   
  7. //ams向应用发消息进行启动activity操作,准备工作  
  8. 01-01 13:26:59.710  1162  1439 I am_restart_activity: [0,233918075,10,com.android.messaging/.ui.conversationlist.ConversationListActivity]  
  9.   
  10.  //activity resume执行完成,与restart_activity之间这个可以理解为Activity的生命周期执行时间。  
  11. 01-01 13:26:59.782  2189  2189 I am_on_resume_called: [0,com.android.messaging.ui.conversationlist.ConversationListActivity]  
  12.   
  13. //这里activity显示完成,当前Activity显示过程168ms,整个显示过程168ms。  
  14. //从activity resume完成到这个log之间可以理解为广义上的绘制过程(measure,layout,draw,render)。  
  15. 01-01 13:26:59.871  1162  1283 I am_activity_launch_time: [0,233918075,com.android.messaging/.ui.conversationlist.ConversationListActivity,168,168]  

亮屏关键LOG

[plain] view plain copy
  1. //kernel中断key事件,ScanCode:116为Power键,value:1为down事件  
  2. <6>[41051.961488] c1 [SPRD_KEY_INFO]Key:Power Key ScanCode:116 value:1  
  3.   
  4. //InputReader获取power键事件,code=116为power键  
  5. 01-02 08:04:44.016   600   643 D InputReader: processEventsLocked: type=1 Count=2 code=116 value=1 deviceId=2  
  6.   
  7. //Power收到亮屏调用,开始亮屏  
  8. 01-02 08:04:44.037   600   643 I PowerManagerService: Waking up from sleep (uid 1000)...  
  9.   
  10. //开始block亮屏,直到keyguard与windows绘制完成  
  11. 01-02 08:04:44.052   600   622 I DisplayPowerController: Blocking screen on until initial contents have been drawn.  
  12.   
  13. //开始绘制keyguard  
  14. 01-02 08:04:44.052   600   622 I WindowManager: Screen turning on...  
  15.   
  16. //tosuspend_disable()耗时283s,有时为setPowerMode耗时长  
  17. 01-02 08:04:44.347   600   676 D PowerManagerService-JNI: Excessive delay in autosuspend_disable() while   
  18.   
  19. //yguard绘制完成  
  20. 01-02 08:04:44.504   600   700 D WindowManager: mKeyguardDelegate.ShowListener.onDrawn.  
  21. 01-02 08:04:44.504   600   614 W WindowManager: Setting mKeyguardDrawComplete  
  22.   
  23. //windows绘制完成  
  24. 01-02 08:04:44.551   600   620 I WindowManager: All windows ready for display!  
  25. 01-02 08:04:44.551   600   614 W WindowManager: Setting mWindowManagerDrawComplete  
  26.   
  27. //block亮屏,总共blocked亮屏505ms  
  28. 01-02 08:04:44.557   600   622 I DisplayPowerController: Unblocked screen on after 505 ms  
  29.   
  30. //屏幕亮度,往节点中写亮度值  
  31. 01-02 08:04:44.558   600   676 D LIGHTS  : file:vendor/sprd/modules/lights/lights.c, func:set_light_backlight, brightness=25  
  32. 01-02 08:04:44.559   600   676 E LIGHTS  : file:vendor/sprd/modules/lights/lights.c, func:write_int, path=/sys/class/backlight/sprd_backlight/brightness, value=25  

来电亮屏LOG

[plain] view plain copy
  1. //创建dialer进程  
  2. 12-22 15:46:23.704   595   595 I ActivityManager: Start proc 5067:com.android.dialer/u0a1 for service com.android.dialer/com.android.incallui.InCallServiceImpl  
  3.   
  4. //来电响铃  
  5. 12-22 15:46:23.736   595  5083 I Telecom : AsyncRingtonePlayer: Play ringtone.  
  6.   
  7. //启动InCallActivity   
  8. 12-22 15:46:24.410   595  1016 I ActivityManager: START u0 {act=android.intent.action.MAIN flg=0x10040000 cmp=com.android.dialer/com.android.incallui.InCallActivity (has extras)} from uid 10001 on display 0  
  9.   
  10. //显示InCallActivity  
  11. 12-22 15:46:25.715   595   615 I am_activity_launch_time: [0,134650581,com.android.dialer/com.android.incallui.InCallActivity,1293,1299]  
  12.   
  13. //power收到亮屏调用  
  14. 12-22 15:46:25.730   595   615 I PowerManagerService: Waking up from sleep due toandroid android.server.wm:TURN_ON (uid 1000)...  
  15.   
  16. //点亮屏幕  
  17. A012-22 15:46:26.220   595   679 D LIGHTS  : file:vendor/sprd/modules/lights/lights.c, func:set_light_backlight, brightness=25  
  18. A012-22 15:46:26.221   595   679 E LIGHTS  : file:vendor/sprd/modules/lights/lights.c, func:write_int, path=/sys/class/backlight/sprd_backlight/brightness, value=25  

灭屏LOG

[plain] view plain copy
  1. //kernel中断key事件,ScanCode:116为Power键,value:1为down事件  
  2. <6>[42586.507314] c1 [SPRD_KEY_INFO]Key:Power Key ScanCode:116 value:1  
  3.   
  4. //value:0为up事件  
  5. <6>[42586.660288] c1 [SPRD_KEY_INFO]Key:Power Key ScanCode:116 value:0  
  6.   
  7. //Input收到power键down事件  
  8. 01-06 13:25:48.460  3339  3447 D InputReader: processEventsLocked: type=1 Count=2 code=116 value=1 deviceId=2  
  9.   
  10. //Input收到power键up事件  
  11. 01-06 13:25:48.643  3339  3447 D InputReader: processEventsLocked: type=1 Count=2 code=116 value=0 deviceId=2  
  12.   
  13. //短按power键,power开始灭屏  
  14. 01-06 13:25:48.643  3339  3447 I PowerManagerService: Going to sleep due to power button (uid 1000)...  
  15.   
  16. //设置全局变量,通知keyguard灭屏了  
  17. 01-06 13:25:48.645  3339  3361 I WindowManager: Screen turned off...  
  18.   
  19. //设置屏幕亮度为0  
  20. 01-06 13:25:48.645  3339  3493 D LIGHTS  : file:vendor/sprd/modules/lights/lights.c, func:set_light_backlight, brightness=0  
  21. 01-06 13:25:48.645  3339  3493 E LIGHTS  : file:vendor/sprd/modules/lights/lights.c, func:write_int, path=/sys/class/backlight/sprd_backlight/brightness, value=0  

添加LOG信息

java层添加

    当在调试系统代码时,如果要确认代码是否走了某个流程,就可以添加log信息,如果执行某项操作可以将该行log打印出来就说明走了该流程。
[java] view plain copy
  1. import android.util.Log;    //导入LOG包  
  2.   
  3.     private static String getActiveSubscriberId(Context context, int subId) {  
  4.         final TelephonyManager tele = TelephonyManager.from(context);  
  5.         String retVal = tele.getSubscriberId(subId);  
  6.         Log.d(TAG, "getActiveSubscriberId=" + retVal + " subId=" + subId); //添加log信息  
  7.         return retVal;  
  8.     }  

如果想知道某行代码是怎么调用过来的,他的调用关系是什么,就可以通过打印堆栈的方式来确认。具体方式如下;

[java] view plain copy
  1. try {  
  2.     throw new Exception("Call Stack Trace");  
  3. catch (Exception e) {  
  4.     Log.i("kevin""xxx", e);  
  5. }  

例如在唤醒屏幕流程,如果想要分析wakeUpInternal是怎么调用过来的,就可以打印堆栈的方式来确认调用关系。

[java] view plain copy
  1. private void wakeUpInternal(long eventTime, String reason, int uid, String opPackageName,  
  2.         int opUid) {  
  3.     synchronized (mLock) {  
  4.   
  5.         try {  
  6.             throw new Exception("Call Stack Trace");  
  7.         } catch (Exception e) {  
  8.             Log.i("kevin""xxx", e);  
  9.         }  
  10.   
  11.         if (wakeUpNoUpdateLocked(eventTime, reason, uid, opPackageName, opUid)) {  
  12.             updatePowerStateLocked();  
  13.         }  
  14.     }  
  15. }  

当我们修改好代码后编译services.jar,将services.jar push到手机中,重启,按power键亮灭屏就可以看到如下信息。

Android Framework常用工具及LOG调试方法

C++层添加

如果想要在C++层添加log信息,需要在对应的Android.mk文件中添加下面代码,添加共享库。

[cpp] view plain copy
  1. LOCAL_SHARED_LIBRARIES := libutils  

用如下log可以打印C++层的信息。

[cpp] view plain copy
  1. ALOGD("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);   

如果要在C++层中打印对应堆栈,使用如下代码:

[cpp] view plain copy
  1. #include <utils/CallStack.h>  
  2.   
  3. CallStack stack;  
  4. stack.update();  
  5. stack.log("kevin");  

示例代码如下:

[cpp] view plain copy
  1. void NuPlayer::start() {  
  2.     CallStack stack;  
  3.     stack.update();  
  4.     stack.log("kevin");  
  5.     (new AMessage(kWhatStart, this))->post();  
  6. }  

输出堆栈如下:

Android Framework常用工具及LOG调试方法

可以使用前面学习的addr2line

Android Framework常用工具及LOG调试方法

可以看到具体的代码调用。
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.****.net/fu_kevin0606/article/details/79616216

概述  

    Framework开发是一项非常繁琐复杂的工作,需要阅读大量的源代码,分析及其多的LOG信息来定位错误位置。这个时候如果使用一些工具或者知道如何定位重要LOG信息,就可以使一些复杂的工作变的简单很多,使我们分析问题的效率变得更快,不再为阅读大量的源代码而感到一筹莫展。本文将针对一些场景讲解如何分析系统LOG信息,如何添加LOG定位错误信息,以及常用工具以及使用方法。

常用工具

HierarchyViewer

      HierarchyViewer是随Android SDK发布的工具,位置在sdktools文件夹下,名为hierarchyviewer。它是Android自带的非常有用而且使用简单的工具,能够让我们从可视化的角度直观地获得UI布局设计结构和各种属性的信息,帮助我们优化布局设计。打开HierarchyViewer后我们可以看到当前view的布局,如下图所示。

Android Framework常用工具及LOG调试方法

DDMS

       DDMS 的全称是Dalvik Debug Monitor Service,是 Android 开发环境中的Dalvik虚拟机调试监控服务。它为我们提供例如:为测试设备截屏,针对特定的进程查看正在运行的线程以及堆信息、Logcat、广播状态信息、模拟电话呼叫、接收SMS、虚拟地理坐标等等。DDMS打开界面如下:

Android Framework常用工具及LOG调试方法

左侧的Devices一栏会列出已连接的设备,点击设备名称左侧三角符号图标会列出该设备运行中的进程的app包名。

Android Framework常用工具及LOG调试方法

模拟按键

使用命令adb shell input keyevent + 对应的键值,可以模拟对应的操作。手机系统中主要的键值如下:

[java] view plain copy
  1. /** Key code constant: Home key. 
  2.  * This key is handled by the framework and is never delivered to applications. */  
  3. public static final int KEYCODE_HOME            = 3;    //Home键  
  4. /** Key code constant: Back key. */  
  5. public static final int KEYCODE_BACK            = 4;    //Back键  
  6. /** Key code constant: Call key. */  
  7. public static final int KEYCODE_CALL            = 5;    //打电话  
  8. /** Key code constant: End Call key. */  
  9. public static final int KEYCODE_ENDCALL         = 6;    //挂断电话  
  10. /** Key code constant: Volume Up key. 
  11.  * Adjusts the speaker volume up. */  
  12. public static final int KEYCODE_VOLUME_UP       = 24;   //调大声音  
  13. /** Key code constant: Volume Down key. 
  14.  * Adjusts the speaker volume down. */  
  15. public static final int KEYCODE_VOLUME_DOWN     = 25;   //调小声音  
  16. /** Key code constant: Power key. */  
  17. public static final int KEYCODE_POWER           = 26;   //电源键  
  18. /** Key code constant: Camera key. 
  19.  * Used to launch a camera application or take pictures. */  
  20. public static final int KEYCODE_CAMERA          = 27;     //相机按键  
  21. /** Key code constant: Clear key. */  
  22. public static final int KEYCODE_CLEAR           = 28;     //清理  
  23. /** Key code constant: Space key. */  
  24. public static final int KEYCODE_SPACE           = 62;     //空格键  
  25. /** Key code constant: Backspace key. 
  26.  * Deletes characters before the insertion point, unlike {@link #KEYCODE_FORWARD_DEL}. */  
  27. public static final int KEYCODE_DEL             = 67;     //删除键  
  28. /** Key code constant: Menu key. */  
  29. public static final int KEYCODE_MENU            = 82;      //菜单键  

当我们要模拟power键亮灭屏事件就可以执行下面命令:

[java] view plain copy
  1. adb shell input keyevent 26  

模拟别的按键事件同理。

而adb shell getevent / adb shell sendevent是发送对应的事件,包括触屏,按键等事件。

am命令

      有时候我们在调试系统时可以在终端使用am命令来发送广播,打开Activity,启动Service等操作,十分方便。am的详细操作如下,我们可以通过adb shell am + 对应命令,就可操作。

[java] view plain copy
  1. usage: am [subcommand] [options]  
  2. usage: am start [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>]  
  3.                [--sampling INTERVAL] [-R COUNT] [-S]  
  4.                [--track-allocation] [--user <USER_ID> | current] <INTENT> //可以通过该命令启动对应Activity  
  5.        am startservice [--user <USER_ID> | current] <INTENT>   //启动服务  
  6.        am stopservice [--user <USER_ID> | current] <INTENT>    //停止服务  
  7.        am force-stop [--user <USER_ID> | all | current] <PACKAGE>  //通过包名强制停止应用  
  8.        am kill [--user <USER_ID> | all | current] <PACKAGE>  //根据进程号杀死进程  
  9.        am kill-all                                           //杀掉所有后台进程  
  10.        am broadcast [--user <USER_ID> | all | current] <INTENT>  //发送广播  
  11.        am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]  
  12.                [--user <USER_ID> | current]  
  13.                [--no-window-animation] [--abi <ABI>] <COMPONENT>  
  14.        am profile start [--user <USER_ID> current] [--sampling INTERVAL] <PROCESS> <FILE> //抓取traceview  
  15.        am profile stop [--user <USER_ID> current] [<PROCESS>]      //停止抓取traceview  
  16.        am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>  
  17.        am set-debug-app [-w] [--persistent] <PACKAGE>  
  18.        am clear-debug-app  
  19.        am set-watch-heap <PROCESS> <MEM-LIMIT>  
  20.        am clear-watch-heap  
  21.        am bug-report [--progress]  
  22.        am monitor [--gdb <port>]  
  23.        am hang [--allow-restart]  
  24.        am restart                             //重启应用  
  25.        am idle-maintenance  
  26.        am screen-compat [on|off] <PACKAGE>  
  27.        am package-importance <PACKAGE>  
  28.        am to-uri [INTENT]  
  29.        am to-intent-uri [INTENT]  
  30.        am to-app-uri [INTENT]  
  31.        am switch-user <USER_ID>  
  32.        am start-user <USER_ID>  
  33.        am unlock-user <USER_ID> [TOKEN_HEX]  
  34.        am stop-user [-w] [-f] <USER_ID>  
  35.        am stack start <DISPLAY_ID> <INTENT>           
  36.        am stack movetask <TASK_ID> <STACK_ID> [true|false]  //stack相关  
  37.        am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>  
  38.        am stack resize-animated <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>  
  39.        am stack resize-docked-stack <LEFT,TOP,RIGHT,BOTTOM> [<TASK_LEFT,TASK_TOP,TASK_RIGHT,TASK_BOTTOM>]  
  40.        am stack size-docked-stack-test: <STEP_SIZE> <l|t|r|b> [DELAY_MS]  
  41.        am stack move-top-activity-to-pinned-stack: <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>  
  42.        am stack positiontask <TASK_ID> <STACK_ID> <POSITION>  
  43.        am stack list                                    //列出系统中的所有stack     
  44.        am stack info <STACK_ID>                         //stack信息  
  45.        am stack remove <STACK_ID>                       //移除stack  
  46.        am task lock <TASK_ID>  
  47.        am task lock stop                           
  48.        am task resizeable <TASK_ID> [0 (unresizeable) | 1 (crop_windows) | 2 (resizeable) | 3 (resizeable_and_pipable)]  
  49.        am task resize <TASK_ID> <LEFT,TOP,RIGHT,BOTTOM>  
  50.        am task drag-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS]   
  51.        am task size-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS]   
  52.        am get-config  
  53.        am suppress-resize-config-changes <true|false>  
  54.        am set-inactive [--user <USER_ID>] <PACKAGE> true|false  
  55.        am get-inactive [--user <USER_ID>] <PACKAGE>  
  56.        am send-trim-memory [--user <USER_ID>] <PROCESS>  
  57.                [HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|RUNNING_CRITICAL|COMPLETE]  
  58.        am get-current-user  
  59.   
  60. am start: start an Activity.  Options are:    //启动Activity详细使用方法  
  61.     -D: enable debugging  
  62.     -N: enable native debugging  
  63.     -W: wait for launch to complete  
  64.     --start-profiler <FILE>: start profiler and send results to <FILE>  
  65.     --sampling INTERVAL: use sample profiling with INTERVAL microseconds  
  66.         between samples (use with --start-profiler)  
  67.     -P <FILE>: like above, but profiling stops when app goes idle  
  68.     -R: repeat the activity launch <COUNT> times.  Prior to each repeat,  
  69.         the top activity will be finished.  
  70.     -S: force stop the target app before starting the activity  
  71.     --track-allocation: enable tracking of object allocations  
  72.     --user <USER_ID> | current: Specify which user to run as; if not  
  73.         specified then run as the current user.  
  74.     --stack <STACK_ID>: Specify into which stack should the activity be put.  
  75. am startservice: start a Service.  Options are:  
  76.     --user <USER_ID> | current: Specify which user to run as; if not  
  77.         specified then run as the current user.  
  78.   
  79. am stopservice: stop a Service.  Options are:  
  80.     --user <USER_ID> | current: Specify which user to run as; if not  
  81.         specified then run as the current user.  
  82.   
  83. am force-stop: force stop everything associated with <PACKAGE>.  
  84.     --user <USER_ID> | all | current: Specify user to force stop;  
  85.         all users if not specified.  
  86.   
  87. am kill: Kill all processes associated with <PACKAGE>.  Only kills.  
  88.   processes that are safe to kill -- that is, will not impact the user  
  89.   experience.  
  90.     --user <USER_ID> | all | current: Specify user whose processes to kill;  
  91.         all users if not specified.  
  92.   
  93. am kill-all: Kill all background processes.  
  94.   
  95. am broadcast: send a broadcast Intent.  Options are:  
  96.     --user <USER_ID> | all | current: Specify which user to send to; if not  
  97.         specified then send to all users.  
  98.     --receiver-permission <PERMISSION>: Require receiver to hold permission.  
  99.   
  100. am instrument: start an Instrumentation.  Typically this target <COMPONENT>  
  101.   is the form <TEST_PACKAGE>/<RUNNER_CLASS> or only <TEST_PACKAGE> if there   
  102.   is only one instrumentation.  Options are:  
  103.     -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT).  Use with  
  104.         [-e perf true] to generate raw output for performance measurements.  
  105.     -e <NAME> <VALUE>: set argument <NAME> to <VALUE>.  For test runners a  
  106.         common form is [-e <testrunner_flag> <value>[,<value>...]].  
  107.     -p <FILE>: write profiling data to <FILE>  
  108.     -w: wait for instrumentation to finish before returning.  Required for  
  109.         test runners.  
  110.     --user <USER_ID> | current: Specify user instrumentation runs in;  
  111.         current user if not specified.  
  112.     --no-window-animation: turn off window animations while running.  
  113.     --abi <ABI>: Launch the instrumented process with the selected ABI.  
  114.         This assumes that the process supports the selected ABI.  
  115.   
  116. am trace-ipc: Trace IPC transactions.  
  117.   start: start tracing IPC transactions.  
  118.   stop: stop tracing IPC transactions and dump the results to file.  
  119.     --dump-file <FILE>: Specify the file the trace should be dumped to.  
  120.   
  121. am profile: start and stop profiler on a process.  The given <PROCESS> argument  
  122.   may be either a process name or pid.  Options are:  
  123.     --user <USER_ID> | current: When supplying a process name,  
  124.         specify user of process to profile; uses current user if not specified.  
  125.   
  126. am dumpheap: dump the heap of a process.  The given <PROCESS> argument may  
  127.   be either a process name or pid.  Options are:  
  128.     -n: dump native heap instead of managed heap  
  129.     --user <USER_ID> | current: When supplying a process name,  
  130.         specify user of process to dump; uses current user if not specified.  
  131.   
  132. am set-debug-app: set application <PACKAGE> to debug.  Options are:  
  133.     -w: wait for debugger when application starts  
  134.     --persistent: retain this value  
  135.   
  136. am clear-debug-app: clear the previously set-debug-app.  
  137.   
  138. am set-watch-heap: start monitoring pss size of <PROCESS>, if it is at or  
  139.     above <HEAP-LIMIT> then a heap dump is collected for the user to report  
  140.   
  141. am clear-watch-heap: clear the previously set-watch-heap.  
  142.   
  143. am bug-report: request bug report generation; will launch a notification  
  144.     when done to select where it should be delivered. Options are:   
  145.    --progress: will launch a notification right away to show its progress.  
  146.   
  147. am monitor: start monitoring for crashes or ANRs.  
  148.     --gdb: start gdbserv on the given port at crash/ANR  
  149.   
  150. am hang: hang the system.  
  151.     --allow-restart: allow watchdog to perform normal system restart  
  152.   
  153. am restart: restart the user-space system.  
  154.   
  155. am idle-maintenance: perform idle maintenance now.  
  156.   
  157. am screen-compat: control screen compatibility mode of <PACKAGE>.  
  158.   
  159. am package-importance: print current importance of <PACKAGE>.  
  160.   
  161. am to-uri: print the given Intent specification as a URI.  
  162.   
  163. am to-intent-uri: print the given Intent specification as an intent: URI.  
  164.   
  165. am to-app-uri: print the given Intent specification as an android-app: URI.  
  166.   
  167. am switch-user: switch to put USER_ID in the foreground, starting  
  168.   execution of that user if it is currently stopped.  
  169.   
  170. am start-user: start USER_ID in background if it is currently stopped,  
  171.   use switch-user if you want to start the user in foreground.  
  172.   
  173. am stop-user: stop execution of USER_ID, not allowing it to run any  
  174.   code until a later explicit start or switch to it.  
  175.   -w: wait for stop-user to complete.  
  176.   -f: force stop even if there are related users that cannot be stopped.  
  177.   
  178. am stack start: start a new activity on <DISPLAY_ID> using <INTENT>.  
  179.   
  180. am stack movetask: move <TASK_ID> from its current stack to the top (true) or   bottom (false) of <STACK_ID>.  
  181.   
  182. am stack resize: change <STACK_ID> size and position to <LEFT,TOP,RIGHT,BOTTOM>.  
  183.   
  184. am stack resize-docked-stack: change docked stack to <LEFT,TOP,RIGHT,BOTTOM>  
  185.    and supplying temporary different task bounds indicated by  
  186.    <TASK_LEFT,TOP,RIGHT,BOTTOM>  
  187.   
  188. am stack size-docked-stack-test: test command for sizing docked stack by  
  189.    <STEP_SIZE> increments from the side <l>eft, <t>op, <r>ight, or <b>ottom  
  190.    applying the optional [DELAY_MS] between each step.  
  191.   
  192. am stack move-top-activity-to-pinned-stack: moves the top activity from  
  193.    <STACK_ID> to the pinned stack using <LEFT,TOP,RIGHT,BOTTOM> for the  
  194.    bounds of the pinned stack.  
  195.   
  196. am stack positiontask: place <TASK_ID> in <STACK_ID> at <POSITION>  
  197. am stack list: list all of the activity stacks and their sizes.  
  198.   
  199. am stack info: display the information about activity stack <STACK_ID>.  
  200.   
  201. am stack remove: remove stack <STACK_ID>.  
  202.   
  203. am task lock: bring <TASK_ID> to the front and don't allow other tasks to run.  
  204.   
  205. am task lock stop: end the current task lock.  
  206.   
  207. am task resizeable: change resizeable mode of <TASK_ID>.  
  208.    0 (unresizeable) | 1 (crop_windows) | 2 (resizeable) | 3 (resizeable_and_pipable)  
  209.   
  210. am task resize: makes sure <TASK_ID> is in a stack with the specified bounds.  
  211.    Forces the task to be resizeable and creates a stack if no existing stack  
  212.    has the specified bounds.  
  213.   
  214. am task drag-task-test: test command for dragging/moving <TASK_ID> by  
  215.    <STEP_SIZE> increments around the screen applying the optional [DELAY_MS]  
  216.    between each step.  
  217.   
  218. am task size-task-test: test command for sizing <TASK_ID> by <STEP_SIZE>   increments within the screen applying the optional [DELAY_MS] between  
  219.    each step.  
  220.   
  221. am get-config: retrieve the configuration and any recent configurations  
  222.   of the device.  
  223. am suppress-resize-config-changes: suppresses configuration changes due to  
  224.   user resizing an activity/task.  
  225.   
  226. am set-inactive: sets the inactive state of an app.  
  227.   
  228. am get-inactive: returns the inactive state of an app.  
  229.   
  230. am send-trim-memory: send a memory trim event to a <PROCESS>.  
  231.   
  232. am get-current-user: returns id of the current foreground user.  
  233.   
  234.   
  235. <INTENT> specifications include these flags and arguments:  
  236.     [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]  
  237.     [-c <CATEGORY> [-c <CATEGORY>] ...]  
  238.     [-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE> ...]  
  239.     [--esn <EXTRA_KEY> ...]  
  240.     [--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE> ...]  
  241.     [--ei <EXTRA_KEY> <EXTRA_INT_VALUE> ...]  
  242.     [--el <EXTRA_KEY> <EXTRA_LONG_VALUE> ...]  
  243.     [--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE> ...]  
  244.     [--eu <EXTRA_KEY> <EXTRA_URI_VALUE> ...]  
  245.     [--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>]  
  246.     [--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]  
  247.         (mutiple extras passed as Integer[])  
  248.     [--eial <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]]  
  249.         (mutiple extras passed as List<Integer>)  
  250.     [--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]  
  251.         (mutiple extras passed as Long[])  
  252.     [--elal <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]]  
  253.         (mutiple extras passed as List<Long>)  
  254.     [--efa <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]  
  255.         (mutiple extras passed as Float[])  
  256.     [--efal <EXTRA_KEY> <EXTRA_FLOAT_VALUE>[,<EXTRA_FLOAT_VALUE...]]  
  257.         (mutiple extras passed as List<Float>)  
  258.     [--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]  
  259.         (mutiple extras passed as String[]; to embed a comma into a string,  
  260.          escape it using "\,")  
  261.     [--esal <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]]  
  262.         (mutiple extras passed as List<String>; to embed a comma into a string,  
  263.          escape it using "\,")  
  264.     [--f <FLAG>]  
  265.     [--grant-read-uri-permission] [--grant-write-uri-permission]  
  266.     [--grant-persistable-uri-permission] [--grant-prefix-uri-permission]  
  267.     [--debug-log-resolution] [--exclude-stopped-packages]  
  268.     [--include-stopped-packages]  
  269.     [--activity-brought-to-front] [--activity-clear-top]  
  270.     [--activity-clear-when-task-reset] [--activity-exclude-from-recents]  
  271.     [--activity-launched-from-history] [--activity-multiple-task]  
  272.     [--activity-no-animation] [--activity-no-history]  
  273.     [--activity-no-user-action] [--activity-previous-is-top]  
  274.     [--activity-reorder-to-front] [--activity-reset-task-if-needed]  
  275.     [--activity-single-top] [--activity-clear-task]  
  276.     [--activity-task-on-home]  
  277.     [--receiver-registered-only] [--receiver-replace-pending]  
  278.     [--receiver-foreground]  
  279.     [--selector]  
  280.     [<URI> | <PACKAGE> | <COMPONENT>]  

pm命令

当要查询系统中某个应用是否存在,或者存在路径,就可以根据对应的包名来查找对应的apk信息。
[java] view plain copy
  1. usage: pm path [--user USER_ID] PACKAGE  
  2.        pm dump PACKAGE                       //dump某个apk  
  3.        pm install [-lrtsfd] [-i PACKAGE] [--user USER_ID] [PATH]  //安装应用  
  4.        pm install-create [-lrtsfdp] [-i PACKAGE] [-S BYTES]  
  5.                [--install-location 0/1/2]  
  6.                [--force-uuid internal|UUID]  
  7.        pm install-write [-S BYTES] SESSION_ID SPLIT_NAME [PATH]  
  8.        pm install-commit SESSION_ID  
  9.        pm install-abandon SESSION_ID  
  10.        pm uninstall [-k] [--user USER_ID] PACKAGE            //卸载应用  
  11.        pm set-installer PACKAGE INSTALLER                    //设置installer  
  12.        pm move-package PACKAGE [internal|UUID]               //移除package  
  13.        pm move-primary-storage [internal|UUID]  
  14.        pm clear [--user USER_ID] PACKAGE                     //清除应用信息  
  15.        pm enable [--user USER_ID] PACKAGE_OR_COMPONENT  
  16.        pm disable [--user USER_ID] PACKAGE_OR_COMPONENT  
  17.        pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT  
  18.        pm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT  
  19.        pm default-state [--user USER_ID] PACKAGE_OR_COMPONENT  
  20.        pm hide [--user USER_ID] PACKAGE_OR_COMPONENT  
  21.        pm unhide [--user USER_ID] PACKAGE_OR_COMPONENT  
  22.        pm grant [--user USER_ID] PACKAGE PERMISSION  
  23.        pm revoke [--user USER_ID] PACKAGE PERMISSION  
  24.        pm reset-permissions                                //重置权限  
  25.        pm set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}  
  26.        pm get-app-link [--user USER_ID] PACKAGE  
  27.        pm set-install-location [0/auto] [1/internal] [2/external]   //设置安装路径  
  28.        pm get-install-location                                     获取安装路径  
  29.        pm set-permission-enforced PERMISSION [true|false]  
  30.        pm trim-caches DESIRED_FREE_SPACE [internal|UUID]  
  31.        pm create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral] [--guest] USER_NAME  
  32.        pm remove-user USER_ID  
  33.        pm get-max-users  
  34.   
  35. NOTE: 'pm list' commands have moved! Run 'adb shell cmd package'  
  36.   to display the new commands.   //使用adb shell pm list packages -f获取系统中所有apk的安装路径  
  37.   
  38. pm path: print the path to the .apk of the given PACKAGE. //adb shell path +包名,获取apk路径  
  39.   
  40. pm dump: print system state associated with the given PACKAGE.  
  41.   
  42. pm install: install a single legacy package  
  43. pm install-create: create an install session  
  44.     -l: forward lock application  
  45.     -r: replace existing application  
  46.     -t: allow test packages  
  47.     -i: specify the installer package name  
  48.     -s: install application on sdcard  
  49.     -f: install application on internal flash  
  50.     -d: allow version code downgrade (debuggable packages only)  
  51.     -p: partial application install  
  52.     -g: grant all runtime permissions  
  53.     -S: size in bytes of entire session  
  54.   
  55. pm install-write: write a package into existing session; path may  
  56.   be '-' to read from stdin  
  57.     -S: size in bytes of package, required for stdin  
  58.   
  59. pm install-commit: perform install of fully staged session  
  60. pm install-abandon: abandon session  
  61.   
  62. pm set-installer: set installer package name  
  63.   
  64. pm uninstall: removes a package from the system. Options:  
  65.     -k: keep the data and cache directories around after package removal.  
  66.   
  67. pm clear: deletes all data associated with a package.  
  68.   
  69. pm enable, disable, disable-user, disable-until-used, default-state:  
  70.   these commands change the enabled state of a given package or  
  71.   component (written as "package/class").  
  72.   
  73. pm grant, revoke: these commands either grant or revoke permissions  
  74.     to apps. The permissions must be declared as used in the app's  
  75.     manifest, be runtime permissions (protection level dangerous),  
  76.     and the app targeting SDK greater than Lollipop MR1.  
  77.   
  78. pm reset-permissions: revert all runtime permissions to their default state.  
  79.   
  80. pm get-install-location: returns the current install location.  
  81.     0 [auto]: Let system decide the best location  
  82.     1 [internal]: Install on internal device storage  
  83.     2 [external]: Install on external media  
  84.   
  85. pm set-install-location: changes the default install location.  
  86.   NOTE: this is only intended for debugging; using this can cause  
  87.   applications to break and other undersireable behavior.  
  88.     0 [auto]: Let system decide the best location  
  89.     1 [internal]: Install on internal device storage  
  90.     2 [external]: Install on external media  
  91.   
  92. pm trim-caches: trim cache files to reach the given free space.  
  93.   
  94. pm create-user: create a new user with the given USER_NAME,  
  95.   printing the new user identifier of the user.  
  96.   
  97. pm remove-user: remove the user with the given USER_IDENTIFIER,  
  98.   deleting all data associated with that user  

dumpsys

该命令用于打印出当前系统信息,默认打印出设备中所有service的信息,可以在命令后面加指定的service name

可以通过adb shell dumpsys + services可以打印出对应系统service的dump信息。可以将某个模块详细信息输出到控制台,可以更加直观的分析。

例如要打印Activity的dump信息:adb shell dumpsys activity

[java] view plain copy
  1. Currently running services:  
  2.   AtCmdFwd  
  3.   DockObserver  
  4.   SurfaceFlinger     //重要  
  5.   accessibility  
  6.   account  
  7.   activity          //重要  
  8.   alarm             //重要  
  9.   android.security.keystore  
  10.   android.service.gatekeeper.IGateKeeperService  
  11.   appops  
  12.   appwidget  
  13.   assetatlas  
  14.   audio           //重要  
  15.   backup     
  16.   battery         //重要  
  17.   batteryproperties  
  18.   batterystats  
  19.   bluetooth_manager  
  20.   carrier_config  
  21.   clipboard  
  22.   cneservice  
  23.   com.qualcomm.location.izat.IzatService  
  24.   com.qualcomm.qti.qseeproxy  
  25.   commontime_management  
  26.   connectivity  
  27.   connectivity_metrics_logger  
  28.   connmetrics  
  29.   consumer_ir  
  30.   content  
  31.   contexthub_service  
  32.   country_detector  
  33.   cpuinfo         
  34.   dbinfo  
  35.   device_policy  
  36.   deviceidle  
  37.   devicestoragemonitor  
  38.   diskstats  
  39.   display       //重要  
  40.   display.qservice  
  41.   dpmservice  
  42.   dreams  
  43.   drm.drmManager  
  44.   dropbox  
  45.   eSEPowerManagerService  
  46.   ethernet  
  47.   extphone  
  48.   gfxinfo  
  49.   gpu         //重要  
  50.   graphicsstats  
  51.   hardware_properties  
  52.   imms  
  53.   ims  
  54.   input       //重要  
  55.   input_method  //重要  
  56.   iphonesubinfo  
  57.   isms  
  58.   isub  
  59.   jobscheduler  
  60.   launcherapps  
  61.   location  
  62.   lock_settings  
  63.   mdtp  
  64.   media.audio_flinger  
  65.   media.audio_policy  
  66.   media.camera  
  67.   media.camera.proxy  
  68.   media.codec  
  69.   media.drm  
  70.   media.extractor  
  71.   media.player  
  72.   media.radio  
  73.   media.resource_manager  
  74.   media.sound_trigger_hw  
  75.   media_projection  
  76.   media_router  
  77.   media_session  
  78.   meminfo       //输出内存相关,重要  
  79.   midi  
  80.   mount          
  81.   netd  
  82.   netd_listener  
  83.   netpolicy  
  84.   netstats  
  85.   network_management  
  86.   network_score  
  87.   network_time_update_service  
  88.   notification  
  89.   okay_property  
  90.   otadexopt  
  91.   package          //重要  
  92.   permission  
  93.   persistent_data_block  
  94.   phone  
  95.   pinner  
  96.   power           //电源管理,重要  
  97.   print  
  98.   processinfo  
  99.   procstats  
  100.   qti.ims.connectionmanagerservice  
  101.   qti.ims.ext  
  102.   qtitetherservice  
  103.   recovery  
  104.   regionalization  
  105.   restrictions  
  106.   rttmanager  
  107.   samplingprofiler  
  108.   scheduling_policy  
  109.   search  
  110.   sensorservice  
  111.   serial  
  112.   servicediscovery  
  113.   shortcut  
  114.   simphonebook  
  115.   soundtrigger  
  116.   statusbar  
  117.   telecom  
  118.   telephony.registry  
  119.   textservices  
  120.   trust  
  121.   uimode  
  122.   updatelock  
  123.   usagestats  
  124.   usb  
  125.   user  
  126.   vendor.qcom.PeripheralManager  
  127.   vibrator  
  128.   voiceinteraction  
  129.   vrmanager  
  130.   wallpaper     //重要  
  131.   webviewupdate  
  132.   wifi  
  133.   wifip2p  
  134.   wifiscanner  
  135.   window         //Windows管理信息,重要  

wakelock

       wakelock主要是系统为上层提供控制屏幕亮度显示,以及cpu唤醒的一个接口。我们可以通过上面学习的dumpsys命令来查看系统此时存在那些wakelock。

adb shell dumpsys power

[java] view plain copy
  1. Wake Locks: size=1  
  2.   SCREEN_BRIGHT_WAKE_LOCK        'WindowManager' ON_AFTER_RELEASE ACQ=-1s234ms (uid=1000 pid=1495 ws=WorkSource{1000})  

       此时系统只有一个wakelock,类型为SCREEN_BRIGHT_WAKE_LOCK,所属模块为WIndowManager。下面讲解一下如何使用wakelock。

[java] view plain copy
  1. PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); //获取PowerManager  
  2. sWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK   //使用power创建一个新的wakelock,执行类型  
  3.         | PowerManager.ACQUIRE_CAUSES_WAKEUP  
  4.         | PowerManager.ON_AFTER_RELEASE, TAG);  
  5. sWakeLock.acquire();                                    //使wakelock起作用,当不需要时使用release释放wakelock  

   任何应用程序使用WakeLock,必须要求android.permission.WAKE_LOCK许可在应用程序的清单上使用<uses-permission>元素。下面为我们可以调用的公共方法。

[java] view plain copy
  1. Public Methods  
  2. void acquire() --->当你创建这个WakeLock时,确保这个设备按照你的要求保持唤醒的状态。  
  3. void acquire(long timeout) --->当你创建这个WakeLock时,确保这个设备按照你的要求保持唤醒的状态。  
  4. void isHeld()  
  5. void release() ---> 按照你的要求释放cpu或屏幕。  
  6. void setReferenceCounted(boolean value)--->如果需要使用引用计数,则将value设置为true。默认设置为                                                               true,表示当用户申请多少次锁时,就必须释放多少次。  
  7. void setWorkSource(WorkSource ws)  
  8. String toString() --->返回一个简洁的字符串用来将这个对象描述为人们可读懂的。  
  9. void Finalize() --->当垃圾收集器检测到该实例不再运行调用。  

wakelock有不同的类型,我们可以根据需要选择不同的wakelock类型。

Flag Value CPU Screen Keyboard
PARTIAL_WAKE_LOCK On Off   Off
SCREEN_DIM_WAKE_LOCK On  Dim Off
SCREEN_BRIGHT_WAKE_LOCK On Bright Off
FULL_WAKE_LOCK On Bright Bright
      如果你持有的partial wakelock,CPU将继续运行,不论何时,即使当用户按下电源按钮。对于所有其他wakelocks,但用户使用电源按钮时,系统将进入睡眠,cpu将不再继续运行。
PARTIAL_WAKE_LOCK:保持CPU 运转,屏幕和键盘灯有可能是关闭的。
SCREEN_DIM_WAKE_LOCK:保持CPU 运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯
SCREEN_BRIGHT_WAKE_LOCK:保持CPU 运转,允许保持屏幕高亮显示,允许关闭键盘灯
FULL_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度
ACQUIRE_CAUSES_WAKEUP:正常唤醒锁实际上并不打开照明。相反,一旦打开他们会一直仍然保持(例如来世user的activity)。当获得wakelock,这个标志会使屏幕或/和键盘立即打开。一个典型的使用就是可以立即看到那些对用户重要的通知。
ON_AFTER_RELEASE:设置了这个标志,当wakelock释放时用户activity计时器会被重置,导致照明持续一段时间。如果你在wacklock条件中循环,这个可以用来减少闪烁

  我们可以创建多个锁,并hold它,即使对同一类型,也如此,对于某类型的wakelock只要有一个被hold,那么它所对应的电源状态(illumination),就将不会超时,将被延续(hold).在上表中我们把越往下的,称为更高一级的wakelocks.当高级和低级wakelocks相遇的时候,高级起作用。在上面的flag上还再加上如下的2个flag,但是他们和PARTIAL_WAKE_LOCK.组合没任何意义ACQUIRE_CAUSES_WAKEUP默认情况下wake locks并不是马上开启CPU或Screen或Keyboard的(对于Screen是Dim或Bright,Keyboard是Bright. wake locks只是在被开启后(比如用户的活动),让设备延续(保存)你设定开启的状态. 但是如果加上ACQUIRE_CAUSES_WAKEUP就可以让Screen或Keyboar没开启的情况,马上开启它们。 典型的应用就是在收到一个重要的notifications时,需要马上点亮屏幕。

addr2line

在分析framework稳定性问题时会遇到Native crash的发生,而Native crash与java crash的堆栈信息不同。下面是一段Native 堆栈的片段。
[java] view plain copy
  1. 03-19 14:58:50.034   319  3145 D kevin_Render: #01 pc 0005f8a5  /system/lib/libmediaplayerservice.so (android::NuPlayer::Renderer::setAnchorTime(long longlong longlong long, bool)+72)  
  2. 03-19 14:58:50.034   319  3145 D kevin_Render: #02 pc 000618c5  /system/lib/libmediaplayerservice.so (android::NuPlayer::Renderer::onNewAudioMediaTime(long long)+88)  
  3. 03-19 14:58:50.035   319  3145 D kevin_Render: #03 pc 00062249  /system/lib/libmediaplayerservice.so (android::NuPlayer::Renderer::onDrainAudioQueue()+764)  
  4. 03-19 14:58:50.035   319  3145 D kevin_Render: #04 pc 00062ec3  /system/lib/libmediaplayerservice.so (android::NuPlayer::Renderer::onMessageReceived(android::sp<android::AMessage> const&)+866)  
  5. 03-19 14:58:50.035   319  3145 D kevin_Render: #05 pc 0000d12d  /system/lib/libstagefright_foundation.so (android::ALooperRoster::deliverMessage(android::sp<android::AMessage> const&)+164)  
  6. 03-19 14:58:50.035   319  3145 D kevin_Render: #06 pc 0000cac1  /system/lib/libstagefright_foundation.so (android::ALooper::loop()+216)  
  7. 03-19 14:58:50.035   319  3145 D kevin_Render: #07 pc 00010977  /system/lib/libutils.so (android::Thread::_threadLoop(void*)+110)  
  8. 03-19 14:58:50.035   319  3145 D kevin_Render: #08 pc 00016f5b  /system/lib/libc.so (__pthread_start(void*)+30)  
  9. 03-19 14:58:50.035   319  3145 D kevin_Render: #09 pc 00014f7b  /system/lib/libc.so (__start_thread+6)  
根据上面的堆栈,我们并不能看到具体哪个函数,哪行代码出现了问题,这个时候我们就需要解析Native函数的地址值,如上面 00062ec3这样的符号,我们需要通过addr2line来进行解析。我们可以使用linux系统提供的addr2line命令,也可以使用源代码sdk中的工具。具体命令如下:
addr2line -e out/target/product/项目名/symbols/system/lib/libxxx.so -f -C <addr> 
如果我们想要解析03行的地址值00062249
[java] view plain copy
  1. kevin@kevin-All-Series:~/work/$ addr2line -e out/target/product/miki8163_9003/symbols/system/lib/libmediaplayerservice.so -f -C 00062249  
  2. android::NuPlayer::Renderer::onDrainAudioQueue()  
  3. /home/kevin/work/source/sm8163/sm8163/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp:868  
解析后我们看到该行代码属于函数android::NuPlayer::Renderer::onDrainAudioQueue(),在NuPlayerRenderer.cpp的868行,这样就十分方便了。

meminfo

当我们查询系统的内存信息除了使用dumpsys命令,还可以直接使用adb shell cat /proc/meminfo
[java] view plain copy
  1. kevin@kevin-All-Series:~/work$ adb shell cat /proc/meminfo  
  2. MemTotal:        1844152 kB       //内存的总大小  
  3. MemFree:           41364 kB       //空闲内存  
  4. MemAvailable:     230892 kB       //可用的内存  
  5. Buffers:            3520 kB         
  6. Cached:           230312 kB       //缓存  
  7. SwapCached:         6484 kB  
  8. Active:           538568 kB  
  9. Inactive:         257680 kB  
  10. Active(anon):     426264 kB  
  11. Inactive(anon):   144884 kB  
  12. Active(file):     112304 kB  
  13. Inactive(file):   112796 kB  
  14. Unevictable:         256 kB  
  15. Mlocked:             256 kB  
  16. SwapTotal:        524284 kB  
  17. SwapFree:            156 kB  
  18. Dirty:                44 kB      //脏页  
  19. Writeback:             0 kB  
  20. AnonPages:        559864 kB  
  21. Mapped:           216980 kB  
  22. Shmem:              8608 kB  
  23. Slab:             354744 kB  
  24. SReclaimable:      56820 kB  
  25. SUnreclaim:       297924 kB  
  26. KernelStack:       35488 kB  
  27. PageTables:        34172 kB  
  28. NFS_Unstable:          0 kB  
  29. Bounce:                0 kB  
  30. WritebackTmp:          0 kB  
  31. CommitLimit:     1446360 kB  
  32. Committed_AS:   63267272 kB  
  33. VmallocTotal:   244318144 kB  
  34. VmallocUsed:      116780 kB  
  35. VmallocChunk:   244056036 kB  

fastboot

      Android系统编译后会生成很多的image文件,我们可以通过刷机工具将image烧制到手机中,我们也可以使用fastboot命令很方便的将image文件烧制到系统中。下面为fastboot的使用方法:

1.开机状态下执行

adb reboot bootloader(执行命令后系统会关机重启,进入fastboot模式)

2.烧写system.img

fastboot flash system system.img

如果要烧制boot.img,那么就执行fastboot flash boot boot.img,其他image也一样。

3.重启

fastboot reboot

简单几步就可以快速将我们编译出来的文件烧制到手机中。

bootchart

      bootchart是一个用于linux启动过程性能分析的开源软件工具,在系统启动过程自动收集CPU占用率、进程等信息,并以图形方式显示分析结果,可用作指导优化系统启动过程。bootchart详细使用说明请参考《Android7.0 bootchart工具使用说明

LOG分析

      在调试Android系统时如果要实时的查看输出的log信息就可以使用adb logcat -vthreadtime或者adb logcat在终端输出需要的log信息,在5.1及其之前的版本需要adb logcat后需要加上-vthreadtime 意思是将输出时间以及进程线程信息,5.1之后的版本系统自动添加了时间与进程线程信息,直接用adb logcat就可以。

    而更多的时候我们需要分析log文件,也就是在系统运行时会将log信息输出在log文件中,以便在出现问题时让开发人员进行分析,下面讲几个场景的关键LOG信息。

开机LOG

     在分析开机log时通过根据开机流程进行分段分析,这里省略bootloader中log,首先从执行kernel完成分析,到启动launcher分析结束,来看其中执行了那些过程,如果开机流程出现问题,就可以定位哪个流程出现问题。

[plain] view plain copy
  1. //开始启动init进程,也就是kernel启动完成,取时间戳2.172934s,为启动kernel所耗时.  
  2. [01-01 08:30:04.349] <13>[    2.172934] c5 init: init started!  
  3.   
  4. //开始启动zygote,使用时间戳相减4.281027-2.172934计算出启动init进程到启动zygote耗时2.1s.  
  5. [01-01 08:30:04.367] <13>[    4.281027] c0 init: Starting service 'zygote'...  
  6.   
  7. //进入zygote,由于kernel时间与android不能相减,所以无法计算启动zygote到进入zygote所花费时间.  
  8. A001-01 08:30:05.036  2810  2810 D AndroidRuntime: >>>>>> START com.android.internal.os.ZygoteInit uid 0 <<<<<<  
  9.   
  10. //进入SystemServer,使用android时间08:30:08.629-08:30:05.036 获得,从进入zygote到SystemServer耗时  
  11. A101-01 08:30:08.629  3285  3285 I SystemServer: Entered the Android system server!  
  12.   
  13. //开始初始化Package, 使用android时间相减,获取进入SystemServer到初始化Package的耗时.  
  14. A101-01 08:30:09.021  3285  3285 I SystemServer: Package Manager  
  15. //扫描解析应用耗时,可以直接获取1.544 seconds  
  16. A101-01 08:30:10.813  3285  3285 I PackageManager: Time to scan packages: 1.544 seconds  
  17.   
  18. //开始执行network systemReady函数,使用android时间相减,获取初始化Package完成到开始执行network systemReady函数的耗时.  
  19. A101-01 08:30:14.285  3285  3285 D NetworkManagement: enabling bandwidth control  
  20.   
  21. //network执行完相关命令,使用android时间相减,获取执行network执行相关命令耗时.  
  22. A101-01 08:30:15.475  3285  3285 I SystemServiceManager: Starting phase 600  
  23.   
  24. //启动launcher, 使用android时间相减,获取执行network命令完成,到启动launcher耗时  
  25. A101-01 08:30:15.915  3285  3285 I ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.android.launcher3/.Launcher} from uid 0 on display 0  

关机LOG

      在分析关机log时,是从长按power键,点击确认关机,到灭屏震动关机。关机主要经过的流程为发送关机广播,关闭AMS,PMS,关闭移动数据,卸载sd卡等流程,最后调用power往底层系统配置中写入对应的信息,底层读取信息,进行关机。

[plain] view plain copy
  1. //按确认键,开始关机  
  2. 01-01 12:49:10.410  1147  1226 I ShutdownThread: shutdown goto shutdownInner  
  3.   
  4. //发送关机广播,使用android时间相减,获得关机到发送关机广播之间耗时  
  5. 01-01 12:49:10.498  1147  2504 I ShutdownThread: Sending shutdown broadcast...  
  6.   
  7. //开始shutdown activity manager, 使用android时间相减,获得关机广播处理耗时  
  8. 01-01 12:49:10.637  1147  2504 I ShutdownThread: Shutting down activity manager...  
  9.   
  10.  //开始关闭蜂窝网,使用android时间相减,获得开机shutdown activity manager到关闭蜂窝网耗时  
  11. 01-01 12:49:10.746  1147  2522 W ShutdownThread: Turning off cellular radios...       
  12.   
  13.  //开始关闭Radio,获得关闭蜂窝网到开始关闭Radio耗时  
  14. 01-01 12:49:10.753  1147  2522 I ShutdownThread: Waiting for NFC, Bluetooth and Radio...  
  15.   
  16. //关闭Radio完成,使用android时间相减,获得关闭Radio耗时,该流程可能耗时较长.重点  
  17. 01-01 12:49:11.255  1147  2522 I ShutdownThread: NFC, Radio and Bluetooth shutdown complete.  
  18.   
  19. //开始关闭MountService,使用android时间相减,获得关闭Radio完成到关闭MountService耗时.  
  20. 01-01 12:49:11.257  1147  2504 I ShutdownThread: Shutting down MountService  
  21.   
  22. //关闭MountService完成,使用android时间相减,获得关闭MountService耗时.该流程可能耗时较长.重点  
  23. 01-01 12:49:11.268  1147  1304 W ShutdownThread: Result code 0 from MountService.shutdown  
  24.   
  25. //调用底层接口,关机完成.  
  26. 01-01 12:49:11.776  1147  2504 I ShutdownThread: Performing low-level shutdown...  

首启动应用LOG

      在分析分析应用启动问题时,我们通常分析event log信息,使用命令adb logcat -b events,其中的log信息主要为应用的生命周期信息。通过查看生命周期信息来分析,应用是否行为异常。

首次启动

[plain] view plain copy
  1. //开始启动activity  
  2. 07-29 10:26:57.033  1173  1995 I am_create_activity: [0,102422011,29,com.android.dialer/.DialtactsActivity,android.intent.action.MAIN,NULL,NULL,270532608]  
  3.   
  4. //launcher pause完成。  
  5. 07-29 10:26:57.109  2009  2009 I am_on_paused_called: [0,com.android.launcher3.Launcher]  
  6.   
  7. //进程开始创建,与开始启动activity时间相减,获得准备工作耗时.           
  8. 07-29 10:26:57.142  1173  1996 I am_proc_start: [0,5164,10038,com.android.dialer,activity,com.android.dialer/.DialtactsActivity]  
  9.   
  10. //进程bound完成,与进程创建之间这个过程可以理解为进程创建的时间。为创建进程耗时.  
  11. 07-29 10:26:57.195  1173  1404 I am_proc_bound: [0,5164,com.android.dialer]  
  12.   
  13. //ams向应用发消息进行启动activity操作  
  14. 07-29 10:26:57.199  1173  1404 I am_restart_activity: [0,102422011,29,com.android.dialer/.DialtactsActivity]  
  15.   
  16. //activity resume执行完成,与restart_activity之间这个可以理解为Activity的生命周期执行时间。为生命周期耗时  
  17. 07-29 10:26:57.394  5164  5164 I am_on_resume_called: [0,com.android.dialer.DialtactsActivity]  
  18.   
  19. //这里activity显示完成,当前Activity显示过程644ms,整个显示过程644ms。  
  20. //从activity resume完成到这个log之间可以理解为广义上的绘制过程(measure,layout,draw,render)。  
  21. 07-29 10:26:57.757  1173  1356 I am_activity_launch_time: [0,102422011,com.android.dialer/.DialtactsActivity,644,644]  

非首次启动

[plain] view plain copy
  1. //开始启动activity,到launcher pause完成。  
  2. 01-01 13:26:59.645  1162  1733 I am_create_activity: [0,233918075,10,com.android.messaging/.ui.conversationlist.ConversationListActivity,android.intent.action.MAIN,NULL,NULL,270532608]  
  3.   
  4. //launcher pause完成。  
  5.  07-29 10:26:57.109  2009  2009 I am_on_paused_called: [0,com.android.launcher3.Launcher]  
  6.   
  7. //ams向应用发消息进行启动activity操作,准备工作  
  8. 01-01 13:26:59.710  1162  1439 I am_restart_activity: [0,233918075,10,com.android.messaging/.ui.conversationlist.ConversationListActivity]  
  9.   
  10.  //activity resume执行完成,与restart_activity之间这个可以理解为Activity的生命周期执行时间。  
  11. 01-01 13:26:59.782  2189  2189 I am_on_resume_called: [0,com.android.messaging.ui.conversationlist.ConversationListActivity]  
  12.   
  13. //这里activity显示完成,当前Activity显示过程168ms,整个显示过程168ms。  
  14. //从activity resume完成到这个log之间可以理解为广义上的绘制过程(measure,layout,draw,render)。  
  15. 01-01 13:26:59.871  1162  1283 I am_activity_launch_time: [0,233918075,com.android.messaging/.ui.conversationlist.ConversationListActivity,168,168]  

亮屏关键LOG

[plain] view plain copy
  1. //kernel中断key事件,ScanCode:116为Power键,value:1为down事件  
  2. <6>[41051.961488] c1 [SPRD_KEY_INFO]Key:Power Key ScanCode:116 value:1  
  3.   
  4. //InputReader获取power键事件,code=116为power键  
  5. 01-02 08:04:44.016   600   643 D InputReader: processEventsLocked: type=1 Count=2 code=116 value=1 deviceId=2  
  6.   
  7. //Power收到亮屏调用,开始亮屏  
  8. 01-02 08:04:44.037   600   643 I PowerManagerService: Waking up from sleep (uid 1000)...  
  9.   
  10. //开始block亮屏,直到keyguard与windows绘制完成  
  11. 01-02 08:04:44.052   600   622 I DisplayPowerController: Blocking screen on until initial contents have been drawn.  
  12.   
  13. //开始绘制keyguard  
  14. 01-02 08:04:44.052   600   622 I WindowManager: Screen turning on...  
  15.   
  16. //tosuspend_disable()耗时283s,有时为setPowerMode耗时长  
  17. 01-02 08:04:44.347   600   676 D PowerManagerService-JNI: Excessive delay in autosuspend_disable() while   
  18.   
  19. //yguard绘制完成  
  20. 01-02 08:04:44.504   600   700 D WindowManager: mKeyguardDelegate.ShowListener.onDrawn.  
  21. 01-02 08:04:44.504   600   614 W WindowManager: Setting mKeyguardDrawComplete  
  22.   
  23. //windows绘制完成  
  24. 01-02 08:04:44.551   600   620 I WindowManager: All windows ready for display!  
  25. 01-02 08:04:44.551   600   614 W WindowManager: Setting mWindowManagerDrawComplete  
  26.   
  27. //block亮屏,总共blocked亮屏505ms  
  28. 01-02 08:04:44.557   600   622 I DisplayPowerController: Unblocked screen on after 505 ms  
  29.   
  30. //屏幕亮度,往节点中写亮度值  
  31. 01-02 08:04:44.558   600   676 D LIGHTS  : file:vendor/sprd/modules/lights/lights.c, func:set_light_backlight, brightness=25  
  32. 01-02 08:04:44.559   600   676 E LIGHTS  : file:vendor/sprd/modules/lights/lights.c, func:write_int, path=/sys/class/backlight/sprd_backlight/brightness, value=25  

来电亮屏LOG

[plain] view plain copy
  1. //创建dialer进程  
  2. 12-22 15:46:23.704   595   595 I ActivityManager: Start proc 5067:com.android.dialer/u0a1 for service com.android.dialer/com.android.incallui.InCallServiceImpl  
  3.   
  4. //来电响铃  
  5. 12-22 15:46:23.736   595  5083 I Telecom : AsyncRingtonePlayer: Play ringtone.  
  6.   
  7. //启动InCallActivity   
  8. 12-22 15:46:24.410   595  1016 I ActivityManager: START u0 {act=android.intent.action.MAIN flg=0x10040000 cmp=com.android.dialer/com.android.incallui.InCallActivity (has extras)} from uid 10001 on display 0  
  9.   
  10. //显示InCallActivity  
  11. 12-22 15:46:25.715   595   615 I am_activity_launch_time: [0,134650581,com.android.dialer/com.android.incallui.InCallActivity,1293,1299]  
  12.   
  13. //power收到亮屏调用  
  14. 12-22 15:46:25.730   595   615 I PowerManagerService: Waking up from sleep due toandroid android.server.wm:TURN_ON (uid 1000)...  
  15.   
  16. //点亮屏幕  
  17. A012-22 15:46:26.220   595   679 D LIGHTS  : file:vendor/sprd/modules/lights/lights.c, func:set_light_backlight, brightness=25  
  18. A012-22 15:46:26.221   595   679 E LIGHTS  : file:vendor/sprd/modules/lights/lights.c, func:write_int, path=/sys/class/backlight/sprd_backlight/brightness, value=25  

灭屏LOG

[plain] view plain copy
  1. //kernel中断key事件,ScanCode:116为Power键,value:1为down事件  
  2. <6>[42586.507314] c1 [SPRD_KEY_INFO]Key:Power Key ScanCode:116 value:1  
  3.   
  4. //value:0为up事件  
  5. <6>[42586.660288] c1 [SPRD_KEY_INFO]Key:Power Key ScanCode:116 value:0  
  6.   
  7. //Input收到power键down事件  
  8. 01-06 13:25:48.460  3339  3447 D InputReader: processEventsLocked: type=1 Count=2 code=116 value=1 deviceId=2  
  9.   
  10. //Input收到power键up事件  
  11. 01-06 13:25:48.643  3339  3447 D InputReader: processEventsLocked: type=1 Count=2 code=116 value=0 deviceId=2  
  12.   
  13. //短按power键,power开始灭屏  
  14. 01-06 13:25:48.643  3339  3447 I PowerManagerService: Going to sleep due to power button (uid 1000)...  
  15.   
  16. //设置全局变量,通知keyguard灭屏了  
  17. 01-06 13:25:48.645  3339  3361 I WindowManager: Screen turned off...  
  18.   
  19. //设置屏幕亮度为0  
  20. 01-06 13:25:48.645  3339  3493 D LIGHTS  : file:vendor/sprd/modules/lights/lights.c, func:set_light_backlight, brightness=0  
  21. 01-06 13:25:48.645  3339  3493 E LIGHTS  : file:vendor/sprd/modules/lights/lights.c, func:write_int, path=/sys/class/backlight/sprd_backlight/brightness, value=0  

添加LOG信息

java层添加

    当在调试系统代码时,如果要确认代码是否走了某个流程,就可以添加log信息,如果执行某项操作可以将该行log打印出来就说明走了该流程。
[java] view plain copy
  1. import android.util.Log;    //导入LOG包  
  2.   
  3.     private static String getActiveSubscriberId(Context context, int subId) {  
  4.         final TelephonyManager tele = TelephonyManager.from(context);  
  5.         String retVal = tele.getSubscriberId(subId);  
  6.         Log.d(TAG, "getActiveSubscriberId=" + retVal + " subId=" + subId); //添加log信息  
  7.         return retVal;  
  8.     }  

如果想知道某行代码是怎么调用过来的,他的调用关系是什么,就可以通过打印堆栈的方式来确认。具体方式如下;

[java] view plain copy
  1. try {  
  2.     throw new Exception("Call Stack Trace");  
  3. catch (Exception e) {  
  4.     Log.i("kevin""xxx", e);  
  5. }  

例如在唤醒屏幕流程,如果想要分析wakeUpInternal是怎么调用过来的,就可以打印堆栈的方式来确认调用关系。

[java] view plain copy
  1. private void wakeUpInternal(long eventTime, String reason, int uid, String opPackageName,  
  2.         int opUid) {  
  3.     synchronized (mLock) {  
  4.   
  5.         try {  
  6.             throw new Exception("Call Stack Trace");  
  7.         } catch (Exception e) {  
  8.             Log.i("kevin""xxx", e);  
  9.         }  
  10.   
  11.         if (wakeUpNoUpdateLocked(eventTime, reason, uid, opPackageName, opUid)) {  
  12.             updatePowerStateLocked();  
  13.         }  
  14.     }  
  15. }  

当我们修改好代码后编译services.jar,将services.jar push到手机中,重启,按power键亮灭屏就可以看到如下信息。

Android Framework常用工具及LOG调试方法

C++层添加

如果想要在C++层添加log信息,需要在对应的Android.mk文件中添加下面代码,添加共享库。

[cpp] view plain copy
  1. LOCAL_SHARED_LIBRARIES := libutils  

用如下log可以打印C++层的信息。

[cpp] view plain copy
  1. ALOGD("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);   

如果要在C++层中打印对应堆栈,使用如下代码:

[cpp] view plain copy
  1. #include <utils/CallStack.h>  
  2.   
  3. CallStack stack;  
  4. stack.update();  
  5. stack.log("kevin");  

示例代码如下:

[cpp] view plain copy
  1. void NuPlayer::start() {  
  2.     CallStack stack;  
  3.     stack.update();  
  4.     stack.log("kevin");  
  5.     (new AMessage(kWhatStart, this))->post();  
  6. }  

输出堆栈如下:

Android Framework常用工具及LOG调试方法

可以使用前面学习的addr2line

Android Framework常用工具及LOG调试方法

可以看到具体的代码调用。