summaryrefslogtreecommitdiffstats
path: root/tools/split-select/SplitDescription.cpp
diff options
context:
space:
mode:
authorAdam Lesinski <adamlesinski@google.com>2014-09-16 14:43:29 -0700
committerAdam Lesinski <adamlesinski@google.com>2014-10-23 10:39:31 -0700
commit40e8eefbedcafc51948945647d746daaee092f16 (patch)
treeeb14bacf3510fc8865145a1c68b4dcb8fc802904 /tools/split-select/SplitDescription.cpp
parent74af6700196ed55a0aa39c7777293e735e7b4d73 (diff)
downloadframeworks_base-40e8eefbedcafc51948945647d746daaee092f16.zip
frameworks_base-40e8eefbedcafc51948945647d746daaee092f16.tar.gz
frameworks_base-40e8eefbedcafc51948945647d746daaee092f16.tar.bz2
First commit of split-select tool
This tool emits a set of rules as JSON for when a Split APK should match a target device. Change-Id: I8bfbdfbdb51efcfc645889dd03e1961f16e39645
Diffstat (limited to 'tools/split-select/SplitDescription.cpp')
-rw-r--r--tools/split-select/SplitDescription.cpp175
1 files changed, 175 insertions, 0 deletions
diff --git a/tools/split-select/SplitDescription.cpp b/tools/split-select/SplitDescription.cpp
new file mode 100644
index 0000000..8037ef0
--- /dev/null
+++ b/tools/split-select/SplitDescription.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SplitDescription.h"
+
+#include "aapt/AaptConfig.h"
+#include "aapt/AaptUtil.h"
+
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+using namespace android;
+
+namespace split {
+
+SplitDescription::SplitDescription()
+: abi(abi::Variant::none) {
+}
+
+int SplitDescription::compare(const SplitDescription& rhs) const {
+ int cmp;
+ cmp = (int)abi - (int)rhs.abi;
+ if (cmp != 0) return cmp;
+ return config.compareLogical(rhs.config);
+}
+
+bool SplitDescription::isBetterThan(const SplitDescription& o, const SplitDescription& target) const {
+ if (abi != abi::Variant::none || o.abi != abi::Variant::none) {
+ abi::Family family = abi::getFamily(abi);
+ abi::Family oFamily = abi::getFamily(o.abi);
+ if (family != oFamily) {
+ return family != abi::Family::none;
+ }
+
+ if (int(target.abi) - int(abi) < int(target.abi) - int(o.abi)) {
+ return true;
+ }
+ }
+ return config.isBetterThan(o.config, &target.config);
+}
+
+bool SplitDescription::match(const SplitDescription& o) const {
+ if (abi != abi::Variant::none) {
+ abi::Family family = abi::getFamily(abi);
+ abi::Family oFamily = abi::getFamily(o.abi);
+ if (family != oFamily) {
+ return false;
+ }
+
+ if (int(abi) > int(o.abi)) {
+ return false;
+ }
+ }
+ return config.match(o.config);
+}
+
+String8 SplitDescription::toString() const {
+ String8 extension;
+ if (abi != abi::Variant::none) {
+ if (extension.isEmpty()) {
+ extension.append(":");
+ } else {
+ extension.append("-");
+ }
+ extension.append(abi::toString(abi));
+ }
+ String8 str(config.toString());
+ str.append(extension);
+ return str;
+}
+
+ssize_t parseAbi(const Vector<String8>& parts, const ssize_t index,
+ SplitDescription* outSplit) {
+ const ssize_t N = parts.size();
+ abi::Variant abi = abi::Variant::none;
+ ssize_t endIndex = index;
+ if (parts[endIndex] == "arm64") {
+ endIndex++;
+ if (endIndex < N) {
+ if (parts[endIndex] == "v8a") {
+ endIndex++;
+ abi = abi::Variant::arm64_v8a;
+ }
+ }
+ } else if (parts[endIndex] == "armeabi") {
+ endIndex++;
+ abi = abi::Variant::armeabi;
+ if (endIndex < N) {
+ if (parts[endIndex] == "v7a") {
+ endIndex++;
+ abi = abi::Variant::armeabi_v7a;
+ }
+ }
+ } else if (parts[endIndex] == "x86") {
+ endIndex++;
+ abi = abi::Variant::x86;
+ } else if (parts[endIndex] == "x86_64") {
+ endIndex++;
+ abi = abi::Variant::x86_64;
+ } else if (parts[endIndex] == "mips") {
+ endIndex++;
+ abi = abi::Variant::mips;
+ } else if (parts[endIndex] == "mips64") {
+ endIndex++;
+ abi = abi::Variant::mips64;
+ }
+
+ if (abi == abi::Variant::none && endIndex != index) {
+ return -1;
+ }
+
+ if (outSplit != NULL) {
+ outSplit->abi = abi;
+ }
+ return endIndex;
+}
+
+bool SplitDescription::parse(const String8& str, SplitDescription* outSplit) {
+ ssize_t index = str.find(":");
+
+ String8 configStr;
+ String8 extensionStr;
+ if (index >= 0) {
+ configStr.setTo(str.string(), index);
+ extensionStr.setTo(str.string() + index + 1);
+ } else {
+ configStr.setTo(str);
+ }
+
+ SplitDescription split;
+ if (!AaptConfig::parse(configStr, &split.config)) {
+ return false;
+ }
+
+ Vector<String8> parts = AaptUtil::splitAndLowerCase(extensionStr, '-');
+ const ssize_t N = parts.size();
+ index = 0;
+
+ if (extensionStr.length() == 0) {
+ goto success;
+ }
+
+ index = parseAbi(parts, index, &split);
+ if (index < 0) {
+ return false;
+ } else {
+ if (index == N) {
+ goto success;
+ }
+ }
+
+ // Unrecognized
+ return false;
+
+success:
+ if (outSplit != NULL) {
+ *outSplit = split;
+ }
+ return true;
+}
+
+} // namespace split