/* * 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. */ #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" #include "DisplayTransactionTestHelpers.h" namespace android { using testing::AnyNumber; using testing::DoAll; using testing::Mock; using testing::Return; using testing::SetArgPointee; using android::hardware::graphics::composer::hal::HWDisplayId; using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector; DisplayTransactionTest::DisplayTransactionTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); // Default to no wide color display support configured mFlinger.mutableHasWideColorDisplay() = false; mFlinger.mutableUseColorManagement() = false; mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged; mFlinger.setCreateBufferQueueFunction([](auto, auto, auto) { ADD_FAILURE() << "Unexpected request to create a buffer queue."; }); mFlinger.setCreateNativeWindowSurface([](auto) { ADD_FAILURE() << "Unexpected request to create a native window surface."; return nullptr; }); injectMockScheduler(); mFlinger.mutableEventQueue().reset(mMessageQueue); mFlinger.setupRenderEngine(std::unique_ptr(mRenderEngine)); mFlinger.mutableInterceptor() = mSurfaceInterceptor; injectMockComposer(0); } DisplayTransactionTest::~DisplayTransactionTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } void DisplayTransactionTest::injectMockScheduler() { EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)); EXPECT_CALL(*mEventThread, createEventConnection(_, _)) .WillOnce(Return( new EventThreadConnection(mEventThread, /*callingUid=*/0, ResyncCallback()))); EXPECT_CALL(*mSFEventThread, registerDisplayEventConnection(_)); EXPECT_CALL(*mSFEventThread, createEventConnection(_, _)) .WillOnce(Return( new EventThreadConnection(mSFEventThread, /*callingUid=*/0, ResyncCallback()))); mFlinger.setupScheduler(std::unique_ptr(mVsyncController), std::unique_ptr(mVSyncTracker), std::unique_ptr(mEventThread), std::unique_ptr(mSFEventThread), &mSchedulerCallback); } void DisplayTransactionTest::injectMockComposer(int virtualDisplayCount) { if (mComposer) { // If reinjecting, disable first to prevent the enable below from being a no-op. mFlinger.enableHalVirtualDisplays(false); } mComposer = new Hwc2::mock::Composer(); mFlinger.setupComposer(std::unique_ptr(mComposer)); EXPECT_CALL(*mComposer, getMaxVirtualDisplayCount()).WillOnce(Return(virtualDisplayCount)); mFlinger.enableHalVirtualDisplays(true); Mock::VerifyAndClear(mComposer); } void DisplayTransactionTest::injectFakeBufferQueueFactory() { // This setup is only expected once per test. ASSERT_TRUE(mConsumer == nullptr && mProducer == nullptr); mConsumer = new mock::GraphicBufferConsumer(); mProducer = new mock::GraphicBufferProducer(); mFlinger.setCreateBufferQueueFunction([this](auto outProducer, auto outConsumer, bool) { *outProducer = mProducer; *outConsumer = mConsumer; }); } void DisplayTransactionTest::injectFakeNativeWindowSurfaceFactory() { // This setup is only expected once per test. ASSERT_TRUE(mNativeWindowSurface == nullptr); mNativeWindowSurface = new surfaceflinger::mock::NativeWindowSurface(); mFlinger.setCreateNativeWindowSurface([this](auto) { return std::unique_ptr(mNativeWindowSurface); }); } sp DisplayTransactionTest::injectDefaultInternalDisplay( std::function injectExtra) { constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID(777); constexpr int DEFAULT_DISPLAY_WIDTH = 1080; constexpr int DEFAULT_DISPLAY_HEIGHT = 1920; constexpr HWDisplayId DEFAULT_DISPLAY_HWC_DISPLAY_ID = 0; // The DisplayDevice is required to have a framebuffer (behind the // ANativeWindow interface) which uses the actual hardware display // size. EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_WIDTH, _)) .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_WIDTH), Return(0))); EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _)) .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_HEIGHT), Return(0))); EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT)); EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT)); EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64)); EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)).Times(AnyNumber()); constexpr auto kConnectionType = ui::DisplayConnectionType::Internal; constexpr bool kIsPrimary = true; auto compositionDisplay = compositionengine::impl::createDisplay(mFlinger.getCompositionEngine(), compositionengine::DisplayCreationArgsBuilder() .setId(DEFAULT_DISPLAY_ID) .setConnectionType(kConnectionType) .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT}) .setPowerAdvisor(&mPowerAdvisor) .build()); auto injector = FakeDisplayDeviceInjector(mFlinger, compositionDisplay, kConnectionType, DEFAULT_DISPLAY_HWC_DISPLAY_ID, kIsPrimary); injector.setNativeWindow(mNativeWindow); if (injectExtra) { injectExtra(injector); } auto displayDevice = injector.inject(); Mock::VerifyAndClear(mNativeWindow.get()); return displayDevice; } bool DisplayTransactionTest::hasPhysicalHwcDisplay(HWDisplayId hwcDisplayId) { return mFlinger.mutableHwcPhysicalDisplayIdMap().count(hwcDisplayId) == 1; } bool DisplayTransactionTest::hasTransactionFlagSet(int flag) { return mFlinger.mutableTransactionFlags() & flag; } bool DisplayTransactionTest::hasDisplayDevice(sp displayToken) { return mFlinger.mutableDisplays().count(displayToken) == 1; } sp DisplayTransactionTest::getDisplayDevice(sp displayToken) { return mFlinger.mutableDisplays()[displayToken]; } bool DisplayTransactionTest::hasCurrentDisplayState(sp displayToken) { return mFlinger.mutableCurrentState().displays.indexOfKey(displayToken) >= 0; } const DisplayDeviceState& DisplayTransactionTest::getCurrentDisplayState(sp displayToken) { return mFlinger.mutableCurrentState().displays.valueFor(displayToken); } bool DisplayTransactionTest::hasDrawingDisplayState(sp displayToken) { return mFlinger.mutableDrawingState().displays.indexOfKey(displayToken) >= 0; } const DisplayDeviceState& DisplayTransactionTest::getDrawingDisplayState(sp displayToken) { return mFlinger.mutableDrawingState().displays.valueFor(displayToken); } } // namespace android