1 /* 2 * Copyright (C) 2014 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 "RuleGenerator.h" 18 #include "aapt/SdkConstants.h" 19 20 #include <algorithm> 21 #include <cmath> 22 #include <vector> 23 #include <androidfw/ResourceTypes.h> 24 25 using namespace android; 26 27 namespace split { 28 29 // Calculate the point at which the density selection changes between l and h. 30 static inline int findMid(int l, int h) { 31 double root = sqrt((h*h) + (8*l*h)); 32 return (double(-h) + root) / 2.0; 33 } 34 35 sp<Rule> RuleGenerator::generateDensity(const Vector<int>& allDensities, size_t index) { 36 if (allDensities[index] != ResTable_config::DENSITY_ANY) { 37 sp<Rule> densityRule = new Rule(); 38 densityRule->op = Rule::AND_SUBRULES; 39 40 const bool hasAnyDensity = std::find(allDensities.begin(), 41 allDensities.end(), (int) ResTable_config::DENSITY_ANY) != allDensities.end(); 42 43 if (hasAnyDensity) { 44 sp<Rule> version = new Rule(); 45 version->op = Rule::LESS_THAN; 46 version->key = Rule::SDK_VERSION; 47 version->longArgs.add((long) SDK_LOLLIPOP); 48 densityRule->subrules.add(version); 49 } 50 51 if (index > 0) { 52 sp<Rule> gt = new Rule(); 53 gt->op = Rule::GREATER_THAN; 54 gt->key = Rule::SCREEN_DENSITY; 55 gt->longArgs.add(findMid(allDensities[index - 1], allDensities[index]) - 1); 56 densityRule->subrules.add(gt); 57 } 58 59 if (index + 1 < allDensities.size() && allDensities[index + 1] != ResTable_config::DENSITY_ANY) { 60 sp<Rule> lt = new Rule(); 61 lt->op = Rule::LESS_THAN; 62 lt->key = Rule::SCREEN_DENSITY; 63 lt->longArgs.add(findMid(allDensities[index], allDensities[index + 1])); 64 densityRule->subrules.add(lt); 65 } 66 return densityRule; 67 } else { 68 // SDK_VERSION is handled elsewhere, so we always pick DENSITY_ANY if it's 69 // available. 70 sp<Rule> always = new Rule(); 71 always->op = Rule::ALWAYS_TRUE; 72 return always; 73 } 74 } 75 76 sp<Rule> RuleGenerator::generateAbi(const Vector<abi::Variant>& splitAbis, size_t index) { 77 const abi::Variant thisAbi = splitAbis[index]; 78 const Vector<abi::Variant>& familyVariants = abi::getVariants(abi::getFamily(thisAbi)); 79 80 Vector<abi::Variant>::const_iterator start = 81 std::find(familyVariants.begin(), familyVariants.end(), thisAbi); 82 83 Vector<abi::Variant>::const_iterator end = familyVariants.end(); 84 if (index + 1 < splitAbis.size()) { 85 end = std::find(start, familyVariants.end(), splitAbis[index + 1]); 86 } 87 88 sp<Rule> abiRule = new Rule(); 89 abiRule->op = Rule::CONTAINS_ANY; 90 abiRule->key = Rule::NATIVE_PLATFORM; 91 while (start != end) { 92 abiRule->stringArgs.add(String8(abi::toString(*start))); 93 ++start; 94 } 95 return abiRule; 96 } 97 98 sp<Rule> RuleGenerator::generate(const SortedVector<SplitDescription>& group, size_t index) { 99 sp<Rule> rootRule = new Rule(); 100 rootRule->op = Rule::AND_SUBRULES; 101 102 if (group[index].config.locale != 0) { 103 sp<Rule> locale = new Rule(); 104 locale->op = Rule::EQUALS; 105 locale->key = Rule::LANGUAGE; 106 char str[RESTABLE_MAX_LOCALE_LEN]; 107 group[index].config.getBcp47Locale(str); 108 locale->stringArgs.add(String8(str)); 109 rootRule->subrules.add(locale); 110 } 111 112 if (group[index].config.sdkVersion != 0) { 113 sp<Rule> sdk = new Rule(); 114 sdk->op = Rule::GREATER_THAN; 115 sdk->key = Rule::SDK_VERSION; 116 sdk->longArgs.add(group[index].config.sdkVersion - 1); 117 rootRule->subrules.add(sdk); 118 } 119 120 if (group[index].config.density != 0) { 121 size_t densityIndex = 0; 122 Vector<int> allDensities; 123 allDensities.add(group[index].config.density); 124 125 const size_t groupSize = group.size(); 126 for (size_t i = 0; i < groupSize; i++) { 127 if (group[i].config.density != group[index].config.density) { 128 // This group differs by density. 129 allDensities.clear(); 130 for (size_t j = 0; j < groupSize; j++) { 131 allDensities.add(group[j].config.density); 132 } 133 densityIndex = index; 134 break; 135 } 136 } 137 rootRule->subrules.add(generateDensity(allDensities, densityIndex)); 138 } 139 140 if (group[index].abi != abi::Variant_none) { 141 size_t abiIndex = 0; 142 Vector<abi::Variant> allVariants; 143 allVariants.add(group[index].abi); 144 145 const size_t groupSize = group.size(); 146 for (size_t i = 0; i < groupSize; i++) { 147 if (group[i].abi != group[index].abi) { 148 // This group differs by ABI. 149 allVariants.clear(); 150 for (size_t j = 0; j < groupSize; j++) { 151 allVariants.add(group[j].abi); 152 } 153 abiIndex = index; 154 break; 155 } 156 } 157 rootRule->subrules.add(generateAbi(allVariants, abiIndex)); 158 } 159 160 return rootRule; 161 } 162 163 } // namespace split 164