Use ApexManifest proto object in apexd instead of ApexManifest class.

Validation and converting to proto object. Simpler to maintain one common schema for apexd and apexer, instead of maintaining 2 classes in apexd and apexer.

Bug: 116129963

Test: mmma system/apex
      out/host/linux-x86/testcases/apex_manifest_test/x86/apex_manifest_test

Change-Id: Iff48e770ea5b8f520a801f1ef50be8a4752516f5
diff --git a/apexd/Android.bp b/apexd/Android.bp
index a090e4b..05e6c10 100644
--- a/apexd/Android.bp
+++ b/apexd/Android.bp
@@ -3,6 +3,8 @@
   cflags: [
     "-Wall",
     "-Wextra",
+    "-Werror",
+    "-Wno-unused-parameter",
 
     // Some extra flags.
     "-fstrict-aliasing",
@@ -22,8 +24,13 @@
     "libjsoncpp",
     "libprotobuf-cpp-full",
     "libziparchive",
+    // Required full for parsing json string to message
+    "libprotobuf-cpp-full",
   ],
-  static_libs: ["lib_apex_session_state_proto"],
+  static_libs: [
+    "lib_apex_session_state_proto",
+    "lib_apex_manifest_proto"
+  ],
 }
 
 aidl_interface {
diff --git a/apexd/apex_file.cpp b/apexd/apex_file.cpp
index 8111ea8..4b2518d 100644
--- a/apexd/apex_file.cpp
+++ b/apexd/apex_file.cpp
@@ -153,7 +153,7 @@
     }
   }
 
-  StatusOr<ApexManifest> manifest = ApexManifest::Parse(manifest_content);
+  StatusOr<ApexManifest> manifest = ParseManifest(manifest_content);
   if (!manifest.Ok()) {
     return StatusOr<ApexFile>::MakeError(manifest.ErrorMessage());
   }
@@ -286,10 +286,10 @@
                     << apex.GetPath());
   }
 
-  if (keyName != apex.GetManifest().GetName()) {
+  if (keyName != apex.GetManifest().name()) {
     return StatusOr<std::string>::MakeError(
         StringLog() << "Key mismatch: apex name is '"
-                    << apex.GetManifest().GetName() << "'"
+                    << apex.GetManifest().name() << "'"
                     << " but key name is '" << keyName << "'");
   }
 
diff --git a/apexd/apex_file_test.cpp b/apexd/apex_file_test.cpp
index e90dc3b..58afd27 100644
--- a/apexd/apex_file_test.cpp
+++ b/apexd/apex_file_test.cpp
@@ -72,8 +72,8 @@
   const std::string filePath = testDataDir + "apex.apexd_test.apex";
   StatusOr<ApexFile> apexFile = ApexFile::Open(filePath);
   ASSERT_TRUE(apexFile.Ok());
-  EXPECT_EQ("com.android.apex.test_package", apexFile->GetManifest().GetName());
-  EXPECT_EQ(1UL, apexFile->GetManifest().GetVersion());
+  EXPECT_EQ("com.android.apex.test_package", apexFile->GetManifest().name());
+  EXPECT_EQ(1u, apexFile->GetManifest().version());
 }
 
 TEST(ApexFileTest, VerifyApexVerity) {
diff --git a/apexd/apex_manifest.cpp b/apexd/apex_manifest.cpp
index fd6525f..ae2dfa4 100644
--- a/apexd/apex_manifest.cpp
+++ b/apexd/apex_manifest.cpp
@@ -16,81 +16,82 @@
 
 #include "apex_manifest.h"
 #include "string_log.h"
-
 #include <android-base/logging.h>
-#include <json/reader.h>
-#include <json/value.h>
+
+#include <google/protobuf/util/json_util.h>
+#include <google/protobuf/util/type_resolver_util.h>
 #include <memory>
 #include <string>
 
+using google::protobuf::DescriptorPool;
+using google::protobuf::scoped_ptr;
+using google::protobuf::util::NewTypeResolverForDescriptorPool;
+using google::protobuf::util::TypeResolver;
+
 namespace android {
 namespace apex {
+namespace {
+const char kTypeUrlPrefix[] = "type.googleapis.com";
 
-StatusOr<ApexManifest> ApexManifest::Parse(const std::string& content) {
-  constexpr const char* kNameTag = "name";
-  constexpr const char* kVersionTag = "version";
-  constexpr const char* kPreInstallTag = "preInstallHook";
-  constexpr const char* kPostInstallTag = "postInstallHook";
+std::string GetTypeUrl(const ApexManifest& apex_manifest) {
+  const google::protobuf::Descriptor* message = apex_manifest.GetDescriptor();
+  return std::string(kTypeUrlPrefix) + "/" + message->full_name();
+}
 
-  std::string name;
-  std::string preInstallHook;
-  std::string postInstallHook;
-  uint64_t version;
-
-  Json::Value root;
-  Json::Reader reader;
-  if (!reader.parse(content, root)) {
-    std::string err = StringLog()
-                      << "Failed to parse APEX Manifest JSON config: "
-                      << reader.getFormattedErrorMessages();
-    return StatusOr<ApexManifest>::MakeError(err);
+// TODO: JsonStringToMessage is a newly added function in protobuf
+// and is not yet available in the android tree. Replace this function with
+// https://developers.google.com/protocol-buffers/docs/reference/cpp/
+// google.protobuf.util.json_util#JsonStringToMessage.details
+// as and when the android tree gets updated
+StatusOr<ApexManifest> JsonToApexManifestMessage(const std::string& content,
+                                                 ApexManifest& apex_manifest) {
+  scoped_ptr<TypeResolver> resolver(NewTypeResolverForDescriptorPool(
+      kTypeUrlPrefix, DescriptorPool::generated_pool()));
+  std::string binary;
+  auto parse_status = JsonToBinaryString(
+      resolver.get(), GetTypeUrl(apex_manifest), content, &binary);
+  if (!parse_status.ok()) {
+    return StatusOr<ApexManifest>::MakeError(
+        StringLog() << "Failed to parse APEX Manifest JSON config: "
+                    << parse_status.error_message().as_string());
   }
 
-  std::string err_str;
-  auto read_string_field = [&](const char* tag, bool req, std::string* field) {
-    if (!root.isMember(tag)) {
-      if (req) {
-        err_str = StringLog() << "Missing required field \"" << tag
-                              << "\" from APEX manifest.";
-        return false;
-      }
-      return true;
-    }
+  if (!apex_manifest.ParseFromString(binary)) {
+    return StatusOr<ApexManifest>::MakeError(
+        StringLog() << "Unexpected fields in APEX Manifest JSON config");
+  }
+  return StatusOr<ApexManifest>(apex_manifest);
+}
 
-    *field = root[tag].asString();
-    return true;
-  };
+}  // namespace
 
+StatusOr<ApexManifest> ParseManifest(const std::string& content) {
+  ApexManifest apex_manifest;
+  std::string err;
+  StatusOr<ApexManifest> parse_manifest_status =
+      JsonToApexManifestMessage(content, apex_manifest);
+  if (!parse_manifest_status.Ok()) {
+    return parse_manifest_status;
+  }
+
+  // Verifying required fields.
   // name
-  if (!read_string_field(kNameTag, /*req=*/true, &name)) {
-    return StatusOr<ApexManifest>::MakeError(err_str);
+  if (apex_manifest.name().empty()) {
+    err = StringLog() << "Missing required field \"name\" from APEX manifest.";
+    return StatusOr<ApexManifest>::MakeError(err);
   }
 
   // version
-  if (!root.isMember(kVersionTag)) {
-    std::string err = StringLog() << "Missing required field \"" << kVersionTag
-                                  << "\" from APEX manifest.";
+  if (apex_manifest.version() == 0) {
+    err =
+        StringLog() << "Missing required field \"version\" from APEX manifest.";
     return StatusOr<ApexManifest>::MakeError(err);
   }
-  Json::Value jVersion = root[kVersionTag];
-  if (!jVersion.isUInt64()) {
-    std::string err = StringLog()
-                      << "Invalid type for field \"" << kVersionTag
-                      << "\" from APEX manifest, expecting integer.";
-    return StatusOr<ApexManifest>::MakeError(err);
-  }
-  version = jVersion.asUInt64();
+  return parse_manifest_status;
+}
 
-  // [pre|post]InstallHook
-  if (!read_string_field(kPreInstallTag, /*req=*/false, &preInstallHook)) {
-    return StatusOr<ApexManifest>::MakeError(err_str);
-  }
-  if (!read_string_field(kPostInstallTag, /*req=*/false, &postInstallHook)) {
-    return StatusOr<ApexManifest>::MakeError(err_str);
-  }
-
-  ApexManifest manifest(name, preInstallHook, postInstallHook, version);
-  return StatusOr<ApexManifest>(std::move(manifest));
+std::string GetPackageId(const ApexManifest& apexManifest) {
+  return apexManifest.name() + "@" + std::to_string(apexManifest.version());
 }
 
 }  // namespace apex
diff --git a/apexd/apex_manifest.h b/apexd/apex_manifest.h
index a8777d0..8d11e26 100644
--- a/apexd/apex_manifest.h
+++ b/apexd/apex_manifest.h
@@ -17,41 +17,19 @@
 #ifndef ANDROID_APEXD_APEX_MANIFEST_H_
 #define ANDROID_APEXD_APEX_MANIFEST_H_
 
+#include "apex_manifest.pb.h"
 #include "status_or.h"
 
 #include <string>
 
+using ::apex::proto::ApexManifest;
+
 namespace android {
 namespace apex {
-
-// Parses an APEX manifest on construction and exposes its fields.
-class ApexManifest {
- public:
-  static StatusOr<ApexManifest> Parse(const std::string& content);
-  ApexManifest() = delete;
-  ApexManifest(ApexManifest&&) = default;
-
-  const std::string& GetName() const { return name_; }
-  uint64_t GetVersion() const { return version_; }
-  const std::string& GetPackageId() const { return package_id_; }
-  const std::string& GetPreInstallHook() const { return preInstallHook_; }
-  const std::string& GetPostInstallHook() const { return postInstallHook_; }
-
- private:
-  ApexManifest(std::string& name, std::string& preInstallHook,
-               std::string& postInstallHook, uint64_t version)
-      : name_(std::move(name)),
-        preInstallHook_(std::move(preInstallHook)),
-        postInstallHook_(std::move(postInstallHook)),
-        version_(version),
-        package_id_(name_ + "@" + std::to_string(version_)) {}
-
-  std::string name_;
-  std::string preInstallHook_;
-  std::string postInstallHook_;
-  uint64_t version_;
-  std::string package_id_;
-};
+// Parses and validates APEX manifest.
+StatusOr<ApexManifest> ParseManifest(const std::string& content);
+// Returns package id of an ApexManifest
+std::string GetPackageId(const ApexManifest& apex_manifest);
 
 }  // namespace apex
 }  // namespace android
diff --git a/apexd/apex_manifest_test.cpp b/apexd/apex_manifest_test.cpp
index c7de07c..06a0b5b 100644
--- a/apexd/apex_manifest_test.cpp
+++ b/apexd/apex_manifest_test.cpp
@@ -22,82 +22,80 @@
 namespace apex {
 
 TEST(ApexManifestTest, SimpleTest) {
-  auto apexManifest = ApexManifest::Parse(
+  auto apex_manifest = ParseManifest(
       "{\"name\": \"com.android.example.apex\", \"version\": 1}\n");
-  ASSERT_TRUE(apexManifest.Ok());
-  EXPECT_EQ("com.android.example.apex", std::string(apexManifest->GetName()));
-  EXPECT_EQ(1u, apexManifest->GetVersion());
+  ASSERT_TRUE(apex_manifest.Ok());
+  EXPECT_EQ("com.android.example.apex", std::string(apex_manifest->name()));
+  EXPECT_EQ(1u, apex_manifest->version());
 }
 
 TEST(ApexManifestTest, NameMissing) {
-  auto apexManifest = ApexManifest::Parse("{\"version\": 1}\n");
-  ASSERT_FALSE(apexManifest.Ok());
-  EXPECT_EQ(apexManifest.ErrorMessage(),
+  auto apex_manifest = ParseManifest("{\"version\": 1}\n");
+  ASSERT_FALSE(apex_manifest.Ok());
+  EXPECT_EQ(apex_manifest.ErrorMessage(),
             std::string("Missing required field \"name\" from APEX manifest."))
-      << apexManifest.ErrorMessage();
+      << apex_manifest.ErrorMessage();
 }
 
 TEST(ApexManifestTest, VersionMissing) {
-  auto apexManifest =
-      ApexManifest::Parse("{\"name\": \"com.android.example.apex\"}\n");
-  ASSERT_FALSE(apexManifest.Ok());
+  auto apex_manifest =
+      ParseManifest("{\"name\": \"com.android.example.apex\"}\n");
+  ASSERT_FALSE(apex_manifest.Ok());
   EXPECT_EQ(
-      apexManifest.ErrorMessage(),
+      apex_manifest.ErrorMessage(),
       std::string("Missing required field \"version\" from APEX manifest."))
-      << apexManifest.ErrorMessage();
+      << apex_manifest.ErrorMessage();
 }
 
 TEST(ApexManifestTest, VersionNotNumber) {
-  auto apexManifest = ApexManifest::Parse(
-      "{\"name\": \"com.android.example.apex\", \"version\": \"1\"}\n");
-  ASSERT_FALSE(apexManifest.Ok());
-  EXPECT_EQ(apexManifest.ErrorMessage(),
-            std::string("Invalid type for field \"version\" from APEX "
-                        "manifest, expecting integer."))
-      << apexManifest.ErrorMessage();
+  auto apex_manifest = ParseManifest(
+      "{\"name\": \"com.android.example.apex\", \"version\": \"a\"}\n");
+
+  ASSERT_FALSE(apex_manifest.Ok());
+  EXPECT_EQ(apex_manifest.ErrorMessage(),
+            std::string("Failed to parse APEX Manifest JSON config: "
+                        "version: invalid value \"a\" for type TYPE_INT64"))
+      << apex_manifest.ErrorMessage();
 }
 
 TEST(ApexManifestTest, NoPreInstallHook) {
-  auto apexManifest = ApexManifest::Parse(
+  auto apex_manifest = ParseManifest(
       "{\"name\": \"com.android.example.apex\", \"version\": 1}\n");
-  ASSERT_TRUE(apexManifest.Ok());
-  EXPECT_EQ("", std::string(apexManifest->GetPreInstallHook()));
+  ASSERT_TRUE(apex_manifest.Ok());
+  EXPECT_EQ("", std::string(apex_manifest->preinstallhook()));
 }
 
 TEST(ApexManifestTest, PreInstallHook) {
-  auto apexManifest = ApexManifest::Parse(
+  auto apex_manifest = ParseManifest(
       "{\"name\": \"com.android.example.apex\", \"version\": 1, "
       "\"preInstallHook\": \"bin/preInstallHook\"}\n");
-  ASSERT_TRUE(apexManifest.Ok());
-  EXPECT_EQ("bin/preInstallHook",
-            std::string(apexManifest->GetPreInstallHook()));
+  ASSERT_TRUE(apex_manifest.Ok());
+  EXPECT_EQ("bin/preInstallHook", std::string(apex_manifest->preinstallhook()));
 }
 
 TEST(ApexManifestTest, NoPostInstallHook) {
-  auto apexManifest = ApexManifest::Parse(
+  auto apex_manifest = ParseManifest(
       "{\"name\": \"com.android.example.apex\", \"version\": 1}\n");
-  ASSERT_TRUE(apexManifest.Ok());
-  EXPECT_EQ("", std::string(apexManifest->GetPostInstallHook()));
+  ASSERT_TRUE(apex_manifest.Ok());
+  EXPECT_EQ("", std::string(apex_manifest->postinstallhook()));
 }
 
 TEST(ApexManifestTest, PostInstallHook) {
-  auto apexManifest = ApexManifest::Parse(
+  auto apex_manifest = ParseManifest(
       "{\"name\": \"com.android.example.apex\", \"version\": 1, "
       "\"postInstallHook\": \"bin/postInstallHook\"}\n");
-  ASSERT_TRUE(apexManifest.Ok());
+  ASSERT_TRUE(apex_manifest.Ok());
   EXPECT_EQ("bin/postInstallHook",
-            std::string(apexManifest->GetPostInstallHook()));
+            std::string(apex_manifest->postinstallhook()));
 }
 
 TEST(ApexManifestTest, UnparsableManifest) {
-  auto apexManifest = ApexManifest::Parse("This is an invalid pony");
-  ASSERT_FALSE(apexManifest.Ok());
-  EXPECT_EQ(
-      apexManifest.ErrorMessage(),
-      std::string(
-          "Failed to parse APEX Manifest JSON config: * Line 1, Column 1\n"
-          "  Syntax error: value, object or array expected.\n"))
-      << apexManifest.ErrorMessage();
+  auto apex_manifest = ParseManifest("This is an invalid pony");
+  ASSERT_FALSE(apex_manifest.Ok());
+  EXPECT_EQ(apex_manifest.ErrorMessage(),
+            std::string("Failed to parse APEX Manifest JSON config: Unexpected "
+                        "token.\nThis is an invalid p\n^"))
+      << apex_manifest.ErrorMessage();
 }
 
 }  // namespace apex
diff --git a/apexd/apexd.cpp b/apexd/apexd.cpp
index f93b8a4..7b1e6ee 100644
--- a/apexd/apexd.cpp
+++ b/apexd/apexd.cpp
@@ -430,7 +430,7 @@
                          MountedApexData* apex_data) {
   const ApexManifest& manifest = apex.GetManifest();
   const std::string& full_path = apex.GetPath();
-  const std::string& packageId = manifest.GetPackageId();
+  const std::string& packageId = GetPackageId(manifest);
 
   LoopbackDeviceUniqueFd loopbackDevice;
   for (size_t attempts = 1;; ++attempts) {
@@ -596,20 +596,20 @@
     return st;
   }
 
-  gMountedApexes.AddMountedApex(apex.GetManifest().GetName(), false,
+  gMountedApexes.AddMountedApex(apex.GetManifest().name(), false,
                                 std::move(data));
   return Status::Success();
 }
 
 Status UnmountPackage(const ApexFile& apex) {
-  LOG(VERBOSE) << "Unmounting " << apex.GetManifest().GetPackageId();
+  LOG(VERBOSE) << "Unmounting " << GetPackageId(apex.GetManifest());
 
   const ApexManifest& manifest = apex.GetManifest();
 
   const MountedApexData* data = nullptr;
   bool latest = false;
 
-  gMountedApexes.ForallMountedApexes(manifest.GetName(),
+  gMountedApexes.ForallMountedApexes(manifest.name(),
                                      [&](const MountedApexData& d, bool l) {
                                        if (d.full_path == apex.GetPath()) {
                                          data = &d;
@@ -636,7 +636,7 @@
 
   // Clean up gMountedApexes now, even though we're not fully done.
   std::string loop = data->loop_name;
-  gMountedApexes.RemoveMountedApex(manifest.GetName(), apex.GetPath());
+  gMountedApexes.RemoveMountedApex(manifest.name(), apex.GetPath());
 
   // Attempt to delete the folder. If the folder is retained, other
   // data may be incorrect.
@@ -668,11 +668,11 @@
 }
 
 std::string GetPackageMountPoint(const ApexManifest& manifest) {
-  return StringPrintf("%s/%s", kApexRoot, manifest.GetPackageId().c_str());
+  return StringPrintf("%s/%s", kApexRoot, GetPackageId(manifest).c_str());
 }
 
 std::string GetActiveMountPoint(const ApexManifest& manifest) {
-  return StringPrintf("%s/%s", kApexRoot, manifest.GetName().c_str());
+  return StringPrintf("%s/%s", kApexRoot, manifest.name().c_str());
 }
 
 }  // namespace apexd_private
@@ -693,20 +693,22 @@
   bool found_other_version = false;
   bool version_found_mounted = false;
   {
-    uint64_t new_version = manifest.GetVersion();
+    uint64_t new_version = manifest.version();
     bool version_found_active = false;
     gMountedApexes.ForallMountedApexes(
-        manifest.GetName(), [&](const MountedApexData& data, bool latest) {
+        manifest.name(), [&](const MountedApexData& data, bool latest) {
           StatusOr<ApexFile> otherApex = ApexFile::Open(data.full_path);
           if (!otherApex.Ok()) {
             return;
           }
           found_other_version = true;
-          if (otherApex->GetManifest().GetVersion() == new_version) {
+          if (static_cast<uint64_t>(otherApex->GetManifest().version()) ==
+              new_version) {
             version_found_mounted = true;
             version_found_active = latest;
           }
-          if (otherApex->GetManifest().GetVersion() > new_version) {
+          if (static_cast<uint64_t>(otherApex->GetManifest().version()) >
+              new_version) {
             is_newest_version = false;
           }
         });
@@ -735,7 +737,7 @@
     }
   }
   if (mounted_latest) {
-    gMountedApexes.SetLatest(manifest.GetName(), full_path);
+    gMountedApexes.SetLatest(manifest.name(), full_path);
   }
 
   return Status::Success();
@@ -752,8 +754,7 @@
   Status st = deactivatePackageImpl(*apexFile);
 
   if (st.Ok()) {
-    gMountedApexes.RemoveMountedApex(apexFile->GetManifest().GetName(),
-                                     full_path);
+    gMountedApexes.RemoveMountedApex(apexFile->GetManifest().name(), full_path);
   }
 
   return st;
@@ -772,7 +773,6 @@
           // TODO: Fail?
           return;
         }
-
         ret.emplace_back(std::move(*apexFile));
       });
 
@@ -782,7 +782,7 @@
 StatusOr<ApexFile> getActivePackage(const std::string& packageName) {
   std::vector<ApexFile> packages = getActivePackages();
   for (ApexFile& apex : packages) {
-    if (apex.GetManifest().GetName() == packageName) {
+    if (apex.GetManifest().name() == packageName) {
       return StatusOr<ApexFile>(std::move(apex));
     }
   }
@@ -958,7 +958,7 @@
     if (!apex_file.Ok()) {
       return apex_file.ErrorStatus();
     }
-    if (!apex_file->GetManifest().GetPreInstallHook().empty()) {
+    if (!apex_file->GetManifest().preinstallhook().empty()) {
       has_preInstallHooks = true;
     }
     apex_files.emplace_back(std::move(*apex_file));
@@ -995,7 +995,7 @@
 
   auto path_fn = [](const ApexFile& apex_file) {
     return StringPrintf("%s/%s%s", kApexPackageDataDir,
-                        apex_file.GetManifest().GetPackageId().c_str(),
+                        GetPackageId(apex_file.GetManifest()).c_str(),
                         kApexPackageSuffix);
   };
 
diff --git a/apexd/apexd_prepostinstall.cpp b/apexd/apexd_prepostinstall.cpp
index b115897..1d116a8 100644
--- a/apexd/apexd_prepostinstall.cpp
+++ b/apexd/apexd_prepostinstall.cpp
@@ -103,8 +103,7 @@
     std::string mount_point =
         apexd_private::GetPackageMountPoint(apex.GetManifest());
 
-    if (!apexd_private::IsMounted(apex.GetManifest().GetName(),
-                                  apex.GetPath())) {
+    if (!apexd_private::IsMounted(apex.GetManifest().name(), apex.GetPath())) {
       Status mountStatus = apexd_private::MountPackage(apex, mount_point);
       if (!mountStatus.Ok()) {
         return mountStatus;
@@ -226,22 +225,21 @@
 }  // namespace
 
 Status StagePreInstall(std::vector<ApexFile>& apexes) {
-  return StageFnInstall(apexes, &ApexManifest::GetPreInstallHook,
-                        "--pre-install", "pre-install");
+  return StageFnInstall(apexes, &ApexManifest::preinstallhook, "--pre-install",
+                        "pre-install");
 }
 
 int RunPreInstall(char** in_argv) {
-  return RunFnInstall(in_argv, &ApexManifest::GetPreInstallHook, "pre-install");
+  return RunFnInstall(in_argv, &ApexManifest::preinstallhook, "pre-install");
 }
 
 Status StagePostInstall(std::vector<ApexFile>& apexes) {
-  return StageFnInstall(apexes, &ApexManifest::GetPostInstallHook,
+  return StageFnInstall(apexes, &ApexManifest::postinstallhook,
                         "--post-install", "post-install");
 }
 
 int RunPostInstall(char** in_argv) {
-  return RunFnInstall(in_argv, &ApexManifest::GetPostInstallHook,
-                      "post-install");
+  return RunFnInstall(in_argv, &ApexManifest::postinstallhook, "post-install");
 }
 
 }  // namespace apex
diff --git a/apexd/apexd_private.h b/apexd/apexd_private.h
index 1e29a0a..c96af10 100644
--- a/apexd/apexd_private.h
+++ b/apexd/apexd_private.h
@@ -20,13 +20,13 @@
 #include <string>
 
 #include "apex_database.h"
+#include "apex_manifest.h"
 #include "status.h"
 
 namespace android {
 namespace apex {
 
 class ApexFile;
-class ApexManifest;
 
 static constexpr int kMkdirMode = 0755;
 
diff --git a/apexd/apexservice.cpp b/apexd/apexservice.cpp
index 066bef3..5e9676a 100644
--- a/apexd/apexservice.cpp
+++ b/apexd/apexservice.cpp
@@ -125,9 +125,9 @@
 
   for (const auto& package : *packages) {
     ApexInfo out;
-    out.packageName = package.GetManifest().GetName();
+    out.packageName = package.GetManifest().name();
     out.packagePath = package.GetPath();
-    out.versionCode = package.GetManifest().GetVersion();
+    out.versionCode = package.GetManifest().version();
     apex_info_list->apexInfos.push_back(out);
   }
   *aidl_return = true;
@@ -226,9 +226,9 @@
   auto packages = ::android::apex::getActivePackages();
   for (const auto& package : packages) {
     ApexInfo out;
-    out.packageName = package.GetManifest().GetName();
+    out.packageName = package.GetManifest().name();
     out.packagePath = package.GetPath();
-    out.versionCode = package.GetManifest().GetVersion();
+    out.versionCode = package.GetManifest().version();
     aidl_return->push_back(out);
   }
 
@@ -239,9 +239,9 @@
                                            ApexInfo* aidl_return) {
   StatusOr<ApexFile> apex = ::android::apex::getActivePackage(packageName);
   if (apex.Ok()) {
-    aidl_return->packageName = apex->GetManifest().GetName();
+    aidl_return->packageName = apex->GetManifest().name();
     aidl_return->packagePath = apex->GetPath();
-    aidl_return->versionCode = apex->GetManifest().GetVersion();
+    aidl_return->versionCode = apex->GetManifest().version();
   }
 
   return BinderStatus::ok();
diff --git a/apexd/apexservice_test.cpp b/apexd/apexservice_test.cpp
index d10996f..4c2f76b 100644
--- a/apexd/apexservice_test.cpp
+++ b/apexd/apexservice_test.cpp
@@ -216,8 +216,8 @@
       }
 
       const ApexManifest& manifest = apex_file->GetManifest();
-      package = manifest.GetName();
-      version = manifest.GetVersion();
+      package = manifest.name();
+      version = manifest.version();
 
       test_installed_file = std::string(kApexPackageDataDir) + "/" + package +
                             "@" + std::to_string(version) + ".apex";
diff --git a/proto/Android.bp b/proto/Android.bp
index d057455..962542b 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -14,6 +14,16 @@
  * limitations under the License.
  */
 
+cc_library_static {
+    name: "lib_apex_manifest_proto",
+    host_supported: true,
+    proto: {
+        export_proto_headers: true,
+        type: "full",
+    },
+    srcs: ["apex_manifest.proto"],
+}
+
 python_library_host {
     name: "apex_manifest_proto",
     version: {