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

Commit 839fe5b4 authored by Xiang Wang's avatar Xiang Wang
Browse files

Add unit test on sending power hints in SurfaceFlinger

Bug: b/204322192
Test: atest libsurfaceflinger_unittest:libsurfaceflinger_unittest.SurfaceFlingerPowerHintTest#sendDurationsIncludingHwcWaitTime
Change-Id: I0c9ba1abc169ba0b2136663e3937cd93191730ae
parent 01709c20
Loading
Loading
Loading
Loading
+16 −14
Original line number Original line Diff line number Diff line
@@ -95,6 +95,7 @@
#include <cmath>
#include <cmath>
#include <cstdint>
#include <cstdint>
#include <functional>
#include <functional>
#include <memory>
#include <mutex>
#include <mutex>
#include <optional>
#include <optional>
#include <type_traits>
#include <type_traits>
@@ -113,6 +114,7 @@
#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/Hal.h"
#include "DisplayHardware/Hal.h"
#include "DisplayHardware/PowerAdvisor.h"
#include "DisplayHardware/VirtualDisplaySurface.h"
#include "DisplayHardware/VirtualDisplaySurface.h"
#include "DisplayRenderArea.h"
#include "DisplayRenderArea.h"
#include "EffectLayer.h"
#include "EffectLayer.h"
@@ -327,7 +329,7 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
        mTunnelModeEnabledReporter(new TunnelModeEnabledReporter()),
        mTunnelModeEnabledReporter(new TunnelModeEnabledReporter()),
        mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)),
        mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)),
        mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)),
        mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)),
        mPowerAdvisor(*this),
        mPowerAdvisor(std::make_unique<Hwc2::impl::PowerAdvisor>(*this)),
        mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::make(*this)) {
        mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::make(*this)) {
    ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());
    ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());
}
}
@@ -677,16 +679,16 @@ void SurfaceFlinger::bootFinished() {
        }
        }


        readPersistentProperties();
        readPersistentProperties();
        mPowerAdvisor.onBootFinished();
        mPowerAdvisor->onBootFinished();
        mPowerAdvisor.enablePowerHint(mFlagManager.use_adpf_cpu_hint());
        mPowerAdvisor->enablePowerHint(mFlagManager.use_adpf_cpu_hint());
        if (mPowerAdvisor.usePowerHintSession()) {
        if (mPowerAdvisor->usePowerHintSession()) {
            std::optional<pid_t> renderEngineTid = getRenderEngine().getRenderEngineTid();
            std::optional<pid_t> renderEngineTid = getRenderEngine().getRenderEngineTid();
            std::vector<int32_t> tidList;
            std::vector<int32_t> tidList;
            tidList.emplace_back(gettid());
            tidList.emplace_back(gettid());
            if (renderEngineTid.has_value()) {
            if (renderEngineTid.has_value()) {
                tidList.emplace_back(*renderEngineTid);
                tidList.emplace_back(*renderEngineTid);
            }
            }
            if (!mPowerAdvisor.startPowerHintSession(tidList)) {
            if (!mPowerAdvisor->startPowerHintSession(tidList)) {
                ALOGW("Cannot start power hint session");
                ALOGW("Cannot start power hint session");
            }
            }
        }
        }
@@ -812,7 +814,7 @@ void SurfaceFlinger::init() {
    // set initial conditions (e.g. unblank default device)
    // set initial conditions (e.g. unblank default device)
    initializeDisplays();
    initializeDisplays();


    mPowerAdvisor.init();
    mPowerAdvisor->init();


    char primeShaderCache[PROPERTY_VALUE_MAX];
    char primeShaderCache[PROPERTY_VALUE_MAX];
    property_get("service.sf.prime_shader_cache", primeShaderCache, "1");
    property_get("service.sf.prime_shader_cache", primeShaderCache, "1");
@@ -1284,10 +1286,10 @@ void SurfaceFlinger::disableExpensiveRendering() {
    const char* const whence = __func__;
    const char* const whence = __func__;
    auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) {
    auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) {
        ATRACE_NAME(whence);
        ATRACE_NAME(whence);
        if (mPowerAdvisor.isUsingExpensiveRendering()) {
        if (mPowerAdvisor->isUsingExpensiveRendering()) {
            for (const auto& [_, display] : mDisplays) {
            for (const auto& [_, display] : mDisplays) {
                constexpr bool kDisable = false;
                constexpr bool kDisable = false;
                mPowerAdvisor.setExpensiveRenderingExpected(display->getId(), kDisable);
                mPowerAdvisor->setExpensiveRenderingExpected(display->getId(), kDisable);
            }
            }
        }
        }
    });
    });
@@ -1809,7 +1811,7 @@ void SurfaceFlinger::scheduleCommit(FrameHint hint) {
    if (hint == FrameHint::kActive) {
    if (hint == FrameHint::kActive) {
        mScheduler->resetIdleTimer();
        mScheduler->resetIdleTimer();
    }
    }
    mPowerAdvisor.notifyDisplayUpdateImminent();
    mPowerAdvisor->notifyDisplayUpdateImminent();
    mScheduler->scheduleFrame();
    mScheduler->scheduleFrame();
}
}


@@ -1979,7 +1981,7 @@ nsecs_t SurfaceFlinger::calculateExpectedPresentTime(DisplayStatInfo stats) cons
bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime)
bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime)
        FTL_FAKE_GUARD(kMainThreadContext) {
        FTL_FAKE_GUARD(kMainThreadContext) {
    // we set this once at the beginning of commit to ensure consistency throughout the whole frame
    // we set this once at the beginning of commit to ensure consistency throughout the whole frame
    mPowerHintSessionData.sessionEnabled = mPowerAdvisor.usePowerHintSession();
    mPowerHintSessionData.sessionEnabled = mPowerAdvisor->usePowerHintSession();
    if (mPowerHintSessionData.sessionEnabled) {
    if (mPowerHintSessionData.sessionEnabled) {
        mPowerHintSessionData.commitStart = systemTime();
        mPowerHintSessionData.commitStart = systemTime();
    }
    }
@@ -1998,7 +2000,7 @@ bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expected
    mScheduledPresentTime = expectedVsyncTime;
    mScheduledPresentTime = expectedVsyncTime;


    if (mPowerHintSessionData.sessionEnabled) {
    if (mPowerHintSessionData.sessionEnabled) {
        mPowerAdvisor.setTargetWorkDuration(mExpectedPresentTime -
        mPowerAdvisor->setTargetWorkDuration(mExpectedPresentTime -
                                             mPowerHintSessionData.commitStart);
                                             mPowerHintSessionData.commitStart);
    }
    }
    const auto vsyncIn = [&] {
    const auto vsyncIn = [&] {
@@ -2263,7 +2265,7 @@ void SurfaceFlinger::composite(nsecs_t frameTime, int64_t vsyncId)
    if (mPowerHintSessionData.sessionEnabled) {
    if (mPowerHintSessionData.sessionEnabled) {
        const nsecs_t flingerDuration =
        const nsecs_t flingerDuration =
                (mPowerHintSessionData.presentEnd - mPowerHintSessionData.commitStart);
                (mPowerHintSessionData.presentEnd - mPowerHintSessionData.commitStart);
        mPowerAdvisor.sendActualWorkDuration(flingerDuration, mPowerHintSessionData.presentEnd);
        mPowerAdvisor->sendActualWorkDuration(flingerDuration, mPowerHintSessionData.presentEnd);
    }
    }
}
}


@@ -2918,7 +2920,7 @@ void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,


    builder.setPixels(resolution);
    builder.setPixels(resolution);
    builder.setIsSecure(state.isSecure);
    builder.setIsSecure(state.isSecure);
    builder.setPowerAdvisor(&mPowerAdvisor);
    builder.setPowerAdvisor(mPowerAdvisor.get());
    builder.setName(state.displayName);
    builder.setName(state.displayName);
    auto compositionDisplay = getCompositionEngine().createDisplay(builder.build());
    auto compositionDisplay = getCompositionEngine().createDisplay(builder.build());
    compositionDisplay->setLayerCachingEnabled(mLayerCachingEnabled);
    compositionDisplay->setLayerCachingEnabled(mLayerCachingEnabled);
+1 −1
Original line number Original line Diff line number Diff line
@@ -1383,7 +1383,7 @@ private:
    sp<os::IInputFlinger> mInputFlinger;
    sp<os::IInputFlinger> mInputFlinger;
    InputWindowCommands mInputWindowCommands;
    InputWindowCommands mInputWindowCommands;


    Hwc2::impl::PowerAdvisor mPowerAdvisor;
    std::unique_ptr<Hwc2::PowerAdvisor> mPowerAdvisor;


    void enableRefreshRateOverlay(bool enable) REQUIRES(mStateLock);
    void enableRefreshRateOverlay(bool enable) REQUIRES(mStateLock);


+1 −0
Original line number Original line Diff line number Diff line
@@ -103,6 +103,7 @@ cc_test {
        "SurfaceFlinger_HotplugTest.cpp",
        "SurfaceFlinger_HotplugTest.cpp",
        "SurfaceFlinger_NotifyPowerBoostTest.cpp",
        "SurfaceFlinger_NotifyPowerBoostTest.cpp",
        "SurfaceFlinger_OnInitializeDisplaysTest.cpp",
        "SurfaceFlinger_OnInitializeDisplaysTest.cpp",
        "SurfaceFlinger_PowerHintTest.cpp",
        "SurfaceFlinger_SetDisplayStateTest.cpp",
        "SurfaceFlinger_SetDisplayStateTest.cpp",
        "SurfaceFlinger_SetPowerModeInternalTest.cpp",
        "SurfaceFlinger_SetPowerModeInternalTest.cpp",
        "SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp",
        "SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp",
+4 −3
Original line number Original line Diff line number Diff line
@@ -113,8 +113,9 @@ public:
        mFlinger.setupTimeStats(std::shared_ptr<TimeStats>(mTimeStats));
        mFlinger.setupTimeStats(std::shared_ptr<TimeStats>(mTimeStats));


        mComposer = new Hwc2::mock::Composer();
        mComposer = new Hwc2::mock::Composer();
        mPowerAdvisor = new Hwc2::mock::PowerAdvisor();
        mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer));
        mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer));

        mFlinger.setupPowerAdvisor(std::unique_ptr<Hwc2::PowerAdvisor>(mPowerAdvisor));
        mFlinger.mutableMaxRenderTargetSize() = 16384;
        mFlinger.mutableMaxRenderTargetSize() = 16384;
    }
    }


@@ -188,7 +189,7 @@ public:
    Hwc2::mock::Composer* mComposer = nullptr;
    Hwc2::mock::Composer* mComposer = nullptr;
    renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
    renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
    mock::TimeStats* mTimeStats = new mock::TimeStats();
    mock::TimeStats* mTimeStats = new mock::TimeStats();
    Hwc2::mock::PowerAdvisor mPowerAdvisor;
    Hwc2::mock::PowerAdvisor* mPowerAdvisor = nullptr;


    sp<Fence> mClientTargetAcquireFence = Fence::NO_FENCE;
    sp<Fence> mClientTargetAcquireFence = Fence::NO_FENCE;


@@ -300,7 +301,7 @@ struct BaseDisplayVariant {
                                     .setId(DEFAULT_DISPLAY_ID)
                                     .setId(DEFAULT_DISPLAY_ID)
                                     .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT})
                                     .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT})
                                     .setIsSecure(Derived::IS_SECURE)
                                     .setIsSecure(Derived::IS_SECURE)
                                     .setPowerAdvisor(&test->mPowerAdvisor)
                                     .setPowerAdvisor(test->mPowerAdvisor)
                                     .setName(std::string("Injected display for ") +
                                     .setName(std::string("Injected display for ") +
                                              test_info->test_case_name() + "." + test_info->name())
                                              test_info->test_case_name() + "." + test_info->name())
                                     .build();
                                     .build();
+155 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright 2022 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 "SurfaceFlingerPowerHintTest"

#include <compositionengine/Display.h>
#include <compositionengine/mock/DisplaySurface.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <renderengine/mock/RenderEngine.h>
#include <algorithm>
#include <chrono>
#include <memory>
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/DisplayHardware/MockPowerAdvisor.h"
#include "mock/MockEventThread.h"
#include "mock/MockTimeStats.h"
#include "mock/MockVsyncController.h"
#include "mock/system/window/MockNativeWindow.h"

using namespace android;
using namespace android::Hwc2::mock;
using namespace android::hardware::power;
using namespace std::chrono_literals;
using namespace testing;

namespace android {
namespace {
using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector;
using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;

constexpr hal::HWDisplayId HWC_DISPLAY = FakeHwcDisplayInjector::DEFAULT_HWC_DISPLAY_ID;
constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(42u);
constexpr int DEFAULT_DISPLAY_WIDTH = 1920;
constexpr int DEFAULT_DISPLAY_HEIGHT = 1024;

class SurfaceFlingerPowerHintTest : public Test {
public:
    void SetUp() override;

    void setupScheduler();

protected:
    TestableSurfaceFlinger mFlinger;
    renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
    sp<DisplayDevice> mDisplay;
    sp<compositionengine::mock::DisplaySurface> mDisplaySurface =
            new compositionengine::mock::DisplaySurface();
    mock::NativeWindow* mNativeWindow = new mock::NativeWindow();
    mock::TimeStats* mTimeStats = new mock::TimeStats();
    Hwc2::mock::PowerAdvisor* mPowerAdvisor = nullptr;
    Hwc2::mock::Composer* mComposer = nullptr;
};

void SurfaceFlingerPowerHintTest::SetUp() {
    setupScheduler();
    mComposer = new Hwc2::mock::Composer();
    mPowerAdvisor = new Hwc2::mock::PowerAdvisor();
    mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
    mFlinger.setupTimeStats(std::shared_ptr<TimeStats>(mTimeStats));
    mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer));
    mFlinger.setupPowerAdvisor(std::unique_ptr<Hwc2::PowerAdvisor>(mPowerAdvisor));
    static constexpr bool kIsPrimary = true;
    FakeHwcDisplayInjector(DEFAULT_DISPLAY_ID, hal::DisplayType::PHYSICAL, kIsPrimary)
            .setPowerMode(hal::PowerMode::ON)
            .inject(&mFlinger, mComposer);
    auto compostionEngineDisplayArgs =
            compositionengine::DisplayCreationArgsBuilder()
                    .setId(DEFAULT_DISPLAY_ID)
                    .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT})
                    .setPowerAdvisor(mPowerAdvisor)
                    .setName("injected display")
                    .build();
    auto compositionDisplay =
            compositionengine::impl::createDisplay(mFlinger.getCompositionEngine(),
                                                   std::move(compostionEngineDisplayArgs));
    mDisplay =
            FakeDisplayDeviceInjector(mFlinger, compositionDisplay,
                                      ui::DisplayConnectionType::Internal, HWC_DISPLAY, kIsPrimary)
                    .setDisplaySurface(mDisplaySurface)
                    .setNativeWindow(mNativeWindow)
                    .setPowerMode(hal::PowerMode::ON)
                    .inject();
}

void SurfaceFlingerPowerHintTest::setupScheduler() {
    auto eventThread = std::make_unique<mock::EventThread>();
    auto sfEventThread = std::make_unique<mock::EventThread>();

    EXPECT_CALL(*eventThread, registerDisplayEventConnection(_));
    EXPECT_CALL(*eventThread, createEventConnection(_, _))
            .WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0,
                                                       ResyncCallback())));

    EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_));
    EXPECT_CALL(*sfEventThread, createEventConnection(_, _))
            .WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0,
                                                       ResyncCallback())));

    auto vsyncController = std::make_unique<mock::VsyncController>();
    auto vsyncTracker = std::make_unique<mock::VSyncTracker>();

    EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
    EXPECT_CALL(*vsyncTracker, currentPeriod())
            .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
    EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));

    mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
                            std::move(eventThread), std::move(sfEventThread),
                            TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp,
                            TestableSurfaceFlinger::kTwoDisplayModes);
}

TEST_F(SurfaceFlingerPowerHintTest, sendDurationsIncludingHwcWaitTime) {
    ON_CALL(*mPowerAdvisor, usePowerHintSession()).WillByDefault(Return(true));

    const std::chrono::nanoseconds mockVsyncPeriod = 15ms;
    const std::chrono::nanoseconds expectedTargetTime = 14ms;
    EXPECT_CALL(*mPowerAdvisor, setTargetWorkDuration(Gt(expectedTargetTime.count()))).Times(1);

    const nsecs_t now = systemTime();
    const std::chrono::nanoseconds mockHwcRunTime = 20ms;
    EXPECT_CALL(*mDisplaySurface,
                prepareFrame(compositionengine::DisplaySurface::CompositionType::Hwc))
            .Times(1);
    EXPECT_CALL(*mComposer, presentOrValidateDisplay(HWC_DISPLAY, _, _, _, _, _))
            .WillOnce([mockHwcRunTime] {
                std::this_thread::sleep_for(mockHwcRunTime);
                return hardware::graphics::composer::V2_1::Error::NONE;
            });
    EXPECT_CALL(*mPowerAdvisor,
                sendActualWorkDuration(Gt(mockHwcRunTime.count()),
                                       Gt(now + mockHwcRunTime.count())))
            .Times(1);
    static constexpr bool kVsyncId = 123; // arbitrary
    mFlinger.commitAndComposite(now, kVsyncId, now + mockVsyncPeriod.count());
}

} // namespace
} // namespace android
Loading