Merge "Move log tag definition from Android.bp to cpp file."
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index e583b40..1e8d94c 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -1331,6 +1331,7 @@
         uint32_t allocHeight = 0;
         PixelFormat allocFormat = PIXEL_FORMAT_UNKNOWN;
         uint64_t allocUsage = 0;
+        std::string allocName;
         { // Autolock scope
             Mutex::Autolock lock(mCore->mMutex);
             mCore->waitWhileAllocatingLocked();
@@ -1350,6 +1351,7 @@
             allocHeight = height > 0 ? height : mCore->mDefaultHeight;
             allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
             allocUsage = usage | mCore->mConsumerUsageBits;
+            allocName.assign(mCore->mConsumerName.string(), mCore->mConsumerName.size());
 
             mCore->mIsAllocating = true;
         } // Autolock scope
@@ -1358,7 +1360,7 @@
         for (size_t i = 0; i <  newBufferCount; ++i) {
             sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
                     allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT,
-                    allocUsage, {mConsumerName.string(), mConsumerName.size()});
+                    allocUsage, allocName);
 
             status_t result = graphicBuffer->initCheck();
 
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index a4aec6e..e08d6b0 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -881,6 +881,10 @@
                 *value = mGraphicBufferProducer != nullptr ? 1 : 0;
                 return NO_ERROR;
             }
+            case NATIVE_WINDOW_DATASPACE: {
+                *value = static_cast<int>(mDataSpace);
+                return NO_ERROR;
+            }
         }
     }
     return mGraphicBufferProducer->query(what, value);
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index e54f147..e0d2113 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -325,8 +325,8 @@
         eventTime = event->getHistoricalEventTime(h);
         for (size_t i = 0; i < pointerCount; i++) {
             uint32_t index = pointerIndex[i];
-            positions[index].x = event->getHistoricalX(i, h);
-            positions[index].y = event->getHistoricalY(i, h);
+            positions[index].x = event->getHistoricalRawX(i, h);
+            positions[index].y = event->getHistoricalRawY(i, h);
         }
         addMovement(eventTime, idBits, positions);
     }
@@ -334,8 +334,8 @@
     eventTime = event->getEventTime();
     for (size_t i = 0; i < pointerCount; i++) {
         uint32_t index = pointerIndex[i];
-        positions[index].x = event->getX(i);
-        positions[index].y = event->getY(i);
+        positions[index].x = event->getRawX(i);
+        positions[index].y = event->getRawY(i);
     }
     addMovement(eventTime, idBits, positions);
 }
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index c6994c3..2598451 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -33,6 +33,27 @@
     return res < 0 ? res : value;
 }
 
+static bool isDataSpaceValid(ANativeWindow* window, int32_t dataSpace) {
+    bool supported = false;
+    switch (dataSpace) {
+        case HAL_DATASPACE_UNKNOWN:
+        case HAL_DATASPACE_V0_SRGB:
+            return true;
+        // These data space need wide gamut support.
+        case HAL_DATASPACE_V0_SCRGB_LINEAR:
+        case HAL_DATASPACE_V0_SCRGB:
+        case HAL_DATASPACE_DISPLAY_P3:
+            native_window_get_wide_color_support(window, &supported);
+            return supported;
+        // These data space need HDR support.
+        case HAL_DATASPACE_BT2020_PQ:
+            native_window_get_hdr_support(window, &supported);
+            return supported;
+        default:
+            return false;
+    }
+}
+
 /**************************************************************************************************
  * NDK
  **************************************************************************************************/
@@ -101,6 +122,28 @@
     return native_window_set_buffers_transform(window, transform);
 }
 
+int32_t ANativeWindow_setBuffersDataSpace(ANativeWindow* window, int32_t dataSpace) {
+    static_assert(ADATASPACE_UNKNOWN == HAL_DATASPACE_UNKNOWN);
+    static_assert(ADATASPACE_SCRGB_LINEAR == HAL_DATASPACE_V0_SCRGB_LINEAR);
+    static_assert(ADATASPACE_SRGB == HAL_DATASPACE_V0_SRGB);
+    static_assert(ADATASPACE_SCRGB == HAL_DATASPACE_V0_SCRGB);
+    static_assert(ADATASPACE_DISPLAY_P3 == HAL_DATASPACE_DISPLAY_P3);
+    static_assert(ADATASPACE_BT2020_PQ == HAL_DATASPACE_BT2020_PQ);
+
+    if (!window || !query(window, NATIVE_WINDOW_IS_VALID) ||
+            !isDataSpaceValid(window, dataSpace)) {
+        return -EINVAL;
+    }
+    return native_window_set_buffers_data_space(window,
+                                                static_cast<android_dataspace_t>(dataSpace));
+}
+
+int32_t ANativeWindow_getBuffersDataSpace(ANativeWindow* window) {
+    if (!window || !query(window, NATIVE_WINDOW_IS_VALID))
+        return -EINVAL;
+    return query(window, NATIVE_WINDOW_DATASPACE);
+}
+
 /**************************************************************************************************
  * vndk-stable
  **************************************************************************************************/
@@ -209,10 +252,6 @@
     return native_window_set_buffers_timestamp(window, timestamp);
 }
 
-int ANativeWindow_setBufferDataSpace(ANativeWindow* window, android_dataspace_t dataSpace) {
-    return native_window_set_buffers_data_space(window, dataSpace);
-}
-
 int ANativeWindow_setSharedBufferMode(ANativeWindow* window, bool sharedBufferMode) {
     return native_window_set_shared_buffer_mode(window, sharedBufferMode);
 }
diff --git a/libs/nativewindow/include/android/data_space.h b/libs/nativewindow/include/android/data_space.h
new file mode 100644
index 0000000..3ac1c58
--- /dev/null
+++ b/libs/nativewindow/include/android/data_space.h
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file data_space.h
+ */
+
+#ifndef ANDROID_DATA_SPACE_H
+#define ANDROID_DATA_SPACE_H
+
+#include <inttypes.h>
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/**
+ * ADataSpace.
+ */
+enum ADataSpace {
+    /**
+     * Default-assumption data space, when not explicitly specified.
+     *
+     * It is safest to assume the buffer is an image with sRGB primaries and
+     * encoding ranges, but the consumer and/or the producer of the data may
+     * simply be using defaults. No automatic gamma transform should be
+     * expected, except for a possible display gamma transform when drawn to a
+     * screen.
+     */
+    ADATASPACE_UNKNOWN = 0,
+
+    /**
+     * scRGB linear encoding:
+     *
+     * The red, green, and blue components are stored in extended sRGB space,
+     * but are linear, not gamma-encoded.
+     * The RGB primaries and the white point are the same as BT.709.
+     *
+     * The values are floating point.
+     * A pixel value of 1.0, 1.0, 1.0 corresponds to sRGB white (D65) at 80 nits.
+     * Values beyond the range [0.0 - 1.0] would correspond to other colors
+     * spaces and/or HDR content.
+     */
+    ADATASPACE_SCRGB_LINEAR = 406913024, // STANDARD_BT709 | TRANSFER_LINEAR | RANGE_EXTENDED
+
+    /**
+     * sRGB gamma encoding:
+     *
+     * The red, green and blue components are stored in sRGB space, and
+     * converted to linear space when read, using the SRGB transfer function
+     * for each of the R, G and B components. When written, the inverse
+     * transformation is performed.
+     *
+     * The alpha component, if present, is always stored in linear space and
+     * is left unmodified when read or written.
+     *
+     * Use full range and BT.709 standard.
+     */
+    ADATASPACE_SRGB = 142671872, // STANDARD_BT709 | TRANSFER_SRGB | RANGE_FULL
+
+    /**
+     * scRGB:
+     *
+     * The red, green, and blue components are stored in extended sRGB space,
+     * but are linear, not gamma-encoded.
+     * The RGB primaries and the white point are the same as BT.709.
+     *
+     * The values are floating point.
+     * A pixel value of 1.0, 1.0, 1.0 corresponds to sRGB white (D65) at 80 nits.
+     * Values beyond the range [0.0 - 1.0] would correspond to other colors
+     * spaces and/or HDR content.
+     */
+    ADATASPACE_SCRGB = 411107328, // STANDARD_BT709 | TRANSFER_SRGB | RANGE_EXTENDED
+
+    /**
+     * Display P3
+     *
+     * Use same primaries and white-point as DCI-P3
+     * but sRGB transfer function.
+     */
+    ADATASPACE_DISPLAY_P3 = 143261696, // STANDARD_DCI_P3 | TRANSFER_SRGB | RANGE_FULL
+
+    /**
+     * ITU-R Recommendation 2020 (BT.2020)
+     *
+     * Ultra High-definition television
+     *
+     * Use full range, SMPTE 2084 (PQ) transfer and BT2020 standard
+     */
+    ADATASPACE_BT2020_PQ = 163971072, // STANDARD_BT2020 | TRANSFER_ST2084 | RANGE_FULL
+};
+
+__END_DECLS
+
+#endif // ANDROID_DATA_SPACE_H
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index 5290dd5..f2d6f7a 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -29,6 +29,7 @@
 
 #include <sys/cdefs.h>
 
+#include <android/data_space.h>
 #include <android/hardware_buffer.h>
 #include <android/rect.h>
 
@@ -189,6 +190,33 @@
 
 #endif // __ANDROID_API__ >= __ANDROID_API_O__
 
+#if __ANDROID_API__ >= __ANDROID_API_P__
+
+/**
+ * All buffers queued after this call will be associated with the dataSpace
+ * parameter specified.
+ *
+ * dataSpace specifies additional information about the buffer.
+ * For example, it can be used to convey the color space of the image data in
+ * the buffer, or it can be used to indicate that the buffers contain depth
+ * measurement data instead of color images. The default dataSpace is 0,
+ * ADATASPACE_UNKNOWN, unless it has been overridden by the producer.
+ *
+ * \param dataSpace data space of all buffers queued after this call.
+ * \return 0 for success, -EINVAL if window is invalid or the dataspace is not
+ * supported.
+ */
+int32_t ANativeWindow_setBuffersDataSpace(ANativeWindow* window, int32_t dataSpace);
+
+/**
+ * Get the dataspace of the buffers in window.
+ * \return the dataspace of buffers in window, ADATASPACE_UNKNOWN is returned if
+ * dataspace is unknown, or -EINVAL if window is invalid.
+ */
+int32_t ANativeWindow_getBuffersDataSpace(ANativeWindow* window);
+
+#endif // __ANDROID_API__ >= __ANDROID_API_P__
+
 #ifdef __cplusplus
 };
 #endif
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 69e0951..5fa1212 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -179,6 +179,11 @@
      * with GRALLOC_USAGE_PROTECTED usage bits on.
      */
     NATIVE_WINDOW_CONSUMER_IS_PROTECTED = 19,
+
+    /*
+     * Returns data space for the buffers.
+     */
+    NATIVE_WINDOW_DATASPACE = 20,
 };
 
 /* Valid operations for the (*perform)() hook.
diff --git a/libs/nativewindow/include/vndk/window.h b/libs/nativewindow/include/vndk/window.h
index a7b340a..995ba44 100644
--- a/libs/nativewindow/include/vndk/window.h
+++ b/libs/nativewindow/include/vndk/window.h
@@ -306,20 +306,6 @@
 
 
 /*
- * All buffers queued after this call will be associated with the dataSpace
- * parameter specified.
- *
- * dataSpace specifies additional information about the buffer that's dependent
- * on the buffer format and the endpoints. For example, it can be used to convey
- * the color space of the image data in the buffer, or it can be used to
- * indicate that the buffers contain depth measurement data instead of color
- * images.  The default dataSpace is 0, HAL_DATASPACE_UNKNOWN, unless it has been
- * overridden by the consumer.
- */
-int ANativeWindow_setBufferDataSpace(ANativeWindow* window, android_dataspace_t dataSpace);
-
-
-/*
  * Enable/disable shared buffer mode
  */
 int ANativeWindow_setSharedBufferMode(ANativeWindow* window, bool sharedBufferMode);
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index 105d01b..d2ba971 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -15,6 +15,7 @@
     ANativeWindow_acquire;
     ANativeWindow_cancelBuffer; # vndk
     ANativeWindow_dequeueBuffer; # vndk
+    ANativeWindow_getBuffersDataSpace; # introduced=28
     ANativeWindow_getFormat;
     ANativeWindow_getHeight;
     ANativeWindow_getWidth;
@@ -25,7 +26,7 @@
     ANativeWindow_release;
     ANativeWindow_setAutoRefresh; # vndk
     ANativeWindow_setBufferCount; # vndk
-    ANativeWindow_setBufferDataSpace; # vndk
+    ANativeWindow_setBuffersDataSpace; # introduced=28
     ANativeWindow_setBuffersDimensions; # vndk
     ANativeWindow_setBuffersFormat; # vndk
     ANativeWindow_setBuffersGeometry;
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index b53c563..36da084 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -513,6 +513,12 @@
 
 bool Region::validate(const Region& reg, const char* name, bool silent)
 {
+    if (reg.mStorage.isEmpty()) {
+        ALOGE_IF(!silent, "%s: mStorage is empty, which is never valid", name);
+        // return immediately as the code below assumes mStorage is non-empty
+        return false;
+    }
+
     bool result = true;
     const_iterator cur = reg.begin();
     const_iterator const tail = reg.end();
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index d655d69..be8a721 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -244,7 +244,7 @@
   // Standalones only create the composer client once and then use SetPowerMode
   // to control the screen on pause/resume.
   if (!is_standalone_device_ || !composer_) {
-    composer_.reset(new Hwc2::Composer("default"));
+    composer_.reset(new Hwc2::impl::Composer("default"));
     composer_callback_ = new ComposerCallback;
     composer_->registerCallback(composer_callback_);
     LOG_ALWAYS_FATAL_IF(!composer_callback_->HasDisplayId(),
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 4d4c9fc..3dbc136 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -200,7 +200,7 @@
 
     bool blackOutLayer = isProtected() || (isSecure() && !renderArea.isSecure());
 
-    RenderEngine& engine(mFlinger->getRenderEngine());
+    auto& engine(mFlinger->getRenderEngine());
 
     if (!blackOutLayer) {
         // TODO: we could be more subtle with isFixedSize()
@@ -817,7 +817,7 @@
     texCoords[2] = vec2(right, 1.0f - bottom);
     texCoords[3] = vec2(right, 1.0f - top);
 
-    RenderEngine& engine(mFlinger->getRenderEngine());
+    auto& engine(mFlinger->getRenderEngine());
     engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */,
                               getColor());
     engine.setSourceDataSpace(mCurrentState.dataSpace);
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 4d9b43f..46ec0e3 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -23,6 +23,7 @@
 
 #include "DispSync.h"
 #include "Layer.h"
+#include "RenderEngine/Image.h"
 #include "RenderEngine/RenderEngine.h"
 
 #include <inttypes.h>
@@ -56,8 +57,8 @@
 
 static const mat4 mtxIdentity;
 
-BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, RenderEngine& engine,
-                                         uint32_t tex, Layer* layer)
+BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq,
+                                         RE::RenderEngine& engine, uint32_t tex, Layer* layer)
       : ConsumerBase(bq, false),
         mCurrentCrop(Rect::EMPTY_RECT),
         mCurrentTransform(0),
@@ -359,7 +360,7 @@
 
     if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureImage == nullptr) {
         BLC_LOGE("bindTextureImage: no currently-bound texture");
-        mRE.bindExternalTextureImage(mTexName, RE::Image(mRE));
+        mRE.bindExternalTextureImage(mTexName, *mRE.createImage());
         return NO_INIT;
     }
 
@@ -367,7 +368,7 @@
     status_t err = mCurrentTextureImage->createIfNeeded(imageCrop);
     if (err != NO_ERROR) {
         BLC_LOGW("bindTextureImage: can't create image on slot=%d", mCurrentTexture);
-        mRE.bindExternalTextureImage(mTexName, RE::Image(mRE));
+        mRE.bindExternalTextureImage(mTexName, *mRE.createImage());
         return UNKNOWN_ERROR;
     }
 
@@ -604,13 +605,15 @@
     ConsumerBase::dumpLocked(result, prefix);
 }
 
-BufferLayerConsumer::Image::Image(sp<GraphicBuffer> graphicBuffer, const RenderEngine& engine)
+BufferLayerConsumer::Image::Image(sp<GraphicBuffer> graphicBuffer, RE::RenderEngine& engine)
       : mGraphicBuffer(graphicBuffer),
-        mImage{engine},
+        mImage{engine.createImage()},
         mCreated(false),
         mCropWidth(0),
         mCropHeight(0) {}
 
+BufferLayerConsumer::Image::~Image() = default;
+
 status_t BufferLayerConsumer::Image::createIfNeeded(const Rect& imageCrop) {
     const int32_t cropWidth = imageCrop.width();
     const int32_t cropHeight = imageCrop.height();
@@ -618,9 +621,9 @@
         return OK;
     }
 
-    mCreated = mImage.setNativeWindowBuffer(mGraphicBuffer->getNativeBuffer(),
-                                            mGraphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED,
-                                            cropWidth, cropHeight);
+    mCreated = mImage->setNativeWindowBuffer(mGraphicBuffer->getNativeBuffer(),
+                                             mGraphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED,
+                                             cropWidth, cropHeight);
     if (mCreated) {
         mCropWidth = cropWidth;
         mCropHeight = cropHeight;
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index a0272b3..11048d8 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -17,8 +17,6 @@
 #ifndef ANDROID_BUFFERLAYERCONSUMER_H
 #define ANDROID_BUFFERLAYERCONSUMER_H
 
-#include "RenderEngine/Image.h"
-
 #include <gui/BufferQueueDefs.h>
 #include <gui/ConsumerBase.h>
 #include <gui/HdrMetadata.h>
@@ -36,9 +34,13 @@
 
 class DispSync;
 class Layer;
-class RenderEngine;
 class String8;
 
+namespace RE {
+class RenderEngine;
+class Image;
+} // namespace RE
+
 /*
  * BufferLayerConsumer consumes buffers of graphics data from a BufferQueue,
  * and makes them available to RenderEngine as a texture.
@@ -70,8 +72,8 @@
     // BufferLayerConsumer constructs a new BufferLayerConsumer object.  The
     // tex parameter indicates the name of the RenderEngine texture to which
     // images are to be streamed.
-    BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, RenderEngine& engine, uint32_t tex,
-                        Layer* layer);
+    BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, RE::RenderEngine& engine,
+                        uint32_t tex, Layer* layer);
 
     // Sets the contents changed listener. This should be used instead of
     // ConsumerBase::setFrameAvailableListener().
@@ -220,7 +222,7 @@
     // also only creating new RE::Images from buffers when required.
     class Image : public LightRefBase<Image> {
     public:
-        Image(sp<GraphicBuffer> graphicBuffer, const RenderEngine& engine);
+        Image(sp<GraphicBuffer> graphicBuffer, RE::RenderEngine& engine);
 
         Image(const Image& rhs) = delete;
         Image& operator=(const Image& rhs) = delete;
@@ -234,18 +236,18 @@
             return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle;
         }
 
-        const RE::Image& image() const { return mImage; }
+        const RE::Image& image() const { return *mImage; }
 
     private:
         // Only allow instantiation using ref counting.
         friend class LightRefBase<Image>;
-        virtual ~Image() = default;
+        virtual ~Image();
 
         // mGraphicBuffer is the buffer that was used to create this image.
         sp<GraphicBuffer> mGraphicBuffer;
 
         // mImage is the image created from mGraphicBuffer.
-        RE::Image mImage;
+        std::unique_ptr<RE::Image> mImage;
         bool mCreated;
         int32_t mCropWidth;
         int32_t mCropHeight;
@@ -349,7 +351,7 @@
     // setFilteringEnabled().
     bool mFilteringEnabled;
 
-    RenderEngine& mRE;
+    RE::RenderEngine& mRE;
 
     // mTexName is the name of the RenderEngine texture to which streamed
     // images will be bound when bindTexImage is called. It is set at
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index 10e7790..80a90a7 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -48,7 +48,7 @@
     if (s.color.a > 0) {
         Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2);
         computeGeometry(renderArea, mesh, useIdentityTransform);
-        RenderEngine& engine(mFlinger->getRenderEngine());
+        auto& engine(mFlinger->getRenderEngine());
         engine.setupLayerBlending(getPremultipledAlpha(), false /* opaque */,
                                   true /* disableTexture */, s.color);
         engine.drawMesh(mesh);
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index cf70529..d40666e 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -84,7 +84,7 @@
       mHwcDisplayId(hwcId),
       mDisplayToken(displayToken),
       mDisplaySurface(displaySurface),
-      mSurface{flinger->getRenderEngine()},
+      mSurface{flinger->getRenderEngine().createSurface()},
       mDisplayWidth(),
       mDisplayHeight(),
       mPageFlipCount(),
@@ -106,11 +106,11 @@
     /*
      * Create our display's surface
      */
-    mSurface.setCritical(mType == DisplayDevice::DISPLAY_PRIMARY);
-    mSurface.setAsync(mType >= DisplayDevice::DISPLAY_VIRTUAL);
-    mSurface.setNativeWindow(window);
-    mDisplayWidth = mSurface.queryWidth();
-    mDisplayHeight = mSurface.queryHeight();
+    mSurface->setCritical(mType == DisplayDevice::DISPLAY_PRIMARY);
+    mSurface->setAsync(mType >= DisplayDevice::DISPLAY_VIRTUAL);
+    mSurface->setNativeWindow(window);
+    mDisplayWidth = mSurface->queryWidth();
+    mDisplayHeight = mSurface->queryHeight();
 
     // Make sure that composition can never be stalled by a virtual display
     // consumer that isn't processing buffers fast enough. We have to do this
@@ -207,7 +207,7 @@
 
 void DisplayDevice::swapBuffers(HWComposer& hwc) const {
     if (hwc.hasClientComposition(mHwcDisplayId) || hwc.hasFlipClientTargetRequest(mHwcDisplayId)) {
-        mSurface.swapBuffers();
+        mSurface->swapBuffers();
     }
 
     status_t result = mDisplaySurface->advanceFrame();
@@ -222,7 +222,7 @@
 }
 
 bool DisplayDevice::makeCurrent() const {
-    bool success = mFlinger->getRenderEngine().setCurrentSurface(mSurface);
+    bool success = mFlinger->getRenderEngine().setCurrentSurface(*mSurface);
     setViewportAndProjection();
     return success;
 }
@@ -360,14 +360,14 @@
 void DisplayDevice::setDisplaySize(const int newWidth, const int newHeight) {
     dirtyRegion.set(getBounds());
 
-    mSurface.setNativeWindow(nullptr);
+    mSurface->setNativeWindow(nullptr);
 
     mDisplaySurface->resizeBuffers(newWidth, newHeight);
 
     ANativeWindow* const window = mNativeWindow.get();
-    mSurface.setNativeWindow(window);
-    mDisplayWidth = mSurface.queryWidth();
-    mDisplayHeight = mSurface.queryHeight();
+    mSurface->setNativeWindow(window);
+    mDisplayWidth = mSurface->queryWidth();
+    mDisplayHeight = mSurface->queryHeight();
 
     LOG_FATAL_IF(mDisplayWidth != newWidth,
                 "Unable to set new width to %d", newWidth);
@@ -474,9 +474,9 @@
                         "(%d:%d:%d:%d), orient=%2d (type=%08x), "
                         "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n",
                         mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight, window,
-                        mSurface.queryRedSize(), mSurface.queryGreenSize(), mSurface.queryBlueSize(),
-                        mSurface.queryAlphaSize(), mOrientation, tr.getType(),
-                        getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
+                        mSurface->queryRedSize(), mSurface->queryGreenSize(),
+                        mSurface->queryBlueSize(), mSurface->queryAlphaSize(), mOrientation,
+                        tr.getType(), getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
                         mVisibleLayersSortedByZ.size());
     result.appendFormat("   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
                         "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index a470670..d5ed15f 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -187,7 +187,7 @@
     sp<ANativeWindow> mNativeWindow;
     sp<DisplaySurface> mDisplaySurface;
 
-    RE::Surface     mSurface;
+    std::unique_ptr<RE::Surface> mSurface;
     int             mDisplayWidth;
     int             mDisplayHeight;
     mutable uint32_t mPageFlipCount;
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index c707e3c..03b714f 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -31,6 +31,8 @@
 
 namespace Hwc2 {
 
+Composer::~Composer() = default;
+
 namespace {
 
 class BufferHandle {
@@ -103,6 +105,8 @@
 
 } // anonymous namespace
 
+namespace impl {
+
 Composer::CommandWriter::CommandWriter(uint32_t initialMaxSize)
     : CommandWriterBase(initialMaxSize) {}
 
@@ -186,6 +190,8 @@
     }
 }
 
+Composer::~Composer() = default;
+
 std::vector<IComposer::Capability> Composer::getCapabilities()
 {
     std::vector<IComposer::Capability> capabilities;
@@ -1118,6 +1124,8 @@
     *state = data.presentOrValidateState;
 }
 
+} // namespace impl
+
 } // namespace Hwc2
 
 } // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 3d9993e..77675fb 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -26,6 +26,7 @@
 #include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
 #include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
+#include <ui/GraphicBuffer.h>
 #include <utils/StrongPointer.h>
 
 namespace android {
@@ -58,6 +59,118 @@
 using android::hardware::hidl_vec;
 using android::hardware::hidl_handle;
 
+class Composer {
+public:
+    virtual ~Composer() = 0;
+
+    virtual std::vector<IComposer::Capability> getCapabilities() = 0;
+    virtual std::string dumpDebugInfo() = 0;
+
+    virtual void registerCallback(const sp<IComposerCallback>& callback) = 0;
+
+    // Returns true if the connected composer service is running in a remote
+    // process, false otherwise. This will return false if the service is
+    // configured in passthrough mode, for example.
+    virtual bool isRemote() = 0;
+
+    // Reset all pending commands in the command buffer. Useful if you want to
+    // skip a frame but have already queued some commands.
+    virtual void resetCommands() = 0;
+
+    // Explicitly flush all pending commands in the command buffer.
+    virtual Error executeCommands() = 0;
+
+    virtual uint32_t getMaxVirtualDisplayCount() = 0;
+    virtual bool isUsingVrComposer() const = 0;
+    virtual Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format,
+                                       Display* outDisplay) = 0;
+    virtual Error destroyVirtualDisplay(Display display) = 0;
+
+    virtual Error acceptDisplayChanges(Display display) = 0;
+
+    virtual Error createLayer(Display display, Layer* outLayer) = 0;
+    virtual Error destroyLayer(Display display, Layer layer) = 0;
+
+    virtual Error getActiveConfig(Display display, Config* outConfig) = 0;
+    virtual Error getChangedCompositionTypes(
+            Display display, std::vector<Layer>* outLayers,
+            std::vector<IComposerClient::Composition>* outTypes) = 0;
+    virtual Error getColorModes(Display display, std::vector<ColorMode>* outModes) = 0;
+    virtual Error getDisplayAttribute(Display display, Config config,
+                                      IComposerClient::Attribute attribute, int32_t* outValue) = 0;
+    virtual Error getDisplayConfigs(Display display, std::vector<Config>* outConfigs) = 0;
+    virtual Error getDisplayName(Display display, std::string* outName) = 0;
+
+    virtual Error getDisplayRequests(Display display, uint32_t* outDisplayRequestMask,
+                                     std::vector<Layer>* outLayers,
+                                     std::vector<uint32_t>* outLayerRequestMasks) = 0;
+
+    virtual Error getDisplayType(Display display, IComposerClient::DisplayType* outType) = 0;
+    virtual Error getDozeSupport(Display display, bool* outSupport) = 0;
+    virtual Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes,
+                                     float* outMaxLuminance, float* outMaxAverageLuminance,
+                                     float* outMinLuminance) = 0;
+
+    virtual Error getReleaseFences(Display display, std::vector<Layer>* outLayers,
+                                   std::vector<int>* outReleaseFences) = 0;
+
+    virtual Error presentDisplay(Display display, int* outPresentFence) = 0;
+
+    virtual Error setActiveConfig(Display display, Config config) = 0;
+
+    /*
+     * The composer caches client targets internally.  When target is nullptr,
+     * the composer uses slot to look up the client target from its cache.
+     * When target is not nullptr, the cache is updated with the new target.
+     */
+    virtual Error setClientTarget(Display display, uint32_t slot, const sp<GraphicBuffer>& target,
+                                  int acquireFence, Dataspace dataspace,
+                                  const std::vector<IComposerClient::Rect>& damage) = 0;
+    virtual Error setColorMode(Display display, ColorMode mode) = 0;
+    virtual Error setColorTransform(Display display, const float* matrix, ColorTransform hint) = 0;
+    virtual Error setOutputBuffer(Display display, const native_handle_t* buffer,
+                                  int releaseFence) = 0;
+    virtual Error setPowerMode(Display display, IComposerClient::PowerMode mode) = 0;
+    virtual Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled) = 0;
+
+    virtual Error setClientTargetSlotCount(Display display) = 0;
+
+    virtual Error validateDisplay(Display display, uint32_t* outNumTypes,
+                                  uint32_t* outNumRequests) = 0;
+
+    virtual Error presentOrValidateDisplay(Display display, uint32_t* outNumTypes,
+                                           uint32_t* outNumRequests, int* outPresentFence,
+                                           uint32_t* state) = 0;
+
+    virtual Error setCursorPosition(Display display, Layer layer, int32_t x, int32_t y) = 0;
+    /* see setClientTarget for the purpose of slot */
+    virtual Error setLayerBuffer(Display display, Layer layer, uint32_t slot,
+                                 const sp<GraphicBuffer>& buffer, int acquireFence) = 0;
+    virtual Error setLayerSurfaceDamage(Display display, Layer layer,
+                                        const std::vector<IComposerClient::Rect>& damage) = 0;
+    virtual Error setLayerBlendMode(Display display, Layer layer,
+                                    IComposerClient::BlendMode mode) = 0;
+    virtual Error setLayerColor(Display display, Layer layer,
+                                const IComposerClient::Color& color) = 0;
+    virtual Error setLayerCompositionType(Display display, Layer layer,
+                                          IComposerClient::Composition type) = 0;
+    virtual Error setLayerDataspace(Display display, Layer layer, Dataspace dataspace) = 0;
+    virtual Error setLayerDisplayFrame(Display display, Layer layer,
+                                       const IComposerClient::Rect& frame) = 0;
+    virtual Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) = 0;
+    virtual Error setLayerSidebandStream(Display display, Layer layer,
+                                         const native_handle_t* stream) = 0;
+    virtual Error setLayerSourceCrop(Display display, Layer layer,
+                                     const IComposerClient::FRect& crop) = 0;
+    virtual Error setLayerTransform(Display display, Layer layer, Transform transform) = 0;
+    virtual Error setLayerVisibleRegion(Display display, Layer layer,
+                                        const std::vector<IComposerClient::Rect>& visible) = 0;
+    virtual Error setLayerZOrder(Display display, Layer layer, uint32_t z) = 0;
+    virtual Error setLayerInfo(Display display, Layer layer, uint32_t type, uint32_t appId) = 0;
+};
+
+namespace impl {
+
 class CommandReader : public CommandReaderBase {
 public:
     ~CommandReader();
@@ -134,123 +247,111 @@
 };
 
 // Composer is a wrapper to IComposer, a proxy to server-side composer.
-class Composer {
+class Composer final : public Hwc2::Composer {
 public:
     Composer(const std::string& serviceName);
+    ~Composer() override;
 
-    std::vector<IComposer::Capability> getCapabilities();
-    std::string dumpDebugInfo();
+    std::vector<IComposer::Capability> getCapabilities() override;
+    std::string dumpDebugInfo() override;
 
-    void registerCallback(const sp<IComposerCallback>& callback);
+    void registerCallback(const sp<IComposerCallback>& callback) override;
 
     // Returns true if the connected composer service is running in a remote
     // process, false otherwise. This will return false if the service is
     // configured in passthrough mode, for example.
-    bool isRemote();
+    bool isRemote() override;
 
     // Reset all pending commands in the command buffer. Useful if you want to
     // skip a frame but have already queued some commands.
-    void resetCommands();
+    void resetCommands() override;
 
     // Explicitly flush all pending commands in the command buffer.
-    Error executeCommands();
+    Error executeCommands() override;
 
-    uint32_t getMaxVirtualDisplayCount();
-    bool isUsingVrComposer() const { return mIsUsingVrComposer; }
-    Error createVirtualDisplay(uint32_t width, uint32_t height,
-            PixelFormat* format, Display* outDisplay);
-    Error destroyVirtualDisplay(Display display);
+    uint32_t getMaxVirtualDisplayCount() override;
+    bool isUsingVrComposer() const override { return mIsUsingVrComposer; }
+    Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format,
+                               Display* outDisplay) override;
+    Error destroyVirtualDisplay(Display display) override;
 
-    Error acceptDisplayChanges(Display display);
+    Error acceptDisplayChanges(Display display) override;
 
-    Error createLayer(Display display, Layer* outLayer);
-    Error destroyLayer(Display display, Layer layer);
+    Error createLayer(Display display, Layer* outLayer) override;
+    Error destroyLayer(Display display, Layer layer) override;
 
-    Error getActiveConfig(Display display, Config* outConfig);
-    Error getChangedCompositionTypes(Display display,
-            std::vector<Layer>* outLayers,
-            std::vector<IComposerClient::Composition>* outTypes);
-    Error getColorModes(Display display, std::vector<ColorMode>* outModes);
-    Error getDisplayAttribute(Display display, Config config,
-            IComposerClient::Attribute attribute, int32_t* outValue);
+    Error getActiveConfig(Display display, Config* outConfig) override;
+    Error getChangedCompositionTypes(Display display, std::vector<Layer>* outLayers,
+                                     std::vector<IComposerClient::Composition>* outTypes) override;
+    Error getColorModes(Display display, std::vector<ColorMode>* outModes) override;
+    Error getDisplayAttribute(Display display, Config config, IComposerClient::Attribute attribute,
+                              int32_t* outValue) override;
     Error getDisplayConfigs(Display display, std::vector<Config>* outConfigs);
-    Error getDisplayName(Display display, std::string* outName);
+    Error getDisplayName(Display display, std::string* outName) override;
 
     Error getDisplayRequests(Display display, uint32_t* outDisplayRequestMask,
-            std::vector<Layer>* outLayers,
-            std::vector<uint32_t>* outLayerRequestMasks);
+                             std::vector<Layer>* outLayers,
+                             std::vector<uint32_t>* outLayerRequestMasks) override;
 
-    Error getDisplayType(Display display,
-            IComposerClient::DisplayType* outType);
-    Error getDozeSupport(Display display, bool* outSupport);
-    Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes,
-            float* outMaxLuminance, float* outMaxAverageLuminance,
-            float* outMinLuminance);
+    Error getDisplayType(Display display, IComposerClient::DisplayType* outType) override;
+    Error getDozeSupport(Display display, bool* outSupport) override;
+    Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes, float* outMaxLuminance,
+                             float* outMaxAverageLuminance, float* outMinLuminance) override;
 
     Error getReleaseFences(Display display, std::vector<Layer>* outLayers,
-            std::vector<int>* outReleaseFences);
+                           std::vector<int>* outReleaseFences) override;
 
-    Error presentDisplay(Display display, int* outPresentFence);
+    Error presentDisplay(Display display, int* outPresentFence) override;
 
-    Error setActiveConfig(Display display, Config config);
+    Error setActiveConfig(Display display, Config config) override;
 
     /*
      * The composer caches client targets internally.  When target is nullptr,
      * the composer uses slot to look up the client target from its cache.
      * When target is not nullptr, the cache is updated with the new target.
      */
-    Error setClientTarget(Display display, uint32_t slot,
-            const sp<GraphicBuffer>& target,
-            int acquireFence, Dataspace dataspace,
-            const std::vector<IComposerClient::Rect>& damage);
-    Error setColorMode(Display display, ColorMode mode);
-    Error setColorTransform(Display display, const float* matrix,
-            ColorTransform hint);
+    Error setClientTarget(Display display, uint32_t slot, const sp<GraphicBuffer>& target,
+                          int acquireFence, Dataspace dataspace,
+                          const std::vector<IComposerClient::Rect>& damage) override;
+    Error setColorMode(Display display, ColorMode mode) override;
+    Error setColorTransform(Display display, const float* matrix, ColorTransform hint) override;
     Error setOutputBuffer(Display display, const native_handle_t* buffer,
-            int releaseFence);
-    Error setPowerMode(Display display, IComposerClient::PowerMode mode);
-    Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled);
+                          int releaseFence) override;
+    Error setPowerMode(Display display, IComposerClient::PowerMode mode) override;
+    Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled) override;
 
-    Error setClientTargetSlotCount(Display display);
+    Error setClientTargetSlotCount(Display display) override;
 
     Error validateDisplay(Display display, uint32_t* outNumTypes,
-            uint32_t* outNumRequests);
+                          uint32_t* outNumRequests) override;
 
-    Error presentOrValidateDisplay(Display display, uint32_t* outNumTypes,
-                                   uint32_t* outNumRequests,
-                                   int* outPresentFence,
-                                   uint32_t* state);
+    Error presentOrValidateDisplay(Display display, uint32_t* outNumTypes, uint32_t* outNumRequests,
+                                   int* outPresentFence, uint32_t* state) override;
 
-    Error setCursorPosition(Display display, Layer layer,
-            int32_t x, int32_t y);
+    Error setCursorPosition(Display display, Layer layer, int32_t x, int32_t y) override;
     /* see setClientTarget for the purpose of slot */
     Error setLayerBuffer(Display display, Layer layer, uint32_t slot,
-            const sp<GraphicBuffer>& buffer, int acquireFence);
+                         const sp<GraphicBuffer>& buffer, int acquireFence) override;
     Error setLayerSurfaceDamage(Display display, Layer layer,
-            const std::vector<IComposerClient::Rect>& damage);
-    Error setLayerBlendMode(Display display, Layer layer,
-            IComposerClient::BlendMode mode);
-    Error setLayerColor(Display display, Layer layer,
-            const IComposerClient::Color& color);
+                                const std::vector<IComposerClient::Rect>& damage) override;
+    Error setLayerBlendMode(Display display, Layer layer, IComposerClient::BlendMode mode) override;
+    Error setLayerColor(Display display, Layer layer, const IComposerClient::Color& color) override;
     Error setLayerCompositionType(Display display, Layer layer,
-            IComposerClient::Composition type);
-    Error setLayerDataspace(Display display, Layer layer,
-            Dataspace dataspace);
+                                  IComposerClient::Composition type) override;
+    Error setLayerDataspace(Display display, Layer layer, Dataspace dataspace) override;
     Error setLayerDisplayFrame(Display display, Layer layer,
-            const IComposerClient::Rect& frame);
-    Error setLayerPlaneAlpha(Display display, Layer layer,
-            float alpha);
+                               const IComposerClient::Rect& frame) override;
+    Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) override;
     Error setLayerSidebandStream(Display display, Layer layer,
-            const native_handle_t* stream);
+                                 const native_handle_t* stream) override;
     Error setLayerSourceCrop(Display display, Layer layer,
-            const IComposerClient::FRect& crop);
-    Error setLayerTransform(Display display, Layer layer,
-            Transform transform);
+                             const IComposerClient::FRect& crop) override;
+    Error setLayerTransform(Display display, Layer layer, Transform transform) override;
     Error setLayerVisibleRegion(Display display, Layer layer,
-            const std::vector<IComposerClient::Rect>& visible);
-    Error setLayerZOrder(Display display, Layer layer, uint32_t z);
-    Error setLayerInfo(Display display, Layer layer, uint32_t type,
-                       uint32_t appId);
+                                const std::vector<IComposerClient::Rect>& visible) override;
+    Error setLayerZOrder(Display display, Layer layer, uint32_t z) override;
+    Error setLayerInfo(Display display, Layer layer, uint32_t type, uint32_t appId) override;
+
 private:
     class CommandWriter : public CommandWriterBase {
     public:
@@ -287,6 +388,8 @@
     const bool mIsUsingVrComposer;
 };
 
+} // namespace impl
+
 } // namespace Hwc2
 
 } // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 070b691..bcba35f 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -84,12 +84,7 @@
 
 // Device methods
 
-Device::Device(const std::string& serviceName)
-  : mComposer(std::make_unique<Hwc2::Composer>(serviceName)),
-    mCapabilities(),
-    mDisplays(),
-    mRegisteredCallback(false)
-{
+Device::Device(std::unique_ptr<android::Hwc2::Composer> composer) : mComposer(std::move(composer)) {
     loadCapabilities();
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 7b98b3e..aade4e0 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -78,9 +78,7 @@
 class Device
 {
 public:
-    // Service name is expected to be 'default' or 'vr' for normal use.
-    // 'vr' will slightly modify the behavior of the mComposer.
-    Device(const std::string& serviceName);
+    explicit Device(std::unique_ptr<android::Hwc2::Composer> composer);
 
     void registerCallback(ComposerCallback* callback, int32_t sequenceId);
 
@@ -119,7 +117,7 @@
     std::unique_ptr<android::Hwc2::Composer> mComposer;
     std::unordered_set<Capability> mCapabilities;
     std::unordered_map<hwc2_display_t, std::unique_ptr<Display>> mDisplays;
-    bool mRegisteredCallback;
+    bool mRegisteredCallback = false;
 };
 
 // Convenience C++ class to access hwc2_device_t Display functions directly.
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 7eb3998..2cafd8e 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -59,25 +59,10 @@
 
 // ---------------------------------------------------------------------------
 
-HWComposer::HWComposer(const std::string& serviceName)
-    : mHwcDevice(),
-      mDisplayData(2),
-      mFreeDisplaySlots(),
-      mHwcDisplaySlots(),
-      mCBContext(),
-      mVSyncCounts(),
-      mRemainingHwcVirtualDisplays(0)
-{
-    for (size_t i=0 ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {
-        mLastHwVSync[i] = 0;
-        mVSyncCounts[i] = 0;
-    }
+HWComposer::HWComposer(std::unique_ptr<android::Hwc2::Composer> composer)
+      : mHwcDevice(std::make_unique<HWC2::Device>(std::move(composer))) {}
 
-    mHwcDevice = std::make_unique<HWC2::Device>(serviceName);
-    mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
-}
-
-HWComposer::~HWComposer() {}
+HWComposer::~HWComposer() = default;
 
 void HWComposer::registerCallback(HWC2::ComposerCallback* callback,
                                   int32_t sequenceId) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 2e4f5d4..abb0fcb 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -59,12 +59,14 @@
 class Region;
 class String8;
 
+namespace Hwc2 {
+class Composer;
+} // namespace Hwc2
+
 class HWComposer
 {
 public:
-    // Uses the named composer service. Valid choices for normal use
-    // are 'default' and 'vr'.
-    HWComposer(const std::string& serviceName);
+    explicit HWComposer(std::unique_ptr<android::Hwc2::Composer> composer);
 
     ~HWComposer();
 
@@ -199,19 +201,20 @@
     };
 
     std::unique_ptr<HWC2::Device>   mHwcDevice;
-    std::vector<DisplayData>        mDisplayData;
+    std::vector<DisplayData> mDisplayData{HWC_NUM_PHYSICAL_DISPLAY_TYPES};
     std::set<size_t>                mFreeDisplaySlots;
     std::unordered_map<hwc2_display_t, int32_t> mHwcDisplaySlots;
     // protect mDisplayData from races between prepare and dump
     mutable Mutex mDisplayLock;
 
-    cb_context*                     mCBContext;
-    size_t                          mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
-    uint32_t                        mRemainingHwcVirtualDisplays;
+    cb_context* mCBContext = nullptr;
+    size_t mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES]{0, 0};
+    uint32_t mRemainingHwcVirtualDisplays{mHwcDevice->getMaxVirtualDisplayCount()};
 
     // protected by mLock
     mutable Mutex mLock;
-    mutable std::unordered_map<int32_t, nsecs_t> mLastHwVSync;
+    mutable std::unordered_map<int32_t, nsecs_t> mLastHwVSync{
+            {{HWC_DISPLAY_PRIMARY, 0}, {HWC_DISPLAY_EXTERNAL, 0}}};
 
     // thread-safe
     mutable Mutex mVsyncLock;
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 53d95e2..90aab50 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -43,6 +43,10 @@
 
 // ---------------------------------------------------------------------------
 
+EventThread::~EventThread() = default;
+
+namespace impl {
+
 EventThread::EventThread(VSyncSource* src, SurfaceFlinger& flinger, bool interceptVSyncs,
                          const char* threadName)
       : mVSyncSource(src), mFlinger(flinger), mInterceptVSyncs(interceptVSyncs) {
@@ -84,7 +88,7 @@
     mVSyncSource->setPhaseOffset(phaseOffset);
 }
 
-sp<EventThread::Connection> EventThread::createEventConnection() const {
+sp<BnDisplayEventConnection> EventThread::createEventConnection() const {
     return new Connection(const_cast<EventThread*>(this));
 }
 
@@ -404,4 +408,5 @@
 
 // ---------------------------------------------------------------------------
 
+} // namespace impl
 } // namespace android
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 9ae8fb2..708806a 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -56,7 +56,29 @@
     virtual void setPhaseOffset(nsecs_t phaseOffset) = 0;
 };
 
-class EventThread : private VSyncSource::Callback {
+class EventThread {
+public:
+    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(int type, 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);
@@ -82,24 +104,24 @@
                 const char* threadName);
     ~EventThread();
 
-    sp<Connection> createEventConnection() const;
+    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();
+    void onScreenReleased() override;
 
     // called after the screen is turned on from main thread
-    void onScreenAcquired();
+    void onScreenAcquired() override;
 
     // called when receiving a hotplug event
-    void onHotplugReceived(int type, bool connected);
+    void onHotplugReceived(int type, bool connected) override;
 
-    void dump(String8& result) const;
+    void dump(String8& result) const override;
 
-    void setPhaseOffset(nsecs_t phaseOffset);
+    void setPhaseOffset(nsecs_t phaseOffset) override;
 
 private:
     void threadMain();
@@ -139,4 +161,5 @@
 
 // ---------------------------------------------------------------------------
 
-}; // namespace android
+} // namespace impl
+} // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 067a09f..78dd40b 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -719,7 +719,7 @@
 
 void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue,
                             float alpha) const {
-    RenderEngine& engine(mFlinger->getRenderEngine());
+    auto& engine(mFlinger->getRenderEngine());
     computeGeometry(renderArea, getBE().mMesh, false);
     engine.setupFillWithColor(red, green, blue, alpha);
     engine.drawMesh(getBE().mMesh);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index c63399e..3671a2b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -90,7 +90,7 @@
         hwc_color_t color;
     } hwc;
     struct {
-        RenderEngine* renderEngine;
+        RE::RenderEngine* renderEngine;
         Mesh* mesh;
     } renderEngine;
 };
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 34d968d..9ecf8ce 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -105,6 +105,8 @@
 
 // ---------------------------------------------------------------------------
 namespace android {
+namespace RE {
+namespace impl {
 // ---------------------------------------------------------------------------
 
 GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags)
@@ -379,7 +381,9 @@
 }
 
 // ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace impl
+} // namespace RE
+} // namespace android
 // ---------------------------------------------------------------------------
 
 #if defined(__gl_h_)
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index f3af547..6e86ea2 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -35,6 +35,9 @@
 class Mesh;
 class Texture;
 
+namespace RE {
+namespace impl {
+
 class GLES20RenderEngine : public RenderEngine {
     GLuint mProtectedTexName;
     GLint mMaxViewportDims[2];
@@ -105,7 +108,9 @@
 };
 
 // ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace impl
+} // namespace RE
+} // namespace android
 // ---------------------------------------------------------------------------
 
 #endif /* SF_GLES20RENDERENGINE_H_ */
diff --git a/services/surfaceflinger/RenderEngine/Image.cpp b/services/surfaceflinger/RenderEngine/Image.cpp
index 1f8e75a..0d06422 100644
--- a/services/surfaceflinger/RenderEngine/Image.cpp
+++ b/services/surfaceflinger/RenderEngine/Image.cpp
@@ -26,6 +26,10 @@
 namespace android {
 namespace RE {
 
+Image::~Image() = default;
+
+namespace impl {
+
 Image::Image(const RenderEngine& engine) : mEGLDisplay(engine.getEGLDisplay()) {}
 
 Image::~Image() {
@@ -83,5 +87,6 @@
     return true;
 }
 
+} // namespace impl
 } // namespace RE
 } // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Image.h b/services/surfaceflinger/RenderEngine/Image.h
index f55aa59..1ae7e09 100644
--- a/services/surfaceflinger/RenderEngine/Image.h
+++ b/services/surfaceflinger/RenderEngine/Image.h
@@ -24,30 +24,39 @@
 struct ANativeWindowBuffer;
 
 namespace android {
-
-class RenderEngine;
-
 namespace RE {
 
 class Image {
 public:
-    Image(const RenderEngine& engine);
-    ~Image();
+    virtual ~Image() = 0;
+    virtual bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected,
+                                       int32_t cropWidth, int32_t cropHeight) = 0;
+};
+
+namespace impl {
+
+class RenderEngine;
+
+class Image : public RE::Image {
+public:
+    explicit Image(const RenderEngine& engine);
+    ~Image() override;
 
     Image(const Image&) = delete;
     Image& operator=(const Image&) = delete;
 
     bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected, int32_t cropWidth,
-                               int32_t cropHeight);
+                               int32_t cropHeight) override;
 
 private:
     // methods internal to RenderEngine
-    friend class android::RenderEngine;
+    friend class RenderEngine;
     EGLSurface getEGLImage() const { return mEGLImage; }
 
     EGLDisplay mEGLDisplay;
     EGLImageKHR mEGLImage = EGL_NO_IMAGE_KHR;
 };
 
+} // namespace impl
 } // namespace RE
 } // namespace android
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 22016ed..4c878ae 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -37,8 +37,13 @@
 
 // ---------------------------------------------------------------------------
 namespace android {
+namespace RE {
 // ---------------------------------------------------------------------------
 
+RenderEngine::~RenderEngine() = default;
+
+namespace impl {
+
 std::unique_ptr<RenderEngine> RenderEngine::create(int hwcFormat, uint32_t featureFlags) {
     // initialize EGL for the default display
     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
@@ -137,9 +142,7 @@
 
 bool RenderEngine::overrideUseContextPriorityFromConfig(bool useContextPriority) {
     OptionalBool ret;
-    ISurfaceFlingerConfigs::getService()->useContextPriority([&ret](OptionalBool b) {
-        ret = b;
-    });
+    ISurfaceFlingerConfigs::getService()->useContextPriority([&ret](OptionalBool b) { ret = b; });
     if (ret.specified) {
         return ret.value;
     } else {
@@ -177,7 +180,22 @@
     return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext();
 }
 
-bool RenderEngine::setCurrentSurface(const RE::Surface& surface) {
+std::unique_ptr<RE::Surface> RenderEngine::createSurface() {
+    return std::make_unique<Surface>(*this);
+}
+
+std::unique_ptr<RE::Image> RenderEngine::createImage() {
+    return std::make_unique<Image>(*this);
+}
+
+bool RenderEngine::setCurrentSurface(const android::RE::Surface& surface) {
+    // Note: RE::Surface is an abstract interface. This implementation only ever
+    // creates RE::impl::Surface's, so it is safe to just cast to the actual
+    // type.
+    return setCurrentSurface(static_cast<const android::RE::impl::Surface&>(surface));
+}
+
+bool RenderEngine::setCurrentSurface(const android::RE::impl::Surface& surface) {
     bool success = true;
     EGLSurface eglSurface = surface.getEGLSurface();
     if (eglSurface != eglGetCurrentSurface(EGL_DRAW)) {
@@ -349,7 +367,14 @@
     glDeleteTextures(count, names);
 }
 
-void RenderEngine::bindExternalTextureImage(uint32_t texName, const RE::Image& image) {
+void RenderEngine::bindExternalTextureImage(uint32_t texName, const android::RE::Image& image) {
+    // Note: RE::Image is an abstract interface. This implementation only ever
+    // creates RE::impl::Image's, so it is safe to just cast to the actual type.
+    return bindExternalTextureImage(texName, static_cast<const android::RE::impl::Image&>(image));
+}
+
+void RenderEngine::bindExternalTextureImage(uint32_t texName,
+                                            const android::RE::impl::Image& image) {
     const GLenum target = GL_TEXTURE_EXTERNAL_OES;
 
     glBindTexture(target, texName);
@@ -375,34 +400,33 @@
 
 // ---------------------------------------------------------------------------
 
-RenderEngine::BindNativeBufferAsFramebuffer::BindNativeBufferAsFramebuffer(
-        RenderEngine& engine, ANativeWindowBuffer* buffer)
-      : mEngine(engine) {
-    mImage = eglCreateImageKHR(mEngine.mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-                               buffer, nullptr);
-    if (mImage == EGL_NO_IMAGE_KHR) {
-        mStatus = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+void RenderEngine::bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer,
+                                                 RE::BindNativeBufferAsFramebuffer* bindHelper) {
+    bindHelper->mImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+                                           buffer, nullptr);
+    if (bindHelper->mImage == EGL_NO_IMAGE_KHR) {
+        bindHelper->mStatus = NO_MEMORY;
         return;
     }
 
-    mEngine.bindImageAsFramebuffer(mImage, &mTexName, &mFbName, &mStatus);
+    uint32_t glStatus;
+    bindImageAsFramebuffer(bindHelper->mImage, &bindHelper->mTexName, &bindHelper->mFbName,
+                           &glStatus);
 
-    ALOGE_IF(mStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d",
-             mStatus);
+    ALOGE_IF(glStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d",
+             glStatus);
+
+    bindHelper->mStatus = glStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
 }
 
-RenderEngine::BindNativeBufferAsFramebuffer::~BindNativeBufferAsFramebuffer() {
-    if (mImage == EGL_NO_IMAGE_KHR) {
+void RenderEngine::unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) {
+    if (bindHelper->mImage == EGL_NO_IMAGE_KHR) {
         return;
     }
 
     // back to main framebuffer
-    mEngine.unbindFramebuffer(mTexName, mFbName);
-    eglDestroyImageKHR(mEngine.mEGLDisplay, mImage);
-}
-
-status_t RenderEngine::BindNativeBufferAsFramebuffer::getStatus() const {
-    return mStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
+    unbindFramebuffer(bindHelper->mTexName, bindHelper->mFbName);
+    eglDestroyImageKHR(mEGLDisplay, bindHelper->mImage);
 }
 
 // ---------------------------------------------------------------------------
@@ -564,5 +588,7 @@
 }
 
 // ---------------------------------------------------------------------------
-}; // namespace android
-// ---------------------------------------------------------------------------
+
+} // namespace impl
+} // namespace RE
+} // namespace android
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 67c0d1c..eacef38 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -44,91 +44,63 @@
 class Texture;
 
 namespace RE {
+
 class Image;
 class Surface;
-} // namespace RE
+class BindNativeBufferAsFramebuffer;
+
+namespace impl {
+class RenderEngine;
+}
 
 class RenderEngine {
-    enum GlesVersion {
-        GLES_VERSION_1_0 = 0x10000,
-        GLES_VERSION_1_1 = 0x10001,
-        GLES_VERSION_2_0 = 0x20000,
-        GLES_VERSION_3_0 = 0x30000,
-    };
-    static GlesVersion parseGlesVersion(const char* str);
-
-    EGLDisplay mEGLDisplay;
-    EGLConfig mEGLConfig;
-    EGLContext mEGLContext;
-    void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt);
-
-    virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName,
-                                        uint32_t* status) = 0;
-    virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0;
-
-    static bool overrideUseContextPriorityFromConfig(bool useContextPriority);
-
-protected:
-    RenderEngine();
-
 public:
-    virtual ~RenderEngine() = 0;
-
     enum FeatureFlag {
         WIDE_COLOR_SUPPORT = 1 << 0 // Platform has a wide color display
     };
-    static std::unique_ptr<RenderEngine> create(int hwcFormat, uint32_t featureFlags);
 
-    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
+    virtual ~RenderEngine() = 0;
 
-    void primeCache() const;
+    virtual std::unique_ptr<RE::Surface> createSurface() = 0;
+    virtual std::unique_ptr<RE::Image> createImage() = 0;
+
+    virtual void primeCache() const = 0;
 
     // dump the extension strings. always call the base class.
-    virtual void dump(String8& result);
+    virtual void dump(String8& result) = 0;
 
-    bool supportsImageCrop() const;
+    virtual bool supportsImageCrop() const = 0;
 
-    bool isCurrent() const;
-    bool setCurrentSurface(const RE::Surface& surface);
-    void resetCurrentSurface();
+    virtual bool isCurrent() const = 0;
+    virtual bool setCurrentSurface(const RE::Surface& surface) = 0;
+    virtual void resetCurrentSurface() = 0;
 
-    // synchronization
-
+    // helpers
     // flush submits RenderEngine command stream for execution and returns a
     // native fence fd that is signaled when the execution has completed.  It
     // returns -1 on errors.
-    base::unique_fd flush();
+    virtual base::unique_fd flush() = 0;
     // finish waits until RenderEngine command stream has been executed.  It
     // returns false on errors.
-    bool finish();
+    virtual bool finish() = 0;
     // waitFence inserts a wait on an external fence fd to RenderEngine
     // command stream.  It returns false on errors.
-    bool waitFence(base::unique_fd fenceFd);
+    virtual bool waitFence(base::unique_fd fenceFd) = 0;
 
-    // helpers
-    void clearWithColor(float red, float green, float blue, float alpha);
-    void fillRegionWithColor(const Region& region, uint32_t height, float red, float green,
-                             float blue, float alpha);
+    virtual void clearWithColor(float red, float green, float blue, float alpha) = 0;
+    virtual void fillRegionWithColor(const Region& region, uint32_t height, float red, float green,
+                                     float blue, float alpha) = 0;
 
     // common to all GL versions
-    void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top);
-    void disableScissor();
-    void genTextures(size_t count, uint32_t* names);
-    void deleteTextures(size_t count, uint32_t const* names);
-    void bindExternalTextureImage(uint32_t texName, const RE::Image& image);
-    void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels);
-
-    class BindNativeBufferAsFramebuffer {
-        RenderEngine& mEngine;
-        EGLImageKHR mImage;
-        uint32_t mTexName, mFbName;
-        uint32_t mStatus;
-
-    public:
-        BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer);
-        ~BindNativeBufferAsFramebuffer();
-        int getStatus() const;
-    };
+    virtual void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) = 0;
+    virtual void disableScissor() = 0;
+    virtual void genTextures(size_t count, uint32_t* names) = 0;
+    virtual void deleteTextures(size_t count, uint32_t const* names) = 0;
+    virtual void bindExternalTextureImage(uint32_t texName, const RE::Image& image) = 0;
+    virtual void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) = 0;
+    virtual void bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer,
+                                               RE::BindNativeBufferAsFramebuffer* bindHelper) = 0;
+    virtual void unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) = 0;
 
     // set-up
     virtual void checkErrors() const;
@@ -145,7 +117,7 @@
     virtual void setupLayerBlackedOut() = 0;
     virtual void setupFillWithColor(float r, float g, float b, float a) = 0;
 
-    virtual mat4 setupColorTransform(const mat4& /* colorTransform */) { return mat4(); }
+    virtual mat4 setupColorTransform(const mat4& /* colorTransform */) = 0;
 
     virtual void disableTexturing() = 0;
     virtual void disableBlending() = 0;
@@ -156,14 +128,123 @@
     // queries
     virtual size_t getMaxTextureSize() const = 0;
     virtual size_t getMaxViewportDims() const = 0;
+};
+
+class BindNativeBufferAsFramebuffer {
+public:
+    BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer)
+          : mEngine(engine) {
+        mEngine.bindNativeBufferAsFrameBuffer(buffer, this);
+    }
+    ~BindNativeBufferAsFramebuffer() { mEngine.unbindNativeBufferAsFrameBuffer(this); }
+    status_t getStatus() const { return mStatus; }
+
+protected:
+    friend impl::RenderEngine;
+
+    RenderEngine& mEngine;
+    EGLImageKHR mImage;
+    uint32_t mTexName, mFbName;
+    status_t mStatus;
+};
+
+namespace impl {
+
+class Image;
+class Surface;
+
+class RenderEngine : public RE::RenderEngine {
+    enum GlesVersion {
+        GLES_VERSION_1_0 = 0x10000,
+        GLES_VERSION_1_1 = 0x10001,
+        GLES_VERSION_2_0 = 0x20000,
+        GLES_VERSION_3_0 = 0x30000,
+    };
+    static GlesVersion parseGlesVersion(const char* str);
+
+    EGLDisplay mEGLDisplay;
+    EGLConfig mEGLConfig;
+    EGLContext mEGLContext;
+    void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt);
+
+    static bool overrideUseContextPriorityFromConfig(bool useContextPriority);
+
+protected:
+    RenderEngine();
+
+public:
+    virtual ~RenderEngine() = 0;
+
+    static std::unique_ptr<RenderEngine> create(int hwcFormat, uint32_t featureFlags);
+
+    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
+
+    // RenderEngine interface implementation
+
+    std::unique_ptr<RE::Surface> createSurface() override;
+    std::unique_ptr<RE::Image> createImage() override;
+
+    void primeCache() const override;
+
+    // dump the extension strings. always call the base class.
+    void dump(String8& result) override;
+
+    bool supportsImageCrop() const override;
+
+    bool isCurrent() const;
+    bool setCurrentSurface(const RE::Surface& surface) override;
+    void resetCurrentSurface() override;
+
+    // synchronization
+
+    // flush submits RenderEngine command stream for execution and returns a
+    // native fence fd that is signaled when the execution has completed.  It
+    // returns -1 on errors.
+    base::unique_fd flush() override;
+    // finish waits until RenderEngine command stream has been executed.  It
+    // returns false on errors.
+    bool finish() override;
+    // waitFence inserts a wait on an external fence fd to RenderEngine
+    // command stream.  It returns false on errors.
+    bool waitFence(base::unique_fd fenceFd) override;
+
+    // helpers
+    void clearWithColor(float red, float green, float blue, float alpha) override;
+    void fillRegionWithColor(const Region& region, uint32_t height, float red, float green,
+                             float blue, float alpha) override;
+
+    // common to all GL versions
+    void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) override;
+    void disableScissor() override;
+    void genTextures(size_t count, uint32_t* names) override;
+    void deleteTextures(size_t count, uint32_t const* names) override;
+    void bindExternalTextureImage(uint32_t texName, const RE::Image& image) override;
+    void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) override;
+
+    void checkErrors() const override;
+
+    mat4 setupColorTransform(const mat4& /* colorTransform */) override { return mat4(); }
 
     // internal to RenderEngine
     EGLDisplay getEGLDisplay() const;
     EGLConfig getEGLConfig() const;
+
+    // Common implementation
+    bool setCurrentSurface(const RE::impl::Surface& surface);
+    void bindExternalTextureImage(uint32_t texName, const RE::impl::Image& image);
+
+    void bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer,
+                                       RE::BindNativeBufferAsFramebuffer* bindHelper) override;
+    void unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) override;
+
+    // Overriden by each specialization
+    virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName,
+                                        uint32_t* status) = 0;
+    virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0;
 };
 
-// ---------------------------------------------------------------------------
-}; // namespace android
-// ---------------------------------------------------------------------------
+} // namespace impl
+} // namespace RE
+} // namespace android
 
 #endif /* SF_RENDERENGINE_H_ */
diff --git a/services/surfaceflinger/RenderEngine/Surface.cpp b/services/surfaceflinger/RenderEngine/Surface.cpp
index a23d9fb..3c29e4b 100644
--- a/services/surfaceflinger/RenderEngine/Surface.cpp
+++ b/services/surfaceflinger/RenderEngine/Surface.cpp
@@ -23,6 +23,10 @@
 namespace android {
 namespace RE {
 
+Surface::~Surface() = default;
+
+namespace impl {
+
 Surface::Surface(const RenderEngine& engine)
       : mEGLDisplay(engine.getEGLDisplay()), mEGLConfig(engine.getEGLConfig()) {
     // RE does not assume any config when EGL_KHR_no_config_context is supported
@@ -102,5 +106,6 @@
     return querySurface(EGL_HEIGHT);
 }
 
+} // namespace impl
 } // namespace RE
 } // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Surface.h b/services/surfaceflinger/RenderEngine/Surface.h
index 8b10be9..d4d3d8c 100644
--- a/services/surfaceflinger/RenderEngine/Surface.h
+++ b/services/surfaceflinger/RenderEngine/Surface.h
@@ -23,39 +23,60 @@
 struct ANativeWindow;
 
 namespace android {
-
-class RenderEngine;
-
 namespace RE {
 
 class Surface {
 public:
+    virtual ~Surface() = 0;
+
+    virtual void setCritical(bool enable) = 0;
+    virtual void setAsync(bool enable) = 0;
+
+    virtual void setNativeWindow(ANativeWindow* window) = 0;
+    virtual void swapBuffers() const = 0;
+
+    virtual int32_t queryRedSize() const = 0;
+    virtual int32_t queryGreenSize() const = 0;
+    virtual int32_t queryBlueSize() const = 0;
+    virtual int32_t queryAlphaSize() const = 0;
+
+    virtual int32_t queryWidth() const = 0;
+    virtual int32_t queryHeight() const = 0;
+};
+
+namespace impl {
+
+class RenderEngine;
+
+class Surface final : public RE::Surface {
+public:
     Surface(const RenderEngine& engine);
     ~Surface();
 
     Surface(const Surface&) = delete;
     Surface& operator=(const Surface&) = delete;
 
-    void setCritical(bool enable) { mCritical = enable; }
-    void setAsync(bool enable) { mAsync = enable; }
+    // RE::Surface implementation
+    void setCritical(bool enable) override { mCritical = enable; }
+    void setAsync(bool enable) override { mAsync = enable; }
 
-    void setNativeWindow(ANativeWindow* window);
-    void swapBuffers() const;
+    void setNativeWindow(ANativeWindow* window) override;
+    void swapBuffers() const override;
 
-    int32_t queryRedSize() const;
-    int32_t queryGreenSize() const;
-    int32_t queryBlueSize() const;
-    int32_t queryAlphaSize() const;
+    int32_t queryRedSize() const override;
+    int32_t queryGreenSize() const override;
+    int32_t queryBlueSize() const override;
+    int32_t queryAlphaSize() const override;
 
-    int32_t queryWidth() const;
-    int32_t queryHeight() const;
+    int32_t queryWidth() const override;
+    int32_t queryHeight() const override;
 
 private:
     EGLint queryConfig(EGLint attrib) const;
     EGLint querySurface(EGLint attrib) const;
 
     // methods internal to RenderEngine
-    friend class android::RenderEngine;
+    friend class RenderEngine;
     bool getAsync() const { return mAsync; }
     EGLSurface getEGLSurface() const { return mEGLSurface; }
 
@@ -69,5 +90,6 @@
     EGLSurface mEGLSurface = EGL_NO_SURFACE;
 };
 
+} // namespace impl
 } // namespace RE
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1054c32..03f6bdc 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -410,12 +410,11 @@
 
 void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
     class MessageDestroyGLTexture : public MessageBase {
-        RenderEngine& engine;
+        RE::RenderEngine& engine;
         uint32_t texture;
     public:
-        MessageDestroyGLTexture(RenderEngine& engine, uint32_t texture)
-            : engine(engine), texture(texture) {
-        }
+        MessageDestroyGLTexture(RE::RenderEngine& engine, uint32_t texture)
+              : engine(engine), texture(texture) {}
         virtual bool handler() {
             engine.deleteTextures(1, &texture);
             return true;
@@ -575,25 +574,30 @@
     Mutex::Autolock _l(mStateLock);
 
     // start the EventThread
-
-    mEventThreadSource = std::make_unique<DispSyncSource>(
-            &mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs, true, "app");
-    mEventThread = std::make_unique<EventThread>(
-            mEventThreadSource.get(), *this, false, "sfEventThread");
-    mSfEventThreadSource = std::make_unique<DispSyncSource>(
-            &mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
-    mSFEventThread = std::make_unique<EventThread>(
-            mSfEventThreadSource.get(), *this, true, "appEventThread");
+    mEventThreadSource =
+            std::make_unique<DispSyncSource>(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs,
+                                             true, "app");
+    mEventThread = std::make_unique<impl::EventThread>(mEventThreadSource.get(), *this, false,
+                                                       "appEventThread");
+    mSfEventThreadSource =
+            std::make_unique<DispSyncSource>(&mPrimaryDispSync,
+                                             SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
+    mSFEventThread = std::make_unique<impl::EventThread>(mSfEventThreadSource.get(), *this, true,
+                                                         "sfEventThread");
     mEventQueue.setEventThread(mSFEventThread.get());
 
     // Get a RenderEngine for the given display / config (can't fail)
-    getBE().mRenderEngine = RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888,
-            hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0);
+    getBE().mRenderEngine =
+            RE::impl::RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888,
+                                           hasWideColorDisplay
+                                                   ? RE::RenderEngine::WIDE_COLOR_SUPPORT
+                                                   : 0);
     LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine");
 
     LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
             "Starting with vr flinger active is not currently supported.");
-    getBE().mHwc.reset(new HWComposer(getBE().mHwcServiceName));
+    getBE().mHwc.reset(
+            new HWComposer(std::make_unique<Hwc2::impl::Composer>(getBE().mHwcServiceName)));
     getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId);
     // Process any initial hotplug and resulting display changes.
     processDisplayHotplugEventsLocked();
@@ -1065,8 +1069,9 @@
             ALOGV("VSync Injections enabled");
             if (mVSyncInjector.get() == nullptr) {
                 mVSyncInjector = std::make_unique<InjectVSyncSource>();
-                mInjectorEventThread = std::make_unique<EventThread>(
-                        mVSyncInjector.get(), *this, false, "injEvThread");
+                mInjectorEventThread =
+                        std::make_unique<impl::EventThread>(mVSyncInjector.get(), *this, false,
+                                                            "injEventThread");
             }
             mEventQueue.setEventThread(mInjectorEventThread.get());
         } else {
@@ -1342,7 +1347,8 @@
 
     resetDisplayState();
     getBE().mHwc.reset(); // Delete the current instance before creating the new one
-    getBE().mHwc.reset(new HWComposer(vrFlingerRequestsDisplay ? "vr" : getBE().mHwcServiceName));
+    getBE().mHwc.reset(new HWComposer(std::make_unique<Hwc2::impl::Composer>(
+            vrFlingerRequestsDisplay ? "vr" : getBE().mHwcServiceName)));
     getBE().mHwc->registerCallback(this, ++getBE().mComposerSequenceId);
 
     LOG_ALWAYS_FATAL_IF(!getBE().mHwc->getComposer()->isRemote(),
@@ -1471,7 +1477,7 @@
 
                 // and draw the dirty region
                 const int32_t height = hw->getHeight();
-                RenderEngine& engine(getRenderEngine());
+                auto& engine(getRenderEngine());
                 engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1);
 
                 hw->swapBuffers(getHwComposer());
@@ -2854,7 +2860,7 @@
 
 void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& displayDevice, const Region& region) const {
     const int32_t height = displayDevice->getHeight();
-    RenderEngine& engine(getRenderEngine());
+    auto& engine(getRenderEngine());
     engine.fillRegionWithColor(region, height, 0, 0, 0, 0);
 }
 
@@ -4516,7 +4522,7 @@
                                             bool useIdentityTransform) {
     ATRACE_CALL();
 
-    RenderEngine& engine(getRenderEngine());
+    auto& engine(getRenderEngine());
 
     // get screen geometry
     const auto raWidth = renderArea.getWidth();
@@ -4595,7 +4601,7 @@
 
     // this binds the given EGLImage as a framebuffer for the
     // duration of this scope.
-    RenderEngine::BindNativeBufferAsFramebuffer bufferBond(getRenderEngine(), buffer);
+    RE::BindNativeBufferAsFramebuffer bufferBond(getRenderEngine(), buffer);
     if (bufferBond.getStatus() != NO_ERROR) {
         ALOGE("got ANWB binding error while taking screenshot");
         return INVALID_OPERATION;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 19dd059..b7ebb1b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -83,16 +83,23 @@
 // ---------------------------------------------------------------------------
 
 class Client;
-class DisplayEventConnection;
-class EventThread;
-class Layer;
 class ColorLayer;
-class Surface;
-class RenderEngine;
+class DisplayEventConnection;
 class EventControlThread;
-class VSyncSource;
+class EventThread;
 class InjectVSyncSource;
+class Layer;
+class Surface;
 class SurfaceFlingerBE;
+class VSyncSource;
+
+namespace impl {
+class EventThread;
+} // namespace impl
+
+namespace RE {
+class RenderEngine;
+}
 
 typedef std::function<void(const LayerVector::Visitor&)> TraverseLayersFunction;
 
@@ -139,7 +146,7 @@
     const std::string mHwcServiceName; // "default" for real use, something else for testing.
 
     // constant members (no synchronization needed for access)
-    std::unique_ptr<RenderEngine> mRenderEngine;
+    std::unique_ptr<RE::RenderEngine> mRenderEngine;
     EGLContext mEGLContext;
     EGLDisplay mEGLDisplay;
 
@@ -301,9 +308,7 @@
     // TODO: this should be made accessible only to HWComposer
     const Vector< sp<Layer> >& getLayerSortedByZForHwcDisplay(int id);
 
-    RenderEngine& getRenderEngine() const {
-        return *getBE().mRenderEngine;
-    }
+    RE::RenderEngine& getRenderEngine() const { return *getBE().mRenderEngine; }
 
     bool authenticateSurfaceTextureLocked(
         const sp<IGraphicBufferProducer>& bufferProducer) const;
@@ -311,7 +316,7 @@
 private:
     friend class Client;
     friend class DisplayEventConnection;
-    friend class EventThread;
+    friend class impl::EventThread;
     friend class Layer;
     friend class BufferLayer;
     friend class MonitoredProducer;
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 72e0a0f..3eb07ae 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -20,6 +20,9 @@
     srcs: [
         ":libsurfaceflinger_sources",
         "DisplayTransactionTest.cpp",
+        "MockComposer.cpp",
+        "MockEventThread.cpp",
+        "MockRenderEngine.cpp",
     ],
     static_libs: [
         "libgmock",
diff --git a/services/surfaceflinger/tests/unittests/MockComposer.cpp b/services/surfaceflinger/tests/unittests/MockComposer.cpp
new file mode 100644
index 0000000..318519b
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/MockComposer.cpp
@@ -0,0 +1,29 @@
+/*
+ * 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 "MockComposer.h"
+
+namespace android {
+namespace Hwc2 {
+namespace mock {
+
+// Explicit default instantiation is recommended.
+Composer::Composer() = default;
+Composer::~Composer() = default;
+
+} // namespace mock
+} // namespace Hwc2
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/MockComposer.h b/services/surfaceflinger/tests/unittests/MockComposer.h
new file mode 100644
index 0000000..248afcf
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/MockComposer.h
@@ -0,0 +1,111 @@
+/*
+ * 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 "DisplayHardware/ComposerHal.h"
+
+namespace android {
+
+class GraphicBuffer;
+
+namespace Hwc2 {
+namespace mock {
+
+using android::hardware::graphics::common::V1_0::ColorMode;
+using android::hardware::graphics::common::V1_0::ColorTransform;
+using android::hardware::graphics::common::V1_0::Dataspace;
+using android::hardware::graphics::common::V1_0::Hdr;
+using android::hardware::graphics::common::V1_0::PixelFormat;
+using android::hardware::graphics::common::V1_0::Transform;
+
+using android::hardware::graphics::composer::V2_1::Config;
+using android::hardware::graphics::composer::V2_1::Display;
+using android::hardware::graphics::composer::V2_1::Error;
+using android::hardware::graphics::composer::V2_1::IComposer;
+using android::hardware::graphics::composer::V2_1::IComposerCallback;
+using android::hardware::graphics::composer::V2_1::IComposerClient;
+using android::hardware::graphics::composer::V2_1::Layer;
+
+class Composer : public Hwc2::Composer {
+public:
+    Composer();
+    ~Composer() override;
+
+    MOCK_METHOD0(getCapabilities, std::vector<IComposer::Capability>());
+    MOCK_METHOD0(dumpDebugInfo, std::string());
+    MOCK_METHOD1(registerCallback, void(const sp<IComposerCallback>&));
+    MOCK_METHOD0(isRemote, bool());
+    MOCK_METHOD0(resetCommands, void());
+    MOCK_METHOD0(executeCommands, Error());
+    MOCK_METHOD0(getMaxVirtualDisplayCount, uint32_t());
+    MOCK_CONST_METHOD0(isUsingVrComposer, bool());
+    MOCK_METHOD4(createVirtualDisplay, Error(uint32_t, uint32_t, PixelFormat*, Display*));
+    MOCK_METHOD1(destroyVirtualDisplay, Error(Display));
+    MOCK_METHOD1(acceptDisplayChanges, Error(Display));
+    MOCK_METHOD2(createLayer, Error(Display, Layer* outLayer));
+    MOCK_METHOD2(destroyLayer, Error(Display, Layer));
+    MOCK_METHOD2(getActiveConfig, Error(Display, Config*));
+    MOCK_METHOD3(getChangedCompositionTypes,
+                 Error(Display, std::vector<Layer>*, std::vector<IComposerClient::Composition>*));
+    MOCK_METHOD2(getColorModes, Error(Display, std::vector<ColorMode>*));
+    MOCK_METHOD4(getDisplayAttribute,
+                 Error(Display, Config config, IComposerClient::Attribute, int32_t*));
+    MOCK_METHOD2(getDisplayConfigs, Error(Display, std::vector<Config>*));
+    MOCK_METHOD2(getDisplayName, Error(Display, std::string*));
+    MOCK_METHOD4(getDisplayRequests,
+                 Error(Display, uint32_t*, std::vector<Layer>*, std::vector<uint32_t>*));
+    MOCK_METHOD2(getDisplayType, Error(Display, IComposerClient::DisplayType*));
+    MOCK_METHOD2(getDozeSupport, Error(Display, bool*));
+    MOCK_METHOD5(getHdrCapabilities, Error(Display, std::vector<Hdr>*, float*, float*, float*));
+    MOCK_METHOD3(getReleaseFences, Error(Display, std::vector<Layer>*, std::vector<int>*));
+    MOCK_METHOD2(presentDisplay, Error(Display, int*));
+    MOCK_METHOD2(setActiveConfig, Error(Display, Config));
+    MOCK_METHOD6(setClientTarget,
+                 Error(Display, uint32_t, const sp<GraphicBuffer>&, int, Dataspace,
+                       const std::vector<IComposerClient::Rect>&));
+    MOCK_METHOD2(setColorMode, Error(Display, ColorMode));
+    MOCK_METHOD3(setColorTransform, Error(Display, const float*, ColorTransform));
+    MOCK_METHOD3(setOutputBuffer, Error(Display, const native_handle_t*, int));
+    MOCK_METHOD2(setPowerMode, Error(Display, IComposerClient::PowerMode));
+    MOCK_METHOD2(setVsyncEnabled, Error(Display, IComposerClient::Vsync));
+    MOCK_METHOD1(setClientTargetSlotCount, Error(Display));
+    MOCK_METHOD3(validateDisplay, Error(Display, uint32_t*, uint32_t*));
+    MOCK_METHOD5(presentOrValidateDisplay, Error(Display, uint32_t*, uint32_t*, int*, uint32_t*));
+    MOCK_METHOD4(setCursorPosition, Error(Display, Layer, int32_t, int32_t));
+    MOCK_METHOD5(setLayerBuffer, Error(Display, Layer, uint32_t, const sp<GraphicBuffer>&, int));
+    MOCK_METHOD3(setLayerSurfaceDamage,
+                 Error(Display, Layer, const std::vector<IComposerClient::Rect>&));
+    MOCK_METHOD3(setLayerBlendMode, Error(Display, Layer, IComposerClient::BlendMode));
+    MOCK_METHOD3(setLayerColor, Error(Display, Layer, const IComposerClient::Color&));
+    MOCK_METHOD3(setLayerCompositionType, Error(Display, Layer, IComposerClient::Composition));
+    MOCK_METHOD3(setLayerDataspace, Error(Display, Layer, Dataspace));
+    MOCK_METHOD3(setLayerDisplayFrame, Error(Display, Layer, const IComposerClient::Rect&));
+    MOCK_METHOD3(setLayerPlaneAlpha, Error(Display, Layer, float));
+    MOCK_METHOD3(setLayerSidebandStream, Error(Display, Layer, const native_handle_t*));
+    MOCK_METHOD3(setLayerSourceCrop, Error(Display, Layer, const IComposerClient::FRect&));
+    MOCK_METHOD3(setLayerTransform, Error(Display, Layer, Transform));
+    MOCK_METHOD3(setLayerVisibleRegion,
+                 Error(Display, Layer, const std::vector<IComposerClient::Rect>&));
+    MOCK_METHOD3(setLayerZOrder, Error(Display, Layer, uint32_t));
+    MOCK_METHOD4(setLayerInfo, Error(Display, Layer, uint32_t, uint32_t));
+};
+
+} // namespace mock
+} // namespace Hwc2
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/MockEventThread.cpp b/services/surfaceflinger/tests/unittests/MockEventThread.cpp
new file mode 100644
index 0000000..6b5ea4b
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/MockEventThread.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 "MockEventThread.h"
+
+namespace android {
+namespace mock {
+
+// Explicit default instantiation is recommended.
+EventThread::EventThread() = default;
+EventThread::~EventThread() = default;
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/MockEventThread.h b/services/surfaceflinger/tests/unittests/MockEventThread.h
new file mode 100644
index 0000000..e6ea663
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/MockEventThread.h
@@ -0,0 +1,40 @@
+/*
+ * 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 "EventThread.h"
+
+namespace android {
+namespace mock {
+
+class EventThread : public android::EventThread {
+public:
+    EventThread();
+    ~EventThread() override;
+
+    MOCK_CONST_METHOD0(createEventConnection, sp<BnDisplayEventConnection>());
+    MOCK_METHOD0(onScreenReleased, void());
+    MOCK_METHOD0(onScreenAcquired, void());
+    MOCK_METHOD2(onHotplugReceived, void(int, bool));
+    MOCK_CONST_METHOD1(dump, void(String8&));
+    MOCK_METHOD1(setPhaseOffset, void(nsecs_t phaseOffset));
+};
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/MockRenderEngine.cpp b/services/surfaceflinger/tests/unittests/MockRenderEngine.cpp
new file mode 100644
index 0000000..e69f4cf
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/MockRenderEngine.cpp
@@ -0,0 +1,35 @@
+/*
+ * 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 "MockRenderEngine.h"
+
+namespace android {
+namespace RE {
+namespace mock {
+
+// Explicit default instantiation is recommended.
+RenderEngine::RenderEngine() = default;
+RenderEngine::~RenderEngine() = default;
+
+Surface::Surface() = default;
+Surface::~Surface() = default;
+
+Image::Image() = default;
+Image::~Image() = default;
+
+} // namespace mock
+} // namespace RE
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/MockRenderEngine.h
new file mode 100644
index 0000000..aefbfcf
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/MockRenderEngine.h
@@ -0,0 +1,108 @@
+/*
+ * 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 "RenderEngine/Image.h"
+#include "RenderEngine/Mesh.h"
+#include "RenderEngine/RenderEngine.h"
+#include "RenderEngine/Surface.h"
+#include "RenderEngine/Texture.h"
+
+namespace android {
+namespace RE {
+namespace mock {
+
+class RenderEngine : public RE::RenderEngine {
+public:
+    RenderEngine();
+    ~RenderEngine() override;
+
+    MOCK_METHOD0(createSurface, std::unique_ptr<RE::Surface>());
+    MOCK_METHOD0(createImage, std::unique_ptr<RE::Image>());
+    MOCK_CONST_METHOD0(primeCache, void());
+    MOCK_METHOD1(dump, void(String8&));
+    MOCK_CONST_METHOD0(supportsImageCrop, bool());
+    MOCK_CONST_METHOD0(isCurrent, bool());
+    MOCK_METHOD1(setCurrentSurface, bool(const RE::Surface&));
+    MOCK_METHOD0(resetCurrentSurface, void());
+    MOCK_METHOD0(flush, base::unique_fd());
+    MOCK_METHOD0(finish, bool());
+    MOCK_METHOD1(waitFence, bool(base::unique_fd*));
+    bool waitFence(base::unique_fd fd) override { return waitFence(&fd); };
+    MOCK_METHOD4(clearWithColor, void(float, float, float, float));
+    MOCK_METHOD6(fillRegionWithColor, void(const Region&, uint32_t, float, float, float, float));
+    MOCK_METHOD4(setScissor, void(uint32_t, uint32_t, uint32_t, uint32_t));
+    MOCK_METHOD0(disableScissor, void());
+    MOCK_METHOD2(genTextures, void(size_t, uint32_t*));
+    MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*));
+    MOCK_METHOD2(bindExternalTextureImage, void(uint32_t, const RE::Image&));
+    MOCK_METHOD5(readPixels, void(size_t, size_t, size_t, size_t, uint32_t*));
+    MOCK_CONST_METHOD0(checkErrors, void());
+    MOCK_METHOD6(setViewportAndProjection,
+                 void(size_t, size_t, Rect, size_t, bool, Transform::orientation_flags));
+    MOCK_METHOD4(setupLayerBlending, void(bool, bool, bool, const half4&));
+    MOCK_METHOD1(setColorMode, void(android_color_mode));
+    MOCK_METHOD1(setSourceDataSpace, void(android_dataspace));
+    MOCK_METHOD1(setSourceY410BT2020, void(bool));
+    MOCK_METHOD1(setWideColor, void(bool));
+    MOCK_METHOD0(usesWideColor, bool());
+    MOCK_METHOD1(setupLayerTexturing, void(const Texture&));
+    MOCK_METHOD0(setupLayerBlackedOut, void());
+    MOCK_METHOD4(setupFillWithColor, void(float, float, float, float));
+    MOCK_METHOD1(setupColorTransform, mat4(const mat4&));
+    MOCK_METHOD0(disableTexturing, void());
+    MOCK_METHOD0(disableBlending, void());
+    MOCK_METHOD2(bindNativeBufferAsFrameBuffer,
+                 void(ANativeWindowBuffer*, RE::BindNativeBufferAsFramebuffer*));
+    MOCK_METHOD1(unbindNativeBufferAsFrameBuffer, void(RE::BindNativeBufferAsFramebuffer*));
+    MOCK_METHOD1(drawMesh, void(const Mesh&));
+    MOCK_CONST_METHOD0(getMaxTextureSize, size_t());
+    MOCK_CONST_METHOD0(getMaxViewportDims, size_t());
+};
+
+class Surface : public RE::Surface {
+public:
+    Surface();
+    ~Surface() override;
+
+    MOCK_METHOD1(setCritical, void(bool));
+    MOCK_METHOD1(setAsync, void(bool));
+    MOCK_METHOD1(setNativeWindow, void(ANativeWindow*));
+    MOCK_CONST_METHOD0(swapBuffers, void());
+    MOCK_CONST_METHOD0(queryRedSize, int32_t());
+    MOCK_CONST_METHOD0(queryGreenSize, int32_t());
+    MOCK_CONST_METHOD0(queryBlueSize, int32_t());
+    MOCK_CONST_METHOD0(queryAlphaSize, int32_t());
+    MOCK_CONST_METHOD0(queryWidth, int32_t());
+    MOCK_CONST_METHOD0(queryHeight, int32_t());
+};
+
+class Image : public RE::Image {
+public:
+    Image();
+    ~Image() override;
+
+    MOCK_METHOD4(setNativeWindowBuffer,
+                 bool(ANativeWindowBuffer* buffer, bool isProtected, int32_t cropWidth,
+                      int32_t cropHeight));
+};
+
+} // namespace mock
+} // namespace RE
+} // namespace android