ProtoLog开关
在代码中我们经常看见ProtoLog打印的log,如下:
ProtoLog.i(WM_DEBUG_ANIM, "Animation start delayed for %s", mAnimatable);
这种log正常情况不会显示,因此我们需要打开开关,其格式为:
adb shell wm logging enable-text [代码中对应的TAG]
我们这段代码的TAG是WM_DEBUG_ANIM,因此通过命令adb shell wm logging enable-text WM_DEBUG_ANIM打开log开关
另一种情况
ProtoLog.v(WM_SHELL_TASK_ORG, "Task info changed taskId=%d", taskInfo.taskId);
wmshell的log比较特殊,其在SystemUI进程,如果我们直接运行adb shell wm logging enable-text WM_SHELL_TASK_ORG会报错,打印如下:
Loaded 749 log definitions from /system/etc/protolog.conf.json.gz
No IProtoLogGroup named WM_SHELL_TASK_ORG
Not handled, please use `adb shell dumpsys activity service SystemUIService WMShell` if you are looking for ProtoLog in WMShell
根据提示我们打开log
adb shell dumpsys activity service SystemUIService WMShell protolog enable WM_SHELL_TASK_ORG
logcat抓取log
# 抓取普通的andorid log
adb shell logcat > log.txt
# 仅抓取events log
adb shell logcat -b events > log.txt
# 抓取所有类型log
adb shell logcat -b all > log.txt
# 根据关键字抓取log,-i可以忽略大小,-e可以添加多条关键字,如下:
adb shell logcat -b events | grep -ie "关键log1" -ie "关键log2"> log.txt
events.log中对应代码查找
events log对应代码的规律是: events log开头的字段,比如wm_xxx 则对应的代码可以通过 grep 抓取 writeWmxxx 找出是在哪里打印的该events log
例如:
应用走到onresume生命周期的log
wm_on_resume_called: [223605563,com.tencent.mm.ui.LauncherUI,RESUME_ACTIVITY,10]
EventLogTags.writeWmOnResumeCalled(mIdent, getComponentName().getClassName(), reason);
通知cancel的log
notification_canceled: [0|com.tencent.mm|40|null|10218,8,19980,19980,7720,-1,-1,NULL]
EventLogTags.writeNotificationCanceled(canceledKey, reason,
r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now),
rank, count, listenerName);
使用winscope
手机要处于root状态才能使用
-
使用手机自带的winscope 在手机设置里面,找到开发者选项->快捷设置开发者图块->打开 “ Winscope跟踪 ” 打开后复现问题,最后再关闭这个开关,就表示抓取完成 导出文件
adb pull /data/misc/wmtrace把导出文件在源码路径的android-13.0.0_r6/prebuilts/misc/common/winscope/winscope.html打开即可 -
使用脚本抓取winscope(推荐) 附链接:
winscope-t和winscope-u均可离线使用,但是V的版本却不行,需要进行以下操作 1.需要用npm安装http-server
npm install -g http-server2.安装完成后运行http-server,进入下面任意一个ip即可下载后,连接手机,直接运行脚本中的
./run.sh,或者python3 winscope_proxy.pySTART TRACE: 可以持续dump window和SurfaceFlinger信息,一般适用于闪黑场景,复现之前按下,复现后停止即可。 DMUP STATE: 相当于就是抓取一次
dumpsys window和dumpsys SurfaceFlinger
常见dump命令
adb shell dumpsys SurfaceFlinger > ./dump/SurfaceFlinger.txt
adb shell dumpsys window -a > ./dump/window.txt
adb shell dumpsys activity activities > ./dump/activities.txt
adb shell dumpsys activity top > ./dump/top_activity.txt
adb shell dumpsys activity containers > ./dump/containers.txt
adb shell dumpsys input > ./dump/input.txt
查找dump命令的方法
代码路径:frameworks/base/core/java/android/content/Context.java 这个代码里面有很多serviceName
@StringDef(suffix = { "_SERVICE" }, value = {
POWER_SERVICE,
//@hide: POWER_STATS_SERVICE,
WINDOW_SERVICE,
LAYOUT_INFLATER_SERVICE,
ACCOUNT_SERVICE,
ACTIVITY_SERVICE,
ALARM_SERVICE,
NOTIFICATION_SERVICE,
ACCESSIBILITY_SERVICE,
CAPTIONING_SERVICE,
KEYGUARD_SERVICE,
LOCATION_SERVICE,
HEALTHCONNECT_SERVICE,
//@hide: COUNTRY_DETECTOR,
SEARCH_SERVICE,
SENSOR_SERVICE,
SENSOR_PRIVACY_SERVICE,
STORAGE_SERVICE,
STORAGE_STATS_SERVICE,
WALLPAPER_SERVICE,
VIBRATOR_MANAGER_SERVICE,
VIBRATOR_SERVICE,
//@hide: STATUS_BAR_SERVICE,
CONNECTIVITY_SERVICE,
PAC_PROXY_SERVICE,
VCN_MANAGEMENT_SERVICE,
//@hide: IP_MEMORY_STORE_SERVICE,
IPSEC_SERVICE,
VPN_MANAGEMENT_SERVICE,
TEST_NETWORK_SERVICE,
//@hide: UPDATE_LOCK_SERVICE,
//@hide: NETWORKMANAGEMENT_SERVICE,
NETWORK_STATS_SERVICE,
//@hide: NETWORK_POLICY_SERVICE,
WIFI_SERVICE,
WIFI_AWARE_SERVICE,
WIFI_P2P_SERVICE,
WIFI_SCANNING_SERVICE,
//@hide: LOWPAN_SERVICE,
//@hide: WIFI_RTT_SERVICE,
//@hide: ETHERNET_SERVICE,
WIFI_RTT_RANGING_SERVICE,
NSD_SERVICE,
AUDIO_SERVICE,
AUDIO_DEVICE_VOLUME_SERVICE,
AUTH_SERVICE,
FINGERPRINT_SERVICE,
//@hide: FACE_SERVICE,
BIOMETRIC_SERVICE,
MEDIA_ROUTER_SERVICE,
TELEPHONY_SERVICE,
TELEPHONY_SUBSCRIPTION_SERVICE,
CARRIER_CONFIG_SERVICE,
EUICC_SERVICE,
//@hide: MMS_SERVICE,
TELECOM_SERVICE,
CLIPBOARD_SERVICE,
INPUT_METHOD_SERVICE,
TEXT_SERVICES_MANAGER_SERVICE,
TEXT_CLASSIFICATION_SERVICE,
APPWIDGET_SERVICE,
//@hide: VOICE_INTERACTION_MANAGER_SERVICE,
//@hide: BACKUP_SERVICE,
REBOOT_READINESS_SERVICE,
ROLLBACK_SERVICE,
DROPBOX_SERVICE,
//@hide: DEVICE_IDLE_CONTROLLER,
//@hide: POWER_WHITELIST_MANAGER,
DEVICE_POLICY_SERVICE,
UI_MODE_SERVICE,
DOWNLOAD_SERVICE,
NFC_SERVICE,
BLUETOOTH_SERVICE,
//@hide: SIP_SERVICE,
USB_SERVICE,
LAUNCHER_APPS_SERVICE,
//@hide: SERIAL_SERVICE,
//@hide: HDMI_CONTROL_SERVICE,
INPUT_SERVICE,
DISPLAY_SERVICE,
//@hide COLOR_DISPLAY_SERVICE,
USER_SERVICE,
RESTRICTIONS_SERVICE,
APP_OPS_SERVICE,
ROLE_SERVICE,
//@hide ROLE_CONTROLLER_SERVICE,
CAMERA_SERVICE,
//@hide: PLATFORM_COMPAT_SERVICE,
//@hide: PLATFORM_COMPAT_NATIVE_SERVICE,
PRINT_SERVICE,
CONSUMER_IR_SERVICE,
//@hide: TRUST_SERVICE,
TV_INTERACTIVE_APP_SERVICE,
TV_INPUT_SERVICE,
//@hide: TV_TUNER_RESOURCE_MGR_SERVICE,
//@hide: NETWORK_SCORE_SERVICE,
USAGE_STATS_SERVICE,
MEDIA_SESSION_SERVICE,
MEDIA_COMMUNICATION_SERVICE,
BATTERY_SERVICE,
JOB_SCHEDULER_SERVICE,
//@hide: PERSISTENT_DATA_BLOCK_SERVICE,
//@hide: OEM_LOCK_SERVICE,
MEDIA_PROJECTION_SERVICE,
MIDI_SERVICE,
RADIO_SERVICE,
HARDWARE_PROPERTIES_SERVICE,
//@hide: SOUND_TRIGGER_SERVICE,
SHORTCUT_SERVICE,
//@hide: CONTEXTHUB_SERVICE,
SYSTEM_HEALTH_SERVICE,
//@hide: INCIDENT_SERVICE,
//@hide: INCIDENT_COMPANION_SERVICE,
//@hide: STATS_COMPANION_SERVICE,
COMPANION_DEVICE_SERVICE,
VIRTUAL_DEVICE_SERVICE,
CROSS_PROFILE_APPS_SERVICE,
//@hide: SYSTEM_UPDATE_SERVICE,
//@hide: TIME_DETECTOR_SERVICE,
//@hide: TIME_ZONE_DETECTOR_SERVICE,
PERMISSION_SERVICE,
LIGHTS_SERVICE,
LOCALE_SERVICE,
//@hide: PEOPLE_SERVICE,
//@hide: DEVICE_STATE_SERVICE,
//@hide: SPEECH_RECOGNITION_SERVICE,
UWB_SERVICE,
MEDIA_METRICS_SERVICE,
//@hide: ATTESTATION_VERIFICATION_SERVICE,
//@hide: SAFETY_CENTER_SERVICE,
DISPLAY_HASH_SERVICE,
CREDENTIAL_SERVICE,
DEVICE_LOCK_SERVICE,
VIRTUALIZATION_SERVICE,
GRAMMATICAL_INFLECTION_SERVICE,
})
我们只需要根据这些常量找到对应的名称即可,比如输入法:
/**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.view.inputmethod.InputMethodManager} for accessing input
* methods.
*
* @see #getSystemService(String)
*/
public static final String INPUT_METHOD_SERVICE = "input_method";
我们可以看到,其实就是通过getSystemService方法中调用的字符常量,我们要dump输入法服务相关的命令就是adb shell dumpsys input_method
如果我们想知道这个dump的方法具体在哪,会有哪些打印,则只需通过对应Mananger找到对应的ManagerService即可。
比如,我们这里以输入法为例,那么其对应的就是InputMethodManagerService,在这个里面就有对应的dump方法:
代码路径:frameworks/base/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
void dump(@NonNull PrintWriter pw, @NonNull String prefix) {
final SimpleDateFormat dataFormat =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US);
for (int i = 0; i < mEntries.length; ++i) {
final Entry entry = mEntries[(i + mNextIndex) % mEntries.length];
if (entry == null) {
continue;
}
pw.print(prefix);
pw.println("SoftInputShowHideHistory #" + entry.mSequenceNumber + ":");
pw.print(prefix);
pw.println(" time=" + dataFormat.format(new Date(entry.mWallTime))
+ " (timestamp=" + entry.mTimestamp + ")");
pw.print(prefix);
pw.print(" reason=" + InputMethodDebug.softInputDisplayReasonToString(
entry.mReason));
pw.println(" inFullscreenMode=" + entry.mInFullscreenMode);
pw.print(prefix);
pw.println(" requestClient=" + entry.mClientState);
pw.print(prefix);
pw.println(" focusedWindowName=" + entry.mFocusedWindowName);
pw.print(prefix);
pw.println(" requestWindowName=" + entry.mRequestWindowName);
pw.print(prefix);
pw.println(" imeControlTargetName=" + entry.mImeControlTargetName);
pw.print(prefix);
pw.println(" imeTargetNameFromWm=" + entry.mImeTargetNameFromWm);
pw.print(prefix);
pw.print(" editorInfo: ");
pw.print(" inputType=" + entry.mEditorInfo.inputType);
pw.print(" privateImeOptions=" + entry.mEditorInfo.privateImeOptions);
pw.println(" fieldId (viewId)=" + entry.mEditorInfo.fieldId);
pw.print(prefix);
pw.println(" focusedWindowSoftInputMode=" + InputMethodDebug.softInputModeToString(
entry.mFocusedWindowSoftInputMode));
}
}
}
有些命令是带参数的,比如:adb shell dumpsys activity top
可以加上-h来查看所有的命令,如:adb shell dumpsys activity -h
打印结果如下:
Activity manager dump options:
[-a] [-c] [-p PACKAGE] [-h] [WHAT] ...
WHAT may be one of:
a[ctivities]: activity stack state
r[recents]: recent activities state
b[roadcasts] [PACKAGE_NAME] [history [-s]]: broadcast state
broadcast-stats [PACKAGE_NAME]: aggregated broadcast statistics
i[ntents] [PACKAGE_NAME]: pending intent state
p[rocesses] [PACKAGE_NAME]: process state
o[om]: out of memory management
perm[issions]: URI permission grant state
prov[iders] [COMP_SPEC ...]: content provider state
provider [COMP_SPEC]: provider client-side state
s[ervices] [COMP_SPEC ...]: service state
allowed-associations: current package association restrictions
as[sociations]: tracked app associations
exit-info [PACKAGE_NAME]: historical process exit information
lmk: stats on low memory killer
lru: raw LRU process list
binder-proxies: stats on binder objects and IPCs
settings: currently applied config settings
service [COMP_SPEC]: service client-side state
package [PACKAGE_NAME]: all state related to given package
all: dump all activities
top: dump the top activity
users: user state
WHAT may also be a COMP_SPEC to dump activities.
COMP_SPEC may be a component name (com.foo/.myApp),
a partial substring in a component name, a
hex object identifier.
-a: include all available server state.
-c: include client state.
-p: limit output to given package.
-d: limit output to given display.
--checkin: output checkin format, resetting data.
--C: output checkin format, not resetting data.
--proto: output dump in protocol buffer format.
--dump-dumpable: dump just the DUMPABLE-related state of an activity. Use the --list-dumpables option to list the supported DUMPABLEs
--list-dumpables: show the available dumpables in an activity