1e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn// 2fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski// Copyright 2014 The Android Open Source Project 3e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn// 4e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn// Build resource files from raw assets. 5e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn// 6e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn 7e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn#include "ResourceFilter.h" 8fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski#include "AaptUtil.h" 9fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski#include "AaptConfig.h" 10e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn 11e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackbornstatus_t 12fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam LesinskiWeakResourceFilter::parse(const String8& str) 13e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn{ 14fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski Vector<String8> configStrs = AaptUtil::split(str, ','); 15fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t N = configStrs.size(); 16fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski mConfigs.clear(); 17fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski mConfigMask = 0; 18fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski mConfigs.resize(N); 19fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < N; i++) { 20fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const String8& part = configStrs[i]; 21a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin if (part == "en_XA") { 22a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin mContainsPseudoAccented = true; 23a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin } else if (part == "ar_XB") { 24a2ef5c0d4fb863c0382e77ae00f986a019b11cbeAnton Krumin mContainsPseudoBidi = true; 25e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn } 26e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn 27fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski std::pair<ConfigDescription, uint32_t>& entry = mConfigs.editItemAt(i); 28788fa41482b9d398591b7db8b0b01839029611adNarayan Kamath 29fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski AaptLocaleValue val; 30fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (val.initFromFilterString(part)) { 31fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // For backwards compatibility, we accept configurations that 32fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // only specify locale in the standard 'en_US' format. 33fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski val.writeTo(&entry.first); 34fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } else if (!AaptConfig::parse(part, &entry.first)) { 35fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "Invalid configuration: %s\n", part.string()); 36fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return UNKNOWN_ERROR; 37e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn } 38fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 39fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski entry.second = mDefault.diff(entry.first); 40fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 41fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // Ignore the version 42fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski entry.second &= ~ResTable_config::CONFIG_VERSION; 43fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski 44a2bb565db553e3def89a6e010b59f2fd1db98ff4Adam Lesinski // Ignore any densities. Those are best handled in --preferred-density 45a2bb565db553e3def89a6e010b59f2fd1db98ff4Adam Lesinski if ((entry.second & ResTable_config::CONFIG_DENSITY) != 0) { 46a2bb565db553e3def89a6e010b59f2fd1db98ff4Adam Lesinski fprintf(stderr, "warning: ignoring flag -c %s. Use --preferred-density instead.\n", entry.first.toString().string()); 47a2bb565db553e3def89a6e010b59f2fd1db98ff4Adam Lesinski entry.first.density = 0; 48a2bb565db553e3def89a6e010b59f2fd1db98ff4Adam Lesinski entry.second &= ~ResTable_config::CONFIG_DENSITY; 49a2bb565db553e3def89a6e010b59f2fd1db98ff4Adam Lesinski } 50a2bb565db553e3def89a6e010b59f2fd1db98ff4Adam Lesinski 51fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski mConfigMask |= entry.second; 52e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn } 53e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn 54e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn return NO_ERROR; 55e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn} 56e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn 57e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackbornbool 58fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam LesinskiWeakResourceFilter::match(const ResTable_config& config) const 59e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn{ 60fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski uint32_t mask = mDefault.diff(config); 61fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if ((mConfigMask & mask) == 0) { 62fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // The two configurations don't have any common axis. 63e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn return true; 64e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn } 65e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn 66a5cc002bfe7ca8a6536549189b44e7143c8611dcAdam Lesinski uint32_t matchedAxis = 0x0; 67fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const size_t N = mConfigs.size(); 68fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < N; i++) { 69fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski const std::pair<ConfigDescription, uint32_t>& entry = mConfigs[i]; 70fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski uint32_t diff = entry.first.diff(config); 71fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if ((diff & entry.second) == 0) { 72a5cc002bfe7ca8a6536549189b44e7143c8611dcAdam Lesinski // Mark the axis that was matched. 73a5cc002bfe7ca8a6536549189b44e7143c8611dcAdam Lesinski matchedAxis |= entry.second; 74fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } else if ((diff & entry.second) == ResTable_config::CONFIG_LOCALE) { 75fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // If the locales differ, but the languages are the same and 76fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // the locale we are matching only has a language specified, 77fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski // we match. 78a5cc002bfe7ca8a6536549189b44e7143c8611dcAdam Lesinski if (config.language[0] && 79a5cc002bfe7ca8a6536549189b44e7143c8611dcAdam Lesinski memcmp(config.language, entry.first.language, sizeof(config.language)) == 0) { 80fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (config.country[0] == 0) { 81a5cc002bfe7ca8a6536549189b44e7143c8611dcAdam Lesinski matchedAxis |= ResTable_config::CONFIG_LOCALE; 82fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 83fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 84a5cc002bfe7ca8a6536549189b44e7143c8611dcAdam Lesinski } else if ((diff & entry.second) == ResTable_config::CONFIG_SMALLEST_SCREEN_SIZE) { 85a5cc002bfe7ca8a6536549189b44e7143c8611dcAdam Lesinski // Special case if the smallest screen width doesn't match. We check that the 86a5cc002bfe7ca8a6536549189b44e7143c8611dcAdam Lesinski // config being matched has a smaller screen width than the filter specified. 87a5cc002bfe7ca8a6536549189b44e7143c8611dcAdam Lesinski if (config.smallestScreenWidthDp != 0 && 88a5cc002bfe7ca8a6536549189b44e7143c8611dcAdam Lesinski config.smallestScreenWidthDp < entry.first.smallestScreenWidthDp) { 89a5cc002bfe7ca8a6536549189b44e7143c8611dcAdam Lesinski matchedAxis |= ResTable_config::CONFIG_SMALLEST_SCREEN_SIZE; 90a5cc002bfe7ca8a6536549189b44e7143c8611dcAdam Lesinski } 91e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn } 92e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn } 93a5cc002bfe7ca8a6536549189b44e7143c8611dcAdam Lesinski return matchedAxis == (mConfigMask & mask); 94e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn} 95e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn 96fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinskistatus_t 97fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam LesinskiStrongResourceFilter::parse(const String8& str) { 98fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski Vector<String8> configStrs = AaptUtil::split(str, ','); 99fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski ConfigDescription config; 100fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski mConfigs.clear(); 101fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski for (size_t i = 0; i < configStrs.size(); i++) { 102fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski if (!AaptConfig::parse(configStrs[i], &config)) { 103fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski fprintf(stderr, "Invalid configuration: %s\n", configStrs[i].string()); 104fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return UNKNOWN_ERROR; 105fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski } 106fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski mConfigs.insert(config); 107e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn } 108fab50875b98e8274ac8ee44b38ba42521bbbf1f9Adam Lesinski return NO_ERROR; 109e6b680364dd992907a8d2037685a2e500d188dfbDianne Hackborn} 110