• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
findMid(int l,int 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  
generateDensity(const Vector<int> & allDensities,size_t index)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  
generateAbi(const Vector<abi::Variant> & splitAbis,size_t index)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  
generate(const SortedVector<SplitDescription> & group,size_t index)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