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

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

Merge "SF: Enforce thread safety for SurfaceFlinger class" into rvc-dev am:...

Merge "SF: Enforce thread safety for SurfaceFlinger class" into rvc-dev am: b209e7b5 am: 78602bbf am: 875641c2

Change-Id: I8ada22974469a7ef8686a2f583af709fa3efc92a
parents 64c3517c 875641c2
Loading
Loading
Loading
Loading
+119 −111
Original line number Original line Diff line number Diff line
@@ -125,6 +125,19 @@
#include "android-base/parseint.h"
#include "android-base/parseint.h"
#include "android-base/stringprintf.h"
#include "android-base/stringprintf.h"


#define MAIN_THREAD ACQUIRE(mStateLock) RELEASE(mStateLock)

#define ON_MAIN_THREAD(expr)                                       \
    [&] {                                                          \
        LOG_FATAL_IF(std::this_thread::get_id() != mMainThreadId); \
        UnnecessaryLock lock(mStateLock);                          \
        return (expr);                                             \
    }()

#undef NO_THREAD_SAFETY_ANALYSIS
#define NO_THREAD_SAFETY_ANALYSIS \
    _Pragma("GCC error \"Prefer MAIN_THREAD macros or {Conditional,Timed,Unnecessary}Lock.\"")

namespace android {
namespace android {


using namespace std::string_literals;
using namespace std::string_literals;
@@ -173,12 +186,12 @@ bool isWideColorMode(const ColorMode colorMode) {
#pragma clang diagnostic pop
#pragma clang diagnostic pop


template <typename Mutex>
template <typename Mutex>
struct ConditionalLockGuard {
struct SCOPED_CAPABILITY ConditionalLockGuard {
    ConditionalLockGuard(Mutex& mutex, bool lock) : mutex(mutex), lock(lock) {
    ConditionalLockGuard(Mutex& mutex, bool lock) ACQUIRE(mutex) : mutex(mutex), lock(lock) {
        if (lock) mutex.lock();
        if (lock) mutex.lock();
    }
    }


    ~ConditionalLockGuard() {
    ~ConditionalLockGuard() RELEASE() {
        if (lock) mutex.unlock();
        if (lock) mutex.unlock();
    }
    }


@@ -188,6 +201,27 @@ struct ConditionalLockGuard {


using ConditionalLock = ConditionalLockGuard<Mutex>;
using ConditionalLock = ConditionalLockGuard<Mutex>;


struct SCOPED_CAPABILITY TimedLock {
    TimedLock(Mutex& mutex, nsecs_t timeout, const char* whence) ACQUIRE(mutex)
          : mutex(mutex), status(mutex.timedLock(timeout)) {
        ALOGE_IF(!locked(), "%s timed out locking: %s (%d)", whence, strerror(-status), status);
    }

    ~TimedLock() RELEASE() {
        if (locked()) mutex.unlock();
    }

    bool locked() const { return status == NO_ERROR; }

    Mutex& mutex;
    const status_t status;
};

struct SCOPED_CAPABILITY UnnecessaryLock {
    explicit UnnecessaryLock(Mutex& mutex) ACQUIRE(mutex) {}
    ~UnnecessaryLock() RELEASE() {}
};

// TODO(b/141333600): Consolidate with HWC2::Display::Config::Builder::getDefaultDensity.
// TODO(b/141333600): Consolidate with HWC2::Display::Config::Builder::getDefaultDensity.
constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV;
constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV;


@@ -991,7 +1025,7 @@ status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mo
    }
    }


    auto future = schedule([=]() -> status_t {
    auto future = schedule([=]() -> status_t {
        const auto display = getDisplayDeviceLocked(displayToken);
        const auto display = ON_MAIN_THREAD(getDisplayDeviceLocked(displayToken));
        if (!display) {
        if (!display) {
            ALOGE("Attempt to set allowed display configs for invalid display token %p",
            ALOGE("Attempt to set allowed display configs for invalid display token %p",
                  displayToken.get());
                  displayToken.get());
@@ -1176,7 +1210,7 @@ ColorMode SurfaceFlinger::getActiveColorMode(const sp<IBinder>& displayToken) {
}
}


status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, ColorMode mode) {
status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, ColorMode mode) {
    schedule([=] {
    schedule([=]() MAIN_THREAD {
        Vector<ColorMode> modes;
        Vector<ColorMode> modes;
        getDisplayColorModes(displayToken, &modes);
        getDisplayColorModes(displayToken, &modes);
        bool exists = std::find(std::begin(modes), std::end(modes), mode) != std::end(modes);
        bool exists = std::find(std::begin(modes), std::end(modes), mode) != std::end(modes);
@@ -1222,7 +1256,7 @@ status_t SurfaceFlinger::getAutoLowLatencyModeSupport(const sp<IBinder>& display
}
}


void SurfaceFlinger::setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on) {
void SurfaceFlinger::setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on) {
    static_cast<void>(schedule([=] {
    static_cast<void>(schedule([=]() MAIN_THREAD {
        if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
        if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
            getHwComposer().setAutoLowLatencyMode(*displayId, on);
            getHwComposer().setAutoLowLatencyMode(*displayId, on);
        } else {
        } else {
@@ -1253,7 +1287,7 @@ status_t SurfaceFlinger::getGameContentTypeSupport(const sp<IBinder>& displayTok
}
}


void SurfaceFlinger::setGameContentType(const sp<IBinder>& displayToken, bool on) {
void SurfaceFlinger::setGameContentType(const sp<IBinder>& displayToken, bool on) {
    static_cast<void>(schedule([=] {
    static_cast<void>(schedule([=]() MAIN_THREAD {
        if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
        if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
            const auto type = on ? hal::ContentType::GAME : hal::ContentType::NONE;
            const auto type = on ? hal::ContentType::GAME : hal::ContentType::NONE;
            getHwComposer().setContentType(*displayId, type);
            getHwComposer().setContentType(*displayId, type);
@@ -1343,7 +1377,7 @@ status_t SurfaceFlinger::getDisplayedContentSamplingAttributes(const sp<IBinder>
status_t SurfaceFlinger::setDisplayContentSamplingEnabled(const sp<IBinder>& displayToken,
status_t SurfaceFlinger::setDisplayContentSamplingEnabled(const sp<IBinder>& displayToken,
                                                          bool enable, uint8_t componentMask,
                                                          bool enable, uint8_t componentMask,
                                                          uint64_t maxFrames) {
                                                          uint64_t maxFrames) {
    return schedule([=]() -> status_t {
    return schedule([=]() MAIN_THREAD -> status_t {
               if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
               if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
                   return getHwComposer().setDisplayContentSamplingEnabled(*displayId, enable,
                   return getHwComposer().setDisplayContentSamplingEnabled(*displayId, enable,
                                                                           componentMask,
                                                                           componentMask,
@@ -1412,13 +1446,9 @@ status_t SurfaceFlinger::injectVSync(nsecs_t when) {
    return mScheduler->injectVSync(when, calculateExpectedPresentTime(when)) ? NO_ERROR : BAD_VALUE;
    return mScheduler->injectVSync(when, calculateExpectedPresentTime(when)) ? NO_ERROR : BAD_VALUE;
}
}


status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const
status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const {
        NO_THREAD_SAFETY_ANALYSIS {
    TimedLock lock(mStateLock, s2ns(1), __FUNCTION__);
    // Try to acquire a lock for 1s, fail gracefully
    if (!lock.locked()) {
    const status_t err = mStateLock.timedLock(s2ns(1));
    const bool locked = (err == NO_ERROR);
    if (!locked) {
        ALOGE("LayerDebugInfo: SurfaceFlinger unresponsive (%s [%d]) - exit", strerror(-err), err);
        return TIMED_OUT;
        return TIMED_OUT;
    }
    }


@@ -1427,7 +1457,6 @@ status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayer
    mCurrentState.traverseInZOrder(
    mCurrentState.traverseInZOrder(
            [&](Layer* layer) { outLayers->push_back(layer->getLayerDebugInfo(display.get())); });
            [&](Layer* layer) { outLayers->push_back(layer->getLayerDebugInfo(display.get())); });


    mStateLock.unlock();
    return NO_ERROR;
    return NO_ERROR;
}
}


@@ -1484,7 +1513,7 @@ status_t SurfaceFlinger::setDisplayBrightness(const sp<IBinder>& displayToken, f
        return BAD_VALUE;
        return BAD_VALUE;
    }
    }


    return promise::chain(schedule([=] {
    return promise::chain(schedule([=]() MAIN_THREAD {
               if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
               if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
                   return getHwComposer().setDisplayBrightness(*displayId, brightness);
                   return getHwComposer().setDisplayBrightness(*displayId, brightness);
               } else {
               } else {
@@ -1597,7 +1626,7 @@ void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate,
}
}


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


@@ -1650,8 +1679,7 @@ void SurfaceFlinger::setPrimaryVsyncEnabled(bool enabled) {


    // Enable / Disable HWVsync from the main thread to avoid race conditions with
    // Enable / Disable HWVsync from the main thread to avoid race conditions with
    // display power state.
    // display power state.
    static_cast<void>(
    static_cast<void>(schedule([=]() MAIN_THREAD { setPrimaryVsyncEnabledInternal(enabled); }));
            schedule([=]() NO_THREAD_SAFETY_ANALYSIS { setPrimaryVsyncEnabledInternal(enabled); }));
}
}


void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) {
void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) {
@@ -1667,7 +1695,6 @@ void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) {
    }
    }
}
}


// Note: it is assumed the caller holds |mStateLock| when this is called
void SurfaceFlinger::resetDisplayState() {
void SurfaceFlinger::resetDisplayState() {
    mScheduler->disableHardwareVsync(true);
    mScheduler->disableHardwareVsync(true);
    // Clear the drawing state so that the logic inside of
    // Clear the drawing state so that the logic inside of
@@ -1760,7 +1787,7 @@ void SurfaceFlinger::updateVrFlinger() {
    setTransactionFlags(eDisplayTransactionNeeded);
    setTransactionFlags(eDisplayTransactionNeeded);
}
}


sp<Fence> SurfaceFlinger::previousFrameFence() NO_THREAD_SAFETY_ANALYSIS {
sp<Fence> SurfaceFlinger::previousFrameFence() {
    // We are storing the last 2 present fences. If sf's phase offset is to be
    // We are storing the last 2 present fences. If sf's phase offset is to be
    // woken up before the actual vsync but targeting the next vsync, we need to check
    // woken up before the actual vsync but targeting the next vsync, we need to check
    // fence N-2
    // fence N-2
@@ -1768,7 +1795,7 @@ sp<Fence> SurfaceFlinger::previousFrameFence() NO_THREAD_SAFETY_ANALYSIS {
                                                : mPreviousPresentFences[1];
                                                : mPreviousPresentFences[1];
}
}


bool SurfaceFlinger::previousFramePending(int graceTimeMs) NO_THREAD_SAFETY_ANALYSIS {
bool SurfaceFlinger::previousFramePending(int graceTimeMs) {
    ATRACE_CALL();
    ATRACE_CALL();
    const sp<Fence>& fence = previousFrameFence();
    const sp<Fence>& fence = previousFrameFence();


@@ -1782,7 +1809,7 @@ bool SurfaceFlinger::previousFramePending(int graceTimeMs) NO_THREAD_SAFETY_ANAL
    return status == -ETIME;
    return status == -ETIME;
}
}


nsecs_t SurfaceFlinger::previousFramePresentTime() NO_THREAD_SAFETY_ANALYSIS {
nsecs_t SurfaceFlinger::previousFramePresentTime() {
    const sp<Fence>& fence = previousFrameFence();
    const sp<Fence>& fence = previousFrameFence();


    if (fence == Fence::NO_FENCE) {
    if (fence == Fence::NO_FENCE) {
@@ -1800,8 +1827,7 @@ nsecs_t SurfaceFlinger::calculateExpectedPresentTime(nsecs_t now) const {
    return mVSyncModulator->getOffsets().sf > 0 ? presentTime : presentTime + stats.vsyncPeriod;
    return mVSyncModulator->getOffsets().sf > 0 ? presentTime : presentTime + stats.vsyncPeriod;
}
}


void SurfaceFlinger::onMessageReceived(int32_t what,
void SurfaceFlinger::onMessageReceived(int32_t what, nsecs_t expectedVSyncTime) {
                                       nsecs_t expectedVSyncTime) NO_THREAD_SAFETY_ANALYSIS {
    ATRACE_CALL();
    ATRACE_CALL();
    switch (what) {
    switch (what) {
        case MessageQueue::INVALIDATE: {
        case MessageQueue::INVALIDATE: {
@@ -1815,7 +1841,7 @@ void SurfaceFlinger::onMessageReceived(int32_t what,
    }
    }
}
}


void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) NO_THREAD_SAFETY_ANALYSIS {
void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) {
    ATRACE_CALL();
    ATRACE_CALL();


    const nsecs_t frameStart = systemTime();
    const nsecs_t frameStart = systemTime();
@@ -1888,7 +1914,7 @@ void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) NO_THREAD_SA
        // We received the present fence from the HWC, so we assume it successfully updated
        // We received the present fence from the HWC, so we assume it successfully updated
        // the config, hence we update SF.
        // the config, hence we update SF.
        mSetActiveConfigPending = false;
        mSetActiveConfigPending = false;
        setActiveConfigInternal();
        ON_MAIN_THREAD(setActiveConfigInternal());
    }
    }


    if (framePending && mPropagateBackpressure) {
    if (framePending && mPropagateBackpressure) {
@@ -1907,12 +1933,12 @@ void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) NO_THREAD_SA
            std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
            std::chrono::duration_cast<std::chrono::nanoseconds>(1s).count();
    // If we're in a user build then don't push any atoms
    // If we're in a user build then don't push any atoms
    if (!mIsUserBuild && mMissedFrameJankCount > 0) {
    if (!mIsUserBuild && mMissedFrameJankCount > 0) {
        const auto displayDevice = getDefaultDisplayDeviceLocked();
        const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
        // Only report jank when the display is on, as displays in DOZE
        // Only report jank when the display is on, as displays in DOZE
        // power mode may operate at a different frame rate than is
        // power mode may operate at a different frame rate than is
        // reported in their config, which causes noticeable (but less
        // reported in their config, which causes noticeable (but less
        // severe) jank.
        // severe) jank.
        if (displayDevice && displayDevice->getPowerMode() == hal::PowerMode::ON) {
        if (display && display->getPowerMode() == hal::PowerMode::ON) {
            const nsecs_t currentTime = systemTime();
            const nsecs_t currentTime = systemTime();
            const nsecs_t jankDuration = currentTime - mMissedFrameJankStart;
            const nsecs_t jankDuration = currentTime - mMissedFrameJankStart;
            if (jankDuration > kMinJankyDuration && jankDuration < kMaxJankyDuration) {
            if (jankDuration > kMinJankyDuration && jankDuration < kMaxJankyDuration) {
@@ -1969,7 +1995,7 @@ void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) NO_THREAD_SA
        mScheduler->chooseRefreshRateForContent();
        mScheduler->chooseRefreshRateForContent();
    }
    }


    performSetActiveConfig();
    ON_MAIN_THREAD(performSetActiveConfig());


    updateCursorAsync();
    updateCursorAsync();
    updateInputFlinger();
    updateInputFlinger();
@@ -2018,8 +2044,9 @@ void SurfaceFlinger::onMessageRefresh() {
    mRefreshPending = false;
    mRefreshPending = false;


    compositionengine::CompositionRefreshArgs refreshArgs;
    compositionengine::CompositionRefreshArgs refreshArgs;
    refreshArgs.outputs.reserve(mDisplays.size());
    const auto& displays = ON_MAIN_THREAD(mDisplays);
    for (const auto& [_, display] : mDisplays) {
    refreshArgs.outputs.reserve(displays.size());
    for (const auto& [_, display] : displays) {
        refreshArgs.outputs.push_back(display->getCompositionDisplay());
        refreshArgs.outputs.push_back(display->getCompositionDisplay());
    }
    }
    mDrawingState.traverseInZOrder([&refreshArgs](Layer* layer) {
    mDrawingState.traverseInZOrder([&refreshArgs](Layer* layer) {
@@ -2074,21 +2101,18 @@ void SurfaceFlinger::onMessageRefresh() {


    const bool prevFrameHadDeviceComposition = mHadDeviceComposition;
    const bool prevFrameHadDeviceComposition = mHadDeviceComposition;


    mHadClientComposition =
    mHadClientComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) {
            std::any_of(mDisplays.cbegin(), mDisplays.cend(), [](const auto& tokenDisplayPair) {
        const auto& state = pair.second->getCompositionDisplay()->getState();
                auto& displayDevice = tokenDisplayPair.second;
        return state.usesClientComposition && !state.reusedClientComposition;
                return displayDevice->getCompositionDisplay()->getState().usesClientComposition &&
                        !displayDevice->getCompositionDisplay()->getState().reusedClientComposition;
    });
    });
    mHadDeviceComposition =
    mHadDeviceComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) {
            std::any_of(mDisplays.cbegin(), mDisplays.cend(), [](const auto& tokenDisplayPair) {
        const auto& state = pair.second->getCompositionDisplay()->getState();
                auto& displayDevice = tokenDisplayPair.second;
        return state.usesDeviceComposition;
                return displayDevice->getCompositionDisplay()->getState().usesDeviceComposition;
    });
    });
    mReusedClientComposition =
    mReusedClientComposition =
            std::any_of(mDisplays.cbegin(), mDisplays.cend(), [](const auto& tokenDisplayPair) {
            std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) {
                auto& displayDevice = tokenDisplayPair.second;
                const auto& state = pair.second->getCompositionDisplay()->getState();
                return displayDevice->getCompositionDisplay()->getState().reusedClientComposition;
                return state.reusedClientComposition;
            });
            });


    // Only report a strategy change if we move in and out of composition with hw overlays
    // Only report a strategy change if we move in and out of composition with hw overlays
@@ -2194,14 +2218,14 @@ void SurfaceFlinger::postComposition()
    for (auto& layer : mLayersWithQueuedFrames) {
    for (auto& layer : mLayersWithQueuedFrames) {
        layer->releasePendingBuffer(dequeueReadyTime);
        layer->releasePendingBuffer(dequeueReadyTime);
    }
    }
    // |mStateLock| not needed as we are on the main thread

    const auto displayDevice = getDefaultDisplayDeviceLocked();
    const auto* display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()).get();


    getBE().mGlCompositionDoneTimeline.updateSignalTimes();
    getBE().mGlCompositionDoneTimeline.updateSignalTimes();
    std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
    std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
    if (displayDevice && displayDevice->getCompositionDisplay()->getState().usesClientComposition) {
    if (display && display->getCompositionDisplay()->getState().usesClientComposition) {
        glCompositionDoneFenceTime =
        glCompositionDoneFenceTime =
                std::make_shared<FenceTime>(displayDevice->getCompositionDisplay()
                std::make_shared<FenceTime>(display->getCompositionDisplay()
                                                    ->getRenderSurface()
                                                    ->getRenderSurface()
                                                    ->getClientTargetAcquireFence());
                                                    ->getClientTargetAcquireFence());
        getBE().mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime);
        getBE().mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime);
@@ -2211,9 +2235,8 @@ void SurfaceFlinger::postComposition()


    getBE().mDisplayTimeline.updateSignalTimes();
    getBE().mDisplayTimeline.updateSignalTimes();
    mPreviousPresentFences[1] = mPreviousPresentFences[0];
    mPreviousPresentFences[1] = mPreviousPresentFences[0];
    mPreviousPresentFences[0] = displayDevice
    mPreviousPresentFences[0] =
            ? getHwComposer().getPresentFence(*displayDevice->getId())
            display ? getHwComposer().getPresentFence(*display->getId()) : Fence::NO_FENCE;
            : Fence::NO_FENCE;
    auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFences[0]);
    auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFences[0]);
    getBE().mDisplayTimeline.push(presentFenceTime);
    getBE().mDisplayTimeline.push(presentFenceTime);


@@ -2232,8 +2255,7 @@ void SurfaceFlinger::postComposition()
    }
    }


    mDrawingState.traverse([&](Layer* layer) {
    mDrawingState.traverse([&](Layer* layer) {
        const bool frameLatched =
        const bool frameLatched = layer->onPostComposition(display, glCompositionDoneFenceTime,
                layer->onPostComposition(displayDevice.get(), glCompositionDoneFenceTime,
                                                           presentFenceTime, compositorTiming);
                                                           presentFenceTime, compositorTiming);
        if (frameLatched) {
        if (frameLatched) {
            recordBufferingStats(layer->getName(), layer->getOccupancyHistory(false));
            recordBufferingStats(layer->getName(), layer->getOccupancyHistory(false));
@@ -2243,14 +2265,15 @@ void SurfaceFlinger::postComposition()
    mTransactionCompletedThread.addPresentFence(mPreviousPresentFences[0]);
    mTransactionCompletedThread.addPresentFence(mPreviousPresentFences[0]);
    mTransactionCompletedThread.sendCallbacks();
    mTransactionCompletedThread.sendCallbacks();


    if (displayDevice && displayDevice->isPrimary() &&
    if (display && display->isPrimary() && display->getPowerMode() == hal::PowerMode::ON &&
        displayDevice->getPowerMode() == hal::PowerMode::ON && presentFenceTime->isValid()) {
        presentFenceTime->isValid()) {
        mScheduler->addPresentFence(presentFenceTime);
        mScheduler->addPresentFence(presentFenceTime);
    }
    }


    const bool isDisplayConnected = display && getHwComposer().isConnected(*display->getId());

    if (!hasSyncFramework) {
    if (!hasSyncFramework) {
        if (displayDevice && getHwComposer().isConnected(*displayDevice->getId()) &&
        if (isDisplayConnected && display->isPoweredOn()) {
            displayDevice->isPoweredOn()) {
            mScheduler->enableHardwareVsync();
            mScheduler->enableHardwareVsync();
        }
        }
    }
    }
@@ -2261,11 +2284,10 @@ void SurfaceFlinger::postComposition()
        if (presentFenceTime->isValid()) {
        if (presentFenceTime->isValid()) {
            mAnimFrameTracker.setActualPresentFence(
            mAnimFrameTracker.setActualPresentFence(
                    std::move(presentFenceTime));
                    std::move(presentFenceTime));
        } else if (displayDevice && getHwComposer().isConnected(*displayDevice->getId())) {
        } else if (isDisplayConnected) {
            // The HWC doesn't support present fences, so use the refresh
            // The HWC doesn't support present fences, so use the refresh
            // timestamp instead.
            // timestamp instead.
            const nsecs_t presentTime =
            const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(*display->getId());
                    getHwComposer().getRefreshTimestamp(*displayDevice->getId());
            mAnimFrameTracker.setActualPresentTime(presentTime);
            mAnimFrameTracker.setActualPresentTime(presentTime);
        }
        }
        mAnimFrameTracker.advanceFrame();
        mAnimFrameTracker.advanceFrame();
@@ -2286,8 +2308,7 @@ void SurfaceFlinger::postComposition()
    const size_t appConnections = mScheduler->getEventThreadConnectionCount(mAppConnectionHandle);
    const size_t appConnections = mScheduler->getEventThreadConnectionCount(mAppConnectionHandle);
    mTimeStats->recordDisplayEventConnectionCount(sfConnections + appConnections);
    mTimeStats->recordDisplayEventConnectionCount(sfConnections + appConnections);


    if (displayDevice && getHwComposer().isConnected(*displayDevice->getId()) &&
    if (isDisplayConnected && !display->isPoweredOn()) {
        !displayDevice->isPoweredOn()) {
        return;
        return;
    }
    }


@@ -2343,7 +2364,7 @@ FloatRect SurfaceFlinger::getLayerClipBoundsForDisplay(const DisplayDevice& disp
}
}


void SurfaceFlinger::computeLayerBounds() {
void SurfaceFlinger::computeLayerBounds() {
    for (const auto& pair : mDisplays) {
    for (const auto& pair : ON_MAIN_THREAD(mDisplays)) {
        const auto& displayDevice = pair.second;
        const auto& displayDevice = pair.second;
        const auto display = displayDevice->getCompositionDisplay();
        const auto display = displayDevice->getCompositionDisplay();
        for (const auto& layer : mDrawingState.layersSortedByZ) {
        for (const auto& layer : mDrawingState.layersSortedByZ) {
@@ -2358,10 +2379,8 @@ void SurfaceFlinger::computeLayerBounds() {
    }
    }
}
}


void SurfaceFlinger::postFrame()
void SurfaceFlinger::postFrame() {
{
    const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
    // |mStateLock| not needed as we are on the main thread
    const auto display = getDefaultDisplayDeviceLocked();
    if (display && getHwComposer().isConnected(*display->getId())) {
    if (display && getHwComposer().isConnected(*display->getId())) {
        uint32_t flipCount = display->getPageFlipCount();
        uint32_t flipCount = display->getPageFlipCount();
        if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
        if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
@@ -2789,7 +2808,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
        sp<const DisplayDevice> hintDisplay;
        sp<const DisplayDevice> hintDisplay;
        uint32_t currentlayerStack = 0;
        uint32_t currentlayerStack = 0;
        bool first = true;
        bool first = true;
        mCurrentState.traverse([&](Layer* layer) {
        mCurrentState.traverse([&](Layer* layer) REQUIRES(mStateLock) {
            // NOTE: we rely on the fact that layers are sorted by
            // NOTE: we rely on the fact that layers are sorted by
            // layerStack first (so we don't have to traverse the list
            // layerStack first (so we don't have to traverse the list
            // of displays for every layer).
            // of displays for every layer).
@@ -2902,10 +2921,9 @@ void SurfaceFlinger::commitInputWindowCommands() {
    mPendingInputWindowCommands.clear();
    mPendingInputWindowCommands.clear();
}
}


void SurfaceFlinger::updateCursorAsync()
void SurfaceFlinger::updateCursorAsync() {
{
    compositionengine::CompositionRefreshArgs refreshArgs;
    compositionengine::CompositionRefreshArgs refreshArgs;
    for (const auto& [_, display] : mDisplays) {
    for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
        if (display->getId()) {
        if (display->getId()) {
            refreshArgs.outputs.push_back(display->getCompositionDisplay());
            refreshArgs.outputs.push_back(display->getCompositionDisplay());
        }
        }
@@ -2915,7 +2933,7 @@ void SurfaceFlinger::updateCursorAsync()
}
}


void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate,
void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate,
                                       Scheduler::ConfigEvent event) NO_THREAD_SAFETY_ANALYSIS {
                                       Scheduler::ConfigEvent event) {
    // If this is called from the main thread mStateLock must be locked before
    // If this is called from the main thread mStateLock must be locked before
    // Currently the only way to call this function from the main thread is from
    // Currently the only way to call this function from the main thread is from
    // Sheduler::chooseRefreshRateForContent
    // Sheduler::chooseRefreshRateForContent
@@ -3041,7 +3059,7 @@ void SurfaceFlinger::commitOffscreenLayers() {
}
}


void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) {
void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) {
    for (const auto& [token, displayDevice] : mDisplays) {
    for (const auto& [token, displayDevice] : ON_MAIN_THREAD(mDisplays)) {
        auto display = displayDevice->getCompositionDisplay();
        auto display = displayDevice->getCompositionDisplay();
        if (display->belongsInOutput(layer->getLayerStack(), layer->getPrimaryDisplayOnly())) {
        if (display->belongsInOutput(layer->getLayerStack(), layer->getPrimaryDisplayOnly())) {
            display->editState().dirtyRegion.orSelf(dirty);
            display->editState().dirtyRegion.orSelf(dirty);
@@ -4137,7 +4155,7 @@ void SurfaceFlinger::onInitializeDisplays() {


void SurfaceFlinger::initializeDisplays() {
void SurfaceFlinger::initializeDisplays() {
    // Async since we may be called from the main thread.
    // Async since we may be called from the main thread.
    static_cast<void>(schedule([this]() NO_THREAD_SAFETY_ANALYSIS { onInitializeDisplays(); }));
    static_cast<void>(schedule([this]() MAIN_THREAD { onInitializeDisplays(); }));
}
}


void SurfaceFlinger::setVsyncEnabledInHWC(DisplayId displayId, hal::Vsync enabled) {
void SurfaceFlinger::setVsyncEnabledInHWC(DisplayId displayId, hal::Vsync enabled) {
@@ -4228,7 +4246,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal:
}
}


void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
    schedule([=]() NO_THREAD_SAFETY_ANALYSIS {
    schedule([=]() MAIN_THREAD {
        const auto display = getDisplayDeviceLocked(displayToken);
        const auto display = getDisplayDeviceLocked(displayToken);
        if (!display) {
        if (!display) {
            ALOGE("Attempt to set power mode %d for invalid display token %p", mode,
            ALOGE("Attempt to set power mode %d for invalid display token %p", mode,
@@ -4241,8 +4259,7 @@ void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
    }).wait();
    }).wait();
}
}


status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args,
status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) {
                                bool asProto) NO_THREAD_SAFETY_ANALYSIS {
    std::string result;
    std::string result;


    IPCThreadState* ipc = IPCThreadState::self();
    IPCThreadState* ipc = IPCThreadState::self();
@@ -4254,18 +4271,6 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args,
        StringAppendF(&result, "Permission Denial: can't dump SurfaceFlinger from pid=%d, uid=%d\n",
        StringAppendF(&result, "Permission Denial: can't dump SurfaceFlinger from pid=%d, uid=%d\n",
                      pid, uid);
                      pid, uid);
    } else {
    } else {
        // Try to get the main lock, but give up after one second
        // (this would indicate SF is stuck, but we want to be able to
        // print something in dumpsys).
        status_t err = mStateLock.timedLock(s2ns(1));
        bool locked = (err == NO_ERROR);
        if (!locked) {
            StringAppendF(&result,
                          "SurfaceFlinger appears to be unresponsive (%s [%d]), dumping anyways "
                          "(no locks held)\n",
                          strerror(-err), err);
        }

        static const std::unordered_map<std::string, Dumper> dumpers = {
        static const std::unordered_map<std::string, Dumper> dumpers = {
                {"--display-id"s, dumper(&SurfaceFlinger::dumpDisplayIdentificationData)},
                {"--display-id"s, dumper(&SurfaceFlinger::dumpDisplayIdentificationData)},
                {"--dispsync"s,
                {"--dispsync"s,
@@ -4283,18 +4288,23 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args,


        const auto flag = args.empty() ? ""s : std::string(String8(args[0]));
        const auto flag = args.empty() ? ""s : std::string(String8(args[0]));


        const auto it = dumpers.find(flag);
        bool dumpLayers = true;
        if (it != dumpers.end()) {
        {
            TimedLock lock(mStateLock, s2ns(1), __FUNCTION__);
            if (!lock.locked()) {
                StringAppendF(&result, "Dumping without lock after timeout: %s (%d)\n",
                              strerror(-lock.status), lock.status);
            }

            if (const auto it = dumpers.find(flag); it != dumpers.end()) {
                (it->second)(args, asProto, result);
                (it->second)(args, asProto, result);
                dumpLayers = false;
            } else if (!asProto) {
            } else if (!asProto) {
                dumpAllLocked(args, result);
                dumpAllLocked(args, result);
            }
            }

        if (locked) {
            mStateLock.unlock();
        }
        }


        if (it == dumpers.end()) {
        if (dumpLayers) {
            const LayersProto layersProto = dumpProtoFromMainThread();
            const LayersProto layersProto = dumpProtoFromMainThread();
            if (asProto) {
            if (asProto) {
                result.append(layersProto.SerializeAsString());
                result.append(layersProto.SerializeAsString());
@@ -4568,7 +4578,7 @@ void SurfaceFlinger::dumpWideColorInfo(std::string& result) const {


LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const {
LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const {
    // If context is SurfaceTracing thread, mTracingLock blocks display transactions on main thread.
    // If context is SurfaceTracing thread, mTracingLock blocks display transactions on main thread.
    const auto display = getDefaultDisplayDeviceLocked();
    const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());


    LayersProto layersProto;
    LayersProto layersProto;
    for (const sp<Layer>& layer : mDrawingState.layersSortedByZ) {
    for (const sp<Layer>& layer : mDrawingState.layersSortedByZ) {
@@ -5404,7 +5414,7 @@ status_t SurfaceFlinger::setSchedFifo(bool enabled) {
    return NO_ERROR;
    return NO_ERROR;
}
}


const sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) {
sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) {
    const sp<IBinder> displayToken = getPhysicalDisplayTokenLocked(DisplayId{displayOrLayerStack});
    const sp<IBinder> displayToken = getPhysicalDisplayTokenLocked(DisplayId{displayOrLayerStack});
    if (displayToken) {
    if (displayToken) {
        return getDisplayDeviceLocked(displayToken);
        return getDisplayDeviceLocked(displayToken);
@@ -5414,7 +5424,7 @@ const sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t disp
    return getDisplayByLayerStack(displayOrLayerStack);
    return getDisplayByLayerStack(displayOrLayerStack);
}
}


const sp<DisplayDevice> SurfaceFlinger::getDisplayByLayerStack(uint64_t layerStack) {
sp<DisplayDevice> SurfaceFlinger::getDisplayByLayerStack(uint64_t layerStack) {
    for (const auto& [token, display] : mDisplays) {
    for (const auto& [token, display] : mDisplays) {
        if (display->getLayerStack() == layerStack) {
        if (display->getLayerStack() == layerStack) {
            return display;
            return display;
@@ -5989,7 +5999,7 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecs(const sp<IBinder>& display
    }
    }


    auto future = schedule([=]() -> status_t {
    auto future = schedule([=]() -> status_t {
        const auto display = getDisplayDeviceLocked(displayToken);
        const auto display = ON_MAIN_THREAD(getDisplayDeviceLocked(displayToken));
        if (!display) {
        if (!display) {
            ALOGE("Attempt to set desired display configs for invalid display token %p",
            ALOGE("Attempt to set desired display configs for invalid display token %p",
                  displayToken.get());
                  displayToken.get());
@@ -6144,7 +6154,7 @@ status_t SurfaceFlinger::setFrameRate(const sp<IGraphicBufferProducer>& surface,
        return BAD_VALUE;
        return BAD_VALUE;
    }
    }


    static_cast<void>(schedule([=]() NO_THREAD_SAFETY_ANALYSIS {
    static_cast<void>(schedule([=] {
        Mutex::Autolock lock(mStateLock);
        Mutex::Autolock lock(mStateLock);
        if (authenticateSurfaceTextureLocked(surface)) {
        if (authenticateSurfaceTextureLocked(surface)) {
            sp<Layer> layer = (static_cast<MonitoredProducer*>(surface.get()))->getLayer();
            sp<Layer> layer = (static_cast<MonitoredProducer*>(surface.get()))->getLayer();
@@ -6173,8 +6183,7 @@ status_t SurfaceFlinger::acquireFrameRateFlexibilityToken(sp<IBinder>* outToken)
        sp<IBinder> token;
        sp<IBinder> token;


        if (mFrameRateFlexibilityTokenCount == 0) {
        if (mFrameRateFlexibilityTokenCount == 0) {
            // |mStateLock| not needed as we are on the main thread
            const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
            const auto display = getDefaultDisplayDeviceLocked();


            // This is a little racy, but not in a way that hurts anything. As we grab the
            // This is a little racy, but not in a way that hurts anything. As we grab the
            // defaultConfig from the display manager policy, we could be setting a new display
            // defaultConfig from the display manager policy, we could be setting a new display
@@ -6224,8 +6233,7 @@ void SurfaceFlinger::onFrameRateFlexibilityTokenReleased() {
        mFrameRateFlexibilityTokenCount--;
        mFrameRateFlexibilityTokenCount--;
        ALOGD("Frame rate flexibility token released. count=%d", mFrameRateFlexibilityTokenCount);
        ALOGD("Frame rate flexibility token released. count=%d", mFrameRateFlexibilityTokenCount);
        if (mFrameRateFlexibilityTokenCount == 0) {
        if (mFrameRateFlexibilityTokenCount == 0) {
            // |mStateLock| not needed as we are on the main thread
            const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
            const auto display = getDefaultDisplayDeviceLocked();
            constexpr bool kOverridePolicy = true;
            constexpr bool kOverridePolicy = true;
            status_t result = setDesiredDisplayConfigSpecsInternal(display, {}, kOverridePolicy);
            status_t result = setDesiredDisplayConfigSpecsInternal(display, {}, kOverridePolicy);
            LOG_ALWAYS_FATAL_IF(result < 0, "Failed releasing frame rate flexibility token");
            LOG_ALWAYS_FATAL_IF(result < 0, "Failed releasing frame rate flexibility token");
+29 −31

File changed.

Preview size limit exceeded, changes collapsed.

+2 −2
Original line number Original line Diff line number Diff line
@@ -289,14 +289,14 @@ public:
        return mFlinger->destroyDisplay(displayToken);
        return mFlinger->destroyDisplay(displayToken);
    }
    }


    auto resetDisplayState() { return mFlinger->resetDisplayState(); }
    auto resetDisplayState() NO_THREAD_SAFETY_ANALYSIS { return mFlinger->resetDisplayState(); }


    auto setupNewDisplayDeviceInternal(
    auto setupNewDisplayDeviceInternal(
            const wp<IBinder>& displayToken,
            const wp<IBinder>& displayToken,
            std::shared_ptr<compositionengine::Display> compositionDisplay,
            std::shared_ptr<compositionengine::Display> compositionDisplay,
            const DisplayDeviceState& state,
            const DisplayDeviceState& state,
            const sp<compositionengine::DisplaySurface>& dispSurface,
            const sp<compositionengine::DisplaySurface>& dispSurface,
            const sp<IGraphicBufferProducer>& producer) {
            const sp<IGraphicBufferProducer>& producer) NO_THREAD_SAFETY_ANALYSIS {
        return mFlinger->setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state,
        return mFlinger->setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state,
                                                       dispSurface, producer);
                                                       dispSurface, producer);
    }
    }