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

Commit 5073d389 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "CE: Unit test coverage for Output::postFramebuffer"

parents 8770b276 07178e39
Loading
Loading
Loading
Loading
+170 −1
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include <ui/Region.h>

#include "CallOrderStateMachineHelper.h"
#include "MockHWC2.h"
#include "RegionMatcher.h"
#include "TransformMatcher.h"

@@ -42,8 +43,10 @@ namespace {
using testing::_;
using testing::ByMove;
using testing::DoAll;
using testing::Eq;
using testing::InSequence;
using testing::Mock;
using testing::Property;
using testing::Ref;
using testing::Return;
using testing::ReturnRef;
@@ -1860,7 +1863,173 @@ TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) {
 * Output::postFramebuffer()
 */

// TODO(b/144060211) - Add coverage
struct OutputPostFramebufferTest : public testing::Test {
    struct OutputPartialMock : public OutputPartialMockBase {
        // Sets up the helper functions called by composeSurfaces to use a mock
        // implementations.
        MOCK_METHOD0(presentAndGetFrameFences, compositionengine::Output::FrameFences());
    };

    struct Layer {
        Layer() {
            EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
            EXPECT_CALL(outputLayer, getHwcLayer()).WillRepeatedly(Return(&hwc2Layer));
        }

        StrictMock<mock::OutputLayer> outputLayer;
        StrictMock<mock::LayerFE> layerFE;
        StrictMock<HWC2::mock::Layer> hwc2Layer;
    };

    OutputPostFramebufferTest() {
        mOutput.setDisplayColorProfileForTest(
                std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
        mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));

        EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3u));
        EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
                .WillRepeatedly(Return(&mLayer1.outputLayer));
        EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
                .WillRepeatedly(Return(&mLayer2.outputLayer));
        EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2u))
                .WillRepeatedly(Return(&mLayer3.outputLayer));
    }

    StrictMock<OutputPartialMock> mOutput;
    mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
    mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();

    Layer mLayer1;
    Layer mLayer2;
    Layer mLayer3;
};

TEST_F(OutputPostFramebufferTest, ifNotEnabledDoesNothing) {
    mOutput.mState.isEnabled = false;

    mOutput.postFramebuffer();
}

TEST_F(OutputPostFramebufferTest, ifEnabledMustFlipThenPresentThenSendPresentCompleted) {
    mOutput.mState.isEnabled = true;

    compositionengine::Output::FrameFences frameFences;

    // This should happen even if there are no output layers.
    EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));

    // For this test in particular we want to make sure the call expectations
    // setup below are satisfied in the specific order.
    InSequence seq;

    EXPECT_CALL(*mRenderSurface, flip());
    EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
    EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());

    mOutput.postFramebuffer();
}

TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) {
    // Simulate getting release fences from each layer, and ensure they are passed to the
    // front-end layer interface for each layer correctly.

    mOutput.mState.isEnabled = true;

    // Create three unique fence instances
    sp<Fence> layer1Fence = new Fence();
    sp<Fence> layer2Fence = new Fence();
    sp<Fence> layer3Fence = new Fence();

    compositionengine::Output::FrameFences frameFences;
    frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
    frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
    frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);

    EXPECT_CALL(*mRenderSurface, flip());
    EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
    EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());

    // Compare the pointers values of each fence to make sure the correct ones
    // are passed. This happens to work with the current implementation, but
    // would not survive certain calls like Fence::merge() which would return a
    // new instance.
    EXPECT_CALL(mLayer1.layerFE,
                onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer1Fence.get()))));
    EXPECT_CALL(mLayer2.layerFE,
                onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer2Fence.get()))));
    EXPECT_CALL(mLayer3.layerFE,
                onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer3Fence.get()))));

    mOutput.postFramebuffer();
}

TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) {
    mOutput.mState.isEnabled = true;
    mOutput.mState.usesClientComposition = true;

    sp<Fence> clientTargetAcquireFence = new Fence();
    sp<Fence> layer1Fence = new Fence();
    sp<Fence> layer2Fence = new Fence();
    sp<Fence> layer3Fence = new Fence();
    compositionengine::Output::FrameFences frameFences;
    frameFences.clientTargetAcquireFence = clientTargetAcquireFence;
    frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
    frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
    frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);

    EXPECT_CALL(*mRenderSurface, flip());
    EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
    EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());

    // Fence::merge is called, and since none of the fences are actually valid,
    // Fence::NO_FENCE is returned and passed to each onLayerDisplayed() call.
    // This is the best we can do without creating a real kernel fence object.
    EXPECT_CALL(mLayer1.layerFE, onLayerDisplayed(Fence::NO_FENCE));
    EXPECT_CALL(mLayer2.layerFE, onLayerDisplayed(Fence::NO_FENCE));
    EXPECT_CALL(mLayer3.layerFE, onLayerDisplayed(Fence::NO_FENCE));

    mOutput.postFramebuffer();
}

TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) {
    mOutput.mState.isEnabled = true;
    mOutput.mState.usesClientComposition = true;

    // This should happen even if there are no (current) output layers.
    EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));

    // Load up the released layers with some mock instances
    sp<StrictMock<mock::LayerFE>> releasedLayer1{new StrictMock<mock::LayerFE>()};
    sp<StrictMock<mock::LayerFE>> releasedLayer2{new StrictMock<mock::LayerFE>()};
    sp<StrictMock<mock::LayerFE>> releasedLayer3{new StrictMock<mock::LayerFE>()};
    Output::ReleasedLayers layers;
    layers.push_back(releasedLayer1);
    layers.push_back(releasedLayer2);
    layers.push_back(releasedLayer3);
    mOutput.setReleasedLayers(std::move(layers));

    // Set up a fake present fence
    sp<Fence> presentFence = new Fence();
    compositionengine::Output::FrameFences frameFences;
    frameFences.presentFence = presentFence;

    EXPECT_CALL(*mRenderSurface, flip());
    EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
    EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());

    // Each released layer should be given the presentFence.
    EXPECT_CALL(*releasedLayer1,
                onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
    EXPECT_CALL(*releasedLayer2,
                onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
    EXPECT_CALL(*releasedLayer3,
                onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));

    mOutput.postFramebuffer();

    // After the call the list of released layers should have been cleared.
    EXPECT_TRUE(mOutput.getReleasedLayersForTest().empty());
}

/*
 * Output::composeSurfaces()