Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 60836bfb authored by android-build-team Robot's avatar android-build-team Robot Committed by Android (Google) Code Review
Browse files

Merge "resolve merge conflicts of 9eb96871 to master"

parents d316a86b 4c2ac02f
Loading
Loading
Loading
Loading
+498 −0
Original line number Diff line number Diff line
@@ -646,6 +646,309 @@ using HdrDolbyVisionDisplayCase =
        Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
             HdrDolbyVisionSupportedVariant<PrimaryDisplayVariant>>;

/* ------------------------------------------------------------------------
 *
 * SurfaceFlinger::onHotplugReceived
 */

TEST_F(DisplayTransactionTest, hotplugEnqueuesEventsForDisplayTransaction) {
    constexpr int currentSequenceId = 123;
    constexpr hwc2_display_t displayId1 = 456;
    constexpr hwc2_display_t displayId2 = 654;

    // --------------------------------------------------------------------
    // Preconditions

    // Set the current sequence id for accepted events
    mFlinger.mutableComposerSequenceId() = currentSequenceId;

    // Set the main thread id so that the current thread does not appear to be
    // the main thread.
    mFlinger.mutableMainThreadId() = std::thread::id();

    // --------------------------------------------------------------------
    // Call Expectations

    // We expect invalidate() to be invoked once to trigger display transaction
    // processing.
    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);

    // --------------------------------------------------------------------
    // Invocation

    // Simulate two hotplug events (a connect and a disconnect)
    mFlinger.onHotplugReceived(currentSequenceId, displayId1, HWC2::Connection::Connected);
    mFlinger.onHotplugReceived(currentSequenceId, displayId2, HWC2::Connection::Disconnected);

    // --------------------------------------------------------------------
    // Postconditions

    // The display transaction needed flag should be set.
    EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));

    // All events should be in the pending event queue.
    const auto& pendingEvents = mFlinger.mutablePendingHotplugEvents();
    ASSERT_EQ(2u, pendingEvents.size());
    EXPECT_EQ(displayId1, pendingEvents[0].display);
    EXPECT_EQ(HWC2::Connection::Connected, pendingEvents[0].connection);
    EXPECT_EQ(displayId2, pendingEvents[1].display);
    EXPECT_EQ(HWC2::Connection::Disconnected, pendingEvents[1].connection);
}

TEST_F(DisplayTransactionTest, hotplugDiscardsUnexpectedEvents) {
    constexpr int currentSequenceId = 123;
    constexpr int otherSequenceId = 321;
    constexpr hwc2_display_t displayId = 456;

    // --------------------------------------------------------------------
    // Preconditions

    // Set the current sequence id for accepted events
    mFlinger.mutableComposerSequenceId() = currentSequenceId;

    // Set the main thread id so that the current thread does not appear to be
    // the main thread.
    mFlinger.mutableMainThreadId() = std::thread::id();

    // --------------------------------------------------------------------
    // Call Expectations

    // We do not expect any calls to invalidate().
    EXPECT_CALL(*mMessageQueue, invalidate()).Times(0);

    // --------------------------------------------------------------------
    // Invocation

    // Call with an unexpected sequence id
    mFlinger.onHotplugReceived(otherSequenceId, displayId, HWC2::Connection::Invalid);

    // --------------------------------------------------------------------
    // Postconditions

    // The display transaction needed flag should not be set
    EXPECT_FALSE(hasTransactionFlagSet(eDisplayTransactionNeeded));

    // There should be no pending events
    EXPECT_TRUE(mFlinger.mutablePendingHotplugEvents().empty());
}

TEST_F(DisplayTransactionTest, hotplugProcessesEnqueuedEventsIfCalledOnMainThread) {
    constexpr int currentSequenceId = 123;
    constexpr hwc2_display_t displayId1 = 456;

    // --------------------------------------------------------------------
    // Note:
    // --------------------------------------------------------------------
    // This test case is a bit tricky. We want to verify that
    // onHotplugReceived() calls processDisplayHotplugEventsLocked(), but we
    // don't really want to provide coverage for everything the later function
    // does as there are specific tests for it.
    // --------------------------------------------------------------------

    // --------------------------------------------------------------------
    // Preconditions

    // Set the current sequence id for accepted events
    mFlinger.mutableComposerSequenceId() = currentSequenceId;

    // Set the main thread id so that the current thread does appear to be the
    // main thread.
    mFlinger.mutableMainThreadId() = std::this_thread::get_id();

    // --------------------------------------------------------------------
    // Call Expectations

    // We expect invalidate() to be invoked once to trigger display transaction
    // processing.
    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);

    // --------------------------------------------------------------------
    // Invocation

    // Simulate a disconnect on a display id that is not connected. This should
    // be enqueued by onHotplugReceived(), and dequeued by
    // processDisplayHotplugEventsLocked(), but then ignored as invalid.
    mFlinger.onHotplugReceived(currentSequenceId, displayId1, HWC2::Connection::Disconnected);

    // --------------------------------------------------------------------
    // Postconditions

    // The display transaction needed flag should be set.
    EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));

    // There should be no event queued on return, as it should have been
    // processed.
    EXPECT_TRUE(mFlinger.mutablePendingHotplugEvents().empty());
}

/* ------------------------------------------------------------------------
 * SurfaceFlinger::createDisplay
 */

TEST_F(DisplayTransactionTest, createDisplaySetsCurrentStateForNonsecureDisplay) {
    const String8 name("virtual.test");

    // --------------------------------------------------------------------
    // Call Expectations

    // The call should notify the interceptor that a display was created.
    EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1);

    // --------------------------------------------------------------------
    // Invocation

    sp<IBinder> displayToken = mFlinger.createDisplay(name, false);

    // --------------------------------------------------------------------
    // Postconditions

    // The display should have been added to the current state
    ASSERT_TRUE(hasCurrentDisplayState(displayToken));
    const auto& display = getCurrentDisplayState(displayToken);
    EXPECT_EQ(DisplayDevice::DISPLAY_VIRTUAL, display.type);
    EXPECT_EQ(false, display.isSecure);
    EXPECT_EQ(name.string(), display.displayName);

    // --------------------------------------------------------------------
    // Cleanup conditions

    // Destroying the display invalidates the display state.
    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
}

TEST_F(DisplayTransactionTest, createDisplaySetsCurrentStateForSecureDisplay) {
    const String8 name("virtual.test");

    // --------------------------------------------------------------------
    // Call Expectations

    // The call should notify the interceptor that a display was created.
    EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1);

    // --------------------------------------------------------------------
    // Invocation

    sp<IBinder> displayToken = mFlinger.createDisplay(name, true);

    // --------------------------------------------------------------------
    // Postconditions

    // The display should have been added to the current state
    ASSERT_TRUE(hasCurrentDisplayState(displayToken));
    const auto& display = getCurrentDisplayState(displayToken);
    EXPECT_EQ(DisplayDevice::DISPLAY_VIRTUAL, display.type);
    EXPECT_EQ(true, display.isSecure);
    EXPECT_EQ(name.string(), display.displayName);

    // --------------------------------------------------------------------
    // Cleanup conditions

    // Destroying the display invalidates the display state.
    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
}

/* ------------------------------------------------------------------------
 * SurfaceFlinger::destroyDisplay
 */

TEST_F(DisplayTransactionTest, destroyDisplayClearsCurrentStateForDisplay) {
    using Case = NonHwcVirtualDisplayCase;

    // --------------------------------------------------------------------
    // Preconditions

    // A virtual display exists
    auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
    existing.inject();

    // --------------------------------------------------------------------
    // Call Expectations

    // The call should notify the interceptor that a display was created.
    EXPECT_CALL(*mSurfaceInterceptor, saveDisplayDeletion(_)).Times(1);

    // Destroying the display invalidates the display state.
    EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);

    // --------------------------------------------------------------------
    // Invocation

    mFlinger.destroyDisplay(existing.token());

    // --------------------------------------------------------------------
    // Postconditions

    // The display should have been removed from the current state
    EXPECT_FALSE(hasCurrentDisplayState(existing.token()));

    // Ths display should still exist in the drawing state
    EXPECT_TRUE(hasDrawingDisplayState(existing.token()));

    // The display transaction needed flasg should be set
    EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));
}

TEST_F(DisplayTransactionTest, destroyDisplayHandlesUnknownDisplay) {
    // --------------------------------------------------------------------
    // Preconditions

    sp<BBinder> displayToken = new BBinder();

    // --------------------------------------------------------------------
    // Invocation

    mFlinger.destroyDisplay(displayToken);
}

/* ------------------------------------------------------------------------
 * SurfaceFlinger::resetDisplayState
 */

TEST_F(DisplayTransactionTest, resetDisplayStateClearsState) {
    using Case = NonHwcVirtualDisplayCase;

    // --------------------------------------------------------------------
    // Preconditions

    // vsync is enabled and available
    mFlinger.mutablePrimaryHWVsyncEnabled() = true;
    mFlinger.mutableHWVsyncAvailable() = true;

    // A display exists
    auto existing = Case::Display::makeFakeExistingDisplayInjector(this);
    existing.inject();

    // --------------------------------------------------------------------
    // Call Expectations

    // The call disable vsyncs
    EXPECT_CALL(*mEventControlThread, setVsyncEnabled(false)).Times(1);

    // The call clears the current render engine surface
    EXPECT_CALL(*mRenderEngine, resetCurrentSurface());

    // --------------------------------------------------------------------
    // Invocation

    mFlinger.resetDisplayState();

    // --------------------------------------------------------------------
    // Postconditions

    // vsyncs should be off and not available.
    EXPECT_FALSE(mFlinger.mutablePrimaryHWVsyncEnabled());
    EXPECT_FALSE(mFlinger.mutableHWVsyncAvailable());

    // The display should have been removed from the display map.
    EXPECT_FALSE(hasDisplayDevice(existing.token()));

    // The display should still exist in the current state
    EXPECT_TRUE(hasCurrentDisplayState(existing.token()));

    // The display should have been removed from the drawing state
    EXPECT_FALSE(hasDrawingDisplayState(existing.token()));
}

/* ------------------------------------------------------------------------
 * SurfaceFlinger::setupNewDisplayDeviceInternal
 */
@@ -1119,6 +1422,7 @@ TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAdded) {
    // A virtual display was added to the current state, and it has a
    // surface(producer)
    sp<BBinder> displayToken = new BBinder();

    DisplayDeviceState info;
    info.type = Case::Display::TYPE;
    info.isSecure = static_cast<bool>(Case::Display::SECURE);
@@ -1242,5 +1546,199 @@ TEST_F(HandleTransactionLockedTest, processesVirtualDisplayRemoval) {
    verifyDisplayIsNotConnected(existing.token());
}

TEST_F(HandleTransactionLockedTest, processesDisplayLayerStackChanges) {
    using Case = NonHwcVirtualDisplayCase;

    constexpr uint32_t oldLayerStack = 0u;
    constexpr uint32_t newLayerStack = 123u;

    // --------------------------------------------------------------------
    // Preconditions

    // A display is set up
    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
    display.inject();

    // There is a change to the layerStack state
    display.mutableDrawingDisplayState().layerStack = oldLayerStack;
    display.mutableCurrentDisplayState().layerStack = newLayerStack;

    // --------------------------------------------------------------------
    // Invocation

    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);

    // --------------------------------------------------------------------
    // Postconditions

    EXPECT_EQ(newLayerStack, getDisplayDevice(display.token())->getLayerStack());
}

TEST_F(HandleTransactionLockedTest, processesDisplayTransformChanges) {
    using Case = NonHwcVirtualDisplayCase;

    constexpr int oldTransform = 0;
    constexpr int newTransform = 2;

    // --------------------------------------------------------------------
    // Preconditions

    // A display is set up
    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
    display.inject();

    // There is a change to the orientation state
    display.mutableDrawingDisplayState().orientation = oldTransform;
    display.mutableCurrentDisplayState().orientation = newTransform;

    // --------------------------------------------------------------------
    // Invocation

    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);

    // --------------------------------------------------------------------
    // Postconditions

    EXPECT_EQ(newTransform, getDisplayDevice(display.token())->getOrientation());
}

TEST_F(HandleTransactionLockedTest, processesDisplayViewportChanges) {
    using Case = NonHwcVirtualDisplayCase;

    const Rect oldViewport(0, 0, 0, 0);
    const Rect newViewport(0, 0, 123, 456);

    // --------------------------------------------------------------------
    // Preconditions

    // A display is set up
    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
    display.inject();

    // There is a change to the viewport state
    display.mutableDrawingDisplayState().viewport = oldViewport;
    display.mutableCurrentDisplayState().viewport = newViewport;

    // --------------------------------------------------------------------
    // Invocation

    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);

    // --------------------------------------------------------------------
    // Postconditions

    EXPECT_EQ(newViewport, getDisplayDevice(display.token())->getViewport());
}

TEST_F(HandleTransactionLockedTest, processesDisplayFrameChanges) {
    using Case = NonHwcVirtualDisplayCase;

    const Rect oldFrame(0, 0, 0, 0);
    const Rect newFrame(0, 0, 123, 456);

    // --------------------------------------------------------------------
    // Preconditions

    // A display is set up
    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
    display.inject();

    // There is a change to the viewport state
    display.mutableDrawingDisplayState().frame = oldFrame;
    display.mutableCurrentDisplayState().frame = newFrame;

    // --------------------------------------------------------------------
    // Invocation

    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);

    // --------------------------------------------------------------------
    // Postconditions

    EXPECT_EQ(newFrame, getDisplayDevice(display.token())->getFrame());
}

TEST_F(HandleTransactionLockedTest, processesDisplayWidthChanges) {
    using Case = NonHwcVirtualDisplayCase;

    constexpr int oldWidth = 0;
    constexpr int oldHeight = 10;
    constexpr int newWidth = 123;

    // --------------------------------------------------------------------
    // Preconditions

    // A display is set up
    auto nativeWindow = new mock::NativeWindow();
    auto displaySurface = new mock::DisplaySurface();
    auto renderSurface = new RE::mock::Surface();
    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
    display.setNativeWindow(nativeWindow);
    display.setDisplaySurface(displaySurface);
    display.setRenderSurface(std::unique_ptr<RE::Surface>(renderSurface));
    display.inject();

    // There is a change to the viewport state
    display.mutableDrawingDisplayState().width = oldWidth;
    display.mutableDrawingDisplayState().height = oldHeight;
    display.mutableCurrentDisplayState().width = newWidth;
    display.mutableCurrentDisplayState().height = oldHeight;

    // --------------------------------------------------------------------
    // Call Expectations

    EXPECT_CALL(*renderSurface, setNativeWindow(nullptr)).Times(1);
    EXPECT_CALL(*displaySurface, resizeBuffers(newWidth, oldHeight)).Times(1);
    EXPECT_CALL(*renderSurface, setNativeWindow(nativeWindow)).Times(1);
    EXPECT_CALL(*renderSurface, queryWidth()).WillOnce(Return(newWidth));
    EXPECT_CALL(*renderSurface, queryHeight()).WillOnce(Return(oldHeight));

    // --------------------------------------------------------------------
    // Invocation

    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
}

TEST_F(HandleTransactionLockedTest, processesDisplayHeightChanges) {
    using Case = NonHwcVirtualDisplayCase;

    constexpr int oldWidth = 0;
    constexpr int oldHeight = 10;
    constexpr int newHeight = 123;

    // --------------------------------------------------------------------
    // Preconditions

    // A display is set up
    auto nativeWindow = new mock::NativeWindow();
    auto displaySurface = new mock::DisplaySurface();
    auto renderSurface = new RE::mock::Surface();
    auto display = Case::Display::makeFakeExistingDisplayInjector(this);
    display.setNativeWindow(nativeWindow);
    display.setDisplaySurface(displaySurface);
    display.setRenderSurface(std::unique_ptr<RE::Surface>(renderSurface));
    display.inject();

    // There is a change to the viewport state
    display.mutableDrawingDisplayState().width = oldWidth;
    display.mutableDrawingDisplayState().height = oldHeight;
    display.mutableCurrentDisplayState().width = oldWidth;
    display.mutableCurrentDisplayState().height = newHeight;

    // --------------------------------------------------------------------
    // Call Expectations

    EXPECT_CALL(*renderSurface, setNativeWindow(nullptr)).Times(1);
    EXPECT_CALL(*displaySurface, resizeBuffers(oldWidth, newHeight)).Times(1);
    EXPECT_CALL(*renderSurface, setNativeWindow(nativeWindow)).Times(1);
    EXPECT_CALL(*renderSurface, queryWidth()).WillOnce(Return(oldWidth));
    EXPECT_CALL(*renderSurface, queryHeight()).WillOnce(Return(newHeight));

    // --------------------------------------------------------------------
    // Invocation

    mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
}

} // namespace
} // namespace android
+17 −0
Original line number Diff line number Diff line
@@ -60,6 +60,14 @@ public:
     * 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,
@@ -72,6 +80,11 @@ public:
        return mFlinger->handleTransactionLocked(transactionFlags);
    }

    auto onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
                           HWC2::Connection connection) {
        return mFlinger->onHotplugReceived(sequenceId, display, connection);
    }

    /* ------------------------------------------------------------------------
     * Read-write access to private data to set up preconditions and assert
     * post-conditions.
@@ -87,11 +100,15 @@ public:
    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; }