Add policies and enforce overlayable to header

If the fulfilled policies change without the contents of the target
and overlay APKs changing, the idmap for the overlay should be
regenerated. This change adds fulfilled policies and enforce
overlayable to the idmap header so that idmap2d can determine if the
polices or enforce overlayable changed from what was used to generate
the idmap.

Bug: 119328308
Test: idmap2_tests
Test: atest RegenerateIdmapTest

Change-Id: I96f970e82b5243be01b205ac2cb6ab249c6100bc
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index a93184f..908d966 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -33,16 +33,19 @@
 #include "idmap2/BinaryStreamVisitor.h"
 #include "idmap2/FileUtils.h"
 #include "idmap2/Idmap.h"
+#include "idmap2/Result.h"
 #include "idmap2/SysTrace.h"
 #include "idmap2/ZipFile.h"
 #include "utils/String8.h"
 
 using android::IPCThreadState;
+using android::base::StringPrintf;
 using android::binder::Status;
 using android::idmap2::BinaryStreamVisitor;
 using android::idmap2::GetPackageCrc;
 using android::idmap2::Idmap;
 using android::idmap2::IdmapHeader;
+using android::idmap2::ZipFile;
 using android::idmap2::utils::kIdmapCacheDir;
 using android::idmap2::utils::kIdmapFilePermissionMask;
 using android::idmap2::utils::UidHasWriteAccessToPath;
@@ -66,6 +69,21 @@
   return static_cast<PolicyBitmask>(arg);
 }
 
+Status GetCrc(const std::string& apk_path, uint32_t* out_crc) {
+  const auto overlay_zip = ZipFile::Open(apk_path);
+  if (!overlay_zip) {
+    return error(StringPrintf("failed to open apk %s", apk_path.c_str()));
+  }
+
+  const auto crc = GetPackageCrc(*overlay_zip);
+  if (!crc) {
+    return error(crc.GetErrorMessage());
+  }
+
+  *out_crc = *crc;
+  return ok();
+}
+
 }  // namespace
 
 namespace android::os {
@@ -98,10 +116,9 @@
 }
 
 Status Idmap2Service::verifyIdmap(const std::string& target_apk_path,
-                                  const std::string& overlay_apk_path,
-                                  int32_t fulfilled_policies ATTRIBUTE_UNUSED,
-                                  bool enforce_overlayable ATTRIBUTE_UNUSED,
-                                  int32_t user_id ATTRIBUTE_UNUSED, bool* _aidl_return) {
+                                  const std::string& overlay_apk_path, int32_t fulfilled_policies,
+                                  bool enforce_overlayable, int32_t user_id ATTRIBUTE_UNUSED,
+                                  bool* _aidl_return) {
   SYSTRACE << "Idmap2Service::verifyIdmap " << overlay_apk_path;
   assert(_aidl_return);
   const std::string idmap_path = Idmap::CanonicalIdmapPathFor(kIdmapCacheDir, overlay_apk_path);
@@ -113,34 +130,38 @@
     return error("failed to parse idmap header");
   }
 
-  if (strcmp(header->GetTargetPath().data(), target_apk_path.data()) != 0) {
-    *_aidl_return = false;
-    return ok();
-  }
-
-  if (target_apk_path != kFrameworkPath) {
-    *_aidl_return = (bool) header->IsUpToDate();
+  uint32_t target_crc;
+  if (target_apk_path == kFrameworkPath && android_crc_) {
+    target_crc = *android_crc_;
   } else {
-    if (!android_crc_) {
-      // Loading the framework zip can take several milliseconds. Cache the crc of the framework
-      // resource APK to reduce repeated work during boot.
-      const auto target_zip = idmap2::ZipFile::Open(target_apk_path);
-      if (!target_zip) {
-        return error(base::StringPrintf("failed to open target %s", target_apk_path.c_str()));
-      }
-
-      const auto target_crc = GetPackageCrc(*target_zip);
-      if (!target_crc) {
-        return error(target_crc.GetErrorMessage());
-      }
-
-      android_crc_ = *target_crc;
+    auto target_crc_status = GetCrc(target_apk_path, &target_crc);
+    if (!target_crc_status.isOk()) {
+      *_aidl_return = false;
+      return target_crc_status;
     }
 
-    *_aidl_return = (bool) header->IsUpToDate(android_crc_.value());
+    // Loading the framework zip can take several milliseconds. Cache the crc of the framework
+    // resource APK to reduce repeated work during boot.
+    if (target_apk_path == kFrameworkPath) {
+      android_crc_ = target_crc;
+    }
   }
 
-  // TODO(b/119328308): Check that the set of fulfilled policies of the overlay has not changed
+  uint32_t overlay_crc;
+  auto overlay_crc_status = GetCrc(overlay_apk_path, &overlay_crc);
+  if (!overlay_crc_status.isOk()) {
+    *_aidl_return = false;
+    return overlay_crc_status;
+  }
+
+  auto up_to_date =
+      header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(), target_crc, overlay_crc,
+                         fulfilled_policies, enforce_overlayable);
+  if (!up_to_date) {
+    *_aidl_return = false;
+    return error(up_to_date.GetErrorMessage());
+  }
+
   return ok();
 }