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