• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.android.hierarchyviewerlib.device;
18 
19 import org.eclipse.swt.graphics.Image;
20 
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.Comparator;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Set;
28 import java.util.TreeSet;
29 
30 public class ViewNode {
31 
32     public static enum ProfileRating {
33         RED, YELLOW, GREEN, NONE
34     };
35 
36     private static final double RED_THRESHOLD = 0.8;
37 
38     private static final double YELLOW_THRESHOLD = 0.5;
39 
40     public static final String MISCELLANIOUS = "miscellaneous";
41 
42     public String id;
43 
44     public String name;
45 
46     public String hashCode;
47 
48     public List<Property> properties = new ArrayList<Property>();
49 
50     public Map<String, Property> namedProperties = new HashMap<String, Property>();
51 
52     public ViewNode parent;
53 
54     public List<ViewNode> children = new ArrayList<ViewNode>();
55 
56     public int left;
57 
58     public int top;
59 
60     public int width;
61 
62     public int height;
63 
64     public int scrollX;
65 
66     public int scrollY;
67 
68     public int paddingLeft;
69 
70     public int paddingRight;
71 
72     public int paddingTop;
73 
74     public int paddingBottom;
75 
76     public int marginLeft;
77 
78     public int marginRight;
79 
80     public int marginTop;
81 
82     public int marginBottom;
83 
84     public int baseline;
85 
86     public boolean willNotDraw;
87 
88     public boolean hasMargins;
89 
90     public boolean hasFocus;
91 
92     public int index;
93 
94     public double measureTime;
95 
96     public double layoutTime;
97 
98     public double drawTime;
99 
100     public ProfileRating measureRating = ProfileRating.NONE;
101 
102     public ProfileRating layoutRating = ProfileRating.NONE;
103 
104     public ProfileRating drawRating = ProfileRating.NONE;
105 
106     public Set<String> categories = new TreeSet<String>();
107 
108     public Window window;
109 
110     public Image image;
111 
112     public int imageReferences = 1;
113 
114     public int viewCount;
115 
116     public boolean filtered;
117 
118     public int protocolVersion;
119 
ViewNode(Window window, ViewNode parent, String data)120     public ViewNode(Window window, ViewNode parent, String data) {
121         this.window = window;
122         this.parent = parent;
123         index = this.parent == null ? 0 : this.parent.children.size();
124         if (this.parent != null) {
125             this.parent.children.add(this);
126         }
127         int delimIndex = data.indexOf('@');
128         name = data.substring(0, delimIndex);
129         data = data.substring(delimIndex + 1);
130         delimIndex = data.indexOf(' ');
131         hashCode = data.substring(0, delimIndex);
132         loadProperties(data.substring(delimIndex + 1).trim());
133 
134         measureTime = -1;
135         layoutTime = -1;
136         drawTime = -1;
137     }
138 
dispose()139     public void dispose() {
140         final int N = children.size();
141         for (int i = 0; i < N; i++) {
142             children.get(i).dispose();
143         }
144         dereferenceImage();
145     }
146 
referenceImage()147     public void referenceImage() {
148         imageReferences++;
149     }
150 
dereferenceImage()151     public void dereferenceImage() {
152         imageReferences--;
153         if (image != null && imageReferences == 0) {
154             image.dispose();
155         }
156     }
157 
loadProperties(String data)158     private void loadProperties(String data) {
159         int start = 0;
160         boolean stop;
161         do {
162             int index = data.indexOf('=', start);
163             ViewNode.Property property = new ViewNode.Property();
164             property.name = data.substring(start, index);
165 
166             int index2 = data.indexOf(',', index + 1);
167             int length = Integer.parseInt(data.substring(index + 1, index2));
168             start = index2 + 1 + length;
169             property.value = data.substring(index2 + 1, index2 + 1 + length);
170 
171             properties.add(property);
172             namedProperties.put(property.name, property);
173 
174             stop = start >= data.length();
175             if (!stop) {
176                 start += 1;
177             }
178         } while (!stop);
179 
180         Collections.sort(properties, new Comparator<ViewNode.Property>() {
181             @Override
182             public int compare(ViewNode.Property source, ViewNode.Property destination) {
183                 return source.name.compareTo(destination.name);
184             }
185         });
186 
187         id = namedProperties.get("mID").value; //$NON-NLS-1$
188 
189         left =
190  namedProperties.containsKey("mLeft") ? getInt("mLeft", 0) : getInt("layout:mLeft", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
191                         0);
192         top = namedProperties.containsKey("mTop") ? getInt("mTop", 0) : getInt("layout:mTop", 0); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
193         width =
194                 namedProperties.containsKey("getWidth()") ? getInt("getWidth()", 0) : getInt( //$NON-NLS-1$ //$NON-NLS-2$
195                         "layout:getWidth()", 0); //$NON-NLS-1$
196         height =
197                 namedProperties.containsKey("getHeight()") ? getInt("getHeight()", 0) : getInt( //$NON-NLS-1$ //$NON-NLS-2$
198                         "layout:getHeight()", 0); //$NON-NLS-1$
199         scrollX =
200                 namedProperties.containsKey("mScrollX") ? getInt("mScrollX", 0) : getInt( //$NON-NLS-1$ //$NON-NLS-2$
201                         "scrolling:mScrollX", 0); //$NON-NLS-1$
202         scrollY =
203                 namedProperties.containsKey("mScrollY") ? getInt("mScrollY", 0) : getInt( //$NON-NLS-1$ //$NON-NLS-2$
204                         "scrolling:mScrollY", 0); //$NON-NLS-1$
205         paddingLeft =
206                 namedProperties.containsKey("mPaddingLeft") ? getInt("mPaddingLeft", 0) : getInt( //$NON-NLS-1$ //$NON-NLS-2$
207                         "padding:mPaddingLeft", 0); //$NON-NLS-1$
208         paddingRight =
209                 namedProperties.containsKey("mPaddingRight") ? getInt("mPaddingRight", 0) : getInt( //$NON-NLS-1$ //$NON-NLS-2$
210                         "padding:mPaddingRight", 0); //$NON-NLS-1$
211         paddingTop =
212                 namedProperties.containsKey("mPaddingTop") ? getInt("mPaddingTop", 0) : getInt( //$NON-NLS-1$ //$NON-NLS-2$
213                         "padding:mPaddingTop", 0); //$NON-NLS-1$
214         paddingBottom =
215                 namedProperties.containsKey("mPaddingBottom") ? getInt("mPaddingBottom", 0) //$NON-NLS-1$ //$NON-NLS-2$
216                         : getInt("padding:mPaddingBottom", 0); //$NON-NLS-1$
217         marginLeft =
218                 namedProperties.containsKey("layout_leftMargin") ? getInt("layout_leftMargin", //$NON-NLS-1$ //$NON-NLS-2$
219                         Integer.MIN_VALUE) : getInt("layout:layout_leftMargin", Integer.MIN_VALUE); //$NON-NLS-1$
220         marginRight =
221                 namedProperties.containsKey("layout_rightMargin") ? getInt("layout_rightMargin", //$NON-NLS-1$ //$NON-NLS-2$
222                         Integer.MIN_VALUE) : getInt("layout:layout_rightMargin", Integer.MIN_VALUE); //$NON-NLS-1$
223         marginTop =
224                 namedProperties.containsKey("layout_topMargin") ? getInt("layout_topMargin", //$NON-NLS-1$ //$NON-NLS-2$
225                         Integer.MIN_VALUE) : getInt("layout:layout_topMargin", Integer.MIN_VALUE); //$NON-NLS-1$
226         marginBottom =
227                 namedProperties.containsKey("layout_bottomMargin") ? getInt("layout_bottomMargin", //$NON-NLS-1$ //$NON-NLS-2$
228                         Integer.MIN_VALUE)
229                         : getInt("layout:layout_bottomMargin", Integer.MIN_VALUE); //$NON-NLS-1$
230         baseline =
231                 namedProperties.containsKey("getBaseline()") ? getInt("getBaseline()", 0) : getInt( //$NON-NLS-1$ //$NON-NLS-2$
232                         "layout:getBaseline()", 0); //$NON-NLS-1$
233         willNotDraw =
234                 namedProperties.containsKey("willNotDraw()") ? getBoolean("willNotDraw()", false) //$NON-NLS-1$ //$NON-NLS-2$
235                         : getBoolean("drawing:willNotDraw()", false); //$NON-NLS-1$
236         hasFocus =
237                 namedProperties.containsKey("hasFocus()") ? getBoolean("hasFocus()", false) //$NON-NLS-1$ //$NON-NLS-2$
238                         : getBoolean("focus:hasFocus()", false); //$NON-NLS-1$
239 
240         hasMargins =
241                 marginLeft != Integer.MIN_VALUE && marginRight != Integer.MIN_VALUE
242                         && marginTop != Integer.MIN_VALUE && marginBottom != Integer.MIN_VALUE;
243 
244         for (String name : namedProperties.keySet()) {
245             int index = name.indexOf(':');
246             if (index != -1) {
247                 categories.add(name.substring(0, index));
248             }
249         }
250         if (categories.size() != 0) {
251             categories.add(MISCELLANIOUS);
252         }
253     }
254 
setProfileRatings()255     public void setProfileRatings() {
256         final int N = children.size();
257         if (N > 1) {
258             double totalMeasure = 0;
259             double totalLayout = 0;
260             double totalDraw = 0;
261             for (int i = 0; i < N; i++) {
262                 ViewNode child = children.get(i);
263                 totalMeasure += child.measureTime;
264                 totalLayout += child.layoutTime;
265                 totalDraw += child.drawTime;
266             }
267             for (int i = 0; i < N; i++) {
268                 ViewNode child = children.get(i);
269                 if (child.measureTime / totalMeasure >= RED_THRESHOLD) {
270                     child.measureRating = ProfileRating.RED;
271                 } else if (child.measureTime / totalMeasure >= YELLOW_THRESHOLD) {
272                     child.measureRating = ProfileRating.YELLOW;
273                 } else {
274                     child.measureRating = ProfileRating.GREEN;
275                 }
276                 if (child.layoutTime / totalLayout >= RED_THRESHOLD) {
277                     child.layoutRating = ProfileRating.RED;
278                 } else if (child.layoutTime / totalLayout >= YELLOW_THRESHOLD) {
279                     child.layoutRating = ProfileRating.YELLOW;
280                 } else {
281                     child.layoutRating = ProfileRating.GREEN;
282                 }
283                 if (child.drawTime / totalDraw >= RED_THRESHOLD) {
284                     child.drawRating = ProfileRating.RED;
285                 } else if (child.drawTime / totalDraw >= YELLOW_THRESHOLD) {
286                     child.drawRating = ProfileRating.YELLOW;
287                 } else {
288                     child.drawRating = ProfileRating.GREEN;
289                 }
290             }
291         }
292         for (int i = 0; i < N; i++) {
293             children.get(i).setProfileRatings();
294         }
295     }
296 
setViewCount()297     public void setViewCount() {
298         viewCount = 1;
299         final int N = children.size();
300         for (int i = 0; i < N; i++) {
301             ViewNode child = children.get(i);
302             child.setViewCount();
303             viewCount += child.viewCount;
304         }
305     }
306 
filter(String text)307     public void filter(String text) {
308         int dotIndex = name.lastIndexOf('.');
309         String shortName = (dotIndex == -1) ? name : name.substring(dotIndex + 1);
310         filtered =
311                 !text.equals("") //$NON-NLS-1$
312                         && (shortName.toLowerCase().contains(text.toLowerCase()) || (!id
313                                 .equals("NO_ID") && id.toLowerCase().contains(text.toLowerCase()))); //$NON-NLS-1$
314         final int N = children.size();
315         for (int i = 0; i < N; i++) {
316             children.get(i).filter(text);
317         }
318     }
319 
getBoolean(String name, boolean defaultValue)320     private boolean getBoolean(String name, boolean defaultValue) {
321         Property p = namedProperties.get(name);
322         if (p != null) {
323             try {
324                 return Boolean.parseBoolean(p.value);
325             } catch (NumberFormatException e) {
326                 return defaultValue;
327             }
328         }
329         return defaultValue;
330     }
331 
getInt(String name, int defaultValue)332     private int getInt(String name, int defaultValue) {
333         Property p = namedProperties.get(name);
334         if (p != null) {
335             try {
336                 return Integer.parseInt(p.value);
337             } catch (NumberFormatException e) {
338                 return defaultValue;
339             }
340         }
341         return defaultValue;
342     }
343 
344     @Override
toString()345     public String toString() {
346         return name + "@" + hashCode; //$NON-NLS-1$
347     }
348 
349     public static class Property {
350         public String name;
351 
352         public String value;
353 
354         @Override
toString()355         public String toString() {
356             return name + '=' + value;
357         }
358     }
359 }
360