/* * Copyright 2021 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 #include #include #include #include #include #include #include #include #include "DisplayDevice.h" #include "DisplayHardware/ComposerHal.h" #include "FrameTimeline/FrameTimeline.h" #include "FrameTracer/FrameTracer.h" #include "FrontEnd/LayerHandle.h" #include "Layer.h" #include "NativeWindowSurface.h" #include "Scheduler/EventThread.h" #include "Scheduler/MessageQueue.h" #include "Scheduler/RefreshRateSelector.h" #include "Scheduler/VSyncTracker.h" #include "Scheduler/VsyncConfiguration.h" #include "Scheduler/VsyncController.h" #include "Scheduler/VsyncModulator.h" #include "StartPropertySetThread.h" #include "SurfaceFlinger.h" #include "SurfaceFlingerDefaultFactory.h" #include "ThreadContext.h" #include "TimeStats/TimeStats.h" #include "surfaceflinger_scheduler_fuzzer.h" #include "renderengine/mock/RenderEngine.h" #include "scheduler/TimeKeeper.h" #include "tests/unittests/mock/DisplayHardware/MockComposer.h" #include "tests/unittests/mock/DisplayHardware/MockDisplayMode.h" #include "tests/unittests/mock/DisplayHardware/MockHWC2.h" #include "tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h" #include "tests/unittests/mock/MockEventThread.h" #include "tests/unittests/mock/MockFrameTimeline.h" #include "tests/unittests/mock/MockFrameTracer.h" #include "tests/unittests/mock/MockNativeWindowSurface.h" #include "tests/unittests/mock/MockTimeStats.h" #include "tests/unittests/mock/MockVSyncTracker.h" #include "tests/unittests/mock/MockVsyncController.h" namespace android { namespace Hwc2 { class Composer; namespace types = hardware::graphics::common; namespace V2_1 = hardware::graphics::composer::V2_1; namespace V2_2 = hardware::graphics::composer::V2_2; namespace V2_3 = hardware::graphics::composer::V2_3; namespace V2_4 = hardware::graphics::composer::V2_4; using types::V1_0::ColorTransform; using types::V1_0::Transform; using types::V1_1::RenderIntent; using types::V1_2::ColorMode; using types::V1_2::Dataspace; using types::V1_2::PixelFormat; using V2_1::Config; using V2_1::Display; using V2_1::Error; using V2_1::Layer; using V2_4::CommandReaderBase; using V2_4::CommandWriterBase; using V2_4::IComposer; using V2_4::IComposerCallback; using V2_4::IComposerClient; using V2_4::VsyncPeriodChangeTimeline; using V2_4::VsyncPeriodNanos; using DisplayCapability = IComposerClient::DisplayCapability; using PerFrameMetadata = IComposerClient::PerFrameMetadata; using PerFrameMetadataKey = IComposerClient::PerFrameMetadataKey; using PerFrameMetadataBlob = IComposerClient::PerFrameMetadataBlob; }; // namespace Hwc2 static constexpr hal::HWDisplayId kHwDisplayId = 1000; static constexpr ui::Hdr kHdrTypes[] = {ui::Hdr::DOLBY_VISION, ui::Hdr::HDR10, ui::Hdr::HLG, ui::Hdr::HDR10_PLUS}; static constexpr ui::ColorMode kColormodes[] = {ui::ColorMode::NATIVE, ui::ColorMode::STANDARD_BT601_625, ui::ColorMode::STANDARD_BT601_625_UNADJUSTED, ui::ColorMode::STANDARD_BT601_525, ui::ColorMode::STANDARD_BT601_525_UNADJUSTED, ui::ColorMode::STANDARD_BT709, ui::ColorMode::DCI_P3, ui::ColorMode::SRGB, ui::ColorMode::ADOBE_RGB, ui::ColorMode::DISPLAY_P3, ui::ColorMode::BT2020, ui::ColorMode::BT2100_PQ, ui::ColorMode::BT2100_HLG, ui::ColorMode::DISPLAY_BT2020}; static constexpr ui::PixelFormat kPixelFormats[] = {ui::PixelFormat::RGBA_8888, ui::PixelFormat::RGBX_8888, ui::PixelFormat::RGB_888, ui::PixelFormat::RGB_565, ui::PixelFormat::BGRA_8888, ui::PixelFormat::YCBCR_422_SP, ui::PixelFormat::YCRCB_420_SP, ui::PixelFormat::YCBCR_422_I, ui::PixelFormat::RGBA_FP16, ui::PixelFormat::RAW16, ui::PixelFormat::BLOB, ui::PixelFormat::IMPLEMENTATION_DEFINED, ui::PixelFormat::YCBCR_420_888, ui::PixelFormat::RAW_OPAQUE, ui::PixelFormat::RAW10, ui::PixelFormat::RAW12, ui::PixelFormat::RGBA_1010102, ui::PixelFormat::Y8, ui::PixelFormat::Y16, ui::PixelFormat::YV12, ui::PixelFormat::DEPTH_16, ui::PixelFormat::DEPTH_24, ui::PixelFormat::DEPTH_24_STENCIL_8, ui::PixelFormat::DEPTH_32F, ui::PixelFormat::DEPTH_32F_STENCIL_8, ui::PixelFormat::STENCIL_8, ui::PixelFormat::YCBCR_P010, ui::PixelFormat::HSV_888}; inline VsyncId getFuzzedVsyncId(FuzzedDataProvider& fdp) { return VsyncId{fdp.ConsumeIntegral()}; } inline TimePoint getFuzzedTimePoint(FuzzedDataProvider& fdp) { return TimePoint::fromNs(fdp.ConsumeIntegral()); } inline Duration getFuzzedDuration(FuzzedDataProvider& fdp) { return Duration::fromNs(fdp.ConsumeIntegral()); } inline FloatRect getFuzzedFloatRect(FuzzedDataProvider* fdp) { return FloatRect(fdp->ConsumeFloatingPoint() /*left*/, fdp->ConsumeFloatingPoint() /*right*/, fdp->ConsumeFloatingPoint() /*top*/, fdp->ConsumeFloatingPoint() /*bottom*/); } inline HdrMetadata getFuzzedHdrMetadata(FuzzedDataProvider* fdp) { HdrMetadata hdrMetadata; if (fdp->ConsumeBool()) { hdrMetadata.cta8613.maxContentLightLevel = fdp->ConsumeFloatingPoint(); hdrMetadata.cta8613.maxFrameAverageLightLevel = fdp->ConsumeFloatingPoint(); hdrMetadata.validTypes |= HdrMetadata::CTA861_3; } else { hdrMetadata.smpte2086.displayPrimaryRed.x = fdp->ConsumeFloatingPoint(); hdrMetadata.smpte2086.displayPrimaryRed.y = fdp->ConsumeFloatingPoint(); hdrMetadata.smpte2086.displayPrimaryGreen.x = fdp->ConsumeFloatingPoint(); hdrMetadata.smpte2086.displayPrimaryGreen.y = fdp->ConsumeFloatingPoint(); hdrMetadata.smpte2086.displayPrimaryBlue.x = fdp->ConsumeFloatingPoint(); hdrMetadata.smpte2086.displayPrimaryBlue.y = fdp->ConsumeFloatingPoint(); hdrMetadata.smpte2086.whitePoint.x = fdp->ConsumeFloatingPoint(); hdrMetadata.smpte2086.whitePoint.y = fdp->ConsumeFloatingPoint(); hdrMetadata.smpte2086.minLuminance = fdp->ConsumeFloatingPoint(); hdrMetadata.smpte2086.maxLuminance = fdp->ConsumeFloatingPoint(); hdrMetadata.validTypes |= HdrMetadata::SMPTE2086; } return hdrMetadata; } class EventThread; namespace hal = android::hardware::graphics::composer::hal; struct FakePhaseOffsets : scheduler::VsyncConfiguration { static constexpr nsecs_t FAKE_PHASE_OFFSET_NS = 0; static constexpr auto FAKE_DURATION_OFFSET_NS = std::chrono::nanoseconds(0); scheduler::VsyncConfigSet getConfigsForRefreshRate(Fps) const override { return getCurrentConfigs(); } scheduler::VsyncConfigSet getCurrentConfigs() const override { return {{FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS, FAKE_DURATION_OFFSET_NS, FAKE_DURATION_OFFSET_NS}, {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS, FAKE_DURATION_OFFSET_NS, FAKE_DURATION_OFFSET_NS}, {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS, FAKE_DURATION_OFFSET_NS, FAKE_DURATION_OFFSET_NS}, FAKE_DURATION_OFFSET_NS}; } void reset() override {} void setRefreshRateFps(Fps) override {} void dump(std::string &) const override {} }; namespace scheduler { class TestableScheduler : public Scheduler, private ICompositor { public: TestableScheduler(const std::shared_ptr& selectorPtr, sp modulatorPtr, ISchedulerCallback& callback) : TestableScheduler(std::make_unique(), std::make_shared(), selectorPtr, std::move(modulatorPtr), callback) {} TestableScheduler(std::unique_ptr controller, VsyncSchedule::TrackerPtr tracker, std::shared_ptr selectorPtr, sp modulatorPtr, ISchedulerCallback& callback) : Scheduler(*this, callback, Feature::kContentDetection, std::move(modulatorPtr)) { const auto displayId = selectorPtr->getActiveMode().modePtr->getPhysicalDisplayId(); registerDisplayInternal(displayId, std::move(selectorPtr), std::shared_ptr( new VsyncSchedule(displayId, std::move(tracker), std::make_shared(), std::move(controller)))); } ConnectionHandle createConnection(std::unique_ptr eventThread) { return Scheduler::createConnection(std::move(eventThread)); } auto &mutableLayerHistory() { return mLayerHistory; } auto refreshRateSelector() { return pacesetterSelectorPtr(); } void replaceTouchTimer(int64_t millis) { if (mTouchTimer) { mTouchTimer.reset(); } mTouchTimer.emplace( "Testable Touch timer", std::chrono::milliseconds(millis), [this] { touchTimerCallback(TimerState::Reset); }, [this] { touchTimerCallback(TimerState::Expired); }); mTouchTimer->start(); } bool isTouchActive() { std::lock_guard lock(mPolicyLock); return mPolicy.touch == Scheduler::TouchState::Active; } void dispatchCachedReportedMode() { std::lock_guard lock(mPolicyLock); return Scheduler::dispatchCachedReportedMode(); } void clearCachedReportedMode() { std::lock_guard lock(mPolicyLock); mPolicy.cachedModeChangedParams.reset(); } void onNonPrimaryDisplayModeChanged(ConnectionHandle handle, const FrameRateMode &mode) { return Scheduler::onNonPrimaryDisplayModeChanged(handle, mode); } using Scheduler::setVsyncConfig; private: // ICompositor overrides: void configure() override {} bool commit(TimePoint, VsyncId, TimePoint) override { return false; } void composite(TimePoint, VsyncId) override {} void sample() override {} // MessageQueue overrides: void scheduleFrame() override {} void postMessage(sp&&) override {} }; } // namespace scheduler namespace surfaceflinger::test { class Factory final : public surfaceflinger::Factory { struct NoOpMessageQueue : android::impl::MessageQueue { using android::impl::MessageQueue::MessageQueue; void onFrameSignal(ICompositor&, VsyncId, TimePoint) override {} }; public: ~Factory() = default; std::unique_ptr createHWComposer(const std::string&) override { return nullptr; } std::unique_ptr createMessageQueue(ICompositor& compositor) { return std::make_unique(compositor); } std::unique_ptr createVsyncConfiguration( Fps /*currentRefreshRate*/) override { return std::make_unique(); } std::unique_ptr createScheduler( const std::shared_ptr&, scheduler::ISchedulerCallback&) { return nullptr; } sp createStartPropertySetThread(bool timestampPropertyValue) override { return sp::make(timestampPropertyValue); } sp createDisplayDevice(DisplayDeviceCreationArgs &creationArgs) override { return sp::make(creationArgs); } sp createGraphicBuffer(uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount, uint64_t usage, std::string requestorName) override { return sp::make(width, height, format, layerCount, usage, requestorName); } void createBufferQueue(sp *outProducer, sp *outConsumer, bool consumerIsSurfaceFlinger) override { if (!mCreateBufferQueue) { BufferQueue::createBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger); return; } mCreateBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger); } std::unique_ptr createNativeWindowSurface( const sp &producer) override { if (!mCreateNativeWindowSurface) return nullptr; return mCreateNativeWindowSurface(producer); } std::unique_ptr createCompositionEngine() override { return compositionengine::impl::createCompositionEngine(); } sp createBufferStateLayer(const LayerCreationArgs &) override { return nullptr; } sp createEffectLayer(const LayerCreationArgs &args) override { return sp::make(args); } sp createLayerFE(const std::string &layerName) override { return sp::make(layerName); } std::unique_ptr createFrameTracer() override { return std::make_unique(); } std::unique_ptr createFrameTimeline( std::shared_ptr timeStats, pid_t surfaceFlingerPid = 0) override { return std::make_unique(timeStats, surfaceFlingerPid); } using CreateBufferQueueFunction = std::function * /* outProducer */, sp * /* outConsumer */, bool /* consumerIsSurfaceFlinger */)>; CreateBufferQueueFunction mCreateBufferQueue; using CreateNativeWindowSurfaceFunction = std::function( const sp &)>; CreateNativeWindowSurfaceFunction mCreateNativeWindowSurface; using CreateCompositionEngineFunction = std::function()>; CreateCompositionEngineFunction mCreateCompositionEngine; }; } // namespace surfaceflinger::test // TODO(b/189053744) : Create a common test/mock library for surfaceflinger class TestableSurfaceFlinger final : private scheduler::ISchedulerCallback { public: using HotplugEvent = SurfaceFlinger::HotplugEvent; SurfaceFlinger *flinger() { return mFlinger.get(); } scheduler::TestableScheduler *scheduler() { return mScheduler; } void initializeDisplays() { FTL_FAKE_GUARD(kMainThreadContext, mFlinger->initializeDisplays()); } void setGlobalShadowSettings(FuzzedDataProvider *fdp) { const half4 ambientColor{fdp->ConsumeFloatingPoint(), fdp->ConsumeFloatingPoint(), fdp->ConsumeFloatingPoint(), fdp->ConsumeFloatingPoint()}; const half4 spotColor{fdp->ConsumeFloatingPoint(), fdp->ConsumeFloatingPoint(), fdp->ConsumeFloatingPoint(), fdp->ConsumeFloatingPoint()}; float lightPosY = fdp->ConsumeFloatingPoint(); float lightPosZ = fdp->ConsumeFloatingPoint(); float lightRadius = fdp->ConsumeFloatingPoint(); mFlinger->setGlobalShadowSettings(ambientColor, spotColor, lightPosY, lightPosZ, lightRadius); } void onPullAtom(FuzzedDataProvider *fdp) { const int32_t atomId = fdp->ConsumeIntegral(); std::vector pulledData = fdp->ConsumeRemainingBytes(); bool success = fdp->ConsumeBool(); mFlinger->onPullAtom(atomId, &pulledData, &success); } void fuzzDumpsysAndDebug(FuzzedDataProvider *fdp) { std::string result = fdp->ConsumeRandomLengthString().c_str(); mFlinger->appendSfConfigString(result); result = fdp->ConsumeRandomLengthString().c_str(); mFlinger->listLayersLocked(result); using DumpArgs = Vector; DumpArgs dumpArgs; dumpArgs.push_back(String16(fdp->ConsumeRandomLengthString().c_str())); mFlinger->clearStatsLocked(dumpArgs, result); mFlinger->dumpTimeStats(dumpArgs, fdp->ConsumeBool(), result); FTL_FAKE_GUARD(kMainThreadContext, mFlinger->logFrameStats(TimePoint::fromNs(fdp->ConsumeIntegral()))); result = fdp->ConsumeRandomLengthString().c_str(); mFlinger->dumpFrameTimeline(dumpArgs, result); result = fdp->ConsumeRandomLengthString().c_str(); mFlinger->dumpRawDisplayIdentificationData(dumpArgs, result); LayersProto layersProto = mFlinger->dumpDrawingStateProto(fdp->ConsumeIntegral()); mFlinger->dumpOffscreenLayersProto(layersProto); mFlinger->dumpDisplayProto(); result = fdp->ConsumeRandomLengthString().c_str(); mFlinger->dumpHwc(result); mFlinger->calculateColorMatrix(fdp->ConsumeFloatingPoint()); mFlinger->updateColorMatrixLocked(); mFlinger->CheckTransactCodeCredentials(fdp->ConsumeIntegral()); } void getCompositionPreference() { ui::Dataspace outDataspace; ui::PixelFormat outPixelFormat; ui::Dataspace outWideColorGamutDataspace; ui::PixelFormat outWideColorGamutPixelFormat; mFlinger->getCompositionPreference(&outDataspace, &outPixelFormat, &outWideColorGamutDataspace, &outWideColorGamutPixelFormat); } void overrideHdrTypes(sp &display, FuzzedDataProvider *fdp) { std::vector hdrTypes; hdrTypes.push_back(fdp->PickValueInArray(kHdrTypes)); mFlinger->overrideHdrTypes(display, hdrTypes); } void getDisplayedContentSample(sp &display, FuzzedDataProvider *fdp) { DisplayedFrameStats outDisplayedFrameStats; mFlinger->getDisplayedContentSample(display, fdp->ConsumeIntegral(), fdp->ConsumeIntegral(), &outDisplayedFrameStats); } void getDisplayStats(sp &display) { android::DisplayStatInfo stats; mFlinger->getDisplayStats(display, &stats); } void getDisplayState(sp &display) { ui::DisplayState displayState; mFlinger->getDisplayState(display, &displayState); } void getStaticDisplayInfo(int64_t displayId) { ui::StaticDisplayInfo staticDisplayInfo; mFlinger->getStaticDisplayInfo(displayId, &staticDisplayInfo); } void getDynamicDisplayInfo(int64_t displayId) { android::ui::DynamicDisplayInfo dynamicDisplayInfo; mFlinger->getDynamicDisplayInfoFromId(displayId, &dynamicDisplayInfo); } void getDisplayNativePrimaries(sp &display) { android::ui::DisplayPrimaries displayPrimaries; mFlinger->getDisplayNativePrimaries(display, displayPrimaries); } void getDesiredDisplayModeSpecs(sp &display) { gui::DisplayModeSpecs _; mFlinger->getDesiredDisplayModeSpecs(display, &_); } // TODO(b/248317436): extend to cover all displays for multi-display devices static std::optional getFirstDisplayId() { std::vector ids = SurfaceComposerClient::getPhysicalDisplayIds(); if (ids.empty()) return {}; return ids.front(); } std::pair, int64_t> fuzzBoot(FuzzedDataProvider *fdp) { mFlinger->callingThreadHasUnscopedSurfaceFlingerAccess(fdp->ConsumeBool()); const sp client = sp::make(mFlinger); DisplayIdGenerator kGenerator; HalVirtualDisplayId halVirtualDisplayId = kGenerator.generateId().value(); ui::Size uiSize{fdp->ConsumeIntegral(), fdp->ConsumeIntegral()}; ui::PixelFormat pixelFormat{}; mFlinger->getHwComposer().allocateVirtualDisplay(halVirtualDisplayId, uiSize, &pixelFormat); PhysicalDisplayId physicalDisplayId = getFirstDisplayId().value_or( PhysicalDisplayId::fromPort(fdp->ConsumeIntegral())); mFlinger->getHwComposer().allocatePhysicalDisplay(kHwDisplayId, physicalDisplayId); sp display = mFlinger->createDisplay(String8(fdp->ConsumeRandomLengthString().c_str()), fdp->ConsumeBool()); initializeDisplays(); mFlinger->getPhysicalDisplayToken(physicalDisplayId); mFlinger->mStartPropertySetThread = mFlinger->getFactory().createStartPropertySetThread(fdp->ConsumeBool()); mFlinger->bootFinished(); return {display, physicalDisplayId.value}; } void fuzzSurfaceFlinger(const uint8_t *data, size_t size) { FuzzedDataProvider mFdp(data, size); auto [display, displayId] = fuzzBoot(&mFdp); sp bufferProducer = sp::make(); mFlinger->createDisplayEventConnection(); getDisplayStats(display); getDisplayState(display); getStaticDisplayInfo(displayId); getDynamicDisplayInfo(displayId); getDisplayNativePrimaries(display); mFlinger->setAutoLowLatencyMode(display, mFdp.ConsumeBool()); mFlinger->setGameContentType(display, mFdp.ConsumeBool()); mFlinger->setPowerMode(display, mFdp.ConsumeIntegral()); overrideHdrTypes(display, &mFdp); onPullAtom(&mFdp); getCompositionPreference(); getDisplayedContentSample(display, &mFdp); getDesiredDisplayModeSpecs(display); bool outSupport; mFlinger->getDisplayBrightnessSupport(display, &outSupport); mFlinger->notifyPowerBoost(mFdp.ConsumeIntegral()); setGlobalShadowSettings(&mFdp); mFlinger->binderDied(display); mFlinger->onFirstRef(); mFlinger->updateInputFlinger(VsyncId{}, TimePoint{}); mFlinger->updateCursorAsync(); mutableScheduler().setVsyncConfig({.sfOffset = mFdp.ConsumeIntegral(), .appOffset = mFdp.ConsumeIntegral(), .sfWorkDuration = getFuzzedDuration(mFdp), .appWorkDuration = getFuzzedDuration(mFdp)}, getFuzzedDuration(mFdp)); { ftl::FakeGuard guard(kMainThreadContext); mFlinger->commitTransactions(); mFlinger->flushTransactionQueues(getFuzzedVsyncId(mFdp)); mFlinger->postComposition(systemTime()); } mFlinger->setTransactionFlags(mFdp.ConsumeIntegral()); mFlinger->clearTransactionFlags(mFdp.ConsumeIntegral()); mFlinger->commitOffscreenLayers(); mFlinger->frameIsEarly(getFuzzedTimePoint(mFdp), getFuzzedVsyncId(mFdp)); mFlinger->computeLayerBounds(); mFlinger->startBootAnim(); mFlinger->readPersistentProperties(); mFlinger->exceedsMaxRenderTargetSize(mFdp.ConsumeIntegral(), mFdp.ConsumeIntegral()); mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mFdp.ConsumeIntegral()); mFlinger->calculateExpectedPresentTime({}); mFlinger->enableHalVirtualDisplays(mFdp.ConsumeBool()); fuzzDumpsysAndDebug(&mFdp); mFlinger->destroyDisplay(display); } void setupRenderEngine(std::unique_ptr renderEngine) { mFlinger->mRenderEngine = std::move(renderEngine); mFlinger->mCompositionEngine->setRenderEngine(mFlinger->mRenderEngine.get()); } void setupComposer(std::unique_ptr composer) { mFlinger->mCompositionEngine->setHwComposer( std::make_unique(std::move(composer))); } void setupTimeStats(const std::shared_ptr &timeStats) { mFlinger->mCompositionEngine->setTimeStats(timeStats); } // The ISchedulerCallback argument can be nullptr for a no-op implementation. void setupScheduler(std::unique_ptr vsyncController, std::shared_ptr vsyncTracker, std::unique_ptr appEventThread, std::unique_ptr sfEventThread, scheduler::ISchedulerCallback* callback = nullptr, bool hasMultipleModes = false) { constexpr DisplayModeId kModeId60{0}; DisplayModes modes = makeModes(mock::createDisplayMode(kModeId60, 60_Hz)); if (hasMultipleModes) { constexpr DisplayModeId kModeId90{1}; modes.try_emplace(kModeId90, mock::createDisplayMode(kModeId90, 90_Hz)); } mRefreshRateSelector = std::make_shared(modes, kModeId60); const auto fps = mRefreshRateSelector->getActiveMode().modePtr->getFps(); mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(fps); mFlinger->mRefreshRateStats = std::make_unique(*mFlinger->mTimeStats, fps, hal::PowerMode::OFF); auto modulatorPtr = sp::make( mFlinger->mVsyncConfiguration->getCurrentConfigs()); mScheduler = new scheduler::TestableScheduler(std::move(vsyncController), std::move(vsyncTracker), mRefreshRateSelector, std::move(modulatorPtr), *(callback ?: this)); mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread)); mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread)); resetScheduler(mScheduler); } void resetScheduler(scheduler::Scheduler *scheduler) { mFlinger->mScheduler.reset(scheduler); } scheduler::TestableScheduler &mutableScheduler() const { return *mScheduler; } using CreateBufferQueueFunction = surfaceflinger::test::Factory::CreateBufferQueueFunction; void setCreateBufferQueueFunction(CreateBufferQueueFunction f) { mFactory.mCreateBufferQueue = f; } using CreateNativeWindowSurfaceFunction = surfaceflinger::test::Factory::CreateNativeWindowSurfaceFunction; void setCreateNativeWindowSurface(CreateNativeWindowSurfaceFunction f) { mFactory.mCreateNativeWindowSurface = f; } void setInternalDisplayPrimaries(const ui::DisplayPrimaries &primaries) { memcpy(&mFlinger->mInternalDisplayPrimaries, &primaries, sizeof(ui::DisplayPrimaries)); } static auto &mutableLayerDrawingState(const sp &layer) { return layer->mDrawingState; } auto &mutableStateLock() { return mFlinger->mStateLock; } static auto findOutputLayerForDisplay(const sp &layer, const sp &display) { return layer->findOutputLayerForDisplay(display.get()); } /* ------------------------------------------------------------------------ * Forwarding for functions being tested */ void enableHalVirtualDisplays(bool enable) { mFlinger->enableHalVirtualDisplays(enable); } void commitTransactionsLocked(uint32_t transactionFlags) FTL_FAKE_GUARD(kMainThreadContext) { Mutex::Autolock lock(mFlinger->mStateLock); mFlinger->commitTransactionsLocked(transactionFlags); } auto setDisplayStateLocked(const DisplayState &s) { Mutex::Autolock lock(mFlinger->mStateLock); return mFlinger->setDisplayStateLocked(s); } auto notifyPowerBoost(int32_t boostId) { return mFlinger->notifyPowerBoost(boostId); } // Allow reading display state without locking, as if called on the SF main thread. auto setPowerModeInternal(const sp &display, hal::PowerMode mode) NO_THREAD_SAFETY_ANALYSIS { return mFlinger->setPowerModeInternal(display, mode); } auto &getTransactionQueue() { return mFlinger->mTransactionHandler.mLocklessTransactionQueue; } auto &getPendingTransactionQueue() { return mFlinger->mTransactionHandler.mPendingTransactionQueues; } auto setTransactionState( const FrameTimelineInfo& frameTimelineInfo, Vector& states, Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const std::vector& uncacheBuffers, bool hasListenerCallbacks, std::vector& listenerCallbacks, uint64_t transactionId, const std::vector& mergedTransactionIds) { return mFlinger->setTransactionState(frameTimelineInfo, states, displays, flags, applyToken, inputWindowCommands, desiredPresentTime, isAutoTimestamp, uncacheBuffers, hasListenerCallbacks, listenerCallbacks, transactionId, mergedTransactionIds); } auto flushTransactionQueues() { ftl::FakeGuard guard(kMainThreadContext); return mFlinger->flushTransactionQueues(VsyncId{0}); } auto onTransact(uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { return mFlinger->onTransact(code, data, reply, flags); } auto getGpuContextPriority() { return mFlinger->getGpuContextPriority(); } auto calculateMaxAcquiredBufferCount(Fps refreshRate, std::chrono::nanoseconds presentLatency) const { return SurfaceFlinger::calculateMaxAcquiredBufferCount(refreshRate, presentLatency); } /* Read-write access to private data to set up preconditions and assert * post-conditions. */ auto& mutableSupportsWideColor() { return mFlinger->mSupportsWideColor; } auto& mutableCurrentState() { return mFlinger->mCurrentState; } auto& mutableDisplays() { return mFlinger->mDisplays; } auto& mutableDrawingState() { return mFlinger->mDrawingState; } auto fromHandle(const sp &handle) { return LayerHandle::getLayer(handle); } ~TestableSurfaceFlinger() { mutableDisplays().clear(); mutableCurrentState().displays.clear(); mutableDrawingState().displays.clear(); mFlinger->mScheduler.reset(); mFlinger->mCompositionEngine->setHwComposer(std::unique_ptr()); mFlinger->mRenderEngine = std::unique_ptr(); mFlinger->mCompositionEngine->setRenderEngine(mFlinger->mRenderEngine.get()); } private: void setVsyncEnabled(PhysicalDisplayId, bool) override {} void requestDisplayModes(std::vector) override {} void kernelTimerChanged(bool) override {} void triggerOnFrameRateOverridesChanged() override {} surfaceflinger::test::Factory mFactory; sp mFlinger = sp::make(mFactory, SurfaceFlinger::SkipInitialization); scheduler::TestableScheduler *mScheduler = nullptr; std::shared_ptr mRefreshRateSelector; }; } // namespace android