From 809a7f6080312f3e12f1a3a30eacf0e0c7627305 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Thu, 14 May 2009 15:44:42 -0700 Subject: [PATCH] New feature to track down #1846038. Adds the ability to export flags encoded in int values so as to make them human readable in HierarchyViewer. --- core/java/android/view/View.java | 57 +++++++----- core/java/android/view/ViewDebug.java | 91 ++++++++++++++++++- .../internal/view/menu/IconMenuView.java | 28 +++--- 3 files changed, 138 insertions(+), 38 deletions(-) diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index af5dca6ee8177..9e709cfd1f475 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -850,28 +850,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback { */ public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000; - /** - * View flag indicating whether this view was invalidated (fully or partially.) - * - * @hide - */ - static final int DIRTY = 0x20000000; - - /** - * View flag indicating whether this view was invalidated by an opaque - * invalidate request. - * - * @hide - */ - static final int DIRTY_OPAQUE = 0x40000000; - - /** - * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}. - * - * @hide - */ - static final int DIRTY_MASK = 0x60000000; - /** * Use with {@link #focusSearch}. Move focus to the previous selectable * item. @@ -1427,6 +1405,28 @@ public class View implements Drawable.Callback, KeyEvent.Callback { */ static final int SCROLL_CONTAINER_ADDED = 0x00100000; + /** + * View flag indicating whether this view was invalidated (fully or partially.) + * + * @hide + */ + static final int DIRTY = 0x00200000; + + /** + * View flag indicating whether this view was invalidated by an opaque + * invalidate request. + * + * @hide + */ + static final int DIRTY_OPAQUE = 0x00400000; + + /** + * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}. + * + * @hide + */ + static final int DIRTY_MASK = 0x00600000; + /** * The parent this view is attached to. * {@hide} @@ -1443,7 +1443,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback { /** * {@hide} */ - @ViewDebug.ExportedProperty + @ViewDebug.ExportedProperty(flagMapping = { + @ViewDebug.FlagToString(mask = FORCE_LAYOUT, equals = FORCE_LAYOUT, + name = "FORCE_LAYOUT"), + @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED, + name = "LAYOUT_REQUIRED"), + @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID, + name = "DRAWING_CACHE_VALID", outputIf = false), + @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true), + @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false), + @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"), + @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY") + }) int mPrivateFlags; /** diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 4436f4b6e62c5..74a248f65834d 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -187,7 +187,7 @@ public class ViewDebug { * of an array: * *
-         * @ViewDebug.ExportedProperty(mapping = {
+         * @ViewDebug.ExportedProperty(indexMapping = {
          *     @ViewDebug.IntToString(from = 0, to = "INVALID"),
          *     @ViewDebug.IntToString(from = 1, to = "FIRST"),
          *     @ViewDebug.IntToString(from = 2, to = "SECOND")
@@ -202,6 +202,25 @@ public class ViewDebug {
          */
         IntToString[] indexMapping() default { };
 
+        /**
+         * A flags mapping can be defined to map flags encoded in an integer to
+         * specific strings. A mapping can be used to see human readable values
+         * for the flags of an integer:
+         *
+         * 
+         * @ViewDebug.ExportedProperty(flagMapping = {
+         *     @ViewDebug.FlagToString(mask = ENABLED_MASK, equals = ENABLED, name = "ENABLED"),
+         *     @ViewDebug.FlagToString(mask = ENABLED_MASK, equals = DISABLED, name = "DISABLED"),
+         * })
+         * private int mFlags;
+         * 
+         *
+         * A specified String is output when the following is true:
+         * 
+         * @return An array of int to String mappings
+         */
+        FlagToString[] flagMapping() default { };
+
         /**
          * When deep export is turned on, this property is not dumped. Instead, the
          * properties contained in this property are dumped. Each child property
@@ -246,7 +265,45 @@ public class ViewDebug {
          */
         String to();
     }
-    
+
+    /**
+     * Defines a mapping from an flag to a String. Such a mapping can be used
+     * in a @ExportedProperty to provide more meaningful values to the end user.
+     *
+     * @see android.view.ViewDebug.ExportedProperty
+     */
+    @Target({ ElementType.TYPE })
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface FlagToString {
+        /**
+         * The mask to apply to the original value.
+         *
+         * @return An arbitrary int value.
+         */
+        int mask();
+
+        /**
+         * The value to compare to the result of:
+         * original value & {@link #mask()}.
+         *
+         * @return An arbitrary value.
+         */
+        int equals();
+
+        /**
+         * The String to use in place of the original int value.
+         *
+         * @return An arbitrary non-null String.
+         */
+        String name();
+
+        /**
+         * Indicates whether to output the flag when the test is true,
+         * or false. Defaults to true.
+         */
+        boolean outputIf() default true;
+    }
+
     /**
      * This annotation can be used to mark fields and methods to be dumped when
      * the view is captured. Methods with this annotation must have no arguments
@@ -1039,6 +1096,13 @@ public class ViewDebug {
                         final int id = (Integer) methodValue;
                         methodValue = resolveId(context, id);
                     } else {
+                        final FlagToString[] flagsMapping = property.flagMapping();
+                        if (flagsMapping.length > 0) {
+                            final int intValue = (Integer) methodValue;
+                            final String valuePrefix = prefix + method.getName() + '_';
+                            exportUnrolledFlags(out, flagsMapping, intValue, valuePrefix);
+                        }
+
                         final IntToString[] mapping = property.mapping();
                         if (mapping.length > 0) {
                             final int intValue = (Integer) methodValue;
@@ -1100,6 +1164,13 @@ public class ViewDebug {
                         final int id = field.getInt(view);
                         fieldValue = resolveId(context, id);
                     } else {
+                        final FlagToString[] flagsMapping = property.flagMapping();
+                        if (flagsMapping.length > 0) {
+                            final int intValue = field.getInt(view);
+                            final String valuePrefix = prefix + field.getName() + '_';
+                            exportUnrolledFlags(out, flagsMapping, intValue, valuePrefix);
+                        }
+
                         final IntToString[] mapping = property.mapping();
                         if (mapping.length > 0) {
                             final int intValue = field.getInt(view);
@@ -1157,6 +1228,22 @@ public class ViewDebug {
         out.write(' ');
     }
 
+    private static void exportUnrolledFlags(BufferedWriter out, FlagToString[] mapping,
+            int intValue, String prefix) throws IOException {
+
+        final int count = mapping.length;
+        for (int j = 0; j < count; j++) {
+            final FlagToString flagMapping = mapping[j];
+            final boolean ifTrue = flagMapping.outputIf();
+            final boolean test = (intValue & flagMapping.mask()) == flagMapping.equals();
+            if ((test && ifTrue) || (!test && !ifTrue)) {
+                final String name = flagMapping.name();
+                final String value = ifTrue ? "true" : "false";
+                writeEntry(out, prefix, name, "", value);
+            }
+        }
+    }
+
     private static void exportUnrolledArray(Context context, BufferedWriter out,
             ExportedProperty property, int[] array, String prefix, String suffix)
             throws IOException {
diff --git a/core/java/com/android/internal/view/menu/IconMenuView.java b/core/java/com/android/internal/view/menu/IconMenuView.java
index 6034a1e6e82d2..b81c2b3527d65 100644
--- a/core/java/com/android/internal/view/menu/IconMenuView.java
+++ b/core/java/com/android/internal/view/menu/IconMenuView.java
@@ -498,19 +498,23 @@ public final class IconMenuView extends ViewGroup implements ItemInvoker, MenuVi
 
     @Override
     protected void onDraw(Canvas canvas) {
-        if (mHorizontalDivider != null) {
+        Drawable drawable = mHorizontalDivider;
+        if (drawable != null) {
             // If we have a horizontal divider to draw, draw it at the remembered positions
-            for (int i = mHorizontalDividerRects.size() - 1; i >= 0; i--) {
-                mHorizontalDivider.setBounds(mHorizontalDividerRects.get(i));
-                mHorizontalDivider.draw(canvas);
+            final ArrayList rects = mHorizontalDividerRects;
+            for (int i = rects.size() - 1; i >= 0; i--) {
+                drawable.setBounds(rects.get(i));
+                drawable.draw(canvas);
             }
         }
-        
-        if (mVerticalDivider != null) {
+
+        drawable = mVerticalDivider;
+        if (drawable != null) {
             // If we have a vertical divider to draw, draw it at the remembered positions
-            for (int i = mVerticalDividerRects.size() - 1; i >= 0; i--) {
-                mVerticalDivider.setBounds(mVerticalDividerRects.get(i));
-                mVerticalDivider.draw(canvas);
+            final ArrayList rects = mVerticalDividerRects;
+            for (int i = rects.size() - 1; i >= 0; i--) {
+                drawable.setBounds(rects.get(i));
+                drawable.draw(canvas);
             }
         }
     }
@@ -520,14 +524,12 @@ public final class IconMenuView extends ViewGroup implements ItemInvoker, MenuVi
     }
 
     @Override
-    public LayoutParams generateLayoutParams(AttributeSet attrs)
-    {
+    public LayoutParams generateLayoutParams(AttributeSet attrs) {
         return new IconMenuView.LayoutParams(getContext(), attrs);
     }
 
     @Override
-    protected boolean checkLayoutParams(ViewGroup.LayoutParams p)
-    {
+    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
         // Override to allow type-checking of LayoutParams. 
         return p instanceof IconMenuView.LayoutParams;
     }