1355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski/* 2355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * Copyright (C) 2016 The Android Open Source Project 3355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * 4355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * you may not use this file except in compliance with the License. 6355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * You may obtain a copy of the License at 7355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * 8355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * 10355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * Unless required by applicable law or agreed to in writing, software 11355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * See the License for the specific language governing permissions and 14355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * limitations under the License. 15355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski */ 16355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 17355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski#include "ConfigDescription.h" 18355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski#include "ResourceTable.h" 19355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski#include "split/TableSplitter.h" 20355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 21803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski#include <algorithm> 22355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski#include <map> 23355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski#include <set> 24355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski#include <unordered_map> 25355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski#include <vector> 26355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 27355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskinamespace aapt { 28355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 29355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskiusing ConfigClaimedMap = std::unordered_map<ResourceConfigValue*, bool>; 30355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskiusing ConfigDensityGroups = std::map<ConfigDescription, std::vector<ResourceConfigValue*>>; 31355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 32355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskistatic ConfigDescription copyWithoutDensity(const ConfigDescription& config) { 33355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski ConfigDescription withoutDensity = config; 34355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski withoutDensity.density = 0; 35355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski return withoutDensity; 36355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 37355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 38355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski/** 39355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * Selects values that match exactly the constraints given. 40355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski */ 41355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskiclass SplitValueSelector { 42355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskipublic: 43355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski SplitValueSelector(const SplitConstraints& constraints) { 44355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (const ConfigDescription& config : constraints.configs) { 45355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (config.density == 0) { 46355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski mDensityIndependentConfigs.insert(config); 47355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } else { 48355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski mDensityDependentConfigToDensityMap[copyWithoutDensity(config)] = config.density; 49355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 50355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 51355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 52355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 53355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski std::vector<ResourceConfigValue*> selectValues(const ConfigDensityGroups& densityGroups, 54355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski ConfigClaimedMap* claimedValues) { 55355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski std::vector<ResourceConfigValue*> selected; 56355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 57355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // Select the regular values. 58355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (auto& entry : *claimedValues) { 59355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // Check if the entry has a density. 60355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski ResourceConfigValue* configValue = entry.first; 61355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (configValue->config.density == 0 && !entry.second) { 62355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // This is still available. 63355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (mDensityIndependentConfigs.find(configValue->config) != 64355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski mDensityIndependentConfigs.end()) { 65355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski selected.push_back(configValue); 66355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 67355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // Mark the entry as taken. 68355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski entry.second = true; 69355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 70355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 71355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 72355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 73355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // Now examine the densities 74355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (auto& entry : densityGroups) { 75355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // We do not care if the value is claimed, since density values can be 76355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // in multiple splits. 77355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski const ConfigDescription& config = entry.first; 78355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski const std::vector<ResourceConfigValue*>& relatedValues = entry.second; 79355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 80355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski auto densityValueIter = mDensityDependentConfigToDensityMap.find(config); 81355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (densityValueIter != mDensityDependentConfigToDensityMap.end()) { 82355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // Select the best one! 83355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski ConfigDescription targetDensity = config; 84355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski targetDensity.density = densityValueIter->second; 85355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 86355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski ResourceConfigValue* bestValue = nullptr; 87355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (ResourceConfigValue* thisValue : relatedValues) { 88355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (!bestValue || 89355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski thisValue->config.isBetterThan(bestValue->config, &targetDensity)) { 90355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski bestValue = thisValue; 91355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 92355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 93355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // When we select one of these, they are all claimed such that the base 94355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // doesn't include any anymore. 95355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski (*claimedValues)[thisValue] = true; 96355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 97355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski assert(bestValue); 98355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski selected.push_back(bestValue); 99355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 100355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 101355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski return selected; 102355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 103355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 104355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskiprivate: 105355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski std::set<ConfigDescription> mDensityIndependentConfigs; 106355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski std::map<ConfigDescription, uint16_t> mDensityDependentConfigToDensityMap; 107355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski}; 108355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 109355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski/** 110355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * Marking non-preferred densities as claimed will make sure the base doesn't include them, 111355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski * leaving only the preferred density behind. 112355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski */ 113355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskistatic void markNonPreferredDensitiesAsClaimed(uint16_t preferredDensity, 114355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski const ConfigDensityGroups& densityGroups, 115355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski ConfigClaimedMap* configClaimedMap) { 116355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (auto& entry : densityGroups) { 117355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski const ConfigDescription& config = entry.first; 118355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski const std::vector<ResourceConfigValue*>& relatedValues = entry.second; 119355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 120355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski ConfigDescription targetDensity = config; 121355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski targetDensity.density = preferredDensity; 122355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski ResourceConfigValue* bestValue = nullptr; 123355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (ResourceConfigValue* thisValue : relatedValues) { 124355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (!bestValue) { 125355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski bestValue = thisValue; 126355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } else if (thisValue->config.isBetterThan(bestValue->config, &targetDensity)) { 127355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // Claim the previous value so that it is not included in the base. 128355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski (*configClaimedMap)[bestValue] = true; 129355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski bestValue = thisValue; 130355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } else { 131355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // Claim this value so that it is not included in the base. 132355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski (*configClaimedMap)[thisValue] = true; 133355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 134355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 135355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski assert(bestValue); 136355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 137355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 138355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 139355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskibool TableSplitter::verifySplitConstraints(IAaptContext* context) { 140355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski bool error = false; 141355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (size_t i = 0; i < mSplitConstraints.size(); i++) { 142355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (size_t j = i + 1; j < mSplitConstraints.size(); j++) { 143355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (const ConfigDescription& config : mSplitConstraints[i].configs) { 144355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (mSplitConstraints[j].configs.find(config) != 145355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski mSplitConstraints[j].configs.end()) { 146355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski context->getDiagnostics()->error(DiagMessage() << "config '" << config 147355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski << "' appears in multiple splits, " 148355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski << "target split ambiguous"); 149355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski error = true; 150355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 151355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 152355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 153355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 154355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski return !error; 155355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 156355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 157355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinskivoid TableSplitter::splitTable(ResourceTable* originalTable) { 158355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski const size_t splitCount = mSplitConstraints.size(); 159355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (auto& pkg : originalTable->packages) { 160355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // Initialize all packages for splits. 161355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (size_t idx = 0; idx < splitCount; idx++) { 162355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski ResourceTable* splitTable = mSplits[idx].get(); 163355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski splitTable->createPackage(pkg->name, pkg->id); 164355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 165355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 166355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (auto& type : pkg->types) { 167355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (type->type == ResourceType::kMipmap) { 168355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // Always keep mipmaps. 169355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski continue; 170355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 171355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 172355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (auto& entry : type->entries) { 173355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (mConfigFilter) { 174355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // First eliminate any resource that we definitely don't want. 175355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (std::unique_ptr<ResourceConfigValue>& configValue : entry->values) { 176355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (!mConfigFilter->match(configValue->config)) { 177355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // null out the entry. We will clean up and remove nulls at the end 178355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // for performance reasons. 179355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski configValue.reset(); 180355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 181355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 182355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 183355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 184355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // Organize the values into two separate buckets. Those that are density-dependent 185355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // and those that are density-independent. 186355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // One density technically matches all density, it's just that some densities 187355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // match better. So we need to be aware of the full set of densities to make this 188355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // decision. 189355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski ConfigDensityGroups densityGroups; 190355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski ConfigClaimedMap configClaimedMap; 191355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (const std::unique_ptr<ResourceConfigValue>& configValue : entry->values) { 192355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (configValue) { 193355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski configClaimedMap[configValue.get()] = false; 194355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 195355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (configValue->config.density != 0) { 196355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // Create a bucket for this density-dependent config. 197355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski densityGroups[copyWithoutDensity(configValue->config)] 198355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski .push_back(configValue.get()); 199355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 200355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 201355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 202355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 203355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // First we check all the splits. If it doesn't match one of the splits, we 204355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // leave it in the base. 205355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (size_t idx = 0; idx < splitCount; idx++) { 206355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski const SplitConstraints& splitConstraint = mSplitConstraints[idx]; 207355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski ResourceTable* splitTable = mSplits[idx].get(); 208355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 209355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // Select the values we want from this entry for this split. 210355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski SplitValueSelector selector(splitConstraint); 211355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski std::vector<ResourceConfigValue*> selectedValues = 212355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski selector.selectValues(densityGroups, &configClaimedMap); 213355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 214355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // No need to do any work if we selected nothing. 215355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (!selectedValues.empty()) { 216355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // Create the same resource structure in the split. We do this lazily 217355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // because we might not have actual values for each type/entry. 218355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski ResourceTablePackage* splitPkg = splitTable->findPackage(pkg->name); 219355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski ResourceTableType* splitType = splitPkg->findOrCreateType(type->type); 220355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (!splitType->id) { 221355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski splitType->id = type->id; 222355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski splitType->symbolStatus = type->symbolStatus; 223355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 224355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 225355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski ResourceEntry* splitEntry = splitType->findOrCreateEntry(entry->name); 226355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (!splitEntry->id) { 227355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski splitEntry->id = entry->id; 228355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski splitEntry->symbolStatus = entry->symbolStatus; 229355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 230355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 231355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // Copy the selected values into the new Split Entry. 232355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (ResourceConfigValue* configValue : selectedValues) { 233355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski ResourceConfigValue* newConfigValue = splitEntry->findOrCreateValue( 234355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski configValue->config, configValue->product); 235355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski newConfigValue->value = std::unique_ptr<Value>( 236355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski configValue->value->clone(&splitTable->stringPool)); 237355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 238355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 239355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 240355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 241355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (mPreferredDensity) { 242355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski markNonPreferredDensitiesAsClaimed(mPreferredDensity.value(), 243355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski densityGroups, 244355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski &configClaimedMap); 245355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 246355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 247355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // All splits are handled, now check to see what wasn't claimed and remove 248355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // whatever exists in other splits. 249355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski for (std::unique_ptr<ResourceConfigValue>& configValue : entry->values) { 250355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski if (configValue && configClaimedMap[configValue.get()]) { 251355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // Claimed, remove from base. 252355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski configValue.reset(); 253355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 254355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 255355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 256355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski // Now erase all nullptrs. 257355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski entry->values.erase( 258355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski std::remove(entry->values.begin(), entry->values.end(), nullptr), 259355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski entry->values.end()); 260355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 261355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 262355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski } 263355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} 264355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 265355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski} // namespace aapt 266