Android event logcat的研究
经常有这样的需求:在程序A启动之后,在这个程序上覆盖一个界面,让用户输入密码后才能启动程序A,这类场景主要集中在安全软件中。
那应该怎样得知某某程序启动了,系统没有相应的广播,这很难知道程序启动了。
既然没有通知,那我们就只能用最笨的方法:主动去询问最近启动过哪些程序。
这需要用后台服务器一直跑,每隔一段时间就询问一次。程序启动的时候,会在Logcat中打印出一些日志信息,其中就有类似下面的日志,表明是启动了哪个程序
01-21 15:09:56.957: I/ActivityManager(240): START {act=android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.estrongs.android.pop/.view.FileExplorerActivity u=0} from
pid 2176
这些日志都可以通过以下代码读取到,并且提供了解析包名的相应方法:
try { int tagCode = EventLog.getTagCode("am_proc_start"); Collection<Event>(); EventLog.readEvents(new int[] { tagCode }, output); for (event : output) { // PID, UID, Process Name, Type, Component Object[] objects = (Object[]) event.getData(); ComponentName componentName = ComponentName .unflattenFromString(objects[4].toString()); String packageName = componentName.getPackageName(); Log.d(TAG, "packageName=" + packageName); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
那么你可能要问,“am_proc_start”这个Tag名是哪来的,那我们就把android.util.EventLog的代码翻出来看一下:
/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.util; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Collection; import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Access to the system diagnostic event record. System diagnostic events are * used to record certain system-level events (such as garbage collection, * activity manager state, system watchdogs, and other low level activity), * which may be automatically collected and analyzed during system development. * * <p>This is <b>not</b> the main "logcat" debugging log ({@link android.util.Log})! * These diagnostic events are for system integrators, not application authors. * * <p>Events use integer tag codes corresponding to /system/etc/event-log-tags. * They carry a payload of one or more int, long, or String values. The * event-log-tags file defines the payload contents for each type code. */ public class EventLog { /** @hide */ public EventLog() {} private static final String TAG = "EventLog"; private static final String TAGS_FILE = "/system/etc/event-log-tags"; private static final String COMMENT_PATTERN = "^\\s*(#.*)?$"; private static final String TAG_PATTERN = "^\\s*(\\d+)\\s+(\\w+)\\s*(\\(.*\\))?\\s*$"; private static HashMap<String, Integer> sTagCodes = null; private static HashMap<Integer, String> sTagNames = null; /** A previously logged event read from the logs. */ public static final class Event { private final ByteBuffer mBuffer; // Layout of event log entry received from kernel. private static final int LENGTH_OFFSET = 0; private static final int PROCESS_OFFSET = 4; private static final int THREAD_OFFSET = 8; private static final int SECONDS_OFFSET = 12; private static final int NANOSECONDS_OFFSET = 16; private static final int PAYLOAD_START = 20; private static final int TAG_OFFSET = 20; private static final int DATA_START = 24; // Value types private static final byte INT_TYPE = 0; private static final byte LONG_TYPE = 1; private static final byte STRING_TYPE = 2; private static final byte LIST_TYPE = 3; /** @param data containing event, read from the system */ /*package*/ Event(byte[] data) { mBuffer = ByteBuffer.wrap(data); mBuffer.order(ByteOrder.nativeOrder()); } /** @return the process ID which wrote the log entry */ public int getProcessId() { return mBuffer.getInt(PROCESS_OFFSET); } /** @return the thread ID which wrote the log entry */ public int getThreadId() { return mBuffer.getInt(THREAD_OFFSET); } /** @return the wall clock time when the entry was written */ public long getTimeNanos() { return mBuffer.getInt(SECONDS_OFFSET) * 1000000000l + mBuffer.getInt(NANOSECONDS_OFFSET); } /** @return the type tag code of the entry */ public int getTag() { return mBuffer.getInt(TAG_OFFSET); } /** @return one of Integer, Long, String, null, or Object[] of same. */ public synchronized Object getData() { try { mBuffer.limit(PAYLOAD_START + mBuffer.getShort(LENGTH_OFFSET)); mBuffer.position(DATA_START); // Just after the tag. return decodeObject(); } catch (IllegalArgumentException e) { Log.wtf(TAG, "Illegal entry payload: tag=" + getTag(), e); return null; } catch (BufferUnderflowException e) { Log.wtf(TAG, "Truncated entry payload: tag=" + getTag(), e); return null; } } /** @return the loggable item at the current position in mBuffer. */ private Object decodeObject() { byte type = mBuffer.get(); switch (type) { case INT_TYPE: return (Integer) mBuffer.getInt(); case LONG_TYPE: return (Long) mBuffer.getLong(); case STRING_TYPE: try { int length = mBuffer.getInt(); int start = mBuffer.position(); mBuffer.position(start + length); return new String(mBuffer.array(), start, length, "UTF-8"); } catch (UnsupportedEncodingException e) { Log.wtf(TAG, "UTF-8 is not supported", e); return null; } case LIST_TYPE: int length = mBuffer.get(); if (length < 0) length += 256; // treat as signed byte Object[] array = new Object[length]; for (int i = 0; i < length; ++i) array[i] = decodeObject(); return array; default: throw new IllegalArgumentException("Unknown entry type: " + type); } } } // We assume that the native methods deal with any concurrency issues. /** * Record an event log message. * @param tag The event type tag code * @param value A value to log * @return The number of bytes written */ public static native int writeEvent(int tag, int value); /** * Record an event log message. * @param tag The event type tag code * @param value A value to log * @return The number of bytes written */ public static native int writeEvent(int tag, long value); /** * Record an event log message. * @param tag The event type tag code * @param str A value to log * @return The number of bytes written */ public static native int writeEvent(int tag, String str); /** * Record an event log message. * @param tag The event type tag code * @param list A list of values to log * @return The number of bytes written */ public static native int writeEvent(int tag, Object... list); /** * Read events from the log, filtered by type. * @param tags to search for * @param output container to add events into * @throws IOException if something goes wrong reading events */ public static native void readEvents(int[] tags, Collection<Event> output) throws IOException; /** * Get the name associated with an event type tag code. * @param tag code to look up * @return the name of the tag, or null if no tag has that number */ public static String getTagName(int tag) { readTagsFile(); return sTagNames.get(tag); } /** * Get the event type tag code associated with an event name. * @param name of event to look up * @return the tag code, or -1 if no tag has that name */ public static int getTagCode(String name) { readTagsFile(); Integer code = sTagCodes.get(name); return code != null ? code : -1; } /** * Read TAGS_FILE, populating sTagCodes and sTagNames, if not already done. */ private static synchronized void readTagsFile() { if (sTagCodes != null && sTagNames != null) return; sTagCodes = new HashMap<String, Integer>(); sTagNames = new HashMap<Integer, String>(); Pattern comment = Pattern.compile(COMMENT_PATTERN); Pattern tag = Pattern.compile(TAG_PATTERN); BufferedReader reader = null; String line; try { reader = new BufferedReader(new FileReader(TAGS_FILE), 256); while ((line = reader.readLine()) != null) { if (comment.matcher(line).matches()) continue; Matcher m = tag.matcher(line); if (!m.matches()) { Log.wtf(TAG, "Bad entry in " + TAGS_FILE + ": " + line); continue; } try { int num = Integer.parseInt(m.group(1)); String name = m.group(2); sTagCodes.put(name, num); sTagNames.put(num, name); } catch (NumberFormatException e) { Log.wtf(TAG, "Error in " + TAGS_FILE + ": " + line, e); } } } catch (IOException e) { Log.wtf(TAG, "Error reading " + TAGS_FILE, e); // Leave the maps existing but unpopulated } finally { try { if (reader != null) reader.close(); } catch (IOException e) {} } } }
那么你可能要问,“am_proc_start”这个Tag名是哪来的,那我们就把android.util.EventLog的代码翻出来看一下:
1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.util; 18 19 import java.io.BufferedReader; 20 import java.io.FileReader; 21 import java.io.IOException; 22 import java.io.UnsupportedEncodingException; 23 import java.nio.BufferUnderflowException; 24 import java.nio.ByteBuffer; 25 import java.nio.ByteOrder; 26 import java.util.Collection; 27 import java.util.HashMap; 28 import java.util.regex.Matcher; 29 import java.util.regex.Pattern; 30 31 /** 32 * Access to the system diagnostic event record. System diagnostic events are 33 * used to record certain system-level events (such as garbage collection, 34 * activity manager state, system watchdogs, and other low level activity), 35 * which may be automatically collected and analyzed during system development. 36 * 37 * <p>This is <b>not</b> the main "logcat" debugging log ({@link android.util.Log})! 38 * These diagnostic events are for system integrators, not application authors. 39 * 40 * <p>Events use integer tag codes corresponding to /system/etc/event-log-tags. 41 * They carry a payload of one or more int, long, or String values. The 42 * event-log-tags file defines the payload contents for each type code. 43 */ 44 public class EventLog { 45 /** @hide */ public EventLog() {} 46 47 private static final String TAG = "EventLog"; 48 49 private static final String TAGS_FILE = "/system/etc/event-log-tags"; 50 private static final String COMMENT_PATTERN = "^\\s*(#.*)?$"; 51 private static final String TAG_PATTERN = "^\\s*(\\d+)\\s+(\\w+)\\s*(\\(.*\\))?\\s*$"; 52 private static HashMap<String, Integer> sTagCodes = null; 53 private static HashMap<Integer, String> sTagNames = null; 54 55 /** A previously logged event read from the logs. */ 56 public static final class Event { 57 private final ByteBuffer mBuffer; 58 59 // Layout of event log entry received from kernel. 60 private static final int LENGTH_OFFSET = 0; 61 private static final int PROCESS_OFFSET = 4; 62 private static final int THREAD_OFFSET = 8; 63 private static final int SECONDS_OFFSET = 12; 64 private static final int NANOSECONDS_OFFSET = 16; 65 66 private static final int PAYLOAD_START = 20; 67 private static final int TAG_OFFSET = 20; 68 private static final int DATA_START = 24; 69 70 // Value types 71 private static final byte INT_TYPE = 0; 72 private static final byte LONG_TYPE = 1; 73 private static final byte STRING_TYPE = 2; 74 private static final byte LIST_TYPE = 3; 75 76 /** @param data containing event, read from the system */ 77 /*package*/ Event(byte[] data) { 78 mBuffer = ByteBuffer.wrap(data); 79 mBuffer.order(ByteOrder.nativeOrder()); 80 } 81 82 /** @return the process ID which wrote the log entry */ 83 public int getProcessId() { 84 return mBuffer.getInt(PROCESS_OFFSET); 85 } 86 87 /** @return the thread ID which wrote the log entry */ 88 public int getThreadId() { 89 return mBuffer.getInt(THREAD_OFFSET); 90 } 91 92 /** @return the wall clock time when the entry was written */ 93 public long getTimeNanos() { 94 return mBuffer.getInt(SECONDS_OFFSET) * 1000000000l 95 + mBuffer.getInt(NANOSECONDS_OFFSET); 96 } 97 98 /** @return the type tag code of the entry */ 99 public int getTag() { 100 return mBuffer.getInt(TAG_OFFSET); 101 } 102 103 /** @return one of Integer, Long, String, null, or Object[] of same. */ 104 public synchronized Object getData() { 105 try { 106 mBuffer.limit(PAYLOAD_START + mBuffer.getShort(LENGTH_OFFSET)); 107 mBuffer.position(DATA_START); // Just after the tag. 108 return decodeObject(); 109 } catch (IllegalArgumentException e) { 110 Log.wtf(TAG, "Illegal entry payload: tag=" + getTag(), e); 111 return null; 112 } catch (BufferUnderflowException e) { 113 Log.wtf(TAG, "Truncated entry payload: tag=" + getTag(), e); 114 return null; 115 } 116 } 117 118 /** @return the loggable item at the current position in mBuffer. */ 119 private Object decodeObject() { 120 byte type = mBuffer.get(); 121 switch (type) { 122 case INT_TYPE: 123 return (Integer) mBuffer.getInt(); 124 125 case LONG_TYPE: 126 return (Long) mBuffer.getLong(); 127 128 case STRING_TYPE: 129 try { 130 int length = mBuffer.getInt(); 131 int start = mBuffer.position(); 132 mBuffer.position(start + length); 133 return new String(mBuffer.array(), start, length, "UTF-8"); 134 } catch (UnsupportedEncodingException e) { 135 Log.wtf(TAG, "UTF-8 is not supported", e); 136 return null; 137 } 138 139 case LIST_TYPE: 140 int length = mBuffer.get(); 141 if (length < 0) length += 256; // treat as signed byte 142 Object[] array = new Object[length]; 143 for (int i = 0; i < length; ++i) array[i] = decodeObject(); 144 return array; 145 146 default: 147 throw new IllegalArgumentException("Unknown entry type: " + type); 148 } 149 } 150 } 151 152 // We assume that the native methods deal with any concurrency issues. 153 154 /** 155 * Record an event log message. 156 * @param tag The event type tag code 157 * @param value A value to log 158 * @return The number of bytes written 159 */ 160 public static native int writeEvent(int tag, int value); 161 162 /** 163 * Record an event log message. 164 * @param tag The event type tag code 165 * @param value A value to log 166 * @return The number of bytes written 167 */ 168 public static native int writeEvent(int tag, long value); 169 170 /** 171 * Record an event log message. 172 * @param tag The event type tag code 173 * @param str A value to log 174 * @return The number of bytes written 175 */ 176 public static native int writeEvent(int tag, String str); 177 178 /** 179 * Record an event log message. 180 * @param tag The event type tag code 181 * @param list A list of values to log 182 * @return The number of bytes written 183 */ 184 public static native int writeEvent(int tag, Object... list); 185 186 /** 187 * Read events from the log, filtered by type. 188 * @param tags to search for 189 * @param output container to add events into 190 * @throws IOException if something goes wrong reading events 191 */ 192 public static native void readEvents(int[] tags, Collection<Event> output) 193 throws IOException; 194 195 /** 196 * Get the name associated with an event type tag code. 197 * @param tag code to look up 198 * @return the name of the tag, or null if no tag has that number 199 */ 200 public static String getTagName(int tag) { 201 readTagsFile(); 202 return sTagNames.get(tag); 203 } 204 205 /** 206 * Get the event type tag code associated with an event name. 207 * @param name of event to look up 208 * @return the tag code, or -1 if no tag has that name 209 */ 210 public static int getTagCode(String name) { 211 readTagsFile(); 212 Integer code = sTagCodes.get(name); 213 return code != null ? code : -1; 214 } 215 216 /** 217 * Read TAGS_FILE, populating sTagCodes and sTagNames, if not already done. 218 */ 219 private static synchronized void readTagsFile() { 220 if (sTagCodes != null && sTagNames != null) return; 221 222 sTagCodes = new HashMap<String, Integer>(); 223 sTagNames = new HashMap<Integer, String>(); 224 225 Pattern comment = Pattern.compile(COMMENT_PATTERN); 226 Pattern tag = Pattern.compile(TAG_PATTERN); 227 BufferedReader reader = null; 228 String line; 229 230 try { 231 reader = new BufferedReader(new FileReader(TAGS_FILE), 256); 232 while ((line = reader.readLine()) != null) { 233 if (comment.matcher(line).matches()) continue; 234 235 Matcher m = tag.matcher(line); 236 if (!m.matches()) { 237 Log.wtf(TAG, "Bad entry in " + TAGS_FILE + ": " + line); 238 continue; 239 } 240 241 try { 242 int num = Integer.parseInt(m.group(1)); 243 String name = m.group(2); 244 sTagCodes.put(name, num); 245 sTagNames.put(num, name); 246 } catch (NumberFormatException e) { 247 Log.wtf(TAG, "Error in " + TAGS_FILE + ": " + line, e); 248 } 249 } 250 } catch (IOException e) { 251 Log.wtf(TAG, "Error reading " + TAGS_FILE, e); 252 // Leave the maps existing but unpopulated 253 } finally { 254 try { if (reader != null) reader.close(); } catch (IOException e) {} 255 } 256 } 257 }
发现EventLog的Tag名称来自一个文件/system/etc/log-tags,文件内容列出来,就可以看到已经定义好的各种Tag,这样子,想监听哪些事件,都可以一目了然了。
42 answer (to life the universe etc|3) 314 pi 2718 e 2719 configuration_changed (config mask|1|5) 2720 sync (id|3),(activity (Token|1|5),(Task ID|1|5),(Component Name|3),(Reason|3) 30002 am_task_to_front (Task|1|5) 30003 am_new_intent (Token|1|5),(Task ID|1|5),(Component Name|3),(Action|3),(MIME Type|3),(URI|3),(Flags|1|5) 30004 am_create_task (Task ID|1|5) 30005 am_create_activity (Token|1|5),(Task ID|1|5),(Component Name|3) 30007 am_resume_activity_launch_time (Token|1|5),(Component Name|3),(time|2|3) 30010 am_proc_bound (PID|1|5),(Process Name|3) 30011 am_proc_died (PID|1|5),(Process Name|3) 30012 am_failed_to_pause (Token|1|5),(Wanting to pause|3),(Currently pausing|3) 30013 am_pause_activity (Token|1|5),(Task ID|1|5),(Component Name|3),(Reason|3) 30019 am_relaunch_resume_activity (Token|1|5),(Task ID|1|5),(Component Name|3) 30021 am_on_paused_called (Component Name|3) 30022 am_on_resume_called (Component Name|3) 30023 am_kill (PID|1|5),(Process Name|3),(OomAdj|1|5),(Reason|3) 30024 am_broadcast_discard_filter (Broadcast|1|5),(Action|3),(Receiver Number|1|1),(BroadcastFilter|1|5) 30025 am_broadcast_discard_app (Broadcast|1|5),(Action|3),(Receiver Number|1|1),(App|3) 30030 am_create_service (Service Record|1|5),(Name|3),(Intent|3),(PID|1|5) 30031 am_destroy_service (Service Record|1|5),(Name|3),(PID|1|5) 30032 am_process_crashed_too_much (Name|3),(PID|1|5) 30033 am_drop_process (PID|1|5) 30034 am_service_crashed_too_much (Crash Count|1|1),(Component Name|3),(PID|1|5) 30035 am_schedule_service_restart (Component Name|3),(Time|2|3) 30036 am_provider_lost_process (Package Name|3),(UID|1|5),(Name|3) 30037 am_process_start_timeout (PID|1|5),(UID|1|5),(Process Name|3) 30039 am_crash (PID|1|5),(Process Name|3),(Flags|1|5),(Exception|3),(Message|3),(File|3),(Line|1|5) 30040 am_wtf (PID|1|5),(Process Name|3),(Flags|1|5),(Tag|3),(Message|3) 31000 wm_no_surface_memory (Window|3),(PID|1|5),(Operation|3) 32000 imf_force_reconnect_ime (IME|4),(Time Since Connect|2|3),(Showing|1|1) 50000 menu_item_selected (Menu type where 0 is options and 1 is context|1|5),(Menu item title|3) 50001 menu_opened (Menu type where 0 is options and 1 is context|1|5) 50020 connectivity_state_changed (custom|1|5) 50021 wifi_state_changed (wifi_state|3) 50022 wifi_event|1|5) 50023 wifi_supplicant_state_changed (supplicant_state|1|5) 50100 pdp_bad_dns_address (dns_address|3) 50101 pdp_radio_reset_countdown_triggered (out_packet_count|1|1) 50102 pdp_radio_reset (out_packet_count|1|1) 50103 pdp_context_reset (out_packet_count|1|1) 50104 pdp_reregister_network (out_packet_count|1|1) 50105 pdp_setup_fail (cause|1|5), (cid|1|5), (network_type|1|5) 50106 call_drop (cause|1|5), (cid|1|5), (network_type|1|5) 50107 data_network_registration_fail (op_numeric|1|5), (cid|1|5) 50108 data_network_status_on_radio_off (dc_state|3), (enable|1|5) 50109 pdp_network_drop (cid|1|5), (network_type|1|5) 50110 cdma_data_setup_failed (cause|1|5), (cid|1|5), (network_type|1|5) 50111 cdma_data_drop (cid|1|5), (network_type|1|5) 50112 gsm_rat_switched (cid|1|5), (network_from|1|5), (network_to|1|5) 50113 gsm_data_state_change (oldState|3), (newState|3) 50114 gsm_service_state_change (oldState|1|5), (oldGprsState|1|5), (newState|1|5), (newGprsState|1|5) 50115 cdma_data_state_change (oldState|3), (newState|3) 50116 cdma_service_state_change (oldState|1|5), (oldDataState|1|5), (newState|1|5), (newDataState|1|5) 50117 bad_ip_address (ip_address|3) 50118 data_stall_recovery_get_data_call_list (out_packet_count|1|1) 50119 data_stall_recovery_cleanup (out_packet_count|1|1) 50120 data_stall_recovery_reregister (out_packet_count|1|1) 50121 data_stall_recovery_radio_restart (out_packet_count|1|1) 50122 data_stall_recovery_radio_restart_with_prop (out_packet_count|1|1) 51000 socket_stats (send|1|2),(recv|1|2),(ip|1|5),(port|1|5),(close|1|5) 51100 netstats_mobile_sample (dev_rx_bytes|2|2),(dev_tx_bytes|2|2),(dev_rx_pkts|2|1),(dev_tx_pkts|2|1),(xt_rx_bytes|2|2),(xt_tx_bytes|2|2),(xt_rx_pkts|2|1),(xt_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1),(trusted_time|2|3) 51101 netstats_wifi_sample (dev_rx_bytes|2|2),(dev_tx_bytes|2|2),(dev_rx_pkts|2|1),(dev_tx_pkts|2|1),(xt_rx_bytes|2|2),(xt_tx_bytes|2|2),(xt_rx_pkts|2|1),(xt_tx_pkts|2|1),(uid_rx_bytes|2|2),(uid_tx_bytes|2|2),(uid_rx_pkts|2|1),(uid_tx_pkts|2|1),(trusted_time|2|3) 52000 db_sample (db|3),(sql|3),(time|1|3),(blocking_package|3),(sample_percent|1|6) 52001 http_stats (useragent|3),(response|2|3),(processing|2|3),(tx|1|2),(rx|1|2) 52002 content_query_sample (uri|3),(projection|3),(selection|3),(sortorder|3),(time|1|3),(blocking_package|3),(sample_percent|1|6) 52003 content_update_sample (uri|3),(operation|3),(selection|3),(time|1|3),(blocking_package|3),(sample_percent|1|6) 52004 binder_sample (descriptor|3),(method_num|1|5),(time|1|3),(blocking_package|3),(sample_percent|1|6) 60000 viewroot_draw (Draw time|1|3) 60001 viewroot_layout (Layout time|1|3) 60002 view_build_drawing_cache (View created drawing cache|1|5) 60003 view_use_drawing_cache (View drawn using bitmap cache|1|5) 60100 sf_app_dequeue_before (buffer|1),(identity|1),(time|2) 60101 sf_app_dequeue_after (buffer|1),(identity|1),(time|2) 60102 sf_app_lock_before (buffer|1),(identity|1),(time|2) 60103 sf_app_lock_after (buffer|1),(identity|1),(time|2) 60104 sf_app_queue (buffer|1),(identity|1),(time|2) 60105 sf_repaint (buffer|1),(time|2) 60106 sf_composition_complete (buffer|1),(time|2) 60107 sf_unlock_clients (buffer|1),(time|2) 60108 sf_swapbuffers (buffer|1),(time|2) 60109 sf_repaint_done (buffer|1),(time|2) 60110 sf_fb_post_before (buffer|1),(time|2) 60111 sf_fb_post_after (buffer|1),(time|2) 60112 sf_fb_dequeue_before (buffer|1),(time|2) 60113 sf_fb_dequeue_after (buffer|1),(time|2) 60114 sf_fb_lock_before (buffer|1),(time|2) 60115 sf_fb_lock_after (buffer|1),(time|2) 65537 netlink_failure (uid|1) 70000 screen_toggled (screen_state|1|5) 70101 browser_zoom_level_change (start level|1|5),(end level|1|5),(time|2|3) 70102 browser_double_tap_duration (duration|1|3),(time|2|3) 70103 browser_bookmark_added (url|3), (where|3) 70104 browser_page_loaded (url|3), (time|2|3) 70105 browser_timeonpage (url|3), (time|2|3) 70150 browser_snap_center 70151 browser_text_size_change (oldSize|1|5), (newSize|1|5) 70200 aggregation (aggregation time|2|3) 70201 aggregation_test (field1|1|2),(field2|1|2),(field3|1|2),(field4|1|2),(field5|1|2) 70301 phone_ui_enter 70302 phone_ui_exit 70303 phone_ui_button_click (text|3) 70304 phone_ui_ringer_query_elapsed 70305 phone_ui_multiple_query 71001 qsb_start (name|3),(version|1),(start_method|3),(latency|1|3),(search_source|3),(enabled_sources|3),(on_create_latency|1|3) 71002 qsb_click (id|2),(suggestions|3),(queried_sources|3),(num_chars|1),(click_type|1) 71003 qsb_search (search_source|3),(method|1),(num_chars|1) 71004 qsb_voice_search (search_source|3) 71005 qsb_exit (suggestions|3),(num_chars|1) 71006 qsb_latency (corpus|3),(latency|1|3),(num_chars|1) 74000 music_start_playback_requested (track_id|1|5) (source_id|3|50) (cache_hit|1|5) 74001 music_stop_playback_requested (track_id|1|5) (source_id|3|50) 74002 music_pause_playback_requested (track_id|1|5) (source_id|3|50) 74003 music_download_status (track_id|1|5) (source_id|3|50) (status|1|5) (data|1|5) (latency|1|5) (network_type|1|5) (network_subtype|1|5) (download_type|1|5) 74004 music_track_saved_as_ringtone (track_id|1|5) (source_id|3|50) (type|1|5) 75000 sqlite_mem_alarm_current (current|1|2) 75001 sqlite_mem_alarm_max (max|1|2) 75002 sqlite_mem_alarm_alloc_attempt (attempts|1|4) 75003 sqlite_mem_released (Memory released|1|2) 75004 sqlite_db_corrupt (Database file corrupt|3) 76001 tts_speak_success (engine|3),(caller_uid|1),(caller_pid|1),(length|1),(locale|3),(rate|1),(pitch|1),(engine_latency|2|3),(engine_total|2|3),(audio_latency|2|3) 76002 tts_speak_failure (engine|3),(caller_uid|1),(caller_pid|1),(length|1),(locale|3),(rate|1),(pitch|1) 78001 dispatchCommand_overflow 90000 nfc_first_share 90001 nfc_share (size|1|2),(tnf|1),(type|3),(aar_present|1),(duration|1|3) 90002 nfc_share_fail (size|1|2),(tnf|1),(type|3),(aar_present|1) 90003 nfc_ndef_received (size|1|2),(tnf|1),(type|3),(aar_present|1) 201001 system_update (status|1|5),(download_result|1|5),(bytes|2|2),(url|3) 201002 system_update_user (action|3) 202001 vending_reconstruct (changes|1) 202901 transaction_event (data|3) 203001 sync_details (authority|3),(send|1|2),(recv|1|2),(details|3) 203002 google_http_request (elapsed|2|3),(status|1),(appname|3),(reused|1) 204001 gtalkservice (eventType|1) 204002 gtalk_connection (status|1) 204003 gtalk_conn_close (status|1),(duration|1) 204004 gtalk_heartbeat_reset (interval_and_nt|1),(ip|3) 204005 c2dm (packet_type|1),(persistent_id|3),(stream_id|1),(last_stream_id|1) 205001 setup_server_timeout 205002 setup_required_captcha (action|3) 205003 setup_io_error (status|3) 205004 setup_server_error 205005 setup_retries_exhausted 205006 setup_no_data_network 205007 setup_completed 205008 gls_account_tried (status|1) 205009 gls_account_saved (status|1) 205010 gls_authenticate (status|1),(service|3) 205011 google_mail_switch (direction|1) 206002 gmail_perf_end (action|3),(cpu_time|1|3),(wall_time|1|3),(num_sub_iteration|1)