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

Commit c740f5aa authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 9597030 from 3e263ad5 to udc-release

Change-Id: Ifc1b0d7f5b4586ce878d0b008022461cb68ab57b
parents 9e705df4 3e263ad5
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 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 <vector>

#include "Display/DisplayModeRequest.h"

namespace android::scheduler {

struct ISchedulerCallback {
    virtual void setVsyncEnabled(bool) = 0;
    virtual void requestDisplayModes(std::vector<display::DisplayModeRequest>) = 0;
    virtual void kernelTimerChanged(bool expired) = 0;
    virtual void triggerOnFrameRateOverridesChanged() = 0;

protected:
    ~ISchedulerCallback() = default;
};

} // namespace android::scheduler
+15 −68
Original line number Diff line number Diff line
@@ -28,10 +28,10 @@
#include <ftl/enum.h>
#include <ftl/fake_guard.h>
#include <ftl/small_map.h>
#include <gui/TraceUtils.h>
#include <gui/WindowInfo.h>
#include <system/window.h>
#include <utils/Timers.h>
#include <utils/Trace.h>

#include <FrameTimeline/FrameTimeline.h>
#include <scheduler/interface/ICompositor.h>
@@ -155,7 +155,7 @@ void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
}

void Scheduler::createVsyncSchedule(FeatureFlags features) {
    mVsyncSchedule.emplace(features);
    mVsyncSchedule = std::make_unique<VsyncSchedule>(features);
}

std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const {
@@ -171,6 +171,7 @@ bool Scheduler::isVsyncValid(TimePoint expectedVsyncTimestamp, uid_t uid) const
        return true;
    }

    ATRACE_FORMAT("%s uid: %d frameRate: %s", __func__, uid, to_string(*frameRate).c_str());
    return mVsyncSchedule->getTracker().isVSyncInPhase(expectedVsyncTimestamp.ns(), *frameRate);
}

@@ -393,38 +394,17 @@ void Scheduler::setVsyncConfig(const VsyncConfig& config, Period vsyncPeriod) {
}

void Scheduler::enableHardwareVsync() {
    std::lock_guard<std::mutex> lock(mHWVsyncLock);
    if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
        mVsyncSchedule->getTracker().resetModel();
        mSchedulerCallback.setVsyncEnabled(true);
        mPrimaryHWVsyncEnabled = true;
    }
    mVsyncSchedule->enableHardwareVsync(mSchedulerCallback);
}

void Scheduler::disableHardwareVsync(bool makeUnavailable) {
    std::lock_guard<std::mutex> lock(mHWVsyncLock);
    if (mPrimaryHWVsyncEnabled) {
        mSchedulerCallback.setVsyncEnabled(false);
        mPrimaryHWVsyncEnabled = false;
    }
    if (makeUnavailable) {
        mHWVsyncAvailable = false;
    }
void Scheduler::disableHardwareVsync(bool disallow) {
    mVsyncSchedule->disableHardwareVsync(mSchedulerCallback, disallow);
}

void Scheduler::resyncToHardwareVsync(bool makeAvailable, Fps refreshRate) {
    {
        std::lock_guard<std::mutex> lock(mHWVsyncLock);
        if (makeAvailable) {
            mHWVsyncAvailable = makeAvailable;
        } else if (!mHWVsyncAvailable) {
            // Hardware vsync is not currently available, so abort the resync
            // attempt for now
            return;
        }
void Scheduler::resyncToHardwareVsync(bool allowToEnable, Fps refreshRate) {
    if (mVsyncSchedule->isHardwareVsyncAllowed(allowToEnable) && refreshRate.isValid()) {
        mVsyncSchedule->startPeriodTransition(mSchedulerCallback, refreshRate.getPeriod());
    }

    setVsyncPeriod(refreshRate.getPeriodNsecs());
}

void Scheduler::setRenderRate(Fps renderFrameRate) {
@@ -457,37 +437,12 @@ void Scheduler::resync() {
    }
}

void Scheduler::setVsyncPeriod(nsecs_t period) {
    if (period <= 0) return;

    std::lock_guard<std::mutex> lock(mHWVsyncLock);
    mVsyncSchedule->getController().startPeriodTransition(period);

    if (!mPrimaryHWVsyncEnabled) {
        mVsyncSchedule->getTracker().resetModel();
        mSchedulerCallback.setVsyncEnabled(true);
        mPrimaryHWVsyncEnabled = true;
    }
}

void Scheduler::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod,
                                bool* periodFlushed) {
    bool needsHwVsync = false;
    *periodFlushed = false;
    { // Scope for the lock
        std::lock_guard<std::mutex> lock(mHWVsyncLock);
        if (mPrimaryHWVsyncEnabled) {
            needsHwVsync =
                    mVsyncSchedule->getController().addHwVsyncTimestamp(timestamp, hwcVsyncPeriod,
                                                                        periodFlushed);
        }
    }

    if (needsHwVsync) {
        enableHardwareVsync();
    } else {
        disableHardwareVsync(false);
    }
bool Scheduler::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriodIn) {
    const auto hwcVsyncPeriod = ftl::Optional(hwcVsyncPeriodIn).transform([](nsecs_t nanos) {
        return Period::fromNs(nanos);
    });
    return mVsyncSchedule->addResyncSample(mSchedulerCallback, TimePoint::fromNs(timestamp),
                                           hwcVsyncPeriod);
}

void Scheduler::addPresentFence(std::shared_ptr<FenceTime> fence) {
@@ -635,14 +590,6 @@ void Scheduler::dump(utils::Dumper& dumper) const {

    mFrameRateOverrideMappings.dump(dumper);
    dumper.eol();

    {
        utils::Dumper::Section section(dumper, "Hardware VSYNC"sv);

        std::lock_guard lock(mHWVsyncLock);
        dumper.dump("hwVsyncAvailable"sv, mHWVsyncAvailable);
        dumper.dump("hwVsyncEnabled"sv, mPrimaryHWVsyncEnabled);
    }
}

void Scheduler::dumpVsync(std::string& out) const {
+9 −23
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@
#include "Display/DisplayModeRequest.h"
#include "EventThread.h"
#include "FrameRateOverrideMappings.h"
#include "ISchedulerCallback.h"
#include "LayerHistory.h"
#include "MessageQueue.h"
#include "OneShotTimer.h"
@@ -92,16 +93,6 @@ namespace scheduler {

using GlobalSignals = RefreshRateSelector::GlobalSignals;

struct ISchedulerCallback {
    virtual void setVsyncEnabled(bool) = 0;
    virtual void requestDisplayModes(std::vector<display::DisplayModeRequest>) = 0;
    virtual void kernelTimerChanged(bool expired) = 0;
    virtual void triggerOnFrameRateOverridesChanged() = 0;

protected:
    ~ISchedulerCallback() = default;
};

class Scheduler : android::impl::MessageQueue {
    using Impl = android::impl::MessageQueue;

@@ -192,20 +183,20 @@ public:
    void setRenderRate(Fps);

    void enableHardwareVsync();
    void disableHardwareVsync(bool makeUnavailable);
    void disableHardwareVsync(bool disallow);

    // Resyncs the scheduler to hardware vsync.
    // If makeAvailable is true, then hardware vsync will be turned on.
    // If allowToEnable is true, then hardware vsync will be turned on.
    // Otherwise, if hardware vsync is not already enabled then this method will
    // no-op.
    void resyncToHardwareVsync(bool makeAvailable, Fps refreshRate);
    void resyncToHardwareVsync(bool allowToEnable, Fps refreshRate);
    void resync() EXCLUDES(mDisplayLock);
    void forceNextResync() { mLastResyncTime = 0; }

    // Passes a vsync sample to VsyncController. periodFlushed will be true if
    // VsyncController detected that the vsync period changed, and false otherwise.
    void addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod,
                         bool* periodFlushed);
    // Passes a vsync sample to VsyncController. Returns true if
    // VsyncController detected that the vsync period changed and false
    // otherwise.
    bool addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod);
    void addPresentFence(std::shared_ptr<FenceTime>);

    // Layers are registered on creation, and unregistered when the weak reference expires.
@@ -297,7 +288,6 @@ private:
    void touchTimerCallback(TimerState);
    void displayPowerTimerCallback(TimerState);

    void setVsyncPeriod(nsecs_t period);
    void setVsyncConfig(const VsyncConfig&, Period vsyncPeriod);

    // Chooses a leader among the registered displays, unless `leaderIdOpt` is specified. The new
@@ -362,14 +352,10 @@ private:
    ConnectionHandle mAppConnectionHandle;
    ConnectionHandle mSfConnectionHandle;

    mutable std::mutex mHWVsyncLock;
    bool mPrimaryHWVsyncEnabled GUARDED_BY(mHWVsyncLock) = false;
    bool mHWVsyncAvailable GUARDED_BY(mHWVsyncLock) = false;

    std::atomic<nsecs_t> mLastResyncTime = 0;

    const FeatureFlags mFeatures;
    std::optional<VsyncSchedule> mVsyncSchedule;
    std::unique_ptr<VsyncSchedule> mVsyncSchedule;

    // Shifts the VSYNC phase during certain transactions and refresh rate changes.
    const sp<VsyncModulator> mVsyncModulator;
+11 −1
Original line number Diff line number Diff line
@@ -31,8 +31,8 @@
#include <android-base/stringprintf.h>
#include <cutils/compiler.h>
#include <cutils/properties.h>
#include <gui/TraceUtils.h>
#include <utils/Log.h>
#include <utils/Trace.h>

#include "RefreshRateSelector.h"
#include "VSyncPredictor.h"
@@ -282,6 +282,13 @@ bool VSyncPredictor::isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const {
}

bool VSyncPredictor::isVSyncInPhaseLocked(nsecs_t timePoint, unsigned divisor) const {
    const TimePoint now = TimePoint::now();
    const auto getTimePointIn = [](TimePoint now, nsecs_t timePoint) -> float {
        return ticks<std::milli, float>(TimePoint::fromNs(timePoint) - now);
    };
    ATRACE_FORMAT("%s timePoint in: %.2f divisor: %zu", __func__, getTimePointIn(now, timePoint),
                  divisor);

    struct VsyncError {
        nsecs_t vsyncTimestamp;
        float error;
@@ -304,6 +311,7 @@ bool VSyncPredictor::isVSyncInPhaseLocked(nsecs_t timePoint, unsigned divisor) c
    if (knownTimestampIter == mRateDivisorKnownTimestampMap.end()) {
        const auto vsync = nextAnticipatedVSyncTimeFromLocked(justBeforeTimePoint);
        mRateDivisorKnownTimestampMap[dividedPeriod] = vsync;
        ATRACE_FORMAT_INSTANT("(first) knownVsync in: %.2f", getTimePointIn(now, vsync));
        return true;
    }

@@ -323,6 +331,8 @@ bool VSyncPredictor::isVSyncInPhaseLocked(nsecs_t timePoint, unsigned divisor) c

    const auto minVsyncError = std::min_element(vsyncs.begin(), vsyncs.end());
    mRateDivisorKnownTimestampMap[dividedPeriod] = minVsyncError->vsyncTimestamp;
    ATRACE_FORMAT_INSTANT("knownVsync in: %.2f",
                          getTimePointIn(now, minVsyncError->vsyncTimestamp));
    return std::abs(minVsyncError->vsyncTimestamp - timePoint) < period / 2;
}

+80 −6
Original line number Diff line number Diff line
@@ -16,11 +16,14 @@

#define ATRACE_TAG ATRACE_TAG_GRAPHICS

#include <ftl/fake_guard.h>
#include <scheduler/Fps.h>
#include <scheduler/Timer.h>

#include "VsyncSchedule.h"

#include "ISchedulerCallback.h"
#include "Utils/Dumper.h"
#include "VSyncDispatchTimerQueue.h"
#include "VSyncPredictor.h"
#include "VSyncReactor.h"
@@ -54,18 +57,16 @@ private:
VsyncSchedule::VsyncSchedule(FeatureFlags features)
      : mTracker(createTracker()),
        mDispatch(createDispatch(*mTracker)),
        mController(createController(*mTracker, features)) {
    if (features.test(Feature::kTracePredictedVsync)) {
        mTracer = std::make_unique<PredictedVsyncTracer>(*mDispatch);
    }
}
        mController(createController(*mTracker, features)),
        mTracer(features.test(Feature::kTracePredictedVsync)
                        ? std::make_unique<PredictedVsyncTracer>(*mDispatch)
                        : nullptr) {}

VsyncSchedule::VsyncSchedule(TrackerPtr tracker, DispatchPtr dispatch, ControllerPtr controller)
      : mTracker(std::move(tracker)),
        mDispatch(std::move(dispatch)),
        mController(std::move(controller)) {}

VsyncSchedule::VsyncSchedule(VsyncSchedule&&) = default;
VsyncSchedule::~VsyncSchedule() = default;

Period VsyncSchedule::period() const {
@@ -77,6 +78,16 @@ TimePoint VsyncSchedule::vsyncDeadlineAfter(TimePoint timePoint) const {
}

void VsyncSchedule::dump(std::string& out) const {
    utils::Dumper dumper(out);
    {
        std::lock_guard<std::mutex> lock(mHwVsyncLock);
        dumper.dump("hwVsyncState", ftl::enum_string(mHwVsyncState));

        ftl::FakeGuard guard(kMainThreadContext);
        dumper.dump("pendingHwVsyncState", ftl::enum_string(mPendingHwVsyncState));
        dumper.eol();
    }

    out.append("VsyncController:\n");
    mController->dump(out);

@@ -120,4 +131,67 @@ VsyncSchedule::ControllerPtr VsyncSchedule::createController(VsyncTracker& track
    return reactor;
}

void VsyncSchedule::startPeriodTransition(ISchedulerCallback& callback, Period period) {
    std::lock_guard<std::mutex> lock(mHwVsyncLock);
    mController->startPeriodTransition(period.ns());
    enableHardwareVsyncLocked(callback);
}

bool VsyncSchedule::addResyncSample(ISchedulerCallback& callback, TimePoint timestamp,
                                    ftl::Optional<Period> hwcVsyncPeriod) {
    bool needsHwVsync = false;
    bool periodFlushed = false;
    {
        std::lock_guard<std::mutex> lock(mHwVsyncLock);
        if (mHwVsyncState == HwVsyncState::Enabled) {
            needsHwVsync = mController->addHwVsyncTimestamp(timestamp.ns(),
                                                            hwcVsyncPeriod.transform(&Period::ns),
                                                            &periodFlushed);
        }
    }
    if (needsHwVsync) {
        enableHardwareVsync(callback);
    } else {
        disableHardwareVsync(callback, false /* disallow */);
    }
    return periodFlushed;
}

void VsyncSchedule::enableHardwareVsync(ISchedulerCallback& callback) {
    std::lock_guard<std::mutex> lock(mHwVsyncLock);
    enableHardwareVsyncLocked(callback);
}

void VsyncSchedule::enableHardwareVsyncLocked(ISchedulerCallback& callback) {
    if (mHwVsyncState == HwVsyncState::Disabled) {
        getTracker().resetModel();
        callback.setVsyncEnabled(true);
        mHwVsyncState = HwVsyncState::Enabled;
    }
}

void VsyncSchedule::disableHardwareVsync(ISchedulerCallback& callback, bool disallow) {
    std::lock_guard<std::mutex> lock(mHwVsyncLock);
    if (mHwVsyncState == HwVsyncState::Enabled) {
        callback.setVsyncEnabled(false);
    }
    mHwVsyncState = disallow ? HwVsyncState::Disallowed : HwVsyncState::Disabled;
}

bool VsyncSchedule::isHardwareVsyncAllowed(bool makeAllowed) {
    std::lock_guard<std::mutex> lock(mHwVsyncLock);
    if (makeAllowed && mHwVsyncState == HwVsyncState::Disallowed) {
        mHwVsyncState = HwVsyncState::Disabled;
    }
    return mHwVsyncState != HwVsyncState::Disallowed;
}

void VsyncSchedule::setPendingHardwareVsyncState(bool enabled) {
    mPendingHwVsyncState = enabled ? HwVsyncState::Enabled : HwVsyncState::Disabled;
}

bool VsyncSchedule::getPendingHardwareVsyncState() const {
    return mPendingHwVsyncState == HwVsyncState::Enabled;
}

} // namespace android::scheduler
Loading