blob: 60952bfa2fee03f8ced281f6772a1028fec735ea [file] [log] [blame]
/*
* Copyright 2020 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 <gmock/gmock.h>
#include <gtest/gtest.h>
#include "Scheduler/VsyncModulator.h"
namespace android::scheduler {
class VsyncModulatorTest : public testing::Test {
enum {
SF_OFFSET_LATE,
APP_OFFSET_LATE,
SF_DURATION_LATE,
APP_DURATION_LATE,
SF_OFFSET_EARLY,
APP_OFFSET_EARLY,
SF_DURATION_EARLY,
APP_DURATION_EARLY,
SF_OFFSET_EARLY_GPU,
APP_OFFSET_EARLY_GPU,
SF_DURATION_EARLY_GPU,
APP_DURATION_EARLY_GPU,
HWC_MIN_WORK_DURATION,
};
static VsyncModulator::TimePoint Now() {
static VsyncModulator::TimePoint now;
return now += VsyncModulator::MIN_EARLY_TRANSACTION_TIME;
}
protected:
static constexpr auto MIN_EARLY_TRANSACTION_FRAMES =
VsyncModulator::MIN_EARLY_TRANSACTION_FRAMES;
using Schedule = scheduler::TransactionSchedule;
using nanos = std::chrono::nanoseconds;
const VsyncModulator::VsyncConfig kEarly{SF_OFFSET_EARLY, APP_OFFSET_EARLY,
nanos(SF_DURATION_LATE), nanos(APP_DURATION_LATE)};
const VsyncModulator::VsyncConfig kEarlyGpu{SF_OFFSET_EARLY_GPU, APP_OFFSET_EARLY_GPU,
nanos(SF_DURATION_EARLY),
nanos(APP_DURATION_EARLY)};
const VsyncModulator::VsyncConfig kLate{SF_OFFSET_LATE, APP_OFFSET_LATE,
nanos(SF_DURATION_EARLY_GPU),
nanos(APP_DURATION_EARLY_GPU)};
const VsyncModulator::VsyncConfigSet mOffsets = {kEarly, kEarlyGpu, kLate,
nanos(HWC_MIN_WORK_DURATION)};
VsyncModulator mVsyncModulator{mOffsets, Now};
void SetUp() override { EXPECT_EQ(kLate, mVsyncModulator.setVsyncConfigSet(mOffsets)); }
};
#define CHECK_COMMIT(result, configs) \
EXPECT_EQ(result, mVsyncModulator.onTransactionCommit()); \
EXPECT_EQ(configs, mVsyncModulator.getVsyncConfig());
#define CHECK_REFRESH(N, result, configs) \
for (int i = 0; i < N; i++) { \
EXPECT_EQ(result, mVsyncModulator.onDisplayRefresh(false)); \
EXPECT_EQ(configs, mVsyncModulator.getVsyncConfig()); \
}
TEST_F(VsyncModulatorTest, Late) {
EXPECT_FALSE(mVsyncModulator.setTransactionSchedule(Schedule::Late));
CHECK_COMMIT(std::nullopt, kLate);
CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kLate);
}
TEST_F(VsyncModulatorTest, EarlyEnd) {
EXPECT_EQ(kEarly, mVsyncModulator.setTransactionSchedule(Schedule::EarlyEnd));
CHECK_COMMIT(kEarly, kEarly);
CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
CHECK_REFRESH(1, kLate, kLate);
}
TEST_F(VsyncModulatorTest, EarlyStart) {
EXPECT_EQ(kEarly, mVsyncModulator.setTransactionSchedule(Schedule::EarlyStart));
CHECK_COMMIT(kEarly, kEarly);
CHECK_REFRESH(5 * MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kEarly);
EXPECT_EQ(kEarly, mVsyncModulator.setTransactionSchedule(Schedule::EarlyEnd));
CHECK_COMMIT(kEarly, kEarly);
CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
CHECK_REFRESH(1, kLate, kLate);
}
TEST_F(VsyncModulatorTest, EarlyStartWithMoreTransactions) {
EXPECT_EQ(kEarly, mVsyncModulator.setTransactionSchedule(Schedule::EarlyStart));
CHECK_COMMIT(kEarly, kEarly);
for (int i = 0; i < 5 * MIN_EARLY_TRANSACTION_FRAMES; i++) {
EXPECT_FALSE(mVsyncModulator.setTransactionSchedule(Schedule::Late));
CHECK_REFRESH(1, std::nullopt, kEarly);
}
EXPECT_EQ(kEarly, mVsyncModulator.setTransactionSchedule(Schedule::EarlyEnd));
CHECK_COMMIT(kEarly, kEarly);
CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
CHECK_REFRESH(1, kLate, kLate);
}
TEST_F(VsyncModulatorTest, EarlyStartAfterEarlyEnd) {
EXPECT_EQ(kEarly, mVsyncModulator.setTransactionSchedule(Schedule::EarlyEnd));
CHECK_COMMIT(kEarly, kEarly);
CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
EXPECT_EQ(kEarly, mVsyncModulator.setTransactionSchedule(Schedule::EarlyStart));
CHECK_COMMIT(kEarly, kEarly);
CHECK_REFRESH(1, kEarly, kEarly);
CHECK_REFRESH(5 * MIN_EARLY_TRANSACTION_FRAMES, std::nullopt, kEarly);
EXPECT_EQ(kEarly, mVsyncModulator.setTransactionSchedule(Schedule::EarlyEnd));
CHECK_COMMIT(kEarly, kEarly);
CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
CHECK_REFRESH(1, kLate, kLate);
}
TEST_F(VsyncModulatorTest, EarlyStartAfterEarlyEndWithMoreTransactions) {
EXPECT_EQ(kEarly, mVsyncModulator.setTransactionSchedule(Schedule::EarlyEnd));
CHECK_COMMIT(kEarly, kEarly);
CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
EXPECT_EQ(kEarly, mVsyncModulator.setTransactionSchedule(Schedule::EarlyStart));
CHECK_COMMIT(kEarly, kEarly);
CHECK_REFRESH(1, kEarly, kEarly);
for (int i = 0; i < 5 * MIN_EARLY_TRANSACTION_FRAMES; i++) {
EXPECT_FALSE(mVsyncModulator.setTransactionSchedule(Schedule::Late));
CHECK_REFRESH(1, std::nullopt, kEarly);
}
EXPECT_EQ(kEarly, mVsyncModulator.setTransactionSchedule(Schedule::EarlyEnd));
CHECK_COMMIT(kEarly, kEarly);
CHECK_REFRESH(MIN_EARLY_TRANSACTION_FRAMES - 1, kEarly, kEarly);
CHECK_REFRESH(1, kLate, kLate);
}
} // namespace android::scheduler