diff options
Diffstat (limited to 'services/surfaceflinger/FlagManager.cpp')
| -rw-r--r-- | services/surfaceflinger/FlagManager.cpp | 175 |
1 files changed, 122 insertions, 53 deletions
diff --git a/services/surfaceflinger/FlagManager.cpp b/services/surfaceflinger/FlagManager.cpp index f8ad8f6941..a8f05bbd56 100644 --- a/services/surfaceflinger/FlagManager.cpp +++ b/services/surfaceflinger/FlagManager.cpp @@ -26,37 +26,21 @@ #include <server_configurable_flags/get_flags.h> #include <cinttypes> +#include <com_android_graphics_surfaceflinger_flags.h> + namespace android { +using namespace com::android::graphics::surfaceflinger; + static constexpr const char* kExperimentNamespace = "surface_flinger_native_boot"; -static constexpr const int64_t kDemoFlag = -1; -FlagManager::~FlagManager() = default; +std::unique_ptr<FlagManager> FlagManager::mInstance; +std::once_flag FlagManager::mOnce; -void FlagManager::dump(std::string& result) const { - base::StringAppendF(&result, "FlagManager values: \n"); - base::StringAppendF(&result, "demo_flag: %" PRId64 "\n", demo_flag()); - base::StringAppendF(&result, "use_adpf_cpu_hint: %s\n", use_adpf_cpu_hint() ? "true" : "false"); - base::StringAppendF(&result, "use_skia_tracing: %s\n", use_skia_tracing() ? "true" : "false"); -} +FlagManager::FlagManager(ConstructorTag) {} +FlagManager::~FlagManager() = default; namespace { -template <typename T> -std::optional<T> doParse(const char* str); - -template <> -[[maybe_unused]] std::optional<int32_t> doParse(const char* str) { - int32_t ret; - return base::ParseInt(str, &ret) ? std::make_optional(ret) : std::nullopt; -} - -template <> -[[maybe_unused]] std::optional<int64_t> doParse(const char* str) { - int64_t ret; - return base::ParseInt(str, &ret) ? std::make_optional(ret) : std::nullopt; -} - -template <> -[[maybe_unused]] std::optional<bool> doParse(const char* str) { +std::optional<bool> parseBool(const char* str) { base::ParseBoolResult parseResult = base::ParseBool(str); switch (parseResult) { case base::ParseBoolResult::kTrue: @@ -67,44 +51,129 @@ template <> return std::nullopt; } } + +bool getFlagValue(std::function<bool()> getter, std::optional<bool> overrideValue) { + if (overrideValue.has_value()) { + return *overrideValue; + } + + return getter(); +} + +void dumpFlag(std::string& result, const char* name, std::function<bool()> getter) { + base::StringAppendF(&result, "%s: %s\n", name, getter() ? "true" : "false"); +} + } // namespace -std::string FlagManager::getServerConfigurableFlag(const std::string& experimentFlagName) const { - return server_configurable_flags::GetServerConfigurableFlag(kExperimentNamespace, - experimentFlagName, ""); +const FlagManager& FlagManager::getInstance() { + return getMutableInstance(); } -template int32_t FlagManager::getValue<int32_t>(const std::string&, std::optional<int32_t>, - int32_t) const; -template int64_t FlagManager::getValue<int64_t>(const std::string&, std::optional<int64_t>, - int64_t) const; -template bool FlagManager::getValue<bool>(const std::string&, std::optional<bool>, bool) const; -template <typename T> -T FlagManager::getValue(const std::string& experimentFlagName, std::optional<T> systemPropertyOpt, - T defaultValue) const { - // System property takes precedence over the experiment config server value. - if (systemPropertyOpt.has_value()) { - return *systemPropertyOpt; - } - std::string str = getServerConfigurableFlag(experimentFlagName); - return str.empty() ? defaultValue : doParse<T>(str.c_str()).value_or(defaultValue); +FlagManager& FlagManager::getMutableInstance() { + std::call_once(mOnce, [&] { + LOG_ALWAYS_FATAL_IF(mInstance, "Instance already created"); + mInstance = std::make_unique<FlagManager>(ConstructorTag{}); + }); + + return *mInstance; } -int64_t FlagManager::demo_flag() const { - std::optional<int64_t> sysPropVal = std::nullopt; - return getValue("DemoFeature__demo_flag", sysPropVal, kDemoFlag); +void FlagManager::markBootCompleted() { + mBootCompleted = true; } -bool FlagManager::use_adpf_cpu_hint() const { - std::optional<bool> sysPropVal = - doParse<bool>(base::GetProperty("debug.sf.enable_adpf_cpu_hint", "").c_str()); - return getValue("AdpfFeature__adpf_cpu_hint", sysPropVal, false); +void FlagManager::setUnitTestMode() { + mUnitTestMode = true; + + // Also set boot completed as we don't really care about it in unit testing + mBootCompleted = true; +} + +void FlagManager::dump(std::string& result) const { +#define DUMP_FLAG(name) dumpFlag(result, #name, std::bind(&FlagManager::name, this)) + + base::StringAppendF(&result, "FlagManager values: \n"); + DUMP_FLAG(use_adpf_cpu_hint); + DUMP_FLAG(use_skia_tracing); + DUMP_FLAG(connected_display); + DUMP_FLAG(dont_skip_on_early); + DUMP_FLAG(enable_small_area_detection); + DUMP_FLAG(misc1); + DUMP_FLAG(late_boot_misc2); + DUMP_FLAG(vrr_config); + +#undef DUMP_FLAG +} + +std::optional<bool> FlagManager::getBoolProperty(const char* property) const { + return parseBool(base::GetProperty(property, "").c_str()); +} + +bool FlagManager::getServerConfigurableFlag(const char* experimentFlagName) const { + const auto value = server_configurable_flags::GetServerConfigurableFlag(kExperimentNamespace, + experimentFlagName, ""); + const auto res = parseBool(value.c_str()); + return res.has_value() && res.value(); } -bool FlagManager::use_skia_tracing() const { - std::optional<bool> sysPropVal = - doParse<bool>(base::GetProperty(PROPERTY_SKIA_ATRACE_ENABLED, "").c_str()); - return getValue("SkiaTracingFeature__use_skia_tracing", sysPropVal, false); +#define FLAG_MANAGER_LEGACY_SERVER_FLAG(name, syspropOverride, serverFlagName) \ + bool FlagManager::name() const { \ + LOG_ALWAYS_FATAL_IF(!mBootCompleted, \ + "Can't read %s before boot completed as it is server writable", \ + __func__); \ + const auto debugOverride = getBoolProperty(syspropOverride); \ + if (debugOverride.has_value()) return debugOverride.value(); \ + return getServerConfigurableFlag(serverFlagName); \ + } + +#define FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, checkForBootCompleted) \ + bool FlagManager::name() const { \ + if (checkForBootCompleted) { \ + LOG_ALWAYS_FATAL_IF(!mBootCompleted, \ + "Can't read %s before boot completed as it is server writable", \ + __func__); \ + } \ + static std::optional<bool> debugOverride = getBoolProperty(syspropOverride); \ + static bool value = getFlagValue([] { return flags::name(); }, debugOverride); \ + if (mUnitTestMode) { \ + /* \ + * When testing, we don't want to rely on the cached values stored in the static \ + * variables. \ + */ \ + debugOverride = getBoolProperty(syspropOverride); \ + value = getFlagValue([] { return flags::name(); }, debugOverride); \ + } \ + return value; \ + } + +#define FLAG_MANAGER_SERVER_FLAG(name, syspropOverride) \ + FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, true) + +#define FLAG_MANAGER_READ_ONLY_FLAG(name, syspropOverride) \ + FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, false) + +/// Legacy server flags /// +FLAG_MANAGER_LEGACY_SERVER_FLAG(test_flag, "", "") +FLAG_MANAGER_LEGACY_SERVER_FLAG(use_adpf_cpu_hint, "debug.sf.enable_adpf_cpu_hint", + "AdpfFeature__adpf_cpu_hint") +FLAG_MANAGER_LEGACY_SERVER_FLAG(use_skia_tracing, PROPERTY_SKIA_ATRACE_ENABLED, + "SkiaTracingFeature__use_skia_tracing") + +/// Trunk stable readonly flags /// +FLAG_MANAGER_READ_ONLY_FLAG(connected_display, "") +FLAG_MANAGER_READ_ONLY_FLAG(enable_small_area_detection, "") +FLAG_MANAGER_READ_ONLY_FLAG(misc1, "") +FLAG_MANAGER_READ_ONLY_FLAG(vrr_config, "debug.sf.enable_vrr_config") + +/// Trunk stable server flags /// +FLAG_MANAGER_SERVER_FLAG(late_boot_misc2, "") + +/// Exceptions /// +bool FlagManager::dont_skip_on_early() const { + // Even though this is a server writable flag, we do call it before boot completed, but that's + // fine since the decision is done per frame. We can't do caching though. + return flags::dont_skip_on_early(); } } // namespace android |