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

Commit c2127c7d authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "GpuService: Add FeatureOverrideParser" into main

parents 88c634d2 8e518c0c
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -19,10 +19,16 @@ cc_defaults {
    ],
}

cc_aconfig_library {
    name: "gpuservice_flags_c_lib",
    aconfig_declarations: "graphicsenv_flags",
}

cc_defaults {
    name: "libgpuservice_defaults",
    defaults: [
        "gpuservice_defaults",
        "libfeatureoverride_deps",
        "libgfxstats_deps",
        "libgpumem_deps",
        "libgpumemtracer_deps",
@@ -40,8 +46,11 @@ cc_defaults {
        "libgraphicsenv",
        "liblog",
        "libutils",
        "server_configurable_flags",
    ],
    static_libs: [
        "gpuservice_flags_c_lib",
        "libfeatureoverride",
        "libgfxstats",
        "libgpumem",
        "libgpumemtracer",
+98 −0
Original line number Diff line number Diff line
// Copyright 2024 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 {
    // See: http://go/android-license-faq
    // A large-scale-change added 'default_applicable_licenses' to import
    // all of the 'license_kinds' from "frameworks_native_license"
    // to get the below license kinds:
    //   SPDX-license-identifier-Apache-2.0
    default_applicable_licenses: ["frameworks_native_license"],
}

cc_defaults {
    name: "libfeatureoverride_deps",
    include_dirs: [
        "external/protobuf",
        "external/protobuf/src",
    ],
    header_libs: [
        "libbase_headers",
    ],
    shared_libs: [
        "libbase",
        "libgraphicsenv",
        "liblog",
    ],
    static_libs: [
        "libprotobuf-cpp-lite-ndk",
    ],
}

filegroup {
    name: "feature_config_proto_definitions",
    srcs: [
        "proto/feature_config.proto",
    ],
}

genrule {
    name: "feature_config_proto_lite_gen_headers",
    srcs: [
        ":feature_config_proto_definitions",
    ],
    tools: [
        "aprotoc",
    ],
    cmd: "$(location aprotoc) " +
        "--proto_path=frameworks/native/services/gpuservice/feature_override " +
        "--cpp_out=lite=true:$(genDir)/frameworks/native/services/gpuservice/feature_override " +
        "$(locations :feature_config_proto_definitions)",
    out: [
        "frameworks/native/services/gpuservice/feature_override/proto/feature_config.pb.h",
    ],
    export_include_dirs: [
        "frameworks/native/services/gpuservice/feature_override/proto/",
    ],
}

cc_library_static {
    name: "libfeatureoverride",
    defaults: [
        "libfeatureoverride_deps",
    ],
    srcs: [
        ":feature_config_proto_definitions",
        "FeatureOverrideParser.cpp",
    ],
    local_include_dirs: [
        "include",
    ],
    cflags: [
        "-Wall",
        "-Werror",
        "-Wimplicit-fallthrough",
    ],
    cppflags: [
        "-Wno-sign-compare",
    ],
    export_include_dirs: ["include"],
    proto: {
        type: "lite",
        static: true,
    },
    generated_headers: [
        "feature_config_proto_lite_gen_headers",
    ],
}
+141 −0
Original line number Diff line number Diff line
/*
 * Copyright 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.
 */

#include <feature_override/FeatureOverrideParser.h>

#include <chrono>
#include <fstream>
#include <sstream>
#include <string>
#include <sys/stat.h>
#include <vector>

#include <graphicsenv/FeatureOverrides.h>
#include <log/log.h>

#include "feature_config.pb.h"

namespace {

void resetFeatureOverrides(android::FeatureOverrides &featureOverrides) {
    featureOverrides.mGlobalFeatures.clear();
    featureOverrides.mPackageFeatures.clear();
}

void initFeatureConfig(android::FeatureConfig &featureConfig,
                       const feature_override::FeatureConfig &featureConfigProto) {
    featureConfig.mFeatureName = featureConfigProto.feature_name();
    featureConfig.mEnabled = featureConfigProto.enabled();
}

feature_override::FeatureOverrideProtos readFeatureConfigProtos(std::string configFilePath) {
    feature_override::FeatureOverrideProtos overridesProtos;

    std::ifstream protobufBinaryFile(configFilePath.c_str());
    if (protobufBinaryFile.fail()) {
        ALOGE("Failed to open feature config file: `%s`.", configFilePath.c_str());
        return overridesProtos;
    }

    std::stringstream buffer;
    buffer << protobufBinaryFile.rdbuf();
    std::string serializedConfig = buffer.str();
    std::vector<uint8_t> serialized(
            reinterpret_cast<const uint8_t *>(serializedConfig.data()),
            reinterpret_cast<const uint8_t *>(serializedConfig.data()) +
            serializedConfig.size());

    if (!overridesProtos.ParseFromArray(serialized.data(),
                                        static_cast<int>(serialized.size()))) {
        ALOGE("Failed to parse GpuConfig protobuf data.");
    }

    return overridesProtos;
}

} // namespace

namespace android {

std::string FeatureOverrideParser::getFeatureOverrideFilePath() const {
    const std::string kConfigFilePath = "/system/etc/angle/feature_config_vk.binarypb";

    return kConfigFilePath;
}

bool FeatureOverrideParser::shouldReloadFeatureOverrides() const {
    std::string configFilePath = getFeatureOverrideFilePath();
    struct stat fileStat{};
    if (stat(getFeatureOverrideFilePath().c_str(), &fileStat) != 0) {
        ALOGE("Error getting file information for '%s': %s", getFeatureOverrideFilePath().c_str(),
              strerror(errno));
        // stat'ing the file failed, so return false since reading it will also likely fail.
        return false;
    }

    return fileStat.st_mtime > mLastProtobufReadTime;
}

void FeatureOverrideParser::forceFileRead() {
    resetFeatureOverrides(mFeatureOverrides);
    mLastProtobufReadTime = 0;
}

void FeatureOverrideParser::parseFeatureOverrides() {
    const feature_override::FeatureOverrideProtos overridesProtos = readFeatureConfigProtos(
            getFeatureOverrideFilePath());

    // Global feature overrides.
    for (const auto &featureConfigProto: overridesProtos.global_features()) {
        FeatureConfig featureConfig;
        initFeatureConfig(featureConfig, featureConfigProto);

        mFeatureOverrides.mGlobalFeatures.emplace_back(featureConfig);
    }

    // App-specific feature overrides.
    for (auto const &pkgConfigProto: overridesProtos.package_features()) {
        const std::string &packageName = pkgConfigProto.package_name();

        if (mFeatureOverrides.mPackageFeatures.count(packageName)) {
            ALOGE("Package already has feature overrides! Skipping.");
            continue;
        }

        std::vector<FeatureConfig> featureConfigs;
        for (const auto &featureConfigProto: pkgConfigProto.feature_configs()) {
            FeatureConfig featureConfig;
            initFeatureConfig(featureConfig, featureConfigProto);

            featureConfigs.emplace_back(featureConfig);
        }

        mFeatureOverrides.mPackageFeatures[packageName] = featureConfigs;
    }

    mLastProtobufReadTime = std::chrono::system_clock::to_time_t(
            std::chrono::system_clock::now());
}

FeatureOverrides FeatureOverrideParser::getFeatureOverrides() {
    if (shouldReloadFeatureOverrides()) {
        parseFeatureOverrides();
    }

    return mFeatureOverrides;
}

} // namespace android
+49 −0
Original line number Diff line number Diff line
/*
 * Copyright 2024 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.
 */

#ifndef FEATURE_OVERRIDE_PARSER_H_
#define FEATURE_OVERRIDE_PARSER_H_

#include <ctime>
#include <string>
#include <vector>

#include <graphicsenv/FeatureOverrides.h>

namespace android {

class FeatureOverrideParser {
public:
    FeatureOverrideParser() = default;
    FeatureOverrideParser(const FeatureOverrideParser &) = default;
    virtual ~FeatureOverrideParser() = default;

    FeatureOverrides getFeatureOverrides();
    void forceFileRead();

private:
    bool shouldReloadFeatureOverrides() const;
    void parseFeatureOverrides();
    // Allow FeatureOverrideParserMock to override with the unit test file's path.
    virtual std::string getFeatureOverrideFilePath() const;

    std::time_t mLastProtobufReadTime = 0;
    FeatureOverrides mFeatureOverrides;
};

} // namespace android

#endif  // FEATURE_OVERRIDE_PARSER_H_
+53 −0
Original line number Diff line number Diff line
/*
 * Copyright 2024 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.
 */

syntax = "proto3";

package feature_override;

option optimize_for = LITE_RUNTIME;

/**
 * Feature Configuration
 * feature_name: Feature name (see external/angle/include/platform/autogen/FeaturesVk_autogen.h).
 * enabled: Either enable or disable the feature.
 */
message FeatureConfig
{
    string feature_name         = 1;
    bool enabled                = 2;
}

/**
 * Package Configuration
 * feature_configs: List of features configs for the package.
 */
message PackageConfig
{
    string package_name                    = 1;
    repeated FeatureConfig feature_configs = 2;
}

/**
 * Feature Overrides
 * global_features: Features to apply globally, for every package.
 * package_features: Features to apply for individual packages.
 */
message FeatureOverrideProtos
{
    repeated FeatureConfig global_features  = 1;
    repeated PackageConfig package_features = 2;
}
Loading