blob: 84d9ce89af279a7ff8064179eb08a10939abc7d8 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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
17package android.util;
18
Dianne Hackbornb9a5e4a2015-03-03 17:04:12 -080019import java.io.PrintWriter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import java.lang.reflect.Method;
21import java.lang.reflect.InvocationTargetException;
Elliott Hughescb64d432013-08-02 10:00:44 -070022import java.util.Locale;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023
24/**
Jesse Wilsona0f8bc52011-02-24 10:44:33 -080025 * <p>Various utilities for debugging and logging.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026 */
27public class DebugUtils {
Jesse Wilsona0f8bc52011-02-24 10:44:33 -080028 /** @hide */ public DebugUtils() {}
29
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030 /**
31 * <p>Filters objects against the <code>ANDROID_OBJECT_FILTER</code>
32 * environment variable. This environment variable can filter objects
33 * based on their class name and attribute values.</p>
34 *
35 * <p>Here is the syntax for <code>ANDROID_OBJECT_FILTER</code>:</p>
36 *
37 * <p><code>ClassName@attribute1=value1@attribute2=value2...</code></p>
38 *
39 * <p>Examples:</p>
40 * <ul>
41 * <li>Select TextView instances: <code>TextView</code></li>
42 * <li>Select TextView instances of text "Loading" and bottom offset of 22:
43 * <code>TextView@text=Loading.*@bottom=22</code></li>
44 * </ul>
45 *
46 * <p>The class name and the values are regular expressions.</p>
47 *
48 * <p>This class is useful for debugging and logging purpose:</p>
49 * <pre>
Dave Bort34f1ca72009-04-13 17:18:45 -070050 * if (DEBUG) {
51 * if (DebugUtils.isObjectSelected(childView) && LOGV_ENABLED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052 * Log.v(TAG, "Object " + childView + " logged!");
53 * }
54 * }
55 * </pre>
56 *
57 * <p><strong>NOTE</strong>: This method is very expensive as it relies
58 * heavily on regular expressions and reflection. Calls to this method
59 * should always be stripped out of the release binaries and avoided
60 * as much as possible in debug mode.</p>
61 *
62 * @param object any object to match against the ANDROID_OBJECT_FILTER
63 * environement variable
64 * @return true if object is selected by the ANDROID_OBJECT_FILTER
65 * environment variable, false otherwise
66 */
67 public static boolean isObjectSelected(Object object) {
68 boolean match = false;
69 String s = System.getenv("ANDROID_OBJECT_FILTER");
70 if (s != null && s.length() > 0) {
71 String[] selectors = s.split("@");
72 // first selector == class name
73 if (object.getClass().getSimpleName().matches(selectors[0])) {
74 // check potential attributes
75 for (int i = 1; i < selectors.length; i++) {
76 String[] pair = selectors[i].split("=");
77 Class<?> klass = object.getClass();
78 try {
79 Method declaredMethod = null;
80 Class<?> parent = klass;
81 do {
82 declaredMethod = parent.getDeclaredMethod("get" +
Elliott Hughescb64d432013-08-02 10:00:44 -070083 pair[0].substring(0, 1).toUpperCase(Locale.ROOT) +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 pair[0].substring(1),
85 (Class[]) null);
86 } while ((parent = klass.getSuperclass()) != null &&
87 declaredMethod == null);
88
89 if (declaredMethod != null) {
90 Object value = declaredMethod
91 .invoke(object, (Object[])null);
92 match |= (value != null ?
93 value.toString() : "null").matches(pair[1]);
94 }
95 } catch (NoSuchMethodException e) {
96 e.printStackTrace();
97 } catch (IllegalAccessException e) {
98 e.printStackTrace();
99 } catch (InvocationTargetException e) {
100 e.printStackTrace();
101 }
102 }
103 }
104 }
105 return match;
106 }
107
Dianne Hackborna2ea7472010-12-20 12:10:01 -0800108 /** @hide */
109 public static void buildShortClassTag(Object cls, StringBuilder out) {
110 if (cls == null) {
111 out.append("null");
112 } else {
113 String simpleName = cls.getClass().getSimpleName();
114 if (simpleName == null || simpleName.isEmpty()) {
115 simpleName = cls.getClass().getName();
116 int end = simpleName.lastIndexOf('.');
117 if (end > 0) {
118 simpleName = simpleName.substring(end+1);
119 }
120 }
121 out.append(simpleName);
122 out.append('{');
123 out.append(Integer.toHexString(System.identityHashCode(cls)));
124 }
125 }
126
Dianne Hackbornb9a5e4a2015-03-03 17:04:12 -0800127 /** @hide */
128 public static void printSizeValue(PrintWriter pw, long number) {
129 float result = number;
130 String suffix = "";
131 if (result > 900) {
132 suffix = "KB";
133 result = result / 1024;
134 }
135 if (result > 900) {
136 suffix = "MB";
137 result = result / 1024;
138 }
139 if (result > 900) {
140 suffix = "GB";
141 result = result / 1024;
142 }
143 if (result > 900) {
144 suffix = "TB";
145 result = result / 1024;
146 }
147 if (result > 900) {
148 suffix = "PB";
149 result = result / 1024;
150 }
151 String value;
152 if (result < 1) {
153 value = String.format("%.2f", result);
154 } else if (result < 10) {
155 value = String.format("%.1f", result);
156 } else if (result < 100) {
157 value = String.format("%.0f", result);
158 } else {
159 value = String.format("%.0f", result);
160 }
161 pw.print(value);
162 pw.print(suffix);
163 }
164
165 /** @hide */
166 public static String sizeValueToString(long number, StringBuilder outBuilder) {
167 if (outBuilder == null) {
168 outBuilder = new StringBuilder(32);
169 }
170 float result = number;
171 String suffix = "";
172 if (result > 900) {
173 suffix = "KB";
174 result = result / 1024;
175 }
176 if (result > 900) {
177 suffix = "MB";
178 result = result / 1024;
179 }
180 if (result > 900) {
181 suffix = "GB";
182 result = result / 1024;
183 }
184 if (result > 900) {
185 suffix = "TB";
186 result = result / 1024;
187 }
188 if (result > 900) {
189 suffix = "PB";
190 result = result / 1024;
191 }
192 String value;
193 if (result < 1) {
194 value = String.format("%.2f", result);
195 } else if (result < 10) {
196 value = String.format("%.1f", result);
197 } else if (result < 100) {
198 value = String.format("%.0f", result);
199 } else {
200 value = String.format("%.0f", result);
201 }
202 outBuilder.append(value);
203 outBuilder.append(suffix);
204 return outBuilder.toString();
205 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206}