Merge changes I91b38c51,Ic62bfb68

* changes:
  [SurfaceFlinger] Allow DispSync to be GMock'd
  [SurfaceFlinger] Hide SyncFeatures behind RenderEngine
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index d231790..8788d47 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -40,7 +40,6 @@
 #include <gui/SurfaceComposerClient.h>
 
 #include <private/gui/ComposerService.h>
-#include <private/gui/SyncFeatures.h>
 
 #include <utils/Log.h>
 #include <utils/String8.h>
@@ -206,7 +205,7 @@
         return err;
     }
 
-    if (!SyncFeatures::getInstance().useNativeFenceSync()) {
+    if (mRE.useNativeFenceSync()) {
         // Bind the new buffer to the GL texture.
         //
         // Older devices require the "implicit" synchronization provided
@@ -374,7 +373,7 @@
     BLC_LOGV("syncForReleaseLocked");
 
     if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
-        if (SyncFeatures::getInstance().useNativeFenceSync()) {
+        if (mRE.useNativeFenceSync()) {
             base::unique_fd fenceFd = mRE.flush();
             if (fenceFd == -1) {
                 BLC_LOGE("syncForReleaseLocked: failed to flush RenderEngine");
@@ -512,7 +511,7 @@
     }
 
     if (mCurrentFence->isValid()) {
-        if (SyncFeatures::getInstance().useWaitSync()) {
+        if (mRE.useWaitSync()) {
             base::unique_fd fenceFd(mCurrentFence->dup());
             if (fenceFd == -1) {
                 BLC_LOGE("doFenceWait: error dup'ing fence fd: %d", errno);
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 80f741b..6c339b7 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -245,8 +245,9 @@
     LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
                     getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
                     getTransformToDisplayInverse(), mFreezeGeometryUpdates);
-    status_t updateResult = mConsumer->updateTexImage(&r, mFlinger->mPrimaryDispSync, &mAutoRefresh,
-                                                      &queuedBuffer, mLastFrameNumberReceived);
+    status_t updateResult =
+            mConsumer->updateTexImage(&r, *mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer,
+                                      mLastFrameNumberReceived);
     if (updateResult == BufferQueue::PRESENT_LATER) {
         // Producer doesn't want buffer to be displayed yet.  Signal a
         // layer update so we check again at the next opportunity.
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index 829b53d..cdfbba3 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -40,6 +40,10 @@
 
 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;
@@ -707,4 +711,6 @@
     result.appendFormat("current monotonic time: %" PRId64 "\n", now);
 }
 
+} // namespace impl
+
 } // namespace android
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index c00c161..1be131f 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -31,6 +31,36 @@
 
 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 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
@@ -46,21 +76,15 @@
 // current model accurately represents the hardware event times it will return
 // false to indicate that a resynchronization (via addResyncSample) is not
 // needed.
-class DispSync {
+class DispSync : public android::DispSync {
 public:
-    class Callback {
-    public:
-        virtual ~Callback(){};
-        virtual void onDispSyncEvent(nsecs_t when) = 0;
-    };
-
     explicit DispSync(const char* name);
-    ~DispSync();
+    ~DispSync() override;
 
     void init(bool hasSyncFramework, int64_t dispSyncPresentTimeOffset);
 
     // reset clears the resync samples and error value.
-    void reset();
+    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
@@ -71,7 +95,7 @@
     //
     // 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);
+    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-
@@ -84,45 +108,45 @@
     // 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();
-    bool addResyncSample(nsecs_t timestamp);
-    void endResync();
+    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);
+    void setPeriod(nsecs_t period) override;
 
     // The getPeriod method returns the current vsync period.
-    nsecs_t getPeriod();
+    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);
+    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);
+    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);
+    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);
+    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;
+    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,
@@ -130,10 +154,10 @@
     // 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);
+    void setIgnorePresentFences(bool ignore) override;
 
     // dump appends human-readable debug info to the result string.
-    void dump(String8& result) const;
+    void dump(String8& result) const override;
 
 private:
     void updateModelLocked();
@@ -206,6 +230,8 @@
     std::unique_ptr<Callback> mZeroPhaseTracer;
 };
 
+} // namespace impl
+
 } // namespace android
 
 #endif // ANDROID_DISPSYNC_H
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 0b8b838..39f7e30 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -29,6 +29,7 @@
 
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <configstore/Utils.h>
+#include <private/gui/SyncFeatures.h>
 
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
@@ -175,6 +176,14 @@
     return mEGLConfig;
 }
 
+bool RenderEngine::useNativeFenceSync() const {
+    return SyncFeatures::getInstance().useNativeFenceSync();
+}
+
+bool RenderEngine::useWaitSync() const {
+    return SyncFeatures::getInstance().useWaitSync();
+}
+
 bool RenderEngine::isCurrent() const {
     return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext();
 }
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 95b9ec8..40bc966 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -69,6 +69,9 @@
     // dump the extension strings. always call the base class.
     virtual void dump(String8& result) = 0;
 
+    virtual bool useNativeFenceSync() const = 0;
+    virtual bool useWaitSync() const = 0;
+
     virtual bool isCurrent() const = 0;
     virtual bool setCurrentSurface(const RE::Surface& surface) = 0;
     virtual void resetCurrentSurface() = 0;
@@ -190,6 +193,9 @@
     // dump the extension strings. always call the base class.
     void dump(String8& result) override;
 
+    bool useNativeFenceSync() const override;
+    bool useWaitSync() const override;
+
     bool isCurrent() const;
     bool setCurrentSurface(const RE::Surface& surface) override;
     void resetCurrentSurface() override;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 399fbd8..31e4444 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -264,7 +264,6 @@
         mDebugInTransaction(0),
         mLastTransactionTime(0),
         mForceFullDamage(false),
-        mPrimaryDispSync("PrimaryDispSync"),
         mPrimaryHWVsyncEnabled(false),
         mHWVsyncAvailable(false),
         mHasPoweredOff(false),
@@ -325,7 +324,13 @@
     }
     ALOGV("Primary Display Orientation is set to %2d.", mPrimaryDisplayOrientation);
 
-    mPrimaryDispSync.init(SurfaceFlinger::hasSyncFramework, SurfaceFlinger::dispSyncPresentTimeOffset);
+    // Note: We create a local temporary with the real DispSync implementation
+    // type temporarily so we can initialize it with the configured values,
+    // before storing it for more generic use using the interface type.
+    auto primaryDispSync = std::make_unique<impl::DispSync>("PrimaryDispSync");
+    primaryDispSync->init(SurfaceFlinger::hasSyncFramework,
+                          SurfaceFlinger::dispSyncPresentTimeOffset);
+    mPrimaryDispSync = std::move(primaryDispSync);
 
     // debugging stuff...
     char value[PROPERTY_VALUE_MAX];
@@ -703,14 +708,14 @@
 
     // start the EventThread
     mEventThreadSource =
-            std::make_unique<DispSyncSource>(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs,
-                                             true, "app");
+            std::make_unique<DispSyncSource>(mPrimaryDispSync.get(),
+                                             SurfaceFlinger::vsyncPhaseOffsetNs, true, "app");
     mEventThread = std::make_unique<impl::EventThread>(mEventThreadSource.get(),
                                                        [this] { resyncWithRateLimit(); },
                                                        impl::EventThread::InterceptVSyncsCallback(),
                                                        "appEventThread");
     mSfEventThreadSource =
-            std::make_unique<DispSyncSource>(&mPrimaryDispSync,
+            std::make_unique<DispSyncSource>(mPrimaryDispSync.get(),
                                              SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
 
     mSFEventThread =
@@ -996,8 +1001,8 @@
 
     // FIXME for now we always return stats for the primary display
     memset(stats, 0, sizeof(*stats));
-    stats->vsyncTime   = mPrimaryDispSync.computeNextRefresh(0);
-    stats->vsyncPeriod = mPrimaryDispSync.getPeriod();
+    stats->vsyncTime = mPrimaryDispSync->computeNextRefresh(0);
+    stats->vsyncPeriod = mPrimaryDispSync->getPeriod();
     return NO_ERROR;
 }
 
@@ -1295,7 +1300,7 @@
 void SurfaceFlinger::enableHardwareVsync() {
     Mutex::Autolock _l(mHWVsyncLock);
     if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
-        mPrimaryDispSync.beginResync();
+        mPrimaryDispSync->beginResync();
         mEventControlThread->setVsyncEnabled(true);
         mPrimaryHWVsyncEnabled = true;
     }
@@ -1320,11 +1325,11 @@
     const auto activeConfig = getHwComposer().getActiveConfig(displayId);
     const nsecs_t period = activeConfig->getVsyncPeriod();
 
-    mPrimaryDispSync.reset();
-    mPrimaryDispSync.setPeriod(period);
+    mPrimaryDispSync->reset();
+    mPrimaryDispSync->setPeriod(period);
 
     if (!mPrimaryHWVsyncEnabled) {
-        mPrimaryDispSync.beginResync();
+        mPrimaryDispSync->beginResync();
         mEventControlThread->setVsyncEnabled(true);
         mPrimaryHWVsyncEnabled = true;
     }
@@ -1334,7 +1339,7 @@
     Mutex::Autolock _l(mHWVsyncLock);
     if (mPrimaryHWVsyncEnabled) {
         mEventControlThread->setVsyncEnabled(false);
-        mPrimaryDispSync.endResync();
+        mPrimaryDispSync->endResync();
         mPrimaryHWVsyncEnabled = false;
     }
     if (makeUnavailable) {
@@ -1379,7 +1384,7 @@
     { // Scope for the lock
         Mutex::Autolock _l(mHWVsyncLock);
         if (mPrimaryHWVsyncEnabled) {
-            needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
+            needsHwVsync = mPrimaryDispSync->addResyncSample(timestamp);
         }
     }
 
@@ -1506,8 +1511,8 @@
 
     // The present fences returned from vr_hwc are not an accurate
     // representation of vsync times.
-    mPrimaryDispSync.setIgnorePresentFences(
-            getBE().mHwc->isUsingVrComposer() || !hasSyncFramework);
+    mPrimaryDispSync->setIgnorePresentFences(getBE().mHwc->isUsingVrComposer() ||
+                                             !hasSyncFramework);
 
     // Use phase of 0 since phase is not known.
     // Use latency of 0, which will snap to the ideal latency.
@@ -1770,8 +1775,8 @@
     auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFence);
     getBE().mDisplayTimeline.push(presentFenceTime);
 
-    nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0);
-    nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod();
+    nsecs_t vsyncPhase = mPrimaryDispSync->computeNextRefresh(0);
+    nsecs_t vsyncInterval = mPrimaryDispSync->getPeriod();
 
     // We use the refreshStartTime which might be sampled a little later than
     // when we started doing work for this frame, but that should be okay
@@ -1794,7 +1799,7 @@
     });
 
     if (presentFenceTime->isValid()) {
-        if (mPrimaryDispSync.addPresentFence(presentFenceTime)) {
+        if (mPrimaryDispSync->addPresentFence(presentFenceTime)) {
             enableHardwareVsync();
         } else {
             disableHardwareVsync(false);
@@ -2873,7 +2878,7 @@
     mDrawingState.traverseInZOrder([&](Layer* layer) {
         if (layer->hasReadyFrame()) {
             frameQueued = true;
-            if (layer->shouldPresentNow(mPrimaryDispSync)) {
+            if (layer->shouldPresentNow(*mPrimaryDispSync)) {
                 mLayersWithQueuedFrames.push_back(layer);
             } else {
                 layer->useEmptyDamage();
@@ -3966,7 +3971,7 @@
             if ((index < numArgs) &&
                     (args[index] == String16("--dispsync"))) {
                 index++;
-                mPrimaryDispSync.dump(result);
+                mPrimaryDispSync->dump(result);
                 dumpAll = false;
             }
 
@@ -4749,7 +4754,7 @@
             // Needs to be shifted to proper binder interface when we productize
             case 1016: {
                 n = data.readInt32();
-                mPrimaryDispSync.setRefreshSkipCount(n);
+                mPrimaryDispSync->setRefreshSkipCount(n);
                 return NO_ERROR;
             }
             case 1017: {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index eaaf742..12f4185 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -853,7 +853,7 @@
     // these are thread safe
     mutable std::unique_ptr<MessageQueue> mEventQueue{std::make_unique<impl::MessageQueue>()};
     FrameTracker mAnimFrameTracker;
-    DispSync mPrimaryDispSync;
+    std::unique_ptr<DispSync> mPrimaryDispSync;
     int mPrimaryDisplayOrientation = DisplayState::eOrientationDefault;
 
     // protected by mDestroyedLayerLock;
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 95c54b8..8f1f5e5 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -27,6 +27,7 @@
         "mock/DisplayHardware/MockPowerAdvisor.cpp",
         "mock/gui/MockGraphicBufferConsumer.cpp",
         "mock/gui/MockGraphicBufferProducer.cpp",
+        "mock/MockDispSync.cpp",
         "mock/MockEventControlThread.cpp",
         "mock/MockEventThread.cpp",
         "mock/MockMessageQueue.cpp",
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 58d3879..508875d 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -25,6 +25,7 @@
 #include "TestableSurfaceFlinger.h"
 #include "mock/DisplayHardware/MockComposer.h"
 #include "mock/DisplayHardware/MockDisplaySurface.h"
+#include "mock/MockDispSync.h"
 #include "mock/MockEventControlThread.h"
 #include "mock/MockEventThread.h"
 #include "mock/MockMessageQueue.h"
@@ -119,6 +120,7 @@
     Hwc2::mock::Composer* mComposer = nullptr;
     mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
     mock::SurfaceInterceptor* mSurfaceInterceptor = new mock::SurfaceInterceptor();
+    mock::DispSync* mPrimaryDispSync = new mock::DispSync();
 
     // These mocks are created only when expected to be created via a factory.
     sp<mock::GraphicBufferConsumer> mConsumer;
@@ -154,6 +156,7 @@
     mFlinger.mutableEventQueue().reset(mMessageQueue);
     mFlinger.setupRenderEngine(std::unique_ptr<RE::RenderEngine>(mRenderEngine));
     mFlinger.mutableInterceptor().reset(mSurfaceInterceptor);
+    mFlinger.mutablePrimaryDispSync().reset(mPrimaryDispSync);
 
     injectMockComposer(0);
 }
@@ -961,6 +964,9 @@
     // The call clears the current render engine surface
     EXPECT_CALL(*mRenderEngine, resetCurrentSurface());
 
+    // The call ends any display resyncs
+    EXPECT_CALL(*mPrimaryDispSync, endResync()).Times(1);
+
     // --------------------------------------------------------------------
     // Invocation
 
@@ -2400,6 +2406,24 @@
     }
 };
 
+struct DispSyncIsSupportedVariant {
+    static void setupBeginResyncCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mPrimaryDispSync, reset()).Times(1);
+        EXPECT_CALL(*test->mPrimaryDispSync, setPeriod(DEFAULT_REFRESH_RATE)).Times(1);
+        EXPECT_CALL(*test->mPrimaryDispSync, beginResync()).Times(1);
+    }
+
+    static void setupEndResyncCallExpectations(DisplayTransactionTest* test) {
+        EXPECT_CALL(*test->mPrimaryDispSync, endResync()).Times(1);
+    }
+};
+
+struct DispSyncNotSupportedVariant {
+    static void setupBeginResyncCallExpectations(DisplayTransactionTest* /* test */) {}
+
+    static void setupEndResyncCallExpectations(DisplayTransactionTest* /* test */) {}
+};
+
 // --------------------------------------------------------------------
 // Note:
 //
@@ -2421,6 +2445,7 @@
     static void setupCallExpectations(DisplayTransactionTest* test) {
         Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON);
         Case::EventThread::setupAcquireAndEnableVsyncCallExpectations(test);
+        Case::DispSync::setupBeginResyncCallExpectations(test);
         Case::setupRepaintEverythingCallExpectations(test);
     }
 
@@ -2450,6 +2475,7 @@
     template <typename Case>
     static void setupCallExpectations(DisplayTransactionTest* test) {
         Case::EventThread::setupReleaseAndDisableVsyncCallExpectations(test);
+        Case::DispSync::setupEndResyncCallExpectations(test);
         Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::OFF);
     }
 
@@ -2485,6 +2511,7 @@
     template <typename Case>
     static void setupCallExpectations(DisplayTransactionTest* test) {
         Case::EventThread::setupAcquireAndEnableVsyncCallExpectations(test);
+        Case::DispSync::setupBeginResyncCallExpectations(test);
         Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE);
     }
 };
@@ -2503,6 +2530,7 @@
     template <typename Case>
     static void setupCallExpectations(DisplayTransactionTest* test) {
         Case::EventThread::setupAcquireAndEnableVsyncCallExpectations(test);
+        Case::DispSync::setupBeginResyncCallExpectations(test);
         Case::setupComposerCallExpectations(test, IComposerClient::PowerMode::ON);
     }
 };
@@ -2512,6 +2540,7 @@
     template <typename Case>
     static void setupCallExpectations(DisplayTransactionTest* test) {
         Case::EventThread::setupReleaseAndDisableVsyncCallExpectations(test);
+        Case::DispSync::setupEndResyncCallExpectations(test);
         Case::setupComposerCallExpectations(test, Case::Doze::ACTUAL_POWER_MODE_FOR_DOZE_SUSPEND);
     }
 };
@@ -2534,11 +2563,12 @@
 // --------------------------------------------------------------------
 
 template <typename DisplayVariant, typename DozeVariant, typename EventThreadVariant,
-          typename TransitionVariant>
+          typename DispSyncVariant, typename TransitionVariant>
 struct DisplayPowerCase {
     using Display = DisplayVariant;
     using Doze = DozeVariant;
     using EventThread = EventThreadVariant;
+    using DispSync = DispSyncVariant;
     using Transition = TransitionVariant;
 
     static auto injectDisplayWithInitialPowerMode(DisplayTransactionTest* test, int mode) {
@@ -2586,15 +2616,16 @@
 // In addition to having event thread support, we emulate doze support.
 template <typename TransitionVariant>
 using PrimaryDisplayPowerCase = DisplayPowerCase<PrimaryDisplayVariant, DozeIsSupportedVariant,
-                                                 EventThreadIsSupportedVariant, TransitionVariant>;
+                                                 EventThreadIsSupportedVariant,
+                                                 DispSyncIsSupportedVariant, TransitionVariant>;
 
 // A sample configuration for the external display.
 // In addition to not having event thread support, we emulate not having doze
 // support.
 template <typename TransitionVariant>
-using ExternalDisplayPowerCase =
-        DisplayPowerCase<ExternalDisplayVariant, DozeNotSupportedVariant,
-                         EventThreadNotSupportedVariant, TransitionVariant>;
+using ExternalDisplayPowerCase = DisplayPowerCase<ExternalDisplayVariant, DozeNotSupportedVariant,
+                                                  EventThreadNotSupportedVariant,
+                                                  DispSyncNotSupportedVariant, TransitionVariant>;
 
 class SetPowerModeInternalTest : public DisplayTransactionTest {
 public:
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 5031148..9df4264 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -126,6 +126,7 @@
     auto& mutableInterceptor() { return mFlinger->mInterceptor; }
     auto& mutableMainThreadId() { return mFlinger->mMainThreadId; }
     auto& mutablePendingHotplugEvents() { return mFlinger->mPendingHotplugEvents; }
+    auto& mutablePrimaryDispSync() { return mFlinger->mPrimaryDispSync; }
     auto& mutablePrimaryHWVsyncEnabled() { return mFlinger->mPrimaryHWVsyncEnabled; }
     auto& mutableTransactionFlags() { return mFlinger->mTransactionFlags; }
     auto& mutableUseHwcVirtualDisplays() { return mFlinger->mUseHwcVirtualDisplays; }
@@ -144,6 +145,7 @@
         mutableEventQueue().reset();
         mutableEventThread().reset();
         mutableInterceptor().reset();
+        mutablePrimaryDispSync().reset();
         mFlinger->getBE().mHwc.reset();
         mFlinger->getBE().mRenderEngine.reset();
     }
diff --git a/services/surfaceflinger/tests/unittests/mock/MockDispSync.cpp b/services/surfaceflinger/tests/unittests/mock/MockDispSync.cpp
new file mode 100644
index 0000000..2f7e5ea
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#include "mock/MockDispSync.h"
+
+namespace android {
+namespace mock {
+
+// Explicit default instantiation is recommended.
+DispSync::DispSync() = default;
+DispSync::~DispSync() = default;
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
new file mode 100644
index 0000000..4a466ef
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 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 <gmock/gmock.h>
+
+#include <utils/String8.h>
+#include "DispSync.h"
+
+namespace android {
+namespace mock {
+
+class DispSync : public android::DispSync {
+public:
+    DispSync();
+    ~DispSync() override;
+
+    MOCK_METHOD0(reset, void());
+    MOCK_METHOD1(addPresentFence, bool(const std::shared_ptr<FenceTime>&));
+    MOCK_METHOD0(beginResync, void());
+    MOCK_METHOD1(addResyncSample, bool(nsecs_t));
+    MOCK_METHOD0(endResync, void());
+    MOCK_METHOD1(setPeriod, void(nsecs_t));
+    MOCK_METHOD0(getPeriod, nsecs_t());
+    MOCK_METHOD1(setRefreshSkipCount, void(int));
+    MOCK_METHOD3(addEventListener, status_t(const char*, nsecs_t, Callback*));
+    MOCK_METHOD1(removeEventListener, status_t(Callback*));
+    MOCK_METHOD2(changePhaseOffset, status_t(Callback*, nsecs_t));
+    MOCK_CONST_METHOD1(computeNextRefresh, nsecs_t(int));
+    MOCK_METHOD1(setIgnorePresentFences, void(bool));
+
+    MOCK_CONST_METHOD1(dump, void(String8&));
+};
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
index 7caf864..7814d32 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
@@ -37,6 +37,8 @@
     MOCK_METHOD0(createImage, std::unique_ptr<RE::Image>());
     MOCK_CONST_METHOD0(primeCache, void());
     MOCK_METHOD1(dump, void(String8&));
+    MOCK_CONST_METHOD0(useNativeFenceSync, bool());
+    MOCK_CONST_METHOD0(useWaitSync, bool());
     MOCK_CONST_METHOD0(isCurrent, bool());
     MOCK_METHOD1(setCurrentSurface, bool(const RE::Surface&));
     MOCK_METHOD0(resetCurrentSurface, void());