1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2008 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License. 6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at 7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License. 15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/** 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * One line from the loaded-classes file. 19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiclass Record { 21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * The delimiter character we use, {@code :}, conflicts with some other 24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * names. In that case, manually replace the delimiter with something else. 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private static final String[] REPLACE_CLASSES = { 27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.apps.maps:FriendService", 28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.apps.maps\\u003AFriendService", 29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.apps.maps:driveabout", 30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.apps.maps\\u003Adriveabout", 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.apps.maps:GoogleLocationService", 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.apps.maps\\u003AGoogleLocationService", 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.apps.maps:LocationFriendService", 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.apps.maps\\u003ALocationFriendService", 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.apps.maps:MapsBackgroundService", 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.apps.maps\\u003AMapsBackgroundService", 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.apps.maps:NetworkLocationService", 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.apps.maps\\u003ANetworkLocationService", 39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.android.chrome:sandboxed_process", 40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.android.chrome\\u003Asandboxed_process", 41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.android.fakeoemfeatures:background", 42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.android.fakeoemfeatures\\u003Abackground", 43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.android.fakeoemfeatures:core", 44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.android.fakeoemfeatures\\u003Acore", 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.android.launcher:wallpaper_chooser", 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.android.launcher\\u003Awallpaper_chooser", 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.android.nfc:handover", 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.android.nfc\\u003Ahandover", 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.music:main", 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.music\\u003Amain", 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.music:ui", 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.music\\u003Aui", 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.setupwarlock:broker", 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.google.android.setupwarlock\\u003Abroker", 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "mobi.mgeek.TunnyBrowser:DolphinNotification", 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "mobi.mgeek.TunnyBrowser\\u003ADolphinNotification", 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.qo.android.sp.oem:Quickword", 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "com.qo.android.sp.oem\\u003AQuickword", 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "android:ui", 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "android\\u003Aui", 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "system:ui", 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "system\\u003Aui", 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski }; 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski enum Type { 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** Start of initialization. */ 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski START_LOAD, 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** End of initialization. */ 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski END_LOAD, 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** Start of initialization. */ 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski START_INIT, 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** End of initialization. */ 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski END_INIT 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** Parent process ID. */ 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski final int ppid; 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** Process ID. */ 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski final int pid; 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** Thread ID. */ 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski final int tid; 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** Process name. */ 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski final String processName; 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** Class loader pointer. */ 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski final int classLoader; 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** Type of record. */ 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski final Type type; 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** Name of loaded class. */ 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski final String className; 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** Record time (ns). */ 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski final long time; 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** Source file line# */ 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int sourceLineNumber; 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Parses a line from the loaded-classes file. 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Record(String line, int lineNum) { 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char typeChar = line.charAt(0); 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski switch (typeChar) { 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case '>': type = Type.START_LOAD; break; 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case '<': type = Type.END_LOAD; break; 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case '+': type = Type.START_INIT; break; 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case '-': type = Type.END_INIT; break; 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski default: throw new AssertionError("Bad line: " + line); 117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski sourceLineNumber = lineNum; 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 0; i < REPLACE_CLASSES.length; i+= 2) { 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski line = line.replace(REPLACE_CLASSES[i], REPLACE_CLASSES[i+1]); 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski line = line.substring(1); 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String[] parts = line.split(":"); 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ppid = Integer.parseInt(parts[0]); 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski pid = Integer.parseInt(parts[1]); 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski tid = Integer.parseInt(parts[2]); 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski processName = decode(parts[3]).intern(); 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski classLoader = Integer.parseInt(parts[4]); 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski className = vmTypeToLanguage(decode(parts[5])).intern(); 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski time = Long.parseLong(parts[6]); 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Decode any escaping that may have been written to the log line. 142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Supports unicode-style escaping: \\uXXXX = character in hex 144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param rawField the field as it was written into the log 146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @result the same field with any escaped characters replaced 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String decode(String rawField) { 149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String result = rawField; 150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int offset = result.indexOf("\\u"); 151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski while (offset >= 0) { 152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String before = result.substring(0, offset); 153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String escaped = result.substring(offset+2, offset+6); 154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String after = result.substring(offset+6); 155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski result = String.format("%s%c%s", before, Integer.parseInt(escaped, 16), after); 157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // find another but don't recurse 159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski offset = result.indexOf("\\u", offset + 1); 160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return result; 162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Converts a VM-style name to a language-style name. 166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String vmTypeToLanguage(String typeName) { 168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // if the typename is (null), just return it as-is. This is probably in dexopt and 169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // will be discarded anyway. NOTE: This corresponds to the case in dalvik/vm/oo/Class.c 170282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // where dvmLinkClass() returns false and we clean up and exit. 171282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if ("(null)".equals(typeName)) { 172282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return typeName; 173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!typeName.startsWith("L") || !typeName.endsWith(";") ) { 176282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new AssertionError("Bad name: " + typeName + " in line " + sourceLineNumber); 177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski typeName = typeName.substring(1, typeName.length() - 1); 180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return typeName.replace("/", "."); 181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 183