Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 86edf366 authored by Pierre Lecesne's avatar Pierre Lecesne Committed by Android (Google) Code Review
Browse files

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

parents 4f7413ea f267a404
Loading
Loading
Loading
Loading
+46 −6
Original line number Original line Diff line number Diff line
@@ -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) {
@@ -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
+8 −0
Original line number Original line Diff line number Diff line
@@ -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:
@@ -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