| /* | 
 |  * Copyright (C) 2018 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 <compositionengine/Display.h> | 
 | #include <compositionengine/Layer.h> | 
 | #include <compositionengine/OutputLayer.h> | 
 | #include <compositionengine/impl/CompositionEngine.h> | 
 | #include <compositionengine/impl/LayerCompositionState.h> | 
 | #include <compositionengine/impl/OutputLayerCompositionState.h> | 
 |  | 
 | #include "BufferQueueLayer.h" | 
 | #include "BufferStateLayer.h" | 
 | #include "ColorLayer.h" | 
 | #include "ContainerLayer.h" | 
 | #include "DisplayDevice.h" | 
 | #include "FakePhaseOffsets.h" | 
 | #include "Layer.h" | 
 | #include "NativeWindowSurface.h" | 
 | #include "StartPropertySetThread.h" | 
 | #include "SurfaceFlinger.h" | 
 | #include "SurfaceFlingerFactory.h" | 
 | #include "SurfaceInterceptor.h" | 
 |  | 
 | #include "TimeStats/TimeStats.h" | 
 |  | 
 | namespace android { | 
 |  | 
 | class EventThread; | 
 |  | 
 | namespace renderengine { | 
 |  | 
 | class RenderEngine; | 
 |  | 
 | } // namespace renderengine | 
 |  | 
 | namespace Hwc2 { | 
 |  | 
 | class Composer; | 
 |  | 
 | } // namespace Hwc2 | 
 |  | 
 | namespace surfaceflinger::test { | 
 |  | 
 | class Factory final : public surfaceflinger::Factory { | 
 | public: | 
 |     ~Factory() = default; | 
 |  | 
 |     std::unique_ptr<DispSync> createDispSync(const char*, bool, int64_t) override { | 
 |         // TODO: Use test-fixture controlled factory | 
 |         return nullptr; | 
 |     } | 
 |  | 
 |     std::unique_ptr<EventControlThread> createEventControlThread( | 
 |             std::function<void(bool)>) override { | 
 |         // TODO: Use test-fixture controlled factory | 
 |         return nullptr; | 
 |     } | 
 |  | 
 |     std::unique_ptr<HWComposer> createHWComposer(const std::string&) override { | 
 |         // TODO: Use test-fixture controlled factory | 
 |         return nullptr; | 
 |     } | 
 |  | 
 |     std::unique_ptr<MessageQueue> createMessageQueue() override { | 
 |         // TODO: Use test-fixture controlled factory | 
 |         return std::make_unique<android::impl::MessageQueue>(); | 
 |     } | 
 |  | 
 |     std::unique_ptr<scheduler::PhaseOffsets> createPhaseOffsets() override { | 
 |         return std::make_unique<scheduler::FakePhaseOffsets>(); | 
 |     } | 
 |  | 
 |     std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)>) override { | 
 |         // TODO: Use test-fixture controlled factory | 
 |         return nullptr; | 
 |     } | 
 |  | 
 |     std::unique_ptr<SurfaceInterceptor> createSurfaceInterceptor(SurfaceFlinger* flinger) override { | 
 |         // TODO: Use test-fixture controlled factory | 
 |         return std::make_unique<android::impl::SurfaceInterceptor>(flinger); | 
 |     } | 
 |  | 
 |     sp<StartPropertySetThread> createStartPropertySetThread(bool timestampPropertyValue) override { | 
 |         // TODO: Use test-fixture controlled factory | 
 |         return new StartPropertySetThread(timestampPropertyValue); | 
 |     } | 
 |  | 
 |     sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs&& creationArgs) override { | 
 |         // TODO: Use test-fixture controlled factory | 
 |         return new DisplayDevice(std::move(creationArgs)); | 
 |     } | 
 |  | 
 |     sp<GraphicBuffer> createGraphicBuffer(uint32_t width, uint32_t height, PixelFormat format, | 
 |                                           uint32_t layerCount, uint64_t usage, | 
 |                                           std::string requestorName) override { | 
 |         // TODO: Use test-fixture controlled factory | 
 |         return new GraphicBuffer(width, height, format, layerCount, usage, requestorName); | 
 |     } | 
 |  | 
 |     void createBufferQueue(sp<IGraphicBufferProducer>* outProducer, | 
 |                            sp<IGraphicBufferConsumer>* outConsumer, | 
 |                            bool consumerIsSurfaceFlinger) override { | 
 |         if (!mCreateBufferQueue) return; | 
 |         mCreateBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger); | 
 |     } | 
 |  | 
 |     std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface( | 
 |             const sp<IGraphicBufferProducer>& producer) override { | 
 |         if (!mCreateNativeWindowSurface) return nullptr; | 
 |         return mCreateNativeWindowSurface(producer); | 
 |     } | 
 |  | 
 |     std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() override { | 
 |         return compositionengine::impl::createCompositionEngine(); | 
 |     } | 
 |  | 
 |     sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs&) override { | 
 |         // TODO: Use test-fixture controlled factory | 
 |         return nullptr; | 
 |     } | 
 |  | 
 |     sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs&) override { | 
 |         // TODO: Use test-fixture controlled factory | 
 |         return nullptr; | 
 |     } | 
 |  | 
 |     sp<ColorLayer> createColorLayer(const LayerCreationArgs&) override { | 
 |         // TODO: Use test-fixture controlled factory | 
 |         return nullptr; | 
 |     } | 
 |  | 
 |     sp<ContainerLayer> createContainerLayer(const LayerCreationArgs&) override { | 
 |         // TODO: Use test-fixture controlled factory | 
 |         return nullptr; | 
 |     } | 
 |  | 
 |     std::shared_ptr<TimeStats> createTimeStats() override { | 
 |         // TODO: Use test-fixture controlled factory | 
 |         return std::make_shared<android::impl::TimeStats>(); | 
 |     } | 
 |  | 
 |     using CreateBufferQueueFunction = | 
 |             std::function<void(sp<IGraphicBufferProducer>* /* outProducer */, | 
 |                                sp<IGraphicBufferConsumer>* /* outConsumer */, | 
 |                                bool /* consumerIsSurfaceFlinger */)>; | 
 |     CreateBufferQueueFunction mCreateBufferQueue; | 
 |  | 
 |     using CreateNativeWindowSurfaceFunction = | 
 |             std::function<std::unique_ptr<surfaceflinger::NativeWindowSurface>( | 
 |                     const sp<IGraphicBufferProducer>&)>; | 
 |     CreateNativeWindowSurfaceFunction mCreateNativeWindowSurface; | 
 |  | 
 |     using CreateCompositionEngineFunction = | 
 |             std::function<std::unique_ptr<compositionengine::CompositionEngine>()>; | 
 |     CreateCompositionEngineFunction mCreateCompositionEngine; | 
 | }; | 
 |  | 
 | } // namespace surfaceflinger::test | 
 |  | 
 | class TestableSurfaceFlinger { | 
 | public: | 
 |     // Extend this as needed for accessing SurfaceFlinger private (and public) | 
 |     // functions. | 
 |  | 
 |     void setupRenderEngine(std::unique_ptr<renderengine::RenderEngine> renderEngine) { | 
 |         mFlinger->mCompositionEngine->setRenderEngine(std::move(renderEngine)); | 
 |     } | 
 |  | 
 |     void setupComposer(std::unique_ptr<Hwc2::Composer> composer) { | 
 |         mFlinger->mCompositionEngine->setHwComposer( | 
 |                 std::make_unique<impl::HWComposer>(std::move(composer))); | 
 |     } | 
 |  | 
 |     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)); | 
 |     } | 
 |  | 
 |     using HotplugEvent = SurfaceFlinger::HotplugEvent; | 
 |  | 
 |     auto& mutableLayerCurrentState(sp<Layer> layer) { return layer->mCurrentState; } | 
 |     auto& mutableLayerDrawingState(sp<Layer> layer) { return layer->mDrawingState; } | 
 |  | 
 |     void setLayerSidebandStream(sp<Layer> layer, sp<NativeHandle> sidebandStream) { | 
 |         layer->mDrawingState.sidebandStream = sidebandStream; | 
 |         layer->mSidebandStream = sidebandStream; | 
 |         layer->getCompositionLayer()->editState().frontEnd.sidebandStream = sidebandStream; | 
 |     } | 
 |  | 
 |     void setLayerCompositionType(sp<Layer> layer, HWC2::Composition type) { | 
 |         auto outputLayer = layer->findOutputLayerForDisplay(mFlinger->getDefaultDisplayDevice()); | 
 |         LOG_ALWAYS_FATAL_IF(!outputLayer); | 
 |         auto& state = outputLayer->editState(); | 
 |         LOG_ALWAYS_FATAL_IF(!outputLayer->getState().hwc); | 
 |         (*state.hwc).hwcCompositionType = static_cast<Hwc2::IComposerClient::Composition>(type); | 
 |     }; | 
 |  | 
 |     void setLayerPotentialCursor(sp<Layer> layer, bool potentialCursor) { | 
 |         layer->mPotentialCursor = potentialCursor; | 
 |     } | 
 |  | 
 |     /* ------------------------------------------------------------------------ | 
 |      * Forwarding for functions being tested | 
 |      */ | 
 |  | 
 |     auto createDisplay(const String8& displayName, bool secure) { | 
 |         return mFlinger->createDisplay(displayName, secure); | 
 |     } | 
 |  | 
 |     auto destroyDisplay(const sp<IBinder>& displayToken) { | 
 |         return mFlinger->destroyDisplay(displayToken); | 
 |     } | 
 |  | 
 |     auto resetDisplayState() { return mFlinger->resetDisplayState(); } | 
 |  | 
 |     auto setupNewDisplayDeviceInternal(const wp<IBinder>& displayToken, | 
 |                                        const std::optional<DisplayId>& displayId, | 
 |                                        const DisplayDeviceState& state, | 
 |                                        const sp<compositionengine::DisplaySurface>& dispSurface, | 
 |                                        const sp<IGraphicBufferProducer>& producer) { | 
 |         return mFlinger->setupNewDisplayDeviceInternal(displayToken, displayId, state, dispSurface, | 
 |                                                        producer); | 
 |     } | 
 |  | 
 |     auto handleTransactionLocked(uint32_t transactionFlags) { | 
 |         Mutex::Autolock _l(mFlinger->mStateLock); | 
 |         return mFlinger->handleTransactionLocked(transactionFlags); | 
 |     } | 
 |  | 
 |     auto onHotplugReceived(int32_t sequenceId, hwc2_display_t display, | 
 |                            HWC2::Connection connection) { | 
 |         return mFlinger->onHotplugReceived(sequenceId, display, connection); | 
 |     } | 
 |  | 
 |     auto setDisplayStateLocked(const DisplayState& s) { return mFlinger->setDisplayStateLocked(s); } | 
 |  | 
 |     // Allow reading display state without locking, as if called on the SF main thread. | 
 |     auto onInitializeDisplays() NO_THREAD_SAFETY_ANALYSIS { | 
 |         return mFlinger->onInitializeDisplays(); | 
 |     } | 
 |  | 
 |     // Allow reading display state without locking, as if called on the SF main thread. | 
 |     auto setPowerModeInternal(const sp<DisplayDevice>& display, | 
 |                               int mode) NO_THREAD_SAFETY_ANALYSIS { | 
 |         return mFlinger->setPowerModeInternal(display, mode); | 
 |     } | 
 |  | 
 |     auto onMessageReceived(int32_t what) { return mFlinger->onMessageReceived(what); } | 
 |  | 
 |     auto captureScreenImplLocked(const RenderArea& renderArea, | 
 |                                  TraverseLayersFunction traverseLayers, ANativeWindowBuffer* buffer, | 
 |                                  bool useIdentityTransform, bool forSystem, int* outSyncFd) { | 
 |         return mFlinger->captureScreenImplLocked(renderArea, traverseLayers, buffer, | 
 |                                                  useIdentityTransform, forSystem, outSyncFd); | 
 |     } | 
 |  | 
 |     auto traverseLayersInDisplay(const sp<const DisplayDevice>& display, | 
 |                                  const LayerVector::Visitor& visitor) { | 
 |         return mFlinger->SurfaceFlinger::traverseLayersInDisplay(display, visitor); | 
 |     } | 
 |  | 
 |     auto getDisplayNativePrimaries(const sp<IBinder>& displayToken, | 
 |                                    ui::DisplayPrimaries &primaries) { | 
 |         return mFlinger->SurfaceFlinger::getDisplayNativePrimaries(displayToken, primaries); | 
 |     } | 
 |  | 
 |     /* ------------------------------------------------------------------------ | 
 |      * Read-only access to private data to assert post-conditions. | 
 |      */ | 
 |  | 
 |     const auto& getAnimFrameTracker() const { return mFlinger->mAnimFrameTracker; } | 
 |     const auto& getHasPoweredOff() const { return mFlinger->mHasPoweredOff; } | 
 |     const auto& getVisibleRegionsDirty() const { return mFlinger->mVisibleRegionsDirty; } | 
 |     auto& getHwComposer() const { | 
 |         return static_cast<impl::HWComposer&>(mFlinger->getHwComposer()); | 
 |     } | 
 |  | 
 |     const auto& getCompositorTiming() const { return mFlinger->getBE().mCompositorTiming; } | 
 |  | 
 |     /* ------------------------------------------------------------------------ | 
 |      * Read-write access to private data to set up preconditions and assert | 
 |      * post-conditions. | 
 |      */ | 
 |  | 
 |     auto& mutableHasWideColorDisplay() { return SurfaceFlinger::hasWideColorDisplay; } | 
 |     auto& mutablePrimaryDisplayOrientation() { return SurfaceFlinger::primaryDisplayOrientation; } | 
 |     auto& mutableUseColorManagement() { return SurfaceFlinger::useColorManagement; } | 
 |  | 
 |     auto& mutableCurrentState() { return mFlinger->mCurrentState; } | 
 |     auto& mutableDisplayColorSetting() { return mFlinger->mDisplayColorSetting; } | 
 |     auto& mutableDisplays() { return mFlinger->mDisplays; } | 
 |     auto& mutableDrawingState() { return mFlinger->mDrawingState; } | 
 |     auto& mutableEventQueue() { return mFlinger->mEventQueue; } | 
 |     auto& mutableGeometryInvalid() { return mFlinger->mGeometryInvalid; } | 
 |     auto& mutableInterceptor() { return mFlinger->mInterceptor; } | 
 |     auto& mutableMainThreadId() { return mFlinger->mMainThreadId; } | 
 |     auto& mutablePendingHotplugEvents() { return mFlinger->mPendingHotplugEvents; } | 
 |     auto& mutablePhysicalDisplayTokens() { return mFlinger->mPhysicalDisplayTokens; } | 
 |     auto& mutableTexturePool() { return mFlinger->mTexturePool; } | 
 |     auto& mutableTransactionFlags() { return mFlinger->mTransactionFlags; } | 
 |     auto& mutableUseHwcVirtualDisplays() { return mFlinger->mUseHwcVirtualDisplays; } | 
 |  | 
 |     auto& mutableComposerSequenceId() { return mFlinger->getBE().mComposerSequenceId; } | 
 |     auto& mutableHwcDisplayData() { return getHwComposer().mDisplayData; } | 
 |     auto& mutableHwcPhysicalDisplayIdMap() { return getHwComposer().mPhysicalDisplayIdMap; } | 
 |     auto& mutableInternalHwcDisplayId() { return getHwComposer().mInternalHwcDisplayId; } | 
 |     auto& mutableExternalHwcDisplayId() { return getHwComposer().mExternalHwcDisplayId; } | 
 |     auto& mutableScheduler() { return mFlinger->mScheduler; } | 
 |     auto& mutableAppConnectionHandle() { return mFlinger->mAppConnectionHandle; } | 
 |     auto& mutableSfConnectionHandle() { return mFlinger->mSfConnectionHandle; } | 
 |  | 
 |     ~TestableSurfaceFlinger() { | 
 |         // All these pointer and container clears help ensure that GMock does | 
 |         // not report a leaked object, since the SurfaceFlinger instance may | 
 |         // still be referenced by something despite our best efforts to destroy | 
 |         // it after each test is done. | 
 |         mutableDisplays().clear(); | 
 |         mutableEventQueue().reset(); | 
 |         mutableInterceptor().reset(); | 
 |         mutableScheduler().reset(); | 
 |         mFlinger->mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>()); | 
 |         mFlinger->mCompositionEngine->setRenderEngine( | 
 |                 std::unique_ptr<renderengine::RenderEngine>()); | 
 |     } | 
 |  | 
 |     /* ------------------------------------------------------------------------ | 
 |      * Wrapper classes for Read-write access to private data to set up | 
 |      * preconditions and assert post-conditions. | 
 |      */ | 
 |     class FakePowerAdvisor : public Hwc2::PowerAdvisor { | 
 |     public: | 
 |         FakePowerAdvisor() = default; | 
 |         ~FakePowerAdvisor() override = default; | 
 |         void setExpensiveRenderingExpected(hwc2_display_t, bool) override {} | 
 |     }; | 
 |  | 
 |     struct HWC2Display : public HWC2::impl::Display { | 
 |         HWC2Display(Hwc2::Composer& composer, Hwc2::PowerAdvisor& advisor, | 
 |                     const std::unordered_set<HWC2::Capability>& capabilities, hwc2_display_t id, | 
 |                     HWC2::DisplayType type) | 
 |               : HWC2::impl::Display(composer, advisor, capabilities, id, type) {} | 
 |         ~HWC2Display() { | 
 |             // Prevents a call to disable vsyncs. | 
 |             mType = HWC2::DisplayType::Invalid; | 
 |         } | 
 |  | 
 |         auto& mutableIsConnected() { return this->mIsConnected; } | 
 |         auto& mutableConfigs() { return this->mConfigs; } | 
 |         auto& mutableLayers() { return this->mLayers; } | 
 |     }; | 
 |  | 
 |     class FakeHwcDisplayInjector { | 
 |     public: | 
 |         static constexpr hwc2_display_t DEFAULT_HWC_DISPLAY_ID = 1000; | 
 |         static constexpr int32_t DEFAULT_WIDTH = 1920; | 
 |         static constexpr int32_t DEFAULT_HEIGHT = 1280; | 
 |         static constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'666; | 
 |         static constexpr int32_t DEFAULT_DPI = 320; | 
 |         static constexpr int32_t DEFAULT_ACTIVE_CONFIG = 0; | 
 |  | 
 |         FakeHwcDisplayInjector(DisplayId displayId, HWC2::DisplayType hwcDisplayType, | 
 |                                bool isPrimary) | 
 |               : mDisplayId(displayId), mHwcDisplayType(hwcDisplayType), mIsPrimary(isPrimary) {} | 
 |  | 
 |         auto& setHwcDisplayId(hwc2_display_t displayId) { | 
 |             mHwcDisplayId = displayId; | 
 |             return *this; | 
 |         } | 
 |  | 
 |         auto& setWidth(int32_t width) { | 
 |             mWidth = width; | 
 |             return *this; | 
 |         } | 
 |  | 
 |         auto& setHeight(int32_t height) { | 
 |             mHeight = height; | 
 |             return *this; | 
 |         } | 
 |  | 
 |         auto& setRefreshRate(int32_t refreshRate) { | 
 |             mRefreshRate = refreshRate; | 
 |             return *this; | 
 |         } | 
 |  | 
 |         auto& setDpiX(int32_t dpi) { | 
 |             mDpiX = dpi; | 
 |             return *this; | 
 |         } | 
 |  | 
 |         auto& setDpiY(int32_t dpi) { | 
 |             mDpiY = dpi; | 
 |             return *this; | 
 |         } | 
 |  | 
 |         auto& setActiveConfig(int32_t config) { | 
 |             mActiveConfig = config; | 
 |             return *this; | 
 |         } | 
 |  | 
 |         auto& setCapabilities(const std::unordered_set<HWC2::Capability>* capabilities) { | 
 |             mCapabilities = capabilities; | 
 |             return *this; | 
 |         } | 
 |  | 
 |         auto& setPowerAdvisor(Hwc2::PowerAdvisor* powerAdvisor) { | 
 |             mPowerAdvisor = powerAdvisor; | 
 |             return *this; | 
 |         } | 
 |  | 
 |         void inject(TestableSurfaceFlinger* flinger, Hwc2::Composer* composer) { | 
 |             static FakePowerAdvisor defaultPowerAdvisor; | 
 |             if (mPowerAdvisor == nullptr) mPowerAdvisor = &defaultPowerAdvisor; | 
 |             static const std::unordered_set<HWC2::Capability> defaultCapabilities; | 
 |             if (mCapabilities == nullptr) mCapabilities = &defaultCapabilities; | 
 |  | 
 |             // Caution - Make sure that any values passed by reference here do | 
 |             // not refer to an instance owned by FakeHwcDisplayInjector. This | 
 |             // class has temporary lifetime, while the constructed HWC2::Display | 
 |             // is much longer lived. | 
 |             auto display = std::make_unique<HWC2Display>(*composer, *mPowerAdvisor, *mCapabilities, | 
 |                                                          mHwcDisplayId, mHwcDisplayType); | 
 |  | 
 |             auto config = HWC2::Display::Config::Builder(*display, mActiveConfig); | 
 |             config.setWidth(mWidth); | 
 |             config.setHeight(mHeight); | 
 |             config.setVsyncPeriod(mRefreshRate); | 
 |             config.setDpiX(mDpiX); | 
 |             config.setDpiY(mDpiY); | 
 |             display->mutableConfigs().emplace(mActiveConfig, config.build()); | 
 |             display->mutableIsConnected() = true; | 
 |  | 
 |             flinger->mutableHwcDisplayData()[mDisplayId].hwcDisplay = display.get(); | 
 |  | 
 |             if (mHwcDisplayType == HWC2::DisplayType::Physical) { | 
 |                 flinger->mutableHwcPhysicalDisplayIdMap().emplace(mHwcDisplayId, mDisplayId); | 
 |                 (mIsPrimary ? flinger->mutableInternalHwcDisplayId() | 
 |                             : flinger->mutableExternalHwcDisplayId()) = mHwcDisplayId; | 
 |             } | 
 |  | 
 |             flinger->mFakeHwcDisplays.push_back(std::move(display)); | 
 |         } | 
 |  | 
 |     private: | 
 |         const DisplayId mDisplayId; | 
 |         const HWC2::DisplayType mHwcDisplayType; | 
 |         const bool mIsPrimary; | 
 |  | 
 |         hwc2_display_t mHwcDisplayId = DEFAULT_HWC_DISPLAY_ID; | 
 |         int32_t mWidth = DEFAULT_WIDTH; | 
 |         int32_t mHeight = DEFAULT_HEIGHT; | 
 |         int32_t mRefreshRate = DEFAULT_REFRESH_RATE; | 
 |         int32_t mDpiX = DEFAULT_DPI; | 
 |         int32_t mDpiY = DEFAULT_DPI; | 
 |         int32_t mActiveConfig = DEFAULT_ACTIVE_CONFIG; | 
 |         const std::unordered_set<HWC2::Capability>* mCapabilities = nullptr; | 
 |         Hwc2::PowerAdvisor* mPowerAdvisor = nullptr; | 
 |     }; | 
 |  | 
 |     class FakeDisplayDeviceInjector { | 
 |     public: | 
 |         FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger, | 
 |                                   const std::optional<DisplayId>& displayId, bool isVirtual, | 
 |                                   bool isPrimary) | 
 |               : mFlinger(flinger), mCreationArgs(flinger.mFlinger.get(), mDisplayToken, displayId) { | 
 |             mCreationArgs.isVirtual = isVirtual; | 
 |             mCreationArgs.isPrimary = isPrimary; | 
 |         } | 
 |  | 
 |         sp<IBinder> token() const { return mDisplayToken; } | 
 |  | 
 |         DisplayDeviceState& mutableDrawingDisplayState() { | 
 |             return mFlinger.mutableDrawingState().displays.editValueFor(mDisplayToken); | 
 |         } | 
 |  | 
 |         DisplayDeviceState& mutableCurrentDisplayState() { | 
 |             return mFlinger.mutableCurrentState().displays.editValueFor(mDisplayToken); | 
 |         } | 
 |  | 
 |         const auto& getDrawingDisplayState() { | 
 |             return mFlinger.mutableDrawingState().displays.valueFor(mDisplayToken); | 
 |         } | 
 |  | 
 |         const auto& getCurrentDisplayState() { | 
 |             return mFlinger.mutableCurrentState().displays.valueFor(mDisplayToken); | 
 |         } | 
 |  | 
 |         auto& mutableDisplayDevice() { return mFlinger.mutableDisplays()[mDisplayToken]; } | 
 |  | 
 |         auto& setNativeWindow(const sp<ANativeWindow>& nativeWindow) { | 
 |             mCreationArgs.nativeWindow = nativeWindow; | 
 |             return *this; | 
 |         } | 
 |  | 
 |         auto& setDisplaySurface(const sp<compositionengine::DisplaySurface>& displaySurface) { | 
 |             mCreationArgs.displaySurface = displaySurface; | 
 |             return *this; | 
 |         } | 
 |  | 
 |         auto& setSecure(bool secure) { | 
 |             mCreationArgs.isSecure = secure; | 
 |             return *this; | 
 |         } | 
 |  | 
 |         auto& setPowerMode(int mode) { | 
 |             mCreationArgs.initialPowerMode = mode; | 
 |             return *this; | 
 |         } | 
 |  | 
 |         auto& setHwcColorModes( | 
 |                 const std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> | 
 |                         hwcColorModes) { | 
 |             mCreationArgs.hwcColorModes = hwcColorModes; | 
 |             return *this; | 
 |         } | 
 |  | 
 |         auto& setHasWideColorGamut(bool hasWideColorGamut) { | 
 |             mCreationArgs.hasWideColorGamut = hasWideColorGamut; | 
 |             return *this; | 
 |         } | 
 |  | 
 |         sp<DisplayDevice> inject() { | 
 |             DisplayDeviceState state; | 
 |             state.displayId = mCreationArgs.isVirtual ? std::nullopt : mCreationArgs.displayId; | 
 |             state.isSecure = mCreationArgs.isSecure; | 
 |  | 
 |             sp<DisplayDevice> device = new DisplayDevice(std::move(mCreationArgs)); | 
 |             mFlinger.mutableDisplays().emplace(mDisplayToken, device); | 
 |             mFlinger.mutableCurrentState().displays.add(mDisplayToken, state); | 
 |             mFlinger.mutableDrawingState().displays.add(mDisplayToken, state); | 
 |  | 
 |             if (!mCreationArgs.isVirtual) { | 
 |                 LOG_ALWAYS_FATAL_IF(!state.displayId); | 
 |                 mFlinger.mutablePhysicalDisplayTokens()[*state.displayId] = mDisplayToken; | 
 |             } | 
 |  | 
 |             return device; | 
 |         } | 
 |  | 
 |     private: | 
 |         TestableSurfaceFlinger& mFlinger; | 
 |         sp<BBinder> mDisplayToken = new BBinder(); | 
 |         DisplayDeviceCreationArgs mCreationArgs; | 
 |     }; | 
 |  | 
 |     surfaceflinger::test::Factory mFactory; | 
 |     sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(mFactory, SurfaceFlinger::SkipInitialization); | 
 |  | 
 |     // We need to keep a reference to these so they are properly destroyed. | 
 |     std::vector<std::unique_ptr<HWC2Display>> mFakeHwcDisplays; | 
 | }; | 
 |  | 
 | } // namespace android |