Home | History | Annotate | Download | only in util
      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 {
     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      */
     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 */
    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