Search in sources :

Example 6 with Pair

use of com.android.util.Pair in project android_frameworks_base by ResurrectionRemix.

the class BridgeContext method createStyleBasedTypedArray.

// ------------- private new methods
/**
     * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the
     * values found in the given style. If no style is specified, the default theme, along with the
     * styles applied to it are used.
     *
     * @see #obtainStyledAttributes(int, int[])
     */
private Pair<BridgeTypedArray, PropertiesMap> createStyleBasedTypedArray(@Nullable StyleResourceValue style, int[] attrs) throws Resources.NotFoundException {
    List<Pair<String, Boolean>> attributes = searchAttrs(attrs);
    BridgeTypedArray ta = Resources_Delegate.newTypeArray(mSystemResources, attrs.length, false);
    PropertiesMap defaultPropMap = new PropertiesMap();
    // for each attribute, get its name so that we can search it in the style
    for (int i = 0; i < attrs.length; i++) {
        Pair<String, Boolean> attribute = attributes.get(i);
        if (attribute != null) {
            // look for the value in the given style
            ResourceValue resValue;
            String attrName = attribute.getFirst();
            boolean frameworkAttr = attribute.getSecond();
            if (style != null) {
                resValue = mRenderResources.findItemInStyle(style, attrName, frameworkAttr);
            } else {
                resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr);
            }
            if (resValue != null) {
                // Add it to defaultPropMap before resolving
                String preResolve = resValue.getValue();
                // resolve it to make sure there are no references left.
                resValue = mRenderResources.resolveResValue(resValue);
                ta.bridgeSetValue(i, attrName, frameworkAttr, resValue);
                defaultPropMap.put(frameworkAttr ? SdkConstants.ANDROID_PREFIX + attrName : attrName, new Property(preResolve, resValue.getValue()));
            }
        }
    }
    ta.sealArray();
    return Pair.of(ta, defaultPropMap);
}
Also used : StyleResourceValue(com.android.ide.common.rendering.api.StyleResourceValue) ResourceValue(com.android.ide.common.rendering.api.ResourceValue) BridgeTypedArray(android.content.res.BridgeTypedArray) PropertiesMap(com.android.util.PropertiesMap) Property(com.android.util.PropertiesMap.Property) Pair(com.android.util.Pair)

Example 7 with Pair

use of com.android.util.Pair in project android_frameworks_base by ResurrectionRemix.

the class BridgeContext method obtainStyledAttributes.

@Override
public BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
    PropertiesMap defaultPropMap = null;
    boolean isPlatformFile = true;
    // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java
    if (set instanceof BridgeXmlBlockParser) {
        BridgeXmlBlockParser parser;
        parser = (BridgeXmlBlockParser) set;
        isPlatformFile = parser.isPlatformFile();
        Object key = parser.getViewCookie();
        if (key != null) {
            defaultPropMap = mDefaultPropMaps.get(key);
            if (defaultPropMap == null) {
                defaultPropMap = new PropertiesMap();
                mDefaultPropMaps.put(key, defaultPropMap);
            }
        }
    } else if (set instanceof BridgeLayoutParamsMapAttributes) {
        // this is only for temp layout params generated dynamically, so this is never
        // platform content.
        isPlatformFile = false;
    } else if (set != null) {
        // null parser is ok
        // really this should not be happening since its instantiated in Bridge
        Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Parser is not a BridgeXmlBlockParser!", null);
        return null;
    }
    List<Pair<String, Boolean>> attributeList = searchAttrs(attrs);
    BridgeTypedArray ta = Resources_Delegate.newTypeArray(mSystemResources, attrs.length, isPlatformFile);
    // look for a custom style.
    String customStyle = null;
    if (set != null) {
        customStyle = set.getAttributeValue(null, "style");
    }
    StyleResourceValue customStyleValues = null;
    if (customStyle != null) {
        ResourceValue item = mRenderResources.findResValue(customStyle, isPlatformFile);
        // resolve it in case it links to something else
        item = mRenderResources.resolveResValue(item);
        if (item instanceof StyleResourceValue) {
            customStyleValues = (StyleResourceValue) item;
        }
    }
    // resolve the defStyleAttr value into a IStyleResourceValue
    StyleResourceValue defStyleValues = null;
    if (defStyleAttr != 0) {
        // get the name from the int.
        Pair<String, Boolean> defStyleAttribute = searchAttr(defStyleAttr);
        if (defStyleAttribute == null) {
            // This should be rare. Happens trying to map R.style.foo to @style/foo fails.
            // This will happen if the user explicitly used a non existing int value for
            // defStyleAttr or there's something wrong with the project structure/build.
            Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE, "Failed to find the style corresponding to the id " + defStyleAttr, null);
        } else {
            String defStyleName = defStyleAttribute.getFirst();
            // look for the style in the current theme, and its parent:
            ResourceValue item = mRenderResources.findItemInTheme(defStyleName, defStyleAttribute.getSecond());
            if (item != null) {
                // item is a reference to a style entry. Search for it.
                item = mRenderResources.findResValue(item.getValue(), item.isFramework());
                item = mRenderResources.resolveResValue(item);
                if (item instanceof StyleResourceValue) {
                    defStyleValues = (StyleResourceValue) item;
                }
                if (defaultPropMap != null) {
                    if (defStyleAttribute.getSecond()) {
                        defStyleName = "android:" + defStyleName;
                    }
                    defaultPropMap.put("style", new Property(defStyleName, item.getValue()));
                }
            } else {
                Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, String.format("Failed to find style '%s' in current theme", defStyleAttribute.getFirst()), null);
            }
        }
    } else if (defStyleRes != 0) {
        StyleResourceValue item = getStyleByDynamicId(defStyleRes);
        if (item != null) {
            defStyleValues = item;
        } else {
            boolean isFrameworkRes = true;
            Pair<ResourceType, String> value = Bridge.resolveResourceId(defStyleRes);
            if (value == null) {
                value = mLayoutlibCallback.resolveResourceId(defStyleRes);
                isFrameworkRes = false;
            }
            if (value != null) {
                if ((value.getFirst() == ResourceType.STYLE)) {
                    // look for the style in all resources:
                    item = mRenderResources.getStyle(value.getSecond(), isFrameworkRes);
                    if (item != null) {
                        if (defaultPropMap != null) {
                            String name = item.getName();
                            defaultPropMap.put("style", new Property(name, name));
                        }
                        defStyleValues = item;
                    } else {
                        Bridge.getLog().error(null, String.format("Style with id 0x%x (resolved to '%s') does not exist.", defStyleRes, value.getSecond()), null);
                    }
                } else {
                    Bridge.getLog().error(null, String.format("Resource id 0x%x is not of type STYLE (instead %s)", defStyleRes, value.getFirst().toString()), null);
                }
            } else {
                Bridge.getLog().error(null, String.format("Failed to find style with id 0x%x in current theme", defStyleRes), null);
            }
        }
    }
    String appNamespace = mLayoutlibCallback.getNamespace();
    if (attributeList != null) {
        for (int index = 0; index < attributeList.size(); index++) {
            Pair<String, Boolean> attribute = attributeList.get(index);
            if (attribute == null) {
                continue;
            }
            String attrName = attribute.getFirst();
            boolean frameworkAttr = attribute.getSecond();
            String value = null;
            if (set != null) {
                value = set.getAttributeValue(frameworkAttr ? BridgeConstants.NS_RESOURCES : appNamespace, attrName);
                // new res-auto namespace as well
                if (!frameworkAttr && value == null) {
                    value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName);
                }
            }
            // values in the widget defStyle, and then in the theme.
            if (value == null) {
                ResourceValue resValue = null;
                // look for the value in the custom style first (and its parent if needed)
                if (customStyleValues != null) {
                    resValue = mRenderResources.findItemInStyle(customStyleValues, attrName, frameworkAttr);
                }
                // then look for the value in the default Style (and its parent if needed)
                if (resValue == null && defStyleValues != null) {
                    resValue = mRenderResources.findItemInStyle(defStyleValues, attrName, frameworkAttr);
                }
                // its parent themes)
                if (resValue == null) {
                    resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr);
                }
                // So we resolve it.
                if (resValue != null) {
                    String preResolve = resValue.getValue();
                    resValue = mRenderResources.resolveResValue(resValue);
                    if (defaultPropMap != null) {
                        defaultPropMap.put(frameworkAttr ? SdkConstants.PREFIX_ANDROID + attrName : attrName, new Property(preResolve, resValue.getValue()));
                    }
                    // If the value is a reference to another theme attribute that doesn't
                    // exist, we should log a warning and omit it.
                    String val = resValue.getValue();
                    if (val != null && val.startsWith(SdkConstants.PREFIX_THEME_REF)) {
                        if (!attrName.equals(RTL_ATTRS.get(val)) || getApplicationInfo().targetSdkVersion < VERSION_CODES.JELLY_BEAN_MR1) {
                            // Only log a warning if the referenced value isn't one of the RTL
                            // attributes, or the app targets old API.
                            Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, String.format("Failed to find '%s' in current theme.", val), val);
                        }
                        resValue = null;
                    }
                }
                ta.bridgeSetValue(index, attrName, frameworkAttr, resValue);
            } else {
                // there is a value in the XML, but we need to resolve it in case it's
                // referencing another resource or a theme value.
                ta.bridgeSetValue(index, attrName, frameworkAttr, mRenderResources.resolveValue(null, attrName, value, isPlatformFile));
            }
        }
    }
    ta.sealArray();
    return ta;
}
Also used : PropertiesMap(com.android.util.PropertiesMap) StyleResourceValue(com.android.ide.common.rendering.api.StyleResourceValue) StyleResourceValue(com.android.ide.common.rendering.api.StyleResourceValue) ResourceValue(com.android.ide.common.rendering.api.ResourceValue) BridgeTypedArray(android.content.res.BridgeTypedArray) Property(com.android.util.PropertiesMap.Property) Pair(com.android.util.Pair)

Example 8 with Pair

use of com.android.util.Pair in project android by JetBrains.

the class ViewLoader method loadAndParseRClass.

@VisibleForTesting
void loadAndParseRClass(@NotNull String className) throws ClassNotFoundException, InconvertibleClassError {
    if (LOG.isDebugEnabled()) {
        LOG.debug(String.format("loadAndParseRClass(%s)", anonymizeClassName(className)));
    }
    Class<?> aClass = myLoadedClasses.get(className);
    AppResourceRepository appResources = AppResourceRepository.getAppResources(myModule, true);
    if (aClass == null) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("  The R class is not loaded.");
        }
        final ModuleClassLoader moduleClassLoader = getModuleClassLoader();
        final boolean isClassLoaded = moduleClassLoader.isClassLoaded(className);
        aClass = moduleClassLoader.loadClass(className);
        if (!isClassLoaded && aClass != null) {
            if (LOG.isDebugEnabled()) {
                LOG.debug(String.format("  Class found in module %s, first time load.", anonymize(myModule)));
            }
            // This is the first time we've found the resources. The dynamic R classes generated for aar libraries are now stale and must be
            // regenerated. Clear the ModuleClassLoader and reload the R class.
            myLoadedClasses.clear();
            ModuleClassLoader.clearCache(myModule);
            myModuleClassLoader = null;
            aClass = getModuleClassLoader().loadClass(className);
            if (appResources != null) {
                appResources.resetDynamicIds(true);
            }
        } else {
            if (LOG.isDebugEnabled()) {
                if (isClassLoaded) {
                    LOG.debug(String.format("  Class already loaded in module %s.", anonymize(myModule)));
                }
            }
        }
        if (aClass != null) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("  Class loaded");
            }
            assert myLogger != null;
            myLoadedClasses.put(className, aClass);
            myLogger.setHasLoadedClasses(true);
        }
    }
    if (aClass != null) {
        final Map<ResourceType, TObjectIntHashMap<String>> res2id = new EnumMap<>(ResourceType.class);
        final TIntObjectHashMap<Pair<ResourceType, String>> id2res = new TIntObjectHashMap<>();
        final Map<IntArrayWrapper, String> styleableId2res = new HashMap<>();
        if (parseClass(aClass, id2res, styleableId2res, res2id)) {
            if (appResources != null) {
                appResources.setCompiledResources(id2res, styleableId2res, res2id);
            }
        }
    }
    if (LOG.isDebugEnabled()) {
        LOG.debug(String.format("END loadAndParseRClass(%s)", anonymizeClassName(className)));
    }
}
Also used : TObjectIntHashMap(gnu.trove.TObjectIntHashMap) HashMap(java.util.HashMap) TIntObjectHashMap(gnu.trove.TIntObjectHashMap) AppResourceRepository(com.android.tools.idea.res.AppResourceRepository) ResourceType(com.android.resources.ResourceType) TObjectIntHashMap(gnu.trove.TObjectIntHashMap) TIntObjectHashMap(gnu.trove.TIntObjectHashMap) IntArrayWrapper(com.android.ide.common.resources.IntArrayWrapper) EnumMap(java.util.EnumMap) Pair(com.android.util.Pair) VisibleForTesting(com.android.annotations.VisibleForTesting)

Example 9 with Pair

use of com.android.util.Pair in project android_frameworks_base by crdroidandroid.

the class BridgeContext method obtainStyledAttributes.

@Override
public BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
    PropertiesMap defaultPropMap = null;
    boolean isPlatformFile = true;
    // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java
    if (set instanceof BridgeXmlBlockParser) {
        BridgeXmlBlockParser parser;
        parser = (BridgeXmlBlockParser) set;
        isPlatformFile = parser.isPlatformFile();
        Object key = parser.getViewCookie();
        if (key != null) {
            defaultPropMap = mDefaultPropMaps.get(key);
            if (defaultPropMap == null) {
                defaultPropMap = new PropertiesMap();
                mDefaultPropMaps.put(key, defaultPropMap);
            }
        }
    } else if (set instanceof BridgeLayoutParamsMapAttributes) {
        // this is only for temp layout params generated dynamically, so this is never
        // platform content.
        isPlatformFile = false;
    } else if (set != null) {
        // null parser is ok
        // really this should not be happening since its instantiated in Bridge
        Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Parser is not a BridgeXmlBlockParser!", null);
        return null;
    }
    List<Pair<String, Boolean>> attributeList = searchAttrs(attrs);
    BridgeTypedArray ta = Resources_Delegate.newTypeArray(mSystemResources, attrs.length, isPlatformFile);
    // look for a custom style.
    String customStyle = null;
    if (set != null) {
        customStyle = set.getAttributeValue(null, "style");
    }
    StyleResourceValue customStyleValues = null;
    if (customStyle != null) {
        ResourceValue item = mRenderResources.findResValue(customStyle, isPlatformFile);
        // resolve it in case it links to something else
        item = mRenderResources.resolveResValue(item);
        if (item instanceof StyleResourceValue) {
            customStyleValues = (StyleResourceValue) item;
        }
    }
    // resolve the defStyleAttr value into a IStyleResourceValue
    StyleResourceValue defStyleValues = null;
    if (defStyleAttr != 0) {
        // get the name from the int.
        Pair<String, Boolean> defStyleAttribute = searchAttr(defStyleAttr);
        if (defStyleAttribute == null) {
            // This should be rare. Happens trying to map R.style.foo to @style/foo fails.
            // This will happen if the user explicitly used a non existing int value for
            // defStyleAttr or there's something wrong with the project structure/build.
            Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE, "Failed to find the style corresponding to the id " + defStyleAttr, null);
        } else {
            String defStyleName = defStyleAttribute.getFirst();
            // look for the style in the current theme, and its parent:
            ResourceValue item = mRenderResources.findItemInTheme(defStyleName, defStyleAttribute.getSecond());
            if (item != null) {
                // item is a reference to a style entry. Search for it.
                item = mRenderResources.findResValue(item.getValue(), item.isFramework());
                item = mRenderResources.resolveResValue(item);
                if (item instanceof StyleResourceValue) {
                    defStyleValues = (StyleResourceValue) item;
                }
                if (defaultPropMap != null) {
                    if (defStyleAttribute.getSecond()) {
                        defStyleName = "android:" + defStyleName;
                    }
                    defaultPropMap.put("style", new Property(defStyleName, item.getValue()));
                }
            } else {
                Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, String.format("Failed to find style '%s' in current theme", defStyleAttribute.getFirst()), null);
            }
        }
    } else if (defStyleRes != 0) {
        StyleResourceValue item = getStyleByDynamicId(defStyleRes);
        if (item != null) {
            defStyleValues = item;
        } else {
            boolean isFrameworkRes = true;
            Pair<ResourceType, String> value = Bridge.resolveResourceId(defStyleRes);
            if (value == null) {
                value = mLayoutlibCallback.resolveResourceId(defStyleRes);
                isFrameworkRes = false;
            }
            if (value != null) {
                if ((value.getFirst() == ResourceType.STYLE)) {
                    // look for the style in all resources:
                    item = mRenderResources.getStyle(value.getSecond(), isFrameworkRes);
                    if (item != null) {
                        if (defaultPropMap != null) {
                            String name = item.getName();
                            defaultPropMap.put("style", new Property(name, name));
                        }
                        defStyleValues = item;
                    } else {
                        Bridge.getLog().error(null, String.format("Style with id 0x%x (resolved to '%s') does not exist.", defStyleRes, value.getSecond()), null);
                    }
                } else {
                    Bridge.getLog().error(null, String.format("Resource id 0x%x is not of type STYLE (instead %s)", defStyleRes, value.getFirst().toString()), null);
                }
            } else {
                Bridge.getLog().error(null, String.format("Failed to find style with id 0x%x in current theme", defStyleRes), null);
            }
        }
    }
    String appNamespace = mLayoutlibCallback.getNamespace();
    if (attributeList != null) {
        for (int index = 0; index < attributeList.size(); index++) {
            Pair<String, Boolean> attribute = attributeList.get(index);
            if (attribute == null) {
                continue;
            }
            String attrName = attribute.getFirst();
            boolean frameworkAttr = attribute.getSecond();
            String value = null;
            if (set != null) {
                value = set.getAttributeValue(frameworkAttr ? BridgeConstants.NS_RESOURCES : appNamespace, attrName);
                // new res-auto namespace as well
                if (!frameworkAttr && value == null) {
                    value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName);
                }
            }
            // values in the widget defStyle, and then in the theme.
            if (value == null) {
                ResourceValue resValue = null;
                // look for the value in the custom style first (and its parent if needed)
                if (customStyleValues != null) {
                    resValue = mRenderResources.findItemInStyle(customStyleValues, attrName, frameworkAttr);
                }
                // then look for the value in the default Style (and its parent if needed)
                if (resValue == null && defStyleValues != null) {
                    resValue = mRenderResources.findItemInStyle(defStyleValues, attrName, frameworkAttr);
                }
                // its parent themes)
                if (resValue == null) {
                    resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr);
                }
                // So we resolve it.
                if (resValue != null) {
                    String preResolve = resValue.getValue();
                    resValue = mRenderResources.resolveResValue(resValue);
                    if (defaultPropMap != null) {
                        defaultPropMap.put(frameworkAttr ? SdkConstants.PREFIX_ANDROID + attrName : attrName, new Property(preResolve, resValue.getValue()));
                    }
                    // If the value is a reference to another theme attribute that doesn't
                    // exist, we should log a warning and omit it.
                    String val = resValue.getValue();
                    if (val != null && val.startsWith(SdkConstants.PREFIX_THEME_REF)) {
                        if (!attrName.equals(RTL_ATTRS.get(val)) || getApplicationInfo().targetSdkVersion < VERSION_CODES.JELLY_BEAN_MR1) {
                            // Only log a warning if the referenced value isn't one of the RTL
                            // attributes, or the app targets old API.
                            Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, String.format("Failed to find '%s' in current theme.", val), val);
                        }
                        resValue = null;
                    }
                }
                ta.bridgeSetValue(index, attrName, frameworkAttr, resValue);
            } else {
                // there is a value in the XML, but we need to resolve it in case it's
                // referencing another resource or a theme value.
                ta.bridgeSetValue(index, attrName, frameworkAttr, mRenderResources.resolveValue(null, attrName, value, isPlatformFile));
            }
        }
    }
    ta.sealArray();
    return ta;
}
Also used : PropertiesMap(com.android.util.PropertiesMap) StyleResourceValue(com.android.ide.common.rendering.api.StyleResourceValue) StyleResourceValue(com.android.ide.common.rendering.api.StyleResourceValue) ResourceValue(com.android.ide.common.rendering.api.ResourceValue) BridgeTypedArray(android.content.res.BridgeTypedArray) Property(com.android.util.PropertiesMap.Property) Pair(com.android.util.Pair)

Example 10 with Pair

use of com.android.util.Pair in project platform_frameworks_base by android.

the class BridgeContext method obtainStyledAttributes.

@Override
public BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
    PropertiesMap defaultPropMap = null;
    boolean isPlatformFile = true;
    // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java
    if (set instanceof BridgeXmlBlockParser) {
        BridgeXmlBlockParser parser;
        parser = (BridgeXmlBlockParser) set;
        isPlatformFile = parser.isPlatformFile();
        Object key = parser.getViewCookie();
        if (key != null) {
            defaultPropMap = mDefaultPropMaps.get(key);
            if (defaultPropMap == null) {
                defaultPropMap = new PropertiesMap();
                mDefaultPropMaps.put(key, defaultPropMap);
            }
        }
    } else if (set instanceof BridgeLayoutParamsMapAttributes) {
        // this is only for temp layout params generated dynamically, so this is never
        // platform content.
        isPlatformFile = false;
    } else if (set != null) {
        // null parser is ok
        // really this should not be happening since its instantiated in Bridge
        Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Parser is not a BridgeXmlBlockParser!", null);
        return null;
    }
    List<Pair<String, Boolean>> attributeList = searchAttrs(attrs);
    BridgeTypedArray ta = Resources_Delegate.newTypeArray(mSystemResources, attrs.length, isPlatformFile);
    // look for a custom style.
    String customStyle = null;
    if (set != null) {
        customStyle = set.getAttributeValue(null, "style");
    }
    StyleResourceValue customStyleValues = null;
    if (customStyle != null) {
        ResourceValue item = mRenderResources.findResValue(customStyle, isPlatformFile);
        // resolve it in case it links to something else
        item = mRenderResources.resolveResValue(item);
        if (item instanceof StyleResourceValue) {
            customStyleValues = (StyleResourceValue) item;
        }
    }
    // resolve the defStyleAttr value into a IStyleResourceValue
    StyleResourceValue defStyleValues = null;
    if (defStyleAttr != 0) {
        // get the name from the int.
        Pair<String, Boolean> defStyleAttribute = searchAttr(defStyleAttr);
        if (defStyleAttribute == null) {
            // This should be rare. Happens trying to map R.style.foo to @style/foo fails.
            // This will happen if the user explicitly used a non existing int value for
            // defStyleAttr or there's something wrong with the project structure/build.
            Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE, "Failed to find the style corresponding to the id " + defStyleAttr, null);
        } else {
            String defStyleName = defStyleAttribute.getFirst();
            // look for the style in the current theme, and its parent:
            ResourceValue item = mRenderResources.findItemInTheme(defStyleName, defStyleAttribute.getSecond());
            if (item != null) {
                // item is a reference to a style entry. Search for it.
                item = mRenderResources.findResValue(item.getValue(), item.isFramework());
                item = mRenderResources.resolveResValue(item);
                if (item instanceof StyleResourceValue) {
                    defStyleValues = (StyleResourceValue) item;
                }
                if (defaultPropMap != null) {
                    if (defStyleAttribute.getSecond()) {
                        defStyleName = "android:" + defStyleName;
                    }
                    defaultPropMap.put("style", new Property(defStyleName, item.getValue()));
                }
            } else {
                Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, String.format("Failed to find style '%s' in current theme", defStyleAttribute.getFirst()), null);
            }
        }
    } else if (defStyleRes != 0) {
        StyleResourceValue item = getStyleByDynamicId(defStyleRes);
        if (item != null) {
            defStyleValues = item;
        } else {
            boolean isFrameworkRes = true;
            Pair<ResourceType, String> value = Bridge.resolveResourceId(defStyleRes);
            if (value == null) {
                value = mLayoutlibCallback.resolveResourceId(defStyleRes);
                isFrameworkRes = false;
            }
            if (value != null) {
                if ((value.getFirst() == ResourceType.STYLE)) {
                    // look for the style in all resources:
                    item = mRenderResources.getStyle(value.getSecond(), isFrameworkRes);
                    if (item != null) {
                        if (defaultPropMap != null) {
                            String name = item.getName();
                            defaultPropMap.put("style", new Property(name, name));
                        }
                        defStyleValues = item;
                    } else {
                        Bridge.getLog().error(null, String.format("Style with id 0x%x (resolved to '%s') does not exist.", defStyleRes, value.getSecond()), null);
                    }
                } else {
                    Bridge.getLog().error(null, String.format("Resource id 0x%x is not of type STYLE (instead %s)", defStyleRes, value.getFirst().toString()), null);
                }
            } else {
                Bridge.getLog().error(null, String.format("Failed to find style with id 0x%x in current theme", defStyleRes), null);
            }
        }
    }
    String appNamespace = mLayoutlibCallback.getNamespace();
    if (attributeList != null) {
        for (int index = 0; index < attributeList.size(); index++) {
            Pair<String, Boolean> attribute = attributeList.get(index);
            if (attribute == null) {
                continue;
            }
            String attrName = attribute.getFirst();
            boolean frameworkAttr = attribute.getSecond();
            String value = null;
            if (set != null) {
                value = set.getAttributeValue(frameworkAttr ? BridgeConstants.NS_RESOURCES : appNamespace, attrName);
                // new res-auto namespace as well
                if (!frameworkAttr && value == null) {
                    value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName);
                }
            }
            // values in the widget defStyle, and then in the theme.
            if (value == null) {
                ResourceValue resValue = null;
                // look for the value in the custom style first (and its parent if needed)
                if (customStyleValues != null) {
                    resValue = mRenderResources.findItemInStyle(customStyleValues, attrName, frameworkAttr);
                }
                // then look for the value in the default Style (and its parent if needed)
                if (resValue == null && defStyleValues != null) {
                    resValue = mRenderResources.findItemInStyle(defStyleValues, attrName, frameworkAttr);
                }
                // its parent themes)
                if (resValue == null) {
                    resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr);
                }
                // So we resolve it.
                if (resValue != null) {
                    String preResolve = resValue.getValue();
                    resValue = mRenderResources.resolveResValue(resValue);
                    if (defaultPropMap != null) {
                        defaultPropMap.put(frameworkAttr ? SdkConstants.PREFIX_ANDROID + attrName : attrName, new Property(preResolve, resValue.getValue()));
                    }
                    // If the value is a reference to another theme attribute that doesn't
                    // exist, we should log a warning and omit it.
                    String val = resValue.getValue();
                    if (val != null && val.startsWith(SdkConstants.PREFIX_THEME_REF)) {
                        if (!attrName.equals(RTL_ATTRS.get(val)) || getApplicationInfo().targetSdkVersion < VERSION_CODES.JELLY_BEAN_MR1) {
                            // Only log a warning if the referenced value isn't one of the RTL
                            // attributes, or the app targets old API.
                            Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR, String.format("Failed to find '%s' in current theme.", val), val);
                        }
                        resValue = null;
                    }
                }
                ta.bridgeSetValue(index, attrName, frameworkAttr, resValue);
            } else {
                // there is a value in the XML, but we need to resolve it in case it's
                // referencing another resource or a theme value.
                ta.bridgeSetValue(index, attrName, frameworkAttr, mRenderResources.resolveValue(null, attrName, value, isPlatformFile));
            }
        }
    }
    ta.sealArray();
    return ta;
}
Also used : PropertiesMap(com.android.util.PropertiesMap) StyleResourceValue(com.android.ide.common.rendering.api.StyleResourceValue) StyleResourceValue(com.android.ide.common.rendering.api.StyleResourceValue) ResourceValue(com.android.ide.common.rendering.api.ResourceValue) BridgeTypedArray(android.content.res.BridgeTypedArray) Property(com.android.util.PropertiesMap.Property) Pair(com.android.util.Pair)

Aggregations

Pair (com.android.util.Pair)13 BridgeTypedArray (android.content.res.BridgeTypedArray)12 ResourceValue (com.android.ide.common.rendering.api.ResourceValue)12 StyleResourceValue (com.android.ide.common.rendering.api.StyleResourceValue)12 PropertiesMap (com.android.util.PropertiesMap)10 Property (com.android.util.PropertiesMap.Property)10 BridgeResources (android.content.res.BridgeResources)2 VisibleForTesting (com.android.annotations.VisibleForTesting)1 IntArrayWrapper (com.android.ide.common.resources.IntArrayWrapper)1 ResourceType (com.android.resources.ResourceType)1 AppResourceRepository (com.android.tools.idea.res.AppResourceRepository)1 TIntObjectHashMap (gnu.trove.TIntObjectHashMap)1 TObjectIntHashMap (gnu.trove.TObjectIntHashMap)1 EnumMap (java.util.EnumMap)1 HashMap (java.util.HashMap)1