| Adam Lesinski | fab5087 | 2014-04-16 14:40:42 -0700 | [diff] [blame] | 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 "AaptAssets.h" | 
|  | 18 | #include "ApkBuilder.h" | 
|  | 19 |  | 
|  | 20 | using namespace android; | 
|  | 21 |  | 
|  | 22 | ApkBuilder::ApkBuilder(const sp<WeakResourceFilter>& configFilter) | 
|  | 23 | : mConfigFilter(configFilter) | 
|  | 24 | , mDefaultFilter(new AndResourceFilter()) { | 
|  | 25 | // Add the default split, which is present for all APKs. | 
|  | 26 | mDefaultFilter->addFilter(mConfigFilter); | 
|  | 27 | mSplits.add(new ApkSplit(std::set<ConfigDescription>(), mDefaultFilter, true)); | 
|  | 28 | } | 
|  | 29 |  | 
|  | 30 | status_t ApkBuilder::createSplitForConfigs(const std::set<ConfigDescription>& configs) { | 
|  | 31 | const size_t N = mSplits.size(); | 
|  | 32 | for (size_t i = 0; i < N; i++) { | 
|  | 33 | const std::set<ConfigDescription>& splitConfigs = mSplits[i]->getConfigs(); | 
|  | 34 | std::set<ConfigDescription>::const_iterator iter = configs.begin(); | 
|  | 35 | for (; iter != configs.end(); iter++) { | 
|  | 36 | if (splitConfigs.count(*iter) > 0) { | 
|  | 37 | // Can't have overlapping configurations. | 
|  | 38 | fprintf(stderr, "ERROR: Split configuration '%s' is already defined " | 
| Tomasz Wasilczyk | d2a6983 | 2023-08-10 23:54:44 +0000 | [diff] [blame] | 39 | "in another split.\n", iter->toString().c_str()); | 
| Adam Lesinski | fab5087 | 2014-04-16 14:40:42 -0700 | [diff] [blame] | 40 | return ALREADY_EXISTS; | 
|  | 41 | } | 
|  | 42 | } | 
|  | 43 | } | 
|  | 44 |  | 
|  | 45 | sp<StrongResourceFilter> splitFilter = new StrongResourceFilter(configs); | 
|  | 46 |  | 
|  | 47 | // Add the inverse filter of this split filter to the base apk filter so it will | 
|  | 48 | // omit resources that belong in this split. | 
|  | 49 | mDefaultFilter->addFilter(new InverseResourceFilter(splitFilter)); | 
|  | 50 |  | 
|  | 51 | // Now add the apk-wide config filter to our split filter. | 
|  | 52 | sp<AndResourceFilter> filter = new AndResourceFilter(); | 
|  | 53 | filter->addFilter(splitFilter); | 
|  | 54 | filter->addFilter(mConfigFilter); | 
|  | 55 | mSplits.add(new ApkSplit(configs, filter)); | 
|  | 56 | return NO_ERROR; | 
|  | 57 | } | 
|  | 58 |  | 
|  | 59 | status_t ApkBuilder::addEntry(const String8& path, const sp<AaptFile>& file) { | 
|  | 60 | const size_t N = mSplits.size(); | 
|  | 61 | for (size_t i = 0; i < N; i++) { | 
|  | 62 | if (mSplits[i]->matches(file)) { | 
|  | 63 | return mSplits.editItemAt(i)->addEntry(path, file); | 
|  | 64 | } | 
|  | 65 | } | 
|  | 66 | // Entry can be dropped if it doesn't match any split. This will only happen | 
|  | 67 | // if the enry doesn't mConfigFilter. | 
|  | 68 | return NO_ERROR; | 
|  | 69 | } | 
|  | 70 |  | 
|  | 71 | void ApkBuilder::print() const { | 
|  | 72 | fprintf(stderr, "APK Builder\n"); | 
|  | 73 | fprintf(stderr, "-----------\n"); | 
|  | 74 | const size_t N = mSplits.size(); | 
|  | 75 | for (size_t i = 0; i < N; i++) { | 
|  | 76 | mSplits[i]->print(); | 
|  | 77 | fprintf(stderr, "\n"); | 
|  | 78 | } | 
|  | 79 | } | 
|  | 80 |  | 
|  | 81 | ApkSplit::ApkSplit(const std::set<ConfigDescription>& configs, const sp<ResourceFilter>& filter, bool isBase) | 
|  | 82 | : mConfigs(configs), mFilter(filter), mIsBase(isBase) { | 
|  | 83 | std::set<ConfigDescription>::const_iterator iter = configs.begin(); | 
|  | 84 | for (; iter != configs.end(); iter++) { | 
|  | 85 | if (mName.size() > 0) { | 
|  | 86 | mName.append(","); | 
|  | 87 | mDirName.append("_"); | 
| Adam Lesinski | 6240840 | 2014-08-07 21:26:53 -0700 | [diff] [blame] | 88 | mPackageSafeName.append("."); | 
| Adam Lesinski | fab5087 | 2014-04-16 14:40:42 -0700 | [diff] [blame] | 89 | } | 
|  | 90 |  | 
|  | 91 | String8 configStr = iter->toString(); | 
| Adam Lesinski | 6240840 | 2014-08-07 21:26:53 -0700 | [diff] [blame] | 92 | String8 packageConfigStr(configStr); | 
|  | 93 | size_t len = packageConfigStr.length(); | 
|  | 94 | if (len > 0) { | 
|  | 95 | char* buf = packageConfigStr.lockBuffer(len); | 
|  | 96 | for (char* end = buf + len; buf < end; ++buf) { | 
|  | 97 | if (*buf == '-') { | 
|  | 98 | *buf = '_'; | 
|  | 99 | } | 
|  | 100 | } | 
|  | 101 | packageConfigStr.unlockBuffer(len); | 
|  | 102 | } | 
| Adam Lesinski | fab5087 | 2014-04-16 14:40:42 -0700 | [diff] [blame] | 103 | mName.append(configStr); | 
|  | 104 | mDirName.append(configStr); | 
| Adam Lesinski | 6240840 | 2014-08-07 21:26:53 -0700 | [diff] [blame] | 105 | mPackageSafeName.append(packageConfigStr); | 
| Adam Lesinski | fab5087 | 2014-04-16 14:40:42 -0700 | [diff] [blame] | 106 | } | 
|  | 107 | } | 
|  | 108 |  | 
|  | 109 | status_t ApkSplit::addEntry(const String8& path, const sp<AaptFile>& file) { | 
|  | 110 | if (!mFiles.insert(OutputEntry(path, file)).second) { | 
|  | 111 | // Duplicate file. | 
|  | 112 | return ALREADY_EXISTS; | 
|  | 113 | } | 
|  | 114 | return NO_ERROR; | 
|  | 115 | } | 
|  | 116 |  | 
|  | 117 | void ApkSplit::print() const { | 
| Tomasz Wasilczyk | d2a6983 | 2023-08-10 23:54:44 +0000 | [diff] [blame] | 118 | fprintf(stderr, "APK Split '%s'\n", mName.c_str()); | 
| Adam Lesinski | fab5087 | 2014-04-16 14:40:42 -0700 | [diff] [blame] | 119 |  | 
|  | 120 | std::set<OutputEntry>::const_iterator iter = mFiles.begin(); | 
|  | 121 | for (; iter != mFiles.end(); iter++) { | 
| Tomasz Wasilczyk | d2a6983 | 2023-08-10 23:54:44 +0000 | [diff] [blame] | 122 | fprintf(stderr, "  %s (%s)\n", iter->getPath().c_str(), iter->getFile()->getSourceFile().c_str()); | 
| Adam Lesinski | fab5087 | 2014-04-16 14:40:42 -0700 | [diff] [blame] | 123 | } | 
|  | 124 | } |