/* * 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 renderEngine) { mFlinger->getBE().mRenderEngine = std::move(renderEngine); } void setupComposer(std::unique_ptr 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& display) { return mFlinger->destroyDisplay(display); } auto resetDisplayState() { return mFlinger->resetDisplayState(); } auto setupNewDisplayDeviceInternal(const wp& display, int hwcId, const DisplayDeviceState& state, const sp& dispSurface, const sp& 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& 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. */ struct HWC2Display : public HWC2::Display { HWC2Display(Hwc2::Composer& composer, const std::unordered_set& capabilities, hwc2_display_t id, HWC2::DisplayType type) : HWC2::Display(composer, 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& addCapability(HWC2::Capability cap) { mCapabilities.emplace(cap); return *this; } void inject(TestableSurfaceFlinger* flinger, Hwc2::Composer* composer) { auto display = std::make_unique(*composer, 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(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; std::unordered_set mCapabilities; }; class FakeDisplayDeviceInjector { public: FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger, DisplayDevice::DisplayType type, int hwcId) : mFlinger(flinger), mType(type), mHwcId(hwcId) {} sp 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& nativeWindow) { mNativeWindow = nativeWindow; return *this; } auto& setDisplaySurface(const sp& displaySurface) { mDisplaySurface = displaySurface; return *this; } auto& setRenderSurface(std::unique_ptr renderSurface) { mRenderSurface = std::move(renderSurface); return *this; } auto& setSecure(bool secure) { mSecure = secure; return *this; } sp inject() { std::unordered_map> hdrAndRenderIntents; sp 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 mDisplayToken = new BBinder(); DisplayDevice::DisplayType mType; int mHwcId; sp mNativeWindow; sp mDisplaySurface; std::unique_ptr mRenderSurface; bool mSecure = false; }; sp mFlinger = new SurfaceFlinger(SurfaceFlinger::SkipInitialization); // We need to keep a reference to these so they are properly destroyed. std::vector> mFakeHwcDisplays; }; } // namespace android