blob: 1f7bf5f2a8c913778cabb26b65225fb0bbc13746 [file] [log] [blame]
/*
* 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 <ftl/fake_guard.h>
#include <gmock/gmock.h>
#include <gui/ISurfaceComposer.h>
#include <scheduler/interface/ICompositor.h>
#include "Scheduler/EventThread.h"
#include "Scheduler/LayerHistory.h"
#include "Scheduler/Scheduler.h"
#include "Scheduler/VSyncTracker.h"
#include "Scheduler/VsyncController.h"
#include "Scheduler/VsyncSchedule.h"
#include "mock/MockVSyncDispatch.h"
#include "mock/MockVSyncTracker.h"
#include "mock/MockVsyncController.h"
namespace android {
class TestableSurfaceFlinger;
} // namespace android
namespace android::scheduler {
class TestableScheduler : public Scheduler, private ICompositor {
public:
TestableScheduler(RefreshRateSelectorPtr selectorPtr,
TestableSurfaceFlinger& testableSurfaceFlinger, ISchedulerCallback& callback);
TestableScheduler(std::unique_ptr<VsyncController> controller,
std::shared_ptr<VSyncTracker> tracker, RefreshRateSelectorPtr selectorPtr,
surfaceflinger::Factory& factory, TimeStats& timeStats,
ISchedulerCallback& schedulerCallback)
: Scheduler(*this, schedulerCallback,
(FeatureFlags)Feature::kContentDetection |
Feature::kSmallDirtyContentDetection,
factory, selectorPtr->getActiveMode().fps, timeStats) {
const auto displayId = selectorPtr->getActiveMode().modePtr->getPhysicalDisplayId();
registerDisplay(displayId, std::move(selectorPtr), std::move(controller),
std::move(tracker), displayId);
ON_CALL(*this, postMessage).WillByDefault([](sp<MessageHandler>&& handler) {
// Execute task to prevent broken promise exception on destruction.
handler->handleMessage(Message());
});
}
MOCK_METHOD(void, scheduleConfigure, (), (override));
MOCK_METHOD(void, scheduleFrame, (), (override));
MOCK_METHOD(void, postMessage, (sp<MessageHandler>&&), (override));
void doFrameSignal(ICompositor& compositor, VsyncId vsyncId) {
ftl::FakeGuard guard1(kMainThreadContext);
ftl::FakeGuard guard2(mDisplayLock);
Scheduler::onFrameSignal(compositor, vsyncId, TimePoint());
}
void setEventThread(Cycle cycle, std::unique_ptr<EventThread> eventThreadPtr) {
if (cycle == Cycle::Render) {
mRenderEventThread = std::move(eventThreadPtr);
mRenderEventConnection = mRenderEventThread->createEventConnection();
} else {
mLastCompositeEventThread = std::move(eventThreadPtr);
mLastCompositeEventConnection = mLastCompositeEventThread->createEventConnection();
}
}
auto refreshRateSelector() { return pacesetterSelectorPtr(); }
void registerDisplay(
PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr,
std::optional<PhysicalDisplayId> activeDisplayIdOpt = {},
std::shared_ptr<VSyncTracker> vsyncTracker = std::make_shared<mock::VSyncTracker>()) {
registerDisplay(displayId, std::move(selectorPtr),
std::make_unique<mock::VsyncController>(), vsyncTracker,
activeDisplayIdOpt.value_or(displayId));
}
void registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr,
std::unique_ptr<VsyncController> controller,
std::shared_ptr<VSyncTracker> tracker, PhysicalDisplayId activeDisplayId) {
ftl::FakeGuard guard(kMainThreadContext);
Scheduler::registerDisplayInternal(displayId, std::move(selectorPtr),
std::shared_ptr<VsyncSchedule>(
new VsyncSchedule(displayId, std::move(tracker),
std::make_shared<
mock::VSyncDispatch>(),
std::move(controller),
mockRequestHardwareVsync
.AsStdFunction())),
activeDisplayId);
}
testing::MockFunction<void(PhysicalDisplayId, bool)> mockRequestHardwareVsync;
void setDisplayPowerMode(PhysicalDisplayId displayId, hal::PowerMode powerMode) {
ftl::FakeGuard guard(kMainThreadContext);
Scheduler::setDisplayPowerMode(displayId, powerMode);
}
std::optional<PhysicalDisplayId> pacesetterDisplayId() const NO_THREAD_SAFETY_ANALYSIS {
return mPacesetterDisplayId;
}
void setPacesetterDisplay(PhysicalDisplayId displayId) {
ftl::FakeGuard guard(kMainThreadContext);
Scheduler::setPacesetterDisplay(displayId);
}
std::optional<hal::PowerMode> getDisplayPowerMode(PhysicalDisplayId id) {
ftl::FakeGuard guard1(kMainThreadContext);
ftl::FakeGuard guard2(mDisplayLock);
return mDisplays.get(id).transform(
[](const Display& display) { return display.powerMode; });
}
using Scheduler::resyncAllToHardwareVsync;
auto& mutableLayerHistory() { return mLayerHistory; }
auto& mutableAttachedChoreographers() NO_THREAD_SAFETY_ANALYSIS {
return mAttachedChoreographers;
}
size_t layerHistorySize() NO_THREAD_SAFETY_ANALYSIS {
return mLayerHistory.mActiveLayerInfos.size() + mLayerHistory.mInactiveLayerInfos.size();
}
size_t getNumActiveLayers() NO_THREAD_SAFETY_ANALYSIS {
return mLayerHistory.mActiveLayerInfos.size();
}
void replaceTouchTimer(int64_t millis,
std::function<void(bool isReset)>&& testCallback = nullptr) {
if (mTouchTimer) {
mTouchTimer.reset();
}
mTouchTimer.emplace(
"Testable Touch timer", std::chrono::milliseconds(millis),
[this, testCallback] {
touchTimerCallback(TimerState::Reset);
if (testCallback != nullptr) {
testCallback(true);
}
},
[this, testCallback] {
touchTimerCallback(TimerState::Expired);
if (testCallback != nullptr) {
testCallback(false);
}
});
mTouchTimer->start();
}
bool isTouchActive() {
std::lock_guard<std::mutex> lock(mPolicyLock);
return mPolicy.touch == Scheduler::TouchState::Active;
}
void setTouchStateAndIdleTimerPolicy(GlobalSignals globalSignals) {
std::lock_guard<std::mutex> lock(mPolicyLock);
mPolicy.touch = globalSignals.touch ? TouchState::Active : TouchState::Inactive;
mPolicy.idleTimer = globalSignals.idle ? TimerState::Expired : TimerState::Reset;
}
void setContentRequirements(std::vector<RefreshRateSelector::LayerRequirement> layers) {
std::lock_guard<std::mutex> lock(mPolicyLock);
mPolicy.contentRequirements = std::move(layers);
}
using Scheduler::DisplayModeChoice;
using Scheduler::DisplayModeChoiceMap;
DisplayModeChoiceMap chooseDisplayModes() NO_THREAD_SAFETY_ANALYSIS {
return Scheduler::chooseDisplayModes();
}
void dispatchCachedReportedMode() {
std::lock_guard<std::mutex> lock(mPolicyLock);
Scheduler::dispatchCachedReportedMode();
}
void clearCachedReportedMode() {
std::lock_guard<std::mutex> lock(mPolicyLock);
mPolicy.cachedModeChangedParams.reset();
}
void setInitialHwVsyncEnabled(PhysicalDisplayId id, bool enabled) {
auto schedule = getVsyncSchedule(id);
std::lock_guard<std::mutex> lock(schedule->mHwVsyncLock);
schedule->mHwVsyncState = enabled ? VsyncSchedule::HwVsyncState::Enabled
: VsyncSchedule::HwVsyncState::Disabled;
}
void updateAttachedChoreographers(
const surfaceflinger::frontend::LayerHierarchy& layerHierarchy,
Fps displayRefreshRate) {
Scheduler::updateAttachedChoreographers(layerHierarchy, displayRefreshRate);
}
using Scheduler::onHardwareVsyncRequest;
private:
// ICompositor overrides:
void configure() override {}
bool commit(PhysicalDisplayId, const scheduler::FrameTargets&) override { return false; }
CompositeResultsPerDisplay composite(PhysicalDisplayId,
const scheduler::FrameTargeters&) override {
return {};
}
void sample() override {}
void sendNotifyExpectedPresentHint(PhysicalDisplayId) override {}
};
} // namespace android::scheduler