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

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

Merge "AssetManager: Cache a pre-filtered list of configurations" into nyc-dev

parents 5d9de3ab d4b16917
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -1896,6 +1896,13 @@ private:

    mutable Mutex               mLock;

    // Mutex that controls access to the list of pre-filtered configurations
    // to check when looking up entries.
    // When iterating over a bag, the mLock mutex is locked. While mLock is locked,
    // we do resource lookups.
    // Mutex is not reentrant, so we must use a different lock than mLock.
    mutable Mutex               mFilteredConfigLock;

    status_t                    mError;

    ResTable_config             mParams;
+61 −7
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <string.h>

#include <limits>
#include <memory>
#include <type_traits>

#include <androidfw/ByteBucketArray.h>
@@ -3146,6 +3147,9 @@ struct ResTable::Entry {
    StringPoolRef keyStr;
};

template <typename T>
using SharedVector = std::shared_ptr<Vector<T>>;

struct ResTable::Type
{
    Type(const Header* _header, const Package* _package, size_t count)
@@ -3158,6 +3162,10 @@ struct ResTable::Type
    const uint32_t*                 typeSpecFlags;
    IdmapEntries                    idmapEntries;
    Vector<const ResTable_type*>    configs;

    // The set of configurations that match the current parameters.
    // This will be swapped with a new set when the parameters change.
    SharedVector<const ResTable_type*> filteredConfigs;
};

struct ResTable::Package
@@ -4430,18 +4438,44 @@ ssize_t ResTable::getBagLocked(uint32_t resID, const bag_entry** outBag,

void ResTable::setParameters(const ResTable_config* params)
{
    mLock.lock();
    AutoMutex _lock(mLock);
    AutoMutex _lock2(mFilteredConfigLock);

    if (kDebugTableGetEntry) {
        ALOGI("Setting parameters: %s\n", params->toString().string());
    }
    mParams = *params;
    for (size_t i=0; i<mPackageGroups.size(); i++) {
    for (size_t p = 0; p < mPackageGroups.size(); p++) {
        PackageGroup* packageGroup = mPackageGroups.editItemAt(p);
        if (kDebugTableNoisy) {
            ALOGI("CLEARING BAGS FOR GROUP %zu!", i);
            ALOGI("CLEARING BAGS FOR GROUP %zu!", p);
        }
        packageGroup->clearBagCache();

        for (size_t t = 0; t < packageGroup->types.size(); t++) {
            TypeList& typeList = packageGroup->types.editItemAt(t);
            for (size_t ts = 0; ts < typeList.size(); ts++) {
                Type* type = typeList.editItemAt(ts);

                SharedVector<const ResTable_type*> newFilteredConfigs =
                        std::make_shared<Vector<const ResTable_type*>>();
                for (size_t ti = 0; ti < type->configs.size(); ti++) {
                    ResTable_config config;
                    config.copyFromDtoH(type->configs[ti]->config);

                    if (config.match(mParams)) {
                        newFilteredConfigs->add(type->configs[ti]);
                    }
                }

                if (kDebugTableNoisy) {
                    ALOGD("Updating pkg=%zu type=%zu with %zu filtered configs",
                          p, t, newFilteredConfigs->size());
                }
                type->filteredConfigs = newFilteredConfigs;
            }
        }
        mPackageGroups[i]->clearBagCache();
    }
    mLock.unlock();
}

void ResTable::getParameters(ResTable_config* params) const
@@ -5974,9 +6008,29 @@ status_t ResTable::getEntry(
            specFlags = -1;
        }

        const size_t numConfigs = typeSpec->configs.size();
        const Vector<const ResTable_type*>* candidateConfigs = &typeSpec->configs;

        SharedVector<const ResTable_type*> filteredConfigs;
        if (config && memcmp(&mParams, config, sizeof(mParams)) == 0) {
            // Grab the lock first so we can safely get the current filtered list.
            AutoMutex _lock(mFilteredConfigLock);

            // This configuration is equal to the one we have previously cached for,
            // so use the filtered configs.

            if (typeSpec->filteredConfigs) {
                // Grab a reference to the shared_ptr so it doesn't get destroyed while
                // going through this list.
                filteredConfigs = typeSpec->filteredConfigs;

                // Use this filtered list.
                candidateConfigs = filteredConfigs.get();
            }
        }

        const size_t numConfigs = candidateConfigs->size();
        for (size_t c = 0; c < numConfigs; c++) {
            const ResTable_type* const thisType = typeSpec->configs[c];
            const ResTable_type* const thisType = candidateConfigs->itemAt(c);
            if (thisType == NULL) {
                continue;
            }