Search in sources :

Example 11 with ResName

use of org.robolectric.res.ResName in project robolectric by robolectric.

the class ShadowLegacyAssetManager method findAttributeValue.

private AttributeResource findAttributeValue(int resId, AttributeSet attributeSet, Style styleAttrStyle, Style defStyleFromAttr, Style defStyleFromRes, @Nonnull Style themeStyleSet) {
    if (attributeSet != null) {
        for (int i = 0; i < attributeSet.getAttributeCount(); i++) {
            if (attributeSet.getAttributeNameResource(i) == resId) {
                String attributeValue;
                try {
                    attributeValue = attributeSet.getAttributeValue(i);
                } catch (IndexOutOfBoundsException e) {
                    // type is TypedValue.TYPE_NULL, ignore...
                    continue;
                }
                if (attributeValue != null) {
                    String defaultPackageName = ResourceIds.isFrameworkResource(resId) ? "android" : RuntimeEnvironment.getApplication().getPackageName();
                    ResName resName = ResName.qualifyResName(attributeSet.getAttributeName(i), defaultPackageName, "attr");
                    Integer referenceResId = null;
                    if (AttributeResource.isResourceReference(attributeValue)) {
                        referenceResId = attributeSet.getAttributeResourceValue(i, -1);
                        // binary AttributeSet references have a string value of @resId rather than fully qualified resource name
                        if (referenceResId != 0) {
                            ResName refResName = getResourceTable().getResName(referenceResId);
                            if (refResName != null) {
                                attributeValue = "@" + refResName.getFullyQualifiedName();
                            }
                        }
                    }
                    return new AttributeResource(resName, attributeValue, "fixme!!!", referenceResId);
                }
            }
        }
    }
    ResName attrName = getResourceTable().getResName(resId);
    if (attrName == null)
        return null;
    if (styleAttrStyle != null) {
        AttributeResource attribute = styleAttrStyle.getAttrValue(attrName);
        if (attribute != null) {
            return attribute;
        }
    }
    // else if attr in defStyleFromAttr, use its value
    if (defStyleFromAttr != null) {
        AttributeResource attribute = defStyleFromAttr.getAttrValue(attrName);
        if (attribute != null) {
            return attribute;
        }
    }
    if (defStyleFromRes != null) {
        AttributeResource attribute = defStyleFromRes.getAttrValue(attrName);
        if (attribute != null) {
            return attribute;
        }
    }
    // else if attr in theme, use its value
    return themeStyleSet.getAttrValue(attrName);
}
Also used : AttributeResource(org.robolectric.res.AttributeResource) ResName(org.robolectric.res.ResName) SuppressLint(android.annotation.SuppressLint)

Example 12 with ResName

use of org.robolectric.res.ResName in project robolectric by robolectric.

the class ShadowLegacyAssetManager method buildTypedValue.

private TypedValue buildTypedValue(AttributeSet set, int resId, int defStyleAttr, Style themeStyleSet, int defStyleRes) {
    /*
     * When determining the final value of a particular attribute, there are four inputs that come into play:
     *
     * 1. Any attribute values in the given AttributeSet.
     * 2. The style resource specified in the AttributeSet (named "style").
     * 3. The default style specified by defStyleAttr and defStyleRes
     * 4. The base values in this theme.
     */
    Style defStyleFromAttr = null;
    Style defStyleFromRes = null;
    Style styleAttrStyle = null;
    if (defStyleAttr != 0) {
        // Load the theme attribute for the default style attributes. E.g., attr/buttonStyle
        ResName defStyleName = getResName(defStyleAttr);
        // Load the style for the default style attribute. E.g. "@style/Widget.Robolectric.Button";
        AttributeResource defStyleAttribute = themeStyleSet.getAttrValue(defStyleName);
        if (defStyleAttribute != null) {
            while (defStyleAttribute.isStyleReference()) {
                AttributeResource other = themeStyleSet.getAttrValue(defStyleAttribute.getStyleReference());
                if (other == null) {
                    throw new RuntimeException("couldn't dereference " + defStyleAttribute);
                }
                defStyleAttribute = other;
            }
            if (defStyleAttribute.isResourceReference()) {
                ResName defStyleResName = defStyleAttribute.getResourceReference();
                defStyleFromAttr = resolveStyle(defStyleResName, themeStyleSet);
            }
        }
    }
    if (set != null && set.getStyleAttribute() != 0) {
        ResName styleAttributeResName = getResName(set.getStyleAttribute());
        while (styleAttributeResName.type.equals("attr")) {
            AttributeResource attrValue = themeStyleSet.getAttrValue(styleAttributeResName);
            if (attrValue == null) {
                throw new RuntimeException("no value for " + styleAttributeResName.getFullyQualifiedName() + " in " + themeStyleSet);
            }
            if (attrValue.isResourceReference()) {
                styleAttributeResName = attrValue.getResourceReference();
            } else if (attrValue.isStyleReference()) {
                styleAttributeResName = attrValue.getStyleReference();
            }
        }
        styleAttrStyle = resolveStyle(styleAttributeResName, themeStyleSet);
    }
    if (defStyleRes != 0) {
        ResName resName = getResName(defStyleRes);
        if (resName.type.equals("attr")) {
            // todo: this should be a style resId, not an attr
            System.out.println("WARN: " + resName.getFullyQualifiedName() + " should be a style resId");
        // AttributeResource attributeValue = findAttributeValue(defStyleRes, set, styleAttrStyle, defStyleFromAttr, defStyleFromAttr, themeStyleSet);
        // if (attributeValue != null) {
        // if (attributeValue.isStyleReference()) {
        // resName = themeStyleSet.getAttrValue(attributeValue.getStyleReference()).getResourceReference();
        // } else if (attributeValue.isResourceReference()) {
        // resName = attributeValue.getResourceReference();
        // }
        // }
        } else if (resName.type.equals("style")) {
            defStyleFromRes = resolveStyle(resName, themeStyleSet);
        }
    }
    AttributeResource attribute = findAttributeValue(resId, set, styleAttrStyle, defStyleFromAttr, defStyleFromRes, themeStyleSet);
    while (attribute != null && attribute.isStyleReference()) {
        ResName otherAttrName = attribute.getStyleReference();
        if (attribute.resName.equals(otherAttrName)) {
            Logger.info("huh... circular reference for %s?", attribute.resName.getFullyQualifiedName());
            return null;
        }
        ResName resName = getResourceTable().getResName(resId);
        AttributeResource otherAttr = themeStyleSet.getAttrValue(otherAttrName);
        if (otherAttr == null) {
            strictError("no such attr %s in %s while resolving value for %s", attribute.value, themeStyleSet, resName.getFullyQualifiedName());
            attribute = null;
        } else {
            attribute = new AttributeResource(resName, otherAttr.value, otherAttr.contextPackageName);
        }
    }
    if (attribute == null || attribute.isNull()) {
        return null;
    } else {
        TypedValue typedValue = new TypedValue();
        convertAndFill(attribute, typedValue, config, true);
        return typedValue;
    }
}
Also used : AttributeResource(org.robolectric.res.AttributeResource) EmptyStyle(org.robolectric.res.EmptyStyle) Style(org.robolectric.res.Style) ResName(org.robolectric.res.ResName) TypedValue(android.util.TypedValue)

Example 13 with ResName

use of org.robolectric.res.ResName in project robolectric by robolectric.

the class LegacyManifestParser method createPermissionInfo.

private static PermissionInfo createPermissionInfo(Package owner, PermissionItemData itemData) {
    PermissionInfo permissionInfo = new PermissionInfo();
    populatePackageItemInfo(permissionInfo, owner, itemData);
    permissionInfo.group = itemData.getPermissionGroup();
    permissionInfo.protectionLevel = decodeProtectionLevel(itemData.getProtectionLevel());
    permissionInfo.metaData = metaDataToBundle(itemData.getMetaData().getValueMap());
    String descriptionRef = itemData.getDescription();
    if (descriptionRef != null) {
        ResName descResName = AttributeResource.getResourceReference(descriptionRef, owner.packageName, "string");
        permissionInfo.descriptionRes = RuntimeEnvironment.getAppResourceTable().getResourceId(descResName);
    }
    String labelRefOrString = itemData.getLabel();
    if (labelRefOrString != null) {
        if (AttributeResource.isResourceReference(labelRefOrString)) {
            ResName labelResName = AttributeResource.getResourceReference(labelRefOrString, owner.packageName, "string");
            permissionInfo.labelRes = RuntimeEnvironment.getAppResourceTable().getResourceId(labelResName);
        } else {
            permissionInfo.nonLocalizedLabel = labelRefOrString;
        }
    }
    return permissionInfo;
}
Also used : PermissionInfo(android.content.pm.PermissionInfo) ResName(org.robolectric.res.ResName)

Example 14 with ResName

use of org.robolectric.res.ResName in project robolectric by robolectric.

the class ShadowAssetManager method getThemeValue.

@HiddenApi
@Implementation(minSdk = LOLLIPOP)
public boolean getThemeValue(long themePtr, int ident, TypedValue outValue, boolean resolveRefs) {
    ResName resName = resourceTable.getResName(ident);
    ThemeStyleSet themeStyleSet = getNativeTheme(themePtr).themeStyleSet;
    AttributeResource attrValue = themeStyleSet.getAttrValue(resName);
    while (attrValue != null && attrValue.isStyleReference()) {
        ResName attrResName = attrValue.getStyleReference();
        if (attrValue.resName.equals(attrResName)) {
            Logger.info("huh... circular reference for %s?", attrResName.getFullyQualifiedName());
            return false;
        }
        attrValue = themeStyleSet.getAttrValue(attrResName);
    }
    if (attrValue != null) {
        convertAndFill(attrValue, outValue, RuntimeEnvironment.getQualifiers(), resolveRefs);
        return true;
    }
    return false;
}
Also used : AttributeResource(org.robolectric.res.AttributeResource) ThemeStyleSet(org.robolectric.res.ThemeStyleSet) ResName(org.robolectric.res.ResName) HiddenApi(org.robolectric.annotation.HiddenApi) Implementation(org.robolectric.annotation.Implementation)

Example 15 with ResName

use of org.robolectric.res.ResName in project robolectric by robolectric.

the class ShadowAssetManager method convertAndFill.

private void convertAndFill(AttributeResource attribute, TypedValue outValue, String qualifiers, boolean resolveRefs) {
    if (attribute.isNull()) {
        outValue.type = TypedValue.TYPE_NULL;
        outValue.data = TypedValue.DATA_NULL_UNDEFINED;
        return;
    } else if (attribute.isEmpty()) {
        outValue.type = TypedValue.TYPE_NULL;
        outValue.data = TypedValue.DATA_NULL_EMPTY;
        return;
    }
    // short-circuit Android caching of loaded resources cuz our string positions don't remain stable...
    outValue.assetCookie = Converter.getNextStringCookie();
    // TODO: Handle resource and style references
    if (attribute.isStyleReference()) {
        return;
    }
    while (attribute.isResourceReference()) {
        Integer resourceId;
        ResName resName = attribute.getResourceReference();
        if (attribute.getReferenceResId() != null) {
            resourceId = attribute.getReferenceResId();
        } else {
            resourceId = resourceTable.getResourceId(resName);
        }
        if (resourceId == null) {
            throw new Resources.NotFoundException("unknown resource " + resName);
        }
        outValue.type = TypedValue.TYPE_REFERENCE;
        if (!resolveRefs) {
            // Just return the resourceId if resolveRefs is false.
            outValue.data = resourceId;
            return;
        }
        outValue.resourceId = resourceId;
        TypedResource dereferencedRef = resourceTable.getValue(resName, qualifiers);
        if (dereferencedRef == null) {
            Logger.strict("couldn't resolve %s from %s", resName.getFullyQualifiedName(), attribute);
            if (resName.type.equals("id")) {
                return;
            } else if (resName.type.equals("layout")) {
                // resourceId is good enough, right?
                return;
            } else if (resName.type.equals("dimen")) {
                return;
            } else if (resName.type.equals("transition")) {
                return;
            } else if (resName.type.equals("interpolator")) {
                return;
            } else if (resName.type.equals("menu")) {
                return;
            } else if (resName.type.equals("raw")) {
                return;
            } else if (DrawableResourceLoader.isStillHandledHere(resName.type)) {
                // wtf. color and drawable references reference are all kinds of stupid.
                TypedResource drawableResource = resourceTable.getValue(resName, qualifiers);
                if (drawableResource == null) {
                    throw new Resources.NotFoundException("can't find file for " + resName);
                } else {
                    outValue.type = TypedValue.TYPE_STRING;
                    outValue.data = 0;
                    outValue.assetCookie = Converter.getNextStringCookie();
                    outValue.string = (CharSequence) drawableResource.getData();
                    return;
                }
            } else {
                throw new RuntimeException("huh? " + resName);
            }
        } else {
            if (dereferencedRef.isFile()) {
                outValue.type = TypedValue.TYPE_STRING;
                outValue.data = 0;
                outValue.assetCookie = Converter.getNextStringCookie();
                outValue.string = dereferencedRef.asString();
                return;
            } else if (dereferencedRef.getData() instanceof String) {
                attribute = new AttributeResource(attribute.resName, dereferencedRef.asString(), resName.packageName);
                if (attribute.isResourceReference()) {
                    continue;
                }
                if (resolveRefs) {
                    Converter.getConverter(dereferencedRef.getResType()).fillTypedValue(attribute.value, outValue);
                    return;
                }
            }
        }
        break;
    }
    if (attribute.isNull()) {
        outValue.type = TypedValue.TYPE_NULL;
        return;
    }
    TypedResource attrTypeData = resourceTable.getValue(attribute.resName, qualifiers);
    if (attrTypeData != null) {
        AttrData attrData = (AttrData) attrTypeData.getData();
        String format = attrData.getFormat();
        String[] types = format.split("\\|");
        for (String type : types) {
            // already handled above
            if ("reference".equals(type))
                continue;
            Converter converter = Converter.getConverterFor(attrData, type);
            if (converter != null) {
                if (converter.fillTypedValue(attribute.value, outValue)) {
                    return;
                }
            }
        }
    } else {
        /**
       * In cases where the runtime framework doesn't know this attribute, e.g: viewportHeight (added in 21) on a
       * KitKat runtine, then infer the attribute type from the value.
       *
       * TODO: When we are able to pass the SDK resources from the build environment then we can remove this
       * and replace the NullResourceLoader with simple ResourceProvider that only parses attribute type information.
       */
        ResType resType = ResType.inferFromValue(attribute.value);
        Converter.getConverter(resType).fillTypedValue(attribute.value, outValue);
    }
}
Also used : AttrData(org.robolectric.res.AttrData) FileTypedResource(org.robolectric.res.FileTypedResource) TypedResource(org.robolectric.res.TypedResource) ResType(org.robolectric.res.ResType) AttributeResource(org.robolectric.res.AttributeResource) ResName(org.robolectric.res.ResName) Resources(android.content.res.Resources)

Aggregations

ResName (org.robolectric.res.ResName)26 AttributeResource (org.robolectric.res.AttributeResource)9 TypedValue (android.util.TypedValue)6 FileTypedResource (org.robolectric.res.FileTypedResource)6 ResourceTable (org.robolectric.res.ResourceTable)6 HiddenApi (org.robolectric.annotation.HiddenApi)4 Implementation (org.robolectric.annotation.Implementation)4 TypedResource (org.robolectric.res.TypedResource)4 SuppressLint (android.annotation.SuppressLint)2 PermissionInfo (android.content.pm.PermissionInfo)2 ByteArrayInputStream (java.io.ByteArrayInputStream)2 FileNotFoundException (java.io.FileNotFoundException)2 IOException (java.io.IOException)2 Test (org.junit.Test)2 PermissionItemData (org.robolectric.manifest.PermissionItemData)2 AttrData (org.robolectric.res.AttrData)2 EmptyStyle (org.robolectric.res.EmptyStyle)2 ResType (org.robolectric.res.ResType)2 Style (org.robolectric.res.Style)2 ThemeStyleSet (org.robolectric.res.ThemeStyleSet)2