1 /* 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 17 package android.util; 18 19 import java.lang.reflect.Method; 20 import java.lang.reflect.InvocationTargetException; 21 import java.util.Locale; 22 23 /** 24 * <p>Various utilities for debugging and logging.</p> 25 */ 26 public class DebugUtils { DebugUtils()27 /** @hide */ public DebugUtils() {} 28 29 /** 30 * <p>Filters objects against the <code>ANDROID_OBJECT_FILTER</code> 31 * environment variable. This environment variable can filter objects 32 * based on their class name and attribute values.</p> 33 * 34 * <p>Here is the syntax for <code>ANDROID_OBJECT_FILTER</code>:</p> 35 * 36 * <p><code>ClassName@attribute1=value1@attribute2=value2...</code></p> 37 * 38 * <p>Examples:</p> 39 * <ul> 40 * <li>Select TextView instances: <code>TextView</code></li> 41 * <li>Select TextView instances of text "Loading" and bottom offset of 22: 42 * <code>TextView@text=Loading.*@bottom=22</code></li> 43 * </ul> 44 * 45 * <p>The class name and the values are regular expressions.</p> 46 * 47 * <p>This class is useful for debugging and logging purpose:</p> 48 * <pre> 49 * if (DEBUG) { 50 * if (DebugUtils.isObjectSelected(childView) && LOGV_ENABLED) { 51 * Log.v(TAG, "Object " + childView + " logged!"); 52 * } 53 * } 54 * </pre> 55 * 56 * <p><strong>NOTE</strong>: This method is very expensive as it relies 57 * heavily on regular expressions and reflection. Calls to this method 58 * should always be stripped out of the release binaries and avoided 59 * as much as possible in debug mode.</p> 60 * 61 * @param object any object to match against the ANDROID_OBJECT_FILTER 62 * environement variable 63 * @return true if object is selected by the ANDROID_OBJECT_FILTER 64 * environment variable, false otherwise 65 */ isObjectSelected(Object object)66 public static boolean isObjectSelected(Object object) { 67 boolean match = false; 68 String s = System.getenv("ANDROID_OBJECT_FILTER"); 69 if (s != null && s.length() > 0) { 70 String[] selectors = s.split("@"); 71 // first selector == class name 72 if (object.getClass().getSimpleName().matches(selectors[0])) { 73 // check potential attributes 74 for (int i = 1; i < selectors.length; i++) { 75 String[] pair = selectors[i].split("="); 76 Class<?> klass = object.getClass(); 77 try { 78 Method declaredMethod = null; 79 Class<?> parent = klass; 80 do { 81 declaredMethod = parent.getDeclaredMethod("get" + 82 pair[0].substring(0, 1).toUpperCase(Locale.ROOT) + 83 pair[0].substring(1), 84 (Class[]) null); 85 } while ((parent = klass.getSuperclass()) != null && 86 declaredMethod == null); 87 88 if (declaredMethod != null) { 89 Object value = declaredMethod 90 .invoke(object, (Object[])null); 91 match |= (value != null ? 92 value.toString() : "null").matches(pair[1]); 93 } 94 } catch (NoSuchMethodException e) { 95 e.printStackTrace(); 96 } catch (IllegalAccessException e) { 97 e.printStackTrace(); 98 } catch (InvocationTargetException e) { 99 e.printStackTrace(); 100 } 101 } 102 } 103 } 104 return match; 105 } 106 107 /** @hide */ buildShortClassTag(Object cls, StringBuilder out)108 public static void buildShortClassTag(Object cls, StringBuilder out) { 109 if (cls == null) { 110 out.append("null"); 111 } else { 112 String simpleName = cls.getClass().getSimpleName(); 113 if (simpleName == null || simpleName.isEmpty()) { 114 simpleName = cls.getClass().getName(); 115 int end = simpleName.lastIndexOf('.'); 116 if (end > 0) { 117 simpleName = simpleName.substring(end+1); 118 } 119 } 120 out.append(simpleName); 121 out.append('{'); 122 out.append(Integer.toHexString(System.identityHashCode(cls))); 123 } 124 } 125 126 } 127