/* * Copyright (C) 2014 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 "RuleGenerator.h" #include #include #include #include using namespace android; namespace split { // Calculate the point at which the density selection changes between l and h. static inline int findMid(int l, int h) { double root = sqrt((h*h) + (8*l*h)); return (double(-h) + root) / 2.0; } sp RuleGenerator::generateDensity(const Vector& allDensities, size_t index) { sp densityRule = new Rule(); densityRule->op = Rule::AND_SUBRULES; const bool anyDensity = allDensities[index] == ResTable_config::DENSITY_ANY; sp any = new Rule(); any->op = Rule::EQUALS; any->key = Rule::SCREEN_DENSITY; any->longArgs.add((int)ResTable_config::DENSITY_ANY); any->negate = !anyDensity; densityRule->subrules.add(any); if (!anyDensity) { if (index > 0) { sp gt = new Rule(); gt->op = Rule::GREATER_THAN; gt->key = Rule::SCREEN_DENSITY; gt->longArgs.add(findMid(allDensities[index - 1], allDensities[index]) - 1); densityRule->subrules.add(gt); } if (index + 1 < allDensities.size() && allDensities[index + 1] != ResTable_config::DENSITY_ANY) { sp lt = new Rule(); lt->op = Rule::LESS_THAN; lt->key = Rule::SCREEN_DENSITY; lt->longArgs.add(findMid(allDensities[index], allDensities[index + 1])); densityRule->subrules.add(lt); } } return densityRule; } sp RuleGenerator::generateAbi(const Vector& splitAbis, size_t index) { const abi::Variant thisAbi = splitAbis[index]; const std::vector& familyVariants = abi::getVariants(abi::getFamily(thisAbi)); std::vector::const_iterator start = std::find(familyVariants.begin(), familyVariants.end(), thisAbi); std::vector::const_iterator end = familyVariants.end(); if (index + 1 < splitAbis.size()) { end = std::find(start, familyVariants.end(), splitAbis[index + 1]); } sp abiRule = new Rule(); abiRule->op = Rule::CONTAINS_ANY; abiRule->key = Rule::NATIVE_PLATFORM; while (start != end) { abiRule->stringArgs.add(String8(abi::toString(*start))); ++start; } return abiRule; } sp RuleGenerator::generate(const SortedVector& group, size_t index) { sp rootRule = new Rule(); rootRule->op = Rule::AND_SUBRULES; if (group[index].config.locale != 0) { sp locale = new Rule(); locale->op = Rule::EQUALS; locale->key = Rule::LANGUAGE; char str[RESTABLE_MAX_LOCALE_LEN]; group[index].config.getBcp47Locale(str); locale->stringArgs.add(String8(str)); rootRule->subrules.add(locale); } if (group[index].config.sdkVersion != 0) { sp sdk = new Rule(); sdk->op = Rule::GREATER_THAN; sdk->key = Rule::SDK_VERSION; sdk->longArgs.add(group[index].config.sdkVersion - 1); rootRule->subrules.add(sdk); } if (group[index].config.density != 0) { size_t densityIndex = 0; Vector allDensities; allDensities.add(group[index].config.density); const size_t groupSize = group.size(); for (size_t i = 0; i < groupSize; i++) { if (group[i].config.density != group[index].config.density) { // This group differs by density. allDensities.clear(); for (size_t j = 0; j < groupSize; j++) { allDensities.add(group[j].config.density); } densityIndex = index; break; } } rootRule->subrules.add(generateDensity(allDensities, densityIndex)); } if (group[index].abi != abi::Variant::none) { size_t abiIndex = 0; Vector allVariants; allVariants.add(group[index].abi); const size_t groupSize = group.size(); for (size_t i = 0; i < groupSize; i++) { if (group[i].abi != group[index].abi) { // This group differs by ABI. allVariants.clear(); for (size_t j = 0; j < groupSize; j++) { allVariants.add(group[j].abi); } abiIndex = index; break; } } rootRule->subrules.add(generateAbi(allVariants, abiIndex)); } return rootRule; } } // namespace split