SF: Adding Mock Display and tests for RefreshRateStats.

Following ag/6005545.

Test: adding SF tests.
Bug: 113612090
Change-Id: Ic4d1ca622f00c4396ae19c44defac0c69fabed1d
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index ad31a40..e34e568 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -44,8 +44,10 @@
         "LayerHistoryTest.cpp",
         "SchedulerTest.cpp",
         "SchedulerUtilsTest.cpp",
+        "RefreshRateStatsTest.cpp",
         "TimeStatsTest.cpp",
         "mock/DisplayHardware/MockComposer.cpp",
+        "mock/DisplayHardware/MockDisplay.cpp",
         "mock/DisplayHardware/MockPowerAdvisor.cpp",
         "mock/gui/MockGraphicBufferConsumer.cpp",
         "mock/gui/MockGraphicBufferProducer.cpp",
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
new file mode 100644
index 0000000..0384d9d
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "SchedulerUnittests"
+
+#include <gmock/gmock.h>
+#include <log/log.h>
+#include <thread>
+
+#include "Scheduler/RefreshRateStats.h"
+#include "mock/DisplayHardware/MockDisplay.h"
+
+using namespace std::chrono_literals;
+
+namespace android {
+namespace scheduler {
+
+class RefreshRateStatsTest : public testing::Test {
+protected:
+    static constexpr int CONFIG_ID_90 = 0;
+    static constexpr int CONFIG_ID_60 = 1;
+    static constexpr int64_t VSYNC_90 = 11111111;
+    static constexpr int64_t VSYNC_60 = 16666667;
+
+    RefreshRateStatsTest();
+    ~RefreshRateStatsTest();
+
+    void init(std::vector<std::shared_ptr<const HWC2::Display::Config>> configs);
+
+    std::unique_ptr<RefreshRateStats> mRefreshRateStats;
+};
+
+RefreshRateStatsTest::RefreshRateStatsTest() {
+    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());
+}
+
+RefreshRateStatsTest::~RefreshRateStatsTest() {
+    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());
+}
+
+void RefreshRateStatsTest::init(std::vector<std::shared_ptr<const HWC2::Display::Config>> configs) {
+    mRefreshRateStats = std::make_unique<RefreshRateStats>(configs);
+}
+
+namespace {
+/* ------------------------------------------------------------------------
+ * Test cases
+ */
+TEST_F(RefreshRateStatsTest, canCreateAndDestroyTest) {
+    std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
+    init(configs);
+
+    // There is one default config, so the refresh rates should have one item.
+    ASSERT_EQ(1, mRefreshRateStats->getTotalTimes().size());
+}
+
+TEST_F(RefreshRateStatsTest, oneConfigTest) {
+    auto display = new Hwc2::mock::Display();
+
+    auto config = HWC2::Display::Config::Builder(*display, CONFIG_ID_90);
+    config.setVsyncPeriod(VSYNC_90);
+    std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
+    configs.push_back(config.build());
+
+    init(configs);
+
+    std::unordered_map<std::string, int64_t> times = mRefreshRateStats->getTotalTimes();
+    ASSERT_EQ(2, times.size());
+    ASSERT_EQ(0, times["ScreenOff"]);
+    ASSERT_EQ(0, times["90fps"]);
+    // Setting up tests on mobile harness can be flaky with time passing, so testing for
+    // exact time changes can result in flaxy numbers. To avoid that remember old
+    // numbers to make sure the correct values are increasing in the next test.
+    int screenOff = times["ScreenOff"];
+    int ninety = times["90fps"];
+
+    // Screen is off by default.
+    std::this_thread::sleep_for(std::chrono::milliseconds(2));
+    times = mRefreshRateStats->getTotalTimes();
+    ASSERT_LT(screenOff, times["ScreenOff"]);
+    ASSERT_EQ(0, times["90fps"]);
+    screenOff = times["ScreenOff"];
+
+    mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+    std::this_thread::sleep_for(std::chrono::milliseconds(2));
+    times = mRefreshRateStats->getTotalTimes();
+    ASSERT_EQ(screenOff, times["ScreenOff"]);
+    ASSERT_LT(ninety, times["90fps"]);
+    ninety = times["90fps"];
+
+    mRefreshRateStats->setPowerMode(HWC_POWER_MODE_DOZE);
+    std::this_thread::sleep_for(std::chrono::milliseconds(2));
+    times = mRefreshRateStats->getTotalTimes();
+    ASSERT_LT(screenOff, times["ScreenOff"]);
+    ASSERT_EQ(ninety, times["90fps"]);
+    screenOff = times["ScreenOff"];
+
+    mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+    std::this_thread::sleep_for(std::chrono::milliseconds(2));
+    times = mRefreshRateStats->getTotalTimes();
+    // Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config
+    // does not update refresh rates that come from the config.
+    ASSERT_LT(screenOff, times["ScreenOff"]);
+    ASSERT_EQ(ninety, times["90fps"]);
+}
+
+TEST_F(RefreshRateStatsTest, twoConfigsTest) {
+    auto display = new Hwc2::mock::Display();
+
+    auto config90 = HWC2::Display::Config::Builder(*display, CONFIG_ID_90);
+    config90.setVsyncPeriod(VSYNC_90);
+    std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
+    configs.push_back(config90.build());
+
+    auto config60 = HWC2::Display::Config::Builder(*display, CONFIG_ID_60);
+    config60.setVsyncPeriod(VSYNC_60);
+    configs.push_back(config60.build());
+
+    init(configs);
+
+    std::unordered_map<std::string, int64_t> times = mRefreshRateStats->getTotalTimes();
+    ASSERT_EQ(3, times.size());
+    ASSERT_EQ(0, times["ScreenOff"]);
+    ASSERT_EQ(0, times["60fps"]);
+    ASSERT_EQ(0, times["90fps"]);
+    // Setting up tests on mobile harness can be flaky with time passing, so testing for
+    // exact time changes can result in flaxy numbers. To avoid that remember old
+    // numbers to make sure the correct values are increasing in the next test.
+    int screenOff = times["ScreenOff"];
+    int sixty = times["60fps"];
+    int ninety = times["90fps"];
+
+    // Screen is off by default.
+    std::this_thread::sleep_for(std::chrono::milliseconds(2));
+    times = mRefreshRateStats->getTotalTimes();
+    ASSERT_LT(screenOff, times["ScreenOff"]);
+    ASSERT_EQ(sixty, times["60fps"]);
+    ASSERT_EQ(ninety, times["90fps"]);
+    screenOff = times["ScreenOff"];
+
+    mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+    std::this_thread::sleep_for(std::chrono::milliseconds(2));
+    times = mRefreshRateStats->getTotalTimes();
+    ASSERT_EQ(screenOff, times["ScreenOff"]);
+    ASSERT_EQ(sixty, times["60fps"]);
+    ASSERT_LT(ninety, times["90fps"]);
+    ninety = times["90fps"];
+
+    // When power mode is normal, time for configs updates.
+    mRefreshRateStats->setConfigMode(CONFIG_ID_60);
+    std::this_thread::sleep_for(std::chrono::milliseconds(2));
+    times = mRefreshRateStats->getTotalTimes();
+    ASSERT_EQ(screenOff, times["ScreenOff"]);
+    ASSERT_EQ(ninety, times["90fps"]);
+    ASSERT_LT(sixty, times["60fps"]);
+    sixty = times["60fps"];
+
+    mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+    std::this_thread::sleep_for(std::chrono::milliseconds(2));
+    times = mRefreshRateStats->getTotalTimes();
+    ASSERT_EQ(screenOff, times["ScreenOff"]);
+    ASSERT_LT(ninety, times["90fps"]);
+    ASSERT_EQ(sixty, times["60fps"]);
+    ninety = times["90fps"];
+
+    mRefreshRateStats->setConfigMode(CONFIG_ID_60);
+    std::this_thread::sleep_for(std::chrono::milliseconds(2));
+    times = mRefreshRateStats->getTotalTimes();
+    ASSERT_EQ(screenOff, times["ScreenOff"]);
+    ASSERT_EQ(ninety, times["90fps"]);
+    ASSERT_LT(sixty, times["60fps"]);
+    sixty = times["60fps"];
+
+    // Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config
+    // does not update refresh rates that come from the config.
+    mRefreshRateStats->setPowerMode(HWC_POWER_MODE_DOZE);
+    mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+    std::this_thread::sleep_for(std::chrono::milliseconds(2));
+    times = mRefreshRateStats->getTotalTimes();
+    ASSERT_LT(screenOff, times["ScreenOff"]);
+    ASSERT_EQ(ninety, times["90fps"]);
+    ASSERT_EQ(sixty, times["60fps"]);
+    screenOff = times["ScreenOff"];
+
+    mRefreshRateStats->setConfigMode(CONFIG_ID_60);
+    std::this_thread::sleep_for(std::chrono::milliseconds(2));
+    times = mRefreshRateStats->getTotalTimes();
+    ASSERT_LT(screenOff, times["ScreenOff"]);
+    ASSERT_EQ(ninety, times["90fps"]);
+    ASSERT_EQ(sixty, times["60fps"]);
+}
+} // namespace
+} // namespace scheduler
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 687941a..2a8dda6 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -335,11 +335,11 @@
         void setExpensiveRenderingExpected(hwc2_display_t, bool) override {}
     };
 
-    struct HWC2Display : public HWC2::Display {
+    struct HWC2Display : public HWC2::impl::Display {
         HWC2Display(Hwc2::Composer& composer, Hwc2::PowerAdvisor& advisor,
                     const std::unordered_set<HWC2::Capability>& capabilities, hwc2_display_t id,
                     HWC2::DisplayType type)
-              : HWC2::Display(composer, advisor, capabilities, id, type) {}
+              : HWC2::impl::Display(composer, advisor, capabilities, id, type) {}
         ~HWC2Display() {
             // Prevents a call to disable vsyncs.
             mType = HWC2::DisplayType::Invalid;
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.cpp b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.cpp
new file mode 100644
index 0000000..2ec37c1
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019 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 "mock/DisplayHardware/MockDisplay.h"
+
+namespace android {
+namespace Hwc2 {
+namespace mock {
+
+// Explicit default instantiation is recommended.
+Display::Display() = default;
+Display::~Display() = default;
+
+} // namespace mock
+} // namespace Hwc2
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h
new file mode 100644
index 0000000..d7e20c4
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2019 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 <gmock/gmock.h>
+
+#include "DisplayHardware/HWC2.h"
+
+using HWC2::Error;
+using HWC2::Layer;
+
+namespace android {
+namespace Hwc2 {
+namespace mock {
+
+class Display : public HWC2::Display {
+public:
+    Display();
+    ~Display();
+
+    MOCK_CONST_METHOD0(getId, hwc2_layer_t());
+    MOCK_CONST_METHOD0(isConnected, bool());
+    MOCK_METHOD1(setConnected, void(bool));
+    MOCK_CONST_METHOD0(getCapabilities, const std::unordered_set<HWC2::DisplayCapability>&());
+
+    MOCK_METHOD0(acceptChanges, Error());
+    MOCK_METHOD1(createLayer, Error(Layer**));
+    MOCK_METHOD1(destroyLayer, Error(Layer*));
+    MOCK_CONST_METHOD1(getActiveConfig, Error(std::shared_ptr<const Config>*));
+    MOCK_CONST_METHOD1(getActiveConfigIndex, Error(int* outIndex));
+    MOCK_METHOD1(getChangedCompositionTypes, Error(std::unordered_map<Layer*, HWC2::Composition>*));
+    MOCK_CONST_METHOD1(getColorModes, Error(std::vector<android::ui::ColorMode>*));
+
+    MOCK_CONST_METHOD0(getSupportedPerFrameMetadata, int32_t());
+    MOCK_CONST_METHOD2(getRenderIntents,
+                       Error(android::ui::ColorMode, std::vector<android::ui::RenderIntent>*));
+    MOCK_METHOD2(getDataspaceSaturationMatrix, Error(android::ui::Dataspace, android::mat4*));
+    MOCK_CONST_METHOD0(getConfigs, std::vector<std::shared_ptr<const Config>>());
+
+    MOCK_CONST_METHOD1(getName, Error(std::string*));
+    MOCK_METHOD2(getRequests,
+                 Error(HWC2::DisplayRequest*, std::unordered_map<Layer*, HWC2::LayerRequest>*));
+    MOCK_CONST_METHOD1(getType, Error(HWC2::DisplayType*));
+    MOCK_CONST_METHOD1(supportsDoze, Error(bool*));
+    MOCK_CONST_METHOD1(getHdrCapabilities, Error(android::HdrCapabilities*));
+    MOCK_CONST_METHOD3(getDisplayedContentSamplingAttributes,
+                       Error(android::ui::PixelFormat*, android::ui::Dataspace*, uint8_t*));
+    MOCK_CONST_METHOD3(setDisplayContentSamplingEnabled, Error(bool, uint8_t, uint64_t));
+    MOCK_CONST_METHOD3(getDisplayedContentSample,
+                       Error(uint64_t, uint64_t, android::DisplayedFrameStats*));
+    MOCK_CONST_METHOD1(getReleaseFences,
+                       Error(std::unordered_map<Layer*, android::sp<android::Fence>>* outFences));
+    MOCK_METHOD1(present, Error(android::sp<android::Fence>*));
+    MOCK_METHOD1(setActiveConfig, Error(const std::shared_ptr<const HWC2::Display::Config>&));
+    MOCK_METHOD4(setClientTarget,
+                 Error(uint32_t, const android::sp<android::GraphicBuffer>&,
+                       const android::sp<android::Fence>&, android::ui::Dataspace));
+    MOCK_METHOD2(setColorMode, Error(android::ui::ColorMode, android::ui::RenderIntent));
+    MOCK_METHOD2(setColorTransform, Error(const android::mat4&, android_color_transform_t));
+    MOCK_METHOD2(setOutputBuffer,
+                 Error(const android::sp<android::GraphicBuffer>&,
+                       const android::sp<android::Fence>&));
+    MOCK_METHOD1(setPowerMode, Error(HWC2::PowerMode));
+    MOCK_METHOD1(setVsyncEnabled, Error(HWC2::Vsync));
+    MOCK_METHOD2(validate, Error(uint32_t*, uint32_t*));
+    MOCK_METHOD4(presentOrValidate,
+                 Error(uint32_t*, uint32_t*, android::sp<android::Fence>*, uint32_t*));
+};
+
+} // namespace mock
+} // namespace Hwc2
+} // namespace android
\ No newline at end of file