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