Add constraints for enabling RROs

This change introduces hidden API's for setting constraints
for enabling RROs. Currently, the constraints are of the following
types:
1. Display id constraint: This can be set for a RRO if the RRO is
desired to be applied on only the apps running on that specific
display.
2. Device id constraint: This can be set for a RRO if the RRO is
desired to be applied on only the apps running on that specific
device (for apps running on the default device, this would be
Context#DEVICE_ID_DEFAULT, and for apps running on a virtual device,
this would be the id of the virtual device).

An overlay would be enabled when any of the given constraints are met.
Constraints can only be set while enabling a RRO. Re-enabling a RRO
with different constraints updates the constraints for the RRO.

This change facilitates the writing of the constraints for RROs
into the correspodning idmap files, and also persists them as part
of the settings used by OverlayManagerService. The filtering of
resource overlays based on constraints during resource resolution
will be done in a follow-up CL.

Test: atest FrameworksServicesTests
Test: atest idmap2_tests
Test: atest libandroidfw_tests
Test: atest CtsResourcesTestCases
Bug: 371801644
Flag: android.content.res.rro_constraints
Change-Id: I0cad58bfb5b9b90105e2ef839c58147b9a50767c
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index d9ff190..f6bee52 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -348,6 +348,7 @@
         "idmap2d/aidl/core/android/os/FabricatedOverlayInternal.aidl",
         "idmap2d/aidl/core/android/os/FabricatedOverlayInternalEntry.aidl",
         "idmap2d/aidl/core/android/os/FabricatedOverlayInfo.aidl",
+        "idmap2d/aidl/core/android/os/OverlayConstraint.aidl",
     ],
     path: "idmap2d/aidl/core/",
 }
diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp
index d5f1b89..d949401 100644
--- a/cmds/idmap2/idmap2/Create.cpp
+++ b/cmds/idmap2/idmap2/Create.cpp
@@ -35,6 +35,7 @@
 using android::idmap2::CommandLineOptions;
 using android::idmap2::Error;
 using android::idmap2::Idmap;
+using android::idmap2::IdmapConstraints;
 using android::idmap2::OverlayResourceContainer;
 using android::idmap2::Result;
 using android::idmap2::TargetResourceContainer;
@@ -104,8 +105,10 @@
     return Error("failed to load apk overlay '%s'", overlay_apk_path.c_str());
   }
 
+  // TODO(b/371801644): Add command-line support for RRO constraints.
+  auto constraints = std::make_unique<const IdmapConstraints>();
   const auto idmap = Idmap::FromContainers(**target, **overlay, overlay_name, fulfilled_policies,
-                                           !ignore_overlayable);
+                                           !ignore_overlayable, std::move(constraints));
   if (!idmap) {
     return Error(idmap.GetError(), "failed to create idmap");
   }
diff --git a/cmds/idmap2/idmap2/CreateMultiple.cpp b/cmds/idmap2/idmap2/CreateMultiple.cpp
index 2608c69..70a2ed1 100644
--- a/cmds/idmap2/idmap2/CreateMultiple.cpp
+++ b/cmds/idmap2/idmap2/CreateMultiple.cpp
@@ -39,6 +39,7 @@
 using android::idmap2::CommandLineOptions;
 using android::idmap2::Error;
 using android::idmap2::Idmap;
+using android::idmap2::IdmapConstraints;
 using android::idmap2::OverlayResourceContainer;
 using android::idmap2::Result;
 using android::idmap2::TargetResourceContainer;
@@ -115,8 +116,11 @@
         continue;
       }
 
+      // TODO(b/371801644): Add command-line support for RRO constraints.
+      auto constraints = std::make_unique<const IdmapConstraints>();
       const auto idmap =
-          Idmap::FromContainers(**target, **overlay, "", fulfilled_policies, !ignore_overlayable);
+          Idmap::FromContainers(**target, **overlay, "", fulfilled_policies, !ignore_overlayable,
+                                std::move(constraints));
       if (!idmap) {
         LOG(WARNING) << "failed to create idmap";
         continue;
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index 6902d6d..2495c55 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -46,6 +46,8 @@
 using android::idmap2::BinaryStreamVisitor;
 using android::idmap2::FabricatedOverlayContainer;
 using android::idmap2::Idmap;
+using android::idmap2::IdmapConstraint;
+using android::idmap2::IdmapConstraints;
 using android::idmap2::IdmapHeader;
 using android::idmap2::OverlayResourceContainer;
 using android::idmap2::PrettyPrintVisitor;
@@ -74,6 +76,18 @@
   return static_cast<PolicyBitmask>(arg);
 }
 
+std::unique_ptr<const IdmapConstraints> ConvertAidlConstraintsToIdmapConstraints(
+        const std::vector<android::os::OverlayConstraint>& constraints) {
+  auto idmapConstraints = std::make_unique<IdmapConstraints>();
+  for (const auto& constraint : constraints) {
+    IdmapConstraint idmapConstraint{};
+    idmapConstraint.constraint_type = constraint.type;
+    idmapConstraint.constraint_value = constraint.value;
+    idmapConstraints->constraints.insert(idmapConstraint);
+  }
+  return idmapConstraints;
+}
+
 }  // namespace
 
 namespace android::os {
@@ -113,6 +127,7 @@
 Status Idmap2Service::verifyIdmap(const std::string& target_path, const std::string& overlay_path,
                                   const std::string& overlay_name, int32_t fulfilled_policies,
                                   bool enforce_overlayable, int32_t user_id ATTRIBUTE_UNUSED,
+                                  const std::vector<os::OverlayConstraint>& constraints,
                                   bool* _aidl_return) {
   SYSTRACE << "Idmap2Service::verifyIdmap " << overlay_path;
   assert(_aidl_return);
@@ -120,12 +135,19 @@
   const std::string idmap_path = Idmap::CanonicalIdmapPathFor(kIdmapCacheDir, overlay_path);
   std::ifstream fin(idmap_path);
   const std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(fin);
+  const std::unique_ptr<const IdmapConstraints> oldConstraints =
+          IdmapConstraints::FromBinaryStream(fin);
   fin.close();
   if (!header) {
     *_aidl_return = false;
     LOG(WARNING) << "failed to parse idmap header of '" << idmap_path << "'";
     return ok();
   }
+  if (!oldConstraints) {
+    *_aidl_return = false;
+    LOG(WARNING) << "failed to parse idmap constraints of '" << idmap_path << "'";
+    return ok();
+  }
 
   const auto target = GetTargetContainer(target_path);
   if (!target) {
@@ -145,7 +167,10 @@
       header->IsUpToDate(*GetPointer(*target), **overlay, overlay_name,
                          ConvertAidlArgToPolicyBitmask(fulfilled_policies), enforce_overlayable);
 
-  *_aidl_return = static_cast<bool>(up_to_date);
+  std::unique_ptr<const IdmapConstraints> newConstraints =
+          ConvertAidlConstraintsToIdmapConstraints(constraints);
+
+  *_aidl_return = static_cast<bool>(up_to_date && (*oldConstraints == *newConstraints));
   if (!up_to_date) {
     LOG(WARNING) << "idmap '" << idmap_path
                  << "' not up to date : " << up_to_date.GetErrorMessage();
@@ -156,6 +181,7 @@
 Status Idmap2Service::createIdmap(const std::string& target_path, const std::string& overlay_path,
                                   const std::string& overlay_name, int32_t fulfilled_policies,
                                   bool enforce_overlayable, int32_t user_id ATTRIBUTE_UNUSED,
+                                  const std::vector<os::OverlayConstraint>& constraints,
                                   std::optional<std::string>* _aidl_return) {
   assert(_aidl_return);
   SYSTRACE << "Idmap2Service::createIdmap " << target_path << " " << overlay_path;
@@ -186,8 +212,11 @@
     return error("failed to load apk overlay '%s'" + overlay_path);
   }
 
+  std::unique_ptr<const IdmapConstraints> idmapConstraints =
+          ConvertAidlConstraintsToIdmapConstraints(constraints);
   const auto idmap = Idmap::FromContainers(*GetPointer(*target), **overlay, overlay_name,
-                                           policy_bitmask, enforce_overlayable);
+                                           policy_bitmask, enforce_overlayable,
+                                           std::move(idmapConstraints));
   if (!idmap) {
     return error(idmap.GetErrorMessage());
   }
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h
index 272ec6b..344a77f 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.h
+++ b/cmds/idmap2/idmap2d/Idmap2Service.h
@@ -20,6 +20,7 @@
 #include <android-base/unique_fd.h>
 #include <android/os/BnIdmap2.h>
 #include <android/os/FabricatedOverlayInfo.h>
+#include <android/os/OverlayConstraint.h>
 #include <binder/BinderService.h>
 #include <idmap2/ResourceContainer.h>
 #include <idmap2/Result.h>
@@ -49,11 +50,13 @@
   binder::Status verifyIdmap(const std::string& target_path, const std::string& overlay_path,
                              const std::string& overlay_name, int32_t fulfilled_policies,
                              bool enforce_overlayable, int32_t user_id,
+                             const std::vector<os::OverlayConstraint>& constraints,
                              bool* _aidl_return) override;
 
   binder::Status createIdmap(const std::string& target_path, const std::string& overlay_path,
                              const std::string& overlay_name, int32_t fulfilled_policies,
                              bool enforce_overlayable, int32_t user_id,
+                             const std::vector<os::OverlayConstraint>& constraints,
                              std::optional<std::string>* _aidl_return) override;
 
   binder::Status createFabricatedOverlay(
diff --git a/cmds/idmap2/idmap2d/aidl/core/android/os/OverlayConstraint.aidl b/cmds/idmap2/idmap2d/aidl/core/android/os/OverlayConstraint.aidl
new file mode 100644
index 0000000..8fce3d6
--- /dev/null
+++ b/cmds/idmap2/idmap2d/aidl/core/android/os/OverlayConstraint.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/**
+ * @hide
+ */
+parcelable OverlayConstraint {
+    int type;
+    int value;
+}
\ No newline at end of file
diff --git a/cmds/idmap2/idmap2d/aidl/services/android/os/IIdmap2.aidl b/cmds/idmap2/idmap2d/aidl/services/android/os/IIdmap2.aidl
index 2bbfba9..4f4f075 100644
--- a/cmds/idmap2/idmap2d/aidl/services/android/os/IIdmap2.aidl
+++ b/cmds/idmap2/idmap2d/aidl/services/android/os/IIdmap2.aidl
@@ -18,6 +18,7 @@
 
 import android.os.FabricatedOverlayInfo;
 import android.os.FabricatedOverlayInternal;
+import android.os.OverlayConstraint;
 
 /**
  * @hide
@@ -30,13 +31,15 @@
                       @utf8InCpp String overlayName,
                       int fulfilledPolicies,
                       boolean enforceOverlayable,
-                      int userId);
+                      int userId,
+                      in OverlayConstraint[] constraints);
   @nullable @utf8InCpp String createIdmap(@utf8InCpp String targetApkPath,
                                           @utf8InCpp String overlayApkPath,
                                           @utf8InCpp String overlayName,
                                           int fulfilledPolicies,
                                           boolean enforceOverlayable,
-                                          int userId);
+                                          int userId,
+                                          in OverlayConstraint[] constraints);
 
   @nullable FabricatedOverlayInfo createFabricatedOverlay(in FabricatedOverlayInternal overlay);
   boolean deleteFabricatedOverlay(@utf8InCpp String path);
diff --git a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
index 57af1b6..3009293 100644
--- a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
+++ b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
@@ -32,6 +32,7 @@
   ~BinaryStreamVisitor() override = default;
   void visit(const Idmap& idmap) override;
   void visit(const IdmapHeader& header) override;
+  void visit(const IdmapConstraints& constraints) override;
   void visit(const IdmapData& data) override;
   void visit(const IdmapData::Header& header) override;
 
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h
index b0ba019..1f15daf 100644
--- a/cmds/idmap2/include/idmap2/Idmap.h
+++ b/cmds/idmap2/include/idmap2/Idmap.h
@@ -17,10 +17,11 @@
 /*
  * # idmap file format (current version)
  *
- * idmap                      := header data*
+ * idmap                      := header constraints_count constraint* data*
  * header                     := magic version target_crc overlay_crc fulfilled_policies
  *                               enforce_overlayable target_path overlay_path overlay_name
  *                               debug_info
+ * constraints                := constraint_type constraint_value
  * data                       := data_header target_entries target_inline_entries
                                  target_inline_entry_value* config* overlay_entries string_pool
  * data_header                := target_entry_count target_inline_entry_count
@@ -67,6 +68,9 @@
  * value_type                       := <uint8_t>
  * value_data                       := <uint32_t>
  * version                          := <uint32_t>
+ * constraints_count                := <uint32_t>
+ * constraint_type                  := <uint32_t>
+ * constraint_value                 := <uint32_t>
  */
 
 #ifndef IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
@@ -76,6 +80,7 @@
 #include <memory>
 #include <string>
 #include <string_view>
+#include <unordered_set>
 #include <vector>
 
 #include "android-base/macros.h"
@@ -171,6 +176,33 @@
   friend Idmap;
   DISALLOW_COPY_AND_ASSIGN(IdmapHeader);
 };
+
+struct IdmapConstraint {
+  // Constraint type can be TYPE_DISPLAY_ID or TYP_DEVICE_ID, please refer
+  // to ConstraintType in OverlayConstraint.java
+  uint32_t constraint_type;
+  uint32_t constraint_value;
+
+  bool operator==(const IdmapConstraint&) const = default;
+};
+
+struct IdmapConstraints {
+  static std::unique_ptr<const IdmapConstraints> FromBinaryStream(std::istream& stream);
+
+  struct Hash {
+    static std::size_t operator()(const IdmapConstraint& constraint) {
+      return std::hash<int>()(constraint.constraint_type) * 31
+              + std::hash<int>()(constraint.constraint_value);
+    }
+  };
+
+  bool operator == (const IdmapConstraints& constraints) const = default;
+
+  void accept(Visitor* v) const;
+
+  std::unordered_set<IdmapConstraint, Hash> constraints;
+};
+
 class IdmapData {
  public:
   class Header {
@@ -286,12 +318,16 @@
   static Result<std::unique_ptr<const Idmap>> FromContainers(
       const TargetResourceContainer& target, const OverlayResourceContainer& overlay,
       const std::string& overlay_name, const PolicyBitmask& fulfilled_policies,
-      bool enforce_overlayable);
+      bool enforce_overlayable, std::unique_ptr<const IdmapConstraints>&& constraints);
 
   const std::unique_ptr<const IdmapHeader>& GetHeader() const {
     return header_;
   }
 
+  const std::unique_ptr<const IdmapConstraints>& GetConstraints() const {
+    return constraints_;
+  }
+
   const std::vector<std::unique_ptr<const IdmapData>>& GetData() const {
     return data_;
   }
@@ -302,6 +338,7 @@
   Idmap() = default;
 
   std::unique_ptr<const IdmapHeader> header_;
+  std::unique_ptr<const IdmapConstraints> constraints_;
   std::vector<std::unique_ptr<const IdmapData>> data_;
 
   DISALLOW_COPY_AND_ASSIGN(Idmap);
@@ -312,6 +349,7 @@
   virtual ~Visitor() = default;
   virtual void visit(const Idmap& idmap) = 0;
   virtual void visit(const IdmapHeader& header) = 0;
+  virtual void visit(const IdmapConstraints& constraints) = 0;
   virtual void visit(const IdmapData& data) = 0;
   virtual void visit(const IdmapData::Header& header) = 0;
 };
diff --git a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
index ed18d9c..033ef85 100644
--- a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
@@ -36,6 +36,7 @@
   ~PrettyPrintVisitor() override = default;
   void visit(const Idmap& idmap) override;
   void visit(const IdmapHeader& header) override;
+  void visit(const IdmapConstraints& constraints) override;
   void visit(const IdmapData& data) override;
   void visit(const IdmapData::Header& header) override;
 
diff --git a/cmds/idmap2/include/idmap2/RawPrintVisitor.h b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
index 849ba11..bd27c0d 100644
--- a/cmds/idmap2/include/idmap2/RawPrintVisitor.h
+++ b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
@@ -37,6 +37,7 @@
   ~RawPrintVisitor() override = default;
   void visit(const Idmap& idmap) override;
   void visit(const IdmapHeader& header) override;
+  void visit(const IdmapConstraints& constraints) override;
   void visit(const IdmapData& data) override;
   void visit(const IdmapData::Header& header) override;
 
diff --git a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
index 00ef0c7..b029aea 100644
--- a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
+++ b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
@@ -63,6 +63,14 @@
   WriteString(header.GetDebugInfo());
 }
 
+void BinaryStreamVisitor::visit(const IdmapConstraints& constraints) {
+  Write32(static_cast<uint32_t>(constraints.constraints.size()));
+  for (const auto& constraint : constraints.constraints) {
+    Write32(constraint.constraint_type);
+    Write32(constraint.constraint_value);
+  }
+}
+
 void BinaryStreamVisitor::visit(const IdmapData& data) {
   for (const auto& target_entry : data.GetTargetEntries()) {
     Write32(target_entry.target_id);
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 7680109..556ca22 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -182,6 +182,26 @@
   return Unit{};
 }
 
+std::unique_ptr<const IdmapConstraints> IdmapConstraints::FromBinaryStream(std::istream& stream) {
+    auto idmap_constraints = std::make_unique<IdmapConstraints>();
+    uint32_t count = 0;
+    if (!Read32(stream, &count)) {
+        return nullptr;
+    }
+    for (size_t i = 0; i < count; i++) {
+        IdmapConstraint constraint{};
+        if (!Read32(stream, &constraint.constraint_type)) {
+            return nullptr;
+        }
+        if (!Read32(stream, &constraint.constraint_value)) {
+            return nullptr;
+        }
+        idmap_constraints->constraints.insert(constraint);
+    }
+
+    return idmap_constraints;
+}
+
 std::unique_ptr<const IdmapData::Header> IdmapData::Header::FromBinaryStream(std::istream& stream) {
   std::unique_ptr<IdmapData::Header> idmap_data_header(new IdmapData::Header());
   if (!Read32(stream, &idmap_data_header->target_entry_count) ||
@@ -315,6 +335,10 @@
   if (!idmap->header_) {
     return Error("failed to parse idmap header");
   }
+  idmap->constraints_ = IdmapConstraints::FromBinaryStream(stream);
+  if (!idmap->constraints_) {
+    return Error("failed to parse idmap constraints");
+  }
 
   // idmap version 0x01 does not specify the number of data blocks that follow
   // the idmap header; assume exactly one data block
@@ -374,10 +398,9 @@
 }
 
 Result<std::unique_ptr<const Idmap>> Idmap::FromContainers(const TargetResourceContainer& target,
-                                                           const OverlayResourceContainer& overlay,
-                                                           const std::string& overlay_name,
-                                                           const PolicyBitmask& fulfilled_policies,
-                                                           bool enforce_overlayable) {
+    const OverlayResourceContainer& overlay, const std::string& overlay_name,
+    const PolicyBitmask& fulfilled_policies, bool enforce_overlayable,
+    std::unique_ptr<const IdmapConstraints>&& constraints) {
   SYSTRACE << "Idmap::FromApkAssets";
   std::unique_ptr<IdmapHeader> header(new IdmapHeader());
   header->magic_ = kIdmapMagic;
@@ -424,6 +447,11 @@
   header->debug_info_ = log_info.GetString();
   idmap->header_ = std::move(header);
   idmap->data_.push_back(std::move(*idmap_data));
+  if (constraints == nullptr) {
+    idmap->constraints_ = std::make_unique<IdmapConstraints>();
+  } else {
+    idmap->constraints_ = std::move(constraints);
+  }
 
   return {std::move(idmap)};
 }
@@ -433,6 +461,11 @@
   v->visit(*this);
 }
 
+void IdmapConstraints::accept(Visitor* v) const {
+  assert(v != nullptr);
+  v->visit(*this);
+}
+
 void IdmapData::Header::accept(Visitor* v) const {
   assert(v != nullptr);
   v->visit(*this);
@@ -447,6 +480,7 @@
 void Idmap::accept(Visitor* v) const {
   assert(v != nullptr);
   header_->accept(v);
+  constraints_->accept(v);
   v->visit(*this);
   auto end = data_.cend();
   for (auto iter = data_.cbegin(); iter != end; ++iter) {
diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
index eb94582..0ec31f4 100644
--- a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
@@ -58,6 +58,19 @@
   if (auto overlay = OverlayResourceContainer::FromPath(header.GetOverlayPath())) {
     overlay_ = std::move(*overlay);
   }
+}
+
+void PrettyPrintVisitor::visit(const IdmapConstraints& constraints) {
+  stream_ << "Constraints:" << '\n';
+  if (constraints.constraints.empty()) {
+    stream_ << TAB << "None\n";
+  } else {
+    for (const IdmapConstraint& constraint : constraints.constraints) {
+      stream_ << TAB
+              << base::StringPrintf("Type: %d, Value: %d\n", constraint.constraint_type,
+                                    constraint.constraint_value);
+    }
+  }
 
   stream_ << "Mapping:" << '\n';
 }
diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
index 9d04a7f..41a3da3 100644
--- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
@@ -55,6 +55,14 @@
   }
 }
 
+void RawPrintVisitor::visit(const IdmapConstraints &idmapConstraints) {
+  print(static_cast<uint32_t>(idmapConstraints.constraints.size()), "constraints count");
+  for (const auto& constraint : idmapConstraints.constraints) {
+    print(constraint.constraint_type, "constraint type");
+    print(constraint.constraint_value, "constraint value");
+  }
+}
+
 void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
   for (auto& target_entry : data.GetTargetEntries()) {
     Result<std::string> target_name(Error(""));
diff --git a/cmds/idmap2/self_targeting/SelfTargeting.cpp b/cmds/idmap2/self_targeting/SelfTargeting.cpp
index 7f9c468..26888ab 100644
--- a/cmds/idmap2/self_targeting/SelfTargeting.cpp
+++ b/cmds/idmap2/self_targeting/SelfTargeting.cpp
@@ -31,6 +31,7 @@
 using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
 using android::idmap2::BinaryStreamVisitor;
 using android::idmap2::Idmap;
+using android::idmap2::IdmapConstraints;
 using android::idmap2::OverlayResourceContainer;
 
 namespace android::self_targeting {
@@ -155,9 +156,10 @@
     // Overlay self target process. Only allow self-targeting types.
     const auto fulfilled_policies = GetFulfilledPolicy(isSystem, isVendor, isProduct,
                                                        isTargetSignature, isOdm, isOem);
-
+    auto constraints = std::make_unique<const IdmapConstraints>();
     const auto idmap = Idmap::FromContainers(**target, **overlay, overlayName,
-                                             fulfilled_policies, true /* enforce_overlayable */);
+                                             fulfilled_policies, true /* enforce_overlayable */,
+                                             std::move(constraints));
     if (!idmap) {
         out_err = base::StringPrintf("Failed to create idmap because of %s",
                                      idmap.GetErrorMessage().c_str());
diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
index f1eeab9..76cccb5 100644
--- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
+++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
@@ -58,6 +58,8 @@
   ASSERT_EQ(idmap1->GetData().size(), 1U);
   ASSERT_EQ(idmap1->GetData().size(), idmap2->GetData().size());
 
+  ASSERT_EQ(idmap1->GetConstraints()->constraints, idmap2->GetConstraints()->constraints);
+
   const std::vector<std::unique_ptr<const IdmapData>>& data_blocks1 = idmap1->GetData();
   ASSERT_EQ(data_blocks1.size(), 1U);
   const std::unique_ptr<const IdmapData>& data1 = data_blocks1[0];
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
index 5a7fcd5..760bbb3 100644
--- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -105,6 +105,7 @@
   fin.close();
 
   ASSERT_TRUE(idmap);
+  ASSERT_EQ((*idmap)->GetConstraints()->constraints.size(), 0);
   ASSERT_IDMAP(**idmap, GetTargetApkPath(), GetOverlayApkPath());
 
   unlink(GetIdmapPath().c_str());
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 7093614..4de2a6b 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -68,7 +68,7 @@
   std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
   ASSERT_THAT(header, NotNull());
   ASSERT_EQ(header->GetMagic(), 0x504d4449U);
-  ASSERT_EQ(header->GetVersion(), 10);
+  ASSERT_EQ(header->GetVersion(), 11);
   ASSERT_EQ(header->GetTargetCrc(), 0x1234U);
   ASSERT_EQ(header->GetOverlayCrc(), 0x5678U);
   ASSERT_EQ(header->GetFulfilledPolicies(), 0x11);
@@ -96,6 +96,19 @@
   ASSERT_FALSE(Idmap::FromBinaryStream(stream));
 }
 
+TEST(IdmapTests, CreateIdmapConstraintsFromBinaryStream) {
+  std::string raw(reinterpret_cast<const char*>(kIdmapRawData), kIdmapRawDataLen);
+  std::istringstream stream(raw);
+  std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
+  std::unique_ptr<const IdmapConstraints> constraints = IdmapConstraints::FromBinaryStream(stream);
+  ASSERT_THAT(constraints, NotNull());
+  ASSERT_EQ(constraints->constraints.size(), 2);
+  IdmapConstraint constraint1{.constraint_type = 0, .constraint_value = 1};
+  IdmapConstraint constraint2{.constraint_type = 1, .constraint_value = 2};
+  ASSERT_NE(constraints->constraints.find(constraint1), constraints->constraints.end());
+  ASSERT_NE(constraints->constraints.find(constraint2), constraints->constraints.end());
+}
+
 TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) {
   const size_t offset = kIdmapRawDataOffset;
   std::string raw(reinterpret_cast<const char*>(kIdmapRawData + offset), kIdmapRawDataLen - offset);
@@ -143,7 +156,7 @@
 
   ASSERT_THAT(idmap->GetHeader(), NotNull());
   ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
-  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 10);
+  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 11);
   ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U);
   ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U);
   ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), kIdmapRawDataPolicies);
@@ -195,16 +208,17 @@
   auto overlay = OverlayResourceContainer::FromPath(overlay_apk_path);
   ASSERT_TRUE(overlay);
 
+  auto constraints = std::make_unique<const IdmapConstraints>();
   auto idmap_result = Idmap::FromContainers(
       **target, **overlay, TestConstants::OVERLAY_NAME_ALL_POLICIES, PolicyFlags::PUBLIC,
-      /* enforce_overlayable */ true);
+      /* enforce_overlayable */ true, std::move(constraints));
   ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage();
   auto& idmap = *idmap_result;
   ASSERT_THAT(idmap, NotNull());
 
   ASSERT_THAT(idmap->GetHeader(), NotNull());
   ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
-  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 10);
+  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 11);
   ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), android::idmap2::TestConstants::TARGET_CRC);
   ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), android::idmap2::TestConstants::OVERLAY_CRC);
   ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), PolicyFlags::PUBLIC);
@@ -238,9 +252,10 @@
   auto overlay = OverlayResourceContainer::FromPath(overlay_apk_path);
   ASSERT_TRUE(overlay);
 
+  auto constraints = std::make_unique<const IdmapConstraints>();
   auto idmap_result = Idmap::FromContainers(
       **target, **overlay, TestConstants::OVERLAY_NAME_DEFAULT, PolicyFlags::PUBLIC,
-      /* enforce_overlayable */ true);
+      /* enforce_overlayable */ true, std::move(constraints));
   ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage();
   auto& idmap = *idmap_result;
   ASSERT_THAT(idmap, NotNull());
@@ -296,8 +311,9 @@
   auto overlay = OverlayResourceContainer::FromPath(tf.path);
   ASSERT_TRUE(overlay);
 
+  auto constraints = std::make_unique<const IdmapConstraints>();
   auto idmap_result = Idmap::FromContainers(**target, **overlay, "SandTheme", PolicyFlags::PUBLIC,
-                                            /* enforce_overlayable */ true);
+                                            /* enforce_overlayable */ true, std::move(constraints));
   ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage();
   auto& idmap = *idmap_result;
   ASSERT_THAT(idmap, NotNull());
@@ -341,13 +357,17 @@
   ASSERT_TRUE(overlay);
 
   {
+    auto constraints = std::make_unique<const IdmapConstraints>();
     auto idmap_result = Idmap::FromContainers(**target, **overlay, "", PolicyFlags::PUBLIC,
-                                              /* enforce_overlayable */ true);
+                                              /* enforce_overlayable */ true,
+                                              std::move(constraints));
     ASSERT_FALSE(idmap_result);
   }
   {
+    auto constraints = std::make_unique<const IdmapConstraints>();
     auto idmap_result = Idmap::FromContainers(**target, **overlay, "unknown", PolicyFlags::PUBLIC,
-                                              /* enforce_overlayable */ true);
+                                              /* enforce_overlayable */ true,
+                                              std::move(constraints));
     ASSERT_FALSE(idmap_result);
   }
 }
@@ -362,9 +382,10 @@
   auto overlay = OverlayResourceContainer::FromPath(overlay_apk_path);
   ASSERT_TRUE(overlay);
 
+  auto constraints = std::make_unique<const IdmapConstraints>();
   auto idmap_result = Idmap::FromContainers(
       **target, **overlay, TestConstants::OVERLAY_NAME_DEFAULT, PolicyFlags::PUBLIC,
-      /* enforce_overlayable */ true);
+      /* enforce_overlayable */ true, std::move(constraints));
   ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage();
   auto& idmap = *idmap_result;
   ASSERT_THAT(idmap, NotNull());
@@ -634,6 +655,10 @@
     stream_ << "TestVisitor::visit(IdmapHeader)" << '\n';
   }
 
+  void visit(const IdmapConstraints& idmap ATTRIBUTE_UNUSED) override {
+    stream_ << "TestVisitor::visit(IdmapConstraints)" << '\n';
+  }
+
   void visit(const IdmapData& idmap ATTRIBUTE_UNUSED) override {
     stream_ << "TestVisitor::visit(IdmapData)" << '\n';
   }
@@ -659,6 +684,7 @@
 
   ASSERT_EQ(test_stream.str(),
             "TestVisitor::visit(IdmapHeader)\n"
+            "TestVisitor::visit(IdmapConstraints)\n"
             "TestVisitor::visit(Idmap)\n"
             "TestVisitor::visit(IdmapData::Header)\n"
             "TestVisitor::visit(IdmapData)\n");
diff --git a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
index 3d3d82a..2f42f79 100644
--- a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
@@ -42,8 +42,10 @@
   auto overlay = OverlayResourceContainer::FromPath(overlay_apk_path);
   ASSERT_TRUE(overlay);
 
+  auto constraints = std::make_unique<const IdmapConstraints>();
   const auto idmap = Idmap::FromContainers(**target, **overlay, TestConstants::OVERLAY_NAME_DEFAULT,
-                                           PolicyFlags::PUBLIC, /* enforce_overlayable */ true);
+                                           PolicyFlags::PUBLIC, /* enforce_overlayable */ true,
+                                           std::move(constraints));
   ASSERT_TRUE(idmap);
 
   std::stringstream stream;
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
index 7fae1c6..d5aafe6 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -55,8 +55,10 @@
   auto overlay = OverlayResourceContainer::FromPath(overlay_apk_path);
   ASSERT_TRUE(overlay);
 
+  auto constraints = std::make_unique<const IdmapConstraints>();
   const auto idmap = Idmap::FromContainers(**target, **overlay, TestConstants::OVERLAY_NAME_DEFAULT,
-                                           PolicyFlags::PUBLIC, /* enforce_overlayable */ true);
+                                           PolicyFlags::PUBLIC, /* enforce_overlayable */ true,
+                                           std::move(constraints));
   ASSERT_TRUE(idmap);
 
   std::stringstream stream;
@@ -64,7 +66,7 @@
   (*idmap)->accept(&visitor);
 
   ASSERT_CONTAINS_REGEX(ADDRESS "504d4449  magic\n", stream.str());
-  ASSERT_CONTAINS_REGEX(ADDRESS "0000000a  version\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "0000000b  version\n", stream.str());
   ASSERT_CONTAINS_REGEX(
       StringPrintf(ADDRESS "%s  target crc\n", android::idmap2::TestConstants::TARGET_CRC_STRING),
       stream.str());
@@ -73,6 +75,7 @@
       stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000001  fulfilled policies: public\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000001  enforce overlayable\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "00000000  constraints count\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000004  target entry count", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000000  target inline entry count", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000000  target inline entry value count", stream.str());
@@ -113,7 +116,7 @@
   (*idmap)->accept(&visitor);
 
   ASSERT_CONTAINS_REGEX(ADDRESS "504d4449  magic\n", stream.str());
-  ASSERT_CONTAINS_REGEX(ADDRESS "0000000a  version\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "0000000b  version\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00001234  target crc\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00005678  overlay crc\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000011  fulfilled policies: public|signature\n", stream.str());
@@ -124,6 +127,11 @@
   ASSERT_CONTAINS_REGEX(ADDRESS "........  overlay path: overlayX.apk\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "0000000b  overlay name size\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "........  overlay name: OverlayName\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "00000002  constraints count\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "00000000  constraint type\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "00000001  constraint value\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "00000001  constraint type\n", stream.str());
+  ASSERT_CONTAINS_REGEX(ADDRESS "00000002  constraint value\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000003  target entry count\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000001  target inline entry count\n", stream.str());
   ASSERT_CONTAINS_REGEX(ADDRESS "00000001  target inline entry value count", stream.str());
diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h
index 2b4ebd1..6f645bd 100644
--- a/cmds/idmap2/tests/TestHelpers.h
+++ b/cmds/idmap2/tests/TestHelpers.h
@@ -34,7 +34,7 @@
     0x49, 0x44, 0x4d, 0x50,
 
     // 0x4: version
-    0x0a, 0x00, 0x00, 0x00,
+    0x0b, 0x00, 0x00, 0x00,
 
     // 0x8: target crc
     0x34, 0x12, 0x00, 0x00,
@@ -73,131 +73,147 @@
     // 0x4c string contents "debug\0\0\0" (padded to word alignment)
     0x64, 0x65, 0x62, 0x75, 0x67, 0x00, 0x00, 0x00,
 
-    // DATA HEADER
-    // 0x54: target_entry_count
-    0x03, 0x00, 0x00, 0x00,
+    // CONSTRAINTS
+    // 0x54: constraints_count
+    0x02, 0x00, 0x00, 0x00,
 
-    // 0x58: target_inline_entry_count
+    // 0x58: constraint_type
+    0x00, 0x00, 0x00, 0x00,
+
+    // 0x5c: constraint_value
     0x01, 0x00, 0x00, 0x00,
 
-    // 0x5c: target_inline_entry_value_count
+    // 0x60: constraint_type
+    0x01, 0x00, 0x00, 0x00,
+
+    // 0x64: constraint_value
+    0x02, 0x00, 0x00, 0x00,
+
+    // DATA HEADER
+    // 0x68: target_entry_count
+    0x03, 0x00, 0x00, 0x00,
+
+    // 0x6c: target_inline_entry_count
+    0x01, 0x00, 0x00, 0x00,
+
+    // 0x70: target_inline_entry_value_count
     0x01, 0x00, 0x00, 0x00,
 
     // 0x60: config_count
     0x01, 0x00, 0x00, 0x00,
 
-    // 0x64: overlay_entry_count
+    // 0x74: overlay_entry_count
     0x03, 0x00, 0x00, 0x00,
 
-    // 0x68: string_pool_offset
+    // 0x78: string_pool_offset
     0x00, 0x00, 0x00, 0x00,
 
     // TARGET ENTRIES
-    // 0x6c: target id (0x7f020000)
+    // 0x7c: target id (0x7f020000)
     0x00, 0x00, 0x02, 0x7f,
-    // 0x70: target id (0x7f030000)
+    // 0x80: target id (0x7f030000)
     0x00, 0x00, 0x03, 0x7f,
-    // 0x74: target id (0x7f030002)
+    // 0x84: target id (0x7f030002)
     0x02, 0x00, 0x03, 0x7f,
 
-    // 0x78: overlay_id (0x7f020000)
+    // 0x88: overlay_id (0x7f020000)
     0x00, 0x00, 0x02, 0x7f,
-    // 0x7c: overlay_id (0x7f030000)
+    // 0x8c: overlay_id (0x7f030000)
     0x00, 0x00, 0x03, 0x7f,
-    // 0x80: overlay_id (0x7f030001)
+    // 0x90: overlay_id (0x7f030001)
     0x01, 0x00, 0x03, 0x7f,
 
     // INLINE TARGET ENTRIES
 
-    // 0x84: target_id
+    // 0x94: target_id
     0x00, 0x00, 0x04, 0x7f,
 
-    // 0x88: start value index
+    // 0x98: start value index
     0x00, 0x00, 0x00, 0x00,
 
-    // 0x8c: value count
+    // 0x9c: value count
     0x01, 0x00, 0x00, 0x00,
 
     // INLINE TARGET ENTRY VALUES
 
-    // 0x90: config index
+    // 0xa0: config index
     0x00, 0x00, 0x00, 0x00,
 
-    // 0x94: Res_value::size (value ignored by idmap)
+    // 0xa4: Res_value::size (value ignored by idmap)
     0x08, 0x00,
 
-    // 0x98: Res_value::res0 (value ignored by idmap)
+    // 0xa8: Res_value::res0 (value ignored by idmap)
     0x00,
 
-    // 0x9c: Res_value::dataType (TYPE_INT_HEX)
+    // 0xac: Res_value::dataType (TYPE_INT_HEX)
     0x11,
 
-    // 0xa0: Res_value::data
+    // 0xb0: Res_value::data
     0x78, 0x56, 0x34, 0x12,
 
     // CONFIGURATIONS
 
-    // 0xa4: ConfigDescription
+    // 0xb4: ConfigDescription
     // size
     0x40, 0x00, 0x00, 0x00,
-    // 0xa8: imsi
+    // 0xb8: imsi
     0x00, 0x00, 0x00, 0x00,
-    // 0xac: locale
+    // 0xbc: locale
     0x00, 0x00, 0x00, 0x00,
-    // 0xb0: screenType
+    // 0xc0: screenType
     0x02, 0x00, 0xe0, 0x01,
-    // 0xb4: input
+    // 0xc4: input
     0x00, 0x00, 0x00, 0x00,
-    // 0xb8: screenSize
+    // 0xc8: screenSize
     0x00, 0x00, 0x00, 0x00,
-    // 0xbc: version
+    // 0xcc: version
     0x07, 0x00, 0x00, 0x00,
-    // 0xc0: screenConfig
+    // 0xd0: screenConfig
     0x00, 0x00, 0x00, 0x00,
-    // 0xc4: screenSizeDp
+    // 0xd4: screenSizeDp
     0x00, 0x00, 0x00, 0x00,
-    // 0xc8: localeScript
+    // 0xd8: localeScript
     0x00, 0x00, 0x00, 0x00,
-    // 0xcc: localVariant(1)
+    // 0xdc: localVariant(1)
     0x00, 0x00, 0x00, 0x00,
-    // 0xd0: localVariant(2)
+    // 0xe0: localVariant(2)
     0x00, 0x00, 0x00, 0x00,
-    // 0xd4: screenConfig2
+    // 0xe4: screenConfig2
     0x00, 0x00, 0x00, 0x00,
-    // 0xd8: localeScriptWasComputed
+    // 0xe8: localeScriptWasComputed
     0x00,
-    // 0xd9: localeNumberingSystem(1)
+    // 0xe9: localeNumberingSystem(1)
     0x00, 0x00, 0x00, 0x00,
-    // 0xdd: localeNumberingSystem(2)
+    // 0xed: localeNumberingSystem(2)
     0x00, 0x00, 0x00, 0x00,
 
-    // 0xe1: padding
+    // 0xf1: padding
     0x00, 0x00, 0x00,
 
     // OVERLAY ENTRIES
-    // 0xe4: 0x7f020000 -> ...
+    // 0xf4: 0x7f020000 -> ...
     0x00, 0x00, 0x02, 0x7f,
-    // 0xe8: 0x7f030000 -> ...
+    // 0xf8: 0x7f030000 -> ...
     0x00, 0x00, 0x03, 0x7f,
-    // 0xec: 0x7f030001 -> ...
+    // 0xfc: 0x7f030001 -> ...
     0x01, 0x00, 0x03, 0x7f,
 
-    // 0xf0: ... -> 0x7f020000
+    // 0x100: ... -> 0x7f020000
     0x00, 0x00, 0x02, 0x7f,
-    // 0xf4: ... -> 0x7f030000
+    // 0x104: ... -> 0x7f030000
     0x00, 0x00, 0x03, 0x7f,
-    // 0xf8: ... -> 0x7f030002
+    // 0x108: ... -> 0x7f030002
     0x02, 0x00, 0x03, 0x7f,
 
-    // 0xfc: string pool
+    // 0x10c: string pool
     // string length,
     0x04, 0x00, 0x00, 0x00,
 
-    // 0x100 string contents "test"
+    // 0x110 string contents "test"
     0x74, 0x65, 0x73, 0x74};
 
 constexpr unsigned int kIdmapRawDataLen = std::size(kIdmapRawData);
-const unsigned int kIdmapRawDataOffset = 0x54;
+const unsigned int kIdmapRawDataOffset = 0x68;
 const unsigned int kIdmapRawDataTargetCrc = 0x1234;
 const unsigned int kIdmapRawOverlayCrc = 0x5678;
 const unsigned int kIdmapRawDataPolicies = 0x11;