Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8989290b authored by Deepanshu Gupta's avatar Deepanshu Gupta Committed by Android Git Automerger
Browse files

am 7b13c4d8: Merge "Always resolve enum when resolving resources." into lmp-dev

* commit '7b13c4d8':
  Always resolve enum when resolving resources.
parents 981258e5 7b13c4d8
Loading
Loading
Loading
Loading
+108 −201
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.rendering.api.StyleResourceValue;
import com.android.internal.util.XmlUtils;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.BridgeConstants;
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
import com.android.layoutlib.bridge.impl.ParserFactory;
@@ -142,16 +141,8 @@ public final class BridgeTypedArray extends TypedArray {
     */
    @Override
    public CharSequence getText(int index) {
        if (index < 0 || index >= mResourceData.length) {
            return null;
        }

        if (mResourceData[index] != null) {
        // FIXME: handle styled strings!
            return mResourceData[index].getValue();
        }

        return null;
        return getString(index);
    }

    /**
@@ -164,15 +155,14 @@ public final class BridgeTypedArray extends TypedArray {
     */
    @Override
    public String getString(int index) {
        if (index < 0 || index >= mResourceData.length) {
        if (!hasValue(index)) {
            return null;
        }

        if (mResourceData[index] != null) {
            return mResourceData[index].getValue();
        }

        return null;
        // As unfortunate as it is, it's possible to use enums with all attribute formats,
        // not just integers/enums. So, we need to search the enums always. In case,
        // enums are used, the returned value is an integer.
        Integer v = resolveEnumAttribute(index);
        return v == null ? mResourceData[index].getValue() : String.valueOf((int) v);
    }

    /**
@@ -185,20 +175,9 @@ public final class BridgeTypedArray extends TypedArray {
     */
    @Override
    public boolean getBoolean(int index, boolean defValue) {
        if (index < 0 || index >= mResourceData.length) {
            return defValue;
        }

        if (mResourceData[index] == null) {
            return defValue;
        }
        String s = getString(index);
        return s == null ? defValue : XmlUtils.convertValueToBoolean(s, defValue);

        String s = mResourceData[index].getValue();
        if (s != null) {
            return XmlUtils.convertValueToBoolean(s, defValue);
        }

        return defValue;
    }

    /**
@@ -211,75 +190,18 @@ public final class BridgeTypedArray extends TypedArray {
     */
    @Override
    public int getInt(int index, int defValue) {
        if (index < 0 || index >= mResourceData.length) {
            return defValue;
        }

        if (mResourceData[index] == null) {
            return defValue;
        }

        String s = mResourceData[index].getValue();

        if (s == null || s.length() == 0) {
            return defValue;
        }

        String s = getString(index);
        try {
            if (s != null) {
                return XmlUtils.convertValueToInt(s, defValue);
        } catch (NumberFormatException e) {
            // pass
            }

        // Field is not null and is not an integer.
        // Check for possible constants and try to find them.
        return (int) resolveEnumAttribute(index, defValue);
    }

    /**
     * Searches for the string in the attributes (flag or enums) and returns the integer.
     * If found, it will return an integer matching the value. However, if the value is not found,
     * it returns {@code defValue} which may be a float.
     *
     * @param index Index of attribute to retrieve.
     * @param defValue Value to return if the attribute is not found.
     *
     * @return Attribute int value, or defValue if not defined.
     */
    private float resolveEnumAttribute(int index, float defValue) {
        // Get the map of attribute-constant -> IntegerValue
        Map<String, Integer> map = null;
        if (mIsFramework[index]) {
            map = Bridge.getEnumValues(mNames[index]);
        } else {
            // get the styleable matching the resolved name
            RenderResources res = mContext.getRenderResources();
            ResourceValue attr = res.getProjectResource(ResourceType.ATTR, mNames[index]);
            if (attr instanceof AttrResourceValue) {
                map = ((AttrResourceValue) attr).getAttributeValues();
            }
        }

        if (map != null) {
            // accumulator to store the value of the 1+ constants.
            int result = 0;

            // split the value in case this is a mix of several flags.
            String[] keywords = mResourceData[index].getValue().split("\\|");
            for (String keyword : keywords) {
                Integer i = map.get(keyword.trim());
                if (i != null) {
                    result |= i;
                } else {
        } catch (NumberFormatException e) {
            Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
                            String.format(
                                "\"%s\" in attribute \"%2$s\" is not a valid value",
                                keyword, mNames[index]), null);
                }
            }
            return result;
                    String.format("\"%s\" in attribute \"%2$s\" is not a valid integer",
                            s, mNames[index]),
                    null);
            return defValue;
        }

        return defValue;
    }

@@ -292,27 +214,16 @@ public final class BridgeTypedArray extends TypedArray {
     */
    @Override
    public float getFloat(int index, float defValue) {
        if (index < 0 || index >= mResourceData.length) {
            return defValue;
        }

        if (mResourceData[index] == null) {
            return defValue;
        }

        String s = mResourceData[index].getValue();

        if (s != null) {
        String s = getString(index);
        try {
            if (s != null) {
                    return Float.parseFloat(s);
            }
        } catch (NumberFormatException e) {
            Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
                        String.format(
                            "\"%s\" in attribute \"%2$s\" cannot be converted to float.",
                            s, mNames[index]), null);

                // we'll return the default value below.
            }
                    String.format("\"%s\" in attribute \"%2$s\" cannot be converted to float.",
                            s, mNames[index]),
                    null);
        }
        return defValue;
    }
@@ -359,11 +270,7 @@ public final class BridgeTypedArray extends TypedArray {
     */
    @Override
    public ColorStateList getColorStateList(int index) {
        if (index < 0 || index >= mResourceData.length) {
            return null;
        }

        if (mResourceData[index] == null) {
        if (!hasValue(index)) {
            return null;
        }

@@ -443,27 +350,25 @@ public final class BridgeTypedArray extends TypedArray {
     */
    @Override
    public float getDimension(int index, float defValue) {
        if (index < 0 || index >= mResourceData.length) {
        String s = getString(index);
        if (s == null) {
            return defValue;
        }

        if (mResourceData[index] == null) {
            return defValue;
        // Check if the value is a magic constant that doesn't require a unit.
        try {
            int i = Integer.parseInt(s);
            if (i == LayoutParams.MATCH_PARENT || i == LayoutParams.WRAP_CONTENT) {
                return i;
            }

        String s = mResourceData[index].getValue();

        if (s == null) {
            return defValue;
        } catch (NumberFormatException ignored) {
            // pass
        }

        if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true)) {
            return mValue.getDimension(mBridgeResources.getDisplayMetrics());
        }

        // looks like we were unable to resolve the dimension value. Check if it is an attribute
        // constant.
        return resolveEnumAttribute(index, defValue);
        return defValue;
    }

    /**
@@ -511,17 +416,14 @@ public final class BridgeTypedArray extends TypedArray {
        try {
            return getDimension(index);
        } catch (RuntimeException e) {
            if (mResourceData[index] != null) {
                String s = mResourceData[index].getValue();
            String s = getString(index);

            if (s != null) {
                // looks like we were unable to resolve the dimension value
                Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
                            String.format(
                                "\"%1$s\" in attribute \"%2$s\" is not a valid format.",
                        String.format("\"%1$s\" in attribute \"%2$s\" is not a valid format.",
                                s, mNames[index]), null);
            }
            }

            return defValue;
        }
@@ -563,21 +465,19 @@ public final class BridgeTypedArray extends TypedArray {
    }

    private int getDimension(int index) {
        if (mResourceData[index] == null) {
            throw new RuntimeException();
        }

        String s = mResourceData[index].getValue();

        String s = getString(index);
        if (s == null) {
            throw new RuntimeException();
        } else if (s.equals(BridgeConstants.MATCH_PARENT) ||
                s.equals(BridgeConstants.FILL_PARENT)) {
            return LayoutParams.MATCH_PARENT;
        } else if (s.equals(BridgeConstants.WRAP_CONTENT)) {
            return LayoutParams.WRAP_CONTENT;
        }

        // Check if the value is a magic constant that doesn't require a unit.
        try {
            int i = Integer.parseInt(s);
            if (i == LayoutParams.MATCH_PARENT || i == LayoutParams.WRAP_CONTENT) {
                return i;
            }
        } catch (NumberFormatException ignored) {
            // pass
        }
        if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true)) {
            float f = mValue.getDimension(mBridgeResources.getDisplayMetrics());

@@ -607,15 +507,7 @@ public final class BridgeTypedArray extends TypedArray {
     */
    @Override
    public float getFraction(int index, int base, int pbase, float defValue) {
        if (index < 0 || index >= mResourceData.length) {
            return defValue;
        }

        if (mResourceData[index] == null) {
            return defValue;
        }

        String value = mResourceData[index].getValue();
        String value = getString(index);
        if (value == null) {
            return defValue;
        }
@@ -766,20 +658,11 @@ public final class BridgeTypedArray extends TypedArray {
     */
    @Override
    public Drawable getDrawable(int index) {
        if (index < 0 || index >= mResourceData.length) {
            return null;
        }

        if (mResourceData[index] == null) {
        if (!hasValue(index)) {
            return null;
        }

        ResourceValue value = mResourceData[index];
        String stringValue = value.getValue();
        if (stringValue == null) {
            return null;
        }

        return ResourceHelper.getDrawable(value, mContext);
    }

@@ -796,15 +679,7 @@ public final class BridgeTypedArray extends TypedArray {
     */
    @Override
    public CharSequence[] getTextArray(int index) {
        if (index < 0 || index >= mResourceData.length) {
            return null;
        }

        if (mResourceData[index] == null) {
            return null;
        }

        String value = mResourceData[index].getValue();
        String value = getString(index);
        if (value != null) {
            return new CharSequence[] { value };
        }
@@ -837,17 +712,8 @@ public final class BridgeTypedArray extends TypedArray {
     */
    @Override
    public boolean getValue(int index, TypedValue outValue) {
        if (index < 0 || index >= mResourceData.length) {
            return false;
        }

        if (mResourceData[index] == null) {
            return false;
        }

        String s = mResourceData[index].getValue();

        return ResourceHelper.parseFloatAttribute(mNames[index], s, outValue, false);
        String s = getString(index);
        return s != null && ResourceHelper.parseFloatAttribute(mNames[index], s, outValue, false);
    }

    /**
@@ -859,12 +725,7 @@ public final class BridgeTypedArray extends TypedArray {
     */
    @Override
    public boolean hasValue(int index) {
        //noinspection SimplifiableIfStatement
        if (index < 0 || index >= mResourceData.length) {
            return false;
        }

        return mResourceData[index] != null;
        return index >= 0 && index < mResourceData.length && mResourceData[index] != null;
    }

    /**
@@ -912,6 +773,52 @@ public final class BridgeTypedArray extends TypedArray {
        return Arrays.toString(mResourceData);
    }

    /**
     * Searches for the string in the attributes (flag or enums) and returns the integer.
     * If found, it will return an integer matching the value.
     *
     * @param index Index of attribute to retrieve.
     *
     * @return Attribute int value, or null if not defined.
     */
    private Integer resolveEnumAttribute(int index) {
        // Get the map of attribute-constant -> IntegerValue
        Map<String, Integer> map = null;
        if (mIsFramework[index]) {
            map = Bridge.getEnumValues(mNames[index]);
        } else {
            // get the styleable matching the resolved name
            RenderResources res = mContext.getRenderResources();
            ResourceValue attr = res.getProjectResource(ResourceType.ATTR, mNames[index]);
            if (attr instanceof AttrResourceValue) {
                map = ((AttrResourceValue) attr).getAttributeValues();
            }
        }

        if (map != null) {
            // accumulator to store the value of the 1+ constants.
            int result = 0;
            boolean found = false;

            // split the value in case this is a mix of several flags.
            String[] keywords = mResourceData[index].getValue().split("\\|");
            for (String keyword : keywords) {
                Integer i = map.get(keyword.trim());
                if (i != null) {
                    result |= i;
                    found = true;
                }
                // TODO: We should act smartly and log a warning for incorrect keywords. However,
                // this method is currently called even if the resourceValue is not an enum.
            }
            if (found) {
                return result;
            }
        }

        return null;
    }

    static TypedArray obtain(Resources res, int len) {
        return res instanceof BridgeResources ?
                new BridgeTypedArray(((BridgeResources) res), null, len, true) : null;
+2 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.layoutlib.bridge.impl;

import com.android.annotations.NonNull;
import com.android.ide.common.rendering.api.DensityBasedResourceValue;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.RenderResources;
@@ -358,7 +359,7 @@ public final class ResourceHelper {
     * @param requireUnit whether the value is expected to contain a unit.
     * @return true if success.
     */
    public static boolean parseFloatAttribute(String attribute, String value,
    public static boolean parseFloatAttribute(String attribute, @NonNull String value,
            TypedValue outValue, boolean requireUnit) {
        assert !requireUnit || attribute != null;