Home | History | Annotate | Download | only in split-select
      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 "SplitDescription.h"
     18 
     19 #include "aapt/AaptConfig.h"
     20 #include "aapt/AaptUtil.h"
     21 
     22 #include <utils/String8.h>
     23 #include <utils/Vector.h>
     24 
     25 using namespace android;
     26 
     27 namespace split {
     28 
     29 SplitDescription::SplitDescription()
     30 : abi(abi::Variant_none) {
     31 }
     32 
     33 int SplitDescription::compare(const SplitDescription& rhs) const {
     34     int cmp;
     35     cmp = (int)abi - (int)rhs.abi;
     36     if (cmp != 0) return cmp;
     37     return config.compareLogical(rhs.config);
     38 }
     39 
     40 bool SplitDescription::isBetterThan(const SplitDescription& o, const SplitDescription& target) const {
     41     if (abi != abi::Variant_none || o.abi != abi::Variant_none) {
     42         abi::Family family = abi::getFamily(abi);
     43         abi::Family oFamily = abi::getFamily(o.abi);
     44         if (family != oFamily) {
     45             return family != abi::Family_none;
     46         }
     47 
     48         if (int(target.abi) - int(abi) < int(target.abi) - int(o.abi)) {
     49             return true;
     50         }
     51     }
     52     return config.isBetterThan(o.config, &target.config);
     53 }
     54 
     55 bool SplitDescription::match(const SplitDescription& o) const {
     56     if (abi != abi::Variant_none) {
     57         abi::Family family = abi::getFamily(abi);
     58         abi::Family oFamily = abi::getFamily(o.abi);
     59         if (family != oFamily) {
     60             return false;
     61         }
     62 
     63         if (int(abi) > int(o.abi)) {
     64             return false;
     65         }
     66     }
     67     return config.match(o.config);
     68 }
     69 
     70 String8 SplitDescription::toString() const {
     71     String8 extension;
     72     if (abi != abi::Variant_none) {
     73         if (extension.isEmpty()) {
     74             extension.append(":");
     75         } else {
     76             extension.append("-");
     77         }
     78         extension.append(abi::toString(abi));
     79     }
     80     String8 str(config.toString());
     81     str.append(extension);
     82     return str;
     83 }
     84 
     85 ssize_t parseAbi(const Vector<String8>& parts, const ssize_t index,
     86         SplitDescription* outSplit) {
     87     const ssize_t N = parts.size();
     88     abi::Variant abi = abi::Variant_none;
     89     ssize_t endIndex = index;
     90     if (parts[endIndex] == "arm64") {
     91         endIndex++;
     92         if (endIndex < N) {
     93             if (parts[endIndex] == "v8a") {
     94                 endIndex++;
     95                 abi = abi::Variant_arm64_v8a;
     96             }
     97         }
     98     } else if (parts[endIndex] == "armeabi") {
     99         endIndex++;
    100         abi = abi::Variant_armeabi;
    101         if (endIndex < N) {
    102             if (parts[endIndex] == "v7a") {
    103                 endIndex++;
    104                 abi = abi::Variant_armeabi_v7a;
    105             }
    106         }
    107     } else if (parts[endIndex] == "x86") {
    108         endIndex++;
    109         abi = abi::Variant_x86;
    110     } else if (parts[endIndex] == "x86_64") {
    111         endIndex++;
    112         abi = abi::Variant_x86_64;
    113     } else if (parts[endIndex] == "mips") {
    114         endIndex++;
    115         abi = abi::Variant_mips;
    116     } else if (parts[endIndex] == "mips64") {
    117         endIndex++;
    118         abi = abi::Variant_mips64;
    119     }
    120 
    121     if (abi == abi::Variant_none && endIndex != index) {
    122         return -1;
    123     }
    124 
    125     if (outSplit != NULL) {
    126         outSplit->abi = abi;
    127     }
    128     return endIndex;
    129 }
    130 
    131 bool SplitDescription::parse(const String8& str, SplitDescription* outSplit) {
    132     ssize_t index = str.find(":");
    133 
    134     String8 configStr;
    135     String8 extensionStr;
    136     if (index >= 0) {
    137         configStr.setTo(str.string(), index);
    138         extensionStr.setTo(str.string() + index + 1);
    139     } else {
    140         configStr.setTo(str);
    141     }
    142 
    143     SplitDescription split;
    144     if (!AaptConfig::parse(configStr, &split.config)) {
    145         return false;
    146     }
    147 
    148     Vector<String8> parts = AaptUtil::splitAndLowerCase(extensionStr, '-');
    149     const ssize_t N = parts.size();
    150     index = 0;
    151 
    152     if (extensionStr.length() == 0) {
    153         goto success;
    154     }
    155 
    156     index = parseAbi(parts, index, &split);
    157     if (index < 0) {
    158         return false;
    159     } else {
    160         if (index == N) {
    161             goto success;
    162         }
    163     }
    164 
    165     // Unrecognized
    166     return false;
    167 
    168 success:
    169     if (outSplit != NULL) {
    170         *outSplit = split;
    171     }
    172     return true;
    173 }
    174 
    175 } // namespace split
    176