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 22 namespace aapt { 23 24 void 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 40 bool 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