Loading tools/aapt2/LoadedApk.cpp +46 −6 Original line number Original line Diff line number Diff line Loading @@ -43,14 +43,17 @@ std::unique_ptr<LoadedApk> LoadedApk::LoadApkFromPath(const StringPiece& path, I return {}; return {}; } } if (apk->FindFile("resources.arsc") != nullptr) { ApkFormat apkFormat = DetermineApkFormat(apk.get()); switch (apkFormat) { case ApkFormat::kBinary: return LoadBinaryApkFromFileCollection(source, std::move(apk), diag); return LoadBinaryApkFromFileCollection(source, std::move(apk), diag); } else if (apk->FindFile("resources.pb") != nullptr) { case ApkFormat::kProto: return LoadProtoApkFromFileCollection(source, std::move(apk), diag); return LoadProtoApkFromFileCollection(source, std::move(apk), diag); } default: diag->Error(DiagMessage(path) << "no resource table found"); diag->Error(DiagMessage(path) << "could not identify format of APK"); return {}; return {}; } } } std::unique_ptr<LoadedApk> LoadedApk::LoadProtoApkFromFileCollection( std::unique_ptr<LoadedApk> LoadedApk::LoadProtoApkFromFileCollection( const Source& source, unique_ptr<io::IFileCollection> collection, IDiagnostics* diag) { const Source& source, unique_ptr<io::IFileCollection> collection, IDiagnostics* diag) { Loading Loading @@ -243,4 +246,41 @@ bool LoadedApk::WriteToArchive(IAaptContext* context, ResourceTable* split_table return true; return true; } } ApkFormat LoadedApk::DetermineApkFormat(io::IFileCollection* apk) { if (apk->FindFile("resources.arsc") != nullptr) { return ApkFormat::kBinary; } else if (apk->FindFile("resources.pb") != 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::ZeroCopyInputAdaptor manifest_adaptor(manifest_in.get()); if (pb_node.ParseFromZeroCopyStream(&manifest_adaptor)) { 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; } } } // namespace aapt } // namespace aapt tools/aapt2/LoadedApk.h +8 −0 Original line number Original line Diff line number Diff line Loading @@ -33,6 +33,12 @@ constexpr static const char kApkResourceTablePath[] = "resources.arsc"; constexpr static const char kProtoResourceTablePath[] = "resources.pb"; constexpr static const char kProtoResourceTablePath[] = "resources.pb"; constexpr static const char kAndroidManifestPath[] = "AndroidManifest.xml"; constexpr static const char kAndroidManifestPath[] = "AndroidManifest.xml"; enum ApkFormat { kUnknown, kBinary, kProto, }; // Info about an APK loaded in memory. // Info about an APK loaded in memory. class LoadedApk { class LoadedApk { public: public: Loading Loading @@ -104,6 +110,8 @@ class LoadedApk { std::unique_ptr<io::IFileCollection> apk_; std::unique_ptr<io::IFileCollection> apk_; std::unique_ptr<ResourceTable> table_; std::unique_ptr<ResourceTable> table_; std::unique_ptr<xml::XmlResource> manifest_; std::unique_ptr<xml::XmlResource> manifest_; static ApkFormat DetermineApkFormat(io::IFileCollection* apk); }; }; } // namespace aapt } // namespace aapt Loading Loading
tools/aapt2/LoadedApk.cpp +46 −6 Original line number Original line Diff line number Diff line Loading @@ -43,14 +43,17 @@ std::unique_ptr<LoadedApk> LoadedApk::LoadApkFromPath(const StringPiece& path, I return {}; return {}; } } if (apk->FindFile("resources.arsc") != nullptr) { ApkFormat apkFormat = DetermineApkFormat(apk.get()); switch (apkFormat) { case ApkFormat::kBinary: return LoadBinaryApkFromFileCollection(source, std::move(apk), diag); return LoadBinaryApkFromFileCollection(source, std::move(apk), diag); } else if (apk->FindFile("resources.pb") != nullptr) { case ApkFormat::kProto: return LoadProtoApkFromFileCollection(source, std::move(apk), diag); return LoadProtoApkFromFileCollection(source, std::move(apk), diag); } default: diag->Error(DiagMessage(path) << "no resource table found"); diag->Error(DiagMessage(path) << "could not identify format of APK"); return {}; return {}; } } } std::unique_ptr<LoadedApk> LoadedApk::LoadProtoApkFromFileCollection( std::unique_ptr<LoadedApk> LoadedApk::LoadProtoApkFromFileCollection( const Source& source, unique_ptr<io::IFileCollection> collection, IDiagnostics* diag) { const Source& source, unique_ptr<io::IFileCollection> collection, IDiagnostics* diag) { Loading Loading @@ -243,4 +246,41 @@ bool LoadedApk::WriteToArchive(IAaptContext* context, ResourceTable* split_table return true; return true; } } ApkFormat LoadedApk::DetermineApkFormat(io::IFileCollection* apk) { if (apk->FindFile("resources.arsc") != nullptr) { return ApkFormat::kBinary; } else if (apk->FindFile("resources.pb") != 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::ZeroCopyInputAdaptor manifest_adaptor(manifest_in.get()); if (pb_node.ParseFromZeroCopyStream(&manifest_adaptor)) { 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; } } } // namespace aapt } // namespace aapt
tools/aapt2/LoadedApk.h +8 −0 Original line number Original line Diff line number Diff line Loading @@ -33,6 +33,12 @@ constexpr static const char kApkResourceTablePath[] = "resources.arsc"; constexpr static const char kProtoResourceTablePath[] = "resources.pb"; constexpr static const char kProtoResourceTablePath[] = "resources.pb"; constexpr static const char kAndroidManifestPath[] = "AndroidManifest.xml"; constexpr static const char kAndroidManifestPath[] = "AndroidManifest.xml"; enum ApkFormat { kUnknown, kBinary, kProto, }; // Info about an APK loaded in memory. // Info about an APK loaded in memory. class LoadedApk { class LoadedApk { public: public: Loading Loading @@ -104,6 +110,8 @@ class LoadedApk { std::unique_ptr<io::IFileCollection> apk_; std::unique_ptr<io::IFileCollection> apk_; std::unique_ptr<ResourceTable> table_; std::unique_ptr<ResourceTable> table_; std::unique_ptr<xml::XmlResource> manifest_; std::unique_ptr<xml::XmlResource> manifest_; static ApkFormat DetermineApkFormat(io::IFileCollection* apk); }; }; } // namespace aapt } // namespace aapt Loading