1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker *
4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker *
8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker *
10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker */
16*d57664e9SAndroid Build Coastguard Worker
17*d57664e9SAndroid Build Coastguard Worker #include "SplitDescription.h"
18*d57664e9SAndroid Build Coastguard Worker
19*d57664e9SAndroid Build Coastguard Worker #include "aapt/AaptConfig.h"
20*d57664e9SAndroid Build Coastguard Worker #include "aapt/AaptUtil.h"
21*d57664e9SAndroid Build Coastguard Worker
22*d57664e9SAndroid Build Coastguard Worker #include <utils/String8.h>
23*d57664e9SAndroid Build Coastguard Worker #include <utils/Vector.h>
24*d57664e9SAndroid Build Coastguard Worker
25*d57664e9SAndroid Build Coastguard Worker using namespace android;
26*d57664e9SAndroid Build Coastguard Worker
27*d57664e9SAndroid Build Coastguard Worker namespace split {
28*d57664e9SAndroid Build Coastguard Worker
SplitDescription()29*d57664e9SAndroid Build Coastguard Worker SplitDescription::SplitDescription()
30*d57664e9SAndroid Build Coastguard Worker : abi(abi::Variant_none) {
31*d57664e9SAndroid Build Coastguard Worker }
32*d57664e9SAndroid Build Coastguard Worker
compare(const SplitDescription & rhs) const33*d57664e9SAndroid Build Coastguard Worker int SplitDescription::compare(const SplitDescription& rhs) const {
34*d57664e9SAndroid Build Coastguard Worker int cmp;
35*d57664e9SAndroid Build Coastguard Worker cmp = (int)abi - (int)rhs.abi;
36*d57664e9SAndroid Build Coastguard Worker if (cmp != 0) return cmp;
37*d57664e9SAndroid Build Coastguard Worker return config.compareLogical(rhs.config);
38*d57664e9SAndroid Build Coastguard Worker }
39*d57664e9SAndroid Build Coastguard Worker
isBetterThan(const SplitDescription & o,const SplitDescription & target) const40*d57664e9SAndroid Build Coastguard Worker bool SplitDescription::isBetterThan(const SplitDescription& o, const SplitDescription& target) const {
41*d57664e9SAndroid Build Coastguard Worker if (abi != abi::Variant_none || o.abi != abi::Variant_none) {
42*d57664e9SAndroid Build Coastguard Worker abi::Family family = abi::getFamily(abi);
43*d57664e9SAndroid Build Coastguard Worker abi::Family oFamily = abi::getFamily(o.abi);
44*d57664e9SAndroid Build Coastguard Worker if (family != oFamily) {
45*d57664e9SAndroid Build Coastguard Worker return family != abi::Family_none;
46*d57664e9SAndroid Build Coastguard Worker }
47*d57664e9SAndroid Build Coastguard Worker
48*d57664e9SAndroid Build Coastguard Worker if (int(target.abi) - int(abi) < int(target.abi) - int(o.abi)) {
49*d57664e9SAndroid Build Coastguard Worker return true;
50*d57664e9SAndroid Build Coastguard Worker }
51*d57664e9SAndroid Build Coastguard Worker }
52*d57664e9SAndroid Build Coastguard Worker return config.isBetterThan(o.config, &target.config);
53*d57664e9SAndroid Build Coastguard Worker }
54*d57664e9SAndroid Build Coastguard Worker
match(const SplitDescription & o) const55*d57664e9SAndroid Build Coastguard Worker bool SplitDescription::match(const SplitDescription& o) const {
56*d57664e9SAndroid Build Coastguard Worker if (abi != abi::Variant_none) {
57*d57664e9SAndroid Build Coastguard Worker abi::Family family = abi::getFamily(abi);
58*d57664e9SAndroid Build Coastguard Worker abi::Family oFamily = abi::getFamily(o.abi);
59*d57664e9SAndroid Build Coastguard Worker if (family != oFamily) {
60*d57664e9SAndroid Build Coastguard Worker return false;
61*d57664e9SAndroid Build Coastguard Worker }
62*d57664e9SAndroid Build Coastguard Worker
63*d57664e9SAndroid Build Coastguard Worker if (int(abi) > int(o.abi)) {
64*d57664e9SAndroid Build Coastguard Worker return false;
65*d57664e9SAndroid Build Coastguard Worker }
66*d57664e9SAndroid Build Coastguard Worker }
67*d57664e9SAndroid Build Coastguard Worker return config.match(o.config);
68*d57664e9SAndroid Build Coastguard Worker }
69*d57664e9SAndroid Build Coastguard Worker
toString() const70*d57664e9SAndroid Build Coastguard Worker String8 SplitDescription::toString() const {
71*d57664e9SAndroid Build Coastguard Worker String8 extension;
72*d57664e9SAndroid Build Coastguard Worker if (abi != abi::Variant_none) {
73*d57664e9SAndroid Build Coastguard Worker if (extension.empty()) {
74*d57664e9SAndroid Build Coastguard Worker extension.append(":");
75*d57664e9SAndroid Build Coastguard Worker } else {
76*d57664e9SAndroid Build Coastguard Worker extension.append("-");
77*d57664e9SAndroid Build Coastguard Worker }
78*d57664e9SAndroid Build Coastguard Worker extension.append(abi::toString(abi));
79*d57664e9SAndroid Build Coastguard Worker }
80*d57664e9SAndroid Build Coastguard Worker String8 str(config.toString());
81*d57664e9SAndroid Build Coastguard Worker str.append(extension);
82*d57664e9SAndroid Build Coastguard Worker return str;
83*d57664e9SAndroid Build Coastguard Worker }
84*d57664e9SAndroid Build Coastguard Worker
parseAbi(const Vector<String8> & parts,const ssize_t index,SplitDescription * outSplit)85*d57664e9SAndroid Build Coastguard Worker ssize_t parseAbi(const Vector<String8>& parts, const ssize_t index,
86*d57664e9SAndroid Build Coastguard Worker SplitDescription* outSplit) {
87*d57664e9SAndroid Build Coastguard Worker const ssize_t N = parts.size();
88*d57664e9SAndroid Build Coastguard Worker abi::Variant abi = abi::Variant_none;
89*d57664e9SAndroid Build Coastguard Worker ssize_t endIndex = index;
90*d57664e9SAndroid Build Coastguard Worker if (parts[endIndex] == "arm64") {
91*d57664e9SAndroid Build Coastguard Worker endIndex++;
92*d57664e9SAndroid Build Coastguard Worker if (endIndex < N) {
93*d57664e9SAndroid Build Coastguard Worker if (parts[endIndex] == "v8a") {
94*d57664e9SAndroid Build Coastguard Worker endIndex++;
95*d57664e9SAndroid Build Coastguard Worker abi = abi::Variant_arm64_v8a;
96*d57664e9SAndroid Build Coastguard Worker }
97*d57664e9SAndroid Build Coastguard Worker }
98*d57664e9SAndroid Build Coastguard Worker } else if (parts[endIndex] == "armeabi") {
99*d57664e9SAndroid Build Coastguard Worker endIndex++;
100*d57664e9SAndroid Build Coastguard Worker abi = abi::Variant_armeabi;
101*d57664e9SAndroid Build Coastguard Worker if (endIndex < N) {
102*d57664e9SAndroid Build Coastguard Worker if (parts[endIndex] == "v7a") {
103*d57664e9SAndroid Build Coastguard Worker endIndex++;
104*d57664e9SAndroid Build Coastguard Worker abi = abi::Variant_armeabi_v7a;
105*d57664e9SAndroid Build Coastguard Worker }
106*d57664e9SAndroid Build Coastguard Worker }
107*d57664e9SAndroid Build Coastguard Worker } else if (parts[endIndex] == "x86") {
108*d57664e9SAndroid Build Coastguard Worker endIndex++;
109*d57664e9SAndroid Build Coastguard Worker abi = abi::Variant_x86;
110*d57664e9SAndroid Build Coastguard Worker } else if (parts[endIndex] == "x86_64") {
111*d57664e9SAndroid Build Coastguard Worker endIndex++;
112*d57664e9SAndroid Build Coastguard Worker abi = abi::Variant_x86_64;
113*d57664e9SAndroid Build Coastguard Worker } else if (parts[endIndex] == "mips") {
114*d57664e9SAndroid Build Coastguard Worker endIndex++;
115*d57664e9SAndroid Build Coastguard Worker abi = abi::Variant_mips;
116*d57664e9SAndroid Build Coastguard Worker } else if (parts[endIndex] == "mips64") {
117*d57664e9SAndroid Build Coastguard Worker endIndex++;
118*d57664e9SAndroid Build Coastguard Worker abi = abi::Variant_mips64;
119*d57664e9SAndroid Build Coastguard Worker }
120*d57664e9SAndroid Build Coastguard Worker
121*d57664e9SAndroid Build Coastguard Worker if (abi == abi::Variant_none && endIndex != index) {
122*d57664e9SAndroid Build Coastguard Worker return -1;
123*d57664e9SAndroid Build Coastguard Worker }
124*d57664e9SAndroid Build Coastguard Worker
125*d57664e9SAndroid Build Coastguard Worker if (outSplit != NULL) {
126*d57664e9SAndroid Build Coastguard Worker outSplit->abi = abi;
127*d57664e9SAndroid Build Coastguard Worker }
128*d57664e9SAndroid Build Coastguard Worker return endIndex;
129*d57664e9SAndroid Build Coastguard Worker }
130*d57664e9SAndroid Build Coastguard Worker
parse(const String8 & str,SplitDescription * outSplit)131*d57664e9SAndroid Build Coastguard Worker bool SplitDescription::parse(const String8& str, SplitDescription* outSplit) {
132*d57664e9SAndroid Build Coastguard Worker ssize_t index = str.find(":");
133*d57664e9SAndroid Build Coastguard Worker
134*d57664e9SAndroid Build Coastguard Worker String8 configStr;
135*d57664e9SAndroid Build Coastguard Worker String8 extensionStr;
136*d57664e9SAndroid Build Coastguard Worker if (index >= 0) {
137*d57664e9SAndroid Build Coastguard Worker configStr = String8(str.c_str(), index);
138*d57664e9SAndroid Build Coastguard Worker extensionStr = (str.c_str() + index + 1);
139*d57664e9SAndroid Build Coastguard Worker } else {
140*d57664e9SAndroid Build Coastguard Worker configStr = str;
141*d57664e9SAndroid Build Coastguard Worker }
142*d57664e9SAndroid Build Coastguard Worker
143*d57664e9SAndroid Build Coastguard Worker SplitDescription split;
144*d57664e9SAndroid Build Coastguard Worker if (!AaptConfig::parse(configStr, &split.config)) {
145*d57664e9SAndroid Build Coastguard Worker return false;
146*d57664e9SAndroid Build Coastguard Worker }
147*d57664e9SAndroid Build Coastguard Worker
148*d57664e9SAndroid Build Coastguard Worker Vector<String8> parts = AaptUtil::splitAndLowerCase(extensionStr, '-');
149*d57664e9SAndroid Build Coastguard Worker const ssize_t N = parts.size();
150*d57664e9SAndroid Build Coastguard Worker index = 0;
151*d57664e9SAndroid Build Coastguard Worker
152*d57664e9SAndroid Build Coastguard Worker if (extensionStr.length() == 0) {
153*d57664e9SAndroid Build Coastguard Worker goto success;
154*d57664e9SAndroid Build Coastguard Worker }
155*d57664e9SAndroid Build Coastguard Worker
156*d57664e9SAndroid Build Coastguard Worker index = parseAbi(parts, index, &split);
157*d57664e9SAndroid Build Coastguard Worker if (index < 0) {
158*d57664e9SAndroid Build Coastguard Worker return false;
159*d57664e9SAndroid Build Coastguard Worker } else {
160*d57664e9SAndroid Build Coastguard Worker if (index == N) {
161*d57664e9SAndroid Build Coastguard Worker goto success;
162*d57664e9SAndroid Build Coastguard Worker }
163*d57664e9SAndroid Build Coastguard Worker }
164*d57664e9SAndroid Build Coastguard Worker
165*d57664e9SAndroid Build Coastguard Worker // Unrecognized
166*d57664e9SAndroid Build Coastguard Worker return false;
167*d57664e9SAndroid Build Coastguard Worker
168*d57664e9SAndroid Build Coastguard Worker success:
169*d57664e9SAndroid Build Coastguard Worker if (outSplit != NULL) {
170*d57664e9SAndroid Build Coastguard Worker *outSplit = split;
171*d57664e9SAndroid Build Coastguard Worker }
172*d57664e9SAndroid Build Coastguard Worker return true;
173*d57664e9SAndroid Build Coastguard Worker }
174*d57664e9SAndroid Build Coastguard Worker
175*d57664e9SAndroid Build Coastguard Worker } // namespace split
176