1 /* 2 * Copyright (C) 2006 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 com.android.traceview; 18 19 import java.util.ArrayList; 20 import java.util.HashMap; 21 22 class ThreadData implements TimeLineView.Row { 23 24 private int mId; 25 private String mName; 26 private boolean mIsEmpty; 27 28 private Call mRootCall; 29 private ArrayList<Call> mStack = new ArrayList<Call>(); 30 31 // This is a hash of all the methods that are currently on the stack. 32 private HashMap<MethodData, Integer> mStackMethods = new HashMap<MethodData, Integer>(); 33 34 boolean mHaveGlobalTime; 35 long mGlobalStartTime; 36 long mGlobalEndTime; 37 38 boolean mHaveThreadTime; 39 long mThreadStartTime; 40 long mThreadEndTime; 41 42 long mThreadCurrentTime; // only used while parsing thread-cpu clock 43 ThreadData(int id, String name, MethodData topLevel)44 ThreadData(int id, String name, MethodData topLevel) { 45 mId = id; 46 mName = String.format("[%d] %s", id, name); 47 mIsEmpty = true; 48 mRootCall = new Call(this, topLevel, null); 49 mRootCall.setName(mName); 50 mStack.add(mRootCall); 51 } 52 getName()53 public String getName() { 54 return mName; 55 } 56 getRootCall()57 public Call getRootCall() { 58 return mRootCall; 59 } 60 61 /** 62 * Returns true if no calls have ever been recorded for this thread. 63 */ isEmpty()64 public boolean isEmpty() { 65 return mIsEmpty; 66 } 67 enter(MethodData method, ArrayList<TraceAction> trace)68 Call enter(MethodData method, ArrayList<TraceAction> trace) { 69 if (mIsEmpty) { 70 mIsEmpty = false; 71 if (trace != null) { 72 trace.add(new TraceAction(TraceAction.ACTION_ENTER, mRootCall)); 73 } 74 } 75 76 Call caller = top(); 77 Call call = new Call(this, method, caller); 78 mStack.add(call); 79 80 if (trace != null) { 81 trace.add(new TraceAction(TraceAction.ACTION_ENTER, call)); 82 } 83 84 Integer num = mStackMethods.get(method); 85 if (num == null) { 86 num = 0; 87 } else if (num > 0) { 88 call.setRecursive(true); 89 } 90 mStackMethods.put(method, num + 1); 91 92 return call; 93 } 94 exit(MethodData method, ArrayList<TraceAction> trace)95 Call exit(MethodData method, ArrayList<TraceAction> trace) { 96 Call call = top(); 97 if (call.mCaller == null) { 98 return null; 99 } 100 101 if (call.getMethodData() != method) { 102 String error = "Method exit (" + method.getName() 103 + ") does not match current method (" + call.getMethodData().getName() 104 + ")"; 105 throw new RuntimeException(error); 106 } 107 108 mStack.remove(mStack.size() - 1); 109 110 if (trace != null) { 111 trace.add(new TraceAction(TraceAction.ACTION_EXIT, call)); 112 } 113 114 Integer num = mStackMethods.get(method); 115 if (num != null) { 116 if (num == 1) { 117 mStackMethods.remove(method); 118 } else { 119 mStackMethods.put(method, num - 1); 120 } 121 } 122 123 return call; 124 } 125 top()126 Call top() { 127 return mStack.get(mStack.size() - 1); 128 } 129 endTrace(ArrayList<TraceAction> trace)130 void endTrace(ArrayList<TraceAction> trace) { 131 for (int i = mStack.size() - 1; i >= 1; i--) { 132 Call call = mStack.get(i); 133 call.mGlobalEndTime = mGlobalEndTime; 134 call.mThreadEndTime = mThreadEndTime; 135 if (trace != null) { 136 trace.add(new TraceAction(TraceAction.ACTION_INCOMPLETE, call)); 137 } 138 } 139 mStack.clear(); 140 mStackMethods.clear(); 141 } 142 updateRootCallTimeBounds()143 void updateRootCallTimeBounds() { 144 if (!mIsEmpty) { 145 mRootCall.mGlobalStartTime = mGlobalStartTime; 146 mRootCall.mGlobalEndTime = mGlobalEndTime; 147 mRootCall.mThreadStartTime = mThreadStartTime; 148 mRootCall.mThreadEndTime = mThreadEndTime; 149 } 150 } 151 152 @Override toString()153 public String toString() { 154 return mName; 155 } 156 getId()157 public int getId() { 158 return mId; 159 } 160 getCpuTime()161 public long getCpuTime() { 162 return mRootCall.mInclusiveCpuTime; 163 } 164 getRealTime()165 public long getRealTime() { 166 return mRootCall.mInclusiveRealTime; 167 } 168 } 169