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

Commit 57e19505 authored by Adam Lesinski's avatar Adam Lesinski Committed by Android (Google) Code Review
Browse files

Merge "Move attribute resolution from core/jni to libandroidfw"

parents 660883de 4452e137
Loading
Loading
Loading
Loading
+24 −458
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@

#include "androidfw/Asset.h"
#include "androidfw/AssetManager.h"
#include "androidfw/AttributeFinder.h"
#include "androidfw/AttributeResolution.h"
#include "androidfw/ResourceTypes.h"
#include "android_runtime/AndroidRuntime.h"
#include "android_util_Binder.h"
@@ -51,7 +51,6 @@ extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
namespace android {

static const bool kThrowOnBadId = false;
static const bool kDebugStyles = false;

// ----------------------------------------------------------------------------

@@ -1121,30 +1120,6 @@ static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
    theme->dumpToLog();
}

class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, jsize> {
public:
    explicit XmlAttributeFinder(const ResXMLParser* parser)
        : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0)
        , mParser(parser) {}

    inline uint32_t getAttribute(jsize index) const {
        return mParser->getAttributeNameResID(index);
    }

private:
    const ResXMLParser* mParser;
};

class BagAttributeFinder : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
public:
    BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
        : BackTrackingAttributeFinder(start, end) {}

    inline uint32_t getAttribute(const ResTable::bag_entry* entry) const {
        return entry->map.name.ident;
    }
};

static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
                                                          jlong themeToken,
                                                          jint defStyleAttr,
@@ -1167,16 +1142,6 @@ static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject c
        return JNI_FALSE;
    }

    if (kDebugStyles) {
        ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x "
              "defStyleRes=0x%x", themeToken, defStyleAttr, defStyleRes);
    }

    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
    const ResTable& res = theme->getResTable();
    ResTable_config config;
    Res_value value;

    const jsize NI = env->GetArrayLength(attrs);
    const jsize NV = env->GetArrayLength(outValues);
    if (NV < (NI*STYLE_NUM_ENTRIES)) {
@@ -1193,159 +1158,32 @@ static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject c
    const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);

    jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
    jint* dest = baseDest;
    if (dest == NULL) {
    if (baseDest == NULL) {
        env->ReleasePrimitiveArrayCritical(attrs, src, 0);
        return JNI_FALSE;
    }

    jint* indices = NULL;
    int indicesIdx = 0;
    if (outIndices != NULL) {
        if (env->GetArrayLength(outIndices) > NI) {
            indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
        }
    }

    // Load default style from attribute, if specified...
    uint32_t defStyleBagTypeSetFlags = 0;
    if (defStyleAttr != 0) {
        Res_value value;
        if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
            if (value.dataType == Res_value::TYPE_REFERENCE) {
                defStyleRes = value.data;
            }
        }
    }

    // Now lock down the resource object and start pulling stuff from it.
    res.lock();

    // Retrieve the default style bag, if requested.
    const ResTable::bag_entry* defStyleStart = NULL;
    uint32_t defStyleTypeSetFlags = 0;
    ssize_t bagOff = defStyleRes != 0
            ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
    defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
    const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
    BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);

    // Now iterate through all of the attributes that the client has requested,
    // filling in each with whatever data we can find.
    ssize_t block = 0;
    uint32_t typeSetFlags;
    for (jsize ii=0; ii<NI; ii++) {
        const uint32_t curIdent = (uint32_t)src[ii];

        if (kDebugStyles) {
            ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
        }

        // Try to find a value for this attribute...  we prioritize values
        // coming from, first XML attributes, then XML style, then default
        // style, and finally the theme.
        value.dataType = Res_value::TYPE_NULL;
        value.data = Res_value::DATA_NULL_UNDEFINED;
        typeSetFlags = 0;
        config.density = 0;

        // Retrieve the current input value if available.
        if (NSV > 0 && srcValues[ii] != 0) {
            block = -1;
            value.dataType = Res_value::TYPE_ATTRIBUTE;
            value.data = srcValues[ii];
            if (kDebugStyles) {
                ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
            }
        }

        if (value.dataType == Res_value::TYPE_NULL) {
            const ResTable::bag_entry* const defStyleEntry = defStyleAttrFinder.find(curIdent);
            if (defStyleEntry != defStyleEnd) {
                block = defStyleEntry->stringBlock;
                typeSetFlags = defStyleTypeSetFlags;
                value = defStyleEntry->map.value;
                if (kDebugStyles) {
                    ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
                }
            }
        }

        uint32_t resid = 0;
        if (value.dataType != Res_value::TYPE_NULL) {
            // Take care of resolving the found resource to its final value.
            ssize_t newBlock = theme->resolveAttributeReference(&value, block,
                    &resid, &typeSetFlags, &config);
            if (newBlock >= 0) block = newBlock;
            if (kDebugStyles) {
                ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
            }
        } else {
            // If we still don't have a value for this attribute, try to find
            // it in the theme!
            ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
            if (newBlock >= 0) {
                if (kDebugStyles) {
                    ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
                }
                newBlock = res.resolveReference(&value, block, &resid,
                        &typeSetFlags, &config);
                if (kThrowOnBadId) {
                    if (newBlock == BAD_INDEX) {
                        jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
                        return JNI_FALSE;
                    }
                }
                if (newBlock >= 0) block = newBlock;
                if (kDebugStyles) {
                    ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
                }
            }
        }

        // Deal with the special @null value -- it turns back to TYPE_NULL.
        if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
            if (kDebugStyles) {
                ALOGI("-> Setting to @null!");
            }
            value.dataType = Res_value::TYPE_NULL;
            value.data = Res_value::DATA_NULL_UNDEFINED;
            block = -1;
        }

        if (kDebugStyles) {
            ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
                  value.data);
        }

        // Write the final value back to Java.
        dest[STYLE_TYPE] = value.dataType;
        dest[STYLE_DATA] = value.data;
        dest[STYLE_ASSET_COOKIE] =
            block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
        dest[STYLE_RESOURCE_ID] = resid;
        dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
        dest[STYLE_DENSITY] = config.density;

        if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
            indicesIdx++;
            indices[indicesIdx] = ii;
        }

        dest += STYLE_NUM_ENTRIES;
    }

    res.unlock();
    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
    bool result = resolveAttrs(theme, defStyleAttr, defStyleRes,
                               (uint32_t*) srcValues, NSV,
                               (uint32_t*) src, NI,
                               (uint32_t*) baseDest,
                               (uint32_t*) indices);

    if (indices != NULL) {
        indices[0] = indicesIdx;
        env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
    }
    env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
    env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
    env->ReleasePrimitiveArrayCritical(attrs, src, 0);

    return JNI_TRUE;
    return result ? JNI_TRUE : JNI_FALSE;
}

static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
@@ -1370,18 +1208,6 @@ static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject cla
        return JNI_FALSE;
    }

    if (kDebugStyles) {
    ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x defStyleRes=0x%x "
          "xml=0x%" PRIx64, themeToken, defStyleAttr, defStyleRes,
          xmlParserToken);
    }

    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
    const ResTable& res = theme->getResTable();
    ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
    ResTable_config config;
    Res_value value;

    const jsize NI = env->GetArrayLength(attrs);
    const jsize NV = env->GetArrayLength(outValues);
    if (NV < (NI*STYLE_NUM_ENTRIES)) {
@@ -1395,211 +1221,32 @@ static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject cla
    }

    jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
    jint* dest = baseDest;
    if (dest == NULL) {
    if (baseDest == NULL) {
        env->ReleasePrimitiveArrayCritical(attrs, src, 0);
        return JNI_FALSE;
    }

    jint* indices = NULL;
    int indicesIdx = 0;
    if (outIndices != NULL) {
        if (env->GetArrayLength(outIndices) > NI) {
            indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
        }
    }

    // Load default style from attribute, if specified...
    uint32_t defStyleBagTypeSetFlags = 0;
    if (defStyleAttr != 0) {
        Res_value value;
        if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
            if (value.dataType == Res_value::TYPE_REFERENCE) {
                defStyleRes = value.data;
            }
        }
    }

    // Retrieve the style class associated with the current XML tag.
    int style = 0;
    uint32_t styleBagTypeSetFlags = 0;
    if (xmlParser != NULL) {
        ssize_t idx = xmlParser->indexOfStyle();
        if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
            if (value.dataType == value.TYPE_ATTRIBUTE) {
                if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
                    value.dataType = Res_value::TYPE_NULL;
                }
            }
            if (value.dataType == value.TYPE_REFERENCE) {
                style = value.data;
            }
        }
    }

    // Now lock down the resource object and start pulling stuff from it.
    res.lock();

    // Retrieve the default style bag, if requested.
    const ResTable::bag_entry* defStyleAttrStart = NULL;
    uint32_t defStyleTypeSetFlags = 0;
    ssize_t bagOff = defStyleRes != 0
            ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
    defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
    const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
    BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);

    // Retrieve the style class bag, if requested.
    const ResTable::bag_entry* styleAttrStart = NULL;
    uint32_t styleTypeSetFlags = 0;
    bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
    styleTypeSetFlags |= styleBagTypeSetFlags;
    const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
    BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);

    // Retrieve the XML attributes, if requested.
    static const ssize_t kXmlBlock = 0x10000000;
    XmlAttributeFinder xmlAttrFinder(xmlParser);
    const jsize xmlAttrEnd = xmlParser != NULL ? xmlParser->getAttributeCount() : 0;

    // Now iterate through all of the attributes that the client has requested,
    // filling in each with whatever data we can find.
    ssize_t block = 0;
    uint32_t typeSetFlags;
    for (jsize ii = 0; ii < NI; ii++) {
        const uint32_t curIdent = (uint32_t)src[ii];

        if (kDebugStyles) {
            ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
        }

        // Try to find a value for this attribute...  we prioritize values
        // coming from, first XML attributes, then XML style, then default
        // style, and finally the theme.
        value.dataType = Res_value::TYPE_NULL;
        value.data = Res_value::DATA_NULL_UNDEFINED;
        typeSetFlags = 0;
        config.density = 0;

        // Walk through the xml attributes looking for the requested attribute.
        const jsize xmlAttrIdx = xmlAttrFinder.find(curIdent);
        if (xmlAttrIdx != xmlAttrEnd) {
            // We found the attribute we were looking for.
            block = kXmlBlock;
            xmlParser->getAttributeValue(xmlAttrIdx, &value);
            if (kDebugStyles) {
                ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
            }
        }

        if (value.dataType == Res_value::TYPE_NULL) {
            // Walk through the style class values looking for the requested attribute.
            const ResTable::bag_entry* const styleAttrEntry = styleAttrFinder.find(curIdent);
            if (styleAttrEntry != styleAttrEnd) {
                // We found the attribute we were looking for.
                block = styleAttrEntry->stringBlock;
                typeSetFlags = styleTypeSetFlags;
                value = styleAttrEntry->map.value;
                if (kDebugStyles) {
                    ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
                }
            }
        }

        if (value.dataType == Res_value::TYPE_NULL) {
            // Walk through the default style values looking for the requested attribute.
            const ResTable::bag_entry* const defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
            if (defStyleAttrEntry != defStyleAttrEnd) {
                // We found the attribute we were looking for.
                block = defStyleAttrEntry->stringBlock;
                typeSetFlags = styleTypeSetFlags;
                value = defStyleAttrEntry->map.value;
                if (kDebugStyles) {
                    ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
                }
            }
        }

        uint32_t resid = 0;
        if (value.dataType != Res_value::TYPE_NULL) {
            // Take care of resolving the found resource to its final value.
            ssize_t newBlock = theme->resolveAttributeReference(&value, block,
                    &resid, &typeSetFlags, &config);
            if (newBlock >= 0) {
                block = newBlock;
            }

            if (kDebugStyles) {
                ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
            }
        } else {
            // If we still don't have a value for this attribute, try to find
            // it in the theme!
            ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
            if (newBlock >= 0) {
                if (kDebugStyles) {
                    ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
                }
                newBlock = res.resolveReference(&value, block, &resid,
                        &typeSetFlags, &config);
                if (kThrowOnBadId) {
                    if (newBlock == BAD_INDEX) {
                        jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
                        return JNI_FALSE;
                    }
                }

                if (newBlock >= 0) {
                    block = newBlock;
                }

                if (kDebugStyles) {
                    ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
                }
            }
        }

        // Deal with the special @null value -- it turns back to TYPE_NULL.
        if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
            if (kDebugStyles) {
                ALOGI("-> Setting to @null!");
            }
            value.dataType = Res_value::TYPE_NULL;
            value.data = Res_value::DATA_NULL_UNDEFINED;
            block = kXmlBlock;
        }

        if (kDebugStyles) {
            ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
        }

        // Write the final value back to Java.
        dest[STYLE_TYPE] = value.dataType;
        dest[STYLE_DATA] = value.data;
        dest[STYLE_ASSET_COOKIE] = block != kXmlBlock ?
            static_cast<jint>(res.getTableCookie(block)) : -1;
        dest[STYLE_RESOURCE_ID] = resid;
        dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
        dest[STYLE_DENSITY] = config.density;

        if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
            indicesIdx++;
            indices[indicesIdx] = ii;
        }

        dest += STYLE_NUM_ENTRIES;
    }

    res.unlock();
    ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
    ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
    bool result = applyStyle(theme, xmlParser,
                             defStyleAttr, defStyleRes,
                             (uint32_t*) src, NI,
                             (uint32_t*) baseDest,
                             (uint32_t*) indices);

    if (indices != NULL) {
        indices[0] = indicesIdx;
        env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
    }
    env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
    env->ReleasePrimitiveArrayCritical(attrs, src, 0);

    return JNI_TRUE;
    return result ? JNI_TRUE : JNI_FALSE;
}

static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
@@ -1627,8 +1274,6 @@ static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, job
    }
    const ResTable& res(am->getResources());
    ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
    ResTable_config config;
    Res_value value;

    const jsize NI = env->GetArrayLength(attrs);
    const jsize NV = env->GetArrayLength(outValues);
@@ -1643,108 +1288,29 @@ static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, job
    }

    jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
    jint* dest = baseDest;
    if (dest == NULL) {
    if (baseDest == NULL) {
        env->ReleasePrimitiveArrayCritical(attrs, src, 0);
        return JNI_FALSE;
    }

    jint* indices = NULL;
    int indicesIdx = 0;
    if (outIndices != NULL) {
        if (env->GetArrayLength(outIndices) > NI) {
            indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
        }
    }

    // Now lock down the resource object and start pulling stuff from it.
    res.lock();

    // Retrieve the XML attributes, if requested.
    const jsize NX = xmlParser->getAttributeCount();
    jsize ix=0;
    uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);

    static const ssize_t kXmlBlock = 0x10000000;

    // Now iterate through all of the attributes that the client has requested,
    // filling in each with whatever data we can find.
    ssize_t block = 0;
    uint32_t typeSetFlags;
    for (jsize ii=0; ii<NI; ii++) {
        const uint32_t curIdent = (uint32_t)src[ii];

        // Try to find a value for this attribute...
        value.dataType = Res_value::TYPE_NULL;
        value.data = Res_value::DATA_NULL_UNDEFINED;
        typeSetFlags = 0;
        config.density = 0;

        // Skip through XML attributes until the end or the next possible match.
        while (ix < NX && curIdent > curXmlAttr) {
            ix++;
            curXmlAttr = xmlParser->getAttributeNameResID(ix);
        }
        // Retrieve the current XML attribute if it matches, and step to next.
        if (ix < NX && curIdent == curXmlAttr) {
            block = kXmlBlock;
            xmlParser->getAttributeValue(ix, &value);
            ix++;
            curXmlAttr = xmlParser->getAttributeNameResID(ix);
        }

        //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
        uint32_t resid = 0;
        if (value.dataType != Res_value::TYPE_NULL) {
            // Take care of resolving the found resource to its final value.
            //printf("Resolving attribute reference\n");
            ssize_t newBlock = res.resolveReference(&value, block, &resid,
                    &typeSetFlags, &config);
            if (kThrowOnBadId) {
                if (newBlock == BAD_INDEX) {
                    jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
                    return JNI_FALSE;
                }
            }
            if (newBlock >= 0) block = newBlock;
        }

        // Deal with the special @null value -- it turns back to TYPE_NULL.
        if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
            value.dataType = Res_value::TYPE_NULL;
            value.data = Res_value::DATA_NULL_UNDEFINED;
        }

        //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);

        // Write the final value back to Java.
        dest[STYLE_TYPE] = value.dataType;
        dest[STYLE_DATA] = value.data;
        dest[STYLE_ASSET_COOKIE] =
            block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
        dest[STYLE_RESOURCE_ID] = resid;
        dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
        dest[STYLE_DENSITY] = config.density;

        if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
            indicesIdx++;
            indices[indicesIdx] = ii;
        }

        dest += STYLE_NUM_ENTRIES;
    }

    res.unlock();
    bool result = retrieveAttributes(&res, xmlParser,
                                     (uint32_t*) src, NI,
                                     (uint32_t*) baseDest,
                                     (uint32_t*) indices);

    if (indices != NULL) {
        indices[0] = indicesIdx;
        env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
    }

    env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
    env->ReleasePrimitiveArrayCritical(attrs, src, 0);

    return JNI_TRUE;
    return result ? JNI_TRUE : JNI_FALSE;
}

static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
+53 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROIDFW_ATTRIBUTERESOLUTION_H
#define ANDROIDFW_ATTRIBUTERESOLUTION_H

#include <androidfw/ResourceTypes.h>

namespace android {

// These are all variations of the same method. They each perform the exact same operation,
// but on various data sources. I *think* they are re-written to avoid an extra branch
// in the inner loop, but after one branch miss (some pointer != null), the branch predictor should
// predict the rest of the iterations' branch correctly.
// TODO(adamlesinski): Run performance tests against these methods and a new, single method
// that uses all the sources and branches to the right ones within the inner loop.

bool resolveAttrs(ResTable::Theme* theme,
                  uint32_t defStyleAttr,
                  uint32_t defStyleRes,
                  uint32_t* srcValues, size_t srcValuesLength,
                  uint32_t* attrs, size_t attrsLength,
                  uint32_t* outValues,
                  uint32_t* outIndices);

bool applyStyle(ResTable::Theme* theme, ResXMLParser* xmlParser,
                uint32_t defStyleAttr,
                uint32_t defStyleRes,
                uint32_t* attrs, size_t attrsLength,
                uint32_t* outValues,
                uint32_t* outIndices);

bool retrieveAttributes(const ResTable* res, ResXMLParser* xmlParser,
                        uint32_t* attrs, size_t attrsLength,
                        uint32_t* outValues,
                        uint32_t* outIndices);

} // namespace android

#endif /* ANDROIDFW_ATTRIBUTERESOLUTION_H */
+1 −0

File changed.

Preview size limit exceeded, changes collapsed.

+500 −0

File added.

Preview size limit exceeded, changes collapsed.