Merge "AAPT2: Use manifest parsing to determine format of APK."
This commit is contained in:
committed by
Android (Google) Code Review
commit
86edf36625
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user