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

Commit 8966d052 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes Ifff32118,I2ef0ad18,I2d5621b0,Icef36ab3

* changes:
  SF: Cleanup EventThread Part 2
  SF: Cleanup EventThread Part 1
  SF: Cleanup EventControlThread
  SF: Clang format selected sources
parents fc9199f9 e83f9315
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ cc_defaults {
        "-DLOG_TAG=\"SurfaceFlinger\"",
        "-Wall",
        "-Werror",
        "-Wthread-safety",
        "-Wunused",
        "-Wunreachable-code",
    ],
+52 −78
Original line number Diff line number Diff line
@@ -33,8 +33,8 @@
#include <ui/FenceTime.h>

#include "DispSync.h"
#include "SurfaceFlinger.h"
#include "EventLog/EventLog.h"
#include "SurfaceFlinger.h"

using std::max;
using std::min;
@@ -59,9 +59,8 @@ static const nsecs_t kErrorThreshold = 160000000000; // 400 usec squared
#define LOG_TAG "DispSyncThread"
class DispSyncThread : public Thread {
public:

    explicit DispSyncThread(const char* name):
            mName(name),
    explicit DispSyncThread(const char* name)
          : mName(name),
            mStop(false),
            mPeriod(0),
            mPhase(0),
@@ -78,8 +77,8 @@ public:
        mPhase = phase;
        mReferenceTime = referenceTime;
        ALOGV("[%s] updateModel: mPeriod = %" PRId64 ", mPhase = %" PRId64
                " mReferenceTime = %" PRId64, mName, ns2us(mPeriod),
                ns2us(mPhase), ns2us(mReferenceTime));
              " mReferenceTime = %" PRId64,
              mName, ns2us(mPeriod), ns2us(mPhase), ns2us(mReferenceTime));
        mCond.signal();
    }

@@ -115,8 +114,7 @@ public:
                if (mPeriod == 0) {
                    err = mCond.wait(mMutex);
                    if (err != NO_ERROR) {
                        ALOGE("error waiting for new events: %s (%d)",
                                strerror(-err), err);
                        ALOGE("error waiting for new events: %s (%d)", strerror(-err), err);
                        return false;
                    }
                    continue;
@@ -133,16 +131,14 @@ public:
                        ALOGV("[%s] Waiting forever", mName);
                        err = mCond.wait(mMutex);
                    } else {
                        ALOGV("[%s] Waiting until %" PRId64, mName,
                                ns2us(targetTime));
                        ALOGV("[%s] Waiting until %" PRId64, mName, ns2us(targetTime));
                        err = mCond.waitRelative(mMutex, targetTime - now);
                    }

                    if (err == TIMED_OUT) {
                        isWakeup = true;
                    } else if (err != NO_ERROR) {
                        ALOGE("error waiting for next event: %s (%d)",
                                strerror(-err), err);
                        ALOGE("error waiting for next event: %s (%d)", strerror(-err), err);
                        return false;
                    }
                }
@@ -153,8 +149,7 @@ public:
                static const nsecs_t kMaxWakeupLatency = us2ns(1500);

                if (isWakeup) {
                    mWakeupLatency = ((mWakeupLatency * 63) +
                            (now - targetTime)) / 64;
                    mWakeupLatency = ((mWakeupLatency * 63) + (now - targetTime)) / 64;
                    mWakeupLatency = min(mWakeupLatency, kMaxWakeupLatency);
                    if (kTraceDetailedInfo) {
                        ATRACE_INT64("DispSync:WakeupLat", now - targetTime);
@@ -173,8 +168,7 @@ public:
        return false;
    }

    status_t addEventListener(const char* name, nsecs_t phase,
            const sp<DispSync::Callback>& callback) {
    status_t addEventListener(const char* name, nsecs_t phase, DispSync::Callback* callback) {
        if (kTraceDetailedInfo) ATRACE_CALL();
        Mutex::Autolock lock(mMutex);

@@ -191,8 +185,7 @@ public:

        // We want to allow the firstmost future event to fire without
        // allowing any past events to fire
        listener.mLastEventTime = systemTime() - mPeriod / 2 + mPhase -
                mWakeupLatency;
        listener.mLastEventTime = systemTime() - mPeriod / 2 + mPhase - mWakeupLatency;

        mEventListeners.push(listener);

@@ -201,7 +194,7 @@ public:
        return NO_ERROR;
    }

    status_t removeEventListener(const sp<DispSync::Callback>& callback) {
    status_t removeEventListener(DispSync::Callback* callback) {
        if (kTraceDetailedInfo) ATRACE_CALL();
        Mutex::Autolock lock(mMutex);

@@ -225,16 +218,15 @@ public:
    }

private:

    struct EventListener {
        const char* mName;
        nsecs_t mPhase;
        nsecs_t mLastEventTime;
        sp<DispSync::Callback> mCallback;
        DispSync::Callback* mCallback;
    };

    struct CallbackInvocation {
        sp<DispSync::Callback> mCallback;
        DispSync::Callback* mCallback;
        nsecs_t mEventTime;
    };

@@ -243,8 +235,7 @@ private:
        ALOGV("[%s] computeNextEventTimeLocked", mName);
        nsecs_t nextEventTime = INT64_MAX;
        for (size_t i = 0; i < mEventListeners.size(); i++) {
            nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i],
                    now);
            nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i], now);

            if (t < nextEventTime) {
                nextEventTime = t;
@@ -257,22 +248,19 @@ private:

    Vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now) {
        if (kTraceDetailedInfo) ATRACE_CALL();
        ALOGV("[%s] gatherCallbackInvocationsLocked @ %" PRId64, mName,
                ns2us(now));
        ALOGV("[%s] gatherCallbackInvocationsLocked @ %" PRId64, mName, ns2us(now));

        Vector<CallbackInvocation> callbackInvocations;
        nsecs_t onePeriodAgo = now - mPeriod;

        for (size_t i = 0; i < mEventListeners.size(); i++) {
            nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i],
                    onePeriodAgo);
            nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i], onePeriodAgo);

            if (t < now) {
                CallbackInvocation ci;
                ci.mCallback = mEventListeners[i].mCallback;
                ci.mEventTime = t;
                ALOGV("[%s] [%s] Preparing to fire", mName,
                        mEventListeners[i].mName);
                ALOGV("[%s] [%s] Preparing to fire", mName, mEventListeners[i].mName);
                callbackInvocations.push(ci);
                mEventListeners.editItemAt(i).mLastEventTime = t;
            }
@@ -281,18 +269,16 @@ private:
        return callbackInvocations;
    }

    nsecs_t computeListenerNextEventTimeLocked(const EventListener& listener,
            nsecs_t baseTime) {
    nsecs_t computeListenerNextEventTimeLocked(const EventListener& listener, nsecs_t baseTime) {
        if (kTraceDetailedInfo) ATRACE_CALL();
        ALOGV("[%s] [%s] computeListenerNextEventTimeLocked(%" PRId64 ")",
                mName, listener.mName, ns2us(baseTime));
        ALOGV("[%s] [%s] computeListenerNextEventTimeLocked(%" PRId64 ")", mName, listener.mName,
              ns2us(baseTime));

        nsecs_t lastEventTime = listener.mLastEventTime + mWakeupLatency;
        ALOGV("[%s] lastEventTime: %" PRId64, mName, ns2us(lastEventTime));
        if (baseTime < lastEventTime) {
            baseTime = lastEventTime;
            ALOGV("[%s] Clamping baseTime to lastEventTime -> %" PRId64, mName,
                    ns2us(baseTime));
            ALOGV("[%s] Clamping baseTime to lastEventTime -> %" PRId64, mName, ns2us(baseTime));
        }

        baseTime -= mReferenceTime;
@@ -374,11 +360,8 @@ private:
    bool mParity;
};

DispSync::DispSync(const char* name) :
        mName(name),
        mRefreshSkipCount(0),
        mThread(new DispSyncThread(name)) {
}
DispSync::DispSync(const char* name)
      : mName(name), mRefreshSkipCount(0), mThread(new DispSyncThread(name)) {}

DispSync::~DispSync() {}

@@ -404,7 +387,8 @@ void DispSync::init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) {
        // not needed because any time there is an event registered we will
        // turn on the HW vsync events.
        if (!mIgnorePresentFences && kEnableZeroPhaseTracer) {
            addEventListener("ZeroPhaseTracer", 0, new ZeroPhaseTracer());
            mZeroPhaseTracer = std::make_unique<ZeroPhaseTracer>();
            addEventListener("ZeroPhaseTracer", 0, mZeroPhaseTracer.get());
        }
    }
}
@@ -451,8 +435,8 @@ bool DispSync::addResyncSample(nsecs_t timestamp) {
        mPhase = 0;
        mReferenceTime = timestamp;
        ALOGV("[%s] First resync sample: mPeriod = %" PRId64 ", mPhase = 0, "
                "mReferenceTime = %" PRId64, mName, ns2us(mPeriod),
                ns2us(mReferenceTime));
              "mReferenceTime = %" PRId64,
              mName, ns2us(mPeriod), ns2us(mReferenceTime));
        mThread->updateModel(mPeriod, mPhase, mReferenceTime);
    }

@@ -480,16 +464,13 @@ bool DispSync::addResyncSample(nsecs_t timestamp) {
    // Check against kErrorThreshold / 2 to add some hysteresis before having to
    // resync again
    bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2);
    ALOGV("[%s] addResyncSample returning %s", mName,
            modelLocked ? "locked" : "unlocked");
    ALOGV("[%s] addResyncSample returning %s", mName, modelLocked ? "locked" : "unlocked");
    return !modelLocked;
}

void DispSync::endResync() {
}
void DispSync::endResync() {}

status_t DispSync::addEventListener(const char* name, nsecs_t phase,
        const sp<Callback>& callback) {
status_t DispSync::addEventListener(const char* name, nsecs_t phase, Callback* callback) {
    Mutex::Autolock lock(mMutex);
    return mThread->addEventListener(name, phase, callback);
}
@@ -501,7 +482,7 @@ void DispSync::setRefreshSkipCount(int count) {
    updateModelLocked();
}

status_t DispSync::removeEventListener(const sp<Callback>& callback) {
status_t DispSync::removeEventListener(Callback* callback) {
    Mutex::Autolock lock(mMutex);
    return mThread->removeEventListener(callback);
}
@@ -597,8 +578,7 @@ void DispSync::updateErrorLocked() {
        // call getSignalTime() periodically so the cache is updated when the
        // fence signals.
        nsecs_t time = mPresentFences[i]->getCachedSignalTime();
        if (time == Fence::SIGNAL_TIME_PENDING ||
                time == Fence::SIGNAL_TIME_INVALID) {
        if (time == Fence::SIGNAL_TIME_PENDING || time == Fence::SIGNAL_TIME_INVALID) {
            continue;
        }

@@ -622,8 +602,7 @@ void DispSync::updateErrorLocked() {
        mError = 0;
        // Use mod ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT to avoid log spam.
        mZeroErrSamplesCount++;
        ALOGE_IF(
                (mZeroErrSamplesCount % ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT) == 0,
        ALOGE_IF((mZeroErrSamplesCount % ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT) == 0,
                 "No present times for model error.");
    }

@@ -650,17 +629,14 @@ nsecs_t DispSync::computeNextRefresh(int periodOffset) const {

void DispSync::dump(String8& result) const {
    Mutex::Autolock lock(mMutex);
    result.appendFormat("present fences are %s\n",
            mIgnorePresentFences ? "ignored" : "used");
    result.appendFormat("mPeriod: %" PRId64 " ns (%.3f fps; skipCount=%d)\n",
            mPeriod, 1000000000.0 / mPeriod, mRefreshSkipCount);
    result.appendFormat("present fences are %s\n", mIgnorePresentFences ? "ignored" : "used");
    result.appendFormat("mPeriod: %" PRId64 " ns (%.3f fps; skipCount=%d)\n", mPeriod,
                        1000000000.0 / mPeriod, mRefreshSkipCount);
    result.appendFormat("mPhase: %" PRId64 " ns\n", mPhase);
    result.appendFormat("mError: %" PRId64 " ns (sqrt=%.1f)\n",
            mError, sqrt(mError));
    result.appendFormat("mError: %" PRId64 " ns (sqrt=%.1f)\n", mError, sqrt(mError));
    result.appendFormat("mNumResyncSamplesSincePresent: %d (limit %d)\n",
                        mNumResyncSamplesSincePresent, MAX_RESYNC_SAMPLES_WITHOUT_PRESENT);
    result.appendFormat("mNumResyncSamples: %zd (max %d)\n",
            mNumResyncSamples, MAX_RESYNC_SAMPLES);
    result.appendFormat("mNumResyncSamples: %zd (max %d)\n", mNumResyncSamples, MAX_RESYNC_SAMPLES);

    result.appendFormat("mResyncSamples:\n");
    nsecs_t previous = -1;
@@ -670,14 +646,13 @@ void DispSync::dump(String8& result) const {
        if (i == 0) {
            result.appendFormat("  %" PRId64 "\n", sampleTime);
        } else {
            result.appendFormat("  %" PRId64 " (+%" PRId64 ")\n",
                    sampleTime, sampleTime - previous);
            result.appendFormat("  %" PRId64 " (+%" PRId64 ")\n", sampleTime,
                                sampleTime - previous);
        }
        previous = sampleTime;
    }

    result.appendFormat("mPresentFences [%d]:\n",
            NUM_PRESENT_SAMPLES);
    result.appendFormat("mPresentFences [%d]:\n", NUM_PRESENT_SAMPLES);
    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
    previous = Fence::SIGNAL_TIME_INVALID;
    for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
@@ -692,9 +667,8 @@ void DispSync::dump(String8& result) const {
            result.appendFormat("  %" PRId64 "  (%.3f ms ago)\n", presentTime,
                                (now - presentTime) / 1000000.0);
        } else {
            result.appendFormat("  %" PRId64 " (+%" PRId64 " / %.3f)  (%.3f ms ago)\n",
                    presentTime, presentTime - previous,
                    (presentTime - previous) / (double) mPeriod,
            result.appendFormat("  %" PRId64 " (+%" PRId64 " / %.3f)  (%.3f ms ago)\n", presentTime,
                                presentTime - previous, (presentTime - previous) / (double)mPeriod,
                                (now - presentTime) / 1000000.0);
        }
        previous = presentTime;
+9 −12
Original line number Diff line number Diff line
@@ -20,8 +20,8 @@
#include <stddef.h>

#include <utils/Mutex.h>
#include <utils/Timers.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>

#include <ui/FenceTime.h>

@@ -47,10 +47,8 @@ class DispSyncThread;
// false to indicate that a resynchronization (via addResyncSample) is not
// needed.
class DispSync {

public:

    class Callback: public virtual RefBase {
    class Callback {
    public:
        virtual ~Callback(){};
        virtual void onDispSyncEvent(nsecs_t when) = 0;
@@ -108,13 +106,12 @@ public:
    // given phase offset from the hardware vsync events.  The callback is
    // called from a separate thread and it should return reasonably quickly
    // (i.e. within a few hundred microseconds).
    status_t addEventListener(const char* name, nsecs_t phase,
            const sp<Callback>& callback);
    status_t addEventListener(const char* name, nsecs_t phase, Callback* callback);

    // removeEventListener removes an already-registered event callback.  Once
    // this method returns that callback will no longer be called by the
    // DispSync object.
    status_t removeEventListener(const sp<Callback>& callback);
    status_t removeEventListener(Callback* callback);

    // computeNextRefresh computes when the next refresh is expected to begin.
    // The periodOffset value can be used to move forward or backward; an
@@ -126,7 +123,6 @@ public:
    void dump(String8& result) const;

private:

    void updateModelLocked();
    void updateErrorLocked();
    void resetErrorLocked();
@@ -174,8 +170,7 @@ private:

    // These member variables store information about the present fences used
    // to validate the currently computed model.
    std::shared_ptr<FenceTime>
            mPresentFences[NUM_PRESENT_SAMPLES] {FenceTime::NO_FENCE};
    std::shared_ptr<FenceTime> mPresentFences[NUM_PRESENT_SAMPLES]{FenceTime::NO_FENCE};
    size_t mPresentSampleOffset;

    int mRefreshSkipCount;
@@ -193,8 +188,10 @@ private:
    // Ignore present (retire) fences if the device doesn't have support for the
    // sync framework
    bool mIgnorePresentFences;

    std::unique_ptr<Callback> mZeroPhaseTracer;
};

}
} // namespace android

#endif // ANDROID_DISPSYNC_H
+40 −33
Original line number Diff line number Diff line
@@ -14,50 +14,57 @@
 * limitations under the License.
 */

#include <pthread.h>
#include <sched.h>
#include <sys/resource.h>

#include <cutils/sched_policy.h>
#include <log/log.h>
#include <system/thread_defs.h>

#include "EventControlThread.h"
#include "SurfaceFlinger.h"

namespace android {

EventControlThread::EventControlThread(const sp<SurfaceFlinger>& flinger):
        mFlinger(flinger),
        mVsyncEnabled(false) {
}
EventControlThread::EventControlThread(EventControlThread::SetVSyncEnabledFunction function)
      : mSetVSyncEnabled(function) {
    pthread_setname_np(mThread.native_handle(), "EventControlThread");

void EventControlThread::setVsyncEnabled(bool enabled) {
    Mutex::Autolock lock(mMutex);
    mVsyncEnabled = enabled;
    mCond.signal();
    pid_t tid = pthread_gettid_np(mThread.native_handle());
    setpriority(PRIO_PROCESS, tid, ANDROID_PRIORITY_URGENT_DISPLAY);
    set_sched_policy(tid, SP_FOREGROUND);
}

bool EventControlThread::threadLoop() {
    enum class VsyncState {Unset, On, Off};
    auto currentVsyncState = VsyncState::Unset;

    while (true) {
        auto requestedVsyncState = VsyncState::On;
EventControlThread::~EventControlThread() {
    {
            Mutex::Autolock lock(mMutex);
            requestedVsyncState =
                    mVsyncEnabled ? VsyncState::On : VsyncState::Off;
            while (currentVsyncState == requestedVsyncState) {
                status_t err = mCond.wait(mMutex);
                if (err != NO_ERROR) {
                    ALOGE("error waiting for new events: %s (%d)",
                          strerror(-err), err);
                    return false;
                }
                requestedVsyncState =
                        mVsyncEnabled ? VsyncState::On : VsyncState::Off;
        std::lock_guard<std::mutex> lock(mMutex);
        mKeepRunning = false;
        mCondition.notify_all();
    }
    mThread.join();
}

        bool enable = requestedVsyncState == VsyncState::On;
        mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, enable);
        currentVsyncState = requestedVsyncState;
void EventControlThread::setVsyncEnabled(bool enabled) {
    std::lock_guard<std::mutex> lock(mMutex);
    mVsyncEnabled = enabled;
    mCondition.notify_all();
}

    return false;
// Unfortunately std::unique_lock gives warnings with -Wthread-safety
void EventControlThread::threadMain() NO_THREAD_SAFETY_ANALYSIS {
    auto keepRunning = true;
    auto currentVsyncEnabled = false;

    while (keepRunning) {
        mSetVSyncEnabled(currentVsyncEnabled);

        std::unique_lock<std::mutex> lock(mMutex);
        mCondition.wait(lock, [this, currentVsyncEnabled, keepRunning]() NO_THREAD_SAFETY_ANALYSIS {
            return currentVsyncEnabled != mVsyncEnabled || keepRunning != mKeepRunning;
        });
        currentVsyncEnabled = mVsyncEnabled;
        keepRunning = mKeepRunning;
    }
}

} // namespace android
+22 −16
Original line number Diff line number Diff line
@@ -14,35 +14,41 @@
 * limitations under the License.
 */

#ifndef ANDROID_EVENTCONTROLTHREAD_H
#define ANDROID_EVENTCONTROLTHREAD_H
#pragma once

#include <stddef.h>
#include <cstddef>
#include <condition_variable>
#include <functional>
#include <mutex>
#include <thread>

#include <utils/Mutex.h>
#include <utils/Thread.h>
#include <android-base/thread_annotations.h>

namespace android {

class SurfaceFlinger;

class EventControlThread: public Thread {
class EventControlThread {
public:
    using SetVSyncEnabledFunction = std::function<void(bool)>;

    explicit EventControlThread(const sp<SurfaceFlinger>& flinger);
    virtual ~EventControlThread() {}
    explicit EventControlThread(SetVSyncEnabledFunction function);
    ~EventControlThread();

    void setVsyncEnabled(bool enabled);
    virtual bool threadLoop();

private:
    sp<SurfaceFlinger> mFlinger;
    bool mVsyncEnabled;
    void threadMain();

    Mutex mMutex;
    Condition mCond;
};
    std::mutex mMutex;
    std::condition_variable mCondition;

    const SetVSyncEnabledFunction mSetVSyncEnabled;
    bool mVsyncEnabled GUARDED_BY(mMutex) = false;
    bool mKeepRunning GUARDED_BY(mMutex) = true;

}
    // Must be last so that everything is initialized before the thread starts.
    std::thread mThread{&EventControlThread::threadMain, this};
};

#endif // ANDROID_EVENTCONTROLTHREAD_H
} // namespace android
Loading