diff options
| author | Android (Google) Code Review <android-gerrit@google.com> | 2009-05-04 14:03:40 -0700 | 
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2009-05-04 14:03:40 -0700 | 
| commit | 7ff943673e48a912eb7cc5add08e206c2c25d68e (patch) | |
| tree | a529f5fea2ba25fb8fa2fc17c2b4737f36d8bbcc /core/java/android/os | |
| parent | 5c6f93f1422647c7f914a15bfad00992685c3eac (diff) | |
| parent | 1ce5bd34632e91a928aa12a30b1c160a35db033b (diff) | |
| download | frameworks_base-7ff943673e48a912eb7cc5add08e206c2c25d68e.zip frameworks_base-7ff943673e48a912eb7cc5add08e206c2c25d68e.tar.gz frameworks_base-7ff943673e48a912eb7cc5add08e206c2c25d68e.tar.bz2 | |
Merge change 911 into donut
* changes:
  Debug: Add setPropertiesOn(), and @hide it for now
Diffstat (limited to 'core/java/android/os')
| -rw-r--r-- | core/java/android/os/Debug.java | 204 | 
1 files changed, 203 insertions, 1 deletions
| diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java index 5ea5aae..1b4b56b 100644 --- a/core/java/android/os/Debug.java +++ b/core/java/android/os/Debug.java @@ -16,10 +16,20 @@  package android.os; +import com.android.internal.util.TypedProperties; + +import android.util.Config; +import android.util.Log; + +import java.io.FileNotFoundException;  import java.io.FileOutputStream; +import java.io.FileReader;  import java.io.IOException;  import java.io.OutputStreamWriter;  import java.io.PrintWriter; +import java.io.Reader; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier;  import org.apache.harmony.dalvik.ddmc.Chunk;  import org.apache.harmony.dalvik.ddmc.ChunkHandler; @@ -721,5 +731,197 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo              count += mCounts[Opcodes.OP_INVOKE_SUPER_QUICK_RANGE];              return count;          } -    }; +    } + + +    /** +     * A Map of typed debug properties. +     */ +    private static final TypedProperties debugProperties; + +    /* +     * Load the debug properties from the standard files into debugProperties. +     */ +    static { +        if (Config.DEBUG) { +            final String TAG = "DebugProperties"; +            final String[] files = { "/system/debug.prop", "/debug.prop", "/data/debug.prop" }; +            final TypedProperties tp = new TypedProperties(); + +            // Read the properties from each of the files, if present. +            for (String file: files) { +                Reader r; +                try { +                    r = new FileReader(file); +                } catch (FileNotFoundException ex) { +                    // It's ok if a file is missing. +                    continue; +                } + +                Exception failure = null; +                try { +                    tp.load(r); +                } catch (IOException ex) { +                    failure = ex; +                } catch (TypedProperties.ParseException ex) { +                    failure = ex; +                } +                if (failure != null) { +                    throw new RuntimeException("Problem loading " + file, failure); +                } +            } + +            debugProperties = tp.isEmpty() ? null : tp; +        } else { +            debugProperties = null; +        } +    } + + +    /** +     * Returns true if the type of the field matches the specified class. +     * Handles the case where the class is, e.g., java.lang.Boolean, but +     * the field is of the primitive "boolean" type.  Also handles all of +     * the java.lang.Number subclasses. +     */ +    private static boolean fieldTypeMatches(Field field, Class<?> cl) { +        Class<?> fieldClass = field.getType(); +        if (fieldClass == cl) { +            return true; +        } +        Field primitiveTypeField; +        try { +            /* All of the classes we care about (Boolean, Integer, etc.) +             * have a Class field called "TYPE" that points to the corresponding +             * primitive class. +             */ +            primitiveTypeField = cl.getField("TYPE"); +        } catch (NoSuchFieldException ex) { +            return false; +        } +        try { +            return fieldClass == (Class<?>)primitiveTypeField.get(null); +        } catch (IllegalAccessException ex) { +            return false; +        } +    } + + +    /** +     * Looks up the property that corresponds to the field, and sets the field's value +     * if the types match. +     */ +    private static void modifyFieldIfSet(final Field field, final String propertyName) { +        if (field.getType() == java.lang.String.class) { +            int stringInfo = debugProperties.getStringInfo(propertyName); +            switch (stringInfo) { +            case TypedProperties.STRING_SET: +                // Handle as usual below. +                break; +            case TypedProperties.STRING_NULL: +                try { +                    field.set(null, null);  // null object for static fields; null string +                } catch (IllegalAccessException ex) { +                    throw new IllegalArgumentException( +                        "Cannot set field for " + propertyName, ex); +                } +                return; +            case TypedProperties.STRING_NOT_SET: +                return; +            case TypedProperties.STRING_TYPE_MISMATCH: +                throw new IllegalArgumentException( +                    "Type of " + propertyName + " " + +                    " does not match field type (" + field.getType() + ")"); +            default: +                throw new IllegalStateException( +                    "Unexpected getStringInfo(" + propertyName + ") return value " + +                    stringInfo); +            } +        } +        Object value = debugProperties.get(propertyName); +        if (value != null) { +            if (!fieldTypeMatches(field, value.getClass())) { +                throw new IllegalArgumentException( +                    "Type of " + propertyName + " (" + value.getClass() + ") " + +                    " does not match field type (" + field.getType() + ")"); +            } +            try { +                field.set(null, value);  // null object for static fields +            } catch (IllegalAccessException ex) { +                throw new IllegalArgumentException( +                    "Cannot set field for " + propertyName, ex); +            } +        } +    } + + +    /** +     * Reflectively sets static fields of a class based on internal debugging +     * properties.  This method is a no-op if android.util.Config.DEBUG is +     * false. +     * <p> +     * <strong>NOTE TO APPLICATION DEVELOPERS</strong>: Config.DEBUG will +     * always be false in release builds.  This API is typically only useful +     * for platform developers. +     * </p> +     * Class setup: define a class whose only fields are non-final, static +     * primitive types (except for "char") or Strings.  In a static block +     * after the field definitions/initializations, pass the class to +     * this method, Debug.setPropertiesOn().  Example: +     * <pre> +     * package com.example; +     * +     * import android.os.Debug; +     * +     * public class MyDebugVars { +     *    public static String s = "a string"; +     *    public static String s2 = "second string"; +     *    public static String ns = null; +     *    public static boolean b = false; +     *    public static int i = 5; +     *    public static float f = 0.1f; +     *    public static double d = 0.5d; +     * +     *    // This MUST appear AFTER all fields are defined and initialized! +     *    static { +     *        Debug.setPropertiesOn(MyDebugVars.class); +     *    } +     * } +     * </pre> +     * setPropertiesOn() may override the value of any field in the class based +     * on internal properties that are fixed at boot time. +     * <p> +     * These properties are only set during platform debugging, and are not +     * meant to be used as a general-purpose properties store. +     * +     * {@hide} +     * +     * @param cl The class to (possibly) modify +     * @throws IllegalArgumentException if any fields are final or non-static, +     *         or if the type of the field does not match the type of +     *         the internal debugging property value. +     */ +    public static void setPropertiesOn(Class<?> cl) { +        if (Config.DEBUG) { +            if (debugProperties != null) { +                /* Only look for fields declared directly by the class, +                 * so we don't mysteriously change static fields in superclasses. +                 */ +                for (Field field : cl.getDeclaredFields()) { +                    final String propertyName = cl.getName() + "." + field.getName(); +                    boolean isStatic = Modifier.isStatic(field.getModifiers()); +                    boolean isFinal = Modifier.isFinal(field.getModifiers()); +                    if (!isStatic || isFinal) { +                        throw new IllegalArgumentException(propertyName + +                            " must be static and non-final"); +                    } +                    modifyFieldIfSet(field, propertyName); +                } +            } +        } else { +            Log.w("android.os.Debug", +                  "setPropertiesOn(" + (cl == null ? "null" : cl.getName()) + +                  ") called in non-DEBUG build"); +        } +    }  } | 
