Merge "gpuservice: Add GPU Vendor ID support to FeatureConfig proto" into main
diff --git a/services/gpuservice/feature_override/Android.bp b/services/gpuservice/feature_override/Android.bp
index 3b5407b..842a0c4 100644
--- a/services/gpuservice/feature_override/Android.bp
+++ b/services/gpuservice/feature_override/Android.bp
@@ -69,6 +69,7 @@
     name: "libfeatureoverride",
     defaults: [
         "libfeatureoverride_deps",
+        "libvkjson_deps",
     ],
     srcs: [
         ":feature_config_proto_definitions",
@@ -85,6 +86,9 @@
     cppflags: [
         "-Wno-sign-compare",
     ],
+    static_libs: [
+        "libvkjson",
+    ],
     export_include_dirs: ["include"],
     proto: {
         type: "lite",
diff --git a/services/gpuservice/feature_override/FeatureOverrideParser.cpp b/services/gpuservice/feature_override/FeatureOverrideParser.cpp
index a16bfa8..26ff84a 100644
--- a/services/gpuservice/feature_override/FeatureOverrideParser.cpp
+++ b/services/gpuservice/feature_override/FeatureOverrideParser.cpp
@@ -23,8 +23,10 @@
 #include <sys/stat.h>
 #include <vector>
 
+#include <android-base/macros.h>
 #include <graphicsenv/FeatureOverrides.h>
 #include <log/log.h>
+#include <vkjson.h>
 
 #include "feature_config.pb.h"
 
@@ -35,13 +37,53 @@
     featureOverrides.mPackageFeatures.clear();
 }
 
+bool
+gpuVendorIdMatches(const VkJsonInstance &vkJsonInstance,
+               const uint32_t &configVendorId) {
+    if (vkJsonInstance.devices.empty()) {
+        return false;
+    }
+
+    // Always match the TEST Vendor ID
+    if (configVendorId == feature_override::GpuVendorID::VENDOR_ID_TEST) {
+        return true;
+    }
+
+    // Always assume one GPU device.
+    uint32_t vendorID = vkJsonInstance.devices.front().properties.vendorID;
+
+    return vendorID == configVendorId;
+}
+
+bool
+conditionsMet(const VkJsonInstance &vkJsonInstance,
+              const android::FeatureConfig &featureConfig) {
+    bool gpuVendorIdMatch = false;
+
+    if (featureConfig.mGpuVendorIDs.empty()) {
+        gpuVendorIdMatch = true;
+    } else {
+        for (const auto &gpuVendorID: featureConfig.mGpuVendorIDs) {
+            if (gpuVendorIdMatches(vkJsonInstance, gpuVendorID)) {
+                gpuVendorIdMatch = true;
+                break;
+            }
+        }
+    }
+
+    return gpuVendorIdMatch;
+}
+
 void initFeatureConfig(android::FeatureConfig &featureConfig,
                        const feature_override::FeatureConfig &featureConfigProto) {
     featureConfig.mFeatureName = featureConfigProto.feature_name();
     featureConfig.mEnabled = featureConfigProto.enabled();
+    for (const auto &gpuVendorIdProto: featureConfigProto.gpu_vendor_ids()) {
+        featureConfig.mGpuVendorIDs.emplace_back(static_cast<uint32_t>(gpuVendorIdProto));
+    }
 }
 
-feature_override::FeatureOverrideProtos readFeatureConfigProtos(std::string configFilePath) {
+feature_override::FeatureOverrideProtos readFeatureConfigProtos(const std::string &configFilePath) {
     feature_override::FeatureOverrideProtos overridesProtos;
 
     std::ifstream protobufBinaryFile(configFilePath.c_str());
@@ -78,9 +120,15 @@
 
 bool FeatureOverrideParser::shouldReloadFeatureOverrides() const {
     std::string configFilePath = getFeatureOverrideFilePath();
+
+    std::ifstream configFile(configFilePath);
+    if (!configFile.good()) {
+        return false;
+    }
+
     struct stat fileStat{};
-    if (stat(getFeatureOverrideFilePath().c_str(), &fileStat) != 0) {
-        ALOGE("Error getting file information for '%s': %s", getFeatureOverrideFilePath().c_str(),
+    if (stat(configFilePath.c_str(), &fileStat) != 0) {
+        ALOGE("Error getting file information for '%s': %s", configFilePath.c_str(),
               strerror(errno));
         // stat'ing the file failed, so return false since reading it will also likely fail.
         return false;
@@ -100,12 +148,22 @@
     // Clear out the stale values before adding the newly parsed data.
     resetFeatureOverrides(mFeatureOverrides);
 
+    if (overridesProtos.global_features().empty() &&
+        overridesProtos.package_features().empty()) {
+        // No overrides to parse.
+        return;
+    }
+
+    const VkJsonInstance vkJsonInstance = VkJsonGetInstance();
+
     // Global feature overrides.
     for (const auto &featureConfigProto: overridesProtos.global_features()) {
         FeatureConfig featureConfig;
         initFeatureConfig(featureConfig, featureConfigProto);
 
-        mFeatureOverrides.mGlobalFeatures.emplace_back(featureConfig);
+        if (conditionsMet(vkJsonInstance, featureConfig)) {
+            mFeatureOverrides.mGlobalFeatures.emplace_back(featureConfig);
+        }
     }
 
     // App-specific feature overrides.
@@ -122,7 +180,9 @@
             FeatureConfig featureConfig;
             initFeatureConfig(featureConfig, featureConfigProto);
 
-            featureConfigs.emplace_back(featureConfig);
+            if (conditionsMet(vkJsonInstance, featureConfig)) {
+                featureConfigs.emplace_back(featureConfig);
+            }
         }
 
         mFeatureOverrides.mPackageFeatures[packageName] = featureConfigs;
diff --git a/services/gpuservice/feature_override/proto/feature_config.proto b/services/gpuservice/feature_override/proto/feature_config.proto
index 4d4bf28..f285187 100644
--- a/services/gpuservice/feature_override/proto/feature_config.proto
+++ b/services/gpuservice/feature_override/proto/feature_config.proto
@@ -21,14 +21,43 @@
 option optimize_for = LITE_RUNTIME;
 
 /**
+ * GPU Vendor IDs.
+ * Taken from: external/angle/src/libANGLE/renderer/driver_utils.h
+ */
+enum GpuVendorID
+{
+    // Test ID matches every GPU Vendor ID.
+    VENDOR_ID_TEST = 0;
+    VENDOR_ID_AMD = 0x1002;
+    VENDOR_ID_ARM = 0x13B5;
+    // Broadcom devices won't use PCI, but this is their Vulkan vendor id.
+    VENDOR_ID_BROADCOM = 0x14E4;
+    VENDOR_ID_GOOGLE = 0x1AE0;
+    VENDOR_ID_INTEL = 0x8086;
+    VENDOR_ID_MESA = 0x10005;
+    VENDOR_ID_MICROSOFT = 0x1414;
+    VENDOR_ID_NVIDIA = 0x10DE;
+    VENDOR_ID_POWERVR = 0x1010;
+    // This is Qualcomm PCI Vendor ID.
+    // Android doesn't have a PCI bus, but all we need is a unique id.
+    VENDOR_ID_QUALCOMM = 0x5143;
+    VENDOR_ID_SAMSUNG = 0x144D;
+    VENDOR_ID_VIVANTE = 0x9999;
+    VENDOR_ID_VMWARE = 0x15AD;
+    VENDOR_ID_VIRTIO = 0x1AF4;
+}
+
+/**
  * Feature Configuration
  * feature_name: Feature name (see external/angle/include/platform/autogen/FeaturesVk_autogen.h).
  * enabled: Either enable or disable the feature.
+ * gpu_vendor_ids: The GPU architectures this FeatureConfig applies to, if any.
  */
 message FeatureConfig
 {
     string feature_name         = 1;
     bool enabled                = 2;
+    repeated GpuVendorID gpu_vendor_ids = 3;
 }
 
 /**
diff --git a/services/gpuservice/tests/unittests/FeatureOverrideParserTest.cpp b/services/gpuservice/tests/unittests/FeatureOverrideParserTest.cpp
index 65a1b58..66556cd 100644
--- a/services/gpuservice/tests/unittests/FeatureOverrideParserTest.cpp
+++ b/services/gpuservice/tests/unittests/FeatureOverrideParserTest.cpp
@@ -70,14 +70,14 @@
 };
 
 testing::AssertionResult validateFeatureConfigTestTxtpbSizes(FeatureOverrides overrides) {
-    size_t expectedGlobalFeaturesSize = 1;
+    size_t expectedGlobalFeaturesSize = 3;
     if (overrides.mGlobalFeatures.size() != expectedGlobalFeaturesSize) {
         return testing::AssertionFailure()
                 << "overrides.mGlobalFeatures.size(): " << overrides.mGlobalFeatures.size()
                 << ", expected: " << expectedGlobalFeaturesSize;
     }
 
-    size_t expectedPackageFeaturesSize = 1;
+    size_t expectedPackageFeaturesSize = 3;
     if (overrides.mPackageFeatures.size() != expectedPackageFeaturesSize) {
         return testing::AssertionFailure()
                 << "overrides.mPackageFeatures.size(): " << overrides.mPackageFeatures.size()
@@ -133,6 +133,96 @@
     EXPECT_TRUE(validateGlobalOverrides1(overrides));
 }
 
+testing::AssertionResult validateGlobalOverrides2(FeatureOverrides overrides) {
+    const int kTestFeatureIndex = 1;
+    const std::string expectedFeatureName = "globalOverrides2";
+    const FeatureConfig &cfg = overrides.mGlobalFeatures[kTestFeatureIndex];
+
+    if (cfg.mFeatureName != expectedFeatureName) {
+        return testing::AssertionFailure()
+                << "cfg.mFeatureName: " << cfg.mFeatureName
+                << ", expected: " << expectedFeatureName;
+    }
+
+    bool expectedEnabled = true;
+    if (cfg.mEnabled != expectedEnabled) {
+        return testing::AssertionFailure()
+                << "cfg.mEnabled: " << cfg.mEnabled
+                << ", expected: " << expectedEnabled;
+    }
+
+    std::vector<uint32_t> expectedGpuVendorIDs = {
+        0,      // GpuVendorID::VENDOR_ID_TEST
+        0x13B5, // GpuVendorID::VENDOR_ID_ARM
+    };
+    if (cfg.mGpuVendorIDs.size() != expectedGpuVendorIDs.size()) {
+        return testing::AssertionFailure()
+                << "cfg.mGpuVendorIDs.size(): " << cfg.mGpuVendorIDs.size()
+                << ", expected: " << expectedGpuVendorIDs.size();
+    }
+    for (int i = 0; i < expectedGpuVendorIDs.size(); i++) {
+        if (cfg.mGpuVendorIDs[i] != expectedGpuVendorIDs[i]) {
+            std::stringstream msg;
+            msg << "cfg.mGpuVendorIDs[" << i << "]: 0x" << std::hex << cfg.mGpuVendorIDs[i]
+                << ", expected: 0x" << std::hex << expectedGpuVendorIDs[i];
+            return testing::AssertionFailure() << msg.str();
+        }
+    }
+
+    return testing::AssertionSuccess();
+}
+
+TEST_F(FeatureOverrideParserTest, globalOverrides2) {
+    FeatureOverrides overrides = mFeatureOverrideParser.getFeatureOverrides();
+
+    EXPECT_TRUE(validateGlobalOverrides2(overrides));
+}
+
+testing::AssertionResult validateGlobalOverrides3(FeatureOverrides overrides) {
+    const int kTestFeatureIndex = 2;
+    const std::string expectedFeatureName = "globalOverrides3";
+    const FeatureConfig &cfg = overrides.mGlobalFeatures[kTestFeatureIndex];
+
+    if (cfg.mFeatureName != expectedFeatureName) {
+        return testing::AssertionFailure()
+                << "cfg.mFeatureName: " << cfg.mFeatureName
+                << ", expected: " << expectedFeatureName;
+    }
+
+    bool expectedEnabled = true;
+    if (cfg.mEnabled != expectedEnabled) {
+        return testing::AssertionFailure()
+                << "cfg.mEnabled: " << cfg.mEnabled
+                << ", expected: " << expectedEnabled;
+    }
+
+    std::vector<uint32_t> expectedGpuVendorIDs = {
+            0,      // GpuVendorID::VENDOR_ID_TEST
+            0x8086, // GpuVendorID::VENDOR_ID_INTEL
+    };
+    if (cfg.mGpuVendorIDs.size() != expectedGpuVendorIDs.size()) {
+        return testing::AssertionFailure()
+                << "cfg.mGpuVendorIDs.size(): " << cfg.mGpuVendorIDs.size()
+                << ", expected: " << expectedGpuVendorIDs.size();
+    }
+    for (int i = 0; i < expectedGpuVendorIDs.size(); i++) {
+        if (cfg.mGpuVendorIDs[i] != expectedGpuVendorIDs[i]) {
+            std::stringstream msg;
+            msg << "cfg.mGpuVendorIDs[" << i << "]: 0x" << std::hex << cfg.mGpuVendorIDs[i]
+                << ", expected: 0x" << std::hex << expectedGpuVendorIDs[i];
+            return testing::AssertionFailure() << msg.str();
+        }
+    }
+
+    return testing::AssertionSuccess();
+}
+
+TEST_F(FeatureOverrideParserTest, globalOverrides3) {
+FeatureOverrides overrides = mFeatureOverrideParser.getFeatureOverrides();
+
+EXPECT_TRUE(validateGlobalOverrides3(overrides));
+}
+
 testing::AssertionResult validatePackageOverrides1(FeatureOverrides overrides) {
     const std::string expectedTestPackageName = "com.gpuservice_unittest.packageOverrides1";
 
@@ -155,6 +245,12 @@
     const std::string expectedFeatureName = "packageOverrides1";
     const FeatureConfig &cfg = features[0];
 
+    if (cfg.mFeatureName != expectedFeatureName) {
+        return testing::AssertionFailure()
+                << "cfg.mFeatureName: " << cfg.mFeatureName
+                << ", expected: " << expectedFeatureName;
+    }
+
     bool expectedEnabled = true;
     if (cfg.mEnabled != expectedEnabled) {
         return testing::AssertionFailure()
@@ -193,6 +289,160 @@
     return testing::AssertionSuccess();
 }
 
+testing::AssertionResult validatePackageOverrides2(FeatureOverrides overrides) {
+    const std::string expectedPackageName = "com.gpuservice_unittest.packageOverrides2";
+
+    if (!overrides.mPackageFeatures.count(expectedPackageName)) {
+        return testing::AssertionFailure()
+                << "overrides.mPackageFeatures missing expected package: " << expectedPackageName;
+    }
+
+    const std::vector<FeatureConfig>& features = overrides.mPackageFeatures[expectedPackageName];
+
+    size_t expectedFeaturesSize = 1;
+    if (features.size() != expectedFeaturesSize) {
+        return testing::AssertionFailure()
+                << "features.size(): " << features.size()
+                << ", expectedFeaturesSize: " << expectedFeaturesSize;
+    }
+
+    const std::string expectedFeatureName = "packageOverrides2";
+    const FeatureConfig &cfg = features[0];
+
+    if (cfg.mFeatureName != expectedFeatureName) {
+        return testing::AssertionFailure()
+                << "cfg.mFeatureName: " << cfg.mFeatureName
+                << ", expected: " << expectedFeatureName;
+    }
+
+    bool expectedEnabled = false;
+    if (cfg.mEnabled != expectedEnabled) {
+        return testing::AssertionFailure()
+                << "cfg.mEnabled: " << cfg.mEnabled
+                << ", expected: " << expectedEnabled;
+    }
+
+    std::vector<uint32_t> expectedGpuVendorIDs = {
+            0,      // GpuVendorID::VENDOR_ID_TEST
+            0x8086, // GpuVendorID::VENDOR_ID_INTEL
+    };
+    if (cfg.mGpuVendorIDs.size() != expectedGpuVendorIDs.size()) {
+        return testing::AssertionFailure()
+                << "cfg.mGpuVendorIDs.size(): " << cfg.mGpuVendorIDs.size()
+                << ", expected: " << expectedGpuVendorIDs.size();
+    }
+    for (int i = 0; i < expectedGpuVendorIDs.size(); i++) {
+        if (cfg.mGpuVendorIDs[i] != expectedGpuVendorIDs[i]) {
+            std::stringstream msg;
+            msg << "cfg.mGpuVendorIDs[" << i << "]: 0x" << std::hex << cfg.mGpuVendorIDs[i]
+                << ", expected: 0x" << std::hex << expectedGpuVendorIDs[i];
+            return testing::AssertionFailure() << msg.str();
+        }
+    }
+
+    return testing::AssertionSuccess();
+}
+
+TEST_F(FeatureOverrideParserTest, packageOverrides2) {
+    FeatureOverrides overrides = mFeatureOverrideParser.getFeatureOverrides();
+
+    EXPECT_TRUE(validatePackageOverrides2(overrides));
+}
+
+testing::AssertionResult validatePackageOverrides3(FeatureOverrides overrides) {
+    const std::string expectedPackageName = "com.gpuservice_unittest.packageOverrides3";
+
+    if (!overrides.mPackageFeatures.count(expectedPackageName)) {
+        return testing::AssertionFailure()
+                << "overrides.mPackageFeatures missing expected package: " << expectedPackageName;
+    }
+
+    const std::vector<FeatureConfig>& features = overrides.mPackageFeatures[expectedPackageName];
+
+    size_t expectedFeaturesSize = 2;
+    if (features.size() != expectedFeaturesSize) {
+        return testing::AssertionFailure()
+                << "features.size(): " << features.size()
+                << ", expectedFeaturesSize: " << expectedFeaturesSize;
+    }
+
+    std::string expectedFeatureName = "packageOverrides3_1";
+    const FeatureConfig &cfg_1 = features[0];
+
+    if (cfg_1.mFeatureName != expectedFeatureName) {
+        return testing::AssertionFailure()
+                << "cfg.mFeatureName: " << cfg_1.mFeatureName
+                << ", expected: " << expectedFeatureName;
+    }
+
+    bool expectedEnabled = false;
+    if (cfg_1.mEnabled != expectedEnabled) {
+        return testing::AssertionFailure()
+                << "cfg.mEnabled: " << cfg_1.mEnabled
+                << ", expected: " << expectedEnabled;
+    }
+
+    std::vector<uint32_t> expectedGpuVendorIDs = {
+            0,      // GpuVendorID::VENDOR_ID_TEST
+            0x13B5, // GpuVendorID::VENDOR_ID_ARM
+    };
+    if (cfg_1.mGpuVendorIDs.size() != expectedGpuVendorIDs.size()) {
+        return testing::AssertionFailure()
+                << "cfg.mGpuVendorIDs.size(): " << cfg_1.mGpuVendorIDs.size()
+                << ", expected: " << expectedGpuVendorIDs.size();
+    }
+    for (int i = 0; i < expectedGpuVendorIDs.size(); i++) {
+        if (cfg_1.mGpuVendorIDs[i] != expectedGpuVendorIDs[i]) {
+            std::stringstream msg;
+            msg << "cfg.mGpuVendorIDs[" << i << "]: 0x" << std::hex << cfg_1.mGpuVendorIDs[i]
+                << ", expected: 0x" << std::hex << expectedGpuVendorIDs[i];
+            return testing::AssertionFailure() << msg.str();
+        }
+    }
+
+    expectedFeatureName = "packageOverrides3_2";
+    const FeatureConfig &cfg_2 = features[1];
+
+    if (cfg_2.mFeatureName != expectedFeatureName) {
+        return testing::AssertionFailure()
+                << "cfg.mFeatureName: " << cfg_2.mFeatureName
+                << ", expected: " << expectedFeatureName;
+    }
+
+    expectedEnabled = true;
+    if (cfg_2.mEnabled != expectedEnabled) {
+        return testing::AssertionFailure()
+                << "cfg.mEnabled: " << cfg_2.mEnabled
+                << ", expected: " << expectedEnabled;
+    }
+
+    expectedGpuVendorIDs = {
+            0,      // GpuVendorID::VENDOR_ID_TEST
+            0x8086, // GpuVendorID::VENDOR_ID_INTEL
+    };
+    if (cfg_2.mGpuVendorIDs.size() != expectedGpuVendorIDs.size()) {
+        return testing::AssertionFailure()
+                << "cfg.mGpuVendorIDs.size(): " << cfg_2.mGpuVendorIDs.size()
+                << ", expected: " << expectedGpuVendorIDs.size();
+    }
+    for (int i = 0; i < expectedGpuVendorIDs.size(); i++) {
+        if (cfg_2.mGpuVendorIDs[i] != expectedGpuVendorIDs[i]) {
+            std::stringstream msg;
+            msg << "cfg.mGpuVendorIDs[" << i << "]: 0x" << std::hex << cfg_2.mGpuVendorIDs[i]
+                << ", expected: 0x" << std::hex << expectedGpuVendorIDs[i];
+            return testing::AssertionFailure() << msg.str();
+        }
+    }
+
+    return testing::AssertionSuccess();
+}
+
+TEST_F(FeatureOverrideParserTest, packageOverrides3) {
+FeatureOverrides overrides = mFeatureOverrideParser.getFeatureOverrides();
+
+EXPECT_TRUE(validatePackageOverrides3(overrides));
+}
+
 TEST_F(FeatureOverrideParserTest, forceFileRead) {
     FeatureOverrides overrides = mFeatureOverrideParser.getFeatureOverrides();
 
diff --git a/services/gpuservice/tests/unittests/data/feature_config_test.txtpb b/services/gpuservice/tests/unittests/data/feature_config_test.txtpb
index 726779e..44a6f78 100644
--- a/services/gpuservice/tests/unittests/data/feature_config_test.txtpb
+++ b/services/gpuservice/tests/unittests/data/feature_config_test.txtpb
@@ -22,6 +22,22 @@
     {
         feature_name: "globalOverrides1"
         enabled: False
+    },
+    {
+        feature_name: "globalOverrides2"
+        enabled: True
+        gpu_vendor_ids: [
+            VENDOR_ID_TEST, # Match every GPU Vendor ID, so the feature isn't dropped when parsed.
+            VENDOR_ID_ARM
+        ]
+    },
+    {
+        feature_name: "globalOverrides3"
+        enabled: True
+        gpu_vendor_ids: [
+            VENDOR_ID_TEST, # Match every GPU Vendor ID, so the feature isn't dropped when parsed.
+            VENDOR_ID_INTEL
+        ]
     }
 ]
 
@@ -36,5 +52,39 @@
                 enabled: True
             }
         ]
+    },
+    {
+        package_name: "com.gpuservice_unittest.packageOverrides2"
+        feature_configs: [
+            {
+                feature_name: "packageOverrides2"
+                enabled: False
+                gpu_vendor_ids: [
+                    VENDOR_ID_TEST, # Match every GPU Vendor ID, so the feature isn't dropped when parsed.
+                    VENDOR_ID_INTEL
+                ]
+            }
+        ]
+    },
+    {
+        package_name: "com.gpuservice_unittest.packageOverrides3"
+        feature_configs: [
+            {
+                feature_name: "packageOverrides3_1"
+                enabled: False
+                gpu_vendor_ids: [
+                    VENDOR_ID_TEST, # Match every GPU Vendor ID, so the feature isn't dropped when parsed.
+                    VENDOR_ID_ARM
+                ]
+            },
+            {
+                feature_name: "packageOverrides3_2"
+                enabled: True
+                gpu_vendor_ids: [
+                    VENDOR_ID_TEST, # Match every GPU Vendor ID, so the feature isn't dropped when parsed.
+                    VENDOR_ID_INTEL
+                ]
+            }
+        ]
     }
 ]