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

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

Merge "Add error checking to aapt for split generation" into lmp-mr1-dev

parents 3f36ba64 de7de47f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -3645,8 +3645,12 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag
    Entry entry;
    status_t err = getEntry(grp, t, e, &desiredConfig, &entry);
    if (err != NO_ERROR) {
        // Only log the failure when we're not running on the host as
        // part of a tool. The caller will do its own logging.
#ifndef STATIC_ANDROIDFW_FOR_TOOLS
        ALOGW("Failure getting entry for 0x%08x (t=%d e=%d) (error %d)\n",
                resID, t, e, err);
#endif
        return err;
    }

+19 −0
Original line number Diff line number Diff line
@@ -794,4 +794,23 @@ bool isSameExcept(const ResTable_config& a, const ResTable_config& b, int axisMa
    return a.diff(b) == axisMask;
}

bool isDensityOnly(const ResTable_config& config) {
    if (config.density == ResTable_config::DENSITY_NONE) {
        return false;
    }

    if (config.density == ResTable_config::DENSITY_ANY) {
        if (config.sdkVersion != SDK_L) {
            // Someone modified the sdkVersion from the default, this is not safe to assume.
            return false;
        }
    } else if (config.sdkVersion != SDK_DONUT) {
        return false;
    }

    const uint32_t mask = ResTable_config::CONFIG_DENSITY | ResTable_config::CONFIG_VERSION;
    const ConfigDescription nullConfig;
    return (nullConfig.diff(config) & ~mask) == 0;
}

} // namespace AaptConfig
+6 −0
Original line number Diff line number Diff line
@@ -80,6 +80,12 @@ android::String8 getVersion(const android::ResTable_config& config);
 */
bool isSameExcept(const android::ResTable_config& a, const android::ResTable_config& b, int configMask);

/**
 * Returns true if the configuration only has the density specified. In the case
 * of 'anydpi', the version is ignored.
 */
bool isDensityOnly(const android::ResTable_config& config);

} // namespace AaptConfig

#endif // __AAPT_CONFIG_H
+69 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
// Build resource files from raw assets.
//
#include "AaptAssets.h"
#include "AaptUtil.h"
#include "AaptXml.h"
#include "CacheUpdater.h"
#include "CrunchCache.h"
@@ -13,9 +14,12 @@
#include "Main.h"
#include "ResourceTable.h"
#include "StringPool.h"
#include "Symbol.h"
#include "WorkQueue.h"
#include "XMLNode.h"

#include <algorithm>

#if HAVE_PRINTF_ZD
#  define ZD "%zd"
#  define ZD_TYPE ssize_t
@@ -1550,6 +1554,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil
    // Re-flatten because we may have added new resource IDs
    // --------------------------------------------------------------


    ResTable finalResTable;
    sp<AaptFile> resFile;
    
@@ -1560,6 +1565,13 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil
            return err;
        }

        KeyedVector<Symbol, Vector<SymbolDefinition> > densityVaryingResources;
        if (builder->getSplits().size() > 1) {
            // Only look for density varying resources if we're generating
            // splits.
            table.getDensityVaryingResources(densityVaryingResources);
        }

        Vector<sp<ApkSplit> >& splits = builder->getSplits();
        const size_t numSplits = splits.size();
        for (size_t i = 0; i < numSplits; i++) {
@@ -1583,6 +1595,63 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil
                    return err;
                }
            } else {
                ResTable resTable;
                err = resTable.add(flattenedTable->getData(), flattenedTable->getSize());
                if (err != NO_ERROR) {
                    fprintf(stderr, "Generated resource table for split '%s' is corrupt.\n",
                            split->getPrintableName().string());
                    return err;
                }

                bool hasError = false;
                const std::set<ConfigDescription>& splitConfigs = split->getConfigs();
                for (std::set<ConfigDescription>::const_iterator iter = splitConfigs.begin();
                        iter != splitConfigs.end();
                        ++iter) {
                    const ConfigDescription& config = *iter;
                    if (AaptConfig::isDensityOnly(config)) {
                        // Each density only split must contain all
                        // density only resources.
                        Res_value val;
                        resTable.setParameters(&config);
                        const size_t densityVaryingResourceCount = densityVaryingResources.size();
                        for (size_t k = 0; k < densityVaryingResourceCount; k++) {
                            const Symbol& symbol = densityVaryingResources.keyAt(k);
                            ssize_t block = resTable.getResource(symbol.id, &val, true);
                            if (block < 0) {
                                // Maybe it's in the base?
                                finalResTable.setParameters(&config);
                                block = finalResTable.getResource(symbol.id, &val, true);
                            }

                            if (block < 0) {
                                hasError = true;
                                SourcePos().error("%s has no definition for density split '%s'",
                                        symbol.toString().string(), config.toString().string());

                                if (bundle->getVerbose()) {
                                    const Vector<SymbolDefinition>& defs = densityVaryingResources[k];
                                    const size_t defCount = std::min(size_t(5), defs.size());
                                    for (size_t d = 0; d < defCount; d++) {
                                        const SymbolDefinition& def = defs[d];
                                        def.source.error("%s has definition for %s",
                                                symbol.toString().string(), def.config.toString().string());
                                    }

                                    if (defCount < defs.size()) {
                                        SourcePos().error("and %d more ...", (int) (defs.size() - defCount));
                                    }
                                }
                            }
                        }
                    }
                }

                if (hasError) {
                    return UNKNOWN_ERROR;
                }

                // Generate the AndroidManifest for this split.
                sp<AaptFile> generatedManifest = new AaptFile(String8("AndroidManifest.xml"),
                        AaptGroupEntry(), String8());
                err = generateAndroidManifestForSplit(bundle, assets, split,
+32 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@

#include "ResourceTable.h"

#include "AaptUtil.h"
#include "XMLNode.h"
#include "ResourceFilter.h"
#include "ResourceIdCache.h"
@@ -4486,3 +4487,34 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle,

    return NO_ERROR;
}

void ResourceTable::getDensityVaryingResources(KeyedVector<Symbol, Vector<SymbolDefinition> >& resources) {
    const ConfigDescription nullConfig;

    const size_t packageCount = mOrderedPackages.size();
    for (size_t p = 0; p < packageCount; p++) {
        const Vector<sp<Type> >& types = mOrderedPackages[p]->getOrderedTypes();
        const size_t typeCount = types.size();
        for (size_t t = 0; t < typeCount; t++) {
            const Vector<sp<ConfigList> >& configs = types[t]->getOrderedConfigs();
            const size_t configCount = configs.size();
            for (size_t c = 0; c < configCount; c++) {
                const DefaultKeyedVector<ConfigDescription, sp<Entry> >& configEntries = configs[c]->getEntries();
                const size_t configEntryCount = configEntries.size();
                for (size_t ce = 0; ce < configEntryCount; ce++) {
                    const ConfigDescription& config = configEntries.keyAt(ce);
                    if (AaptConfig::isDensityOnly(config)) {
                        // This configuration only varies with regards to density.
                        const Symbol symbol(mOrderedPackages[p]->getName(),
                                types[t]->getName(),
                                configs[c]->getName(),
                                getResId(mOrderedPackages[p], types[t], configs[c]->getEntryIndex()));

                        const sp<Entry>& entry = configEntries.valueAt(ce);
                        AaptUtil::appendValue(resources, symbol, SymbolDefinition(symbol, config, entry->getPos()));
                    }
                }
            }
        }
    }
}
Loading