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

Commit 6a008170 authored by Adam Lesinski's avatar Adam Lesinski
Browse files

AAPT2: Support -c configuration filtering

Change-Id: I1e5855ca73440bdc30c21bcbc1dfdd31a9842363
parent e909d94e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ sources := \
	compile/PseudolocaleGenerator.cpp \
	compile/Pseudolocalizer.cpp \
	compile/XmlIdCollector.cpp \
	filter/ConfigFilter.cpp \
	flatten/Archive.cpp \
	flatten/TableFlattener.cpp \
	flatten/XmlFlattener.cpp \
@@ -71,6 +72,7 @@ testSources := \
	compile/PseudolocaleGenerator_test.cpp \
	compile/Pseudolocalizer_test.cpp \
	compile/XmlIdCollector_test.cpp \
	filter/ConfigFilter_test.cpp \
	flatten/FileExportWriter_test.cpp \
	flatten/TableFlattener_test.cpp \
	flatten/XmlFlattener_test.cpp \
+1 −1
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ static inline bool isNumber(const std::string& str) {
    return std::all_of(std::begin(str), std::end(str), ::isdigit);
}

bool LocaleValue::initFromFilterString(const std::string& str) {
bool LocaleValue::initFromFilterString(const StringPiece& str) {
     // A locale (as specified in the filter) is an underscore separated name such
     // as "en_US", "en_Latn_US", or "en_US_POSIX".
     std::vector<std::string> parts = util::splitAndLowercase(str, '_');
+3 −1
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
#ifndef AAPT_LOCALE_VALUE_H
#define AAPT_LOCALE_VALUE_H

#include "util/StringPiece.h"

#include <androidfw/ResourceTypes.h>
#include <string>
#include <vector>
@@ -37,7 +39,7 @@ struct LocaleValue {
    /**
     * Initialize this LocaleValue from a config string.
     */
    bool initFromFilterString(const std::string& config);
    bool initFromFilterString(const StringPiece& config);

    /**
     * Initialize this LocaleValue from parts of a vector.
+77 −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.
 */

#include "ConfigDescription.h"
#include "filter/ConfigFilter.h"

#include <androidfw/ResourceTypes.h>

namespace aapt {

void AxisConfigFilter::addConfig(ConfigDescription config) {
    uint32_t diffMask = ConfigDescription::defaultConfig().diff(config);

    // Ignore the version
    diffMask &= ~android::ResTable_config::CONFIG_VERSION;

    // Ignore any densities. Those are best handled in --preferred-density
    if ((diffMask & android::ResTable_config::CONFIG_DENSITY) != 0) {
        config.density = 0;
        diffMask &= ~android::ResTable_config::CONFIG_DENSITY;
    }

    mConfigs.insert(std::make_pair(config, diffMask));
    mConfigMask |= diffMask;
}

bool AxisConfigFilter::match(const ConfigDescription& config) const {
    const uint32_t mask = ConfigDescription::defaultConfig().diff(config);
    if ((mConfigMask & mask) == 0) {
        // The two configurations don't have any common axis.
        return true;
    }

    uint32_t matchedAxis = 0;
    for (const auto& entry : mConfigs) {
        const ConfigDescription& target = entry.first;
        const uint32_t diffMask = entry.second;
        uint32_t diff = target.diff(config);
        if ((diff & diffMask) == 0) {
            // Mark the axis that was matched.
            matchedAxis |= diffMask;
        } else if ((diff & diffMask) == android::ResTable_config::CONFIG_LOCALE) {
            // If the locales differ, but the languages are the same and
            // the locale we are matching only has a language specified,
            // we match.
            if (config.language[0] &&
                    memcmp(config.language, target.language, sizeof(config.language)) == 0) {
                if (config.country[0] == 0) {
                    matchedAxis |= android::ResTable_config::CONFIG_LOCALE;
                }
            }
        } else if ((diff & diffMask) == android::ResTable_config::CONFIG_SMALLEST_SCREEN_SIZE) {
            // Special case if the smallest screen width doesn't match. We check that the
            // config being matched has a smaller screen width than the filter specified.
            if (config.smallestScreenWidthDp != 0 &&
                    config.smallestScreenWidthDp < target.smallestScreenWidthDp) {
                matchedAxis |= android::ResTable_config::CONFIG_SMALLEST_SCREEN_SIZE;
            }
        }
    }
    return matchedAxis == (mConfigMask & mask);
}

} // namespace aapt
+61 −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 AAPT_FILTER_CONFIGFILTER_H
#define AAPT_FILTER_CONFIGFILTER_H

#include "ConfigDescription.h"

#include <set>
#include <utility>

namespace aapt {

/**
 * Matches ConfigDescriptions based on some pattern.
 */
class IConfigFilter {
public:
    virtual ~IConfigFilter() = default;

    /**
     * Returns true if the filter matches the configuration, false otherwise.
     */
    virtual bool match(const ConfigDescription& config) const = 0;
};

/**
 * Implements config axis matching. An axis is one component of a configuration, like screen
 * density or locale. If an axis is specified in the filter, and the axis is specified in
 * the configuration to match, they must be compatible. Otherwise the configuration to match is
 * accepted.
 *
 * Used when handling "-c" options.
 */
class AxisConfigFilter : public IConfigFilter {
public:
    void addConfig(ConfigDescription config);

    bool match(const ConfigDescription& config) const override;

private:
    std::set<std::pair<ConfigDescription, uint32_t>> mConfigs;
    uint32_t mConfigMask = 0;
};

} // namespace aapt

#endif /* AAPT_FILTER_CONFIGFILTER_H */
Loading