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 53 @Override getName()54 public String getName() { 55 return mName; 56 } 57 getRootCall()58 public Call getRootCall() { 59 return mRootCall; 60 } 61 62 /** 63 * Returns true if no calls have ever been recorded for this thread. 64 */ isEmpty()65 public boolean isEmpty() { 66 return mIsEmpty; 67 } 68 enter(MethodData method, ArrayList<TraceAction> trace)69 Call enter(MethodData method, ArrayList<TraceAction> trace) { 70 if (mIsEmpty) { 71 mIsEmpty = false; 72 if (trace != null) { 73 trace.add(new TraceAction(TraceAction.ACTION_ENTER, mRootCall)); 74 } 75 } 76 77 Call caller = top(); 78 Call call = new Call(this, method, caller); 79 mStack.add(call); 80 81 if (trace != null) { 82 trace.add(new TraceAction(TraceAction.ACTION_ENTER, call)); 83 } 84 85 Integer num = mStackMethods.get(method); 86 if (num == null) { 87 num = 0; 88 } else if (num > 0) { 89 call.setRecursive(true); 90 } 91 mStackMethods.put(method, num + 1); 92 93 return call; 94 } 95 exit(MethodData method, ArrayList<TraceAction> trace)96 Call exit(MethodData method, ArrayList<TraceAction> trace) { 97 Call call = top(); 98 if (call.mCaller == null) { 99 return null; 100 } 101 102 if (call.getMethodData() != method) { 103 String error = "Method exit (" + method.getName() 104 + ") does not match current method (" + call.getMethodData().getName() 105 + ")"; 106 throw new RuntimeException(error); 107 } 108 109 mStack.remove(mStack.size() - 1); 110 111 if (trace != null) { 112 trace.add(new TraceAction(TraceAction.ACTION_EXIT, call)); 113 } 114 115 Integer num = mStackMethods.get(method); 116 if (num != null) { 117 if (num == 1) { 118 mStackMethods.remove(method); 119 } else { 120 mStackMethods.put(method, num - 1); 121 } 122 } 123 124 return call; 125 } 126 top()127 Call top() { 128 return mStack.get(mStack.size() - 1); 129 } 130 endTrace(ArrayList<TraceAction> trace)131 void endTrace(ArrayList<TraceAction> trace) { 132 for (int i = mStack.size() - 1; i >= 1; i--) { 133 Call call = mStack.get(i); 134 call.mGlobalEndTime = mGlobalEndTime; 135 call.mThreadEndTime = mThreadEndTime; 136 if (trace != null) { 137 trace.add(new TraceAction(TraceAction.ACTION_INCOMPLETE, call)); 138 } 139 } 140 mStack.clear(); 141 mStackMethods.clear(); 142 } 143 updateRootCallTimeBounds()144 void updateRootCallTimeBounds() { 145 if (!mIsEmpty) { 146 mRootCall.mGlobalStartTime = mGlobalStartTime; 147 mRootCall.mGlobalEndTime = mGlobalEndTime; 148 mRootCall.mThreadStartTime = mThreadStartTime; 149 mRootCall.mThreadEndTime = mThreadEndTime; 150 } 151 } 152 153 @Override toString()154 public String toString() { 155 return mName; 156 } 157 158 @Override getId()159 public int getId() { 160 return mId; 161 } 162 getCpuTime()163 public long getCpuTime() { 164 return mRootCall.mInclusiveCpuTime; 165 } 166 getRealTime()167 public long getRealTime() { 168 return mRootCall.mInclusiveRealTime; 169 } 170 } 171