| /* | 
 |  * 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<renderengine::RenderEngine>(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<scheduler::VsyncController>(mVsyncController), | 
 |                             std::unique_ptr<scheduler::VSyncTracker>(mVSyncTracker), | 
 |                             std::unique_ptr<EventThread>(mEventThread), | 
 |                             std::unique_ptr<EventThread>(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<Hwc2::Composer>(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<surfaceflinger::NativeWindowSurface>(mNativeWindowSurface); | 
 |     }); | 
 | } | 
 |  | 
 | sp<DisplayDevice> DisplayTransactionTest::injectDefaultInternalDisplay( | 
 |         std::function<void(FakeDisplayDeviceInjector&)> injectExtra) { | 
 |     constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(255u); | 
 |     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<IBinder> displayToken) { | 
 |     return mFlinger.mutableDisplays().count(displayToken) == 1; | 
 | } | 
 |  | 
 | sp<DisplayDevice> DisplayTransactionTest::getDisplayDevice(sp<IBinder> displayToken) { | 
 |     return mFlinger.mutableDisplays()[displayToken]; | 
 | } | 
 |  | 
 | bool DisplayTransactionTest::hasCurrentDisplayState(sp<IBinder> displayToken) { | 
 |     return mFlinger.mutableCurrentState().displays.indexOfKey(displayToken) >= 0; | 
 | } | 
 |  | 
 | const DisplayDeviceState& DisplayTransactionTest::getCurrentDisplayState(sp<IBinder> displayToken) { | 
 |     return mFlinger.mutableCurrentState().displays.valueFor(displayToken); | 
 | } | 
 |  | 
 | bool DisplayTransactionTest::hasDrawingDisplayState(sp<IBinder> displayToken) { | 
 |     return mFlinger.mutableDrawingState().displays.indexOfKey(displayToken) >= 0; | 
 | } | 
 |  | 
 | const DisplayDeviceState& DisplayTransactionTest::getDrawingDisplayState(sp<IBinder> displayToken) { | 
 |     return mFlinger.mutableDrawingState().displays.valueFor(displayToken); | 
 | } | 
 |  | 
 | } // namespace android |