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(),
414d29c6693090cb9a0be209f9cfd0aef307fe52edAdam 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