/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "AppInfo.h" #include "BigBuffer.h" #include "BinaryResourceParser.h" #include "BinaryXmlPullParser.h" #include "BindingXmlPullParser.h" #include "Files.h" #include "Flag.h" #include "JavaClassGenerator.h" #include "Linker.h" #include "ManifestParser.h" #include "ManifestValidator.h" #include "Png.h" #include "ResourceParser.h" #include "ResourceTable.h" #include "ResourceValues.h" #include "SdkConstants.h" #include "SourceXmlPullParser.h" #include "StringPiece.h" #include "TableFlattener.h" #include "Util.h" #include "XmlFlattener.h" #include "ZipFile.h" #include #include #include #include #include #include #include #include #include #include #include constexpr const char* kAaptVersionStr = "2.0-alpha"; using namespace aapt; void printTable(const ResourceTable& table) { std::cout << "ResourceTable package=" << table.getPackage(); if (table.getPackageId() != ResourceTable::kUnsetPackageId) { std::cout << " id=" << std::hex << table.getPackageId() << std::dec; } std::cout << std::endl << "---------------------------------------------------------" << std::endl; for (const auto& type : table) { std::cout << "Type " << type->type; if (type->typeId != ResourceTableType::kUnsetTypeId) { std::cout << " [" << type->typeId << "]"; } std::cout << " (" << type->entries.size() << " entries)" << std::endl; for (const auto& entry : type->entries) { std::cout << " " << entry->name; if (entry->entryId != ResourceEntry::kUnsetEntryId) { std::cout << " [" << entry->entryId << "]"; } std::cout << " (" << entry->values.size() << " configurations)"; if (entry->publicStatus.isPublic) { std::cout << " PUBLIC"; } std::cout << std::endl; for (const auto& value : entry->values) { std::cout << " " << value.config << " (" << value.source << ") : "; value.value->print(std::cout); std::cout << std::endl; } } } } void printStringPool(const StringPool& pool) { std::cout << "String pool of length " << pool.size() << std::endl << "---------------------------------------------------------" << std::endl; size_t i = 0; for (const auto& entry : pool) { std::cout << "[" << i << "]: " << entry->value << " (Priority " << entry->context.priority << ", Config '" << entry->context.config << "')" << std::endl; i++; } } /** * Collect files from 'root', filtering out any files that do not * match the FileFilter 'filter'. */ bool walkTree(const Source& root, const FileFilter& filter, std::vector* outEntries) { bool error = false; for (const std::string& dirName : listFiles(root.path)) { std::string dir = root.path; appendPath(&dir, dirName); FileType ft = getFileType(dir); if (!filter(dirName, ft)) { continue; } if (ft != FileType::kDirectory) { continue; } for (const std::string& fileName : listFiles(dir)) { std::string file(dir); appendPath(&file, fileName); FileType ft = getFileType(file); if (!filter(fileName, ft)) { continue; } if (ft != FileType::kRegular) { Logger::error(Source{ file }) << "not a regular file." << std::endl; error = true; continue; } outEntries->push_back(Source{ file }); } } return !error; } bool loadResTable(android::ResTable* table, const Source& source) { std::ifstream ifs(source.path, std::ifstream::in | std::ifstream::binary); if (!ifs) { Logger::error(source) << strerror(errno) << std::endl; return false; } std::streampos fsize = ifs.tellg(); ifs.seekg(0, std::ios::end); fsize = ifs.tellg() - fsize; ifs.seekg(0, std::ios::beg); assert(fsize >= 0); size_t dataSize = static_cast(fsize); char* buf = new char[dataSize]; ifs.read(buf, dataSize); bool result = table->add(buf, dataSize, -1, true) == android::NO_ERROR; delete [] buf; return result; } void versionStylesForCompat(const std::shared_ptr& table) { for (auto& type : *table) { if (type->type != ResourceType::kStyle) { continue; } for (auto& entry : type->entries) { // Add the versioned styles we want to create // here. They are added to the table after // iterating over the original set of styles. // // A stack is used since auto-generated styles // from later versions should override // auto-generated styles from earlier versions. // Iterating over the styles is done in order, // so we will always visit sdkVersions from smallest // to largest. std::stack addStack; for (ResourceConfigValue& configValue : entry->values) { visitFunc