1 /* 2 * Copyright (C) 2008 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 import java.util.List; 18 import java.util.ArrayList; 19 import java.util.LinkedList; 20 import java.util.Map; 21 import java.util.HashMap; 22 import java.io.Serializable; 23 24 /** 25 * A Dalvik process. 26 */ 27 class Proc implements Serializable { 28 29 private static final long serialVersionUID = 0; 30 31 /** Parent process. */ 32 final Proc parent; 33 34 /** Process ID. */ 35 final int id; 36 37 /** 38 * Name of this process. We may not have the correct name at first, i.e. 39 * some classes could have been loaded before the process name was set. 40 */ 41 String name; 42 43 /** Child processes. */ 44 final List<Proc> children = new ArrayList<Proc>(); 45 46 /** Maps thread ID to operation stack. */ 47 transient final Map<Integer, LinkedList<Operation>> stacks 48 = new HashMap<Integer, LinkedList<Operation>>(); 49 50 /** Number of operations. */ 51 int operationCount; 52 53 /** Sequential list of operations that happened in this process. */ 54 final List<Operation> operations = new ArrayList<Operation>(); 55 56 /** List of past process names. */ 57 final List<String> nameHistory = new ArrayList<String>(); 58 59 /** Constructs a new process. */ Proc(Proc parent, int id)60 Proc(Proc parent, int id) { 61 this.parent = parent; 62 this.id = id; 63 } 64 65 /** Sets name of this process. */ setName(String name)66 void setName(String name) { 67 if (!name.equals(this.name)) { 68 if (this.name != null) { 69 nameHistory.add(this.name); 70 } 71 this.name = name; 72 } 73 } 74 75 /** 76 * Returns true if this process comes from the zygote. 77 */ fromZygote()78 public boolean fromZygote() { 79 return parent != null && parent.name.equals("zygote") 80 && !name.equals("com.android.development"); 81 } 82 83 /** 84 * Starts an operation. 85 * 86 * @param threadId thread the operation started in 87 * @param loadedClass class operation happened to 88 * @param time the operation started 89 */ startOperation(int threadId, LoadedClass loadedClass, long time, Operation.Type type)90 void startOperation(int threadId, LoadedClass loadedClass, long time, 91 Operation.Type type) { 92 Operation o = new Operation( 93 this, loadedClass, time, operationCount++, type); 94 operations.add(o); 95 96 LinkedList<Operation> stack = stacks.get(threadId); 97 if (stack == null) { 98 stack = new LinkedList<Operation>(); 99 stacks.put(threadId, stack); 100 } 101 102 if (!stack.isEmpty()) { 103 stack.getLast().subops.add(o); 104 } 105 106 stack.add(o); 107 } 108 109 /** 110 * Ends an operation. 111 * 112 * @param threadId thread the operation ended in 113 * @param loadedClass class operation happened to 114 * @param time the operation ended 115 */ endOperation(int threadId, String className, LoadedClass loadedClass, long time)116 Operation endOperation(int threadId, String className, 117 LoadedClass loadedClass, long time) { 118 LinkedList<Operation> stack = stacks.get(threadId); 119 120 if (stack == null || stack.isEmpty()) { 121 didNotStart(className); 122 return null; 123 } 124 125 Operation o = stack.getLast(); 126 if (loadedClass != o.loadedClass) { 127 didNotStart(className); 128 return null; 129 } 130 131 stack.removeLast(); 132 133 o.endTimeNanos = time; 134 return o; 135 } 136 137 /** 138 * Prints an error indicating that we saw the end of an operation but not 139 * the start. A bug in the logging framework which results in dropped logs 140 * causes this. 141 */ didNotStart(String name)142 private static void didNotStart(String name) { 143 System.err.println("Warning: An operation ended on " + name 144 + " but it never started!"); 145 } 146 147 /** 148 * Prints this process tree to stdout. 149 */ print()150 void print() { 151 print(""); 152 } 153 154 /** 155 * Prints a child proc to standard out. 156 */ print(String prefix)157 private void print(String prefix) { 158 System.out.println(prefix + "id=" + id + ", name=" + name); 159 for (Proc child : children) { 160 child.print(prefix + " "); 161 } 162 } 163 164 @Override toString()165 public String toString() { 166 return this.name; 167 } 168 } 169