diff options
author | 2025-03-04 10:07:38 -0800 | |
---|---|---|
committer | 2025-03-04 10:07:38 -0800 | |
commit | 1bd65bd06b4951309508a8029a8b3acbfd5d7188 (patch) | |
tree | 335685357bd8928ec03429c491c0224cc776d6cb | |
parent | 0cbf130fa53be50f8d86beba9ec1865a10e1b37e (diff) | |
parent | 6340221c9a35d91e2301ff96c564e46aa9f2e910 (diff) |
Merge "gpuservice: Add GPU Vendor ID support to FeatureConfig proto" into main
5 files changed, 400 insertions, 7 deletions
diff --git a/services/gpuservice/feature_override/Android.bp b/services/gpuservice/feature_override/Android.bp index 3b5407bdd3..842a0c46d2 100644 --- a/services/gpuservice/feature_override/Android.bp +++ b/services/gpuservice/feature_override/Android.bp @@ -69,6 +69,7 @@ cc_library_static { name: "libfeatureoverride", defaults: [ "libfeatureoverride_deps", + "libvkjson_deps", ], srcs: [ ":feature_config_proto_definitions", @@ -85,6 +86,9 @@ cc_library_static { 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 a16bfa8b35..26ff84a34c 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 @@ void resetFeatureOverrides(android::FeatureOverrides &featureOverrides) { 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 @@ std::string FeatureOverrideParser::getFeatureOverrideFilePath() const { 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 @@ void FeatureOverrideParser::parseFeatureOverrides() { // 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 @@ void FeatureOverrideParser::parseFeatureOverrides() { 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 4d4bf289f1..f28518778f 100644 --- a/services/gpuservice/feature_override/proto/feature_config.proto +++ b/services/gpuservice/feature_override/proto/feature_config.proto @@ -21,14 +21,43 @@ package feature_override; 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 65a1b58dc3..66556cd2d0 100644 --- a/services/gpuservice/tests/unittests/FeatureOverrideParserTest.cpp +++ b/services/gpuservice/tests/unittests/FeatureOverrideParserTest.cpp @@ -70,14 +70,14 @@ public: }; 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 @@ TEST_F(FeatureOverrideParserTest, globalOverrides1) { 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 @@ testing::AssertionResult validatePackageOverrides1(FeatureOverrides overrides) { 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 @@ testing::AssertionResult validateForceFileRead(FeatureOverrides overrides) { 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 726779e332..44a6f78e84 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 @@ global_features [ { 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 @@ package_features [ 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 + ] + } + ] } ] |