Main.cpp revision 40e8eefbedcafc51948945647d746daaee092f16
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 <algorithm> 1840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include <cstdio> 1940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 2040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include "aapt/AaptUtil.h" 2140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 2240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include "Grouper.h" 2340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include "Rule.h" 2440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include "RuleGenerator.h" 2540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include "SplitDescription.h" 2640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 2740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include <androidfw/AssetManager.h> 2840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include <androidfw/ResourceTypes.h> 2940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include <utils/KeyedVector.h> 3040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski#include <utils/Vector.h> 3140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 3240e8eefbedcafc51948945647d746daaee092f16Adam Lesinskiusing namespace android; 3340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 3440e8eefbedcafc51948945647d746daaee092f16Adam Lesinskinamespace split { 3540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 3640e8eefbedcafc51948945647d746daaee092f16Adam Lesinskistatic void usage() { 3740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski fprintf(stderr, 3840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski "split-select --help\n" 3940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski "split-select --target <config> --split <path/to/apk> [--split <path/to/apk> [...]]\n" 4040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski "split-select --generate --split <path/to/apk> [--split <path/to/apk> [...]]\n" 4140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski "\n" 4240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski " --help Displays more information about this program.\n" 4340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski " --target <config> Performs the Split APK selection on the given configuration.\n" 4440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski " --generate Generates the logic for selecting the Split APK, in JSON format.\n" 4540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski " --split <path/to/apk> Includes a Split APK in the selection process.\n" 4640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski "\n" 4740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski " Where <config> is an extended AAPT resource qualifier of the form\n" 4840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski " 'resource-qualifiers:extended-qualifiers', where 'resource-qualifiers' is an AAPT resource\n" 4940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski " qualifier (ex: en-rUS-sw600dp-xhdpi), and 'extended-qualifiers' is an ordered list of one\n" 5040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski " qualifier (or none) from each category:\n" 5140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski " Architecture: armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, mips\n"); 5240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} 5340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 5440e8eefbedcafc51948945647d746daaee092f16Adam Lesinskistatic void help() { 5540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski usage(); 5640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski fprintf(stderr, "\n" 5740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski " Generates the logic for selecting a Split APK given some target Android device configuration.\n" 5840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski " Using the flag --generate will emit a JSON encoded tree of rules that must be satisfied in order\n" 5940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski " to install the given Split APK. Using the flag --target along with the device configuration\n" 6040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski " will emit the set of Split APKs to install, following the same logic that would have been emitted\n" 6140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski " via JSON.\n"); 6240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} 6340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 6440e8eefbedcafc51948945647d746daaee092f16Adam Lesinskiclass SplitSelector { 6540e8eefbedcafc51948945647d746daaee092f16Adam Lesinskipublic: 6640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski SplitSelector() = default; 6740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski SplitSelector(const Vector<SplitDescription>& splits); 6840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 6940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski Vector<SplitDescription> getBestSplits(const SplitDescription& target) const; 7040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 7140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski template <typename RuleGenerator> 7240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski KeyedVector<SplitDescription, sp<Rule> > getRules() const; 7340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 7440e8eefbedcafc51948945647d746daaee092f16Adam Lesinskiprivate: 7540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski Vector<SortedVector<SplitDescription> > mGroups; 7640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski}; 7740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 7840e8eefbedcafc51948945647d746daaee092f16Adam LesinskiSplitSelector::SplitSelector(const Vector<SplitDescription>& splits) 7940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski : mGroups(groupByMutualExclusivity(splits)) { 8040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} 8140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 8240e8eefbedcafc51948945647d746daaee092f16Adam Lesinskistatic void selectBestFromGroup(const SortedVector<SplitDescription>& splits, 8340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const SplitDescription& target, Vector<SplitDescription>& splitsOut) { 8440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski SplitDescription bestSplit; 8540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski bool isSet = false; 8640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const size_t splitCount = splits.size(); 8740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t j = 0; j < splitCount; j++) { 8840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const SplitDescription& thisSplit = splits[j]; 8940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (!thisSplit.match(target)) { 9040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski continue; 9140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 9240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 9340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (!isSet || thisSplit.isBetterThan(bestSplit, target)) { 9440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski isSet = true; 9540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski bestSplit = thisSplit; 9640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 9740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 9840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 9940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (isSet) { 10040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski splitsOut.add(bestSplit); 10140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 10240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} 10340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 10440e8eefbedcafc51948945647d746daaee092f16Adam LesinskiVector<SplitDescription> SplitSelector::getBestSplits(const SplitDescription& target) const { 10540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski Vector<SplitDescription> bestSplits; 10640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const size_t groupCount = mGroups.size(); 10740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t i = 0; i < groupCount; i++) { 10840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski selectBestFromGroup(mGroups[i], target, bestSplits); 10940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 11040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return bestSplits; 11140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} 11240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 11340e8eefbedcafc51948945647d746daaee092f16Adam Lesinskitemplate <typename RuleGenerator> 11440e8eefbedcafc51948945647d746daaee092f16Adam LesinskiKeyedVector<SplitDescription, sp<Rule> > SplitSelector::getRules() const { 11540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski KeyedVector<SplitDescription, sp<Rule> > rules; 11640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 11740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const size_t groupCount = mGroups.size(); 11840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t i = 0; i < groupCount; i++) { 11940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const SortedVector<SplitDescription>& splits = mGroups[i]; 12040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const size_t splitCount = splits.size(); 12140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t j = 0; j < splitCount; j++) { 12240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski sp<Rule> rule = Rule::simplify(RuleGenerator::generate(splits, j)); 12340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (rule != NULL) { 12440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski rules.add(splits[j], rule); 12540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 12640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 12740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 12840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return rules; 12940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} 13040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 13140e8eefbedcafc51948945647d746daaee092f16Adam LesinskiVector<SplitDescription> select(const SplitDescription& target, const Vector<SplitDescription>& splits) { 13240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const SplitSelector selector(splits); 13340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return selector.getBestSplits(target); 13440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} 13540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 13640e8eefbedcafc51948945647d746daaee092f16Adam Lesinskivoid generate(const KeyedVector<String8, Vector<SplitDescription> >& splits) { 13740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski Vector<SplitDescription> allSplits; 13840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const size_t apkSplitCount = splits.size(); 13940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t i = 0; i < apkSplitCount; i++) { 14040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski allSplits.appendVector(splits[i]); 14140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 14240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const SplitSelector selector(allSplits); 14340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski KeyedVector<SplitDescription, sp<Rule> > rules(selector.getRules<RuleGenerator>()); 14440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 14540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski fprintf(stdout, "[\n"); 14640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t i = 0; i < apkSplitCount; i++) { 14740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski sp<Rule> masterRule = new Rule(); 14840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski masterRule->op = Rule::OR_SUBRULES; 14940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const Vector<SplitDescription>& splitDescriptions = splits[i]; 15040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const size_t splitDescriptionCount = splitDescriptions.size(); 15140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t j = 0; j < splitDescriptionCount; j++) { 15240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski masterRule->subrules.add(rules.valueFor(splitDescriptions[j])); 15340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 15440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski masterRule = Rule::simplify(masterRule); 15540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski fprintf(stdout, " {\n \"path\": \"%s\",\n \"rules\": %s\n }%s\n", 15640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski splits.keyAt(i).string(), 15740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski masterRule->toJson(2).string(), 15840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski i < apkSplitCount - 1 ? "," : ""); 15940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 16040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski fprintf(stdout, "]\n"); 16140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} 16240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 16340e8eefbedcafc51948945647d746daaee092f16Adam Lesinskistatic void removeRuntimeQualifiers(ConfigDescription* outConfig) { 16440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski outConfig->imsi = 0; 16540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski outConfig->orientation = ResTable_config::ORIENTATION_ANY; 16640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski outConfig->screenWidth = ResTable_config::SCREENWIDTH_ANY; 16740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski outConfig->screenHeight = ResTable_config::SCREENHEIGHT_ANY; 16840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski outConfig->uiMode &= ResTable_config::UI_MODE_NIGHT_ANY; 16940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} 17040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 17140e8eefbedcafc51948945647d746daaee092f16Adam Lesinskistatic Vector<SplitDescription> extractSplitDescriptionsFromApk(const String8& path) { 17240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski AssetManager assetManager; 17340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski Vector<SplitDescription> splits; 17440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski int32_t cookie = 0; 17540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (!assetManager.addAssetPath(path, &cookie)) { 17640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return splits; 17740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 17840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 17940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const ResTable& res = assetManager.getResources(false); 18040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (res.getError() == NO_ERROR) { 18140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski Vector<ResTable_config> configs; 18240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski res.getConfigurations(&configs); 18340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const size_t configCount = configs.size(); 18440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t i = 0; i < configCount; i++) { 18540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski splits.add(); 18640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski splits.editTop().config = configs[i]; 18740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 18840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 18940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 19040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski AssetDir* dir = assetManager.openNonAssetDir(cookie, "lib"); 19140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (dir != NULL) { 19240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const size_t fileCount = dir->getFileCount(); 19340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t i = 0; i < fileCount; i++) { 19440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski splits.add(); 19540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski Vector<String8> parts = AaptUtil::splitAndLowerCase(dir->getFileName(i), '-'); 19640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (parseAbi(parts, 0, &splits.editTop()) < 0) { 19740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski fprintf(stderr, "Malformed library %s\n", dir->getFileName(i).string()); 19840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski splits.pop(); 19940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 20040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 20140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski delete dir; 20240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 20340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return splits; 20440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} 20540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 20640e8eefbedcafc51948945647d746daaee092f16Adam Lesinskistatic int main(int argc, char** argv) { 20740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski // Skip over the first argument. 20840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski argc--; 20940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski argv++; 21040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 21140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski bool generateFlag = false; 21240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski String8 targetConfigStr; 21340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski Vector<String8> splitApkPaths; 21440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski while (argc > 0) { 21540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const String8 arg(*argv); 21640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (arg == "--target") { 21740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski argc--; 21840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski argv++; 21940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (argc < 1) { 22040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski fprintf(stderr, "Missing parameter for --split.\n"); 22140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski usage(); 22240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return 1; 22340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 22440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski targetConfigStr.setTo(*argv); 22540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } else if (arg == "--split") { 22640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski argc--; 22740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski argv++; 22840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (argc < 1) { 22940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski fprintf(stderr, "Missing parameter for --split.\n"); 23040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski usage(); 23140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return 1; 23240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 23340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski splitApkPaths.add(String8(*argv)); 23440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } else if (arg == "--generate") { 23540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski generateFlag = true; 23640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } else if (arg == "--help") { 23740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski help(); 23840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return 0; 23940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } else { 24040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski fprintf(stderr, "Unknown argument '%s'\n", arg.string()); 24140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski usage(); 24240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return 1; 24340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 24440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski argc--; 24540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski argv++; 24640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 24740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 24840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (!generateFlag && targetConfigStr == "") { 24940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski usage(); 25040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return 1; 25140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 25240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 25340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (splitApkPaths.size() == 0) { 25440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski usage(); 25540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return 1; 25640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 25740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 25840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski SplitDescription targetSplit; 25940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (!generateFlag) { 26040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (!SplitDescription::parse(targetConfigStr, &targetSplit)) { 26140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski fprintf(stderr, "Invalid --target config: '%s'\n", 26240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski targetConfigStr.string()); 26340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski usage(); 26440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return 1; 26540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 26640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 26740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski // We don't want to match on things that will change at run-time 26840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski // (orientation, w/h, etc.). 26940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski removeRuntimeQualifiers(&targetSplit.config); 27040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 27140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 27240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski KeyedVector<String8, Vector<SplitDescription> > apkPathSplitMap; 27340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski KeyedVector<SplitDescription, String8> splitApkPathMap; 27440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski Vector<SplitDescription> splitConfigs; 27540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const size_t splitCount = splitApkPaths.size(); 27640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t i = 0; i < splitCount; i++) { 27740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski Vector<SplitDescription> splits = extractSplitDescriptionsFromApk(splitApkPaths[i]); 27840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (splits.isEmpty()) { 27940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski fprintf(stderr, "Invalid --split path: '%s'. No splits found.\n", 28040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski splitApkPaths[i].string()); 28140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski usage(); 28240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return 1; 28340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 28440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski apkPathSplitMap.replaceValueFor(splitApkPaths[i], splits); 28540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const size_t apkSplitDescriptionCount = splits.size(); 28640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t j = 0; j < apkSplitDescriptionCount; j++) { 28740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski splitApkPathMap.replaceValueFor(splits[j], splitApkPaths[i]); 28840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 28940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski splitConfigs.appendVector(splits); 29040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 29140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 29240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski if (!generateFlag) { 29340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski Vector<SplitDescription> matchingConfigs = select(targetSplit, splitConfigs); 29440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const size_t matchingConfigCount = matchingConfigs.size(); 29540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski SortedVector<String8> matchingSplitPaths; 29640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t i = 0; i < matchingConfigCount; i++) { 29740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski matchingSplitPaths.add(splitApkPathMap.valueFor(matchingConfigs[i])); 29840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 29940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 30040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski const size_t matchingSplitApkPathCount = matchingSplitPaths.size(); 30140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski for (size_t i = 0; i < matchingSplitApkPathCount; i++) { 30240e8eefbedcafc51948945647d746daaee092f16Adam Lesinski fprintf(stderr, "%s\n", matchingSplitPaths[i].string()); 30340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 30440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } else { 30540e8eefbedcafc51948945647d746daaee092f16Adam Lesinski generate(apkPathSplitMap); 30640e8eefbedcafc51948945647d746daaee092f16Adam Lesinski } 30740e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return 0; 30840e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} 30940e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 31040e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} // namespace split 31140e8eefbedcafc51948945647d746daaee092f16Adam Lesinski 31240e8eefbedcafc51948945647d746daaee092f16Adam Lesinskiint main(int argc, char** argv) { 31340e8eefbedcafc51948945647d746daaee092f16Adam Lesinski return split::main(argc, argv); 31440e8eefbedcafc51948945647d746daaee092f16Adam Lesinski} 315