1 /*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #undef LOG_TAG
18 #define LOG_TAG "SchedulerUnittests"
19
20 #include <gmock/gmock.h>
21 #include <log/log.h>
22 #include <thread>
23
24 #include "Scheduler/RefreshRateStats.h"
25 #include "mock/DisplayHardware/MockDisplay.h"
26 #include "mock/MockTimeStats.h"
27
28 using namespace std::chrono_literals;
29 using testing::_;
30 using testing::AtLeast;
31
32 namespace android {
33 namespace scheduler {
34
35 class RefreshRateStatsTest : public testing::Test {
36 protected:
37 static constexpr int CONFIG_ID_90 = 0;
38 static constexpr int CONFIG_ID_60 = 1;
39 static constexpr int64_t VSYNC_90 = 11111111;
40 static constexpr int64_t VSYNC_60 = 16666667;
41
42 RefreshRateStatsTest();
43 ~RefreshRateStatsTest();
44
45 mock::TimeStats mTimeStats;
46 RefreshRateConfigs mRefreshRateConfigs;
47 RefreshRateStats mRefreshRateStats{mRefreshRateConfigs, mTimeStats};
48 };
49
RefreshRateStatsTest()50 RefreshRateStatsTest::RefreshRateStatsTest() {
51 const ::testing::TestInfo* const test_info =
52 ::testing::UnitTest::GetInstance()->current_test_info();
53 ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
54 }
55
~RefreshRateStatsTest()56 RefreshRateStatsTest::~RefreshRateStatsTest() {
57 const ::testing::TestInfo* const test_info =
58 ::testing::UnitTest::GetInstance()->current_test_info();
59 ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
60 }
61
62 namespace {
63 /* ------------------------------------------------------------------------
64 * Test cases
65 */
TEST_F(RefreshRateStatsTest,canCreateAndDestroyTest)66 TEST_F(RefreshRateStatsTest, canCreateAndDestroyTest) {
67 std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
68 mRefreshRateConfigs.populate(configs);
69
70 // There is one default config, so the refresh rates should have one item.
71 EXPECT_EQ(1, mRefreshRateStats.getTotalTimes().size());
72 }
73
TEST_F(RefreshRateStatsTest,oneConfigTest)74 TEST_F(RefreshRateStatsTest, oneConfigTest) {
75 auto display = new Hwc2::mock::Display();
76
77 auto config = HWC2::Display::Config::Builder(*display, CONFIG_ID_90);
78 config.setVsyncPeriod(VSYNC_90);
79 std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
80 configs.push_back(config.build());
81
82 mRefreshRateConfigs.populate(configs);
83
84 EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
85 EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1));
86
87 std::unordered_map<std::string, int64_t> times = mRefreshRateStats.getTotalTimes();
88 EXPECT_EQ(2, times.size());
89 EXPECT_NE(0u, times.count("ScreenOff"));
90 EXPECT_EQ(1u, times.count("90fps"));
91 EXPECT_EQ(0, times["90fps"]);
92 // Setting up tests on mobile harness can be flaky with time passing, so testing for
93 // exact time changes can result in flaxy numbers. To avoid that remember old
94 // numbers to make sure the correct values are increasing in the next test.
95 int screenOff = times["ScreenOff"];
96 int ninety = times["90fps"];
97
98 // Screen is off by default.
99 std::this_thread::sleep_for(std::chrono::milliseconds(2));
100 times = mRefreshRateStats.getTotalTimes();
101 EXPECT_LT(screenOff, times["ScreenOff"]);
102 EXPECT_EQ(0, times["90fps"]);
103
104 mRefreshRateStats.setConfigMode(CONFIG_ID_90);
105 mRefreshRateStats.setPowerMode(HWC_POWER_MODE_NORMAL);
106 screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
107 std::this_thread::sleep_for(std::chrono::milliseconds(2));
108 times = mRefreshRateStats.getTotalTimes();
109 EXPECT_EQ(screenOff, times["ScreenOff"]);
110 EXPECT_LT(ninety, times["90fps"]);
111
112 mRefreshRateStats.setPowerMode(HWC_POWER_MODE_DOZE);
113 ninety = mRefreshRateStats.getTotalTimes()["90fps"];
114 std::this_thread::sleep_for(std::chrono::milliseconds(2));
115 times = mRefreshRateStats.getTotalTimes();
116 EXPECT_LT(screenOff, times["ScreenOff"]);
117 EXPECT_EQ(ninety, times["90fps"]);
118
119 mRefreshRateStats.setConfigMode(CONFIG_ID_90);
120 screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
121 std::this_thread::sleep_for(std::chrono::milliseconds(2));
122 times = mRefreshRateStats.getTotalTimes();
123 // Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config
124 // does not update refresh rates that come from the config.
125 EXPECT_LT(screenOff, times["ScreenOff"]);
126 EXPECT_EQ(ninety, times["90fps"]);
127 }
128
TEST_F(RefreshRateStatsTest,twoConfigsTest)129 TEST_F(RefreshRateStatsTest, twoConfigsTest) {
130 auto display = new Hwc2::mock::Display();
131
132 auto config90 = HWC2::Display::Config::Builder(*display, CONFIG_ID_90);
133 config90.setVsyncPeriod(VSYNC_90);
134 std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
135 configs.push_back(config90.build());
136
137 auto config60 = HWC2::Display::Config::Builder(*display, CONFIG_ID_60);
138 config60.setVsyncPeriod(VSYNC_60);
139 configs.push_back(config60.build());
140
141 mRefreshRateConfigs.populate(configs);
142
143 EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
144 EXPECT_CALL(mTimeStats, recordRefreshRate(60, _)).Times(AtLeast(1));
145 EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1));
146
147 std::unordered_map<std::string, int64_t> times = mRefreshRateStats.getTotalTimes();
148 EXPECT_EQ(3, times.size());
149 EXPECT_NE(0u, times.count("ScreenOff"));
150 EXPECT_EQ(1u, times.count("60fps"));
151 EXPECT_EQ(0, times["60fps"]);
152 EXPECT_EQ(1u, times.count("90fps"));
153 EXPECT_EQ(0, times["90fps"]);
154 // Setting up tests on mobile harness can be flaky with time passing, so testing for
155 // exact time changes can result in flaxy numbers. To avoid that remember old
156 // numbers to make sure the correct values are increasing in the next test.
157 int screenOff = times["ScreenOff"];
158 int sixty = times["60fps"];
159 int ninety = times["90fps"];
160
161 // Screen is off by default.
162 std::this_thread::sleep_for(std::chrono::milliseconds(2));
163 times = mRefreshRateStats.getTotalTimes();
164 EXPECT_LT(screenOff, times["ScreenOff"]);
165 EXPECT_EQ(sixty, times["60fps"]);
166 EXPECT_EQ(ninety, times["90fps"]);
167
168 mRefreshRateStats.setConfigMode(CONFIG_ID_90);
169 mRefreshRateStats.setPowerMode(HWC_POWER_MODE_NORMAL);
170 screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
171 std::this_thread::sleep_for(std::chrono::milliseconds(2));
172 times = mRefreshRateStats.getTotalTimes();
173 EXPECT_EQ(screenOff, times["ScreenOff"]);
174 EXPECT_EQ(sixty, times["60fps"]);
175 EXPECT_LT(ninety, times["90fps"]);
176
177 // When power mode is normal, time for configs updates.
178 mRefreshRateStats.setConfigMode(CONFIG_ID_60);
179 ninety = mRefreshRateStats.getTotalTimes()["90fps"];
180 std::this_thread::sleep_for(std::chrono::milliseconds(2));
181 times = mRefreshRateStats.getTotalTimes();
182 EXPECT_EQ(screenOff, times["ScreenOff"]);
183 EXPECT_EQ(ninety, times["90fps"]);
184 EXPECT_LT(sixty, times["60fps"]);
185
186 mRefreshRateStats.setConfigMode(CONFIG_ID_90);
187 sixty = mRefreshRateStats.getTotalTimes()["60fps"];
188 std::this_thread::sleep_for(std::chrono::milliseconds(2));
189 times = mRefreshRateStats.getTotalTimes();
190 EXPECT_EQ(screenOff, times["ScreenOff"]);
191 EXPECT_LT(ninety, times["90fps"]);
192 EXPECT_EQ(sixty, times["60fps"]);
193
194 mRefreshRateStats.setConfigMode(CONFIG_ID_60);
195 ninety = mRefreshRateStats.getTotalTimes()["90fps"];
196 std::this_thread::sleep_for(std::chrono::milliseconds(2));
197 times = mRefreshRateStats.getTotalTimes();
198 EXPECT_EQ(screenOff, times["ScreenOff"]);
199 EXPECT_EQ(ninety, times["90fps"]);
200 EXPECT_LT(sixty, times["60fps"]);
201
202 // Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config
203 // does not update refresh rates that come from the config.
204 mRefreshRateStats.setPowerMode(HWC_POWER_MODE_DOZE);
205 mRefreshRateStats.setConfigMode(CONFIG_ID_90);
206 sixty = mRefreshRateStats.getTotalTimes()["60fps"];
207 std::this_thread::sleep_for(std::chrono::milliseconds(2));
208 times = mRefreshRateStats.getTotalTimes();
209 EXPECT_LT(screenOff, times["ScreenOff"]);
210 EXPECT_EQ(ninety, times["90fps"]);
211 EXPECT_EQ(sixty, times["60fps"]);
212
213 mRefreshRateStats.setConfigMode(CONFIG_ID_60);
214 screenOff = mRefreshRateStats.getTotalTimes()["ScreenOff"];
215 std::this_thread::sleep_for(std::chrono::milliseconds(2));
216 times = mRefreshRateStats.getTotalTimes();
217 EXPECT_LT(screenOff, times["ScreenOff"]);
218 EXPECT_EQ(ninety, times["90fps"]);
219 EXPECT_EQ(sixty, times["60fps"]);
220 }
221 } // namespace
222 } // namespace scheduler
223 } // namespace android
224