[go: nahoru, domu]

1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "ConfigDescription.h"
18#include "filter/ConfigFilter.h"
19
20#include <androidfw/ResourceTypes.h>
21
22namespace aapt {
23
24void AxisConfigFilter::addConfig(ConfigDescription config) {
25    uint32_t diffMask = ConfigDescription::defaultConfig().diff(config);
26
27    // Ignore the version
28    diffMask &= ~android::ResTable_config::CONFIG_VERSION;
29
30    // Ignore any densities. Those are best handled in --preferred-density
31    if ((diffMask & android::ResTable_config::CONFIG_DENSITY) != 0) {
32        config.density = 0;
33        diffMask &= ~android::ResTable_config::CONFIG_DENSITY;
34    }
35
36    mConfigs.insert(std::make_pair(config, diffMask));
37    mConfigMask |= diffMask;
38}
39
40bool AxisConfigFilter::match(const ConfigDescription& config) const {
41    const uint32_t mask = ConfigDescription::defaultConfig().diff(config);
42    if ((mConfigMask & mask) == 0) {
43        // The two configurations don't have any common axis.
44        return true;
45    }
46
47    uint32_t matchedAxis = 0;
48    for (const auto& entry : mConfigs) {
49        const ConfigDescription& target = entry.first;
50        const uint32_t diffMask = entry.second;
51        uint32_t diff = target.diff(config);
52        if ((diff & diffMask) == 0) {
53            // Mark the axis that was matched.
54            matchedAxis |= diffMask;
55        } else if ((diff & diffMask) == android::ResTable_config::CONFIG_LOCALE) {
56            // If the locales differ, but the languages are the same and
57            // the locale we are matching only has a language specified,
58            // we match.
59            if (config.language[0] &&
60                    memcmp(config.language, target.language, sizeof(config.language)) == 0) {
61                if (config.country[0] == 0) {
62                    matchedAxis |= android::ResTable_config::CONFIG_LOCALE;
63                }
64            }
65        } else if ((diff & diffMask) == android::ResTable_config::CONFIG_SMALLEST_SCREEN_SIZE) {
66            // Special case if the smallest screen width doesn't match. We check that the
67            // config being matched has a smaller screen width than the filter specified.
68            if (config.smallestScreenWidthDp != 0 &&
69                    config.smallestScreenWidthDp < target.smallestScreenWidthDp) {
70                matchedAxis |= android::ResTable_config::CONFIG_SMALLEST_SCREEN_SIZE;
71            }
72        }
73    }
74    return matchedAxis == (mConfigMask & mask);
75}
76
77} // namespace aapt
78