概述
在分析Android系统的过程中,经常会看到在系统的关键点打印EventLog日志,并且可以通过adb shell logcat -b events
获取logcat中关于events的日志。现在分析一下events的逻辑,方便于以后定位问题和优化系统。
相关源码说明
EventLog.java
EventLog.java的文件目录为 frameworks/base/core/java/android/util/EventLog.java
,这个文件代替了系统中原有的frameworks/base/core/java/android/util/EventLogTags.java
文件,EventLogTags.java已经被舍弃。EventLog类中用来读写数据的都在native方法中实现,如下
// We assume that the native methods deal with any concurrency issues.
public static native int writeEvent(int tag, int value);
public static native int writeEvent(int tag, long value);
public static native int writeEvent(int tag, float value);
public static native int writeEvent(int tag, String str);
public static native int writeEvent(int tag, Object... list);
public static native void readEvents(int[] tags, Collection<Event> output)
其中tag是通过readTagsFile从/system/etc/event-log-tags
文件中读取的,关于event-log-tags文件下面详细说明;读取的tag内容保存在EventLog的成员变量sTagCodes、sTagNames两个HashMap中,之所以把同一对num和name保存在两个map中,是为了方便查找。
sTagCodes.put(name, num);
sTagNames.put(num, name);
event-log-tags
文件event-log-tags位于手机的/system/etc/下面,用来定义手机支持的所有事件,以下是部分事件:
42 answer (to life the universe etc|3)
314 pi
1003 auditd (avc|3)
1004 logd (dropped|3)
1005 liblog (dropped|1)
2718 e
2719 configuration_changed (config mask|1|5)
2720 sync (id|3),(event|1|5),(source|1|5),(account|1|5)
2721 cpu (total|1|6),(user|1|6),(system|1|6),(iowait|1|6),(irq|1|6),(softirq|1|6)
2722 battery_level (level|1|6),(voltage|1|1),(temperature|1|1)
2723 battery_status (status|1|5),(health|1|5),(present|1|5),(plugged|1|5),(technology|3)
2724 power_sleep_requested (wakeLocksCleared|1|1)
2725 power_screen_broadcast_send (wakelockCount|1|1)
2726 power_screen_broadcast_done (on|1|5),(broadcastDuration|2|3),(wakelockCount|1|1)
2727 power_screen_broadcast_stop (which|1|5),(wakelockCount|1|1)
2728 power_screen_state (offOrOn|1|5),(becauseOfUser|1|5),(totalTouchDownTime|2|3),(touchCycles|1|1)
2729 power_partial_wake_state (releasedorAcquired|1|5),(tag|3)
2730 battery_discharge (duration|2|3),(minLevel|1|6),(maxLevel|1|6)
2731 power_soft_sleep_requested (savedwaketimems|2)
2740 location_controller
2741 force_gc (reason|3)
2742 tickle (authority|3)
2744 free_storage_changed (data|2|2)
2745 low_storage (data|2|2)
2746 free_storage_left (data|2|2),(system|2|2),(cache|2|2)
2747 contacts_aggregation (aggregation time|2|3), (count|1|1)
2748 cache_file_deleted (path|3)
EventLogTags.logtags
通过命令find frameworks/ -type f -name "EventLogTags.logtags"
搜索EventLogTags.logtags文件,可以发现在系统的frameworks目录下的不同目录中有很多EventLogTags.logtags文件:
feng@feng-pc:android_mtk_n_6757_66_mp5$ find frameworks/ -type f -name "EventLogTags.logtags"
frameworks/base/packages/SystemUI/src/com/android/systemui/EventLogTags.logtags
frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/EventLogTags.logtags
frameworks/base/services/core/java/com/android/server/EventLogTags.logtags
frameworks/base/services/core/java/com/android/server/am/EventLogTags.logtags
frameworks/base/core/java/android/speech/tts/EventLogTags.logtags
frameworks/base/core/java/android/webkit/EventLogTags.logtags
frameworks/base/core/java/android/content/EventLogTags.logtags
frameworks/base/core/java/com/android/internal/logging/EventLogTags.logtags
frameworks/native/services/surfaceflinger/EventLog/EventLogTags.logtags
frameworks/opt/telephony/src/java/com/android/internal/telephony/EventLogTags.logtags
这些文件都是定义的某一类的事件,通过和event-log-tags文件对比发现,这些定义的事件是event-log-tags事件的子集,由此可知event-log-tags文件是依赖于.logtags文件生成的,只不过 .logtags文件中有对事件的注释说明,所以在定位问题的时候可以参考 *.logtags文件中的注释。
疑问:我们在看源码的时候发现tag经常引用的宏EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
这个宏是如何与事件的num对应起来的呢?在编译系统的时候python脚本build/tools/java-event-log-tags.py负责将EventLogTags.logtags文件转化为标准的java,同时生成/system/etc/event-log-tags文件,比如frameworks/base/services/core/java/com/android/server/am/EventLogTags.logtags
文件生成的对应文件为out/target/common/obj/JAVA_LIBRARIES/services.core_intermediates/src/java/com/android/server/am/EventLogTags.java
event.logtags
event.logtags文件位于系统源码的system/core/logcat/目录下,它对EventLogTags.logtags文件内容加以解释:
# The entries in this file map a sparse set of log tag numbers to tag names.
# This is installed on the device, in /system/etc, and parsed by logcat.
#
# Tag numbers are decimal integers, from 0 to 2^31. (Let's leave the
# negative values alone for now.)
# Tag numbers是十进制的整数,取值从0到2^31
# Tag names are one or more ASCII letters and numbers or underscores, i.e.
# "[A-Z][a-z][0-9]_". Do not include spaces or punctuation (the former
# impacts log readability, the latter makes regex searches more annoying).
#
# Tag names由1到多个ASCII码的字母和下划线组成,为了方便在log中搜索,name中避免使用空格和标点
# Tag numbers and names are separated by whitespace. Blank lines and lines
# starting with '#' are ignored.
#
# Optionally, after the tag names can be put a description for the value(s)
# of the tag. Description are in the format
# (<name>|data type[|data unit])
(<名字>|数据类型[|数据单位])
# Multiple values are separated by commas.
#
# The data type is a number from the following values:
# 1: int
# 2: long
# 3: string
# 4: list
# 5: float
#
# The data unit is a number taken from the following list:
# 1: Number of objects 对象个数
# 2: Number of bytes 字节个数
# 3: Number of milliseconds 毫秒
# 4: Number of allocations 分配个数
# 5: Id
# 6: Percent 百分比
# Default value for data of type int/long is 2 (bytes).
#
# TODO: generate ".java" and ".h" files with integer constants from this file.
# These are used for testing, do not modify without updating
# tests/framework-tests/src/android/util/EventLogFunctionalTest.java.
日志分析
通过adb shell logcat -b events
输出events日志,一下是部分内容,我们以am_kill为例说明一下日志意义:
05-01 10:42:24.115 1426 2617 I am_proc_bound: [0,6180,com.gionee.change]
05-01 10:42:24.625 1426 1654 I am_kill : [0,4060,com.mediatek.connectivity,906,empty for 5978s]
05-01 10:42:24.681 1426 2433 I am_proc_died: [0,4060,com.mediatek.connectivity]
05-01 10:42:25.142 1426 1709 I am_proc_start: [0,6207,10009,com.gionee.account,content provider,com.gionee.account/.GnAccountProvider]
- 在Android源码的EventLogTags.logtags文件中获取注释和定义,同时可以知道这是哪一类事件,方便在源码中查找事件的调用,由搜索结果可知此是am事件,所以可以在am源码内搜索事件在那个地方调用了:
# Kill a process to reclaim memory.
30023 am_kill (User|1|5),(PID|1|5),(Process Name|3),(OomAdj|1|5),(Reason|3) 如果想知道这个事件是在源码的那个地方调用的,可以源码中out目录下的EventLogTags.java文件中搜索30023,
/** 30023 am_kill (User|1|5),(PID|1|5),(Process Name|3),(OomAdj|1|5),(Reason|3) */
public static final int AM_KILL = 30023;在am源码下搜索AM_KILL宏,可知:
ProcessRecord.java
597: EventLog.writeEvent(EventLogTags.AM_KILL, userId, pid, processName, setAdj, reason);