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