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

Commit b613ddbb authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Add unit test on sending power hints in SurfaceFlinger" into tm-dev am:...

Merge "Add unit test on sending power hints in SurfaceFlinger" into tm-dev am: 82237710 am: 5dc854ad

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/17573287



Change-Id: I9cbb68ce8f0b25977cb3cd77de20d86e7b427ba7
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents f192aea5 5dc854ad
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