| /* |
| * 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 <chrono> |
| #include <thread> |
| |
| #include "Scheduler/VsyncConfiguration.h" |
| |
| using namespace testing; |
| |
| namespace android::scheduler { |
| |
| using namespace std::chrono_literals; |
| |
| class TestableWorkDuration : public impl::WorkDuration { |
| public: |
| TestableWorkDuration(Fps currentFps, nsecs_t sfDuration, nsecs_t appDuration, |
| nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration, |
| nsecs_t sfEarlyGlDuration, nsecs_t appEarlyGlDuration, |
| nsecs_t hwcMinWorkDuration) |
| : impl::WorkDuration(currentFps, sfDuration, appDuration, sfEarlyDuration, |
| appEarlyDuration, sfEarlyGlDuration, appEarlyGlDuration, |
| hwcMinWorkDuration) {} |
| }; |
| |
| class WorkDurationTest : public testing::Test { |
| protected: |
| WorkDurationTest() |
| : mWorkDuration(60_Hz, 10'500'000, 20'500'000, 16'000'000, 16'500'000, 13'500'000, |
| 21'000'000, 1234) {} |
| |
| ~WorkDurationTest() = default; |
| |
| TestableWorkDuration mWorkDuration; |
| }; |
| |
| /* ------------------------------------------------------------------------ |
| * Test cases |
| */ |
| TEST_F(WorkDurationTest, getConfigsForRefreshRate_60Hz) { |
| mWorkDuration.setRefreshRateFps(60_Hz); |
| auto currentOffsets = mWorkDuration.getCurrentConfigs(); |
| auto offsets = mWorkDuration.getConfigsForRefreshRate(60_Hz); |
| |
| EXPECT_EQ(currentOffsets, offsets); |
| EXPECT_EQ(offsets.late.sfOffset, 6'166'667); |
| EXPECT_EQ(offsets.late.appOffset, 2'333'334); |
| |
| EXPECT_EQ(offsets.late.sfWorkDuration, 10'500'000ns); |
| EXPECT_EQ(offsets.late.appWorkDuration, 20'500'000ns); |
| |
| EXPECT_EQ(offsets.early.sfOffset, 666'667); |
| EXPECT_EQ(offsets.early.appOffset, 833'334); |
| |
| EXPECT_EQ(offsets.early.sfWorkDuration, 16'000'000ns); |
| EXPECT_EQ(offsets.early.appWorkDuration, 16'500'000ns); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfOffset, 3'166'667); |
| EXPECT_EQ(offsets.earlyGpu.appOffset, 15'500'001); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfWorkDuration, 13'500'000ns); |
| EXPECT_EQ(offsets.earlyGpu.appWorkDuration, 21'000'000ns); |
| } |
| |
| TEST_F(WorkDurationTest, getConfigsForRefreshRate_90Hz) { |
| mWorkDuration.setRefreshRateFps(90_Hz); |
| auto currentOffsets = mWorkDuration.getCurrentConfigs(); |
| auto offsets = mWorkDuration.getConfigsForRefreshRate(90_Hz); |
| |
| EXPECT_EQ(currentOffsets, offsets); |
| EXPECT_EQ(offsets.late.sfOffset, 611'111); |
| EXPECT_EQ(offsets.late.appOffset, 2'333'333); |
| |
| EXPECT_EQ(offsets.late.sfWorkDuration, 10'500'000ns); |
| EXPECT_EQ(offsets.late.appWorkDuration, 20'500'000ns); |
| |
| EXPECT_EQ(offsets.early.sfOffset, -4'888'889); |
| EXPECT_EQ(offsets.early.appOffset, 833'333); |
| |
| EXPECT_EQ(offsets.early.sfWorkDuration, 16'000'000ns); |
| EXPECT_EQ(offsets.early.appWorkDuration, 16'500'000ns); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfOffset, -2'388'889); |
| EXPECT_EQ(offsets.earlyGpu.appOffset, 9'944'444); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfWorkDuration, 13'500'000ns); |
| EXPECT_EQ(offsets.earlyGpu.appWorkDuration, 21'000'000ns); |
| } |
| |
| TEST_F(WorkDurationTest, getConfigsForRefreshRate_DefaultOffsets) { |
| TestableWorkDuration phaseOffsetsWithDefaultValues(60_Hz, -1, -1, -1, -1, -1, -1, 0); |
| |
| auto validateOffsets = [](const auto& offsets, std::chrono::nanoseconds vsyncPeriod) { |
| EXPECT_EQ(offsets.late.sfOffset, 1'000'000); |
| EXPECT_EQ(offsets.late.appOffset, 1'000'000); |
| |
| EXPECT_EQ(offsets.late.sfWorkDuration, vsyncPeriod - 1'000'000ns); |
| EXPECT_EQ(offsets.late.appWorkDuration, vsyncPeriod); |
| |
| EXPECT_EQ(offsets.early.sfOffset, 1'000'000); |
| EXPECT_EQ(offsets.early.appOffset, 1'000'000); |
| |
| EXPECT_EQ(offsets.early.sfWorkDuration, vsyncPeriod - 1'000'000ns); |
| EXPECT_EQ(offsets.early.appWorkDuration, vsyncPeriod); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfOffset, 1'000'000); |
| EXPECT_EQ(offsets.earlyGpu.appOffset, 1'000'000); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfWorkDuration, vsyncPeriod - 1'000'000ns); |
| EXPECT_EQ(offsets.earlyGpu.appWorkDuration, vsyncPeriod); |
| |
| EXPECT_EQ(offsets.hwcMinWorkDuration, 0ns); |
| }; |
| |
| const auto testForRefreshRate = [&](Fps refreshRate) { |
| phaseOffsetsWithDefaultValues.setRefreshRateFps(refreshRate); |
| auto currentOffsets = phaseOffsetsWithDefaultValues.getCurrentConfigs(); |
| auto offsets = phaseOffsetsWithDefaultValues.getConfigsForRefreshRate(refreshRate); |
| EXPECT_EQ(currentOffsets, offsets); |
| validateOffsets(offsets, std::chrono::nanoseconds(refreshRate.getPeriodNsecs())); |
| }; |
| |
| testForRefreshRate(90_Hz); |
| testForRefreshRate(60_Hz); |
| } |
| |
| TEST_F(WorkDurationTest, getConfigsForRefreshRate_unknownRefreshRate) { |
| auto offsets = mWorkDuration.getConfigsForRefreshRate(14.7_Hz); |
| |
| EXPECT_EQ(offsets.late.sfOffset, 57'527'208); |
| EXPECT_EQ(offsets.late.appOffset, 37'027'208); |
| |
| EXPECT_EQ(offsets.late.sfWorkDuration, 10'500'000ns); |
| EXPECT_EQ(offsets.late.appWorkDuration, 20'500'000ns); |
| |
| EXPECT_EQ(offsets.early.sfOffset, 52'027'208); |
| EXPECT_EQ(offsets.early.appOffset, 35'527'208); |
| |
| EXPECT_EQ(offsets.early.sfWorkDuration, 16'000'000ns); |
| EXPECT_EQ(offsets.early.appWorkDuration, 16'500'000ns); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfOffset, 54'527'208); |
| EXPECT_EQ(offsets.earlyGpu.appOffset, 33'527'208); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfWorkDuration, 13'500'000ns); |
| EXPECT_EQ(offsets.earlyGpu.appWorkDuration, 21'000'000ns); |
| } |
| |
| TEST_F(WorkDurationTest, minHwcWorkDuration) { |
| EXPECT_EQ(mWorkDuration.getCurrentConfigs().hwcMinWorkDuration, 1234ns); |
| } |
| |
| class TestablePhaseOffsets : public impl::PhaseOffsets { |
| public: |
| TestablePhaseOffsets(nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs, |
| std::optional<nsecs_t> earlySfOffsetNs, |
| std::optional<nsecs_t> earlyGpuSfOffsetNs, |
| std::optional<nsecs_t> earlyAppOffsetNs, |
| std::optional<nsecs_t> earlyGpuAppOffsetNs, |
| nsecs_t highFpsVsyncPhaseOffsetNs, nsecs_t highFpsSfVSyncPhaseOffsetNs, |
| std::optional<nsecs_t> highFpsEarlySfOffsetNs, |
| std::optional<nsecs_t> highFpsEarlyGpuSfOffsetNs, |
| std::optional<nsecs_t> highFpsEarlyAppOffsetNs, |
| std::optional<nsecs_t> highFpsEarlyGpuAppOffsetNs, |
| nsecs_t thresholdForNextVsync, nsecs_t hwcMinWorkDuration) |
| : impl::PhaseOffsets(60_Hz, vsyncPhaseOffsetNs, sfVSyncPhaseOffsetNs, earlySfOffsetNs, |
| earlyGpuSfOffsetNs, earlyAppOffsetNs, earlyGpuAppOffsetNs, |
| highFpsVsyncPhaseOffsetNs, highFpsSfVSyncPhaseOffsetNs, |
| highFpsEarlySfOffsetNs, highFpsEarlyGpuSfOffsetNs, |
| highFpsEarlyAppOffsetNs, highFpsEarlyGpuAppOffsetNs, |
| thresholdForNextVsync, hwcMinWorkDuration) {} |
| }; |
| |
| class PhaseOffsetsTest : public testing::Test { |
| protected: |
| PhaseOffsetsTest() = default; |
| ~PhaseOffsetsTest() = default; |
| |
| TestablePhaseOffsets mPhaseOffsets{2'000'000, 6'000'000, 7'000'000, 8'000'000, 3'000'000, |
| 4'000'000, 2'000'000, 1'000'000, 2'000'000, 3'000'000, |
| 3'000'000, 4'000'000, 10'000'000, 1234}; |
| }; |
| |
| TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_unknownRefreshRate) { |
| auto offsets = mPhaseOffsets.getConfigsForRefreshRate(14.7_Hz); |
| |
| EXPECT_EQ(offsets.late.sfOffset, 6'000'000); |
| EXPECT_EQ(offsets.late.appOffset, 2'000'000); |
| |
| EXPECT_EQ(offsets.late.sfWorkDuration, 62'027'208ns); |
| EXPECT_EQ(offsets.late.appWorkDuration, 72'027'208ns); |
| |
| EXPECT_EQ(offsets.early.sfOffset, 7'000'000); |
| EXPECT_EQ(offsets.early.appOffset, 3'000'000); |
| |
| EXPECT_EQ(offsets.early.sfWorkDuration, 61'027'208ns); |
| EXPECT_EQ(offsets.early.appWorkDuration, 72'027'208ns); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfOffset, 8'000'000); |
| EXPECT_EQ(offsets.earlyGpu.appOffset, 4'000'000); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfWorkDuration, 60'027'208ns); |
| EXPECT_EQ(offsets.earlyGpu.appWorkDuration, 72'027'208ns); |
| } |
| |
| TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_60Hz) { |
| auto offsets = mPhaseOffsets.getConfigsForRefreshRate(60_Hz); |
| |
| EXPECT_EQ(offsets.late.sfOffset, 6'000'000); |
| EXPECT_EQ(offsets.late.appOffset, 2'000'000); |
| |
| EXPECT_EQ(offsets.late.sfWorkDuration, 10'666'667ns); |
| EXPECT_EQ(offsets.late.appWorkDuration, 20'666'667ns); |
| |
| EXPECT_EQ(offsets.early.sfOffset, 7'000'000); |
| EXPECT_EQ(offsets.early.appOffset, 3'000'000); |
| |
| EXPECT_EQ(offsets.early.sfWorkDuration, 9'666'667ns); |
| EXPECT_EQ(offsets.early.appWorkDuration, 20'666'667ns); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfOffset, 8'000'000); |
| EXPECT_EQ(offsets.earlyGpu.appOffset, 4'000'000); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfWorkDuration, 8'666'667ns); |
| EXPECT_EQ(offsets.earlyGpu.appWorkDuration, 20'666'667ns); |
| } |
| |
| TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_90Hz) { |
| auto offsets = mPhaseOffsets.getConfigsForRefreshRate(90_Hz); |
| |
| EXPECT_EQ(offsets.late.sfOffset, 1'000'000); |
| EXPECT_EQ(offsets.late.appOffset, 2'000'000); |
| |
| EXPECT_EQ(offsets.late.sfWorkDuration, 10'111'111ns); |
| EXPECT_EQ(offsets.late.appWorkDuration, 21'222'222ns); |
| |
| EXPECT_EQ(offsets.early.sfOffset, 2'000'000); |
| EXPECT_EQ(offsets.early.appOffset, 3'000'000); |
| |
| EXPECT_EQ(offsets.early.sfWorkDuration, 9'111'111ns); |
| EXPECT_EQ(offsets.early.appWorkDuration, 21'222'222ns); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfOffset, 3'000'000); |
| EXPECT_EQ(offsets.earlyGpu.appOffset, 4'000'000); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfWorkDuration, 8'111'111ns); |
| EXPECT_EQ(offsets.earlyGpu.appWorkDuration, 21'222'222ns); |
| } |
| |
| TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_DefaultValues_60Hz) { |
| TestablePhaseOffsets phaseOffsets{1'000'000, 1'000'000, {}, {}, {}, {}, 2'000'000, |
| 1'000'000, {}, {}, {}, {}, 10'000'000, 1234}; |
| auto offsets = phaseOffsets.getConfigsForRefreshRate(60_Hz); |
| |
| EXPECT_EQ(offsets.late.sfOffset, 1'000'000); |
| EXPECT_EQ(offsets.late.appOffset, 1'000'000); |
| |
| EXPECT_EQ(offsets.late.sfWorkDuration, 15'666'667ns); |
| EXPECT_EQ(offsets.late.appWorkDuration, 16'666'667ns); |
| |
| EXPECT_EQ(offsets.early.sfOffset, 1'000'000); |
| EXPECT_EQ(offsets.early.appOffset, 1'000'000); |
| |
| EXPECT_EQ(offsets.early.sfWorkDuration, 15'666'667ns); |
| EXPECT_EQ(offsets.early.appWorkDuration, 16'666'667ns); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfOffset, 1'000'000); |
| EXPECT_EQ(offsets.earlyGpu.appOffset, 1'000'000); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfWorkDuration, 15'666'667ns); |
| EXPECT_EQ(offsets.earlyGpu.appWorkDuration, 16'666'667ns); |
| } |
| |
| TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_DefaultValues_90Hz) { |
| TestablePhaseOffsets phaseOffsets{1'000'000, 1'000'000, {}, {}, {}, {}, 2'000'000, |
| 1'000'000, {}, {}, {}, {}, 10'000'000, 1234}; |
| auto offsets = phaseOffsets.getConfigsForRefreshRate(90_Hz); |
| |
| EXPECT_EQ(offsets.late.sfOffset, 1'000'000); |
| EXPECT_EQ(offsets.late.appOffset, 2'000'000); |
| |
| EXPECT_EQ(offsets.late.sfWorkDuration, 10'111'111ns); |
| EXPECT_EQ(offsets.late.appWorkDuration, 21'222'222ns); |
| |
| EXPECT_EQ(offsets.early.sfOffset, 1'000'000); |
| EXPECT_EQ(offsets.early.appOffset, 2'000'000); |
| |
| EXPECT_EQ(offsets.early.sfWorkDuration, 10'111'111ns); |
| EXPECT_EQ(offsets.early.appWorkDuration, 21'222'222ns); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfOffset, 1'000'000); |
| EXPECT_EQ(offsets.earlyGpu.appOffset, 2'000'000); |
| |
| EXPECT_EQ(offsets.earlyGpu.sfWorkDuration, 10'111'111ns); |
| EXPECT_EQ(offsets.earlyGpu.appWorkDuration, 21'222'222ns); |
| } |
| |
| TEST_F(PhaseOffsetsTest, minHwcWorkDuration) { |
| TestablePhaseOffsets phaseOffsets{1'000'000, 1'000'000, {}, {}, {}, {}, 2'000'000, |
| 1'000'000, {}, {}, {}, {}, 10'000'000, 1234}; |
| EXPECT_EQ(phaseOffsets.getCurrentConfigs().hwcMinWorkDuration, 1234ns); |
| } |
| |
| } // namespace android::scheduler |