Merge "AAPT2: Use manifest parsing to determine format of APK."

This commit is contained in:
Pierre Lecesne
2017-12-01 21:53:37 +00:00
committed by Android (Google) Code Review
2 changed files with 54 additions and 6 deletions

View File

@@ -43,13 +43,16 @@ std::unique_ptr<LoadedApk> LoadedApk::LoadApkFromPath(const StringPiece& path, I
return {};
}
if (apk->FindFile("resources.arsc") != nullptr) {
return LoadBinaryApkFromFileCollection(source, std::move(apk), diag);
} else if (apk->FindFile("resources.pb") != nullptr) {
return LoadProtoApkFromFileCollection(source, std::move(apk), diag);
ApkFormat apkFormat = DetermineApkFormat(apk.get());
switch (apkFormat) {
case ApkFormat::kBinary:
return LoadBinaryApkFromFileCollection(source, std::move(apk), diag);
case ApkFormat::kProto:
return LoadProtoApkFromFileCollection(source, std::move(apk), diag);
default:
diag->Error(DiagMessage(path) << "could not identify format of APK");
return {};
}
diag->Error(DiagMessage(path) << "no resource table found");
return {};
}
std::unique_ptr<LoadedApk> LoadedApk::LoadProtoApkFromFileCollection(
@@ -243,4 +246,41 @@ bool LoadedApk::WriteToArchive(IAaptContext* context, ResourceTable* split_table
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

View File

@@ -33,6 +33,12 @@ constexpr static const char kApkResourceTablePath[] = "resources.arsc";
constexpr static const char kProtoResourceTablePath[] = "resources.pb";
constexpr static const char kAndroidManifestPath[] = "AndroidManifest.xml";
enum ApkFormat {
kUnknown,
kBinary,
kProto,
};
// Info about an APK loaded in memory.
class LoadedApk {
public:
@@ -104,6 +110,8 @@ class LoadedApk {
std::unique_ptr<io::IFileCollection> apk_;
std::unique_ptr<ResourceTable> table_;
std::unique_ptr<xml::XmlResource> manifest_;
static ApkFormat DetermineApkFormat(io::IFileCollection* apk);
};
} // namespace aapt