From 36901b6c6029b561b4600916cbacc57d4e933703 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 19 Sep 2012 19:06:22 -0700 Subject: [PATCH] Move HAS_TRANSIENT_STATE flag into a safe area. Previously, this flag conflicted with other text direction flags, which can cause weird interactions across the View hierarchy, specifically with ListView. Also adds dumpFlags() utility to dump values of all know flags for documentation and sanity checking. Bug: 7189738 Change-Id: Iceb2f93f68a800e19a5889ced93abcce4932b067 --- core/java/android/view/View.java | 97 +++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 3 deletions(-) diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 0f8a491b7f587..87221e0e174d1 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -83,12 +83,18 @@ import static java.lang.Math.max; import com.android.internal.R; import com.android.internal.util.Predicate; import com.android.internal.view.menu.MenuBuilder; +import com.google.android.collect.Lists; +import com.google.android.collect.Maps; import java.lang.ref.WeakReference; +import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.Locale; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicInteger; @@ -1727,7 +1733,51 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ static final int PFLAG_INVALIDATED = 0x80000000; - /* Masks for mPrivateFlags2 */ + /** + * Masks for mPrivateFlags2, as generated by dumpFlags(): + * + * -------|-------|-------|-------| + * PFLAG2_TEXT_ALIGNMENT_FLAGS[0] + * PFLAG2_TEXT_DIRECTION_FLAGS[0] + * 1 PFLAG2_DRAG_CAN_ACCEPT + * 1 PFLAG2_DRAG_HOVERED + * 1 PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT + * 11 PFLAG2_TEXT_DIRECTION_MASK_SHIFT + * 1 1 PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT + * 11 PFLAG2_LAYOUT_DIRECTION_MASK + * 11 1 PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT + * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL + * 1 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT + * 1 1 PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT + * 1 PFLAG2_LAYOUT_DIRECTION_RESOLVED + * 11 PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK + * 1 PFLAG2_TEXT_DIRECTION_FLAGS[1] + * 1 PFLAG2_TEXT_DIRECTION_FLAGS[2] + * 11 PFLAG2_TEXT_DIRECTION_FLAGS[3] + * 1 PFLAG2_TEXT_DIRECTION_FLAGS[4] + * 1 1 PFLAG2_TEXT_DIRECTION_FLAGS[5] + * 111 PFLAG2_TEXT_DIRECTION_MASK + * 1 PFLAG2_TEXT_DIRECTION_RESOLVED + * 1 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT + * 111 PFLAG2_TEXT_DIRECTION_RESOLVED_MASK + * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[1] + * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[2] + * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[3] + * 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[4] + * 1 1 PFLAG2_TEXT_ALIGNMENT_FLAGS[5] + * 11 PFLAG2_TEXT_ALIGNMENT_FLAGS[6] + * 111 PFLAG2_TEXT_ALIGNMENT_MASK + * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED + * 1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT + * 111 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK + * 11 PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK + * 1 PFLAG2_HAS_TRANSIENT_STATE + * 1 PFLAG2_ACCESSIBILITY_FOCUSED + * 1 PFLAG2_ACCESSIBILITY_STATE_CHANGED + * 1 PFLAG2_VIEW_QUICK_REJECTED + * 1 PFLAG2_PADDING_RESOLVED + * -------|-------|-------|-------| + */ /** * Indicates that this view has reported that it can accept the current drag's content. @@ -1825,8 +1875,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * @hide */ - static final int PFLAG2_HAS_TRANSIENT_STATE = 0x00000100; - + static final int PFLAG2_HAS_TRANSIENT_STATE = 0x1 << 22; /** * Text direction is inherited thru {@link ViewGroup} @@ -18114,4 +18163,46 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return (view.mLabelForId == mLabeledId); } } + + /** + * Dump all private flags in readable format, useful for documentation and + * sanity checking. + */ + private static void dumpFlags() { + final HashMap found = Maps.newHashMap(); + try { + for (Field field : View.class.getDeclaredFields()) { + final int modifiers = field.getModifiers(); + if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) { + if (field.getType().equals(int.class)) { + final int value = field.getInt(null); + dumpFlag(found, field.getName(), value); + } else if (field.getType().equals(int[].class)) { + final int[] values = (int[]) field.get(null); + for (int i = 0; i < values.length; i++) { + dumpFlag(found, field.getName() + "[" + i + "]", values[i]); + } + } + } + } + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + + final ArrayList keys = Lists.newArrayList(); + keys.addAll(found.keySet()); + Collections.sort(keys); + for (String key : keys) { + Log.d(VIEW_LOG_TAG, found.get(key)); + } + } + + private static void dumpFlag(HashMap found, String name, int value) { + // Sort flags by prefix, then by bits, always keeping unique keys + final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' '); + final int prefix = name.indexOf('_'); + final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name; + final String output = bits + " " + name; + found.put(key, output); + } }