/* * 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 #include #include #include #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 controller, std::shared_ptr 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&& handler) { // Execute task to prevent broken promise exception on destruction. handler->handleMessage(Message()); }); } MOCK_METHOD(void, scheduleConfigure, (), (override)); MOCK_METHOD(void, scheduleFrame, (Duration), (override)); MOCK_METHOD(void, postMessage, (sp&&), (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 eventThreadPtr) { if (cycle == Cycle::Render) { mRenderEventThread = std::move(eventThreadPtr); } else { mLastCompositeEventThread = std::move(eventThreadPtr); } } auto refreshRateSelector() { return pacesetterSelectorPtr(); } void registerDisplay( PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, std::optional activeDisplayIdOpt = {}, std::shared_ptr vsyncTracker = std::make_shared()) { registerDisplay(displayId, std::move(selectorPtr), std::make_unique(), vsyncTracker, activeDisplayIdOpt.value_or(displayId)); } void registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr, std::unique_ptr controller, std::shared_ptr tracker, PhysicalDisplayId activeDisplayId) { ftl::FakeGuard guard(kMainThreadContext); Scheduler::registerDisplayInternal(displayId, std::move(selectorPtr), std::shared_ptr( new VsyncSchedule(displayId, std::move(tracker), std::make_shared< mock::VSyncDispatch>(), std::move(controller), mockRequestHardwareVsync .AsStdFunction())), activeDisplayId); } testing::MockFunction mockRequestHardwareVsync; void setDisplayPowerMode(PhysicalDisplayId displayId, hal::PowerMode powerMode) { ftl::FakeGuard guard(kMainThreadContext); Scheduler::setDisplayPowerMode(displayId, powerMode); } std::optional pacesetterDisplayId() const NO_THREAD_SAFETY_ANALYSIS { return mPacesetterDisplayId; } void setPacesetterDisplay(PhysicalDisplayId displayId) { ftl::FakeGuard guard(kMainThreadContext); Scheduler::setPacesetterDisplay(displayId); } std::optional 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&& 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 lock(mPolicyLock); return mPolicy.touch == Scheduler::TouchState::Active; } void setTouchStateAndIdleTimerPolicy(GlobalSignals globalSignals) { std::lock_guard lock(mPolicyLock); mPolicy.touch = globalSignals.touch ? TouchState::Active : TouchState::Inactive; mPolicy.idleTimer = globalSignals.idle ? TimerState::Expired : TimerState::Reset; } using Scheduler::TimerState; using Scheduler::idleTimerCallback; using Scheduler::touchTimerCallback; void setContentRequirements(std::vector layers) { std::lock_guard lock(mPolicyLock); mPolicy.contentRequirements = std::move(layers); } using Scheduler::DisplayModeChoice; using Scheduler::DisplayModeChoiceMap; DisplayModeChoiceMap chooseDisplayModes() NO_THREAD_SAFETY_ANALYSIS { return Scheduler::chooseDisplayModes(); } using Scheduler::onDisplayModeChanged; void setInitialHwVsyncEnabled(PhysicalDisplayId id, bool enabled) { auto schedule = getVsyncSchedule(id); std::lock_guard 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