blob: 21050218ff8c56d0610042dfe7dd82f2d0188f6a [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017import java.util.List;
18import java.util.ArrayList;
19import java.util.LinkedList;
20import java.util.Map;
21import java.util.HashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import java.io.Serializable;
23
24/**
25 * A Dalvik process.
26 */
27class Proc implements Serializable {
28
29 private static final long serialVersionUID = 0;
30
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031 /** 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. */
60 Proc(Proc parent, int id) {
61 this.parent = parent;
62 this.id = id;
63 }
64
65 /** Sets name of this process. */
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 /**
Bob Lee9d2d6e12009-08-13 14:41:54 -070076 * Returns true if this process comes from the zygote.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077 */
Bob Lee9d2d6e12009-08-13 14:41:54 -070078 public boolean fromZygote() {
79 return parent != null && parent.name.equals("zygote")
80 && !name.equals("com.android.development");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 }
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 */
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 */
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 */
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 */
150 void print() {
151 print("");
152 }
153
154 /**
155 * Prints a child proc to standard out.
156 */
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
165 public String toString() {
166 return this.name;
167 }
168}