diff options
Diffstat (limited to 'tools/aapt2/LoadedApk.cpp')
-rw-r--r-- | tools/aapt2/LoadedApk.cpp | 118 |
1 files changed, 81 insertions, 37 deletions
diff --git a/tools/aapt2/LoadedApk.cpp b/tools/aapt2/LoadedApk.cpp index 1dd46ba813db..b353ff00a23f 100644 --- a/tools/aapt2/LoadedApk.cpp +++ b/tools/aapt2/LoadedApk.cpp @@ -35,6 +35,43 @@ using ::std::unique_ptr; namespace aapt { +static ApkFormat DetermineApkFormat(io::IFileCollection* apk) { + if (apk->FindFile(kApkResourceTablePath) != nullptr) { + return ApkFormat::kBinary; + } else if (apk->FindFile(kProtoResourceTablePath) != nullptr) { + return ApkFormat::kProto; + } else { + // If the resource table is not present, attempt to read the manifest. + io::IFile* manifest_file = apk->FindFile(kAndroidManifestPath); + if (manifest_file == nullptr) { + return ApkFormat::kUnknown; + } + + // First try in proto format. + std::unique_ptr<io::InputStream> manifest_in = manifest_file->OpenInputStream(); + if (manifest_in != nullptr) { + pb::XmlNode pb_node; + io::ProtoInputStreamReader proto_reader(manifest_in.get()); + if (proto_reader.ReadMessage(&pb_node)) { + return ApkFormat::kProto; + } + } + + // If it didn't work, try in binary format. + std::unique_ptr<io::IData> manifest_data = manifest_file->OpenAsData(); + if (manifest_data != nullptr) { + std::string error; + std::unique_ptr<xml::XmlResource> manifest = + xml::Inflate(manifest_data->data(), manifest_data->size(), &error); + if (manifest != nullptr) { + return ApkFormat::kBinary; + } + } + + return ApkFormat::kUnknown; + } +} + std::unique_ptr<LoadedApk> LoadedApk::LoadApkFromPath(const StringPiece& path, IDiagnostics* diag) { Source source(path); std::string error; @@ -69,14 +106,14 @@ std::unique_ptr<LoadedApk> LoadedApk::LoadProtoApkFromFileCollection( return {}; } - io::ZeroCopyInputAdaptor adaptor(in.get()); - if (!pb_table.ParseFromZeroCopyStream(&adaptor)) { + io::ProtoInputStreamReader proto_reader(in.get()); + if (!proto_reader.ReadMessage(&pb_table)) { diag->Error(DiagMessage(source) << "failed to read " << kProtoResourceTablePath); return {}; } std::string error; - table = util::make_unique<ResourceTable>(); + table = util::make_unique<ResourceTable>(/** validate_resources **/ false); if (!DeserializeTableFromPb(pb_table, collection.get(), table.get(), &error)) { diag->Error(DiagMessage(source) << "failed to deserialize " << kProtoResourceTablePath << ": " << error); @@ -97,8 +134,8 @@ std::unique_ptr<LoadedApk> LoadedApk::LoadProtoApkFromFileCollection( } pb::XmlNode pb_node; - io::ZeroCopyInputAdaptor manifest_adaptor(manifest_in.get()); - if (!pb_node.ParseFromZeroCopyStream(&manifest_adaptor)) { + io::ProtoInputStreamReader proto_reader(manifest_in.get()); + if (!proto_reader.ReadMessage(&pb_node)) { diag->Error(DiagMessage(source) << "failed to read proto " << kAndroidManifestPath); return {}; } @@ -120,7 +157,7 @@ std::unique_ptr<LoadedApk> LoadedApk::LoadBinaryApkFromFileCollection( io::IFile* table_file = collection->FindFile(kApkResourceTablePath); if (table_file != nullptr) { - table = util::make_unique<ResourceTable>(); + table = util::make_unique<ResourceTable>(/** validate_resources **/ false); std::unique_ptr<io::IData> data = table_file->OpenAsData(); if (data == nullptr) { diag->Error(DiagMessage(source) << "failed to open " << kApkResourceTablePath); @@ -184,10 +221,7 @@ bool LoadedApk::WriteToArchive(IAaptContext* context, ResourceTable* split_table std::unique_ptr<io::IFileCollectionIterator> iterator = apk_->Iterator(); while (iterator->HasNext()) { io::IFile* file = iterator->Next(); - std::string path = file->GetSource().path; - // The name of the path has the format "<zip-file-name>@<path-to-file>". - path = path.substr(path.find('@') + 1); // Skip resources that are not referenced if requested. if (path.find("res/") == 0 && referenced_resources.find(path) == referenced_resources.end()) { @@ -257,41 +291,51 @@ bool LoadedApk::WriteToArchive(IAaptContext* context, ResourceTable* split_table return true; } -ApkFormat LoadedApk::DetermineApkFormat(io::IFileCollection* apk) { - if (apk->FindFile(kApkResourceTablePath) != nullptr) { - return ApkFormat::kBinary; - } else if (apk->FindFile(kProtoResourceTablePath) != nullptr) { - return ApkFormat::kProto; - } else { - // If the resource table is not present, attempt to read the manifest. - io::IFile* manifest_file = apk->FindFile(kAndroidManifestPath); - if (manifest_file == nullptr) { - return ApkFormat::kUnknown; +std::unique_ptr<xml::XmlResource> LoadedApk::LoadXml(const std::string& file_path, + IDiagnostics* diag) const { + io::IFile* file = apk_->FindFile(file_path); + if (file == nullptr) { + diag->Error(DiagMessage() << "failed to find file"); + return nullptr; + } + + std::unique_ptr<xml::XmlResource> doc; + if (format_ == ApkFormat::kProto) { + std::unique_ptr<io::InputStream> in = file->OpenInputStream(); + if (!in) { + diag->Error(DiagMessage() << "failed to open file"); + return nullptr; } - // First try in proto format. - std::unique_ptr<io::InputStream> manifest_in = manifest_file->OpenInputStream(); - if (manifest_in != nullptr) { - pb::XmlNode pb_node; - io::ZeroCopyInputAdaptor manifest_adaptor(manifest_in.get()); - if (pb_node.ParseFromZeroCopyStream(&manifest_adaptor)) { - return ApkFormat::kProto; - } + pb::XmlNode pb_node; + io::ProtoInputStreamReader proto_reader(in.get()); + if (!proto_reader.ReadMessage(&pb_node)) { + diag->Error(DiagMessage() << "failed to parse file as proto XML"); + return nullptr; } - // If it didn't work, try in binary format. - std::unique_ptr<io::IData> manifest_data = manifest_file->OpenAsData(); - if (manifest_data != nullptr) { - std::string error; - std::unique_ptr<xml::XmlResource> manifest = - xml::Inflate(manifest_data->data(), manifest_data->size(), &error); - if (manifest != nullptr) { - return ApkFormat::kBinary; - } + std::string err; + doc = DeserializeXmlResourceFromPb(pb_node, &err); + if (!doc) { + diag->Error(DiagMessage() << "failed to deserialize proto XML: " << err); + return nullptr; + } + } else if (format_ == ApkFormat::kBinary) { + std::unique_ptr<io::IData> data = file->OpenAsData(); + if (!data) { + diag->Error(DiagMessage() << "failed to open file"); + return nullptr; } - return ApkFormat::kUnknown; + std::string err; + doc = xml::Inflate(data->data(), data->size(), &err); + if (!doc) { + diag->Error(DiagMessage() << "failed to parse file as binary XML: " << err); + return nullptr; + } } + + return doc; } } // namespace aapt |