Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1bd65bd0 authored by Tim Van Patten's avatar Tim Van Patten Committed by Android (Google) Code Review
Browse files

Merge "gpuservice: Add GPU Vendor ID support to FeatureConfig proto" into main

parents 0cbf130f 6340221c
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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",
+65 −5
Original line number Diff line number Diff line
@@ -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,13 +148,23 @@ 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);

        if (conditionsMet(vkJsonInstance, featureConfig)) {
            mFeatureOverrides.mGlobalFeatures.emplace_back(featureConfig);
        }
    }

    // App-specific feature overrides.
    for (auto const &pkgConfigProto: overridesProtos.package_features()) {
@@ -122,8 +180,10 @@ void FeatureOverrideParser::parseFeatureOverrides() {
            FeatureConfig featureConfig;
            initFeatureConfig(featureConfig, featureConfigProto);

            if (conditionsMet(vkJsonInstance, featureConfig)) {
                featureConfigs.emplace_back(featureConfig);
            }
        }

        mFeatureOverrides.mPackageFeatures[packageName] = featureConfigs;
    }
+29 −0
Original line number Diff line number Diff line
@@ -20,15 +20,44 @@ 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;
}

/**
+252 −2
Original line number Diff line number Diff line
@@ -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();

+50 −0
Original line number Diff line number Diff line
@@ -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
                ]
            }
        ]
    }
]