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

Commit b90711b2 authored by ramindani's avatar ramindani
Browse files

[SF] Adds notifyExpectedPresent call for timeoutNs

Update notifyExpectedPresent to notifyExpectedPresentIfRequired

BUG: 296636253
BUG: 284845445
Test: atest HWComposerTest &&
 libsurfaceflinger_unittest
Change-Id: Ibb2b70cd6073be7c0c2be0507b47e6f5732a9303
parent 3acaaf57
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -147,7 +147,8 @@ public:
    MOCK_METHOD(const aidl::android::hardware::graphics::composer3::OverlayProperties&,
                getOverlaySupport, (), (const, override));
    MOCK_METHOD(status_t, setRefreshRateChangedCallbackDebugEnabled, (PhysicalDisplayId, bool));
    MOCK_METHOD(status_t, notifyExpectedPresent, (PhysicalDisplayId, nsecs_t, int32_t));
    MOCK_METHOD(status_t, notifyExpectedPresentIfRequired,
                (PhysicalDisplayId, nsecs_t, int32_t, int32_t));
};

} // namespace mock
+17 −4
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#include <compositionengine/OutputLayer.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <ftl/concat.h>
#include <gui/TraceUtils.h>
#include <log/log.h>
#include <ui/DebugUtils.h>
#include <ui/GraphicBuffer.h>
@@ -484,6 +485,7 @@ status_t HWComposer::getDeviceCompositionChanges(
    }();

    displayData.validateWasSkipped = false;
    displayData.lastExpectedPresentTimestamp = expectedPresentTime;
    if (canSkipValidate) {
        sp<Fence> outPresentFence;
        uint32_t state = UINT32_MAX;
@@ -876,12 +878,23 @@ status_t HWComposer::setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId
    return NO_ERROR;
}

status_t HWComposer::notifyExpectedPresent(PhysicalDisplayId displayId, nsecs_t expectedPresentTime,
                                           int32_t frameIntervalNs) {
    ATRACE_CALL();
status_t HWComposer::notifyExpectedPresentIfRequired(PhysicalDisplayId displayId,
                                                     nsecs_t expectedPresentTime,
                                                     int32_t frameIntervalNs, int32_t timeoutNs) {
    RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
    const auto error = mComposer->notifyExpectedPresent(mDisplayData[displayId].hwcDisplay->getId(),

    auto& displayData = mDisplayData[displayId];
    if (expectedPresentTime >= displayData.lastExpectedPresentTimestamp &&
        expectedPresentTime < displayData.lastExpectedPresentTimestamp + timeoutNs) {
        return NO_ERROR;
    }

    displayData.lastExpectedPresentTimestamp = expectedPresentTime;
    ATRACE_FORMAT("%s ExpectedPresentTime %" PRId64 " frameIntervalNs %d", __func__,
                  expectedPresentTime, frameIntervalNs);
    const auto error = mComposer->notifyExpectedPresent(displayData.hwcDisplay->getId(),
                                                        expectedPresentTime, frameIntervalNs);

    if (error != hal::Error::NONE) {
        ALOGE("Error in notifyExpectedPresent call %s", to_string(error).c_str());
        return INVALID_OPERATION;
+9 −4
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ namespace hal = hardware::graphics::composer::hal;
struct DisplayedFrameStats;
class GraphicBuffer;
class TestableSurfaceFlinger;
struct HWComposerTest;
struct CompositionInfo;

namespace Hwc2 {
@@ -300,8 +301,9 @@ public:
            aidl::android::hardware::graphics::common::HdrConversionStrategy,
            aidl::android::hardware::graphics::common::Hdr*) = 0;
    virtual status_t setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId, bool enabled) = 0;
    virtual status_t notifyExpectedPresent(PhysicalDisplayId, nsecs_t expectedPresentTime,
                                           int32_t frameIntervalNs) = 0;
    virtual status_t notifyExpectedPresentIfRequired(PhysicalDisplayId, nsecs_t expectedPresentTime,
                                                     int32_t frameIntervalNs,
                                                     int32_t timeoutNs) = 0;
};

static inline bool operator==(const android::HWComposer::DeviceRequestedChanges& lhs,
@@ -460,8 +462,8 @@ public:
            aidl::android::hardware::graphics::common::HdrConversionStrategy,
            aidl::android::hardware::graphics::common::Hdr*) override;
    status_t setRefreshRateChangedCallbackDebugEnabled(PhysicalDisplayId, bool enabled) override;
    status_t notifyExpectedPresent(PhysicalDisplayId, nsecs_t expectedPresentTime,
                                   int32_t frameIntervalNs) override;
    status_t notifyExpectedPresentIfRequired(PhysicalDisplayId, nsecs_t expectedPresentTime,
                                             int32_t frameIntervalNs, int32_t timeoutNs) override;

    // for debugging ----------------------------------------------------------
    void dump(std::string& out) const override;
@@ -487,6 +489,7 @@ public:
private:
    // For unit tests
    friend TestableSurfaceFlinger;
    friend HWComposerTest;

    struct DisplayData {
        std::unique_ptr<HWC2::Display> hwcDisplay;
@@ -494,6 +497,8 @@ private:
        sp<Fence> lastPresentFence = Fence::NO_FENCE; // signals when the last set op retires
        nsecs_t lastPresentTimestamp = 0;

        nsecs_t lastExpectedPresentTimestamp = 0;

        std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;

        bool validateWasSkipped;
+72 −8
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@

#include <gui/LayerMetadata.h>
#include <log/log.h>
#include <chrono>

#include "DisplayHardware/DisplayMode.h"
#include "DisplayHardware/HWComposer.h"
@@ -44,11 +45,11 @@
#pragma clang diagnostic pop // ignored "-Wconversion"

namespace android {
namespace {

namespace V2_1 = hardware::graphics::composer::V2_1;
namespace V2_4 = hardware::graphics::composer::V2_4;
namespace aidl = aidl::android::hardware::graphics::composer3;
using namespace std::chrono_literals;

using Hwc2::Config;

@@ -77,6 +78,12 @@ struct HWComposerTest : testing::Test {
        EXPECT_CALL(*mHal, setVsyncEnabled(hwcDisplayId, Hwc2::IComposerClient::Vsync::DISABLE));
        EXPECT_CALL(*mHal, onHotplugConnect(hwcDisplayId));
    }

    void setDisplayData(HalDisplayId displayId, nsecs_t lastExpectedPresentTimestamp) {
        ASSERT_TRUE(mHwc.mDisplayData.find(displayId) != mHwc.mDisplayData.end());
        auto& displayData = mHwc.mDisplayData.at(displayId);
        displayData.lastExpectedPresentTimestamp = lastExpectedPresentTimestamp;
    }
};

TEST_F(HWComposerTest, isHeadless) {
@@ -227,12 +234,19 @@ TEST_F(HWComposerTest, getModesWithDisplayConfigurations) {
        constexpr int32_t kHeight = 720;
        constexpr int32_t kConfigGroup = 1;
        constexpr int32_t kVsyncPeriod = 16666667;
        hal::DisplayConfiguration displayConfiguration;
        displayConfiguration.configId = kConfigId;
        displayConfiguration.configGroup = kConfigGroup;
        displayConfiguration.height = kHeight;
        displayConfiguration.width = kWidth;
        displayConfiguration.vsyncPeriod = kVsyncPeriod;
        const hal::VrrConfig vrrConfig =
                hal::VrrConfig{.minFrameIntervalNs = static_cast<Fps>(120_Hz).getPeriodNsecs(),
                               .notifyExpectedPresentConfig = hal::VrrConfig::
                                       NotifyExpectedPresentConfig{.notifyExpectedPresentHeadsUpNs =
                                                                           ms2ns(30),
                                                                   .notifyExpectedPresentTimeoutNs =
                                                                           ms2ns(30)}};
        hal::DisplayConfiguration displayConfiguration{.configId = kConfigId,
                                                       .width = kWidth,
                                                       .height = kHeight,
                                                       .configGroup = kConfigGroup,
                                                       .vsyncPeriod = kVsyncPeriod,
                                                       .vrrConfig = vrrConfig};

        EXPECT_CALL(*mHal, getDisplayConfigurations(kHwcDisplayId, _, _))
                .WillOnce(DoAll(SetArgPointee<2>(std::vector<hal::DisplayConfiguration>{
@@ -247,6 +261,7 @@ TEST_F(HWComposerTest, getModesWithDisplayConfigurations) {
        EXPECT_EQ(modes.front().height, kHeight);
        EXPECT_EQ(modes.front().configGroup, kConfigGroup);
        EXPECT_EQ(modes.front().vsyncPeriod, kVsyncPeriod);
        EXPECT_EQ(modes.front().vrrConfig, vrrConfig);
        EXPECT_EQ(modes.front().dpiX, -1);
        EXPECT_EQ(modes.front().dpiY, -1);

@@ -266,6 +281,7 @@ TEST_F(HWComposerTest, getModesWithDisplayConfigurations) {
        EXPECT_EQ(modes.front().height, kHeight);
        EXPECT_EQ(modes.front().configGroup, kConfigGroup);
        EXPECT_EQ(modes.front().vsyncPeriod, kVsyncPeriod);
        EXPECT_EQ(modes.front().vrrConfig, vrrConfig);
        EXPECT_EQ(modes.front().dpiX, kDpi);
        EXPECT_EQ(modes.front().dpiY, kDpi);
    }
@@ -299,6 +315,55 @@ TEST_F(HWComposerTest, onVsyncInvalid) {
    EXPECT_FALSE(displayIdOpt);
}

TEST_F(HWComposerTest, notifyExpectedPresentTimeout) {
    constexpr hal::HWDisplayId kHwcDisplayId = 2;
    expectHotplugConnect(kHwcDisplayId);
    const auto info = mHwc.onHotplug(kHwcDisplayId, hal::Connection::CONNECTED);
    ASSERT_TRUE(info);

    auto expectedPresentTime = systemTime() + ms2ns(10);
    const int32_t frameIntervalNs = static_cast<Fps>(60_Hz).getPeriodNsecs();
    static constexpr nsecs_t kTimeoutNs = ms2ns(30);

    ASSERT_NO_FATAL_FAILURE(setDisplayData(info->id, /* lastExpectedPresentTimestamp= */ 0));

    {
        // Very first ExpectedPresent after idle, no previous timestamp
        EXPECT_CALL(*mHal,
                    notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, frameIntervalNs))
                .WillOnce(Return(HalError::NONE));
        mHwc.notifyExpectedPresentIfRequired(info->id, expectedPresentTime, frameIntervalNs,
                                             kTimeoutNs);
    }
    {
        // ExpectedPresent is after the timeoutNs
        expectedPresentTime += ms2ns(50);
        EXPECT_CALL(*mHal,
                    notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, frameIntervalNs))
                .WillOnce(Return(HalError::NONE));
        mHwc.notifyExpectedPresentIfRequired(info->id, expectedPresentTime, frameIntervalNs,
                                             kTimeoutNs);
    }
    {
        // ExpectedPresent is after the last reported ExpectedPresent.
        expectedPresentTime += ms2ns(10);
        EXPECT_CALL(*mHal, notifyExpectedPresent(kHwcDisplayId, _, _)).Times(0);
        mHwc.notifyExpectedPresentIfRequired(info->id, expectedPresentTime, frameIntervalNs,
                                             kTimeoutNs);
    }
    {
        // ExpectedPresent is before the last reported ExpectedPresent but after the timeoutNs,
        // representing we changed our decision and want to present earlier than previously
        // reported.
        expectedPresentTime -= ms2ns(20);
        EXPECT_CALL(*mHal,
                    notifyExpectedPresent(kHwcDisplayId, expectedPresentTime, frameIntervalNs))
                .WillOnce(Return(HalError::NONE));
        mHwc.notifyExpectedPresentIfRequired(info->id, expectedPresentTime, frameIntervalNs,
                                             kTimeoutNs);
    }
}

struct MockHWC2ComposerCallback final : StrictMock<HWC2::ComposerCallback> {
    MOCK_METHOD2(onComposerHalHotplug, void(hal::HWDisplayId, hal::Connection));
    MOCK_METHOD1(onComposerHalRefresh, void(hal::HWDisplayId));
@@ -423,5 +488,4 @@ TEST_F(HWComposerLayerGenericMetadataTest, forwardsSupportedMetadata) {
    EXPECT_EQ(hal::Error::UNSUPPORTED, result);
}

} // namespace
} // namespace android