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 "SplitDescription.h"
1840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
1940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include "aapt/AaptConfig.h"
2040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include "aapt/AaptUtil.h"
2140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
2240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include <utils/String8.h>
2340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include <utils/Vector.h>
2440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
2540e8eefbedcafc51948945647d746daaee092f16Adam Lesinskiusing namespace android;
2640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
2740e8eefbedcafc51948945647d746daaee092f16Adam Lesinskinamespace split {
2840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
2940e8eefbedcafc51948945647d746daaee092f16Adam LesinskiSplitDescription::SplitDescription()
30c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski: abi(abi::Variant_none) {
3140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski}
3240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
3340e8eefbedcafc51948945647d746daaee092f16Adam Lesinskiint SplitDescription::compare(const SplitDescription& rhs) const {
3440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    int cmp;
3540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    cmp = (int)abi - (int)rhs.abi;
3640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    if (cmp != 0) return cmp;
3740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    return config.compareLogical(rhs.config);
3840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski}
3940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
4040e8eefbedcafc51948945647d746daaee092f16Adam Lesinskibool SplitDescription::isBetterThan(const SplitDescription& o, const SplitDescription& target) const {
41c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski    if (abi != abi::Variant_none || o.abi != abi::Variant_none) {
4240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        abi::Family family = abi::getFamily(abi);
4340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        abi::Family oFamily = abi::getFamily(o.abi);
4440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        if (family != oFamily) {
45c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski            return family != abi::Family_none;
4640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        }
4740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
4840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        if (int(target.abi) - int(abi) < int(target.abi) - int(o.abi)) {
4940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            return true;
5040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        }
5140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
5240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    return config.isBetterThan(o.config, &target.config);
5340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski}
5440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
5540e8eefbedcafc51948945647d746daaee092f16Adam Lesinskibool SplitDescription::match(const SplitDescription& o) const {
56c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski    if (abi != abi::Variant_none) {
5740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        abi::Family family = abi::getFamily(abi);
5840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        abi::Family oFamily = abi::getFamily(o.abi);
5940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        if (family != oFamily) {
6040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            return false;
6140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        }
6240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
6340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        if (int(abi) > int(o.abi)) {
6440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            return false;
6540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        }
6640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
6740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    return config.match(o.config);
6840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski}
6940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
7040e8eefbedcafc51948945647d746daaee092f16Adam LesinskiString8 SplitDescription::toString() const {
7140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    String8 extension;
72c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski    if (abi != abi::Variant_none) {
7340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        if (extension.isEmpty()) {
7440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            extension.append(":");
7540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        } else {
7640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            extension.append("-");
7740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        }
7840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        extension.append(abi::toString(abi));
7940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
8040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    String8 str(config.toString());
8140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    str.append(extension);
8240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    return str;
8340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski}
8440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
8540e8eefbedcafc51948945647d746daaee092f16Adam Lesinskissize_t parseAbi(const Vector<String8>& parts, const ssize_t index,
8640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        SplitDescription* outSplit) {
8740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    const ssize_t N = parts.size();
88c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski    abi::Variant abi = abi::Variant_none;
8940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    ssize_t endIndex = index;
9040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    if (parts[endIndex] == "arm64") {
9140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        endIndex++;
9240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        if (endIndex < N) {
9340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            if (parts[endIndex] == "v8a") {
9440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                endIndex++;
95c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski                abi = abi::Variant_arm64_v8a;
9640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            }
9740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        }
9840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    } else if (parts[endIndex] == "armeabi") {
9940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        endIndex++;
100c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski        abi = abi::Variant_armeabi;
10140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        if (endIndex < N) {
10240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            if (parts[endIndex] == "v7a") {
10340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski                endIndex++;
104c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski                abi = abi::Variant_armeabi_v7a;
10540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            }
10640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        }
10740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    } else if (parts[endIndex] == "x86") {
10840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        endIndex++;
109c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski        abi = abi::Variant_x86;
11040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    } else if (parts[endIndex] == "x86_64") {
11140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        endIndex++;
112c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski        abi = abi::Variant_x86_64;
11340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    } else if (parts[endIndex] == "mips") {
11440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        endIndex++;
115c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski        abi = abi::Variant_mips;
11640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    } else if (parts[endIndex] == "mips64") {
11740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        endIndex++;
118c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski        abi = abi::Variant_mips64;
11940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
12040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
121c3dc0b57b8d0b3875f868788e110aa67fb032b4aAdam Lesinski    if (abi == abi::Variant_none && endIndex != index) {
12240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        return -1;
12340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
12440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
12540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    if (outSplit != NULL) {
12640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        outSplit->abi = abi;
12740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
12840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    return endIndex;
12940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski}
13040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
13140e8eefbedcafc51948945647d746daaee092f16Adam Lesinskibool SplitDescription::parse(const String8& str, SplitDescription* outSplit) {
13240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    ssize_t index = str.find(":");
13340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
13440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    String8 configStr;
13540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    String8 extensionStr;
13640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    if (index >= 0) {
13740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        configStr.setTo(str.string(), index);
13840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        extensionStr.setTo(str.string() + index + 1);
13940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    } else {
14040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        configStr.setTo(str);
14140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
14240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
14340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    SplitDescription split;
14440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    if (!AaptConfig::parse(configStr, &split.config)) {
14540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        return false;
14640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
14740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
14840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    Vector<String8> parts = AaptUtil::splitAndLowerCase(extensionStr, '-');
14940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    const ssize_t N = parts.size();
15040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    index = 0;
15140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
15240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    if (extensionStr.length() == 0) {
15340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        goto success;
15440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
15540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
15640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    index = parseAbi(parts, index, &split);
15740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    if (index < 0) {
15840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        return false;
15940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    } else {
16040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        if (index == N) {
16140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski            goto success;
16240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        }
16340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
16440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
16540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    // Unrecognized
16640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    return false;
16740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
16840e8eefbedcafc51948945647d746daaee092f16Adam Lesinskisuccess:
16940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    if (outSplit != NULL) {
17040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski        *outSplit = split;
17140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    }
17240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski    return true;
17340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski}
17440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski
17540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} // namespace split
176