159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski/*
259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * Copyright (C) 2016 The Android Open Source Project
359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski *
459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * you may not use this file except in compliance with the License.
659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * You may obtain a copy of the License at
759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski *
859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski *
1059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * Unless required by applicable law or agreed to in writing, software
1159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
1259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * See the License for the specific language governing permissions and
1459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * limitations under the License.
1559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski */
1659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
1759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "Debug.h"
1859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "Diagnostics.h"
1959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "Flags.h"
2064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski#include "io/ZipArchive.h"
2159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "process/IResourceTableConsumer.h"
2259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "proto/ProtoSerialize.h"
2359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "util/Files.h"
2459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "util/StringPiece.h"
2559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
2659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include <vector>
2759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
2859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskinamespace aapt {
2959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
3059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski//struct DumpOptions {
3159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski//
3259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski//};
3359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
3459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskivoid dumpCompiledFile(const pb::CompiledFile& pbFile, const void* data, size_t len,
3559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski                      const Source& source, IAaptContext* context) {
3659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    std::unique_ptr<ResourceFile> file = deserializeCompiledFileFromPb(pbFile, source,
3759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski                                                                       context->getDiagnostics());
3859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    if (!file) {
3959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        return;
4059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
4159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
4259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    std::cout << "Resource: " << file->name << "\n"
4359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski              << "Config:   " << file->config << "\n"
4459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski              << "Source:   " << file->source << "\n";
4559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski}
4659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
4759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskivoid dumpCompiledTable(const pb::ResourceTable& pbTable, const Source& source,
4859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski                       IAaptContext* context) {
4959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    std::unique_ptr<ResourceTable> table = deserializeTableFromPb(pbTable, source,
5059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski                                                                  context->getDiagnostics());
5159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    if (!table) {
5259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        return;
5359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
5459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
5559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    Debug::printTable(table.get());
5659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski}
5759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
5859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskivoid tryDumpFile(IAaptContext* context, const std::string& filePath) {
5959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    std::string err;
6064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski    std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::create(filePath, &err);
6164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski    if (zip) {
6264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski        io::IFile* file = zip->findFile("resources.arsc.flat");
6364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski        if (file) {
6464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski            std::unique_ptr<io::IData> data = file->openAsData();
6564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski            if (!data) {
6664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski                context->getDiagnostics()->error(DiagMessage(filePath)
6764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski                                                 << "failed to open resources.arsc.flat");
6864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski                return;
6964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski            }
7064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
7164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski            pb::ResourceTable pbTable;
7264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski            if (!pbTable.ParseFromArray(data->data(), data->size())) {
7364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski                context->getDiagnostics()->error(DiagMessage(filePath)
7464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski                                                 << "invalid resources.arsc.flat");
7564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski                return;
7664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski            }
7764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
7864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski            std::unique_ptr<ResourceTable> table = deserializeTableFromPb(
7964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski                    pbTable, Source(filePath), context->getDiagnostics());
8064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski            if (table) {
8164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski                DebugPrintTableOptions debugPrintTableOptions;
8264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski                debugPrintTableOptions.showSources = true;
8364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski                Debug::printTable(table.get(), debugPrintTableOptions);
8464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski            }
8564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski        }
8664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski        return;
8764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski    }
8864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
8959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    Maybe<android::FileMap> file = file::mmapPath(filePath, &err);
9059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    if (!file) {
9159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        context->getDiagnostics()->error(DiagMessage(filePath) << err);
9259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        return;
9359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
9459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
9559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    android::FileMap* fileMap = &file.value();
9659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
9759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    // Try as a compiled table.
9859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    pb::ResourceTable pbTable;
9959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    if (pbTable.ParseFromArray(fileMap->getDataPtr(), fileMap->getDataLength())) {
10059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        dumpCompiledTable(pbTable, Source(filePath), context);
10159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        return;
10259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
10359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
10459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    // Try as a compiled file.
10559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    CompiledFileInputStream input(fileMap->getDataPtr(), fileMap->getDataLength());
10659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    if (const pb::CompiledFile* pbFile = input.CompiledFile()) {
10759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski       dumpCompiledFile(*pbFile, input.data(), input.size(), Source(filePath), context);
10859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski       return;
10959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
11059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski}
11159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
11259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskiclass DumpContext : public IAaptContext {
11359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskipublic:
11459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    IDiagnostics* getDiagnostics() override {
11559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        return &mDiagnostics;
11659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
11759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
11859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    NameMangler* getNameMangler() override {
11959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        abort();
12059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        return nullptr;
12159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
12259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
12364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski    const std::u16string& getCompilationPackage() override {
12464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski        static std::u16string empty;
12564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski        return empty;
12659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
12759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
12859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    uint8_t getPackageId() override {
12959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        return 0;
13059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
13159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
13264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski    SymbolTable* getExternalSymbols() override {
13359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        abort();
13459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        return nullptr;
13559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
13659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
137355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    bool verbose() override {
138355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski        return mVerbose;
139355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    }
140355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
141355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    void setVerbose(bool val) {
142355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski        mVerbose = val;
143355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    }
144355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
14559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskiprivate:
14659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    StdErrDiagnostics mDiagnostics;
147355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    bool mVerbose = false;
14859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski};
14959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
15059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski/**
15159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * Entry point for dump command.
15259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski */
15359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskiint dump(const std::vector<StringPiece>& args) {
154355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    bool verbose = false;
155355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    Flags flags = Flags()
156355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski            .optionalSwitch("-v", "increase verbosity of output", &verbose);
15759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    if (!flags.parse("aapt2 dump", args, &std::cerr)) {
15859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        return 1;
15959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
16059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
16159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    DumpContext context;
162355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski    context.setVerbose(verbose);
16359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
16459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    for (const std::string& arg : flags.getArgs()) {
16559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski        tryDumpFile(&context, arg);
16659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
16759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    return 0;
16859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski}
16959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
17059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski} // namespace aapt
171