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