|  | /* | 
|  | * 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 "DisplayDevice.h" | 
|  | #include "SurfaceFlinger.h" | 
|  |  | 
|  | namespace android { | 
|  |  | 
|  | class EventThread; | 
|  |  | 
|  | namespace RE { | 
|  | class RenderEngine; | 
|  | } | 
|  |  | 
|  | namespace Hwc2 { | 
|  | class Composer; | 
|  | } | 
|  |  | 
|  | class TestableSurfaceFlinger { | 
|  | public: | 
|  | // Extend this as needed for accessing SurfaceFlinger private (and public) | 
|  | // functions. | 
|  |  | 
|  | void setupRenderEngine(std::unique_ptr<RE::RenderEngine> renderEngine) { | 
|  | mFlinger->getBE().mRenderEngine = std::move(renderEngine); | 
|  | } | 
|  |  | 
|  | void setupComposer(std::unique_ptr<Hwc2::Composer> composer) { | 
|  | mFlinger->getBE().mHwc.reset(new HWComposer(std::move(composer))); | 
|  | } | 
|  |  | 
|  | using CreateBufferQueueFunction = SurfaceFlinger::CreateBufferQueueFunction; | 
|  | void setCreateBufferQueueFunction(CreateBufferQueueFunction f) { | 
|  | mFlinger->mCreateBufferQueue = f; | 
|  | } | 
|  |  | 
|  | using CreateNativeWindowSurfaceFunction = SurfaceFlinger::CreateNativeWindowSurfaceFunction; | 
|  | void setCreateNativeWindowSurface(CreateNativeWindowSurfaceFunction f) { | 
|  | mFlinger->mCreateNativeWindowSurface = f; | 
|  | } | 
|  |  | 
|  | using HotplugEvent = SurfaceFlinger::HotplugEvent; | 
|  |  | 
|  | /* ------------------------------------------------------------------------ | 
|  | * Forwarding for functions being tested | 
|  | */ | 
|  |  | 
|  | auto createDisplay(const String8& displayName, bool secure) { | 
|  | return mFlinger->createDisplay(displayName, secure); | 
|  | } | 
|  |  | 
|  | auto destroyDisplay(const sp<IBinder>& display) { return mFlinger->destroyDisplay(display); } | 
|  |  | 
|  | auto resetDisplayState() { return mFlinger->resetDisplayState(); } | 
|  |  | 
|  | auto setupNewDisplayDeviceInternal(const wp<IBinder>& display, int hwcId, | 
|  | const DisplayDeviceState& state, | 
|  | const sp<DisplaySurface>& dispSurface, | 
|  | const sp<IGraphicBufferProducer>& producer) { | 
|  | return mFlinger->setupNewDisplayDeviceInternal(display, hwcId, state, dispSurface, | 
|  | producer); | 
|  | } | 
|  |  | 
|  | auto handleTransactionLocked(uint32_t transactionFlags) { | 
|  | 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); } | 
|  |  | 
|  | auto onInitializeDisplays() { return mFlinger->onInitializeDisplays(); } | 
|  |  | 
|  | auto setPowerModeInternal(const sp<DisplayDevice>& hw, int mode, bool stateLockHeld = false) { | 
|  | return mFlinger->setPowerModeInternal(hw, mode, stateLockHeld); | 
|  | } | 
|  |  | 
|  | /* ------------------------------------------------------------------------ | 
|  | * 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& getHWVsyncAvailable() const { return mFlinger->mHWVsyncAvailable; } | 
|  | const auto& getVisibleRegionsDirty() const { return mFlinger->mVisibleRegionsDirty; } | 
|  |  | 
|  | 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& mutableBuiltinDisplays() { return mFlinger->mBuiltinDisplays; } | 
|  | auto& mutableCurrentState() { return mFlinger->mCurrentState; } | 
|  | auto& mutableDisplays() { return mFlinger->mDisplays; } | 
|  | auto& mutableDisplayColorSetting() { return mFlinger->mDisplayColorSetting; } | 
|  | auto& mutableDrawingState() { return mFlinger->mDrawingState; } | 
|  | auto& mutableEventControlThread() { return mFlinger->mEventControlThread; } | 
|  | auto& mutableEventQueue() { return mFlinger->mEventQueue; } | 
|  | auto& mutableEventThread() { return mFlinger->mEventThread; } | 
|  | auto& mutableHWVsyncAvailable() { return mFlinger->mHWVsyncAvailable; } | 
|  | auto& mutableInterceptor() { return mFlinger->mInterceptor; } | 
|  | auto& mutableMainThreadId() { return mFlinger->mMainThreadId; } | 
|  | auto& mutablePendingHotplugEvents() { return mFlinger->mPendingHotplugEvents; } | 
|  | auto& mutablePrimaryHWVsyncEnabled() { return mFlinger->mPrimaryHWVsyncEnabled; } | 
|  | auto& mutableTransactionFlags() { return mFlinger->mTransactionFlags; } | 
|  | auto& mutableUseHwcVirtualDisplays() { return mFlinger->mUseHwcVirtualDisplays; } | 
|  |  | 
|  | auto& mutableComposerSequenceId() { return mFlinger->getBE().mComposerSequenceId; } | 
|  | auto& mutableHwcDisplayData() { return mFlinger->getBE().mHwc->mDisplayData; } | 
|  | auto& mutableHwcDisplaySlots() { return mFlinger->getBE().mHwc->mHwcDisplaySlots; } | 
|  |  | 
|  | ~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(); | 
|  | mutableEventControlThread().reset(); | 
|  | mutableEventQueue().reset(); | 
|  | mutableEventThread().reset(); | 
|  | mutableInterceptor().reset(); | 
|  | mFlinger->getBE().mHwc.reset(); | 
|  | mFlinger->getBE().mRenderEngine.reset(); | 
|  | } | 
|  |  | 
|  | /* ------------------------------------------------------------------------ | 
|  | * 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::Display { | 
|  | HWC2Display(Hwc2::Composer& composer, Hwc2::PowerAdvisor& advisor, | 
|  | const std::unordered_set<HWC2::Capability>& capabilities, hwc2_display_t id, | 
|  | HWC2::DisplayType type) | 
|  | : HWC2::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; } | 
|  | }; | 
|  |  | 
|  | 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(DisplayDevice::DisplayType type, HWC2::DisplayType hwcDisplayType) | 
|  | : mType(type), mHwcDisplayType(hwcDisplayType) {} | 
|  |  | 
|  | 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; | 
|  |  | 
|  | ASSERT_TRUE(flinger->mutableHwcDisplayData().size() > static_cast<size_t>(mType)); | 
|  | flinger->mutableHwcDisplayData()[mType].reset(); | 
|  | flinger->mutableHwcDisplayData()[mType].hwcDisplay = display.get(); | 
|  | flinger->mutableHwcDisplaySlots().emplace(mHwcDisplayId, mType); | 
|  |  | 
|  | flinger->mFakeHwcDisplays.push_back(std::move(display)); | 
|  | } | 
|  |  | 
|  | private: | 
|  | DisplayDevice::DisplayType mType; | 
|  | HWC2::DisplayType mHwcDisplayType; | 
|  | 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, DisplayDevice::DisplayType type, | 
|  | int hwcId) | 
|  | : mFlinger(flinger), mType(type), mHwcId(hwcId) {} | 
|  |  | 
|  | 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().valueFor(mDisplayToken); } | 
|  |  | 
|  | auto& setNativeWindow(const sp<ANativeWindow>& nativeWindow) { | 
|  | mNativeWindow = nativeWindow; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | auto& setDisplaySurface(const sp<DisplaySurface>& displaySurface) { | 
|  | mDisplaySurface = displaySurface; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | auto& setRenderSurface(std::unique_ptr<RE::Surface> renderSurface) { | 
|  | mRenderSurface = std::move(renderSurface); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | auto& setSecure(bool secure) { | 
|  | mSecure = secure; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | sp<DisplayDevice> inject() { | 
|  | std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> hdrAndRenderIntents; | 
|  | sp<DisplayDevice> device = | 
|  | new DisplayDevice(mFlinger.mFlinger.get(), mType, mHwcId, mSecure, mDisplayToken, | 
|  | mNativeWindow, mDisplaySurface, std::move(mRenderSurface), 0, | 
|  | 0, false, HdrCapabilities(), 0, hdrAndRenderIntents, | 
|  | HWC_POWER_MODE_NORMAL); | 
|  | mFlinger.mutableDisplays().add(mDisplayToken, device); | 
|  |  | 
|  | DisplayDeviceState state(mType, mSecure); | 
|  | mFlinger.mutableCurrentState().displays.add(mDisplayToken, state); | 
|  | mFlinger.mutableDrawingState().displays.add(mDisplayToken, state); | 
|  |  | 
|  | if (mType >= DisplayDevice::DISPLAY_PRIMARY && mType < DisplayDevice::DISPLAY_VIRTUAL) { | 
|  | mFlinger.mutableBuiltinDisplays()[mType] = mDisplayToken; | 
|  | } | 
|  |  | 
|  | return device; | 
|  | } | 
|  |  | 
|  | private: | 
|  | TestableSurfaceFlinger& mFlinger; | 
|  | sp<BBinder> mDisplayToken = new BBinder(); | 
|  | DisplayDevice::DisplayType mType; | 
|  | int mHwcId; | 
|  | sp<ANativeWindow> mNativeWindow; | 
|  | sp<DisplaySurface> mDisplaySurface; | 
|  | std::unique_ptr<RE::Surface> mRenderSurface; | 
|  | bool mSecure = false; | 
|  | }; | 
|  |  | 
|  | sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(SurfaceFlinger::SkipInitialization); | 
|  |  | 
|  | // We need to keep a reference to these so they are properly destroyed. | 
|  | std::vector<std::unique_ptr<HWC2Display>> mFakeHwcDisplays; | 
|  | }; | 
|  |  | 
|  | } // namespace android |