11ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/*
21ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Copyright (C) 2015 The Android Open Source Project
31ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *
41ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
51ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * you may not use this file except in compliance with the License.
61ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * You may obtain a copy of the License at
71ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *
81ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
91ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *
101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Unless required by applicable law or agreed to in writing, software
111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * See the License for the specific language governing permissions and
141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * limitations under the License.
151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */
161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ResourceTable.h"
181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ResourceValues.h"
191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ValueVisitor.h"
201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "flatten/ChunkWriter.h"
221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "flatten/ResourceTypeExtensions.h"
231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "flatten/TableFlattener.h"
241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/BigBuffer.h"
251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
26e7d2cc308e5f53f244cc05473e1c51127ef057d9Elliott Hughes#include <android-base/macros.h>
27803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski#include <algorithm>
281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <type_traits>
291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <numeric>
301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiusing namespace android;
321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace aapt {
341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace {
361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskitemplate <typename T>
381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistatic bool cmpIds(const T* a, const T* b) {
391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    return a->id.value() < b->id.value();
401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}
411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistatic void strcpy16_htod(uint16_t* dst, size_t len, const StringPiece16& src) {
431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    if (len == 0) {
441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        return;
451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    size_t i;
481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    const char16_t* srcData = src.data();
491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    for (i = 0; i < len - 1 && i < src.size(); i++) {
501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        dst[i] = util::hostToDevice16((uint16_t) srcData[i]);
511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    dst[i] = 0;
531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}
541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
5559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskistatic bool cmpStyleEntries(const Style::Entry& a, const Style::Entry& b) {
5659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski   if (a.key.id) {
5759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski       if (b.key.id) {
5859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski           return a.key.id.value() < b.key.id.value();
5959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski       }
6059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski       return true;
6159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski   } else if (!b.key.id) {
6259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski       return a.key.name.value() < b.key.name.value();
6359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski   }
6459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski   return false;
6559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski}
6659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistruct FlatEntry {
681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    ResourceEntry* entry;
691ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    Value* value;
703b4cd94034ff3e5567a2ba6da35d640ff61db4b9Adam Lesinski
713b4cd94034ff3e5567a2ba6da35d640ff61db4b9Adam Lesinski    // The entry string pool index to the entry's name.
721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    uint32_t entryKey;
731ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
7559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskiclass MapFlattenVisitor : public RawValueVisitor {
769ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinskipublic:
771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    using RawValueVisitor::visit;
781ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
7959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    MapFlattenVisitor(ResTable_entry_ext* outEntry, BigBuffer* buffer) :
8059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski            mOutEntry(outEntry), mBuffer(buffer) {
8128cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski    }
8228cacf091ad2b1c2749e77f590e9523e58735252Adam Lesinski
831ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    void visit(Attribute* attr) override {
841ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        {
8559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski            Reference key = Reference(ResTable_map::ATTR_TYPE);
861ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            BinaryPrimitive val(Res_value::TYPE_INT_DEC, attr->typeMask);
871ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            flattenEntry(&key, &val);
881ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
90a587065721053ad54e34f484868142407d59512dAdam Lesinski        if (attr->minInt != std::numeric_limits<int32_t>::min()) {
9159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski            Reference key = Reference(ResTable_map::ATTR_MIN);
92a587065721053ad54e34f484868142407d59512dAdam Lesinski            BinaryPrimitive val(Res_value::TYPE_INT_DEC, static_cast<uint32_t>(attr->minInt));
93a587065721053ad54e34f484868142407d59512dAdam Lesinski            flattenEntry(&key, &val);
94a587065721053ad54e34f484868142407d59512dAdam Lesinski        }
95a587065721053ad54e34f484868142407d59512dAdam Lesinski
96a587065721053ad54e34f484868142407d59512dAdam Lesinski        if (attr->maxInt != std::numeric_limits<int32_t>::max()) {
9759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski            Reference key = Reference(ResTable_map::ATTR_MAX);
98a587065721053ad54e34f484868142407d59512dAdam Lesinski            BinaryPrimitive val(Res_value::TYPE_INT_DEC, static_cast<uint32_t>(attr->maxInt));
99a587065721053ad54e34f484868142407d59512dAdam Lesinski            flattenEntry(&key, &val);
100a587065721053ad54e34f484868142407d59512dAdam Lesinski        }
101a587065721053ad54e34f484868142407d59512dAdam Lesinski
1021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        for (Attribute::Symbol& s : attr->symbols) {
1031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            BinaryPrimitive val(Res_value::TYPE_INT_DEC, s.value);
1041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            flattenEntry(&s.symbol, &val);
1051ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
1061ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
1071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    void visit(Style* style) override {
1091ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        if (style->parent) {
11059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski            const Reference& parentRef = style->parent.value();
11159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski            assert(parentRef.id && "parent has no ID");
11259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski            mOutEntry->parent.ident = util::hostToDevice32(parentRef.id.value().id);
1131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
1141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        // Sort the style.
1161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        std::sort(style->entries.begin(), style->entries.end(), cmpStyleEntries);
1171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        for (Style::Entry& entry : style->entries) {
1191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            flattenEntry(&entry.key, entry.value.get());
1201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
1211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
1221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    void visit(Styleable* styleable) override {
1241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        for (auto& attrRef : styleable->entries) {
1251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            BinaryPrimitive val(Res_value{});
1261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            flattenEntry(&attrRef, &val);
1271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
12859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
1291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
1301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    void visit(Array* array) override {
1321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        for (auto& item : array->items) {
1331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            ResTable_map* outEntry = mBuffer->nextBlock<ResTable_map>();
1341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            flattenValue(item.get(), outEntry);
1351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            outEntry->value.size = util::hostToDevice16(sizeof(outEntry->value));
1361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            mEntryCount++;
1371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
1381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
1391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    void visit(Plural* plural) override {
1411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        const size_t count = plural->values.size();
1421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        for (size_t i = 0; i < count; i++) {
1431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            if (!plural->values[i]) {
1441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                continue;
1451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            }
1461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            ResourceId q;
1481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            switch (i) {
1491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            case Plural::Zero:
1501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                q.id = android::ResTable_map::ATTR_ZERO;
1511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                break;
1521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            case Plural::One:
1541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                q.id = android::ResTable_map::ATTR_ONE;
1551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                break;
1561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            case Plural::Two:
1581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                q.id = android::ResTable_map::ATTR_TWO;
1591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                break;
1601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            case Plural::Few:
1621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                q.id = android::ResTable_map::ATTR_FEW;
1631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                break;
1641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            case Plural::Many:
1661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                q.id = android::ResTable_map::ATTR_MANY;
1671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                break;
1681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1691ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            case Plural::Other:
1701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                q.id = android::ResTable_map::ATTR_OTHER;
1711ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                break;
1721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1731ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            default:
1741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                assert(false);
1751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                break;
1761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            }
1771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1781ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            Reference key(q);
1791ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            flattenEntry(&key, plural->values[i].get());
1801ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
1811ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
18259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
18359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    /**
18459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski     * Call this after visiting a Value. This will finish any work that
18559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski     * needs to be done to prepare the entry.
18659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski     */
18759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    void finish() {
18859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        mOutEntry->count = util::hostToDevice32(mEntryCount);
18959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
19059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
19159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskiprivate:
19259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    void flattenKey(Reference* key, ResTable_map* outEntry) {
19359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        assert(key->id && "key has no ID");
19459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        outEntry->name.ident = util::hostToDevice32(key->id.value().id);
19559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
19659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
19759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    void flattenValue(Item* value, ResTable_map* outEntry) {
19859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        bool result = value->flatten(&outEntry->value);
19959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        assert(result && "flatten failed");
20059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
20159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
20259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    void flattenEntry(Reference* key, Item* value) {
20359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        ResTable_map* outEntry = mBuffer->nextBlock<ResTable_map>();
20459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        flattenKey(key, outEntry);
20559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        flattenValue(value, outEntry);
20659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        outEntry->value.size = util::hostToDevice16(sizeof(outEntry->value));
20759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        mEntryCount++;
20859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
20959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
21059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    ResTable_entry_ext* mOutEntry;
21159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    BigBuffer* mBuffer;
21259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    size_t mEntryCount = 0;
2131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
2141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2159ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinskiclass PackageFlattener {
2169ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinskipublic:
21759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    PackageFlattener(IDiagnostics* diag, ResourceTablePackage* package) :
21859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski            mDiag(diag), mPackage(package) {
2199ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    }
2209ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski
2219ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    bool flattenPackage(BigBuffer* buffer) {
2229ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        ChunkWriter pkgWriter(buffer);
2239ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        ResTable_package* pkgHeader = pkgWriter.startChunk<ResTable_package>(
2249ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski                RES_TABLE_PACKAGE_TYPE);
2259ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        pkgHeader->id = util::hostToDevice32(mPackage->id.value());
2269ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski
2279ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        if (mPackage->name.size() >= arraysize(pkgHeader->name)) {
2289ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski            mDiag->error(DiagMessage() <<
2299ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski                         "package name '" << mPackage->name << "' is too long");
2309ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski            return false;
2319ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        }
2329ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski
2339ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        // Copy the package name in device endianness.
2349ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        strcpy16_htod(pkgHeader->name, arraysize(pkgHeader->name), mPackage->name);
2359ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski
2369ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        // Serialize the types. We do this now so that our type and key strings
2379ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        // are populated. We write those first.
2389ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        BigBuffer typeBuffer(1024);
2399ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        flattenTypes(&typeBuffer);
2409ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski
2419ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        pkgHeader->typeStrings = util::hostToDevice32(pkgWriter.size());
2429ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        StringPool::flattenUtf16(pkgWriter.getBuffer(), mTypePool);
2439ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski
2449ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        pkgHeader->keyStrings = util::hostToDevice32(pkgWriter.size());
2459ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        StringPool::flattenUtf16(pkgWriter.getBuffer(), mKeyPool);
2469ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski
2479ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        // Append the types.
2489ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        buffer->appendBuffer(std::move(typeBuffer));
2499ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski
2509ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        pkgWriter.finish();
2519ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        return true;
2529ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    }
2539ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski
2549ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinskiprivate:
2551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    IDiagnostics* mDiag;
2561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    ResourceTablePackage* mPackage;
2571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    StringPool mTypePool;
2581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    StringPool mKeyPool;
2591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
260e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski    template <typename T, bool IsItem>
2611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    T* writeEntry(FlatEntry* entry, BigBuffer* buffer) {
2621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        static_assert(std::is_same<ResTable_entry, T>::value ||
2631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                      std::is_same<ResTable_entry_ext, T>::value,
2641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                      "T must be ResTable_entry or ResTable_entry_ext");
2651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        T* result = buffer->nextBlock<T>();
2671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        ResTable_entry* outEntry = (ResTable_entry*)(result);
2689e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski        if (entry->entry->symbolStatus.state == SymbolState::kPublic) {
2691ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            outEntry->flags |= ResTable_entry::FLAG_PUBLIC;
2701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
2711ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        if (entry->value->isWeak()) {
2731ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            outEntry->flags |= ResTable_entry::FLAG_WEAK;
2741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
2751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
276e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski        if (!IsItem) {
2771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            outEntry->flags |= ResTable_entry::FLAG_COMPLEX;
2781ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
2791ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2801ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        outEntry->flags = util::hostToDevice16(outEntry->flags);
28159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        outEntry->key.index = util::hostToDevice32(entry->entryKey);
28259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        outEntry->size = util::hostToDevice16(sizeof(T));
2831ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        return result;
2841ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
2851ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2861ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    bool flattenValue(FlatEntry* entry, BigBuffer* buffer) {
287e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski        if (Item* item = valueCast<Item>(entry->value)) {
288e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski            writeEntry<ResTable_entry, true>(entry, buffer);
2891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            Res_value* outValue = buffer->nextBlock<Res_value>();
290e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski            bool result = item->flatten(outValue);
2911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            assert(result && "flatten failed");
2921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            outValue->size = util::hostToDevice16(sizeof(*outValue));
2931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        } else {
294e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski            ResTable_entry_ext* outEntry = writeEntry<ResTable_entry_ext, false>(entry, buffer);
29559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski            MapFlattenVisitor visitor(outEntry, buffer);
2961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            entry->value->accept(&visitor);
29759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski            visitor.finish();
2981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
2991ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        return true;
3001ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
3011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    bool flattenConfig(const ResourceTableType* type, const ConfigDescription& config,
3031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                       std::vector<FlatEntry>* entries, BigBuffer* buffer) {
3041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        ChunkWriter typeWriter(buffer);
3051ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        ResTable_type* typeHeader = typeWriter.startChunk<ResTable_type>(RES_TABLE_TYPE_TYPE);
3061ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        typeHeader->id = type->id.value();
3071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        typeHeader->config = config;
3081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        typeHeader->config.swapHtoD();
3091ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        auto maxAccum = [](uint32_t max, const std::unique_ptr<ResourceEntry>& a) -> uint32_t {
3111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            return std::max(max, (uint32_t) a->id.value());
3121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        };
3131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        // Find the largest entry ID. That is how many entries we will have.
3151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        const uint32_t entryCount =
3161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                std::accumulate(type->entries.begin(), type->entries.end(), 0, maxAccum) + 1;
3171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        typeHeader->entryCount = util::hostToDevice32(entryCount);
3191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        uint32_t* indices = typeWriter.nextBlock<uint32_t>(entryCount);
3201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        assert((size_t) entryCount <= std::numeric_limits<uint16_t>::max() + 1);
3221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        memset(indices, 0xff, entryCount * sizeof(uint32_t));
3231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        typeHeader->entriesStart = util::hostToDevice32(typeWriter.size());
3251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        const size_t entryStart = typeWriter.getBuffer()->size();
3271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        for (FlatEntry& flatEntry : *entries) {
3281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            assert(flatEntry.entry->id.value() < entryCount);
3291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            indices[flatEntry.entry->id.value()] = util::hostToDevice32(
3301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                    typeWriter.getBuffer()->size() - entryStart);
3311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            if (!flattenValue(&flatEntry, typeWriter.getBuffer())) {
3321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                mDiag->error(DiagMessage()
3331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                             << "failed to flatten resource '"
3341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                             << ResourceNameRef(mPackage->name, type->type, flatEntry.entry->name)
3351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                             << "' for configuration '" << config << "'");
3361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                return false;
3371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            }
3381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
3391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        typeWriter.finish();
3401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        return true;
3411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
3421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    std::vector<ResourceTableType*> collectAndSortTypes() {
3441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        std::vector<ResourceTableType*> sortedTypes;
3451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        for (auto& type : mPackage->types) {
34659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski            if (type->type == ResourceType::kStyleable) {
3471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                // Styleables aren't real Resource Types, they are represented in the R.java
3481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                // file.
3491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                continue;
3501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            }
3511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            assert(type->id && "type must have an ID set");
3531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            sortedTypes.push_back(type.get());
3551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
3561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        std::sort(sortedTypes.begin(), sortedTypes.end(), cmpIds<ResourceTableType>);
3571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        return sortedTypes;
3581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
3591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    std::vector<ResourceEntry*> collectAndSortEntries(ResourceTableType* type) {
3611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        // Sort the entries by entry ID.
3621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        std::vector<ResourceEntry*> sortedEntries;
3631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        for (auto& entry : type->entries) {
3641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            assert(entry->id && "entry must have an ID set");
3651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            sortedEntries.push_back(entry.get());
3661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
3671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        std::sort(sortedEntries.begin(), sortedEntries.end(), cmpIds<ResourceEntry>);
3681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        return sortedEntries;
3691ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
3701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3711ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    bool flattenTypeSpec(ResourceTableType* type, std::vector<ResourceEntry*>* sortedEntries,
3721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                         BigBuffer* buffer) {
3731ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        ChunkWriter typeSpecWriter(buffer);
3741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        ResTable_typeSpec* specHeader = typeSpecWriter.startChunk<ResTable_typeSpec>(
3751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                RES_TABLE_TYPE_SPEC_TYPE);
3761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        specHeader->id = type->id.value();
3771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3781ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        if (sortedEntries->empty()) {
3791ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            typeSpecWriter.finish();
3801ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            return true;
3811ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
3821ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3831ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        // We can't just take the size of the vector. There may be holes in the entry ID space.
3841ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        // Since the entries are sorted by ID, the last one will be the biggest.
3851ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        const size_t numEntries = sortedEntries->back()->id.value() + 1;
3861ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3871ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        specHeader->entryCount = util::hostToDevice32(numEntries);
3881ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        // Reserve space for the masks of each resource in this type. These
3901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        // show for which configuration axis the resource changes.
3911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        uint32_t* configMasks = typeSpecWriter.nextBlock<uint32_t>(numEntries);
3921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        const size_t actualNumEntries = sortedEntries->size();
3941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        for (size_t entryIndex = 0; entryIndex < actualNumEntries; entryIndex++) {
3951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            ResourceEntry* entry = sortedEntries->at(entryIndex);
3961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            // Populate the config masks for this entry.
3981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
3999e10ac70155c993e7053323ad36beaea7bf7d54fAdam Lesinski            if (entry->symbolStatus.state == SymbolState::kPublic) {
4001ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                configMasks[entry->id.value()] |=
4011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                        util::hostToDevice32(ResTable_typeSpec::SPEC_PUBLIC);
4021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            }
4031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
4041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            const size_t configCount = entry->values.size();
4051ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            for (size_t i = 0; i < configCount; i++) {
406e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski                const ConfigDescription& config = entry->values[i]->config;
4071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                for (size_t j = i + 1; j < configCount; j++) {
4081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                    configMasks[entry->id.value()] |= util::hostToDevice32(
409e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski                            config.diff(entry->values[j]->config));
4101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                }
4111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            }
4121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
4131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        typeSpecWriter.finish();
4141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        return true;
4151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
4161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
4171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    bool flattenTypes(BigBuffer* buffer) {
4181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        // Sort the types by their IDs. They will be inserted into the StringPool in this order.
4191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        std::vector<ResourceTableType*> sortedTypes = collectAndSortTypes();
4201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
4211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        size_t expectedTypeId = 1;
4221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        for (ResourceTableType* type : sortedTypes) {
4231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            // If there is a gap in the type IDs, fill in the StringPool
4241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            // with empty values until we reach the ID we expect.
4251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            while (type->id.value() > expectedTypeId) {
4261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                std::u16string typeName(u"?");
4271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                typeName += expectedTypeId;
4281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                mTypePool.makeRef(typeName);
4291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                expectedTypeId++;
4301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            }
4311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            expectedTypeId++;
4321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            mTypePool.makeRef(toString(type->type));
4331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
4341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            std::vector<ResourceEntry*> sortedEntries = collectAndSortEntries(type);
4351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
4361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            if (!flattenTypeSpec(type, &sortedEntries, buffer)) {
4371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                return false;
4381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            }
4391ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
4401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            // The binary resource table lists resource entries for each configuration.
4411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            // We store them inverted, where a resource entry lists the values for each
4421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            // configuration available. Here we reverse this to match the binary table.
4431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            std::map<ConfigDescription, std::vector<FlatEntry>> configToEntryListMap;
4441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            for (ResourceEntry* entry : sortedEntries) {
445e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski                const uint32_t keyIndex = (uint32_t) mKeyPool.makeRef(entry->name).getIndex();
4461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
4471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                // Group values by configuration.
4481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                for (auto& configValue : entry->values) {
449e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski                    configToEntryListMap[configValue->config].push_back(FlatEntry{
450e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski                            entry, configValue->value.get(), keyIndex });
4511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                }
4521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            }
4531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
4541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            // Flatten a configuration value.
4551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            for (auto& entry : configToEntryListMap) {
4561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                if (!flattenConfig(type, entry.first, &entry.second, buffer)) {
4571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                    return false;
4581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                }
4591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            }
4601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
4611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        return true;
4621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
4639ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski};
4641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
4659ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski} // namespace
4661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
4679ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinskibool TableFlattener::consume(IAaptContext* context, ResourceTable* table) {
4689ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    // We must do this before writing the resources, since the string pool IDs may change.
4699ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    table->stringPool.sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
4709ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        int diff = a.context.priority - b.context.priority;
4719ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        if (diff < 0) return true;
4729ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        if (diff > 0) return false;
4739ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        diff = a.context.config.compare(b.context.config);
4749ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        if (diff < 0) return true;
4759ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        if (diff > 0) return false;
4769ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        return a.value < b.value;
4779ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    });
4789ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    table->stringPool.prune();
4799ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski
4809ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    // Write the ResTable header.
4819ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    ChunkWriter tableWriter(mBuffer);
4829ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    ResTable_header* tableHeader = tableWriter.startChunk<ResTable_header>(RES_TABLE_TYPE);
4839ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    tableHeader->packageCount = util::hostToDevice32(table->packages.size());
4849ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski
4859ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    // Flatten the values string pool.
4869ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    StringPool::flattenUtf8(tableWriter.getBuffer(), table->stringPool);
4879ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski
4889ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    BigBuffer packageBuffer(1024);
4899ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski
4909ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    // Flatten each package.
4919ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    for (auto& package : table->packages) {
49259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        PackageFlattener flattener(context->getDiagnostics(), package.get());
4939ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski        if (!flattener.flattenPackage(&packageBuffer)) {
4941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            return false;
4951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
4969ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    }
4971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
4989ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    // Finally merge all the packages into the main buffer.
4999ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    tableWriter.getBuffer()->appendBuffer(std::move(packageBuffer));
5009ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    tableWriter.finish();
5019ba47d813075fcb05c5e1532c137c93b394631cbAdam Lesinski    return true;
5021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}
5031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
5041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} // namespace aapt
505