diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
new file mode 100644
index 0000000..9d9acd3
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -0,0 +1,729 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+//#define LOG_NDEBUG 0
+
+// This is needed for stdint.h to define INT64_MAX in C++
+#define __STDC_LIMIT_MACROS
+
+#include <math.h>
+
+#include <algorithm>
+
+#include <log/log.h>
+#include <utils/String8.h>
+#include <utils/Thread.h>
+#include <utils/Trace.h>
+
+#include <ui/FenceTime.h>
+
+#include "DispSync.h"
+#include "EventLog/EventLog.h"
+#include "SurfaceFlinger.h"
+
+using std::max;
+using std::min;
+
+namespace android {
+
+DispSync::~DispSync() = default;
+
+namespace impl {
+
+// Setting this to true enables verbose tracing that can be used to debug
+// vsync event model or phase issues.
+static const bool kTraceDetailedInfo = false;
+
+// Setting this to true adds a zero-phase tracer for correlating with hardware
+// vsync events
+static const bool kEnableZeroPhaseTracer = false;
+
+// This is the threshold used to determine when hardware vsync events are
+// needed to re-synchronize the software vsync model with the hardware.  The
+// error metric used is the mean of the squared difference between each
+// present time and the nearest software-predicted vsync.
+static const nsecs_t kErrorThreshold = 160000000000; // 400 usec squared
+
+#undef LOG_TAG
+#define LOG_TAG "DispSyncThread"
+class DispSyncThread : public Thread {
+public:
+    explicit DispSyncThread(const char* name)
+          : mName(name),
+            mStop(false),
+            mPeriod(0),
+            mPhase(0),
+            mReferenceTime(0),
+            mWakeupLatency(0),
+            mFrameNumber(0) {}
+
+    virtual ~DispSyncThread() {}
+
+    void updateModel(nsecs_t period, nsecs_t phase, nsecs_t referenceTime) {
+        if (kTraceDetailedInfo) ATRACE_CALL();
+        Mutex::Autolock lock(mMutex);
+        mPeriod = period;
+        mPhase = phase;
+        mReferenceTime = referenceTime;
+        ALOGV("[%s] updateModel: mPeriod = %" PRId64 ", mPhase = %" PRId64
+              " mReferenceTime = %" PRId64,
+              mName, ns2us(mPeriod), ns2us(mPhase), ns2us(mReferenceTime));
+        mCond.signal();
+    }
+
+    void stop() {
+        if (kTraceDetailedInfo) ATRACE_CALL();
+        Mutex::Autolock lock(mMutex);
+        mStop = true;
+        mCond.signal();
+    }
+
+    virtual bool threadLoop() {
+        status_t err;
+        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+
+        while (true) {
+            std::vector<CallbackInvocation> callbackInvocations;
+
+            nsecs_t targetTime = 0;
+
+            { // Scope for lock
+                Mutex::Autolock lock(mMutex);
+
+                if (kTraceDetailedInfo) {
+                    ATRACE_INT64("DispSync:Frame", mFrameNumber);
+                }
+                ALOGV("[%s] Frame %" PRId64, mName, mFrameNumber);
+                ++mFrameNumber;
+
+                if (mStop) {
+                    return false;
+                }
+
+                if (mPeriod == 0) {
+                    err = mCond.wait(mMutex);
+                    if (err != NO_ERROR) {
+                        ALOGE("error waiting for new events: %s (%d)", strerror(-err), err);
+                        return false;
+                    }
+                    continue;
+                }
+
+                targetTime = computeNextEventTimeLocked(now);
+
+                bool isWakeup = false;
+
+                if (now < targetTime) {
+                    if (kTraceDetailedInfo) ATRACE_NAME("DispSync waiting");
+
+                    if (targetTime == INT64_MAX) {
+                        ALOGV("[%s] Waiting forever", mName);
+                        err = mCond.wait(mMutex);
+                    } else {
+                        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);
+                        return false;
+                    }
+                }
+
+                now = systemTime(SYSTEM_TIME_MONOTONIC);
+
+                // Don't correct by more than 1.5 ms
+                static const nsecs_t kMaxWakeupLatency = us2ns(1500);
+
+                if (isWakeup) {
+                    mWakeupLatency = ((mWakeupLatency * 63) + (now - targetTime)) / 64;
+                    mWakeupLatency = min(mWakeupLatency, kMaxWakeupLatency);
+                    if (kTraceDetailedInfo) {
+                        ATRACE_INT64("DispSync:WakeupLat", now - targetTime);
+                        ATRACE_INT64("DispSync:AvgWakeupLat", mWakeupLatency);
+                    }
+                }
+
+                callbackInvocations = gatherCallbackInvocationsLocked(now);
+            }
+
+            if (callbackInvocations.size() > 0) {
+                fireCallbackInvocations(callbackInvocations);
+            }
+        }
+
+        return false;
+    }
+
+    status_t addEventListener(const char* name, nsecs_t phase, DispSync::Callback* callback) {
+        if (kTraceDetailedInfo) ATRACE_CALL();
+        Mutex::Autolock lock(mMutex);
+
+        for (size_t i = 0; i < mEventListeners.size(); i++) {
+            if (mEventListeners[i].mCallback == callback) {
+                return BAD_VALUE;
+            }
+        }
+
+        EventListener listener;
+        listener.mName = name;
+        listener.mPhase = phase;
+        listener.mCallback = callback;
+
+        // We want to allow the firstmost future event to fire without
+        // allowing any past events to fire
+        listener.mLastEventTime = systemTime() - mPeriod / 2 + mPhase - mWakeupLatency;
+
+        mEventListeners.push_back(listener);
+
+        mCond.signal();
+
+        return NO_ERROR;
+    }
+
+    status_t removeEventListener(DispSync::Callback* callback) {
+        if (kTraceDetailedInfo) ATRACE_CALL();
+        Mutex::Autolock lock(mMutex);
+
+        for (std::vector<EventListener>::iterator it = mEventListeners.begin();
+             it != mEventListeners.end(); ++it) {
+            if (it->mCallback == callback) {
+                mEventListeners.erase(it);
+                mCond.signal();
+                return NO_ERROR;
+            }
+        }
+
+        return BAD_VALUE;
+    }
+
+    status_t changePhaseOffset(DispSync::Callback* callback, nsecs_t phase) {
+        if (kTraceDetailedInfo) ATRACE_CALL();
+        Mutex::Autolock lock(mMutex);
+
+        for (auto& eventListener : mEventListeners) {
+            if (eventListener.mCallback == callback) {
+                const nsecs_t oldPhase = eventListener.mPhase;
+                eventListener.mPhase = phase;
+
+                // Pretend that the last time this event was handled at the same frame but with the
+                // new offset to allow for a seamless offset change without double-firing or
+                // skipping.
+                nsecs_t diff = oldPhase - phase;
+                if (diff > mPeriod / 2) {
+                    diff -= mPeriod;
+                } else if (diff < -mPeriod / 2) {
+                    diff += mPeriod;
+                }
+                eventListener.mLastEventTime -= diff;
+                mCond.signal();
+                return NO_ERROR;
+            }
+        }
+
+        return BAD_VALUE;
+    }
+
+private:
+    struct EventListener {
+        const char* mName;
+        nsecs_t mPhase;
+        nsecs_t mLastEventTime;
+        DispSync::Callback* mCallback;
+    };
+
+    struct CallbackInvocation {
+        DispSync::Callback* mCallback;
+        nsecs_t mEventTime;
+    };
+
+    nsecs_t computeNextEventTimeLocked(nsecs_t now) {
+        if (kTraceDetailedInfo) ATRACE_CALL();
+        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);
+
+            if (t < nextEventTime) {
+                nextEventTime = t;
+            }
+        }
+
+        ALOGV("[%s] nextEventTime = %" PRId64, mName, ns2us(nextEventTime));
+        return nextEventTime;
+    }
+
+    std::vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now) {
+        if (kTraceDetailedInfo) ATRACE_CALL();
+        ALOGV("[%s] gatherCallbackInvocationsLocked @ %" PRId64, mName, ns2us(now));
+
+        std::vector<CallbackInvocation> callbackInvocations;
+        nsecs_t onePeriodAgo = now - mPeriod;
+
+        for (auto& eventListener : mEventListeners) {
+            nsecs_t t = computeListenerNextEventTimeLocked(eventListener, onePeriodAgo);
+
+            if (t < now) {
+                CallbackInvocation ci;
+                ci.mCallback = eventListener.mCallback;
+                ci.mEventTime = t;
+                ALOGV("[%s] [%s] Preparing to fire", mName, eventListener.mName);
+                callbackInvocations.push_back(ci);
+                eventListener.mLastEventTime = t;
+            }
+        }
+
+        return callbackInvocations;
+    }
+
+    nsecs_t computeListenerNextEventTimeLocked(const EventListener& listener, nsecs_t baseTime) {
+        if (kTraceDetailedInfo) ATRACE_CALL();
+        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));
+        }
+
+        baseTime -= mReferenceTime;
+        ALOGV("[%s] Relative baseTime = %" PRId64, mName, ns2us(baseTime));
+        nsecs_t phase = mPhase + listener.mPhase;
+        ALOGV("[%s] Phase = %" PRId64, mName, ns2us(phase));
+        baseTime -= phase;
+        ALOGV("[%s] baseTime - phase = %" PRId64, mName, ns2us(baseTime));
+
+        // If our previous time is before the reference (because the reference
+        // has since been updated), the division by mPeriod will truncate
+        // towards zero instead of computing the floor. Since in all cases
+        // before the reference we want the next time to be effectively now, we
+        // set baseTime to -mPeriod so that numPeriods will be -1.
+        // When we add 1 and the phase, we will be at the correct event time for
+        // this period.
+        if (baseTime < 0) {
+            ALOGV("[%s] Correcting negative baseTime", mName);
+            baseTime = -mPeriod;
+        }
+
+        nsecs_t numPeriods = baseTime / mPeriod;
+        ALOGV("[%s] numPeriods = %" PRId64, mName, numPeriods);
+        nsecs_t t = (numPeriods + 1) * mPeriod + phase;
+        ALOGV("[%s] t = %" PRId64, mName, ns2us(t));
+        t += mReferenceTime;
+        ALOGV("[%s] Absolute t = %" PRId64, mName, ns2us(t));
+
+        // Check that it's been slightly more than half a period since the last
+        // event so that we don't accidentally fall into double-rate vsyncs
+        if (t - listener.mLastEventTime < (3 * mPeriod / 5)) {
+            t += mPeriod;
+            ALOGV("[%s] Modifying t -> %" PRId64, mName, ns2us(t));
+        }
+
+        t -= mWakeupLatency;
+        ALOGV("[%s] Corrected for wakeup latency -> %" PRId64, mName, ns2us(t));
+
+        return t;
+    }
+
+    void fireCallbackInvocations(const std::vector<CallbackInvocation>& callbacks) {
+        if (kTraceDetailedInfo) ATRACE_CALL();
+        for (size_t i = 0; i < callbacks.size(); i++) {
+            callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
+        }
+    }
+
+    const char* const mName;
+
+    bool mStop;
+
+    nsecs_t mPeriod;
+    nsecs_t mPhase;
+    nsecs_t mReferenceTime;
+    nsecs_t mWakeupLatency;
+
+    int64_t mFrameNumber;
+
+    std::vector<EventListener> mEventListeners;
+
+    Mutex mMutex;
+    Condition mCond;
+};
+
+#undef LOG_TAG
+#define LOG_TAG "DispSync"
+
+class ZeroPhaseTracer : public DispSync::Callback {
+public:
+    ZeroPhaseTracer() : mParity(false) {}
+
+    virtual void onDispSyncEvent(nsecs_t /*when*/) {
+        mParity = !mParity;
+        ATRACE_INT("ZERO_PHASE_VSYNC", mParity ? 1 : 0);
+    }
+
+private:
+    bool mParity;
+};
+
+DispSync::DispSync(const char* name)
+      : mName(name), mRefreshSkipCount(0), mThread(new DispSyncThread(name)) {}
+
+DispSync::~DispSync() {}
+
+void DispSync::init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset) {
+    mIgnorePresentFences = !hasSyncFramework;
+    mPresentTimeOffset = dispSyncPresentTimeOffset;
+    mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
+
+    // set DispSync to SCHED_FIFO to minimize jitter
+    struct sched_param param = {0};
+    param.sched_priority = 2;
+    if (sched_setscheduler(mThread->getTid(), SCHED_FIFO, &param) != 0) {
+        ALOGE("Couldn't set SCHED_FIFO for DispSyncThread");
+    }
+
+    reset();
+    beginResync();
+
+    if (kTraceDetailedInfo && kEnableZeroPhaseTracer) {
+        mZeroPhaseTracer = std::make_unique<ZeroPhaseTracer>();
+        addEventListener("ZeroPhaseTracer", 0, mZeroPhaseTracer.get());
+    }
+}
+
+void DispSync::reset() {
+    Mutex::Autolock lock(mMutex);
+    resetLocked();
+}
+
+void DispSync::resetLocked() {
+    mPhase = 0;
+    mReferenceTime = 0;
+    mModelUpdated = false;
+    mNumResyncSamples = 0;
+    mFirstResyncSample = 0;
+    mNumResyncSamplesSincePresent = 0;
+    resetErrorLocked();
+}
+
+bool DispSync::addPresentFence(const std::shared_ptr<FenceTime>& fenceTime) {
+    Mutex::Autolock lock(mMutex);
+
+    if (mIgnorePresentFences) {
+        return true;
+    }
+
+    mPresentFences[mPresentSampleOffset] = fenceTime;
+    mPresentSampleOffset = (mPresentSampleOffset + 1) % NUM_PRESENT_SAMPLES;
+    mNumResyncSamplesSincePresent = 0;
+
+    updateErrorLocked();
+
+    return !mModelUpdated || mError > kErrorThreshold;
+}
+
+void DispSync::beginResync() {
+    Mutex::Autolock lock(mMutex);
+    ALOGV("[%s] beginResync", mName);
+    mModelUpdated = false;
+    mNumResyncSamples = 0;
+}
+
+bool DispSync::addResyncSample(nsecs_t timestamp) {
+    Mutex::Autolock lock(mMutex);
+
+    ALOGV("[%s] addResyncSample(%" PRId64 ")", mName, ns2us(timestamp));
+
+    size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
+    mResyncSamples[idx] = timestamp;
+    if (mNumResyncSamples == 0) {
+        mPhase = 0;
+        mReferenceTime = timestamp;
+        ALOGV("[%s] First resync sample: mPeriod = %" PRId64 ", mPhase = 0, "
+              "mReferenceTime = %" PRId64,
+              mName, ns2us(mPeriod), ns2us(mReferenceTime));
+        mThread->updateModel(mPeriod, mPhase, mReferenceTime);
+    }
+
+    if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {
+        mNumResyncSamples++;
+    } else {
+        mFirstResyncSample = (mFirstResyncSample + 1) % MAX_RESYNC_SAMPLES;
+    }
+
+    updateModelLocked();
+
+    if (mNumResyncSamplesSincePresent++ > MAX_RESYNC_SAMPLES_WITHOUT_PRESENT) {
+        resetErrorLocked();
+    }
+
+    if (mIgnorePresentFences) {
+        // If we're ignoring the present fences we have no way to know whether
+        // or not we're synchronized with the HW vsyncs, so we just request
+        // that the HW vsync events be turned on.
+        return true;
+    }
+
+    // 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");
+    return !modelLocked;
+}
+
+void DispSync::endResync() {}
+
+status_t DispSync::addEventListener(const char* name, nsecs_t phase, Callback* callback) {
+    Mutex::Autolock lock(mMutex);
+    return mThread->addEventListener(name, phase, callback);
+}
+
+void DispSync::setRefreshSkipCount(int count) {
+    Mutex::Autolock lock(mMutex);
+    ALOGD("setRefreshSkipCount(%d)", count);
+    mRefreshSkipCount = count;
+    updateModelLocked();
+}
+
+status_t DispSync::removeEventListener(Callback* callback) {
+    Mutex::Autolock lock(mMutex);
+    return mThread->removeEventListener(callback);
+}
+
+status_t DispSync::changePhaseOffset(Callback* callback, nsecs_t phase) {
+    Mutex::Autolock lock(mMutex);
+    return mThread->changePhaseOffset(callback, phase);
+}
+
+void DispSync::setPeriod(nsecs_t period) {
+    Mutex::Autolock lock(mMutex);
+    mPeriodBase = mPeriod = period;
+    mPhase = 0;
+    mReferenceTime = 0;
+    mThread->updateModel(mPeriod, mPhase, mReferenceTime);
+}
+
+void DispSync::scalePeriod(uint32_t multiplier, uint32_t divisor) {
+    Mutex::Autolock lock(mMutex);
+
+    // if only 1 of the properties is updated, we will get to this
+    // point "attempting" to set the scale to 1 when it is already
+    // 1.  Check that special case so that we don't do a useless
+    // update of the model.
+    if ((multiplier == 1) && (divisor == 1) && (mPeriod == mPeriodBase)) return;
+
+    mPeriod = mPeriodBase * multiplier / divisor;
+    mThread->updateModel(mPeriod, mPhase, mReferenceTime);
+}
+
+nsecs_t DispSync::getPeriod() {
+    // lock mutex as mPeriod changes multiple times in updateModelLocked
+    Mutex::Autolock lock(mMutex);
+    return mPeriod;
+}
+
+void DispSync::updateModelLocked() {
+    ALOGV("[%s] updateModelLocked %zu", mName, mNumResyncSamples);
+    if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) {
+        ALOGV("[%s] Computing...", mName);
+        nsecs_t durationSum = 0;
+        nsecs_t minDuration = INT64_MAX;
+        nsecs_t maxDuration = 0;
+        for (size_t i = 1; i < mNumResyncSamples; i++) {
+            size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
+            size_t prev = (idx + MAX_RESYNC_SAMPLES - 1) % MAX_RESYNC_SAMPLES;
+            nsecs_t duration = mResyncSamples[idx] - mResyncSamples[prev];
+            durationSum += duration;
+            minDuration = min(minDuration, duration);
+            maxDuration = max(maxDuration, duration);
+        }
+
+        // Exclude the min and max from the average
+        durationSum -= minDuration + maxDuration;
+        mPeriodBase = mPeriod = durationSum / (mNumResyncSamples - 3);
+
+        ALOGV("[%s] mPeriod = %" PRId64, mName, ns2us(mPeriod));
+
+        double sampleAvgX = 0;
+        double sampleAvgY = 0;
+        double scale = 2.0 * M_PI / double(mPeriod);
+        // Intentionally skip the first sample
+        for (size_t i = 1; i < mNumResyncSamples; i++) {
+            size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
+            nsecs_t sample = mResyncSamples[idx] - mReferenceTime;
+            double samplePhase = double(sample % mPeriod) * scale;
+            sampleAvgX += cos(samplePhase);
+            sampleAvgY += sin(samplePhase);
+        }
+
+        sampleAvgX /= double(mNumResyncSamples - 1);
+        sampleAvgY /= double(mNumResyncSamples - 1);
+
+        mPhase = nsecs_t(atan2(sampleAvgY, sampleAvgX) / scale);
+
+        ALOGV("[%s] mPhase = %" PRId64, mName, ns2us(mPhase));
+
+        if (mPhase < -(mPeriod / 2)) {
+            mPhase += mPeriod;
+            ALOGV("[%s] Adjusting mPhase -> %" PRId64, mName, ns2us(mPhase));
+        }
+
+        if (kTraceDetailedInfo) {
+            ATRACE_INT64("DispSync:Period", mPeriod);
+            ATRACE_INT64("DispSync:Phase", mPhase + mPeriod / 2);
+        }
+
+        // Artificially inflate the period if requested.
+        mPeriod += mPeriod * mRefreshSkipCount;
+
+        mThread->updateModel(mPeriod, mPhase, mReferenceTime);
+        mModelUpdated = true;
+    }
+}
+
+void DispSync::updateErrorLocked() {
+    if (!mModelUpdated) {
+        return;
+    }
+
+    // Need to compare present fences against the un-adjusted refresh period,
+    // since they might arrive between two events.
+    nsecs_t period = mPeriod / (1 + mRefreshSkipCount);
+
+    int numErrSamples = 0;
+    nsecs_t sqErrSum = 0;
+
+    for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
+        // Only check for the cached value of signal time to avoid unecessary
+        // syscalls. It is the responsibility of the DispSync owner to
+        // 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) {
+            continue;
+        }
+
+        nsecs_t sample = time - mReferenceTime;
+        if (sample <= mPhase) {
+            continue;
+        }
+
+        nsecs_t sampleErr = (sample - mPhase) % period;
+        if (sampleErr > period / 2) {
+            sampleErr -= period;
+        }
+        sqErrSum += sampleErr * sampleErr;
+        numErrSamples++;
+    }
+
+    if (numErrSamples > 0) {
+        mError = sqErrSum / numErrSamples;
+        mZeroErrSamplesCount = 0;
+    } else {
+        mError = 0;
+        // Use mod ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT to avoid log spam.
+        mZeroErrSamplesCount++;
+        ALOGE_IF((mZeroErrSamplesCount % ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT) == 0,
+                 "No present times for model error.");
+    }
+
+    if (kTraceDetailedInfo) {
+        ATRACE_INT64("DispSync:Error", mError);
+    }
+}
+
+void DispSync::resetErrorLocked() {
+    mPresentSampleOffset = 0;
+    mError = 0;
+    mZeroErrSamplesCount = 0;
+    for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
+        mPresentFences[i] = FenceTime::NO_FENCE;
+    }
+}
+
+nsecs_t DispSync::computeNextRefresh(int periodOffset) const {
+    Mutex::Autolock lock(mMutex);
+    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+    nsecs_t phase = mReferenceTime + mPhase;
+    return (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase;
+}
+
+void DispSync::setIgnorePresentFences(bool ignore) {
+    Mutex::Autolock lock(mMutex);
+    if (mIgnorePresentFences != ignore) {
+        mIgnorePresentFences = ignore;
+        resetLocked();
+    }
+}
+
+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("mPhase: %" PRId64 " ns\n", mPhase);
+    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("mResyncSamples:\n");
+    nsecs_t previous = -1;
+    for (size_t i = 0; i < mNumResyncSamples; i++) {
+        size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
+        nsecs_t sampleTime = mResyncSamples[idx];
+        if (i == 0) {
+            result.appendFormat("  %" PRId64 "\n", sampleTime);
+        } else {
+            result.appendFormat("  %" PRId64 " (+%" PRId64 ")\n", sampleTime,
+                                sampleTime - previous);
+        }
+        previous = sampleTime;
+    }
+
+    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++) {
+        size_t idx = (i + mPresentSampleOffset) % NUM_PRESENT_SAMPLES;
+        nsecs_t presentTime = mPresentFences[idx]->getSignalTime();
+        if (presentTime == Fence::SIGNAL_TIME_PENDING) {
+            result.appendFormat("  [unsignaled fence]\n");
+        } else if (presentTime == Fence::SIGNAL_TIME_INVALID) {
+            result.appendFormat("  [invalid fence]\n");
+        } else if (previous == Fence::SIGNAL_TIME_PENDING ||
+                   previous == Fence::SIGNAL_TIME_INVALID) {
+            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,
+                                (now - presentTime) / 1000000.0);
+        }
+        previous = presentTime;
+    }
+
+    result.appendFormat("current monotonic time: %" PRId64 "\n", now);
+}
+
+} // namespace impl
+
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/DispSync.h b/services/surfaceflinger/Scheduler/DispSync.h
new file mode 100644
index 0000000..183966f
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/DispSync.h
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#ifndef ANDROID_DISPSYNC_H
+#define ANDROID_DISPSYNC_H
+
+#include <stddef.h>
+
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+#include <utils/Timers.h>
+
+#include <ui/FenceTime.h>
+
+#include <memory>
+
+namespace android {
+
+class String8;
+class FenceTime;
+
+class DispSync {
+public:
+    class Callback {
+    public:
+        virtual ~Callback() = default;
+        virtual void onDispSyncEvent(nsecs_t when) = 0;
+    };
+
+    virtual ~DispSync();
+
+    virtual void reset() = 0;
+    virtual bool addPresentFence(const std::shared_ptr<FenceTime>&) = 0;
+    virtual void beginResync() = 0;
+    virtual bool addResyncSample(nsecs_t timestamp) = 0;
+    virtual void endResync() = 0;
+    virtual void setPeriod(nsecs_t period) = 0;
+    virtual void scalePeriod(const uint32_t multiplier, uint32_t divisor) = 0;
+    virtual nsecs_t getPeriod() = 0;
+    virtual void setRefreshSkipCount(int count) = 0;
+    virtual status_t addEventListener(const char* name, nsecs_t phase, Callback* callback) = 0;
+    virtual status_t removeEventListener(Callback* callback) = 0;
+    virtual status_t changePhaseOffset(Callback* callback, nsecs_t phase) = 0;
+    virtual nsecs_t computeNextRefresh(int periodOffset) const = 0;
+    virtual void setIgnorePresentFences(bool ignore) = 0;
+
+    virtual void dump(String8& result) const = 0;
+};
+
+namespace impl {
+
+class DispSyncThread;
+
+// DispSync maintains a model of the periodic hardware-based vsync events of a
+// display and uses that model to execute period callbacks at specific phase
+// offsets from the hardware vsync events.  The model is constructed by
+// feeding consecutive hardware event timestamps to the DispSync object via
+// the addResyncSample method.
+//
+// The model is validated using timestamps from Fence objects that are passed
+// to the DispSync object via the addPresentFence method.  These fence
+// timestamps should correspond to a hardware vsync event, but they need not
+// be consecutive hardware vsync times.  If this method determines that the
+// current model accurately represents the hardware event times it will return
+// false to indicate that a resynchronization (via addResyncSample) is not
+// needed.
+class DispSync : public android::DispSync {
+public:
+    explicit DispSync(const char* name);
+    ~DispSync() override;
+
+    void init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset);
+
+    // reset clears the resync samples and error value.
+    void reset() override;
+
+    // addPresentFence adds a fence for use in validating the current vsync
+    // event model.  The fence need not be signaled at the time
+    // addPresentFence is called.  When the fence does signal, its timestamp
+    // should correspond to a hardware vsync event.  Unlike the
+    // addResyncSample method, the timestamps of consecutive fences need not
+    // correspond to consecutive hardware vsync events.
+    //
+    // This method should be called with the retire fence from each HWComposer
+    // set call that affects the display.
+    bool addPresentFence(const std::shared_ptr<FenceTime>& fenceTime) override;
+
+    // The beginResync, addResyncSample, and endResync methods are used to re-
+    // synchronize the DispSync's model to the hardware vsync events.  The re-
+    // synchronization process involves first calling beginResync, then
+    // calling addResyncSample with a sequence of consecutive hardware vsync
+    // event timestamps, and finally calling endResync when addResyncSample
+    // indicates that no more samples are needed by returning false.
+    //
+    // This resynchronization process should be performed whenever the display
+    // is turned on (i.e. once immediately after it's turned on) and whenever
+    // addPresentFence returns true indicating that the model has drifted away
+    // from the hardware vsync events.
+    void beginResync() override;
+    bool addResyncSample(nsecs_t timestamp) override;
+    void endResync() override;
+
+    // The setPeriod method sets the vsync event model's period to a specific
+    // value.  This should be used to prime the model when a display is first
+    // turned on.  It should NOT be used after that.
+    void setPeriod(nsecs_t period) override;
+
+    // The scalePeriod method applies the multiplier and divisor to
+    // scale the vsync event model's period.   The function is added
+    // for an experimental test mode and should not be used outside
+    // of that purpose.
+    void scalePeriod(const uint32_t multiplier, uint32_t divisor);
+
+    // The getPeriod method returns the current vsync period.
+    nsecs_t getPeriod() override;
+
+    // setRefreshSkipCount specifies an additional number of refresh
+    // cycles to skip.  For example, on a 60Hz display, a skip count of 1
+    // will result in events happening at 30Hz.  Default is zero.  The idea
+    // is to sacrifice smoothness for battery life.
+    void setRefreshSkipCount(int count) override;
+
+    // addEventListener registers a callback to be called repeatedly at the
+    // 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, Callback* callback) override;
+
+    // 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(Callback* callback) override;
+
+    // changePhaseOffset changes the phase offset of an already-registered event callback. The
+    // method will make sure that there is no skipping or double-firing on the listener per frame,
+    // even when changing the offsets multiple times.
+    status_t changePhaseOffset(Callback* callback, nsecs_t phase) override;
+
+    // computeNextRefresh computes when the next refresh is expected to begin.
+    // The periodOffset value can be used to move forward or backward; an
+    // offset of zero is the next refresh, -1 is the previous refresh, 1 is
+    // the refresh after next. etc.
+    nsecs_t computeNextRefresh(int periodOffset) const override;
+
+    // In certain situations the present fences aren't a good indicator of vsync
+    // time, e.g. when vr flinger is active, or simply aren't available,
+    // e.g. when the sync framework isn't present. Use this method to toggle
+    // whether or not DispSync ignores present fences. If present fences are
+    // ignored, DispSync will always ask for hardware vsync events by returning
+    // true from addPresentFence() and addResyncSample().
+    void setIgnorePresentFences(bool ignore) override;
+
+    // dump appends human-readable debug info to the result string.
+    void dump(String8& result) const override;
+
+private:
+    void updateModelLocked();
+    void updateErrorLocked();
+    void resetLocked();
+    void resetErrorLocked();
+
+    enum { MAX_RESYNC_SAMPLES = 32 };
+    enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 6 };
+    enum { NUM_PRESENT_SAMPLES = 8 };
+    enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 4 };
+    enum { ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT = 64 };
+
+    const char* const mName;
+
+    // mPeriod is the computed period of the modeled vsync events in
+    // nanoseconds.
+    nsecs_t mPeriod;
+    nsecs_t mPeriodBase;
+
+    // mPhase is the phase offset of the modeled vsync events.  It is the
+    // number of nanoseconds from time 0 to the first vsync event.
+    nsecs_t mPhase;
+
+    // mReferenceTime is the reference time of the modeled vsync events.
+    // It is the nanosecond timestamp of the first vsync event after a resync.
+    nsecs_t mReferenceTime;
+
+    // mError is the computed model error.  It is based on the difference
+    // between the estimated vsync event times and those observed in the
+    // mPresentFences array.
+    nsecs_t mError;
+
+    // mZeroErrSamplesCount keeps track of how many times in a row there were
+    // zero timestamps available in the mPresentFences array.
+    // Used to sanity check that we are able to calculate the model error.
+    size_t mZeroErrSamplesCount;
+
+    // Whether we have updated the vsync event model since the last resync.
+    bool mModelUpdated;
+
+    // These member variables are the state used during the resynchronization
+    // process to store information about the hardware vsync event times used
+    // to compute the model.
+    nsecs_t mResyncSamples[MAX_RESYNC_SAMPLES];
+    size_t mFirstResyncSample;
+    size_t mNumResyncSamples;
+    int mNumResyncSamplesSincePresent;
+
+    // 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};
+    size_t mPresentSampleOffset;
+
+    int mRefreshSkipCount;
+
+    // mThread is the thread from which all the callbacks are called.
+    sp<DispSyncThread> mThread;
+
+    // mMutex is used to protect access to all member variables.
+    mutable Mutex mMutex;
+
+    // This is the offset from the present fence timestamps to the corresponding
+    // vsync event.
+    int64_t mPresentTimeOffset;
+
+    // Ignore present (retire) fences if the device doesn't have support for the
+    // sync framework
+    bool mIgnorePresentFences;
+
+    std::unique_ptr<Callback> mZeroPhaseTracer;
+};
+
+} // namespace impl
+
+} // namespace android
+
+#endif // ANDROID_DISPSYNC_H
diff --git a/services/surfaceflinger/Scheduler/EventControlThread.cpp b/services/surfaceflinger/Scheduler/EventControlThread.cpp
new file mode 100644
index 0000000..fb6cff5
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/EventControlThread.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#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"
+
+namespace android {
+
+EventControlThread::~EventControlThread() = default;
+
+namespace impl {
+
+EventControlThread::EventControlThread(EventControlThread::SetVSyncEnabledFunction function)
+      : mSetVSyncEnabled(function) {
+    pthread_setname_np(mThread.native_handle(), "EventControlThread");
+
+    pid_t tid = pthread_gettid_np(mThread.native_handle());
+    setpriority(PRIO_PROCESS, tid, ANDROID_PRIORITY_URGENT_DISPLAY);
+    set_sched_policy(tid, SP_FOREGROUND);
+}
+
+EventControlThread::~EventControlThread() {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mKeepRunning = false;
+        mCondition.notify_all();
+    }
+    mThread.join();
+}
+
+void EventControlThread::setVsyncEnabled(bool enabled) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    mVsyncEnabled = enabled;
+    mCondition.notify_all();
+}
+
+// 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 impl
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/EventControlThread.h b/services/surfaceflinger/Scheduler/EventControlThread.h
new file mode 100644
index 0000000..cafae53
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/EventControlThread.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013 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 <condition_variable>
+#include <cstddef>
+#include <functional>
+#include <mutex>
+#include <thread>
+
+#include <android-base/thread_annotations.h>
+
+namespace android {
+
+class EventControlThread {
+public:
+    virtual ~EventControlThread();
+
+    virtual void setVsyncEnabled(bool enabled) = 0;
+};
+
+namespace impl {
+
+class EventControlThread final : public android::EventControlThread {
+public:
+    using SetVSyncEnabledFunction = std::function<void(bool)>;
+
+    explicit EventControlThread(SetVSyncEnabledFunction function);
+    ~EventControlThread();
+
+    // EventControlThread implementation
+    void setVsyncEnabled(bool enabled) override;
+
+private:
+    void threadMain();
+
+    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};
+};
+
+} // namespace impl
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
new file mode 100644
index 0000000..b84177c
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <pthread.h>
+#include <sched.h>
+#include <sys/types.h>
+#include <chrono>
+#include <cstdint>
+
+#include <cutils/compiler.h>
+#include <cutils/sched_policy.h>
+
+#include <gui/DisplayEventReceiver.h>
+
+#include <utils/Errors.h>
+#include <utils/String8.h>
+#include <utils/Trace.h>
+
+#include "EventThread.h"
+
+using namespace std::chrono_literals;
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+EventThread::~EventThread() = default;
+
+namespace impl {
+
+EventThread::EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback,
+                         InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
+      : mVSyncSource(src),
+        mResyncWithRateLimitCallback(resyncWithRateLimitCallback),
+        mInterceptVSyncsCallback(interceptVSyncsCallback) {
+    for (auto& event : mVSyncEvent) {
+        event.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
+        event.header.id = 0;
+        event.header.timestamp = 0;
+        event.vsync.count = 0;
+    }
+
+    mThread = std::thread(&EventThread::threadMain, this);
+
+    pthread_setname_np(mThread.native_handle(), threadName);
+
+    pid_t tid = pthread_gettid_np(mThread.native_handle());
+
+    // Use SCHED_FIFO to minimize jitter
+    constexpr int EVENT_THREAD_PRIORITY = 2;
+    struct sched_param param = {0};
+    param.sched_priority = EVENT_THREAD_PRIORITY;
+    if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, &param) != 0) {
+        ALOGE("Couldn't set SCHED_FIFO for EventThread");
+    }
+
+    set_sched_policy(tid, SP_FOREGROUND);
+}
+
+EventThread::~EventThread() {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mKeepRunning = false;
+        mCondition.notify_all();
+    }
+    mThread.join();
+}
+
+void EventThread::setPhaseOffset(nsecs_t phaseOffset) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    mVSyncSource->setPhaseOffset(phaseOffset);
+}
+
+sp<BnDisplayEventConnection> EventThread::createEventConnection() const {
+    return new Connection(const_cast<EventThread*>(this));
+}
+
+status_t EventThread::registerDisplayEventConnection(
+        const sp<EventThread::Connection>& connection) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    mDisplayEventConnections.add(connection);
+    mCondition.notify_all();
+    return NO_ERROR;
+}
+
+void EventThread::removeDisplayEventConnectionLocked(
+        const wp<EventThread::Connection>& connection) {
+    mDisplayEventConnections.remove(connection);
+}
+
+void EventThread::setVsyncRate(uint32_t count, const sp<EventThread::Connection>& connection) {
+    if (int32_t(count) >= 0) { // server must protect against bad params
+        std::lock_guard<std::mutex> lock(mMutex);
+        const int32_t new_count = (count == 0) ? -1 : count;
+        if (connection->count != new_count) {
+            connection->count = new_count;
+            mCondition.notify_all();
+        }
+    }
+}
+
+void EventThread::requestNextVsync(const sp<EventThread::Connection>& connection) {
+    std::lock_guard<std::mutex> lock(mMutex);
+
+    if (mResyncWithRateLimitCallback) {
+        mResyncWithRateLimitCallback();
+    }
+
+    if (connection->count < 0) {
+        connection->count = 0;
+        mCondition.notify_all();
+    }
+}
+
+void EventThread::onScreenReleased() {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (!mUseSoftwareVSync) {
+        // disable reliance on h/w vsync
+        mUseSoftwareVSync = true;
+        mCondition.notify_all();
+    }
+}
+
+void EventThread::onScreenAcquired() {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mUseSoftwareVSync) {
+        // resume use of h/w vsync
+        mUseSoftwareVSync = false;
+        mCondition.notify_all();
+    }
+}
+
+void EventThread::onVSyncEvent(nsecs_t timestamp) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
+    mVSyncEvent[0].header.id = 0;
+    mVSyncEvent[0].header.timestamp = timestamp;
+    mVSyncEvent[0].vsync.count++;
+    mCondition.notify_all();
+}
+
+void EventThread::onHotplugReceived(DisplayType displayType, bool connected) {
+    std::lock_guard<std::mutex> lock(mMutex);
+
+    DisplayEventReceiver::Event event;
+    event.header.type = DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG;
+    event.header.id = displayType == DisplayType::Primary ? 0 : 1;
+    event.header.timestamp = systemTime();
+    event.hotplug.connected = connected;
+
+    mPendingEvents.add(event);
+    mCondition.notify_all();
+}
+
+void EventThread::threadMain() NO_THREAD_SAFETY_ANALYSIS {
+    std::unique_lock<std::mutex> lock(mMutex);
+    while (mKeepRunning) {
+        DisplayEventReceiver::Event event;
+        Vector<sp<EventThread::Connection> > signalConnections;
+        signalConnections = waitForEventLocked(&lock, &event);
+
+        // dispatch events to listeners...
+        const size_t count = signalConnections.size();
+        for (size_t i = 0; i < count; i++) {
+            const sp<Connection>& conn(signalConnections[i]);
+            // now see if we still need to report this event
+            status_t err = conn->postEvent(event);
+            if (err == -EAGAIN || err == -EWOULDBLOCK) {
+                // The destination doesn't accept events anymore, it's probably
+                // full. For now, we just drop the events on the floor.
+                // FIXME: Note that some events cannot be dropped and would have
+                // to be re-sent later.
+                // Right-now we don't have the ability to do this.
+                ALOGW("EventThread: dropping event (%08x) for connection %p", event.header.type,
+                      conn.get());
+            } else if (err < 0) {
+                // handle any other error on the pipe as fatal. the only
+                // reasonable thing to do is to clean-up this connection.
+                // The most common error we'll get here is -EPIPE.
+                removeDisplayEventConnectionLocked(signalConnections[i]);
+            }
+        }
+    }
+}
+
+// This will return when (1) a vsync event has been received, and (2) there was
+// at least one connection interested in receiving it when we started waiting.
+Vector<sp<EventThread::Connection> > EventThread::waitForEventLocked(
+        std::unique_lock<std::mutex>* lock, DisplayEventReceiver::Event* outEvent) {
+    Vector<sp<EventThread::Connection> > signalConnections;
+
+    while (signalConnections.isEmpty() && mKeepRunning) {
+        bool eventPending = false;
+        bool waitForVSync = false;
+
+        size_t vsyncCount = 0;
+        nsecs_t timestamp = 0;
+        for (auto& event : mVSyncEvent) {
+            timestamp = event.header.timestamp;
+            if (timestamp) {
+                // we have a vsync event to dispatch
+                if (mInterceptVSyncsCallback) {
+                    mInterceptVSyncsCallback(timestamp);
+                }
+                *outEvent = event;
+                event.header.timestamp = 0;
+                vsyncCount = event.vsync.count;
+                break;
+            }
+        }
+
+        if (!timestamp) {
+            // no vsync event, see if there are some other event
+            eventPending = !mPendingEvents.isEmpty();
+            if (eventPending) {
+                // we have some other event to dispatch
+                *outEvent = mPendingEvents[0];
+                mPendingEvents.removeAt(0);
+            }
+        }
+
+        // find out connections waiting for events
+        size_t count = mDisplayEventConnections.size();
+        for (size_t i = 0; i < count;) {
+            sp<Connection> connection(mDisplayEventConnections[i].promote());
+            if (connection != nullptr) {
+                bool added = false;
+                if (connection->count >= 0) {
+                    // we need vsync events because at least
+                    // one connection is waiting for it
+                    waitForVSync = true;
+                    if (timestamp) {
+                        // we consume the event only if it's time
+                        // (ie: we received a vsync event)
+                        if (connection->count == 0) {
+                            // fired this time around
+                            connection->count = -1;
+                            signalConnections.add(connection);
+                            added = true;
+                        } else if (connection->count == 1 ||
+                                   (vsyncCount % connection->count) == 0) {
+                            // continuous event, and time to report it
+                            signalConnections.add(connection);
+                            added = true;
+                        }
+                    }
+                }
+
+                if (eventPending && !timestamp && !added) {
+                    // we don't have a vsync event to process
+                    // (timestamp==0), but we have some pending
+                    // messages.
+                    signalConnections.add(connection);
+                }
+                ++i;
+            } else {
+                // we couldn't promote this reference, the connection has
+                // died, so clean-up!
+                mDisplayEventConnections.removeAt(i);
+                --count;
+            }
+        }
+
+        // Here we figure out if we need to enable or disable vsyncs
+        if (timestamp && !waitForVSync) {
+            // we received a VSYNC but we have no clients
+            // don't report it, and disable VSYNC events
+            disableVSyncLocked();
+        } else if (!timestamp && waitForVSync) {
+            // we have at least one client, so we want vsync enabled
+            // (TODO: this function is called right after we finish
+            // notifying clients of a vsync, so this call will be made
+            // at the vsync rate, e.g. 60fps.  If we can accurately
+            // track the current state we could avoid making this call
+            // so often.)
+            enableVSyncLocked();
+        }
+
+        // note: !timestamp implies signalConnections.isEmpty(), because we
+        // don't populate signalConnections if there's no vsync pending
+        if (!timestamp && !eventPending) {
+            // wait for something to happen
+            if (waitForVSync) {
+                // This is where we spend most of our time, waiting
+                // for vsync events and new client registrations.
+                //
+                // If the screen is off, we can't use h/w vsync, so we
+                // use a 16ms timeout instead.  It doesn't need to be
+                // precise, we just need to keep feeding our clients.
+                //
+                // We don't want to stall if there's a driver bug, so we
+                // use a (long) timeout when waiting for h/w vsync, and
+                // generate fake events when necessary.
+                bool softwareSync = mUseSoftwareVSync;
+                auto timeout = softwareSync ? 16ms : 1000ms;
+                if (mCondition.wait_for(*lock, timeout) == std::cv_status::timeout) {
+                    if (!softwareSync) {
+                        ALOGW("Timed out waiting for hw vsync; faking it");
+                    }
+                    // FIXME: how do we decide which display id the fake
+                    // vsync came from ?
+                    mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
+                    mVSyncEvent[0].header.id = 0;
+                    mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+                    mVSyncEvent[0].vsync.count++;
+                }
+            } else {
+                // Nobody is interested in vsync, so we just want to sleep.
+                // h/w vsync should be disabled, so this will wait until we
+                // get a new connection, or an existing connection becomes
+                // interested in receiving vsync again.
+                mCondition.wait(*lock);
+            }
+        }
+    }
+
+    // here we're guaranteed to have a timestamp and some connections to signal
+    // (The connections might have dropped out of mDisplayEventConnections
+    // while we were asleep, but we'll still have strong references to them.)
+    return signalConnections;
+}
+
+void EventThread::enableVSyncLocked() {
+    if (!mUseSoftwareVSync) {
+        // never enable h/w VSYNC when screen is off
+        if (!mVsyncEnabled) {
+            mVsyncEnabled = true;
+            mVSyncSource->setCallback(this);
+            mVSyncSource->setVSyncEnabled(true);
+        }
+    }
+    mDebugVsyncEnabled = true;
+}
+
+void EventThread::disableVSyncLocked() {
+    if (mVsyncEnabled) {
+        mVsyncEnabled = false;
+        mVSyncSource->setVSyncEnabled(false);
+        mDebugVsyncEnabled = false;
+    }
+}
+
+void EventThread::dump(String8& result) const {
+    std::lock_guard<std::mutex> lock(mMutex);
+    result.appendFormat("VSYNC state: %s\n", mDebugVsyncEnabled ? "enabled" : "disabled");
+    result.appendFormat("  soft-vsync: %s\n", mUseSoftwareVSync ? "enabled" : "disabled");
+    result.appendFormat("  numListeners=%zu,\n  events-delivered: %u\n",
+                        mDisplayEventConnections.size(), mVSyncEvent[0].vsync.count);
+    for (size_t i = 0; i < mDisplayEventConnections.size(); i++) {
+        sp<Connection> connection = mDisplayEventConnections.itemAt(i).promote();
+        result.appendFormat("    %p: count=%d\n", connection.get(),
+                            connection != nullptr ? connection->count : 0);
+    }
+}
+
+// ---------------------------------------------------------------------------
+
+EventThread::Connection::Connection(EventThread* eventThread)
+      : count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {}
+
+EventThread::Connection::~Connection() {
+    // do nothing here -- clean-up will happen automatically
+    // when the main thread wakes up
+}
+
+void EventThread::Connection::onFirstRef() {
+    // NOTE: mEventThread doesn't hold a strong reference on us
+    mEventThread->registerDisplayEventConnection(this);
+}
+
+status_t EventThread::Connection::stealReceiveChannel(gui::BitTube* outChannel) {
+    outChannel->setReceiveFd(mChannel.moveReceiveFd());
+    return NO_ERROR;
+}
+
+status_t EventThread::Connection::setVsyncRate(uint32_t count) {
+    mEventThread->setVsyncRate(count, this);
+    return NO_ERROR;
+}
+
+void EventThread::Connection::requestNextVsync() {
+    mEventThread->requestNextVsync(this);
+}
+
+status_t EventThread::Connection::postEvent(const DisplayEventReceiver::Event& event) {
+    ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
+    return size < 0 ? status_t(size) : status_t(NO_ERROR);
+}
+
+// ---------------------------------------------------------------------------
+
+} // namespace impl
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
new file mode 100644
index 0000000..a0262b2
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2011 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 <sys/types.h>
+
+#include <array>
+#include <condition_variable>
+#include <cstdint>
+#include <mutex>
+#include <thread>
+
+#include <android-base/thread_annotations.h>
+
+#include <gui/DisplayEventReceiver.h>
+#include <gui/IDisplayEventConnection.h>
+#include <private/gui/BitTube.h>
+
+#include <utils/Errors.h>
+#include <utils/SortedVector.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+// ---------------------------------------------------------------------------
+
+class EventThreadTest;
+class SurfaceFlinger;
+class String8;
+
+// ---------------------------------------------------------------------------
+
+class VSyncSource {
+public:
+    class Callback {
+    public:
+        virtual ~Callback() {}
+        virtual void onVSyncEvent(nsecs_t when) = 0;
+    };
+
+    virtual ~VSyncSource() {}
+    virtual void setVSyncEnabled(bool enable) = 0;
+    virtual void setCallback(Callback* callback) = 0;
+    virtual void setPhaseOffset(nsecs_t phaseOffset) = 0;
+};
+
+class EventThread {
+public:
+    // TODO: Remove once stable display IDs are plumbed through SF/WM interface.
+    enum class DisplayType { Primary, External };
+
+    virtual ~EventThread();
+
+    virtual sp<BnDisplayEventConnection> createEventConnection() const = 0;
+
+    // called before the screen is turned off from main thread
+    virtual void onScreenReleased() = 0;
+
+    // called after the screen is turned on from main thread
+    virtual void onScreenAcquired() = 0;
+
+    // called when receiving a hotplug event
+    virtual void onHotplugReceived(DisplayType displayType, bool connected) = 0;
+
+    virtual void dump(String8& result) const = 0;
+
+    virtual void setPhaseOffset(nsecs_t phaseOffset) = 0;
+};
+
+namespace impl {
+
+class EventThread : public android::EventThread, private VSyncSource::Callback {
+    class Connection : public BnDisplayEventConnection {
+    public:
+        explicit Connection(EventThread* eventThread);
+        virtual ~Connection();
+
+        virtual status_t postEvent(const DisplayEventReceiver::Event& event);
+
+        // count >= 1 : continuous event. count is the vsync rate
+        // count == 0 : one-shot event that has not fired
+        // count ==-1 : one-shot event that fired this round / disabled
+        int32_t count;
+
+    private:
+        virtual void onFirstRef();
+        status_t stealReceiveChannel(gui::BitTube* outChannel) override;
+        status_t setVsyncRate(uint32_t count) override;
+        void requestNextVsync() override; // asynchronous
+        EventThread* const mEventThread;
+        gui::BitTube mChannel;
+    };
+
+public:
+    using ResyncWithRateLimitCallback = std::function<void()>;
+    using InterceptVSyncsCallback = std::function<void(nsecs_t)>;
+
+    EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback,
+                InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName);
+    ~EventThread();
+
+    sp<BnDisplayEventConnection> createEventConnection() const override;
+    status_t registerDisplayEventConnection(const sp<Connection>& connection);
+
+    void setVsyncRate(uint32_t count, const sp<Connection>& connection);
+    void requestNextVsync(const sp<Connection>& connection);
+
+    // called before the screen is turned off from main thread
+    void onScreenReleased() override;
+
+    // called after the screen is turned on from main thread
+    void onScreenAcquired() override;
+
+    // called when receiving a hotplug event
+    void onHotplugReceived(DisplayType displayType, bool connected) override;
+
+    void dump(String8& result) const override;
+
+    void setPhaseOffset(nsecs_t phaseOffset) override;
+
+private:
+    friend EventThreadTest;
+
+    void threadMain();
+    Vector<sp<EventThread::Connection>> waitForEventLocked(std::unique_lock<std::mutex>* lock,
+                                                           DisplayEventReceiver::Event* event)
+            REQUIRES(mMutex);
+
+    void removeDisplayEventConnectionLocked(const wp<Connection>& connection) REQUIRES(mMutex);
+    void enableVSyncLocked() REQUIRES(mMutex);
+    void disableVSyncLocked() REQUIRES(mMutex);
+
+    // Implements VSyncSource::Callback
+    void onVSyncEvent(nsecs_t timestamp) override;
+
+    // constants
+    VSyncSource* const mVSyncSource GUARDED_BY(mMutex) = nullptr;
+    const ResyncWithRateLimitCallback mResyncWithRateLimitCallback;
+    const InterceptVSyncsCallback mInterceptVSyncsCallback;
+
+    std::thread mThread;
+    mutable std::mutex mMutex;
+    mutable std::condition_variable mCondition;
+
+    // protected by mLock
+    SortedVector<wp<Connection>> mDisplayEventConnections GUARDED_BY(mMutex);
+    Vector<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);
+    std::array<DisplayEventReceiver::Event, 2> mVSyncEvent GUARDED_BY(mMutex);
+    bool mUseSoftwareVSync GUARDED_BY(mMutex) = false;
+    bool mVsyncEnabled GUARDED_BY(mMutex) = false;
+    bool mKeepRunning GUARDED_BY(mMutex) = true;
+
+    // for debugging
+    bool mDebugVsyncEnabled GUARDED_BY(mMutex) = false;
+};
+
+// ---------------------------------------------------------------------------
+
+} // namespace impl
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
new file mode 100644
index 0000000..056d381
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#include <errno.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/IPCThreadState.h>
+
+#include <utils/Log.h>
+#include <utils/Timers.h>
+#include <utils/threads.h>
+
+#include <gui/DisplayEventReceiver.h>
+#include <gui/IDisplayEventConnection.h>
+
+#include "EventThread.h"
+#include "MessageQueue.h"
+#include "SurfaceFlinger.h"
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+MessageBase::MessageBase() : MessageHandler() {}
+
+MessageBase::~MessageBase() {}
+
+void MessageBase::handleMessage(const Message&) {
+    this->handler();
+    barrier.open();
+};
+
+// ---------------------------------------------------------------------------
+
+MessageQueue::~MessageQueue() = default;
+
+// ---------------------------------------------------------------------------
+
+namespace impl {
+
+void MessageQueue::Handler::dispatchRefresh() {
+    if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {
+        mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
+    }
+}
+
+void MessageQueue::Handler::dispatchInvalidate() {
+    if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
+        mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
+    }
+}
+
+void MessageQueue::Handler::handleMessage(const Message& message) {
+    switch (message.what) {
+        case INVALIDATE:
+            android_atomic_and(~eventMaskInvalidate, &mEventMask);
+            mQueue.mFlinger->onMessageReceived(message.what);
+            break;
+        case REFRESH:
+            android_atomic_and(~eventMaskRefresh, &mEventMask);
+            mQueue.mFlinger->onMessageReceived(message.what);
+            break;
+    }
+}
+
+// ---------------------------------------------------------------------------
+
+void MessageQueue::init(const sp<SurfaceFlinger>& flinger) {
+    mFlinger = flinger;
+    mLooper = new Looper(true);
+    mHandler = new Handler(*this);
+}
+
+void MessageQueue::setEventThread(android::EventThread* eventThread) {
+    if (mEventThread == eventThread) {
+        return;
+    }
+
+    if (mEventTube.getFd() >= 0) {
+        mLooper->removeFd(mEventTube.getFd());
+    }
+
+    mEventThread = eventThread;
+    mEvents = eventThread->createEventConnection();
+    mEvents->stealReceiveChannel(&mEventTube);
+    mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
+                   this);
+}
+
+void MessageQueue::waitMessage() {
+    do {
+        IPCThreadState::self()->flushCommands();
+        int32_t ret = mLooper->pollOnce(-1);
+        switch (ret) {
+            case Looper::POLL_WAKE:
+            case Looper::POLL_CALLBACK:
+                continue;
+            case Looper::POLL_ERROR:
+                ALOGE("Looper::POLL_ERROR");
+                continue;
+            case Looper::POLL_TIMEOUT:
+                // timeout (should not happen)
+                continue;
+            default:
+                // should not happen
+                ALOGE("Looper::pollOnce() returned unknown status %d", ret);
+                continue;
+        }
+    } while (true);
+}
+
+status_t MessageQueue::postMessage(const sp<MessageBase>& messageHandler, nsecs_t relTime) {
+    const Message dummyMessage;
+    if (relTime > 0) {
+        mLooper->sendMessageDelayed(relTime, messageHandler, dummyMessage);
+    } else {
+        mLooper->sendMessage(messageHandler, dummyMessage);
+    }
+    return NO_ERROR;
+}
+
+void MessageQueue::invalidate() {
+    mEvents->requestNextVsync();
+}
+
+void MessageQueue::refresh() {
+    mHandler->dispatchRefresh();
+}
+
+int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
+    MessageQueue* queue = reinterpret_cast<MessageQueue*>(data);
+    return queue->eventReceiver(fd, events);
+}
+
+int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
+    ssize_t n;
+    DisplayEventReceiver::Event buffer[8];
+    while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) {
+        for (int i = 0; i < n; i++) {
+            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
+                mHandler->dispatchInvalidate();
+                break;
+            }
+        }
+    }
+    return 1;
+}
+
+// ---------------------------------------------------------------------------
+
+} // namespace impl
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h
new file mode 100644
index 0000000..90d1c72
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/MessageQueue.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#ifndef ANDROID_MESSAGE_QUEUE_H
+#define ANDROID_MESSAGE_QUEUE_H
+
+#include <errno.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Looper.h>
+#include <utils/Timers.h>
+#include <utils/threads.h>
+
+#include <gui/IDisplayEventConnection.h>
+#include <private/gui/BitTube.h>
+
+#include "Barrier.h"
+
+#include <functional>
+
+namespace android {
+
+class EventThread;
+class SurfaceFlinger;
+
+// ---------------------------------------------------------------------------
+
+class MessageBase : public MessageHandler {
+public:
+    MessageBase();
+
+    // return true if message has a handler
+    virtual bool handler() = 0;
+
+    // waits for the handler to be processed
+    void wait() const { barrier.wait(); }
+
+protected:
+    virtual ~MessageBase();
+
+private:
+    virtual void handleMessage(const Message& message);
+
+    mutable Barrier barrier;
+};
+
+class LambdaMessage : public MessageBase {
+public:
+    explicit LambdaMessage(std::function<void()> handler)
+          : MessageBase(), mHandler(std::move(handler)) {}
+
+    bool handler() override {
+        mHandler();
+        // This return value is no longer checked, so it's always safe to return true
+        return true;
+    }
+
+private:
+    const std::function<void()> mHandler;
+};
+
+// ---------------------------------------------------------------------------
+
+class MessageQueue {
+public:
+    enum {
+        INVALIDATE = 0,
+        REFRESH = 1,
+    };
+
+    virtual ~MessageQueue();
+
+    virtual void init(const sp<SurfaceFlinger>& flinger) = 0;
+    virtual void setEventThread(EventThread* events) = 0;
+    virtual void waitMessage() = 0;
+    virtual status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime = 0) = 0;
+    virtual void invalidate() = 0;
+    virtual void refresh() = 0;
+};
+
+// ---------------------------------------------------------------------------
+
+namespace impl {
+
+class MessageQueue final : public android::MessageQueue {
+    class Handler : public MessageHandler {
+        enum { eventMaskInvalidate = 0x1, eventMaskRefresh = 0x2, eventMaskTransaction = 0x4 };
+        MessageQueue& mQueue;
+        int32_t mEventMask;
+
+    public:
+        explicit Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) {}
+        virtual void handleMessage(const Message& message);
+        void dispatchRefresh();
+        void dispatchInvalidate();
+    };
+
+    friend class Handler;
+
+    sp<SurfaceFlinger> mFlinger;
+    sp<Looper> mLooper;
+    android::EventThread* mEventThread;
+    sp<IDisplayEventConnection> mEvents;
+    gui::BitTube mEventTube;
+    sp<Handler> mHandler;
+
+    static int cb_eventReceiver(int fd, int events, void* data);
+    int eventReceiver(int fd, int events);
+
+public:
+    ~MessageQueue() override = default;
+    void init(const sp<SurfaceFlinger>& flinger) override;
+    void setEventThread(android::EventThread* events) override;
+
+    void waitMessage() override;
+    status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime = 0) override;
+
+    // sends INVALIDATE message at next VSYNC
+    void invalidate() override;
+    // sends REFRESH message at next VSYNC
+    void refresh() override;
+};
+
+// ---------------------------------------------------------------------------
+
+} // namespace impl
+} // namespace android
+
+#endif /* ANDROID_MESSAGE_QUEUE_H */
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
new file mode 100644
index 0000000..7dfad43
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2018 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/Errors.h>
+
+#include <mutex>
+
+using namespace android::surfaceflinger;
+
+namespace android {
+
+/*
+ * Modulates the vsync-offsets depending on current SurfaceFlinger state.
+ */
+class VSyncModulator {
+private:
+    // Number of frames we'll keep the early phase offsets once they are activated. This acts as a
+    // low-pass filter in case the client isn't quick enough in sending new transactions.
+    const int MIN_EARLY_FRAME_COUNT = 2;
+
+public:
+    struct Offsets {
+        nsecs_t sf;
+        nsecs_t app;
+    };
+
+    enum TransactionStart { EARLY, NORMAL };
+
+    // Sets the phase offsets
+    //
+    // sfEarly: The phase offset when waking up SF early, which happens when marking a transaction
+    //          as early. May be the same as late, in which case we don't shift offsets.
+    // sfEarlyGl: Like sfEarly, but only if we used GL composition. If we use both GL composition
+    //            and the transaction was marked as early, we'll use sfEarly.
+    // sfLate: The regular SF vsync phase offset.
+    // appEarly: Like sfEarly, but for the app-vsync
+    // appEarlyGl: Like sfEarlyGl, but for the app-vsync.
+    // appLate: The regular app vsync phase offset.
+    void setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late) {
+        mEarlyOffsets = early;
+        mEarlyGlOffsets = earlyGl;
+        mLateOffsets = late;
+        mOffsets = late;
+    }
+
+    Offsets getEarlyOffsets() const { return mEarlyOffsets; }
+
+    Offsets getEarlyGlOffsets() const { return mEarlyGlOffsets; }
+
+    void setEventThreads(EventThread* sfEventThread, EventThread* appEventThread) {
+        mSfEventThread = sfEventThread;
+        mAppEventThread = appEventThread;
+    }
+
+    void setTransactionStart(TransactionStart transactionStart) {
+        if (transactionStart == TransactionStart::EARLY) {
+            mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT;
+        }
+
+        // An early transaction stays an early transaction.
+        if (transactionStart == mTransactionStart || mTransactionStart == TransactionStart::EARLY) {
+            return;
+        }
+        mTransactionStart = transactionStart;
+        updateOffsets();
+    }
+
+    void onTransactionHandled() {
+        if (mTransactionStart == TransactionStart::NORMAL) return;
+        mTransactionStart = TransactionStart::NORMAL;
+        updateOffsets();
+    }
+
+    void onRefreshed(bool usedRenderEngine) {
+        bool updateOffsetsNeeded = false;
+        if (mRemainingEarlyFrameCount > 0) {
+            mRemainingEarlyFrameCount--;
+            updateOffsetsNeeded = true;
+        }
+        if (usedRenderEngine != mLastFrameUsedRenderEngine) {
+            mLastFrameUsedRenderEngine = usedRenderEngine;
+            updateOffsetsNeeded = true;
+        }
+        if (updateOffsetsNeeded) {
+            updateOffsets();
+        }
+    }
+
+private:
+    void updateOffsets() {
+        const Offsets desired = getOffsets();
+        const Offsets current = mOffsets;
+
+        bool changed = false;
+        if (desired.sf != current.sf) {
+            mSfEventThread->setPhaseOffset(desired.sf);
+            changed = true;
+        }
+        if (desired.app != current.app) {
+            mAppEventThread->setPhaseOffset(desired.app);
+            changed = true;
+        }
+
+        if (changed) {
+            mOffsets = desired;
+        }
+    }
+
+    Offsets getOffsets() {
+        if (mTransactionStart == TransactionStart::EARLY || mRemainingEarlyFrameCount > 0) {
+            return mEarlyOffsets;
+        } else if (mLastFrameUsedRenderEngine) {
+            return mEarlyGlOffsets;
+        } else {
+            return mLateOffsets;
+        }
+    }
+
+    Offsets mLateOffsets;
+    Offsets mEarlyOffsets;
+    Offsets mEarlyGlOffsets;
+
+    EventThread* mSfEventThread = nullptr;
+    EventThread* mAppEventThread = nullptr;
+
+    std::atomic<Offsets> mOffsets;
+
+    std::atomic<TransactionStart> mTransactionStart = TransactionStart::NORMAL;
+    std::atomic<bool> mLastFrameUsedRenderEngine = false;
+    std::atomic<int> mRemainingEarlyFrameCount = 0;
+};
+
+} // namespace android
