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

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

Merge "SF: Fix thread safety for RefreshRateOverlay" into rvc-dev am: ca4cf8ad

Change-Id: I342e97334fb16bcfe5c4f13f9928093db5ad4b64
parents dbd6f75a ca4cf8ad
Loading
Loading
Loading
Loading
+8 −12
Original line number Diff line number Diff line
@@ -200,26 +200,22 @@ void RefreshRateOverlay::primeCache() {
    }
}

void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) {
    const auto display = mFlinger.getDefaultDisplayDeviceLocked();
    if (!display) {
        return;
    }
void RefreshRateOverlay::setViewport(ui::Size viewport) {
    Rect frame(viewport.width >> 3, viewport.height >> 5);
    frame.offsetBy(viewport.width >> 5, viewport.height >> 4);
    mLayer->setFrame(frame);

    const int32_t left = display->getWidth() / 32;
    const int32_t top = display->getHeight() / 16;
    const int32_t right = left + display->getWidth() / 8;
    const int32_t buttom = top + display->getHeight() / 32;
    mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
}

void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) {
    auto buffer = mBufferCache[refreshRate.getFps()];
    mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {});

    mLayer->setFrame(Rect(left, top, right, buttom));

    mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
}

}; // namespace android
} // namespace android

// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion"
+21 −5
Original line number Diff line number Diff line
@@ -13,19 +13,35 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include "SurfaceFlinger.h"
#include <unordered_map>

#include <math/vec4.h>
#include <ui/Rect.h>
#include <ui/Size.h>
#include <utils/StrongPointer.h>

#include "Scheduler/RefreshRateConfigs.h"

namespace android {

class Client;
class GraphicBuffer;
class IBinder;
class IGraphicBufferProducer;
class Layer;
class SurfaceFlinger;

using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate;

class RefreshRateOverlay {
public:
    RefreshRateOverlay(SurfaceFlinger& flinger);
    explicit RefreshRateOverlay(SurfaceFlinger&);

    void changeRefreshRate(const RefreshRate& refreshRate);
    void setViewport(ui::Size);
    void changeRefreshRate(const RefreshRate&);

private:
    class SevenSegmentDrawer {
@@ -56,7 +72,7 @@ private:
    void primeCache();

    SurfaceFlinger& mFlinger;
    sp<Client> mClient;
    const sp<Client> mClient;
    sp<Layer> mLayer;
    sp<IBinder> mIBinder;
    sp<IGraphicBufferProducer> mGbp;
@@ -68,4 +84,4 @@ private:
    const half3 HIGH_FPS_COLOR = half3(0.0f, 1.0f, 0.0f);
};

}; // namespace android
} // namespace android
+55 −39
Original line number Diff line number Diff line
@@ -582,14 +582,13 @@ void SurfaceFlinger::bootFinished()
    LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
                   ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));

    static_cast<void>(schedule([this]() NO_THREAD_SAFETY_ANALYSIS {
    static_cast<void>(schedule([this] {
        readPersistentProperties();
        mPowerAdvisor.onBootFinished();
        mBootStage = BootStage::FINISHED;

        if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) {
            mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this);
            mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate());
            enableRefreshRateOverlay(true);
        }
    }));
}
@@ -934,9 +933,8 @@ int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) {
    }

    if (isPrimary) {
        std::lock_guard<std::mutex> lock(mActiveConfigLock);
        if (mDesiredActiveConfigChanged) {
            return mDesiredActiveConfig.configId.value();
        if (const auto config = getDesiredActiveConfig()) {
            return config->configId.value();
        }
    }

@@ -1063,14 +1061,7 @@ void SurfaceFlinger::performSetActiveConfig() {
    ATRACE_CALL();
    ALOGV("performSetActiveConfig");
    // Store the local variable to release the lock.
    const auto desiredActiveConfig = [&]() -> std::optional<ActiveConfigInfo> {
        std::lock_guard<std::mutex> lock(mActiveConfigLock);
        if (mDesiredActiveConfigChanged) {
            return mDesiredActiveConfig;
        }
        return std::nullopt;
    }();

    const auto desiredActiveConfig = getDesiredActiveConfig();
    if (!desiredActiveConfig) {
        // No desired active config pending to be applied
        return;
@@ -1605,7 +1596,7 @@ void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate,
}

void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId,
                                       hal::Connection connection) {
                                       hal::Connection connection) NO_THREAD_SAFETY_ANALYSIS {
    ALOGV("%s(%d, %" PRIu64 ", %s)", __FUNCTION__, sequenceId, hwcDisplayId,
          connection == hal::Connection::CONNECTED ? "connected" : "disconnected");

@@ -2679,9 +2670,14 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken,
        if (currentState.width != drawingState.width ||
            currentState.height != drawingState.height) {
            display->setDisplaySize(currentState.width, currentState.height);

            if (display->isPrimary()) {
                mScheduler->onPrimaryDisplayAreaChanged(currentState.width * currentState.height);
            }

            if (mRefreshRateOverlay) {
                mRefreshRateOverlay->setViewport(display->getSize());
            }
        }
    }
}
@@ -5229,16 +5225,16 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r
                return NO_ERROR;
            }
            case 1034: {
                n = data.readInt32();
                if (n == 1 && !mRefreshRateOverlay) {
                    mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this);
                    auto& current = mRefreshRateConfigs->getCurrentRefreshRate();
                    mRefreshRateOverlay->changeRefreshRate(current);
                } else if (n == 0) {
                    mRefreshRateOverlay.reset();
                } else {
                switch (n = data.readInt32()) {
                    case 0:
                    case 1:
                        enableRefreshRateOverlay(static_cast<bool>(n));
                        break;
                    default: {
                        Mutex::Autolock lock(mStateLock);
                        reply->writeBool(mRefreshRateOverlay != nullptr);
                    }
                }
                return NO_ERROR;
            }
            case 1035: {
@@ -5285,29 +5281,26 @@ void SurfaceFlinger::repaintEverythingForHWC() {
void SurfaceFlinger::kernelTimerChanged(bool expired) {
    static bool updateOverlay =
            property_get_bool("debug.sf.kernel_idle_timer_update_overlay", true);
    if (!updateOverlay || !mRefreshRateOverlay) return;
    if (!updateOverlay) return;
    if (Mutex::Autolock lock(mStateLock); !mRefreshRateOverlay) return;

    // Update the overlay on the main thread to avoid race conditions with
    // mRefreshRateConfigs->getCurrentRefreshRate()
    static_cast<void>(schedule([=]() NO_THREAD_SAFETY_ANALYSIS {
        if (mRefreshRateOverlay) {
            const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false);
            const bool timerExpired = kernelTimerEnabled && expired;
            const auto& current = [this]() -> const RefreshRate& {
                std::lock_guard<std::mutex> lock(mActiveConfigLock);
                if (mDesiredActiveConfigChanged) {
                    return mRefreshRateConfigs->getRefreshRateFromConfigId(
                            mDesiredActiveConfig.configId);
                }

                return mRefreshRateConfigs->getCurrentRefreshRate();
            }();
    static_cast<void>(schedule([=] {
        const auto desiredActiveConfig = getDesiredActiveConfig();
        const auto& current = desiredActiveConfig
                ? mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig->configId)
                : mRefreshRateConfigs->getCurrentRefreshRate();
        const auto& min = mRefreshRateConfigs->getMinRefreshRate();

        if (current != min) {
            const auto kernelTimerEnabled = property_get_bool(KERNEL_IDLE_TIMER_PROP, false);
            const bool timerExpired = kernelTimerEnabled && expired;

            if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) {
                mRefreshRateOverlay->changeRefreshRate(timerExpired ? min : current);
                mEventQueue->invalidate();
            }
            mEventQueue->invalidate();
        }
    }));
}
@@ -6224,6 +6217,29 @@ void SurfaceFlinger::onFrameRateFlexibilityTokenReleased() {
    }));
}

void SurfaceFlinger::enableRefreshRateOverlay(bool enable) {
    static_cast<void>(schedule([=] {
        std::unique_ptr<RefreshRateOverlay> overlay;
        if (enable) {
            overlay = std::make_unique<RefreshRateOverlay>(*this);
        }

        {
            Mutex::Autolock lock(mStateLock);

            // Destroy the layer of the current overlay, if any, outside the lock.
            mRefreshRateOverlay.swap(overlay);
            if (!mRefreshRateOverlay) return;

            if (const auto display = getDefaultDisplayDeviceLocked()) {
                mRefreshRateOverlay->setViewport(display->getSize());
            }

            mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate());
        }
    }));
}

} // namespace android

#if defined(__gl_h_)
+11 −4
Original line number Diff line number Diff line
@@ -829,13 +829,13 @@ private:
            const DisplayDeviceState& state,
            const sp<compositionengine::DisplaySurface>& displaySurface,
            const sp<IGraphicBufferProducer>& producer);
    void processDisplayChangesLocked();
    void processDisplayChangesLocked() REQUIRES(mStateLock);
    void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState& state);
    void processDisplayRemoved(const wp<IBinder>& displayToken);
    void processDisplayChanged(const wp<IBinder>& displayToken,
                               const DisplayDeviceState& currentState,
                               const DisplayDeviceState& drawingState);
    void processDisplayHotplugEventsLocked();
                               const DisplayDeviceState& drawingState) REQUIRES(mStateLock);
    void processDisplayHotplugEventsLocked() REQUIRES(mStateLock);

    void dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected);

@@ -1216,6 +1216,12 @@ private:
     * Misc
     */

    std::optional<ActiveConfigInfo> getDesiredActiveConfig() EXCLUDES(mActiveConfigLock) {
        std::lock_guard<std::mutex> lock(mActiveConfigLock);
        if (mDesiredActiveConfigChanged) return mDesiredActiveConfig;
        return std::nullopt;
    }

    std::mutex mActiveConfigLock;
    // This bit is set once we start setting the config. We read from this bit during the
    // process. If at the end, this bit is different than mDesiredActiveConfig, we restart
@@ -1258,7 +1264,8 @@ private:
    // This should only be accessed on the main thread.
    nsecs_t mFrameStartTime = 0;

    std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay;
    void enableRefreshRateOverlay(bool enable);
    std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay GUARDED_BY(mStateLock);

    // Flag used to set override allowed display configs from backdoor
    bool mDebugDisplayConfigSetByBackdoor = false;