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

Commit b4937391 authored by Ady Abraham's avatar Ady Abraham
Browse files

SF: Move desired active mode management to DisplayDevice

SF would set the desired active mode on the specific DisplayDevice the
mode was requested and use it to swicth the active display mode.

Change-Id: Ib4f01ec63b2087ab2a81490051d1e029afc71854
Test: SF unit tests
Test: refresh rate switching is working on device with
more than one display
Bug: 187539899

Change-Id: Ie0e5ffe364f81775c2101ffd0cf2c596051947fa
Merged-In: Ie0e5ffe364f81775c2101ffd0cf2c596051947fa
parent f3e81d2f
Loading
Loading
Loading
Loading
+54 −7
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@
#undef LOG_TAG
#define LOG_TAG "DisplayDevice"

#define ATRACE_TAG ATRACE_TAG_GRAPHICS

#include <android-base/stringprintf.h>
#include <compositionengine/CompositionEngine.h>
#include <compositionengine/Display.h>
@@ -66,6 +68,8 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args)
        mSequenceId(args.sequenceId),
        mConnectionType(args.connectionType),
        mCompositionDisplay{args.compositionDisplay},
        mActiveModeFPSTrace("ActiveModeFPS -" + to_string(getId())),
        mActiveModeFPSHwcTrace("ActiveModeFPS_HWC -" + to_string(getId())),
        mPhysicalOrientation(args.physicalOrientation),
        mSupportedModes(std::move(args.supportedModes)),
        mIsPrimary(args.isPrimary),
@@ -156,6 +160,7 @@ bool DisplayDevice::isPoweredOn() const {
void DisplayDevice::setActiveMode(DisplayModeId id) {
    const auto mode = getMode(id);
    LOG_FATAL_IF(!mode, "Cannot set active mode which is not supported.");
    ATRACE_INT(mActiveModeFPSTrace.c_str(), mode->getFps().getIntValue());
    mActiveMode = mode;
    if (mRefreshRateConfigs) {
        mRefreshRateConfigs->setCurrentModeId(mActiveMode->getId());
@@ -165,17 +170,19 @@ void DisplayDevice::setActiveMode(DisplayModeId id) {
    }
}

status_t DisplayDevice::initiateModeChange(DisplayModeId modeId,
status_t DisplayDevice::initiateModeChange(const ActiveModeInfo& info,
                                           const hal::VsyncPeriodChangeConstraints& constraints,
                                           hal::VsyncPeriodChangeTimeline* outTimeline) const {
    const auto mode = getMode(modeId);
    if (!mode) {
                                           hal::VsyncPeriodChangeTimeline* outTimeline) {
    if (!info.mode || info.mode->getPhysicalDisplayId() != getPhysicalId()) {
        ALOGE("Trying to initiate a mode change to invalid mode %s on display %s",
              std::to_string(modeId.value()).c_str(), to_string(getId()).c_str());
              info.mode ? std::to_string(info.mode->getId().value()).c_str() : "null",
              to_string(getId()).c_str());
        return BAD_VALUE;
    }
    return mHwComposer.setActiveModeWithConstraints(getPhysicalId(), mode->getHwcId(), constraints,
                                                    outTimeline);
    mUpcomingActiveMode = info;
    ATRACE_INT(mActiveModeFPSHwcTrace.c_str(), info.mode->getFps().getIntValue());
    return mHwComposer.setActiveModeWithConstraints(getPhysicalId(), info.mode->getHwcId(),
                                                    constraints, outTimeline);
}

const DisplayModePtr& DisplayDevice::getActiveMode() const {
@@ -435,6 +442,46 @@ void DisplayDevice::onInvalidate() {
    }
}

bool DisplayDevice::setDesiredActiveMode(const ActiveModeInfo& info) {
    ATRACE_CALL();

    LOG_ALWAYS_FATAL_IF(!info.mode, "desired mode not provided");
    LOG_ALWAYS_FATAL_IF(getPhysicalId() != info.mode->getPhysicalDisplayId(), "DisplayId mismatch");

    ALOGV("%s(%s)", __func__, to_string(*info.mode).c_str());

    std::scoped_lock lock(mActiveModeLock);
    if (mDesiredActiveModeChanged) {
        // If a mode change is pending, just cache the latest request in mDesiredActiveMode
        const Scheduler::ModeEvent prevConfig = mDesiredActiveMode.event;
        mDesiredActiveMode = info;
        mDesiredActiveMode.event = mDesiredActiveMode.event | prevConfig;
        return false;
    }

    // Check if we are already at the desired mode
    if (getActiveMode()->getId() == info.mode->getId()) {
        return false;
    }

    // Initiate a mode change.
    mDesiredActiveModeChanged = true;
    mDesiredActiveMode = info;
    return true;
}

std::optional<DisplayDevice::ActiveModeInfo> DisplayDevice::getDesiredActiveMode() const {
    std::scoped_lock lock(mActiveModeLock);
    if (mDesiredActiveModeChanged) return mDesiredActiveMode;
    return std::nullopt;
}

void DisplayDevice::clearDesiredActiveModeState() {
    std::scoped_lock lock(mActiveModeLock);
    mDesiredActiveMode.event = Scheduler::ModeEvent::None;
    mDesiredActiveModeChanged = false;
}

std::atomic<int32_t> DisplayDeviceState::sNextSequenceId(1);

}  // namespace android
+33 −3
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@
#include <utils/RefBase.h>
#include <utils/Timers.h>

#include "MainThreadGuard.h"

#include "DisplayHardware/DisplayIdentification.h"
#include "DisplayHardware/DisplayMode.h"
#include "DisplayHardware/Hal.h"
@@ -46,6 +48,8 @@

#include "Scheduler/RefreshRateConfigs.h"

#include "TracedOrdinal.h"

namespace android {

class Fence;
@@ -181,10 +185,28 @@ public:
     * Display mode management.
     */
    const DisplayModePtr& getActiveMode() const;
    void setActiveMode(DisplayModeId);
    status_t initiateModeChange(DisplayModeId modeId,

    struct ActiveModeInfo {
        DisplayModePtr mode;
        scheduler::RefreshRateConfigEvent event = scheduler::RefreshRateConfigEvent::None;

        bool operator!=(const ActiveModeInfo& other) const {
            return mode != other.mode || event != other.event;
        }
    };

    bool setDesiredActiveMode(const ActiveModeInfo&) EXCLUDES(mActiveModeLock);
    std::optional<ActiveModeInfo> getDesiredActiveMode() const EXCLUDES(mActiveModeLock);
    void clearDesiredActiveModeState() EXCLUDES(mActiveModeLock);
    ActiveModeInfo getUpcomingActiveMode() const REQUIRES(SF_MAIN_THREAD) {
        return mUpcomingActiveMode;
    }

    void setActiveMode(DisplayModeId) REQUIRES(SF_MAIN_THREAD);
    status_t initiateModeChange(const ActiveModeInfo&,
                                const hal::VsyncPeriodChangeConstraints& constraints,
                                hal::VsyncPeriodChangeTimeline* outTimeline) const;
                                hal::VsyncPeriodChangeTimeline* outTimeline)
            REQUIRES(SF_MAIN_THREAD);

    // Return the immutable list of supported display modes. The HWC may report different modes
    // after a hotplug reconnect event, in which case the DisplayDevice object will be recreated.
@@ -236,6 +258,8 @@ private:
    const std::shared_ptr<compositionengine::Display> mCompositionDisplay;

    std::string mDisplayName;
    std::string mActiveModeFPSTrace;
    std::string mActiveModeFPSHwcTrace;

    const ui::Rotation mPhysicalOrientation;
    ui::Rotation mOrientation = ui::ROTATION_0;
@@ -260,6 +284,12 @@ private:

    std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;
    std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay;

    mutable std::mutex mActiveModeLock;
    ActiveModeInfo mDesiredActiveMode GUARDED_BY(mActiveModeLock);
    TracedOrdinal<bool> mDesiredActiveModeChanged
            GUARDED_BY(mActiveModeLock) = {"DesiredActiveModeChanged", false};
    ActiveModeInfo mUpcomingActiveMode GUARDED_BY(SF_MAIN_THREAD);
};

struct DisplayDeviceState {
+35 −0
Original line number Diff line number Diff line
/*
 * Copyright 2021 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.
 */

#pragma once

#include <utils/Mutex.h>

namespace android {
namespace {

// Helps to ensure that some functions runs on SF's main thread by using the
// clang thread safety annotations.
class CAPABILITY("mutex") MainThreadGuard {
} SF_MAIN_THREAD;

struct SCOPED_CAPABILITY MainThreadScopedGuard {
public:
    explicit MainThreadScopedGuard(MainThreadGuard& mutex) ACQUIRE(mutex) {}
    ~MainThreadScopedGuard() RELEASE() {}
};
} // namespace
} // namespace android
+7 −8
Original line number Diff line number Diff line
@@ -118,12 +118,12 @@ DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t times
    return event;
}

DisplayEventReceiver::Event makeModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId,
                                            nsecs_t vsyncPeriod) {
DisplayEventReceiver::Event makeModeChanged(DisplayModePtr mode) {
    DisplayEventReceiver::Event event;
    event.header = {DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, displayId, systemTime()};
    event.modeChange.modeId = modeId.value();
    event.modeChange.vsyncPeriod = vsyncPeriod;
    event.header = {DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, mode->getPhysicalDisplayId(),
                    systemTime()};
    event.modeChange.modeId = mode->getId().value();
    event.modeChange.vsyncPeriod = mode->getVsyncPeriod();
    return event;
}

@@ -375,11 +375,10 @@ void EventThread::onHotplugReceived(PhysicalDisplayId displayId, bool connected)
    mCondition.notify_all();
}

void EventThread::onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId,
                                nsecs_t vsyncPeriod) {
void EventThread::onModeChanged(DisplayModePtr mode) {
    std::lock_guard<std::mutex> lock(mMutex);

    mPendingEvents.push_back(makeModeChanged(displayId, modeId, vsyncPeriod));
    mPendingEvents.push_back(makeModeChanged(mode));
    mCondition.notify_all();
}

+2 −4
Original line number Diff line number Diff line
@@ -124,8 +124,7 @@ public:
    virtual void onHotplugReceived(PhysicalDisplayId displayId, bool connected) = 0;

    // called when SF changes the active mode and apps needs to be notified about the change
    virtual void onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId,
                               nsecs_t vsyncPeriod) = 0;
    virtual void onModeChanged(DisplayModePtr) = 0;

    // called when SF updates the Frame Rate Override list
    virtual void onFrameRateOverridesChanged(PhysicalDisplayId displayId,
@@ -174,8 +173,7 @@ public:

    void onHotplugReceived(PhysicalDisplayId displayId, bool connected) override;

    void onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId,
                       nsecs_t vsyncPeriod) override;
    void onModeChanged(DisplayModePtr) override;

    void onFrameRateOverridesChanged(PhysicalDisplayId displayId,
                                     std::vector<FrameRateOverride> overrides) override;
Loading