Add FlagManager SF class.

To handle Mendel experiment flags and system properties. Example method
is `demo_flag`.

Bug: 190769260
Test: make, atest libsurfaceflinger_unittest
Change-Id: If42630dc9c545d4117b616e862a21970193eda56
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index eeb3f3a..af012cd 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -66,6 +66,7 @@
         "libinput",
         "libutils",
         "libSurfaceFlingerProp",
+        "server_configurable_flags",
     ],
     static_libs: [
         "libcompositionengine",
@@ -154,6 +155,7 @@
         "DisplayRenderArea.cpp",
         "Effects/Daltonizer.cpp",
         "EventLog/EventLog.cpp",
+        "FlagManager.cpp",
         "FpsReporter.cpp",
         "FrameTracer/FrameTracer.cpp",
         "FrameTracker.cpp",
diff --git a/services/surfaceflinger/FlagManager.cpp b/services/surfaceflinger/FlagManager.cpp
new file mode 100644
index 0000000..f0c5b58
--- /dev/null
+++ b/services/surfaceflinger/FlagManager.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2021 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 "FlagManager.h"
+
+#include <SurfaceFlingerProperties.sysprop.h>
+#include <android-base/parsebool.h>
+#include <android-base/parseint.h>
+#include <android-base/stringprintf.h>
+#include <log/log.h>
+#include <server_configurable_flags/get_flags.h>
+#include <cinttypes>
+
+namespace android {
+static constexpr const char* kExperimentNamespace = "surface_flinger_native_boot";
+static constexpr const int64_t kDemoFlag = -1;
+
+FlagManager::~FlagManager() = default;
+
+void FlagManager::dump(std::string& result) const {
+    base::StringAppendF(&result, "FlagManager values: \n");
+    base::StringAppendF(&result, "demo_flag: %" PRId64 "\n", demo_flag());
+}
+
+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) {
+    base::ParseBoolResult parseResult = base::ParseBool(str);
+    switch (parseResult) {
+        case base::ParseBoolResult::kTrue:
+            return std::make_optional(true);
+        case base::ParseBoolResult::kFalse:
+            return std::make_optional(false);
+        case base::ParseBoolResult::kError:
+            return std::nullopt;
+    }
+}
+} // namespace
+
+std::string FlagManager::getServerConfigurableFlag(const std::string& experimentFlagName) const {
+    return server_configurable_flags::GetServerConfigurableFlag(kExperimentNamespace,
+                                                                experimentFlagName, "");
+}
+
+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);
+}
+
+int64_t FlagManager::demo_flag() const {
+    std::optional<int64_t> sysPropVal = std::nullopt;
+    return getValue("DemoFeature__demo_flag", sysPropVal, kDemoFlag);
+}
+} // namespace android
diff --git a/services/surfaceflinger/FlagManager.h b/services/surfaceflinger/FlagManager.h
new file mode 100644
index 0000000..65e30a4
--- /dev/null
+++ b/services/surfaceflinger/FlagManager.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <optional>
+#include <string>
+
+namespace android {
+// Manages flags for SurfaceFlinger, including default values, system properties, and Mendel
+// experiment configuration values.
+class FlagManager {
+public:
+    FlagManager() = default;
+    virtual ~FlagManager();
+    void dump(std::string& result) const;
+
+    int64_t demo_flag() const;
+
+private:
+    friend class FlagManagerTest;
+
+    // Wrapper for mocking in test.
+    virtual std::string getServerConfigurableFlag(const std::string& experimentFlagName) const;
+
+    template <typename T>
+    T getValue(const std::string& experimentFlagName, std::optional<T> systemPropertyOpt,
+               T defaultValue) const;
+};
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 8bd6e62..4ff3f6e 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -57,6 +57,7 @@
         "DisplayDevice_InitiateModeChange.cpp",
         "DisplayDevice_SetProjectionTest.cpp",
         "EventThreadTest.cpp",
+        "FlagManagerTest.cpp",
         "FpsReporterTest.cpp",
         "FpsTest.cpp",
         "FramebufferSurfaceTest.cpp",
@@ -164,6 +165,7 @@
         "libsync",
         "libui",
         "libutils",
+        "server_configurable_flags",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp b/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp
new file mode 100644
index 0000000..0905cd1
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/FlagManagerTest.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2021 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 <cstdint>
+#undef LOG_TAG
+#define LOG_TAG "FlagManagerTest"
+
+#include "FlagManager.h"
+
+#include <android-base/properties.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <server_configurable_flags/get_flags.h>
+#include <optional>
+
+namespace android {
+
+using testing::Return;
+
+class MockFlagManager : public FlagManager {
+public:
+    MockFlagManager() = default;
+    ~MockFlagManager() = default;
+
+    MOCK_METHOD(std::string, getServerConfigurableFlag, (const std::string& experimentFlagName),
+                (const, override));
+};
+
+class FlagManagerTest : public testing::Test {
+public:
+    FlagManagerTest();
+    ~FlagManagerTest() override;
+    std::unique_ptr<MockFlagManager> mFlagManager;
+
+    template <typename T>
+    T getValue(const std::string& experimentFlagName, std::optional<T> systemPropertyOpt,
+               T defaultValue);
+};
+
+FlagManagerTest::FlagManagerTest() {
+    const ::testing::TestInfo* const test_info =
+            ::testing::UnitTest::GetInstance()->current_test_info();
+    ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+    mFlagManager = std::make_unique<MockFlagManager>();
+}
+
+FlagManagerTest::~FlagManagerTest() {
+    const ::testing::TestInfo* const test_info =
+            ::testing::UnitTest::GetInstance()->current_test_info();
+    ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
+}
+
+template <typename T>
+T FlagManagerTest::getValue(const std::string& experimentFlagName,
+                            std::optional<T> systemPropertyOpt, T defaultValue) {
+    return mFlagManager->getValue(experimentFlagName, systemPropertyOpt, defaultValue);
+}
+
+namespace {
+TEST_F(FlagManagerTest, getValue_bool_default) {
+    EXPECT_CALL(*mFlagManager, getServerConfigurableFlag).Times(1).WillOnce(Return(""));
+    const bool defaultValue = false;
+    std::optional<bool> systemPropertyValue = std::nullopt;
+    const bool result = FlagManagerTest::getValue("test_flag", systemPropertyValue, defaultValue);
+    ASSERT_EQ(result, defaultValue);
+}
+
+TEST_F(FlagManagerTest, getValue_bool_sysprop) {
+    const bool defaultValue = false;
+    std::optional<bool> systemPropertyValue = std::make_optional(true);
+    const bool result = FlagManagerTest::getValue("test_flag", systemPropertyValue, defaultValue);
+    ASSERT_EQ(result, true);
+}
+
+TEST_F(FlagManagerTest, getValue_bool_experiment) {
+    EXPECT_CALL(*mFlagManager, getServerConfigurableFlag).Times(1).WillOnce(Return("1"));
+    const bool defaultValue = false;
+    std::optional<bool> systemPropertyValue = std::nullopt;
+    const bool result = FlagManagerTest::getValue("test_flag", systemPropertyValue, defaultValue);
+    ASSERT_EQ(result, true);
+}
+
+TEST_F(FlagManagerTest, getValue_int32_default) {
+    EXPECT_CALL(*mFlagManager, getServerConfigurableFlag).Times(1).WillOnce(Return(""));
+    int32_t defaultValue = 30;
+    std::optional<int32_t> systemPropertyValue = std::nullopt;
+    int32_t result = FlagManagerTest::getValue("test_flag", systemPropertyValue, defaultValue);
+    ASSERT_EQ(result, defaultValue);
+}
+
+TEST_F(FlagManagerTest, getValue_int32_sysprop) {
+    int32_t defaultValue = 30;
+    std::optional<int32_t> systemPropertyValue = std::make_optional(10);
+    int32_t result = FlagManagerTest::getValue("test_flag", systemPropertyValue, defaultValue);
+    ASSERT_EQ(result, 10);
+}
+
+TEST_F(FlagManagerTest, getValue_int32_experiment) {
+    EXPECT_CALL(*mFlagManager, getServerConfigurableFlag).Times(1).WillOnce(Return("50"));
+    std::int32_t defaultValue = 30;
+    std::optional<std::int32_t> systemPropertyValue = std::nullopt;
+    std::int32_t result = FlagManagerTest::getValue("test_flag", systemPropertyValue, defaultValue);
+    ASSERT_EQ(result, 50);
+}
+
+TEST_F(FlagManagerTest, getValue_int64_default) {
+    EXPECT_CALL(*mFlagManager, getServerConfigurableFlag).Times(1).WillOnce(Return(""));
+    int64_t defaultValue = 30;
+    std::optional<int64_t> systemPropertyValue = std::nullopt;
+    int64_t result = getValue("flag_name", systemPropertyValue, defaultValue);
+    ASSERT_EQ(result, defaultValue);
+}
+
+TEST_F(FlagManagerTest, getValue_int64_sysprop) {
+    int64_t defaultValue = 30;
+    std::optional<int64_t> systemPropertyValue = std::make_optional(10);
+    int64_t result = getValue("flag_name", systemPropertyValue, defaultValue);
+    ASSERT_EQ(result, 10);
+}
+
+TEST_F(FlagManagerTest, getValue_int64_experiment) {
+    EXPECT_CALL(*mFlagManager, getServerConfigurableFlag).Times(1).WillOnce(Return("50"));
+    int64_t defaultValue = 30;
+    std::optional<int64_t> systemPropertyValue = std::nullopt;
+    int64_t result = getValue("flag_name", systemPropertyValue, defaultValue);
+    ASSERT_EQ(result, 50);
+}
+} // namespace
+} // namespace android