Merge "Support loading /odm/manifest_${ro.product.model}.xml"
diff --git a/VintfObject.cpp b/VintfObject.cpp
index 9dea4d9..efe6242 100644
--- a/VintfObject.cpp
+++ b/VintfObject.cpp
@@ -24,6 +24,10 @@
 #include <memory>
 #include <mutex>
 
+#ifdef LIBVINTF_TARGET
+#include <android-base/properties.h>
+#endif
+
 namespace android {
 namespace vintf {
 
@@ -58,10 +62,25 @@
 std::shared_ptr<const HalManifest> VintfObject::GetDeviceHalManifest(bool skipCache) {
     static LockedSharedPtr<HalManifest> gVendorManifest;
     static LockedSharedPtr<HalManifest> gOdmManifest;
+#ifdef LIBVINTF_TARGET
+    static LockedSharedPtr<HalManifest> gProductManifest;
+#endif
     static std::mutex gDeviceManifestMutex;
 
     std::unique_lock<std::mutex> _lock(gDeviceManifestMutex);
 
+#ifdef LIBVINTF_TARGET
+    std::string productModel = android::base::GetProperty("ro.product.model", "");
+    if (!productModel.empty()) {
+        auto product = Get(&gProductManifest, skipCache,
+                           std::bind(&HalManifest::fetchAllInformation, std::placeholders::_1,
+                                     "/odm/manifest_" + productModel + ".xml"));
+        if (product != nullptr) {
+            return product;
+        }
+    }
+#endif
+
     auto odm = Get(
         &gOdmManifest, skipCache,
         std::bind(&HalManifest::fetchAllInformation, std::placeholders::_1, "/odm/manifest.xml"));
diff --git a/test/Android.bp b/test/Android.bp
index 4849a63..ee1cf4f 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -60,4 +60,9 @@
         "-O0",
         "-g",
     ],
+    target: {
+        android: {
+            cflags: ["-DLIBVINTF_TARGET"],
+        },
+    }
 }
diff --git a/test/vintf_object_tests.cpp b/test/vintf_object_tests.cpp
index b206158..3033dfe 100644
--- a/test/vintf_object_tests.cpp
+++ b/test/vintf_object_tests.cpp
@@ -21,6 +21,10 @@
 #include <stdio.h>
 #include <unistd.h>
 
+#ifdef LIBVINTF_TARGET
+#include <android-base/properties.h>
+#endif
+
 #include "utils-fake.h"
 #include "vintf/VintfObject.h"
 
@@ -166,9 +170,14 @@
 // Setup the MockFileFetcher used by the fetchAllInformation template
 // so it returns the given metadata info instead of fetching from device.
 void setupMockFetcher(const std::string& vendorManifestXml, const std::string& systemMatrixXml,
-                      const std::string& systemManifestXml, const std::string& vendorMatrixXml) {
+                      const std::string& systemManifestXml, const std::string& vendorMatrixXml,
+                      const std::string& productModel) {
     MockFileFetcher* fetcher = static_cast<MockFileFetcher*>(gFetcher);
 
+    if (!productModel.empty()) {
+        ON_CALL(*fetcher, fetch(StrEq("/odm/manifest_" + productModel + ".xml"), _))
+            .WillByDefault(Return(::android::NAME_NOT_FOUND));
+    }
     ON_CALL(*fetcher, fetch(StrEq("/odm/manifest.xml"), _))
         .WillByDefault(Return(::android::NAME_NOT_FOUND));
     ON_CALL(*fetcher, fetch(StrEq("/vendor/manifest.xml"), _))
@@ -208,14 +217,17 @@
    protected:
     virtual void SetUp() {
         mounter().reset();
-        setupMockFetcher(vendorManifestXml1, systemMatrixXml1, systemManifestXml1,
-                         vendorMatrixXml1);
+#ifdef LIBVINTF_TARGET
+        productModel = android::base::GetProperty("ro.product.model", "");
+#endif
+        setupMockFetcher(vendorManifestXml1, systemMatrixXml1, systemManifestXml1, vendorMatrixXml1,
+                         productModel);
     }
     virtual void TearDown() {
         Mock::VerifyAndClear(&mounter());
         Mock::VerifyAndClear(&fetcher());
     }
-
+    std::string productModel;
 };
 
 // Tests that local info is checked.
@@ -223,6 +235,9 @@
     std::string error;
     std::vector<std::string> packageInfo;
 
+    if (!productModel.empty()) {
+        EXPECT_CALL(fetcher(), fetch(StrEq("/odm/manifest_" + productModel + ".xml"), _));
+    }
     EXPECT_CALL(fetcher(), fetch(StrEq("/odm/manifest.xml"), _));
     EXPECT_CALL(fetcher(), fetch(StrEq("/vendor/manifest.xml"), _));
     EXPECT_CALL(fetcher(), fetch(StrEq("/system/manifest.xml"), _));
@@ -263,6 +278,9 @@
     std::string error;
     std::vector<std::string> packageInfo = {systemMatrixXml1};
 
+    if (!productModel.empty()) {
+        EXPECT_CALL(fetcher(), fetch(StrEq("/odm/manifest_" + productModel + ".xml"), _));
+    }
     EXPECT_CALL(fetcher(), fetch(StrEq("/odm/manifest.xml"), _));
     EXPECT_CALL(fetcher(), fetch(StrEq("/vendor/manifest.xml"), _));
     EXPECT_CALL(fetcher(), fetch(StrEq("/system/manifest.xml"), _));
@@ -325,6 +343,9 @@
     std::string error;
     std::vector<std::string> packageInfo = {systemMatrixXml1, systemManifestXml1};
 
+    if (!productModel.empty()) {
+        EXPECT_CALL(fetcher(), fetch(StrEq("/odm/manifest_" + productModel + ".xml"), _));
+    }
     EXPECT_CALL(fetcher(), fetch(StrEq("/odm/manifest.xml"), _));
     EXPECT_CALL(fetcher(), fetch(StrEq("/vendor/manifest.xml"), _));
     EXPECT_CALL(fetcher(), fetch(StrEq("/system/manifest.xml"), _)).Times(0);
@@ -364,6 +385,9 @@
     std::vector<std::string> packageInfo = {systemMatrixXml1, systemManifestXml1,
             vendorMatrixXml1, vendorManifestXml1};
 
+    if (!productModel.empty()) {
+        EXPECT_CALL(fetcher(), fetch(StrEq("/odm/manifest_" + productModel + ".xml"), _)).Times(0);
+    }
     EXPECT_CALL(fetcher(), fetch(StrEq("/odm/manifest.xml"), _)).Times(0);
     EXPECT_CALL(fetcher(), fetch(StrEq("/vendor/manifest.xml"), _)).Times(0);
     EXPECT_CALL(fetcher(), fetch(StrEq("/system/manifest.xml"), _)).Times(0);
@@ -404,13 +428,17 @@
    protected:
     virtual void SetUp() {
         mounter().reset();
-        setupMockFetcher(vendorManifestXml1, systemMatrixXml2, systemManifestXml1,
-                         vendorMatrixXml1);
+#ifdef LIBVINTF_TARGET
+        productModel = android::base::GetProperty("ro.product.model", "");
+#endif
+        setupMockFetcher(vendorManifestXml1, systemMatrixXml2, systemManifestXml1, vendorMatrixXml1,
+                         productModel);
     }
     virtual void TearDown() {
         Mock::VerifyAndClear(&mounter());
         Mock::VerifyAndClear(&fetcher());
     }
+    std::string productModel;
 };
 
 // Fetch all metadata from device and ensure that it fails.
@@ -418,6 +446,9 @@
     std::string error;
     std::vector<std::string> packageInfo;
 
+    if (!productModel.empty()) {
+        EXPECT_CALL(fetcher(), fetch(StrEq("/odm/manifest_" + productModel + ".xml"), _));
+    }
     EXPECT_CALL(fetcher(), fetch(StrEq("/odm/manifest.xml"), _));
     EXPECT_CALL(fetcher(), fetch(StrEq("/vendor/manifest.xml"), _));
     EXPECT_CALL(fetcher(), fetch(StrEq("/system/manifest.xml"), _));
@@ -434,6 +465,9 @@
     std::string error;
     std::vector<std::string> packageInfo = {systemMatrixXml1};
 
+    if (!productModel.empty()) {
+        EXPECT_CALL(fetcher(), fetch(StrEq("/odm/manifest_" + productModel + ".xml"), _));
+    }
     EXPECT_CALL(fetcher(), fetch(StrEq("/odm/manifest.xml"), _));
     EXPECT_CALL(fetcher(), fetch(StrEq("/vendor/manifest.xml"), _));
     EXPECT_CALL(fetcher(), fetch(StrEq("/system/manifest.xml"), _));