140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski/* 240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * Copyright (C) 2014 The Android Open Source Project 340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * 440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * you may not use this file except in compliance with the License. 640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * You may obtain a copy of the License at 740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * 840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * 1040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * Unless required by applicable law or agreed to in writing, software 1140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 1240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * See the License for the specific language governing permissions and 1440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski * limitations under the License. 1540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski */ 1640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 1740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include "RuleGenerator.h" 18dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski#include "aapt/SdkConstants.h" 1940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 2040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include <algorithm> 2140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include <cmath> 2240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include <vector> 2340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include <androidfw/ResourceTypes.h> 2440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 2540e8eefbedcafc51948945647d746daaee092f16Adam Lesinskiusing namespace android; 2640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 2740e8eefbedcafc51948945647d746daaee092f16Adam Lesinskinamespace split { 2840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 2940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski// Calculate the point at which the density selection changes between l and h. 3040e8eefbedcafc51948945647d746daaee092f16Adam Lesinskistatic inline int findMid(int l, int h) { 3140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski double root = sqrt((h*h) + (8*l*h)); 3240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return (double(-h) + root) / 2.0; 3340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} 3440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 3540e8eefbedcafc51948945647d746daaee092f16Adam Lesinskisp<Rule> RuleGenerator::generateDensity(const Vector<int>& allDensities, size_t index) { 36dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski if (allDensities[index] != ResTable_config::DENSITY_ANY) { 37dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski sp<Rule> densityRule = new Rule(); 38dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski densityRule->op = Rule::AND_SUBRULES; 39dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski 40dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski const bool hasAnyDensity = std::find(allDensities.begin(), 41c3344e8a6d7402326204d1232a4c5ffa382f70a9Adam Lesinski allDensities.end(), (int) ResTable_config::DENSITY_ANY) != allDensities.end(); 42dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski 43dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski if (hasAnyDensity) { 44dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski sp<Rule> version = new Rule(); 45dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski version->op = Rule::LESS_THAN; 46dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski version->key = Rule::SDK_VERSION; 47dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski version->longArgs.add((long) SDK_LOLLIPOP); 48dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski densityRule->subrules.add(version); 49dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski } 50dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski 5140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (index > 0) { 5240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski sp<Rule> gt = new Rule(); 5340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski gt->op = Rule::GREATER_THAN; 5440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski gt->key = Rule::SCREEN_DENSITY; 5540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski gt->longArgs.add(findMid(allDensities[index - 1], allDensities[index]) - 1); 5640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski densityRule->subrules.add(gt); 5740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 5840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 5940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (index + 1 < allDensities.size() && allDensities[index + 1] != ResTable_config::DENSITY_ANY) { 6040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski sp<Rule> lt = new Rule(); 6140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski lt->op = Rule::LESS_THAN; 6240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski lt->key = Rule::SCREEN_DENSITY; 6340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski lt->longArgs.add(findMid(allDensities[index], allDensities[index + 1])); 6440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski densityRule->subrules.add(lt); 6540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 66dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski return densityRule; 67dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski } else { 68dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski // SDK_VERSION is handled elsewhere, so we always pick DENSITY_ANY if it's 69dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski // available. 70dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski sp<Rule> always = new Rule(); 71dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski always->op = Rule::ALWAYS_TRUE; 72dcdfe9fef4b07ee53d312c3fbecc74cb215ace6fAdam Lesinski return always; 7340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 7440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} 7540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 7640e8eefbedcafc51948945647d746daaee092f16Adam Lesinskisp<Rule> RuleGenerator::generateAbi(const Vector<abi::Variant>& splitAbis, size_t index) { 7740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const abi::Variant thisAbi = splitAbis[index]; 78c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski const Vector<abi::Variant>& familyVariants = abi::getVariants(abi::getFamily(thisAbi)); 7940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 80c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski Vector<abi::Variant>::const_iterator start = 8140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski std::find(familyVariants.begin(), familyVariants.end(), thisAbi); 8240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 83c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski Vector<abi::Variant>::const_iterator end = familyVariants.end(); 8440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (index + 1 < splitAbis.size()) { 8540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski end = std::find(start, familyVariants.end(), splitAbis[index + 1]); 8640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 8740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 8840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski sp<Rule> abiRule = new Rule(); 8940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski abiRule->op = Rule::CONTAINS_ANY; 9040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski abiRule->key = Rule::NATIVE_PLATFORM; 9140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski while (start != end) { 9240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski abiRule->stringArgs.add(String8(abi::toString(*start))); 9340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski ++start; 9440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 9540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return abiRule; 9640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} 9740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 9840e8eefbedcafc51948945647d746daaee092f16Adam Lesinskisp<Rule> RuleGenerator::generate(const SortedVector<SplitDescription>& group, size_t index) { 9940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski sp<Rule> rootRule = new Rule(); 10040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski rootRule->op = Rule::AND_SUBRULES; 10140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 10240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (group[index].config.locale != 0) { 10340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski sp<Rule> locale = new Rule(); 10440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski locale->op = Rule::EQUALS; 10540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski locale->key = Rule::LANGUAGE; 10640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski char str[RESTABLE_MAX_LOCALE_LEN]; 10740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski group[index].config.getBcp47Locale(str); 10840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski locale->stringArgs.add(String8(str)); 10940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski rootRule->subrules.add(locale); 11040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 11140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 11240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (group[index].config.sdkVersion != 0) { 11340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski sp<Rule> sdk = new Rule(); 11440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski sdk->op = Rule::GREATER_THAN; 11540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski sdk->key = Rule::SDK_VERSION; 11640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski sdk->longArgs.add(group[index].config.sdkVersion - 1); 11740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski rootRule->subrules.add(sdk); 11840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 11940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 12040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (group[index].config.density != 0) { 12140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski size_t densityIndex = 0; 12240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski Vector<int> allDensities; 12340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski allDensities.add(group[index].config.density); 12440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 12540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const size_t groupSize = group.size(); 12640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t i = 0; i < groupSize; i++) { 12740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (group[i].config.density != group[index].config.density) { 12840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski // This group differs by density. 12940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski allDensities.clear(); 13040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t j = 0; j < groupSize; j++) { 13140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski allDensities.add(group[j].config.density); 13240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 13340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski densityIndex = index; 13440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski break; 13540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 13640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 13740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski rootRule->subrules.add(generateDensity(allDensities, densityIndex)); 13840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 13940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 140c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski if (group[index].abi != abi::Variant_none) { 14140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski size_t abiIndex = 0; 14240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski Vector<abi::Variant> allVariants; 14340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski allVariants.add(group[index].abi); 14440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 14540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const size_t groupSize = group.size(); 14640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t i = 0; i < groupSize; i++) { 14740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (group[i].abi != group[index].abi) { 14840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski // This group differs by ABI. 14940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski allVariants.clear(); 15040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t j = 0; j < groupSize; j++) { 15140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski allVariants.add(group[j].abi); 15240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 15340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski abiIndex = index; 15440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski break; 15540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 15640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 15740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski rootRule->subrules.add(generateAbi(allVariants, abiIndex)); 15840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 15940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 16040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return rootRule; 16140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} 16240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 16340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} // namespace split 164