Merge "Remove unused BufferHubBase::GetBlobFds method"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 49d8fe9..db8848a 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -981,6 +981,8 @@
 
     AddAnrTraceDir(add_to_zip, anr_traces_dir);
 
+    RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
+
     // Slow traces for slow operations.
     struct stat st;
     int i = 0;
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 00f9f42..49383e5 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -982,9 +982,13 @@
         auto to_de = create_data_user_de_path(volume_uuid, user);
         int rc = copy_directory_recursive(from_de.c_str(), to_de.c_str());
         if (rc != 0) {
-            // TODO(narayan): Should we clear clear the rolled back CE data if
-            // something goes wrong here ? We're choosing between leaving the
-            // app devoid of all its data or with just its ce data installed.
+            if (needs_ce_rollback) {
+                auto ce_data = create_data_user_ce_package_path(volume_uuid, user, package_name);
+                LOG(WARNING) << "de_data rollback failed. Erasing rolled back ce_data " << ce_data;
+                if (delete_dir_contents(ce_data.c_str(), 1, nullptr) != 0) {
+                    LOG(WARNING) << "Failed to delete rolled back ce_data " << ce_data;
+                }
+            }
             res = error(rc, "Failed copying " + from_de + " to " + to_de);
             return res;
         }
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 940ba79..a639951 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -314,9 +314,15 @@
         bool skip_compilation = vold_decrypt == "trigger_restart_min_framework" ||
                                 vold_decrypt == "1";
 
-        const std::string resolve_startup_string_arg =
+        std::string resolve_startup_string_arg =
+                MapPropertyToArg("persist.device_config.runtime.dex2oat_resolve_startup_strings",
+                                 "--resolve-startup-const-strings=%s");
+        if (resolve_startup_string_arg.empty()) {
+          // If empty, fall back to system property.
+          resolve_startup_string_arg =
                 MapPropertyToArg("dalvik.vm.dex2oat-resolve-startup-strings",
                                  "--resolve-startup-const-strings=%s");
+        }
 
         const std::string image_block_size_arg =
                 MapPropertyToArg("dalvik.vm.dex2oat-max-image-block-size",
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index c0f8e91..1c99663 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -58,6 +58,27 @@
     }
 }
 
+static std::vector<apex::ApexFile> ActivateApexPackages() {
+    // The logic here is (partially) copied and adapted from
+    // system/apex/apexd/apexd_main.cpp.
+    //
+    // Only scan the APEX directory under /system (within the chroot dir).
+    // Note that this leaves around the loop devices created and used by
+    // libapexd's code, but this is fine, as we expect to reboot soon after.
+    apex::scanPackagesDirAndActivate(apex::kApexPackageSystemDir);
+    return apex::getActivePackages();
+}
+
+static void DeactivateApexPackages(const std::vector<apex::ApexFile>& active_packages) {
+    for (const apex::ApexFile& apex_file : active_packages) {
+        const std::string& package_path = apex_file.GetPath();
+        apex::Status status = apex::deactivatePackage(package_path);
+        if (!status.Ok()) {
+            LOG(ERROR) << "Failed to deactivate " << package_path << ": " << status.ErrorMessage();
+        }
+    }
+}
+
 // Entry for otapreopt_chroot. Expected parameters are:
 //   [cmd] [status-fd] [target-slot] "dexopt" [dexopt-params]
 // The file descriptor denoted by status-fd will be closed. The rest of the parameters will
@@ -199,15 +220,7 @@
 
     // Try to mount APEX packages in "/apex" in the chroot dir. We need at least
     // the Android Runtime APEX, as it is required by otapreopt to run dex2oat.
-    // The logic here is (partially) copied and adapted from
-    // system/apex/apexd/apexd_main.cpp.
-    //
-    // Only scan the APEX directory under /system (within the chroot dir).
-    // Note that this leaves around the loop devices created and used by
-    // libapexd's code, but this is fine, as we expect to reboot soon after.
-    apex::scanPackagesDirAndActivate(apex::kApexPackageSystemDir);
-    // Collect activated packages.
-    std::vector<apex::ApexFile> active_packages = apex::getActivePackages();
+    std::vector<apex::ApexFile> active_packages = ActivateApexPackages();
 
     // Now go on and run otapreopt.
 
@@ -229,14 +242,8 @@
         LOG(ERROR) << "Running otapreopt failed: " << error_msg;
     }
 
-    // Tear down the work down by the apexd logic above (i.e. deactivate packages).
-    for (const apex::ApexFile& apex_file : active_packages) {
-        const std::string& package_path = apex_file.GetPath();
-        apex::Status status = apex::deactivatePackage(package_path);
-        if (!status.Ok()) {
-            LOG(ERROR) << "Failed to deactivate " << package_path << ": " << status.ErrorMessage();
-        }
-    }
+    // Tear down the work down by the apexd logic. (i.e. deactivate packages).
+    DeactivateApexPackages(active_packages);
 
     if (!exec_result) {
         exit(213);
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index e2afe1d..78edce0 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -23,6 +23,8 @@
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/scopeguard.h>
 #include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
 #include <binder/Status.h>
@@ -85,6 +87,23 @@
     system(cmd.c_str());
 }
 
+template <typename Visitor>
+static void run_cmd_and_process_output(const std::string& cmd, const Visitor& visitor) {
+    FILE* file = popen(cmd.c_str(), "r");
+    CHECK(file != nullptr) << "Failed to ptrace " << cmd;
+    char* line = nullptr;
+    while (true) {
+        size_t n = 0u;
+        ssize_t value = getline(&line, &n, file);
+        if (value == -1) {
+            break;
+        }
+        visitor(line);
+    }
+    free(line);
+    fclose(file);
+}
+
 static int mkdir(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
     int ret = ::mkdir(path.c_str(), mode);
     if (ret != 0) {
@@ -222,7 +241,8 @@
     ::testing::AssertionResult create_mock_app() {
         // Create the oat dir.
         app_oat_dir_ = app_apk_dir_ + "/oat";
-        if (mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755) != 0) {
+        // For debug mode, the directory might already exist. Avoid erroring out.
+        if (mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755) != 0 && !kDebug) {
             return ::testing::AssertionFailure() << "Could not create app dir " << app_apk_dir_
                                                  << " : " << strerror(errno);
         }
@@ -628,6 +648,50 @@
                         DEX2OAT_FROM_SCRATCH);
 }
 
+TEST_F(DexoptTest, ResolveStartupConstStrings) {
+    LOG(INFO) << "DexoptDex2oatResolveStartupStrings";
+    const std::string property = "persist.device_config.runtime.dex2oat_resolve_startup_strings";
+    const std::string previous_value = android::base::GetProperty(property, "");
+    auto restore_property = android::base::make_scope_guard([=]() {
+        android::base::SetProperty(property, previous_value);
+    });
+    std::string odex = GetPrimaryDexArtifact(app_oat_dir_.c_str(), apk_path_, "odex");
+    // Disable the property to start.
+    bool found_disable = false;
+    ASSERT_TRUE(android::base::SetProperty(property, "false")) << property;
+    CompilePrimaryDexOk("speed-profile",
+                        DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED |
+                                DEXOPT_GENERATE_APP_IMAGE,
+                        app_oat_dir_.c_str(),
+                        kTestAppGid,
+                        DEX2OAT_FROM_SCRATCH);
+    run_cmd_and_process_output(
+            "oatdump --header-only --oat-file=" + odex,
+            [&](const std::string& line) {
+        if (line.find("--resolve-startup-const-strings=false") != std::string::npos) {
+            found_disable = true;
+        }
+    });
+    EXPECT_TRUE(found_disable);
+    // Enable the property and inspect that .art artifact is larger.
+    bool found_enable = false;
+    ASSERT_TRUE(android::base::SetProperty(property, "true")) << property;
+    CompilePrimaryDexOk("speed-profile",
+                        DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PROFILE_GUIDED |
+                                DEXOPT_GENERATE_APP_IMAGE,
+                        app_oat_dir_.c_str(),
+                        kTestAppGid,
+                        DEX2OAT_FROM_SCRATCH);
+    run_cmd_and_process_output(
+            "oatdump --header-only --oat-file=" + odex,
+            [&](const std::string& line) {
+        if (line.find("--resolve-startup-const-strings=true") != std::string::npos) {
+            found_enable = true;
+        }
+    });
+    EXPECT_TRUE(found_enable);
+}
+
 class PrimaryDexReCompilationTest : public DexoptTest {
   public:
     virtual void SetUp() {
diff --git a/headers/media_plugin/media/cas/CasAPI.h b/headers/media_plugin/media/cas/CasAPI.h
index 4de314d..c87ee56 100644
--- a/headers/media_plugin/media/cas/CasAPI.h
+++ b/headers/media_plugin/media/cas/CasAPI.h
@@ -48,6 +48,14 @@
         uint8_t *data,
         size_t size);
 
+typedef void (*CasPluginCallbackExt)(
+        void *appData,
+        int32_t event,
+        int32_t arg,
+        uint8_t *data,
+        size_t size,
+        const CasSessionId *sessionId);
+
 struct CasFactory {
     CasFactory() {}
     virtual ~CasFactory() {}
@@ -67,6 +75,13 @@
             CasPluginCallback callback,
             CasPlugin **plugin) = 0;
 
+    // Construct a new extend instance of a CasPlugin given a CA_system_id
+    virtual status_t createPlugin(
+            int32_t CA_system_id,
+            void *appData,
+            CasPluginCallbackExt callback,
+            CasPlugin **plugin) = 0;
+
 private:
     CasFactory(const CasFactory &);
     CasFactory &operator=(const CasFactory &); /* NOLINT */
@@ -110,7 +125,15 @@
             int32_t arg,
             const CasData &eventData) = 0;
 
-    // Native implementation of the MediaCas Java API provision method.
+    // Deliver an session event to the CasPlugin. The format of the event is
+    // specific to the CA scheme and is opaque to the framework.
+    virtual status_t sendSessionEvent(
+            const CasSessionId &sessionId,
+            int32_t event,
+            int32_t arg,
+            const CasData &eventData) = 0;
+
+   // Native implementation of the MediaCas Java API provision method.
     virtual status_t provision(
             const String8 &provisionString) = 0;
 
diff --git a/headers/media_plugin/media/openmax/OMX_AsString.h b/headers/media_plugin/media/openmax/OMX_AsString.h
index 152015b..ce30b41 100644
--- a/headers/media_plugin/media/openmax/OMX_AsString.h
+++ b/headers/media_plugin/media/openmax/OMX_AsString.h
@@ -911,6 +911,9 @@
         case OMX_VIDEO_AVCLevel5:  return "Level5";
         case OMX_VIDEO_AVCLevel51: return "Level51";
         case OMX_VIDEO_AVCLevel52: return "Level52";
+        case OMX_VIDEO_AVCLevel6:  return "Level6";
+        case OMX_VIDEO_AVCLevel61: return "Level61";
+        case OMX_VIDEO_AVCLevel62: return "Level62";
         default:                   return def;
     }
 }
diff --git a/headers/media_plugin/media/openmax/OMX_Video.h b/headers/media_plugin/media/openmax/OMX_Video.h
index 9fd2fd2..b6edaa9 100644
--- a/headers/media_plugin/media/openmax/OMX_Video.h
+++ b/headers/media_plugin/media/openmax/OMX_Video.h
@@ -832,6 +832,9 @@
     OMX_VIDEO_AVCLevel5   = 0x4000,   /**< Level 5 */
     OMX_VIDEO_AVCLevel51  = 0x8000,   /**< Level 5.1 */
     OMX_VIDEO_AVCLevel52  = 0x10000,  /**< Level 5.2 */
+    OMX_VIDEO_AVCLevel6   = 0x20000,  /**< Level 6 */
+    OMX_VIDEO_AVCLevel61  = 0x40000,  /**< Level 6.1 */
+    OMX_VIDEO_AVCLevel62  = 0x80000,  /**< Level 6.2 */
     OMX_VIDEO_AVCLevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_VIDEO_AVCLevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_VIDEO_AVCLevelMax = 0x7FFFFFFF
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index f779d6e..49592a8 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -599,17 +599,53 @@
     return mHasFds;
 }
 
+void Parcel::updateWorkSourceRequestHeaderPosition() const {
+    // Only update the request headers once. We only want to point
+    // to the first headers read/written.
+    if (!mRequestHeaderPresent) {
+        mWorkSourceRequestHeaderPosition = dataPosition();
+        mRequestHeaderPresent = true;
+    }
+}
+
 // Write RPC headers.  (previously just the interface token)
 status_t Parcel::writeInterfaceToken(const String16& interface)
 {
     const IPCThreadState* threadState = IPCThreadState::self();
     writeInt32(threadState->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER);
+    updateWorkSourceRequestHeaderPosition();
     writeInt32(threadState->shouldPropagateWorkSource() ?
             threadState->getCallingWorkSourceUid() : IPCThreadState::kUnsetWorkSource);
     // currently the interface identification token is just its name as a string
     return writeString16(interface);
 }
 
+bool Parcel::replaceCallingWorkSourceUid(uid_t uid)
+{
+    if (!mRequestHeaderPresent) {
+        return false;
+    }
+
+    const size_t initialPosition = dataPosition();
+    setDataPosition(mWorkSourceRequestHeaderPosition);
+    status_t err = writeInt32(uid);
+    setDataPosition(initialPosition);
+    return err == NO_ERROR;
+}
+
+uid_t Parcel::readCallingWorkSourceUid()
+{
+    if (!mRequestHeaderPresent) {
+        return IPCThreadState::kUnsetWorkSource;
+    }
+
+    const size_t initialPosition = dataPosition();
+    setDataPosition(mWorkSourceRequestHeaderPosition);
+    uid_t uid = readInt32();
+    setDataPosition(initialPosition);
+    return uid;
+}
+
 bool Parcel::checkInterface(IBinder* binder) const
 {
     return enforceInterface(binder->getInterfaceDescriptor());
@@ -634,6 +670,7 @@
       threadState->setStrictModePolicy(strictPolicy);
     }
     // WorkSource.
+    updateWorkSourceRequestHeaderPosition();
     int32_t workSource = readInt32();
     threadState->setCallingWorkSourceUidWithoutPropagation(workSource);
     // Interface descriptor.
@@ -2889,6 +2926,8 @@
     mAllowFds = true;
     mOwner = nullptr;
     mOpenAshmemSize = 0;
+    mWorkSourceRequestHeaderPosition = 0;
+    mRequestHeaderPresent = false;
 
     // racing multiple init leads only to multiple identical write
     if (gMaxFds == 0) {
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 240b708..afdfe4f 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -395,6 +395,12 @@
     static size_t       getGlobalAllocSize();
     static size_t       getGlobalAllocCount();
 
+    bool                replaceCallingWorkSourceUid(uid_t uid);
+    // Returns the work source provided by the caller. This can only be trusted for trusted calling
+    // uid.
+    uid_t               readCallingWorkSourceUid();
+    void                readRequestHeaders() const;
+
 private:
     typedef void        (*release_func)(Parcel* parcel,
                                         const uint8_t* data, size_t dataSize,
@@ -429,6 +435,7 @@
     void                initState();
     void                scanForFds() const;
     status_t            validateReadData(size_t len) const;
+    void                updateWorkSourceRequestHeaderPosition() const;
                         
     template<class T>
     status_t            readAligned(T *pArg) const;
@@ -477,6 +484,9 @@
     mutable size_t      mNextObjectHint;
     mutable bool        mObjectsSorted;
 
+    mutable bool        mRequestHeaderPresent;
+    mutable size_t      mWorkSourceRequestHeaderPosition;
+
     mutable bool        mFdsKnown;
     mutable bool        mHasFds;
     bool                mAllowFds;
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 6091d3f..206bc30 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -98,8 +98,8 @@
     output.writeInt32(cachedBuffer.bufferId);
     output.writeParcelable(metadata);
 
-    output.writeFloat(colorAlpha);
-    output.writeUint32(static_cast<uint32_t>(colorDataspace));
+    output.writeFloat(bgColorAlpha);
+    output.writeUint32(static_cast<uint32_t>(bgColorDataspace));
 
     return NO_ERROR;
 }
@@ -175,8 +175,8 @@
     cachedBuffer.bufferId = input.readInt32();
     input.readParcelable(&metadata);
 
-    colorAlpha = input.readFloat();
-    colorDataspace = static_cast<ui::Dataspace>(input.readUint32());
+    bgColorAlpha = input.readFloat();
+    bgColorDataspace = static_cast<ui::Dataspace>(input.readUint32());
 
     return NO_ERROR;
 }
@@ -390,13 +390,11 @@
         what |= eCachedBufferChanged;
         cachedBuffer = other.cachedBuffer;
     }
-    if (other.what & eColorAlphaChanged) {
-        what |= eColorAlphaChanged;
-        colorAlpha = other.colorAlpha;
-    }
-    if (other.what & eColorDataspaceChanged) {
-        what |= eColorDataspaceChanged;
-        colorDataspace = other.colorDataspace;
+    if (other.what & eBackgroundColorChanged) {
+        what |= eBackgroundColorChanged;
+        color = other.color;
+        bgColorAlpha = other.bgColorAlpha;
+        bgColorDataspace = other.bgColorDataspace;
     }
     if (other.what & eMetadataChanged) {
         what |= eMetadataChanged;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index c712bde..51385b8 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -678,31 +678,18 @@
     return *this;
 }
 
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColorAlpha(
-        const sp<SurfaceControl>& sc, float alpha) {
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBackgroundColor(
+        const sp<SurfaceControl>& sc, const half3& color, float alpha, ui::Dataspace dataspace) {
     layer_state_t* s = getLayerState(sc);
     if (!s) {
         mStatus = BAD_INDEX;
         return *this;
     }
 
-    s->what |= layer_state_t::eColorAlphaChanged;
-    s->colorAlpha = alpha;
-
-    registerSurfaceControlForCallback(sc);
-    return *this;
-}
-
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColorDataspace(
-        const sp<SurfaceControl>& sc, ui::Dataspace dataspace) {
-    layer_state_t* s = getLayerState(sc);
-    if (!s) {
-        mStatus = BAD_INDEX;
-        return *this;
-    }
-
-    s->what |= layer_state_t::eColorDataspaceChanged;
-    s->colorDataspace = dataspace;
+    s->what |= layer_state_t::eBackgroundColorChanged;
+    s->color = color;
+    s->bgColorAlpha = alpha;
+    s->bgColorDataspace = dataspace;
 
     registerSurfaceControlForCallback(sc);
     return *this;
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 8e500a4..008f520 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -177,6 +177,12 @@
     return mHandle;
 }
 
+sp<IGraphicBufferProducer> SurfaceControl::getIGraphicBufferProducer() const
+{
+    Mutex::Autolock _l(mLock);
+    return mGraphicBufferProducer;
+}
+
 sp<SurfaceComposerClient> SurfaceControl::getClient() const
 {
     return mClient;
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index afd843f..c780c07 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -86,9 +86,8 @@
         eCornerRadiusChanged = 0x80000000,
         eFrameChanged = 0x1'00000000,
         eCachedBufferChanged = 0x2'00000000,
-        eColorAlphaChanged = 0x4'00000000,
-        eColorDataspaceChanged = 0x8'00000000,
-        eMetadataChanged = 0x10'00000000,
+        eBackgroundColorChanged = 0x4'00000000,
+        eMetadataChanged = 0x8'00000000,
     };
 
     layer_state_t()
@@ -115,8 +114,8 @@
             surfaceDamageRegion(),
             api(-1),
             colorTransform(mat4()),
-            colorAlpha(0),
-            colorDataspace(ui::Dataspace::UNKNOWN) {
+            bgColorAlpha(0),
+            bgColorDataspace(ui::Dataspace::UNKNOWN) {
         matrix.dsdx = matrix.dtdy = 1.0f;
         matrix.dsdy = matrix.dtdx = 0.0f;
         hdrMetadata.validTypes = 0;
@@ -187,10 +186,12 @@
 
     cached_buffer_t cachedBuffer;
 
-    float colorAlpha;
-    ui::Dataspace colorDataspace;
-
     LayerMetadata metadata;
+
+    // The following refer to the alpha, and dataspace, respectively of
+    // the background color layer
+    float bgColorAlpha;
+    ui::Dataspace bgColorDataspace;
 };
 
 struct ComposerState {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 8e2bb2b..a95664b 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -330,11 +330,9 @@
 
         Transaction& setColor(const sp<SurfaceControl>& sc, const half3& color);
 
-        // Sets the alpha of the background color layer if it exists.
-        Transaction& setColorAlpha(const sp<SurfaceControl>& sc, float alpha);
-
-        // Sets the dataspace of the background color layer if it exists.
-        Transaction& setColorDataspace(const sp<SurfaceControl>& sc, ui::Dataspace dataspace);
+        // Sets the background color of a layer with the specified color, alpha, and dataspace
+        Transaction& setBackgroundColor(const sp<SurfaceControl>& sc, const half3& color,
+                                        float alpha, ui::Dataspace dataspace);
 
         Transaction& setTransform(const sp<SurfaceControl>& sc, uint32_t transform);
         Transaction& setTransformToDisplayInverse(const sp<SurfaceControl>& sc,
diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
index 9bba766..b584f36 100644
--- a/libs/gui/include/gui/SurfaceControl.h
+++ b/libs/gui/include/gui/SurfaceControl.h
@@ -71,6 +71,8 @@
     sp<Surface> createSurface() const;
     sp<IBinder> getHandle() const;
 
+    sp<IGraphicBufferProducer> getIGraphicBufferProducer() const;
+
     status_t clearLayerFrameStats() const;
     status_t getLayerFrameStats(FrameStats* outStats) const;
 
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index 2c4b5f3..92ea07c 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -94,7 +94,7 @@
     mMapperV2_1 = IMapper::castFrom(mMapper);
 }
 
-bool Gralloc2Mapper::isSupported() const {
+bool Gralloc2Mapper::isLoaded() const {
     return mMapper != nullptr;
 }
 
@@ -359,7 +359,7 @@
     }
 }
 
-bool Gralloc2Allocator::isSupported() const {
+bool Gralloc2Allocator::isLoaded() const {
     return mAllocator != nullptr;
 }
 
diff --git a/libs/ui/Gralloc3.cpp b/libs/ui/Gralloc3.cpp
index acb6b01..306a74b 100644
--- a/libs/ui/Gralloc3.cpp
+++ b/libs/ui/Gralloc3.cpp
@@ -92,7 +92,7 @@
     }
 }
 
-bool Gralloc3Mapper::isSupported() const {
+bool Gralloc3Mapper::isLoaded() const {
     return mMapper != nullptr;
 }
 
@@ -322,7 +322,7 @@
     }
 }
 
-bool Gralloc3Allocator::isSupported() const {
+bool Gralloc3Allocator::isLoaded() const {
     return mAllocator != nullptr;
 }
 
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index da24cf1..15597eb 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -236,15 +236,15 @@
     return NO_ERROR;
 }
 
-status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr)
-{
+status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr, int32_t* outBytesPerPixel,
+                             int32_t* outBytesPerStride) {
     const Rect lockBounds(width, height);
-    status_t res = lock(inUsage, lockBounds, vaddr);
+    status_t res = lock(inUsage, lockBounds, vaddr, outBytesPerPixel, outBytesPerStride);
     return res;
 }
 
-status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr)
-{
+status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr,
+                             int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
     if (rect.left < 0 || rect.right  > width ||
         rect.top  < 0 || rect.bottom > height) {
         ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
@@ -252,10 +252,10 @@
                 width, height);
         return BAD_VALUE;
     }
-    int32_t bytesPerPixel, bytesPerStride;
 
-    status_t res =
-            getBufferMapper().lock(handle, inUsage, rect, vaddr, &bytesPerPixel, &bytesPerStride);
+    status_t res = getBufferMapper().lock(handle, inUsage, rect, vaddr, outBytesPerPixel,
+                                          outBytesPerStride);
+
     return res;
 }
 
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index efb5798..5a67dc4 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -48,12 +48,12 @@
 GraphicBufferAllocator::GraphicBufferAllocator() : mMapper(GraphicBufferMapper::getInstance()) {
     mAllocator = std::make_unique<const Gralloc3Allocator>(
             reinterpret_cast<const Gralloc3Mapper&>(mMapper.getGrallocMapper()));
-    if (!mAllocator->isSupported()) {
+    if (!mAllocator->isLoaded()) {
         mAllocator = std::make_unique<const Gralloc2Allocator>(
                 reinterpret_cast<const Gralloc2Mapper&>(mMapper.getGrallocMapper()));
     }
 
-    if (!mAllocator->isSupported()) {
+    if (!mAllocator->isLoaded()) {
         LOG_ALWAYS_FATAL("gralloc-allocator is missing");
     }
 }
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index 9e36377..79c333f 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -51,11 +51,11 @@
 
 GraphicBufferMapper::GraphicBufferMapper() {
     mMapper = std::make_unique<const Gralloc3Mapper>();
-    if (!mMapper->isSupported()) {
+    if (!mMapper->isLoaded()) {
         mMapper = std::make_unique<const Gralloc2Mapper>();
     }
 
-    if (!mMapper->isSupported()) {
+    if (!mMapper->isLoaded()) {
         LOG_ALWAYS_FATAL("gralloc-mapper is missing");
     }
 }
diff --git a/libs/ui/include/ui/Gralloc.h b/libs/ui/include/ui/Gralloc.h
index a484bce..1b8a930 100644
--- a/libs/ui/include/ui/Gralloc.h
+++ b/libs/ui/include/ui/Gralloc.h
@@ -31,7 +31,7 @@
 public:
     virtual ~GrallocMapper();
 
-    virtual bool isSupported() const = 0;
+    virtual bool isLoaded() const = 0;
 
     virtual status_t createDescriptor(void* bufferDescriptorInfo,
                                       void* outBufferDescriptor) const = 0;
@@ -74,7 +74,7 @@
 public:
     virtual ~GrallocAllocator();
 
-    virtual bool isSupported() const = 0;
+    virtual bool isLoaded() const = 0;
 
     virtual std::string dumpDebugInfo() const = 0;
 
diff --git a/libs/ui/include/ui/Gralloc2.h b/libs/ui/include/ui/Gralloc2.h
index b23d8f7..4ef9b51 100644
--- a/libs/ui/include/ui/Gralloc2.h
+++ b/libs/ui/include/ui/Gralloc2.h
@@ -36,7 +36,7 @@
 
     Gralloc2Mapper();
 
-    bool isSupported() const override;
+    bool isLoaded() const override;
 
     status_t createDescriptor(void* bufferDescriptorInfo, void* outBufferDescriptor) const override;
 
@@ -76,7 +76,7 @@
     // time.
     Gralloc2Allocator(const Gralloc2Mapper& mapper);
 
-    bool isSupported() const override;
+    bool isLoaded() const override;
 
     std::string dumpDebugInfo() const override;
 
diff --git a/libs/ui/include/ui/Gralloc3.h b/libs/ui/include/ui/Gralloc3.h
index b0cbcc1..879e96e 100644
--- a/libs/ui/include/ui/Gralloc3.h
+++ b/libs/ui/include/ui/Gralloc3.h
@@ -35,7 +35,7 @@
 
     Gralloc3Mapper();
 
-    bool isSupported() const override;
+    bool isLoaded() const override;
 
     status_t createDescriptor(void* bufferDescriptorInfo, void* outBufferDescriptor) const override;
 
@@ -74,7 +74,7 @@
     // time.
     Gralloc3Allocator(const Gralloc3Mapper& mapper);
 
-    bool isSupported() const override;
+    bool isLoaded() const override;
 
     std::string dumpDebugInfo() const override;
 
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index b73ca2b..18a27a0 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -169,8 +169,12 @@
     bool needsReallocation(uint32_t inWidth, uint32_t inHeight,
             PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage);
 
-    status_t lock(uint32_t inUsage, void** vaddr);
-    status_t lock(uint32_t inUsage, const Rect& rect, void** vaddr);
+    // For the following two lock functions, if bytesPerStride or bytesPerPixel
+    // are unknown or variable, -1 will be returned
+    status_t lock(uint32_t inUsage, void** vaddr, int32_t* outBytesPerPixel = nullptr,
+                  int32_t* outBytesPerStride = nullptr);
+    status_t lock(uint32_t inUsage, const Rect& rect, void** vaddr,
+                  int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr);
     // For HAL_PIXEL_FORMAT_YCbCr_420_888
     status_t lockYCbCr(uint32_t inUsage, android_ycbcr *ycbcr);
     status_t lockYCbCr(uint32_t inUsage, const Rect& rect,
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index a47a98f..527a27d 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -10,6 +10,7 @@
 #include <mutex>
 #include <thread>
 
+namespace {
 #define RETRY_EINTR(fnc_call)                 \
   ([&]() -> decltype(fnc_call) {              \
     decltype(fnc_call) result;                \
@@ -30,6 +31,7 @@
 using android::dvr::ProducerBuffer;
 using android::pdx::LocalHandle;
 using android::pdx::Status;
+using LibBufferHubTest = ::testing::Test;
 
 const int kWidth = 640;
 const int kHeight = 480;
@@ -41,7 +43,15 @@
     android::BufferHubDefs::kMaxNumberOfClients - 1;
 const int kPollTimeoutMs = 100;
 
-using LibBufferHubTest = ::testing::Test;
+// Helper function to poll the eventfd in BufferHubBase.
+template <class BufferHubBase>
+int PollBufferEvent(const std::unique_ptr<BufferHubBase>& buffer,
+                    int timeout_ms = kPollTimeoutMs) {
+  pollfd p = {buffer->event_fd(), POLLIN, 0};
+  return poll(&p, 1, timeout_ms);
+}
+
+}  // namespace
 
 TEST_F(LibBufferHubTest, TestBasicUsage) {
   std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
@@ -61,36 +71,36 @@
   EXPECT_EQ(c2->client_state_mask(), kFirstClientBitMask << 2);
 
   // Initial state: producer not available, consumers not available.
-  EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
-  EXPECT_EQ(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
-  EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(p)));
+  EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(c1)));
+  EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(c2)));
 
   EXPECT_EQ(0, p->GainAsync());
   EXPECT_EQ(0, p->Post(LocalHandle()));
 
   // New state: producer not available, consumers available.
-  EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
-  EXPECT_EQ(1, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
-  EXPECT_EQ(1, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(p)));
+  EXPECT_EQ(1, RETRY_EINTR(PollBufferEvent(c1)));
+  EXPECT_EQ(1, RETRY_EINTR(PollBufferEvent(c2)));
 
   LocalHandle fence;
   EXPECT_EQ(0, c1->Acquire(&fence));
-  EXPECT_EQ(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
-  EXPECT_EQ(1, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(c1)));
+  EXPECT_EQ(1, RETRY_EINTR(PollBufferEvent(c2)));
 
   EXPECT_EQ(0, c2->Acquire(&fence));
-  EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
-  EXPECT_EQ(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(c2)));
+  EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(c1)));
 
   EXPECT_EQ(0, c1->Release(LocalHandle()));
-  EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(p)));
   EXPECT_EQ(0, c2->Discard());
-  EXPECT_EQ(1, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(1, RETRY_EINTR(PollBufferEvent(p)));
 
   EXPECT_EQ(0, p->Gain(&fence));
-  EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
-  EXPECT_EQ(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
-  EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(p)));
+  EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(c1)));
+  EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(c2)));
 }
 
 TEST_F(LibBufferHubTest, TestEpoll) {
@@ -225,7 +235,7 @@
 
   // Release in acquired state should succeed.
   EXPECT_EQ(0, c->Release(LocalHandle()));
-  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p)));
 
   // Acquire and post in released state should fail.
   EXPECT_EQ(-EBUSY, c->Acquire(&fence));
@@ -266,7 +276,7 @@
   EXPECT_FALSE(invalid_fence.IsValid());
 
   // Acquire in posted state should succeed.
-  EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c)));
   EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
   EXPECT_FALSE(invalid_fence.IsValid());
   EXPECT_EQ(p->buffer_state(), c->buffer_state());
@@ -281,7 +291,7 @@
 
   // Release in acquired state should succeed.
   EXPECT_EQ(0, c->ReleaseAsync(&metadata, invalid_fence));
-  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p)));
   EXPECT_EQ(p->buffer_state(), c->buffer_state());
   EXPECT_TRUE(p->is_released());
 
@@ -387,7 +397,7 @@
   for (size_t i = 0; i < kMaxConsumerCount; ++i) {
     EXPECT_TRUE(
         IsClientPosted(cs[i]->buffer_state(), cs[i]->client_state_mask()));
-    EXPECT_LT(0, RETRY_EINTR(cs[i]->Poll(kPollTimeoutMs)));
+    EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(cs[i])));
     EXPECT_EQ(0, cs[i]->AcquireAsync(&metadata, &invalid_fence));
     EXPECT_TRUE(
         IsClientAcquired(p->buffer_state(), cs[i]->client_state_mask()));
@@ -400,7 +410,7 @@
     EXPECT_EQ(0, cs[i]->ReleaseAsync(&metadata, invalid_fence));
   }
 
-  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p)));
   EXPECT_TRUE(p->is_released());
 
   // Buffer state cross all clients must be consistent.
@@ -427,7 +437,7 @@
   // Post the gained buffer should signal already created consumer.
   EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
   EXPECT_TRUE(AnyClientPosted(p->buffer_state()));
-  EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c)));
   EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
   EXPECT_TRUE(AnyClientAcquired(c->buffer_state()));
 }
@@ -445,7 +455,7 @@
   // Post the gained buffer before any consumer gets created.
   EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
   EXPECT_TRUE(p->is_released());
-  EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(p)));
 
   // Newly created consumer will be signalled for the posted buffer although it
   // is created after producer posting.
@@ -471,7 +481,7 @@
 
   // Post, acquire, and release the buffer..
   EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
-  EXPECT_LT(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c1)));
   EXPECT_EQ(0, c1->AcquireAsync(&metadata, &invalid_fence));
   EXPECT_EQ(0, c1->ReleaseAsync(&metadata, invalid_fence));
 
@@ -479,7 +489,7 @@
   // executed before Release impulse gets executed by bufferhubd. Thus, here we
   // need to wait until the releasd is confirmed before creating another
   // consumer.
-  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p)));
   EXPECT_TRUE(p->is_released());
 
   // Create another consumer immediately after the release, should not make the
@@ -507,14 +517,14 @@
   EXPECT_EQ(0, p->GainAsync());
   Metadata m = {1, 3};
   EXPECT_EQ(0, p->Post(LocalHandle(), &m, sizeof(Metadata)));
-  EXPECT_LE(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+  EXPECT_LE(0, RETRY_EINTR(PollBufferEvent(c)));
   LocalHandle fence;
   Metadata m2 = {};
   EXPECT_EQ(0, c->Acquire(&fence, &m2, sizeof(m2)));
   EXPECT_EQ(m.field1, m2.field1);
   EXPECT_EQ(m.field2, m2.field2);
   EXPECT_EQ(0, c->Release(LocalHandle()));
-  EXPECT_LT(0, RETRY_EINTR(p->Poll(0)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p, /*timeout_ms=*/0)));
 }
 
 TEST_F(LibBufferHubTest, TestPostWithWrongMetaSize) {
@@ -539,7 +549,7 @@
   // buffer allocation.
   OverSizedMetadata evil_meta = {};
   EXPECT_NE(0, p->Post(LocalHandle(), &evil_meta, sizeof(OverSizedMetadata)));
-  EXPECT_GE(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+  EXPECT_GE(0, RETRY_EINTR(PollBufferEvent(c)));
 
   // It is ok to post metadata smaller than originally requested during
   // buffer allocation.
@@ -651,7 +661,7 @@
 
   // Should acquire a valid fence.
   LocalHandle f2;
-  EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c)));
   EXPECT_EQ(0, c->AcquireAsync(&meta, &f2));
   EXPECT_TRUE(f2.IsValid());
   // The original fence and acquired fence should have different fd number.
@@ -668,7 +678,7 @@
 
   // Should gain an invalid fence.
   LocalHandle f3;
-  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p)));
   EXPECT_EQ(0, p->GainAsync(&meta, &f3));
   EXPECT_FALSE(f3.IsValid());
 
@@ -677,7 +687,7 @@
 
   // Should acquire a valid fence and it's already signalled.
   LocalHandle f4;
-  EXPECT_LT(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c)));
   EXPECT_EQ(0, c->AcquireAsync(&meta, &f4));
   EXPECT_TRUE(f4.IsValid());
   EXPECT_LT(0, PollFd(f4.Get(), kPollTimeoutMs));
@@ -690,7 +700,7 @@
 
   // Should gain a valid fence, which is already signaled.
   LocalHandle f6;
-  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p)));
   EXPECT_EQ(0, p->GainAsync(&meta, &f6));
   EXPECT_TRUE(f6.IsValid());
   EXPECT_LT(0, PollFd(f6.Get(), kPollTimeoutMs));
@@ -710,14 +720,14 @@
   EXPECT_EQ(0, p->PostAsync(&meta, LocalHandle()));
 
   LocalHandle fence;
-  EXPECT_LT(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c1)));
   EXPECT_EQ(0, c1->AcquireAsync(&meta, &fence));
 
   // Destroy the consumer who has acquired but not released the buffer.
   c1 = nullptr;
 
   // The buffer is now available for the producer to gain.
-  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p)));
 
   // Newly added consumer is not able to acquire the buffer.
   std::unique_ptr<ConsumerBuffer> c2 =
@@ -725,7 +735,7 @@
   ASSERT_TRUE(c2.get() != nullptr);
   const uint32_t client_state_mask2 = c2->client_state_mask();
   EXPECT_NE(client_state_mask1, client_state_mask2);
-  EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
+  EXPECT_EQ(0, RETRY_EINTR(PollBufferEvent(c2)));
   EXPECT_EQ(-EBUSY, c2->AcquireAsync(&meta, &fence));
 
   // Producer should be able to gain.
@@ -744,7 +754,7 @@
   EXPECT_EQ(0, p->GainAsync());
   DvrNativeBufferMetadata meta;
   EXPECT_EQ(0, p->PostAsync(&meta, LocalHandle()));
-  EXPECT_LT(0, RETRY_EINTR(c1->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c1)));
 
   // c2 is created when the buffer is in posted state. buffer state for c1 is
   // posted. Thus, c2 should be automatically set to posted and able to acquire.
@@ -753,7 +763,7 @@
   ASSERT_TRUE(c2.get() != nullptr);
   const uint32_t client_state_mask2 = c2->client_state_mask();
   EXPECT_NE(client_state_mask1, client_state_mask2);
-  EXPECT_LT(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c2)));
   LocalHandle invalid_fence;
   EXPECT_EQ(0, c2->AcquireAsync(&meta, &invalid_fence));
 
@@ -768,7 +778,7 @@
   const uint32_t client_state_mask3 = c3->client_state_mask();
   EXPECT_NE(client_state_mask1, client_state_mask3);
   EXPECT_NE(client_state_mask2, client_state_mask3);
-  EXPECT_LT(0, RETRY_EINTR(c3->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c3)));
   EXPECT_EQ(0, c3->AcquireAsync(&meta, &invalid_fence));
 
   // Releasing c2 and c3 in normal ways.
@@ -779,7 +789,7 @@
   c1 = nullptr;
 
   // The buffer is now available for the producer to gain.
-  EXPECT_LT(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
+  EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(p)));
 
   // C4 is created in released state. Thus, it cannot gain the just posted
   // buffer.
@@ -788,7 +798,7 @@
   ASSERT_TRUE(c4.get() != nullptr);
   const uint32_t client_state_mask4 = c4->client_state_mask();
   EXPECT_NE(client_state_mask3, client_state_mask4);
-  EXPECT_GE(0, RETRY_EINTR(c3->Poll(kPollTimeoutMs)));
+  EXPECT_GE(0, RETRY_EINTR(PollBufferEvent(c3)));
   EXPECT_EQ(-EBUSY, c3->AcquireAsync(&meta, &invalid_fence));
 
   // Producer should be able to gain.
@@ -813,7 +823,7 @@
   // Detach in posted state should fail.
   EXPECT_EQ(0, p->GainAsync());
   EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
-  EXPECT_GT(RETRY_EINTR(c->Poll(kPollTimeoutMs)), 0);
+  EXPECT_GT(RETRY_EINTR(PollBufferEvent(c)), 0);
   auto s1 = p->Detach();
   EXPECT_FALSE(s1);
 
@@ -824,7 +834,7 @@
 
   // Detach in released state should fail.
   EXPECT_EQ(0, c->ReleaseAsync(&metadata, invalid_fence));
-  EXPECT_GT(RETRY_EINTR(p->Poll(kPollTimeoutMs)), 0);
+  EXPECT_GT(RETRY_EINTR(PollBufferEvent(p)), 0);
   s1 = p->Detach();
   EXPECT_FALSE(s1);
 
@@ -837,12 +847,12 @@
   EXPECT_TRUE(handle.valid());
 
   // Both producer and consumer should have hangup.
-  EXPECT_GT(RETRY_EINTR(p->Poll(kPollTimeoutMs)), 0);
+  EXPECT_GT(RETRY_EINTR(PollBufferEvent(p)), 0);
   auto s2 = p->GetEventMask(POLLHUP);
   EXPECT_TRUE(s2);
   EXPECT_EQ(s2.get(), POLLHUP);
 
-  EXPECT_GT(RETRY_EINTR(c->Poll(kPollTimeoutMs)), 0);
+  EXPECT_GT(RETRY_EINTR(PollBufferEvent(c)), 0);
   s2 = p->GetEventMask(POLLHUP);
   EXPECT_TRUE(s2);
   EXPECT_EQ(s2.get(), POLLHUP);
diff --git a/libs/vr/libbufferhub/buffer_hub_base.cpp b/libs/vr/libbufferhub/buffer_hub_base.cpp
index 7d49482..b28d101 100644
--- a/libs/vr/libbufferhub/buffer_hub_base.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_base.cpp
@@ -196,12 +196,6 @@
   return 0;
 }
 
-int BufferHubBase::Poll(int timeout_ms) {
-  ATRACE_NAME("BufferHubBase::Poll");
-  pollfd p = {event_fd(), POLLIN, 0};
-  return poll(&p, 1, timeout_ms);
-}
-
 int BufferHubBase::Lock(int usage, int x, int y, int width, int height,
                         void** address) {
   return buffer_.Lock(usage, x, y, width, height, address);
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
index 1018f27..b6027e6 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
@@ -21,9 +21,6 @@
   // a file descriptor for the new channel or a negative error code.
   Status<LocalChannelHandle> CreateConsumer();
 
-  // Polls the fd for |timeout_ms| milliseconds (-1 for infinity).
-  int Poll(int timeout_ms);
-
   // Locks the area specified by (x, y, width, height) for a specific usage. If
   // the usage is software then |addr| will be updated to point to the address
   // of the buffer in virtual memory. The caller should only access/modify the
diff --git a/services/inputflinger/InputClassifier.h b/services/inputflinger/InputClassifier.h
index 1f7dd41..cb46494 100644
--- a/services/inputflinger/InputClassifier.h
+++ b/services/inputflinger/InputClassifier.h
@@ -162,15 +162,6 @@
     std::unordered_map<int32_t /*deviceId*/, nsecs_t /*downTime*/>
             mLastDownTimes; //GUARDED_BY(mLock);
     void updateLastDownTime(int32_t deviceId, nsecs_t downTime);
-    // Should only be accessed through isResetNeeded() and setResetNeeded()
-    bool mResetNeeded = false; //GUARDED_BY(mLock);
-    /**
-     * Check whether reset should be performed. Reset should be performed
-     * if the eventTime of the current event is older than mLastDownTime,
-     * i.e. a new gesture has already begun, but an older gesture is still being processed.
-     */
-    bool isResetNeeded(nsecs_t eventTime);
-    void setResetNeeded(bool isNeeded);
 
     /**
      * Exit the InputClassifier HAL thread.
@@ -188,11 +179,12 @@
 class InputClassifier : public InputClassifierInterface {
 public:
     explicit InputClassifier(const sp<InputListenerInterface>& listener);
-    virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args);
-    virtual void notifyKey(const NotifyKeyArgs* args);
-    virtual void notifyMotion(const NotifyMotionArgs* args);
-    virtual void notifySwitch(const NotifySwitchArgs* args);
-    virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);
+
+    virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
+    virtual void notifyKey(const NotifyKeyArgs* args) override;
+    virtual void notifyMotion(const NotifyMotionArgs* args) override;
+    virtual void notifySwitch(const NotifySwitchArgs* args) override;
+    virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
 
 private:
     std::unique_ptr<MotionClassifierInterface> mMotionClassifier = nullptr;
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index c411ec0..fe1d4d0 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -268,7 +268,7 @@
             pointerGestureSwipeMaxWidthRatio(0.25f),
             pointerGestureMovementSpeedRatio(0.8f),
             pointerGestureZoomSpeedRatio(0.3f),
-            showTouches(false) { }
+            showTouches(false), pointerCapture(false) { }
 
     std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const;
     std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueDisplayId)
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index e0e211f..0f987c3 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -444,7 +444,7 @@
     }
 
     virtual bool updateInfo() {
-        mInfo.token = mServerChannel->getToken();
+        mInfo.token = mServerChannel ? mServerChannel->getToken() : nullptr;
         mInfo.name = mName;
         mInfo.layoutParamsFlags = 0;
         mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
@@ -474,8 +474,8 @@
     }
 
     void releaseChannel() {
+        mServerChannel.clear();
         InputWindowHandle::releaseChannel();
-        mDispatcher->unregisterInputChannel(mServerChannel);
     }
 protected:
     virtual bool handled() {
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 2a70293..4c4ee06 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -128,7 +128,6 @@
         "DisplayHardware/FramebufferSurface.cpp",
         "DisplayHardware/HWC2.cpp",
         "DisplayHardware/HWComposer.cpp",
-        "DisplayHardware/HWComposerBufferCache.cpp",
         "DisplayHardware/PowerAdvisor.cpp",
         "DisplayHardware/VirtualDisplaySurface.cpp",
         "Effects/Daltonizer.cpp",
@@ -152,6 +151,7 @@
         "Scheduler/MessageQueue.cpp",
         "Scheduler/Scheduler.cpp",
         "Scheduler/SchedulerUtils.cpp",
+        "Scheduler/PhaseOffsets.cpp",
         "StartPropertySetThread.cpp",
         "SurfaceFlinger.cpp",
         "SurfaceInterceptor.cpp",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 9662fcd..f986329 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -19,6 +19,28 @@
 #define LOG_TAG "BufferLayer"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
+#include <cmath>
+#include <cstdlib>
+#include <mutex>
+
+#include <compositionengine/CompositionEngine.h>
+#include <compositionengine/Layer.h>
+#include <compositionengine/LayerCreationArgs.h>
+#include <cutils/compiler.h>
+#include <cutils/native_handle.h>
+#include <cutils/properties.h>
+#include <gui/BufferItem.h>
+#include <gui/BufferQueue.h>
+#include <gui/LayerDebugInfo.h>
+#include <gui/Surface.h>
+#include <renderengine/RenderEngine.h>
+#include <ui/DebugUtils.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/NativeHandle.h>
+#include <utils/StopWatch.h>
+#include <utils/Trace.h>
+
 #include "BufferLayer.h"
 #include "Colorizer.h"
 #include "DisplayDevice.h"
@@ -26,33 +48,13 @@
 
 #include "TimeStats/TimeStats.h"
 
-#include <renderengine/RenderEngine.h>
-
-#include <gui/BufferItem.h>
-#include <gui/BufferQueue.h>
-#include <gui/LayerDebugInfo.h>
-#include <gui/Surface.h>
-
-#include <ui/DebugUtils.h>
-
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <utils/NativeHandle.h>
-#include <utils/StopWatch.h>
-#include <utils/Trace.h>
-
-#include <cutils/compiler.h>
-#include <cutils/native_handle.h>
-#include <cutils/properties.h>
-
-#include <math.h>
-#include <stdlib.h>
-#include <mutex>
-
 namespace android {
 
 BufferLayer::BufferLayer(const LayerCreationArgs& args)
-      : Layer(args), mTextureName(args.flinger->getNewTexture()) {
+      : Layer(args),
+        mTextureName(args.flinger->getNewTexture()),
+        mCompositionLayer{mFlinger->getCompositionEngine().createLayer(
+                compositionengine::LayerCreationArgs{this})} {
     ALOGV("Creating Layer %s", args.name.string());
 
     mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied);
@@ -649,6 +651,10 @@
     return Rect(bufWidth, bufHeight);
 }
 
+std::shared_ptr<compositionengine::Layer> BufferLayer::getCompositionLayer() const {
+    return mCompositionLayer;
+}
+
 } // namespace android
 
 #if defined(__gl_h_)
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 3fe8ed0..d0c1b13 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -16,35 +16,32 @@
 
 #pragma once
 
-#include "BufferLayerConsumer.h"
-#include "Client.h"
-#include "Layer.h"
-#include "DisplayHardware/HWComposer.h"
-#include "DisplayHardware/HWComposerBufferCache.h"
-#include "FrameTracker.h"
-#include "LayerVector.h"
-#include "MonitoredProducer.h"
-#include "SurfaceFlinger.h"
+#include <sys/types.h>
+#include <cstdint>
+#include <list>
 
 #include <gui/ISurfaceComposerClient.h>
 #include <gui/LayerState.h>
 #include <renderengine/Image.h>
 #include <renderengine/Mesh.h>
 #include <renderengine/Texture.h>
+#include <system/window.h> // For NATIVE_WINDOW_SCALING_MODE_FREEZE
 #include <ui/FrameStats.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
 #include <ui/Region.h>
-
 #include <utils/RefBase.h>
 #include <utils/String8.h>
 #include <utils/Timers.h>
 
-#include <system/window.h> // For NATIVE_WINDOW_SCALING_MODE_FREEZE
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <list>
+#include "BufferLayerConsumer.h"
+#include "Client.h"
+#include "DisplayHardware/HWComposer.h"
+#include "FrameTracker.h"
+#include "Layer.h"
+#include "LayerVector.h"
+#include "MonitoredProducer.h"
+#include "SurfaceFlinger.h"
 
 namespace android {
 
@@ -57,6 +54,8 @@
     // Overriden from Layer
     // -----------------------------------------------------------------------
 public:
+    std::shared_ptr<compositionengine::Layer> getCompositionLayer() const override;
+
     // If we have received a new buffer this frame, we will pass its surface
     // damage down to hardware composer. Otherwise, we must send a region with
     // one empty rect.
@@ -187,6 +186,8 @@
     bool mBufferLatched{false}; // TODO: Use mActiveBuffer?
 
     Rect getBufferSize(const State& s) const override;
+
+    std::shared_ptr<compositionengine::Layer> mCompositionLayer;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 96a66cb..2005d20 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -303,48 +303,6 @@
     return true;
 }
 
-bool BufferStateLayer::setColor(const half3& color) {
-    // create color layer if one does not yet exist
-    if (!mCurrentState.bgColorLayer) {
-        uint32_t flags = ISurfaceComposerClient::eFXSurfaceColor;
-        const String8& name = mName + "BackgroundColorLayer";
-        mCurrentState.bgColorLayer =
-                new ColorLayer(LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, flags));
-
-        // add to child list
-        addChild(mCurrentState.bgColorLayer);
-        mFlinger->mLayersAdded = true;
-        // set up SF to handle added color layer
-        if (isRemovedFromCurrentState()) {
-            mCurrentState.bgColorLayer->onRemovedFromCurrentState();
-        }
-        mFlinger->setTransactionFlags(eTransactionNeeded);
-    }
-
-    mCurrentState.bgColorLayer->setColor(color);
-    mCurrentState.bgColorLayer->setLayer(std::numeric_limits<int32_t>::min());
-
-    return true;
-}
-
-bool BufferStateLayer::setColorAlpha(float alpha) {
-    if (!mCurrentState.bgColorLayer) {
-        ALOGE("Attempting to set color alpha on a buffer state layer with no background color");
-        return false;
-    }
-    mCurrentState.bgColorLayer->setAlpha(alpha);
-    return true;
-}
-
-bool BufferStateLayer::setColorDataspace(ui::Dataspace dataspace) {
-    if (!mCurrentState.bgColorLayer) {
-        ALOGE("Attempting to set color dataspace on a buffer state layer with no background color");
-        return false;
-    }
-    mCurrentState.bgColorLayer->setDataspace(dataspace);
-    return true;
-}
-
 Rect BufferStateLayer::getBufferSize(const State& s) const {
     // for buffer state layers we use the display frame size as the buffer size.
     if (getActiveWidth(s) < UINT32_MAX && getActiveHeight(s) < UINT32_MAX) {
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index bef9f19..138bb4c 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -82,9 +82,6 @@
     }
     bool setCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; }
     bool setOverrideScalingMode(int32_t /*overrideScalingMode*/) override { return false; }
-    bool setColor(const half3& color) override;
-    bool setColorAlpha(float alpha) override;
-    bool setColorDataspace(ui::Dataspace dataspace) override;
     void deferTransactionUntil_legacy(const sp<IBinder>& /*barrierHandle*/,
                                       uint64_t /*frameNumber*/) override {}
     void deferTransactionUntil_legacy(const sp<Layer>& /*barrierLayer*/,
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index 34082c3..d82ff0e 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -22,6 +22,9 @@
 #include <stdlib.h>
 #include <sys/types.h>
 
+#include <compositionengine/CompositionEngine.h>
+#include <compositionengine/Layer.h>
+#include <compositionengine/LayerCreationArgs.h>
 #include <renderengine/RenderEngine.h>
 #include <ui/GraphicBuffer.h>
 #include <utils/Errors.h>
@@ -34,7 +37,10 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-ColorLayer::ColorLayer(const LayerCreationArgs& args) : Layer(args) {}
+ColorLayer::ColorLayer(const LayerCreationArgs& args)
+      : Layer(args),
+        mCompositionLayer{mFlinger->getCompositionEngine().createLayer(
+                compositionengine::LayerCreationArgs{this})} {}
 
 ColorLayer::~ColorLayer() = default;
 
@@ -52,6 +58,21 @@
     return !isHiddenByPolicy() && getAlpha() > 0.0f;
 }
 
+bool ColorLayer::setColor(const half3& color) {
+    if (mCurrentState.color.r == color.r && mCurrentState.color.g == color.g &&
+        mCurrentState.color.b == color.b) {
+        return false;
+    }
+
+    mCurrentState.sequence++;
+    mCurrentState.color.r = color.r;
+    mCurrentState.color.g = color.g;
+    mCurrentState.color.b = color.b;
+    mCurrentState.modified = true;
+    setTransactionFlags(eTransactionNeeded);
+    return true;
+}
+
 void ColorLayer::setPerFrameData(DisplayId displayId, const ui::Transform& transform,
                                  const Rect& viewport, int32_t /* supportedPerFrameMetadata */) {
     RETURN_IF_NO_HWC_LAYER(displayId);
@@ -113,6 +134,10 @@
     getBE().compositionInfo.hwc.surfaceDamage = surfaceDamageRegion;
 }
 
+std::shared_ptr<compositionengine::Layer> ColorLayer::getCompositionLayer() const {
+    return mCompositionLayer;
+}
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index f43fc3c..ed4c2d8 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -28,9 +28,13 @@
     explicit ColorLayer(const LayerCreationArgs&);
     ~ColorLayer() override;
 
+    std::shared_ptr<compositionengine::Layer> getCompositionLayer() const override;
+
     virtual const char* getTypeId() const { return "ColorLayer"; }
     bool isVisible() const override;
 
+    bool setColor(const half3& color) override;
+
     void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport,
                          int32_t supportedPerFrameMetadata) override;
 
@@ -41,6 +45,9 @@
     virtual bool prepareClientLayer(const RenderArea& renderArea, const Region& clip,
                                     bool useIdentityTransform, Region& clearRegion,
                                     renderengine::LayerSettings& layer);
+
+private:
+    std::shared_ptr<compositionengine::Layer> mCompositionLayer;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index 49fa84a..ce6b06c 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -41,8 +41,11 @@
         "src/DisplayColorProfile.cpp",
         "src/DisplaySurface.cpp",
         "src/DumpHelpers.cpp",
+        "src/HwcBufferCache.cpp",
+        "src/Layer.cpp",
         "src/Output.cpp",
         "src/OutputCompositionState.cpp",
+        "src/OutputLayer.cpp",
         "src/RenderSurface.cpp",
     ],
     local_include_dirs: ["include"],
@@ -57,7 +60,10 @@
         "mock/Display.cpp",
         "mock/DisplayColorProfile.cpp",
         "mock/DisplaySurface.cpp",
+        "mock/Layer.cpp",
+        "mock/LayerFE.cpp",
         "mock/Output.cpp",
+        "mock/OutputLayer.cpp",
         "mock/RenderSurface.cpp",
     ],
     static_libs: [
@@ -77,8 +83,11 @@
         "tests/CompositionEngineTest.cpp",
         "tests/DisplayColorProfileTest.cpp",
         "tests/DisplayTest.cpp",
+        "tests/HwcBufferCacheTest.cpp",
+        "tests/LayerTest.cpp",
         "tests/MockHWComposer.cpp",
         "tests/OutputTest.cpp",
+        "tests/OutputLayerTest.cpp",
         "tests/RenderSurfaceTest.cpp",
     ],
     static_libs: [
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
index 30cdb49..896f8aa 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
@@ -29,8 +29,10 @@
 namespace compositionengine {
 
 class Display;
+class Layer;
 
 struct DisplayCreationArgs;
+struct LayerCreationArgs;
 
 /**
  * Encapsulates all the interfaces and implementation details for performing
@@ -42,6 +44,7 @@
 
     // Create a composition Display
     virtual std::shared_ptr<Display> createDisplay(DisplayCreationArgs&&) = 0;
+    virtual std::shared_ptr<Layer> createLayer(LayerCreationArgs&&) = 0;
 
     virtual HWComposer& getHwComposer() const = 0;
     virtual void setHwComposer(std::unique_ptr<HWComposer>) = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h
new file mode 100644
index 0000000..29a7dea
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019 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 <cstdint>
+
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+typedef int64_t nsecs_t;
+
+namespace compositionengine {
+
+class Display;
+class LayerFE;
+
+/**
+ * A layer contains the output-independent composition state for a front-end
+ * Layer
+ */
+class Layer {
+public:
+    virtual ~Layer();
+
+    // Gets the front-end interface for this layer.  Can return nullptr if the
+    // front-end layer no longer exists.
+    virtual sp<LayerFE> getLayerFE() const = 0;
+};
+
+} // namespace compositionengine
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerCreationArgs.h
new file mode 100644
index 0000000..db3312b
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerCreationArgs.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <utils/RefBase.h>
+
+namespace android::compositionengine {
+
+class CompositionEngine;
+class LayerFE;
+
+/**
+ * A parameter object for creating Layer instances
+ */
+struct LayerCreationArgs {
+    // A weak pointer to the front-end layer instance that the new layer will
+    // represent.
+    wp<LayerFE> layerFE;
+};
+
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
new file mode 100644
index 0000000..f9a3624
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <utils/RefBase.h>
+
+namespace android::compositionengine {
+
+// Defines the interface used by the CompositionEngine to make requests
+// of the front-end layer
+class LayerFE : public virtual RefBase {};
+
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index 6be4ad8..84b2423 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -23,11 +23,15 @@
 #include <ui/GraphicTypes.h>
 #include <ui/Region.h>
 #include <ui/Transform.h>
+#include <utils/StrongPointer.h>
 
 namespace android::compositionengine {
 
 class DisplayColorProfile;
+class Layer;
+class LayerFE;
 class RenderSurface;
+class OutputLayer;
 
 namespace impl {
 struct OutputCompositionState;
@@ -38,6 +42,10 @@
  */
 class Output {
 public:
+    using OutputLayers = std::vector<std::unique_ptr<compositionengine::OutputLayer>>;
+
+    virtual ~Output();
+
     // Returns true if the output is valid. This is meant to be checked post-
     // construction and prior to use, as not everything is set up by the
     // constructor.
@@ -102,9 +110,23 @@
     // this output allows that.
     virtual bool belongsInOutput(uint32_t layerStackId, bool internalOnly) const = 0;
 
-protected:
-    ~Output() = default;
+    // Returns a pointer to the output layer corresponding to the given layer on
+    // this output, or nullptr if the layer does not have one
+    virtual OutputLayer* getOutputLayerForLayer(Layer*) const = 0;
 
+    // Gets the OutputLayer corresponding to the input Layer instance from the
+    // current ordered set of output layers. If there is no such layer, a new
+    // one is created and returned.
+    virtual std::unique_ptr<OutputLayer> getOrCreateOutputLayer(std::shared_ptr<Layer>,
+                                                                sp<LayerFE>) = 0;
+
+    // Sets the new ordered set of output layers for this output
+    virtual void setOutputLayersOrderedByZ(OutputLayers&&) = 0;
+
+    // Gets the ordered set of output layers for this output
+    virtual const OutputLayers& getOutputLayersOrderedByZ() const = 0;
+
+protected:
     virtual void setDisplayColorProfile(std::unique_ptr<DisplayColorProfile>) = 0;
     virtual void setRenderSurface(std::unique_ptr<RenderSurface>) = 0;
 };
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
new file mode 100644
index 0000000..4b8ef38
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <utils/StrongPointer.h>
+
+namespace android::compositionengine {
+
+class Output;
+class Layer;
+class LayerFE;
+
+/**
+ * An output layer contains the output-dependent composition state for a layer
+ */
+class OutputLayer {
+public:
+    virtual ~OutputLayer();
+
+    // Gets the output which owns this output layer
+    virtual const Output& getOutput() const = 0;
+
+    // Gets the display-independent layer which this output layer represents
+    virtual Layer& getLayer() const = 0;
+
+    // Gets the front-end layer interface this output layer represents
+    virtual LayerFE& getLayerFE() const = 0;
+};
+
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
index e23c431..b01eb64 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
@@ -27,6 +27,8 @@
 
     std::shared_ptr<compositionengine::Display> createDisplay(
             compositionengine::DisplayCreationArgs&&) override;
+    std::shared_ptr<compositionengine::Layer> createLayer(
+            compositionengine::LayerCreationArgs&&) override;
 
     HWComposer& getHwComposer() const override;
     void setHwComposer(std::unique_ptr<HWComposer>) override;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h
similarity index 79%
rename from services/surfaceflinger/DisplayHardware/HWComposerBufferCache.h
rename to services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h
index a008ca9..b45de5a 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h
@@ -14,20 +14,19 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_SF_HWCOMPOSERBUFFERCACHE_H
-#define ANDROID_SF_HWCOMPOSERBUFFERCACHE_H
+#pragma once
 
-#include <stdint.h>
+#include <cstdint>
+#include <vector>
 
 #include <utils/StrongPointer.h>
 
-#include <vector>
-
 namespace android {
-// ---------------------------------------------------------------------------
 
 class GraphicBuffer;
 
+namespace compositionengine::impl {
+
 // With HIDLized hwcomposer HAL, the HAL can maintain a buffer cache for each
 // HWC display and layer.  When updating a display target or a layer buffer,
 // we have the option to send the buffer handle over or to request the HAL to
@@ -37,17 +36,17 @@
 //
 // To be able to find out whether a buffer is already in the HAL's cache, we
 // use HWComposerBufferCache to mirror the cache in SF.
-class HWComposerBufferCache {
+class HwcBufferCache {
 public:
-    HWComposerBufferCache();
+    HwcBufferCache();
 
     // Given a buffer queue slot and buffer, return the HWC cache slot and
     // buffer to be sent to HWC.
     //
     // outBuffer is set to buffer when buffer is not in the HWC cache;
     // otherwise, outBuffer is set to nullptr.
-    void getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer,
-            uint32_t* outSlot, sp<GraphicBuffer>* outBuffer);
+    void getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer, uint32_t* outSlot,
+                      sp<GraphicBuffer>* outBuffer);
 
 private:
     // a vector as we expect "slot" to be in the range of [0, 63] (that is,
@@ -55,7 +54,5 @@
     std::vector<sp<GraphicBuffer>> mBuffers;
 };
 
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SF_HWCOMPOSERBUFFERCACHE_H
+} // namespace compositionengine::impl
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h
new file mode 100644
index 0000000..631351b
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019 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 <memory>
+
+#include <compositionengine/Layer.h>
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
+
+namespace android::compositionengine {
+
+class CompositionEngine;
+class LayerFE;
+
+struct LayerCreationArgs;
+
+namespace impl {
+
+class Display;
+
+class Layer : public compositionengine::Layer {
+public:
+    Layer(const CompositionEngine&, compositionengine::LayerCreationArgs&&);
+    ~Layer() override;
+
+    sp<LayerFE> getLayerFE() const override;
+
+private:
+    const compositionengine::CompositionEngine& mCompositionEngine;
+    const wp<LayerFE> mLayerFE;
+};
+
+std::shared_ptr<compositionengine::Layer> createLayer(const compositionengine::CompositionEngine&,
+                                                      compositionengine::LayerCreationArgs&&);
+
+} // namespace impl
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index 4be0706..3fd057c 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -17,6 +17,8 @@
 #pragma once
 
 #include <memory>
+#include <utility>
+#include <vector>
 
 #include <compositionengine/Output.h>
 #include <compositionengine/impl/OutputCompositionState.h>
@@ -24,13 +26,15 @@
 namespace android::compositionengine {
 
 class CompositionEngine;
+class Layer;
+class OutputLayer;
 
 namespace impl {
 
 class Output : public virtual compositionengine::Output {
 public:
     Output(const CompositionEngine&);
-    virtual ~Output();
+    ~Output() override;
 
     bool isValid() const override;
 
@@ -60,6 +64,13 @@
     Region getDirtyRegion(bool repaintEverything) const override;
     bool belongsInOutput(uint32_t, bool) const override;
 
+    compositionengine::OutputLayer* getOutputLayerForLayer(
+            compositionengine::Layer*) const override;
+    std::unique_ptr<compositionengine::OutputLayer> getOrCreateOutputLayer(
+            std::shared_ptr<compositionengine::Layer>, sp<LayerFE>) override;
+    void setOutputLayersOrderedByZ(OutputLayers&&) override;
+    const OutputLayers& getOutputLayersOrderedByZ() const override;
+
     // Testing
     void setDisplayColorProfileForTest(std::unique_ptr<compositionengine::DisplayColorProfile>);
     void setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface>);
@@ -79,6 +90,8 @@
 
     std::unique_ptr<compositionengine::DisplayColorProfile> mDisplayColorProfile;
     std::unique_ptr<compositionengine::RenderSurface> mRenderSurface;
+
+    OutputLayers mOutputLayersOrderedByZ;
 };
 
 } // namespace impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
new file mode 100644
index 0000000..f3d0258
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019 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 <memory>
+
+#include <compositionengine/OutputLayer.h>
+
+namespace android::compositionengine::impl {
+
+class OutputLayer : public compositionengine::OutputLayer {
+public:
+    OutputLayer(const compositionengine::Output&, std::shared_ptr<compositionengine::Layer>,
+                sp<compositionengine::LayerFE>);
+    ~OutputLayer() override;
+
+    const compositionengine::Output& getOutput() const override;
+    compositionengine::Layer& getLayer() const override;
+    compositionengine::LayerFE& getLayerFE() const override;
+
+private:
+    const compositionengine::Output& mOutput;
+    std::shared_ptr<compositionengine::Layer> mLayer;
+    sp<compositionengine::LayerFE> mLayerFE;
+};
+
+std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
+        const compositionengine::Output&, std::shared_ptr<compositionengine::Layer>,
+        sp<compositionengine::LayerFE>);
+
+} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
index 1967666..0f57685 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
@@ -18,6 +18,7 @@
 
 #include <compositionengine/CompositionEngine.h>
 #include <compositionengine/DisplayCreationArgs.h>
+#include <compositionengine/LayerCreationArgs.h>
 #include <gmock/gmock.h>
 #include <renderengine/RenderEngine.h>
 
@@ -31,6 +32,7 @@
     ~CompositionEngine() override;
 
     MOCK_METHOD1(createDisplay, std::shared_ptr<Display>(DisplayCreationArgs&&));
+    MOCK_METHOD1(createLayer, std::shared_ptr<Layer>(LayerCreationArgs&&));
 
     MOCK_CONST_METHOD0(getHwComposer, HWComposer&());
     MOCK_METHOD1(setHwComposer, void(std::unique_ptr<HWComposer>));
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h
new file mode 100644
index 0000000..a7cc08e
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019 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 <compositionengine/Layer.h>
+#include <compositionengine/LayerFE.h>
+#include <gmock/gmock.h>
+
+namespace android::compositionengine::mock {
+
+class Layer : public compositionengine::Layer {
+public:
+    Layer();
+    virtual ~Layer();
+
+    MOCK_CONST_METHOD0(getLayerFE, sp<LayerFE>());
+};
+
+} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
new file mode 100644
index 0000000..92e0070
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2019 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 <compositionengine/LayerFE.h>
+#include <gmock/gmock.h>
+
+namespace android::compositionengine::mock {
+
+// Defines the interface used by the CompositionEngine to make requests
+// of the front-end layer.
+class LayerFE : public compositionengine::LayerFE {
+public:
+    LayerFE();
+    virtual ~LayerFE();
+};
+
+} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index e767ad3..2972ad7 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -17,7 +17,10 @@
 #pragma once
 
 #include <compositionengine/DisplayColorProfile.h>
+#include <compositionengine/Layer.h>
+#include <compositionengine/LayerFE.h>
 #include <compositionengine/Output.h>
+#include <compositionengine/OutputLayer.h>
 #include <compositionengine/RenderSurface.h>
 #include <compositionengine/impl/OutputCompositionState.h>
 #include <gmock/gmock.h>
@@ -55,6 +58,15 @@
 
     MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
     MOCK_CONST_METHOD2(belongsInOutput, bool(uint32_t, bool));
+
+    MOCK_CONST_METHOD1(getOutputLayerForLayer,
+                       compositionengine::OutputLayer*(compositionengine::Layer*));
+    MOCK_METHOD2(getOrCreateOutputLayer,
+                 std::unique_ptr<compositionengine::OutputLayer>(
+                         std::shared_ptr<compositionengine::Layer>,
+                         sp<compositionengine::LayerFE>));
+    MOCK_METHOD1(setOutputLayersOrderedByZ, void(OutputLayers&&));
+    MOCK_CONST_METHOD0(getOutputLayersOrderedByZ, OutputLayers&());
 };
 
 } // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
new file mode 100644
index 0000000..f5e5026
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019 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 <compositionengine/Layer.h>
+#include <compositionengine/LayerFE.h>
+#include <compositionengine/Output.h>
+#include <compositionengine/OutputLayer.h>
+#include <gmock/gmock.h>
+
+namespace android::compositionengine::mock {
+
+class OutputLayer : public compositionengine::OutputLayer {
+public:
+    OutputLayer();
+    virtual ~OutputLayer();
+
+    MOCK_CONST_METHOD0(getOutput, const compositionengine::Output&());
+    MOCK_CONST_METHOD0(getLayer, compositionengine::Layer&());
+    MOCK_CONST_METHOD0(getLayerFE, compositionengine::LayerFE&());
+};
+
+} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/mock/Layer.cpp b/services/surfaceflinger/CompositionEngine/mock/Layer.cpp
new file mode 100644
index 0000000..08483cb
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/mock/Layer.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2019 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 <compositionengine/mock/Layer.h>
+
+namespace android::compositionengine::mock {
+
+// The Google Mock documentation recommends explicit non-header instantiations
+// for better compile time performance.
+Layer::Layer() = default;
+Layer::~Layer() = default;
+
+} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/mock/LayerFE.cpp b/services/surfaceflinger/CompositionEngine/mock/LayerFE.cpp
new file mode 100644
index 0000000..607eaad
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/mock/LayerFE.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2019 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 <compositionengine/mock/LayerFE.h>
+
+namespace android::compositionengine::mock {
+
+// The Google Mock documentation recommends explicit non-header instantiations
+// for better compile time performance.
+LayerFE::LayerFE() = default;
+LayerFE::~LayerFE() = default;
+
+} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/mock/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/mock/OutputLayer.cpp
new file mode 100644
index 0000000..4da9377
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/mock/OutputLayer.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2019 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 <compositionengine/mock/OutputLayer.h>
+
+namespace android::compositionengine::mock {
+
+// The Google Mock documentation recommends explicit non-header instantiations
+// for better compile time performance.
+OutputLayer::OutputLayer() = default;
+OutputLayer::~OutputLayer() = default;
+
+} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
index 127d729..cb08b81 100644
--- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
@@ -16,6 +16,7 @@
 
 #include <compositionengine/impl/CompositionEngine.h>
 #include <compositionengine/impl/Display.h>
+#include <compositionengine/impl/Layer.h>
 #include <renderengine/RenderEngine.h>
 
 #include "DisplayHardware/HWComposer.h"
@@ -38,6 +39,10 @@
     return compositionengine::impl::createDisplay(*this, std::move(args));
 }
 
+std::shared_ptr<compositionengine::Layer> CompositionEngine::createLayer(LayerCreationArgs&& args) {
+    return compositionengine::impl::createLayer(*this, std::move(args));
+}
+
 HWComposer& CompositionEngine::getHwComposer() const {
     return *mHwComposer.get();
 }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp b/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp
similarity index 75%
rename from services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
rename to services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp
index a234b63..6f340b9 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposerBufferCache.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp
@@ -14,21 +14,18 @@
  * limitations under the License.
  */
 
-#include "HWComposerBufferCache.h"
-
+#include <compositionengine/impl/HwcBufferCache.h>
 #include <gui/BufferQueue.h>
+#include <ui/GraphicBuffer.h>
 
-namespace android {
+namespace android::compositionengine::impl {
 
-HWComposerBufferCache::HWComposerBufferCache()
-{
+HwcBufferCache::HwcBufferCache() {
     mBuffers.reserve(BufferQueue::NUM_BUFFER_SLOTS);
 }
 
-void HWComposerBufferCache::getHwcBuffer(int slot,
-        const sp<GraphicBuffer>& buffer,
-        uint32_t* outSlot, sp<GraphicBuffer>* outBuffer)
-{
+void HwcBufferCache::getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer, uint32_t* outSlot,
+                                  sp<GraphicBuffer>* outBuffer) {
     if (slot == BufferQueue::INVALID_BUFFER_SLOT || slot < 0) {
         // default to slot 0
         slot = 0;
@@ -51,4 +48,4 @@
     }
 }
 
-} // namespace android
+} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/Layer.cpp b/services/surfaceflinger/CompositionEngine/src/Layer.cpp
new file mode 100644
index 0000000..aaa758e
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/src/Layer.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019 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 <compositionengine/CompositionEngine.h>
+#include <compositionengine/LayerCreationArgs.h>
+#include <compositionengine/LayerFE.h>
+#include <compositionengine/impl/Layer.h>
+
+namespace android::compositionengine {
+
+Layer::~Layer() = default;
+
+namespace impl {
+
+std::shared_ptr<compositionengine::Layer> createLayer(
+        const compositionengine::CompositionEngine& compositionEngine,
+        compositionengine::LayerCreationArgs&& args) {
+    return std::make_shared<Layer>(compositionEngine, std::move(args));
+}
+
+Layer::Layer(const CompositionEngine& compositionEngine, LayerCreationArgs&& args)
+      : mCompositionEngine(compositionEngine), mLayerFE(args.layerFE) {
+    static_cast<void>(mCompositionEngine); // Temporary use to prevent an unused warning
+}
+
+Layer::~Layer() = default;
+
+sp<LayerFE> Layer::getLayerFE() const {
+    return mLayerFE.promote();
+}
+
+} // namespace impl
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index c4d563f..f6c1a33 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -17,11 +17,17 @@
 #include <android-base/stringprintf.h>
 #include <compositionengine/CompositionEngine.h>
 #include <compositionengine/DisplayColorProfile.h>
+#include <compositionengine/LayerFE.h>
 #include <compositionengine/RenderSurface.h>
 #include <compositionengine/impl/Output.h>
+#include <compositionengine/impl/OutputLayer.h>
 #include <ui/DebugUtils.h>
 
-namespace android::compositionengine::impl {
+namespace android::compositionengine {
+
+Output::~Output() = default;
+
+namespace impl {
 
 Output::Output(const CompositionEngine& compositionEngine)
       : mCompositionEngine(compositionEngine) {}
@@ -178,8 +184,37 @@
     return (layerStackId == mState.layerStackId) && (!internalOnly || mState.layerStackInternal);
 }
 
+compositionengine::OutputLayer* Output::getOutputLayerForLayer(
+        compositionengine::Layer* layer) const {
+    for (const auto& outputLayer : mOutputLayersOrderedByZ) {
+        if (outputLayer && &outputLayer->getLayer() == layer) {
+            return outputLayer.get();
+        }
+    }
+    return nullptr;
+}
+
+std::unique_ptr<compositionengine::OutputLayer> Output::getOrCreateOutputLayer(
+        std::shared_ptr<compositionengine::Layer> layer, sp<compositionengine::LayerFE> layerFE) {
+    for (auto& outputLayer : mOutputLayersOrderedByZ) {
+        if (outputLayer && &outputLayer->getLayer() == layer.get()) {
+            return std::move(outputLayer);
+        }
+    }
+    return createOutputLayer(*this, layer, layerFE);
+}
+
+void Output::setOutputLayersOrderedByZ(OutputLayers&& layers) {
+    mOutputLayersOrderedByZ = std::move(layers);
+}
+
+const Output::OutputLayers& Output::getOutputLayersOrderedByZ() const {
+    return mOutputLayersOrderedByZ;
+}
+
 void Output::dirtyEntireOutput() {
     mState.dirtyRegion.set(mState.bounds);
 }
 
-} // namespace android::compositionengine::impl
+} // namespace impl
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
new file mode 100644
index 0000000..e95f3a6
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019 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 <compositionengine/Layer.h>
+#include <compositionengine/LayerFE.h>
+#include <compositionengine/Output.h>
+#include <compositionengine/impl/OutputLayer.h>
+
+namespace android::compositionengine {
+
+OutputLayer::~OutputLayer() = default;
+
+namespace impl {
+
+std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
+        const compositionengine::Output& display, std::shared_ptr<compositionengine::Layer> layer,
+        sp<compositionengine::LayerFE> layerFE) {
+    return std::make_unique<OutputLayer>(display, layer, layerFE);
+}
+
+OutputLayer::OutputLayer(const Output& output, std::shared_ptr<Layer> layer, sp<LayerFE> layerFE)
+      : mOutput(output), mLayer(layer), mLayerFE(layerFE) {}
+
+OutputLayer::~OutputLayer() = default;
+
+const compositionengine::Output& OutputLayer::getOutput() const {
+    return mOutput;
+}
+
+compositionengine::Layer& OutputLayer::getLayer() const {
+    return *mLayer;
+}
+
+compositionengine::LayerFE& OutputLayer::getLayerFE() const {
+    return *mLayerFE;
+}
+
+} // namespace impl
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/HwcBufferCacheTest.cpp b/services/surfaceflinger/CompositionEngine/tests/HwcBufferCacheTest.cpp
new file mode 100644
index 0000000..f2a1aad
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/HwcBufferCacheTest.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2019 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 <compositionengine/impl/HwcBufferCache.h>
+#include <gtest/gtest.h>
+#include <gui/BufferQueue.h>
+#include <ui/GraphicBuffer.h>
+
+namespace android::compositionengine {
+namespace {
+
+class HwcBufferCacheTest : public testing::Test {
+public:
+    ~HwcBufferCacheTest() override = default;
+
+    void testSlot(const int inSlot, const uint32_t expectedSlot) {
+        uint32_t outSlot;
+        sp<GraphicBuffer> outBuffer;
+
+        // The first time, the output  is the same as the input
+        mCache.getHwcBuffer(inSlot, mBuffer1, &outSlot, &outBuffer);
+        EXPECT_EQ(expectedSlot, outSlot);
+        EXPECT_EQ(mBuffer1, outBuffer);
+
+        // The second time with the same buffer, the outBuffer is nullptr.
+        mCache.getHwcBuffer(inSlot, mBuffer1, &outSlot, &outBuffer);
+        EXPECT_EQ(expectedSlot, outSlot);
+        EXPECT_EQ(nullptr, outBuffer.get());
+
+        // With a new buffer, the outBuffer is the input.
+        mCache.getHwcBuffer(inSlot, mBuffer2, &outSlot, &outBuffer);
+        EXPECT_EQ(expectedSlot, outSlot);
+        EXPECT_EQ(mBuffer2, outBuffer);
+
+        // Again, the second request with the same buffer sets outBuffer to nullptr.
+        mCache.getHwcBuffer(inSlot, mBuffer2, &outSlot, &outBuffer);
+        EXPECT_EQ(expectedSlot, outSlot);
+        EXPECT_EQ(nullptr, outBuffer.get());
+
+        // Setting a slot to use nullptr lookslike works, but note that
+        // the output values make it look like no new buffer is being set....
+        mCache.getHwcBuffer(inSlot, sp<GraphicBuffer>(), &outSlot, &outBuffer);
+        EXPECT_EQ(expectedSlot, outSlot);
+        EXPECT_EQ(nullptr, outBuffer.get());
+    }
+
+    impl::HwcBufferCache mCache;
+    sp<GraphicBuffer> mBuffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
+    sp<GraphicBuffer> mBuffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
+};
+
+TEST_F(HwcBufferCacheTest, cacheWorksForSlotZero) {
+    testSlot(0, 0);
+}
+
+TEST_F(HwcBufferCacheTest, cacheWorksForMaxSlot) {
+    testSlot(BufferQueue::NUM_BUFFER_SLOTS - 1, BufferQueue::NUM_BUFFER_SLOTS - 1);
+}
+
+TEST_F(HwcBufferCacheTest, cacheMapsNegativeSlotToZero) {
+    testSlot(-123, 0);
+}
+
+TEST_F(HwcBufferCacheTest, cacheMapsInvalidBufferSlotToZero) {
+    testSlot(BufferQueue::INVALID_BUFFER_SLOT, 0);
+}
+
+} // namespace
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp
new file mode 100644
index 0000000..26115a3
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019 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 <gtest/gtest.h>
+
+#include <compositionengine/LayerCreationArgs.h>
+#include <compositionengine/impl/Layer.h>
+#include <compositionengine/mock/CompositionEngine.h>
+#include <compositionengine/mock/LayerFE.h>
+
+namespace android::compositionengine {
+namespace {
+
+using testing::StrictMock;
+
+class LayerTest : public testing::Test {
+public:
+    ~LayerTest() override = default;
+
+    StrictMock<mock::CompositionEngine> mCompositionEngine;
+    sp<LayerFE> mLayerFE = new StrictMock<mock::LayerFE>();
+    impl::Layer mLayer{mCompositionEngine, LayerCreationArgs{mLayerFE}};
+};
+
+/* ------------------------------------------------------------------------
+ * Basic construction
+ */
+
+TEST_F(LayerTest, canInstantiateLayer) {}
+
+} // namespace
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
new file mode 100644
index 0000000..0a929ac
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019 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 <compositionengine/impl/OutputLayer.h>
+#include <compositionengine/mock/Layer.h>
+#include <compositionengine/mock/LayerFE.h>
+#include <compositionengine/mock/Output.h>
+#include <gtest/gtest.h>
+
+namespace android::compositionengine {
+namespace {
+
+using testing::StrictMock;
+
+class OutputLayerTest : public testing::Test {
+public:
+    ~OutputLayerTest() override = default;
+
+    compositionengine::mock::Output mOutput;
+    std::shared_ptr<compositionengine::mock::Layer> mLayer{
+            new StrictMock<compositionengine::mock::Layer>()};
+    sp<compositionengine::mock::LayerFE> mLayerFE{
+            new StrictMock<compositionengine::mock::LayerFE>()};
+    impl::OutputLayer mOutputLayer{mOutput, mLayer, mLayerFE};
+};
+
+/* ------------------------------------------------------------------------
+ * Basic construction
+ */
+
+TEST_F(OutputLayerTest, canInstantiateOutputLayer) {}
+
+} // namespace
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 0df1dab..314d98b 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -19,6 +19,9 @@
 #include <compositionengine/impl/Output.h>
 #include <compositionengine/mock/CompositionEngine.h>
 #include <compositionengine/mock/DisplayColorProfile.h>
+#include <compositionengine/mock/Layer.h>
+#include <compositionengine/mock/LayerFE.h>
+#include <compositionengine/mock/OutputLayer.h>
 #include <compositionengine/mock/RenderSurface.h>
 #include <gtest/gtest.h>
 #include <ui/Rect.h>
@@ -267,5 +270,84 @@
     EXPECT_FALSE(mOutput.belongsInOutput(layerStack2, false));
 }
 
+/* ------------------------------------------------------------------------
+ * Output::getOutputLayerForLayer()
+ */
+
+TEST_F(OutputTest, getOutputLayerForLayerWorks) {
+    mock::OutputLayer* outputLayer1 = new StrictMock<mock::OutputLayer>();
+    mock::OutputLayer* outputLayer2 = new StrictMock<mock::OutputLayer>();
+
+    Output::OutputLayers outputLayers;
+    outputLayers.emplace_back(std::unique_ptr<OutputLayer>(outputLayer1));
+    outputLayers.emplace_back(nullptr);
+    outputLayers.emplace_back(std::unique_ptr<OutputLayer>(outputLayer2));
+    mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
+
+    StrictMock<mock::Layer> layer;
+    StrictMock<mock::Layer> otherLayer;
+
+    // If the input layer matches the first OutputLayer, it will be returned.
+    EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(layer));
+    EXPECT_EQ(outputLayer1, mOutput.getOutputLayerForLayer(&layer));
+
+    // If the input layer matches the second OutputLayer, it will be returned.
+    EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
+    EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(layer));
+    EXPECT_EQ(outputLayer2, mOutput.getOutputLayerForLayer(&layer));
+
+    // If the input layer does not match an output layer, null will be returned.
+    EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
+    EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(otherLayer));
+    EXPECT_EQ(nullptr, mOutput.getOutputLayerForLayer(&layer));
+}
+
+/* ------------------------------------------------------------------------
+ * Output::getOrCreateOutputLayer()
+ */
+
+TEST_F(OutputTest, getOrCreateOutputLayerWorks) {
+    mock::OutputLayer* existingOutputLayer = new StrictMock<mock::OutputLayer>();
+
+    Output::OutputLayers outputLayers;
+    outputLayers.emplace_back(nullptr);
+    outputLayers.emplace_back(std::unique_ptr<OutputLayer>(existingOutputLayer));
+    mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
+
+    std::shared_ptr<mock::Layer> layer{new StrictMock<mock::Layer>()};
+    sp<LayerFE> layerFE{new StrictMock<mock::LayerFE>()};
+
+    StrictMock<mock::Layer> otherLayer;
+
+    {
+        // If there is no OutputLayer corresponding to the input layer, a
+        // new OutputLayer is constructed and returned.
+        EXPECT_CALL(*existingOutputLayer, getLayer()).WillOnce(ReturnRef(otherLayer));
+        auto result = mOutput.getOrCreateOutputLayer(layer, layerFE);
+        EXPECT_NE(existingOutputLayer, result.get());
+        EXPECT_TRUE(result.get() != nullptr);
+        EXPECT_EQ(layer.get(), &result->getLayer());
+        EXPECT_EQ(layerFE.get(), &result->getLayerFE());
+
+        // The entries in the ordered array should be unchanged.
+        auto& outputLayers = mOutput.getOutputLayersOrderedByZ();
+        EXPECT_EQ(nullptr, outputLayers[0].get());
+        EXPECT_EQ(existingOutputLayer, outputLayers[1].get());
+    }
+
+    {
+        // If there is an existing OutputLayer for the requested layer, an owned
+        // pointer is returned
+        EXPECT_CALL(*existingOutputLayer, getLayer()).WillOnce(ReturnRef(*layer));
+        auto result = mOutput.getOrCreateOutputLayer(layer, layerFE);
+        EXPECT_EQ(existingOutputLayer, result.get());
+
+        // The corresponding entry in the ordered array should be cleared.
+        auto& outputLayers = mOutput.getOutputLayersOrderedByZ();
+        EXPECT_EQ(nullptr, outputLayers[0].get());
+        EXPECT_EQ(nullptr, outputLayers[1].get());
+    }
+}
+
 } // namespace
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 18c524f..7f451a5 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -21,10 +21,10 @@
 #include <sys/types.h>
 
 #include <compositionengine/DisplaySurface.h>
+#include <compositionengine/impl/HwcBufferCache.h>
 #include <gui/ConsumerBase.h>
 
 #include "DisplayIdentification.h"
-#include "HWComposerBufferCache.h"
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -88,7 +88,7 @@
     // Hardware composer, owned by SurfaceFlinger.
     HWComposer& mHwc;
 
-    HWComposerBufferCache mHwcBufferCache;
+    compositionengine::impl::HwcBufferCache mHwcBufferCache;
 
     // Previous buffer to release after getting an updated retire fence
     bool mHasPendingRelease;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 87ae7dd..d6543d1 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -21,11 +21,11 @@
 #include <string>
 
 #include <compositionengine/DisplaySurface.h>
+#include <compositionengine/impl/HwcBufferCache.h>
 #include <gui/ConsumerBase.h>
 #include <gui/IGraphicBufferProducer.h>
 
 #include "DisplayIdentification.h"
-#include "HWComposerBufferCache.h"
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -253,7 +253,7 @@
 
     bool mMustRecompose;
 
-    HWComposerBufferCache mHwcBufferCache;
+    compositionengine::impl::HwcBufferCache mHwcBufferCache;
 
     bool mForceHwcCopy;
 };
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 619964f..185393e 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -46,6 +46,7 @@
 #include <gui/Surface.h>
 
 #include "BufferLayer.h"
+#include "ColorLayer.h"
 #include "Colorizer.h"
 #include "DisplayDevice.h"
 #include "Layer.h"
@@ -107,7 +108,6 @@
     mCurrentState.cornerRadius = 0.0f;
     mCurrentState.api = -1;
     mCurrentState.hasColorTransform = false;
-    mCurrentState.colorDataspace = ui::Dataspace::UNKNOWN;
 
     // drawing state & current state are identical
     mDrawingState = mCurrentState;
@@ -1106,6 +1106,11 @@
         mNeedsFiltering = (!getActiveTransform(c).preserveRects() || type >= ui::Transform::SCALE);
     }
 
+    if (mChildrenChanged) {
+        flags |= eVisibleRegion;
+        mChildrenChanged = false;
+    }
+
     // If the layer is hidden, signal and clear out all local sync points so
     // that transactions for layers depending on this layer's frames becoming
     // visible are not blocked
@@ -1272,17 +1277,35 @@
     return true;
 }
 
-bool Layer::setColor(const half3& color) {
-    if (color.r == mCurrentState.color.r && color.g == mCurrentState.color.g &&
-        color.b == mCurrentState.color.b)
+bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace) {
+    if (!mCurrentState.bgColorLayer && alpha == 0) {
         return false;
+    } else if (!mCurrentState.bgColorLayer && alpha != 0) {
+        // create background color layer if one does not yet exist
+        uint32_t flags = ISurfaceComposerClient::eFXSurfaceColor;
+        const String8& name = mName + "BackgroundColorLayer";
+        mCurrentState.bgColorLayer =
+                new ColorLayer(LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, flags));
 
-    mCurrentState.sequence++;
-    mCurrentState.color.r = color.r;
-    mCurrentState.color.g = color.g;
-    mCurrentState.color.b = color.b;
-    mCurrentState.modified = true;
-    setTransactionFlags(eTransactionNeeded);
+        // add to child list
+        addChild(mCurrentState.bgColorLayer);
+        mFlinger->mLayersAdded = true;
+        // set up SF to handle added color layer
+        if (isRemovedFromCurrentState()) {
+            mCurrentState.bgColorLayer->onRemovedFromCurrentState();
+        }
+        mFlinger->setTransactionFlags(eTransactionNeeded);
+    } else if (mCurrentState.bgColorLayer && alpha == 0) {
+        mCurrentState.bgColorLayer->reparent(nullptr);
+        mCurrentState.bgColorLayer = nullptr;
+        return true;
+    }
+
+    mCurrentState.bgColorLayer->setColor(color);
+    mCurrentState.bgColorLayer->setLayer(std::numeric_limits<int32_t>::min());
+    mCurrentState.bgColorLayer->setAlpha(alpha);
+    mCurrentState.bgColorLayer->setDataspace(dataspace);
+
     return true;
 }
 
@@ -1610,13 +1633,16 @@
 }
 
 void Layer::addChild(const sp<Layer>& layer) {
+    mChildrenChanged = true;
+
     mCurrentChildren.add(layer);
     layer->setParent(this);
 }
 
 ssize_t Layer::removeChild(const sp<Layer>& layer) {
-    layer->setParent(nullptr);
+    mChildrenChanged = true;
 
+    layer->setParent(nullptr);
     return mCurrentChildren.remove(layer);
 }
 
@@ -2227,6 +2253,10 @@
     return mDrawingState.inputInfo.token != nullptr;
 }
 
+std::shared_ptr<compositionengine::Layer> Layer::getCompositionLayer() const {
+    return nullptr;
+}
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 00e1a6f..4cead87 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -19,6 +19,7 @@
 
 #include <sys/types.h>
 
+#include <compositionengine/LayerFE.h>
 #include <gui/BufferQueue.h>
 #include <gui/ISurfaceComposerClient.h>
 #include <gui/LayerState.h>
@@ -51,7 +52,6 @@
 #include "TransactionCompletedThread.h"
 
 #include "DisplayHardware/HWComposer.h"
-#include "DisplayHardware/HWComposerBufferCache.h"
 #include "RenderArea.h"
 
 using namespace android::surfaceflinger;
@@ -68,6 +68,10 @@
 class LayerDebugInfo;
 class LayerBE;
 
+namespace compositionengine {
+class Layer;
+}
+
 namespace impl {
 class SurfaceInterceptor;
 }
@@ -87,7 +91,7 @@
     uint32_t flags;
 };
 
-class Layer : public virtual RefBase {
+class Layer : public virtual compositionengine::LayerFE {
     static std::atomic<int32_t> sSequence;
 
 public:
@@ -205,7 +209,6 @@
         // and the buffer state layer's children.  Z order will be set to
         // INT_MIN
         sp<Layer> bgColorLayer;
-        ui::Dataspace colorDataspace; // The dataspace of the background color layer
 
         // The deque of callback handles for this frame. The back of the deque contains the most
         // recent callback handle.
@@ -271,7 +274,7 @@
     virtual bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ);
 
     virtual bool setAlpha(float alpha);
-    virtual bool setColor(const half3& color);
+    virtual bool setColor(const half3& /*color*/) { return false; };
 
     // Set rounded corner radius for this layer and its children.
     //
@@ -314,8 +317,7 @@
             const std::vector<sp<CallbackHandle>>& /*handles*/) {
         return false;
     };
-    virtual bool setColorAlpha(float /*alpha*/) { return false; };
-    virtual bool setColorDataspace(ui::Dataspace /*dataspace*/) { return false; };
+    virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace);
 
     ui::Dataspace getDataSpace() const { return mCurrentDataSpace; }
 
@@ -326,6 +328,8 @@
     // visually.
     bool isLegacyDataSpace() const;
 
+    virtual std::shared_ptr<compositionengine::Layer> getCompositionLayer() const;
+
     // If we have received a new buffer this frame, we will pass its surface
     // damage down to hardware composer. Otherwise, we must send a region with
     // one empty rect.
@@ -851,6 +855,8 @@
 
     // Can only be accessed with the SF state lock held.
     bool mLayerDetached{false};
+    // Can only be accessed with the SF state lock held.
+    bool mChildrenChanged{false};
 
 private:
     /**
diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h
index 3f5134e..6270efa 100644
--- a/services/surfaceflinger/LayerBE.h
+++ b/services/surfaceflinger/LayerBE.h
@@ -19,6 +19,8 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <compositionengine/impl/HwcBufferCache.h>
+
 #include <renderengine/Mesh.h>
 #include <renderengine/RenderEngine.h>
 #include <renderengine/Texture.h>
@@ -26,7 +28,6 @@
 
 #include "DisplayHardware/DisplayIdentification.h"
 #include "DisplayHardware/HWComposer.h"
-#include "DisplayHardware/HWComposerBufferCache.h"
 #include "SurfaceFlinger.h"
 
 namespace android {
@@ -120,7 +121,7 @@
         bool clearClientTarget;
         Rect displayFrame;
         FloatRect sourceCrop;
-        HWComposerBufferCache bufferCache;
+        compositionengine::impl::HwcBufferCache bufferCache;
         HWC2::Transform transform;
     };
 
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 9b2a6fc..075e238 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -757,18 +757,7 @@
     const uint32_t hwcLatency = 0;
 
     // Ask DispSync when the next refresh will be (CLOCK_MONOTONIC).
-    const nsecs_t nextRefresh = computeNextRefresh(hwcLatency);
-
-    // The DispSync time is already adjusted for the difference between
-    // vsync and reported-vsync (SurfaceFlinger::dispSyncPresentTimeOffset), so
-    // we don't need to factor that in here.  Pad a little to avoid
-    // weird effects if apps might be requesting times right on the edge.
-    nsecs_t extraPadding = 0;
-    if (SurfaceFlinger::vsyncPhaseOffsetNs == 0) {
-        extraPadding = 1000000; // 1ms (6% of 60Hz)
-    }
-
-    return nextRefresh + extraPadding;
+    return computeNextRefresh(hwcLatency);
 }
 
 } // namespace impl
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
new file mode 100644
index 0000000..a0a4455
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2019 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 "PhaseOffsets.h"
+
+#include <cutils/properties.h>
+
+#include "SurfaceFlingerProperties.h"
+
+namespace android {
+using namespace android::sysprop;
+
+namespace scheduler {
+
+PhaseOffsets::~PhaseOffsets() = default;
+
+namespace impl {
+PhaseOffsets::PhaseOffsets() {
+    int64_t vsyncPhaseOffsetNs = vsync_event_phase_offset_ns(1000000);
+
+    int64_t sfVsyncPhaseOffsetNs = vsync_sf_event_phase_offset_ns(1000000);
+
+    char value[PROPERTY_VALUE_MAX];
+    property_get("debug.sf.early_phase_offset_ns", value, "-1");
+    const int earlySfOffsetNs = atoi(value);
+
+    property_get("debug.sf.early_gl_phase_offset_ns", value, "-1");
+    const int earlyGlSfOffsetNs = atoi(value);
+
+    property_get("debug.sf.early_app_phase_offset_ns", value, "-1");
+    const int earlyAppOffsetNs = atoi(value);
+
+    property_get("debug.sf.early_gl_app_phase_offset_ns", value, "-1");
+    const int earlyGlAppOffsetNs = atoi(value);
+
+    property_get("debug.sf.high_fps_early_phase_offset_ns", value, "-1");
+    const int highFpsEarlySfOffsetNs = atoi(value);
+
+    property_get("debug.sf.high_fps_early_gl_phase_offset_ns", value, "-1");
+    const int highFpsEarlyGlSfOffsetNs = atoi(value);
+
+    property_get("debug.sf.high_fps_early_app_phase_offset_ns", value, "-1");
+    const int highFpsEarlyAppOffsetNs = atoi(value);
+
+    property_get("debug.sf.high_fps_early_gl_app_phase_offset_ns", value, "-1");
+    const int highFpsEarlyGlAppOffsetNs = atoi(value);
+
+    // TODO(b/122905996): Define these in device.mk.
+    property_get("debug.sf.high_fps_late_app_phase_offset_ns", value, "1000000");
+    const int highFpsLateAppOffsetNs = atoi(value);
+
+    property_get("debug.sf.high_fps_late_sf_phase_offset_ns", value, "8000000");
+    const int highFpsLateSfOffsetNs = atoi(value);
+
+    mDefaultRefreshRateOffsets.early = {earlySfOffsetNs != -1 ? earlySfOffsetNs
+                                                              : sfVsyncPhaseOffsetNs,
+                                        earlyAppOffsetNs != -1 ? earlyAppOffsetNs
+                                                               : vsyncPhaseOffsetNs};
+    mDefaultRefreshRateOffsets.earlyGl = {earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs
+                                                                  : sfVsyncPhaseOffsetNs,
+                                          earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs
+                                                                   : vsyncPhaseOffsetNs};
+    mDefaultRefreshRateOffsets.late = {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs};
+
+    mHighRefreshRateOffsets.early = {highFpsEarlySfOffsetNs != -1 ? highFpsEarlySfOffsetNs
+                                                                  : highFpsLateAppOffsetNs,
+                                     highFpsEarlyAppOffsetNs != -1 ? highFpsEarlyAppOffsetNs
+                                                                   : highFpsLateSfOffsetNs};
+    mHighRefreshRateOffsets.earlyGl = {highFpsEarlyGlSfOffsetNs != -1 ? highFpsEarlyGlSfOffsetNs
+                                                                      : highFpsLateAppOffsetNs,
+                                       highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs
+                                                                       : highFpsLateSfOffsetNs};
+    mHighRefreshRateOffsets.late = {highFpsLateAppOffsetNs, highFpsLateSfOffsetNs};
+}
+
+PhaseOffsets::Offsets PhaseOffsets::getCurrentOffsets() const {
+    switch (mRefreshRateType) {
+        case RefreshRateConfigs::RefreshRateType::PERFORMANCE:
+            return mHighRefreshRateOffsets;
+        default:
+            return mDefaultRefreshRateOffsets;
+    }
+}
+
+void PhaseOffsets::dump(std::string& result) const {
+    const auto [early, earlyGl, late] = getCurrentOffsets();
+    base::StringAppendF(&result,
+                        "         app phase: %9" PRId64 " ns\t         SF phase: %9" PRId64 " ns\n"
+                        "   early app phase: %9" PRId64 " ns\t   early SF phase: %9" PRId64 " ns\n"
+                        "GL early app phase: %9" PRId64 " ns\tGL early SF phase: %9" PRId64 " ns\n",
+                        late.app, late.sf, early.app, early.sf, earlyGl.app, earlyGl.sf);
+}
+
+nsecs_t PhaseOffsets::getCurrentAppOffset() {
+    return getCurrentOffsets().late.app;
+}
+
+nsecs_t PhaseOffsets::getCurrentSfOffset() {
+    return getCurrentOffsets().late.sf;
+}
+
+} // namespace impl
+} // namespace scheduler
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.h b/services/surfaceflinger/Scheduler/PhaseOffsets.h
new file mode 100644
index 0000000..cbcaade
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2019 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 <cinttypes>
+
+#include "RefreshRateConfigs.h"
+#include "VSyncModulator.h"
+
+namespace android {
+namespace scheduler {
+
+/*
+ * This class encapsulates offsets for different refresh rates. Depending
+ * on what refresh rate we are using, and wheter we are composing in GL,
+ * different offsets will help us with latency. This class keeps track of
+ * which mode the device is on, and returns approprate offsets when needed.
+ */
+class PhaseOffsets {
+public:
+    struct Offsets {
+        VSyncModulator::Offsets early;
+        VSyncModulator::Offsets earlyGl;
+        VSyncModulator::Offsets late;
+    };
+
+    virtual ~PhaseOffsets();
+
+    virtual nsecs_t getCurrentAppOffset() = 0;
+    virtual nsecs_t getCurrentSfOffset() = 0;
+    virtual Offsets getCurrentOffsets() const = 0;
+    virtual void setRefreshRateType(RefreshRateConfigs::RefreshRateType refreshRateType) = 0;
+    virtual void dump(std::string& result) const = 0;
+};
+
+namespace impl {
+class PhaseOffsets : public scheduler::PhaseOffsets {
+public:
+    PhaseOffsets();
+
+    nsecs_t getCurrentAppOffset() override;
+    nsecs_t getCurrentSfOffset() override;
+
+    // Returns early, early GL, and late offsets for Apps and SF.
+    Offsets getCurrentOffsets() const override;
+
+    // This function should be called when the device is switching between different
+    // refresh rates, to properly update the offsets.
+    void setRefreshRateType(RefreshRateConfigs::RefreshRateType refreshRateType) override {
+        mRefreshRateType = refreshRateType;
+    }
+
+    // Returns current offsets in human friendly format.
+    void dump(std::string& result) const override;
+
+private:
+    Offsets getmDefaultRefreshRateOffsets() { return mDefaultRefreshRateOffsets; }
+    Offsets getmHighRefreshRateOffsets() { return mHighRefreshRateOffsets; }
+
+    std::atomic<RefreshRateConfigs::RefreshRateType> mRefreshRateType =
+            RefreshRateConfigs::RefreshRateType::DEFAULT;
+
+    Offsets mDefaultRefreshRateOffsets;
+    Offsets mHighRefreshRateOffsets;
+};
+} // namespace impl
+
+} // namespace scheduler
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index bfe5da5..026f7c7 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -47,6 +47,8 @@
         int configId;
         // Human readable name of the refresh rate.
         std::string name;
+        // Refresh rate in frames per second, rounded to the nearest integer.
+        uint32_t fps = 0;
     };
 
     // TODO(b/122916473): Get this information from configs prepared by vendors, instead of
@@ -63,7 +65,7 @@
     void init(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
         // This is the rate that HWC encapsulates right now when the device is in DOZE mode.
         mRefreshRates.push_back(
-                RefreshRate{RefreshRateType::POWER_SAVING, SCREEN_OFF_CONFIG_ID, "ScreenOff"});
+                RefreshRate{RefreshRateType::POWER_SAVING, SCREEN_OFF_CONFIG_ID, "ScreenOff", 0});
 
         if (configs.size() < 1) {
             ALOGE("Device does not have valid configs. Config size is 0.");
@@ -86,10 +88,11 @@
         nsecs_t vsyncPeriod = configIdToVsyncPeriod[0].second;
         if (vsyncPeriod != 0) {
             const float fps = 1e9 / vsyncPeriod;
-            mRefreshRates.push_back(RefreshRate{RefreshRateType::DEFAULT,
-                                                configIdToVsyncPeriod[0].first,
-                                                base::StringPrintf("%2.ffps", fps)});
+            mRefreshRates.push_back(
+                    RefreshRate{RefreshRateType::DEFAULT, configIdToVsyncPeriod[0].first,
+                                base::StringPrintf("%2.ffps", fps), static_cast<uint32_t>(fps)});
         }
+
         if (configs.size() < 2) {
             return;
         }
@@ -99,9 +102,9 @@
         vsyncPeriod = configIdToVsyncPeriod[1].second;
         if (vsyncPeriod != 0) {
             const float fps = 1e9 / vsyncPeriod;
-            mRefreshRates.push_back(RefreshRate{RefreshRateType::PERFORMANCE,
-                                                configIdToVsyncPeriod[1].first,
-                                                base::StringPrintf("%2.ffps", fps)});
+            mRefreshRates.push_back(
+                    RefreshRate{RefreshRateType::PERFORMANCE, configIdToVsyncPeriod[1].first,
+                                base::StringPrintf("%2.ffps", fps), static_cast<uint32_t>(fps)});
         }
     }
 
@@ -109,4 +112,4 @@
 };
 
 } // namespace scheduler
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h
index 7e22232..dcb2988 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateStats.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h
@@ -20,6 +20,7 @@
 
 #include "Scheduler/RefreshRateConfigs.h"
 #include "Scheduler/SchedulerUtils.h"
+#include "TimeStats/TimeStats.h"
 
 #include "android-base/stringprintf.h"
 #include "utils/Timers.h"
@@ -41,8 +42,10 @@
 
 public:
     explicit RefreshRateStats(
-            const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs)
+            const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
+            const std::shared_ptr<TimeStats>& timeStats)
           : mRefreshRateConfigs(std::make_unique<RefreshRateConfigs>(configs)),
+            mTimeStats(timeStats),
             mPreviousRecordedTime(systemTime()) {}
     ~RefreshRateStats() = default;
 
@@ -116,10 +119,16 @@
     // this method was called.
     void flushTimeForMode(int mode) {
         nsecs_t currentTime = systemTime();
-        int64_t timeElapsedMs = ns2ms(currentTime - mPreviousRecordedTime);
+        nsecs_t timeElapsed = currentTime - mPreviousRecordedTime;
+        int64_t timeElapsedMs = ns2ms(timeElapsed);
         mPreviousRecordedTime = currentTime;
 
         mConfigModesTotalTime[mode] += timeElapsedMs;
+        for (const auto& config : mRefreshRateConfigs->getRefreshRates()) {
+            if (config.configId == mode) {
+                mTimeStats->recordRefreshRate(config.fps, timeElapsed);
+            }
+        }
     }
 
     // Formats the time in milliseconds into easy to read format.
@@ -136,6 +145,9 @@
     // Keeps information about refresh rate configs that device has.
     std::unique_ptr<RefreshRateConfigs> mRefreshRateConfigs;
 
+    // Aggregate refresh rate statistics for telemetry.
+    std::shared_ptr<TimeStats> mTimeStats;
+
     int64_t mCurrentConfigMode = 0;
     int32_t mCurrentPowerMode = HWC_POWER_MODE_OFF;
 
@@ -145,4 +157,4 @@
 };
 
 } // namespace scheduler
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index b003451..00820f1 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -70,7 +70,7 @@
     mEventControlThread = std::make_unique<impl::EventControlThread>(function);
 
     char value[PROPERTY_VALUE_MAX];
-    property_get("debug.sf.set_idle_timer_ms", value, "0");
+    property_get("debug.sf.set_idle_timer_ms", value, "30");
     mSetIdleTimerMs = atoi(value);
 
     if (mSetIdleTimerMs > 0) {
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index dde0c57..d7ec733 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -18,9 +18,10 @@
 
 #include <utils/Errors.h>
 
+#include <cinttypes>
 #include <mutex>
 
-using namespace android::surfaceflinger;
+#include "Scheduler.h"
 
 namespace android {
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ee202a3..cf2b80c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -40,6 +40,8 @@
 #include <compositionengine/CompositionEngine.h>
 #include <compositionengine/Display.h>
 #include <compositionengine/DisplayColorProfile.h>
+#include <compositionengine/Layer.h>
+#include <compositionengine/OutputLayer.h>
 #include <compositionengine/RenderSurface.h>
 #include <compositionengine/impl/OutputCompositionState.h>
 #include <dvr/vr_flinger.h>
@@ -211,8 +213,6 @@
 constexpr float kSrgbWhiteZ = 1.0891f;
 
 // ---------------------------------------------------------------------------
-int64_t SurfaceFlinger::vsyncPhaseOffsetNs;
-int64_t SurfaceFlinger::sfVsyncPhaseOffsetNs;
 int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
 bool SurfaceFlinger::useHwcForRgbToYuv;
 uint64_t SurfaceFlinger::maxVirtualDisplaySize;
@@ -273,6 +273,7 @@
         mLayersRemoved(false),
         mLayersAdded(false),
         mBootTime(systemTime()),
+        mPhaseOffsets{getFactory().createPhaseOffsets()},
         mVisibleRegionsDirty(false),
         mGeometryInvalid(false),
         mAnimCompositionPending(false),
@@ -298,10 +299,6 @@
       : SurfaceFlinger(factory, SkipInitialization) {
     ALOGI("SurfaceFlinger is starting");
 
-    vsyncPhaseOffsetNs = vsync_event_phase_offset_ns(1000000);
-
-    sfVsyncPhaseOffsetNs = vsync_sf_event_phase_offset_ns(1000000);
-
     hasSyncFramework = running_without_sync_framework(true);
 
     dispSyncPresentTimeOffset = present_time_offset_from_vsync_ns(0);
@@ -400,29 +397,11 @@
     auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
     mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
 
-    property_get("debug.sf.early_phase_offset_ns", value, "-1");
-    const int earlySfOffsetNs = atoi(value);
-
-    property_get("debug.sf.early_gl_phase_offset_ns", value, "-1");
-    const int earlyGlSfOffsetNs = atoi(value);
-
-    property_get("debug.sf.early_app_phase_offset_ns", value, "-1");
-    const int earlyAppOffsetNs = atoi(value);
-
-    property_get("debug.sf.early_gl_app_phase_offset_ns", value, "-1");
-    const int earlyGlAppOffsetNs = atoi(value);
-
     property_get("debug.sf.use_scheduler", value, "0");
     mUseScheduler = atoi(value);
 
-    const VSyncModulator::Offsets earlyOffsets =
-            {earlySfOffsetNs != -1 ? earlySfOffsetNs : sfVsyncPhaseOffsetNs,
-            earlyAppOffsetNs != -1 ? earlyAppOffsetNs : vsyncPhaseOffsetNs};
-    const VSyncModulator::Offsets earlyGlOffsets =
-            {earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs : sfVsyncPhaseOffsetNs,
-            earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs : vsyncPhaseOffsetNs};
-    mVsyncModulator.setPhaseOffsets(earlyOffsets, earlyGlOffsets,
-            {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs});
+    const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+    mVsyncModulator.setPhaseOffsets(early, gl, late);
 
     // We should be reading 'persist.sys.sf.color_saturation' here
     // but since /data may be encrypted, we need to wait until after vold
@@ -629,7 +608,7 @@
     ALOGI(  "SurfaceFlinger's main thread ready to run. "
             "Initializing graphics H/W...");
 
-    ALOGI("Phase offest NS: %" PRId64 "", vsyncPhaseOffsetNs);
+    ALOGI("Phase offset NS: %" PRId64 "", mPhaseOffsets->getCurrentAppOffset());
 
     Mutex::Autolock _l(mStateLock);
 
@@ -640,13 +619,17 @@
         mScheduler = getFactory().createScheduler([this](bool enabled) {
             setVsyncEnabled(EventThread::DisplayType::Primary, enabled);
         });
+        // TODO(b/113612090): Currently we assume that if scheduler is turned on, then the refresh
+        // rate is 90. Once b/122905403 is completed, this should be updated accordingly.
+        mPhaseOffsets->setRefreshRateType(
+                scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE);
 
         mAppConnectionHandle =
-                mScheduler->createConnection("appConnection", SurfaceFlinger::vsyncPhaseOffsetNs,
+                mScheduler->createConnection("appConnection", mPhaseOffsets->getCurrentAppOffset(),
                                              resyncCallback,
                                              impl::EventThread::InterceptVSyncsCallback());
         mSfConnectionHandle =
-                mScheduler->createConnection("sfConnection", SurfaceFlinger::sfVsyncPhaseOffsetNs,
+                mScheduler->createConnection("sfConnection", mPhaseOffsets->getCurrentSfOffset(),
                                              resyncCallback, [this](nsecs_t timestamp) {
                                                  mInterceptor->saveVSyncEvent(timestamp);
                                              });
@@ -657,14 +640,14 @@
     } else {
         mEventThreadSource =
                 std::make_unique<DispSyncSource>(mPrimaryDispSync.get(),
-                                                 SurfaceFlinger::vsyncPhaseOffsetNs, true, "app");
+                                                 mPhaseOffsets->getCurrentAppOffset(), true, "app");
         mEventThread =
                 std::make_unique<impl::EventThread>(mEventThreadSource.get(),
                                                     impl::EventThread::InterceptVSyncsCallback(),
                                                     "appEventThread");
         mSfEventThreadSource =
                 std::make_unique<DispSyncSource>(mPrimaryDispSync.get(),
-                                                 SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
+                                                 mPhaseOffsets->getCurrentSfOffset(), true, "sf");
 
         mSFEventThread =
                 std::make_unique<impl::EventThread>(mSfEventThreadSource.get(),
@@ -745,10 +728,24 @@
     }
 
     if (mUseScheduler) {
-        mScheduler->setExpiredIdleTimerCallback([this]() { setRefreshRateTo(60.f /* fps */); });
-        mScheduler->setResetIdleTimerCallback([this]() { setRefreshRateTo(90.f /* fps */); });
-        mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(
-                getHwComposer().getConfigs(*display->getId()));
+        mScheduler->setExpiredIdleTimerCallback([this]() {
+            mPhaseOffsets->setRefreshRateType(
+                    scheduler::RefreshRateConfigs::RefreshRateType::DEFAULT);
+            const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+            mVsyncModulator.setPhaseOffsets(early, gl, late);
+            setRefreshRateTo(60.f /* fps */);
+        });
+        mScheduler->setResetIdleTimerCallback([this]() {
+            mPhaseOffsets->setRefreshRateType(
+                    scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE);
+            const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+            mVsyncModulator.setPhaseOffsets(early, gl, late);
+            setRefreshRateTo(90.f /* fps */);
+        });
+        mRefreshRateStats =
+                std::make_unique<scheduler::RefreshRateStats>(getHwComposer().getConfigs(
+                                                                      *display->getId()),
+                                                              mTimeStats);
     }
 
     ALOGV("Done initializing");
@@ -901,7 +898,7 @@
         info.xdpi = xdpi;
         info.ydpi = ydpi;
         info.fps = 1e9 / hwConfig->getVsyncPeriod();
-        info.appVsyncOffset = vsyncPhaseOffsetNs;
+        info.appVsyncOffset = mPhaseOffsets->getCurrentAppOffset();
 
         // This is how far in advance a buffer must be queued for
         // presentation at a given time.  If you want a buffer to appear
@@ -915,8 +912,8 @@
         //
         // We add an additional 1ms to allow for processing time and
         // differences between the ideal and actual refresh rate.
-        info.presentationDeadline = hwConfig->getVsyncPeriod() -
-                sfVsyncPhaseOffsetNs + 1000000;
+        info.presentationDeadline =
+                hwConfig->getVsyncPeriod() - mPhaseOffsets->getCurrentSfOffset() + 1000000;
 
         // All non-virtual displays are currently considered secure.
         info.secure = true;
@@ -1966,11 +1963,11 @@
                                                 nsecs_t compositeToPresentLatency) {
     // Integer division and modulo round toward 0 not -inf, so we need to
     // treat negative and positive offsets differently.
-    nsecs_t idealLatency = (sfVsyncPhaseOffsetNs > 0)
-            ? (stats.vsyncPeriod - (sfVsyncPhaseOffsetNs % stats.vsyncPeriod))
-            : ((-sfVsyncPhaseOffsetNs) % stats.vsyncPeriod);
+    nsecs_t idealLatency = (mPhaseOffsets->getCurrentSfOffset() > 0)
+            ? (stats.vsyncPeriod - (mPhaseOffsets->getCurrentSfOffset() % stats.vsyncPeriod))
+            : ((-mPhaseOffsets->getCurrentSfOffset()) % stats.vsyncPeriod);
 
-    // Just in case sfVsyncPhaseOffsetNs == -vsyncInterval.
+    // Just in case mPhaseOffsets->getCurrentSfOffset() == -vsyncInterval.
     if (idealLatency <= 0) {
         idealLatency = stats.vsyncPeriod;
     }
@@ -1979,7 +1976,7 @@
     // composition and present times, which often have >1ms of jitter.
     // Reducing jitter is important if an app attempts to extrapolate
     // something (such as user input) to an accurate diasplay time.
-    // Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs
+    // Snapping also allows an app to precisely calculate mPhaseOffsets->getCurrentSfOffset()
     // with (presentLatency % interval).
     nsecs_t bias = stats.vsyncPeriod / 2;
     int64_t extraVsyncs = (compositeToPresentLatency - idealLatency + bias) / stats.vsyncPeriod;
@@ -2257,7 +2254,8 @@
             const auto& displayState = display->getState();
             Region opaqueRegion;
             Region dirtyRegion;
-            Vector<sp<Layer>> layersSortedByZ;
+            compositionengine::Output::OutputLayers layersSortedByZ;
+            Vector<sp<Layer>> deprecated_layersSortedByZ;
             Vector<sp<Layer>> layersNeedingFences;
             const ui::Transform& tr = displayState.transform;
             const Rect bounds = displayState.bounds;
@@ -2265,15 +2263,27 @@
                 computeVisibleRegions(displayDevice, dirtyRegion, opaqueRegion);
 
                 mDrawingState.traverseInZOrder([&](Layer* layer) {
+                    auto compositionLayer = layer->getCompositionLayer();
+                    if (compositionLayer == nullptr) {
+                        return;
+                    }
+
                     bool hwcLayerDestroyed = false;
                     const auto displayId = displayDevice->getId();
+                    sp<compositionengine::LayerFE> layerFE = compositionLayer->getLayerFE();
+                    LOG_ALWAYS_FATAL_IF(layerFE.get() == nullptr);
+
                     if (display->belongsInOutput(layer->getLayerStack(),
                                                  layer->getPrimaryDisplayOnly())) {
                         Region drawRegion(tr.transform(
                                 layer->visibleNonTransparentRegion));
                         drawRegion.andSelf(bounds);
                         if (!drawRegion.isEmpty()) {
-                            layersSortedByZ.add(layer);
+                            layersSortedByZ.emplace_back(
+                                    display->getOrCreateOutputLayer(layer->getCompositionLayer(),
+                                                                    layerFE));
+
+                            deprecated_layersSortedByZ.add(layer);
                         } else {
                             // Clear out the HWC layer if this layer was
                             // previously visible, but no longer is
@@ -2299,7 +2309,10 @@
                     }
                 });
             }
-            displayDevice->setVisibleLayersSortedByZ(layersSortedByZ);
+
+            display->setOutputLayersOrderedByZ(std::move(layersSortedByZ));
+
+            displayDevice->setVisibleLayersSortedByZ(deprecated_layersSortedByZ);
             displayDevice->setLayersNeedingFences(layersNeedingFences);
 
             Region undefinedRegion{bounds};
@@ -3861,17 +3874,16 @@
         if (layer->setColor(s.color))
             flags |= eTraversalNeeded;
     }
-    if (what & layer_state_t::eColorAlphaChanged) {
-        if (layer->setColorAlpha(s.colorAlpha)) flags |= eTraversalNeeded;
-    }
-    if (what & layer_state_t::eColorDataspaceChanged) {
-        if (layer->setColorDataspace(s.colorDataspace)) flags |= eTraversalNeeded;
-    }
     if (what & layer_state_t::eColorTransformChanged) {
         if (layer->setColorTransform(s.colorTransform)) {
             flags |= eTraversalNeeded;
         }
     }
+    if (what & layer_state_t::eBackgroundColorChanged) {
+        if (layer->setBackgroundColor(s.color, s.bgColorAlpha, s.bgColorDataspace)) {
+            flags |= eTraversalNeeded;
+        }
+    }
     if (what & layer_state_t::eMatrixChanged) {
         // TODO: b/109894387
         //
@@ -4520,15 +4532,10 @@
 }
 
 void SurfaceFlinger::dumpVSync(std::string& result) const {
-    const auto [sfEarlyOffset, appEarlyOffset] = mVsyncModulator.getEarlyOffsets();
-    const auto [sfEarlyGlOffset, appEarlyGlOffset] = mVsyncModulator.getEarlyGlOffsets();
+    mPhaseOffsets->dump(result);
     StringAppendF(&result,
-                  "         app phase: %9" PRId64 " ns\t         SF phase: %9" PRId64 " ns\n"
-                  "   early app phase: %9" PRId64 " ns\t   early SF phase: %9" PRId64 " ns\n"
-                  "GL early app phase: %9" PRId64 " ns\tGL early SF phase: %9" PRId64 " ns\n"
                   "    present offset: %9" PRId64 " ns\t     VSYNC period: %9" PRId64 " ns\n\n",
-                  vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, appEarlyOffset, sfEarlyOffset,
-                  appEarlyGlOffset, sfEarlyGlOffset, dispSyncPresentTimeOffset, getVsyncPeriod());
+                  dispSyncPresentTimeOffset, getVsyncPeriod());
 
     StringAppendF(&result, "Scheduler: %s\n\n", mUseScheduler ? "enabled" : "disabled");
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index dfb01fb..9aaf6de 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -59,6 +59,7 @@
 #include "Scheduler/DispSync.h"
 #include "Scheduler/EventThread.h"
 #include "Scheduler/MessageQueue.h"
+#include "Scheduler/PhaseOffsets.h"
 #include "Scheduler/RefreshRateStats.h"
 #include "Scheduler/Scheduler.h"
 #include "Scheduler/VSyncModulator.h"
@@ -952,7 +953,10 @@
     std::unique_ptr<EventControlThread> mEventControlThread;
     std::unordered_map<DisplayId, sp<IBinder>> mPhysicalDisplayTokens;
 
+    // Calculates correct offsets.
     VSyncModulator mVsyncModulator;
+    // Keeps track of all available phase offsets for different refresh types.
+    std::unique_ptr<scheduler::PhaseOffsets> mPhaseOffsets;
 
     // Can only accessed from the main thread, these members
     // don't need synchronization
@@ -996,7 +1000,7 @@
     std::unique_ptr<SurfaceInterceptor> mInterceptor{mFactory.createSurfaceInterceptor(this)};
     SurfaceTracing mTracing;
     LayerStats mLayerStats;
-    std::unique_ptr<TimeStats> mTimeStats;
+    std::shared_ptr<TimeStats> mTimeStats;
     bool mUseHwcVirtualDisplays = false;
     std::atomic<uint32_t> mFrameMissedCount{0};
 
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.cpp b/services/surfaceflinger/SurfaceFlingerFactory.cpp
index 77679e3..26d2c21 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.cpp
+++ b/services/surfaceflinger/SurfaceFlingerFactory.cpp
@@ -33,6 +33,7 @@
 #include "Scheduler/DispSync.h"
 #include "Scheduler/EventControlThread.h"
 #include "Scheduler/MessageQueue.h"
+#include "Scheduler/PhaseOffsets.h"
 #include "Scheduler/Scheduler.h"
 #include "TimeStats/TimeStats.h"
 
@@ -68,6 +69,10 @@
             return std::make_unique<android::impl::MessageQueue>();
         }
 
+        std::unique_ptr<scheduler::PhaseOffsets> createPhaseOffsets() override {
+            return std::make_unique<scheduler::impl::PhaseOffsets>();
+        }
+
         std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)> callback) override {
             return std::make_unique<Scheduler>(callback);
         }
@@ -123,8 +128,8 @@
             return new ColorLayer(args);
         }
 
-        std::unique_ptr<TimeStats> createTimeStats() override {
-            return std::make_unique<TimeStats>();
+        std::shared_ptr<TimeStats> createTimeStats() override {
+            return std::make_shared<android::impl::TimeStats>();
         }
     };
     static Factory factory;
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h
index f747684..fc1d0f8 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerFactory.h
@@ -52,6 +52,10 @@
 namespace compositionengine {
 class CompositionEngine;
 } // namespace compositionengine
+
+namespace scheduler {
+class PhaseOffsets;
+} // namespace scheduler
 namespace surfaceflinger {
 
 class NativeWindowSurface;
@@ -66,6 +70,7 @@
             std::function<void(bool)> setVSyncEnabled) = 0;
     virtual std::unique_ptr<HWComposer> createHWComposer(const std::string& serviceName) = 0;
     virtual std::unique_ptr<MessageQueue> createMessageQueue() = 0;
+    virtual std::unique_ptr<scheduler::PhaseOffsets> createPhaseOffsets() = 0;
     virtual std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)> callback) = 0;
     virtual std::unique_ptr<SurfaceInterceptor> createSurfaceInterceptor(SurfaceFlinger*) = 0;
 
@@ -88,7 +93,7 @@
     virtual sp<ColorLayer> createColorLayer(const LayerCreationArgs& args) = 0;
     virtual sp<ContainerLayer> createContainerLayer(const LayerCreationArgs& args) = 0;
 
-    virtual std::unique_ptr<TimeStats> createTimeStats() = 0;
+    virtual std::shared_ptr<TimeStats> createTimeStats() = 0;
 
 protected:
     ~Factory() = default;
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index 8d3776b..78c6e74 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -32,6 +32,8 @@
 
 namespace android {
 
+namespace impl {
+
 void TimeStats::parseArgs(bool asProto, const Vector<String16>& args, std::string& result) {
     ATRACE_CALL();
 
@@ -450,6 +452,15 @@
     mPowerTime.powerMode = powerMode;
 }
 
+void TimeStats::recordRefreshRate(uint32_t fps, nsecs_t duration) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mTimeStats.refreshRateStats.count(fps)) {
+        mTimeStats.refreshRateStats[fps] += duration;
+    } else {
+        mTimeStats.refreshRateStats.insert({fps, duration});
+    }
+}
+
 void TimeStats::flushAvailableGlobalRecordsToStatsLocked() {
     ATRACE_CALL();
 
@@ -547,6 +558,7 @@
     mTimeStats.clientCompositionFrames = 0;
     mTimeStats.displayOnTime = 0;
     mTimeStats.presentToPresent.hist.clear();
+    mTimeStats.refreshRateStats.clear();
     mPowerTime.prevTime = systemTime();
     mGlobalRecord.prevPresentTime = 0;
     mGlobalRecord.presentFences.clear();
@@ -580,4 +592,6 @@
     }
 }
 
+} // namespace impl
+
 } // namespace android
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index e8fbcab..d8c0786 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -36,6 +36,40 @@
 namespace android {
 
 class TimeStats {
+public:
+    virtual ~TimeStats() = default;
+
+    virtual void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) = 0;
+    virtual bool isEnabled() = 0;
+
+    virtual void incrementTotalFrames() = 0;
+    virtual void incrementMissedFrames() = 0;
+    virtual void incrementClientCompositionFrames() = 0;
+
+    virtual void setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName,
+                             nsecs_t postTime) = 0;
+    virtual void setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime) = 0;
+    virtual void setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime) = 0;
+    virtual void setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime) = 0;
+    virtual void setAcquireFence(int32_t layerID, uint64_t frameNumber,
+                                 const std::shared_ptr<FenceTime>& acquireFence) = 0;
+    virtual void setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime) = 0;
+    virtual void setPresentFence(int32_t layerID, uint64_t frameNumber,
+                                 const std::shared_ptr<FenceTime>& presentFence) = 0;
+    // Clean up the layer record
+    virtual void onDestroy(int32_t layerID) = 0;
+    // If SF skips or rejects a buffer, remove the corresponding TimeRecord.
+    virtual void removeTimeRecord(int32_t layerID, uint64_t frameNumber) = 0;
+
+    virtual void setPowerMode(int32_t powerMode) = 0;
+    // Source of truth is RefrehRateStats.
+    virtual void recordRefreshRate(uint32_t fps, nsecs_t duration) = 0;
+    virtual void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) = 0;
+};
+
+namespace impl {
+
+class TimeStats : public android::TimeStats {
     struct FrameTime {
         uint64_t frameNumber = 0;
         nsecs_t postTime = 0;
@@ -75,32 +109,33 @@
 
 public:
     TimeStats() = default;
-    ~TimeStats() = default;
 
-    void parseArgs(bool asProto, const Vector<String16>& args, std::string& result);
-    bool isEnabled();
+    void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) override;
+    bool isEnabled() override;
 
-    void incrementTotalFrames();
-    void incrementMissedFrames();
-    void incrementClientCompositionFrames();
+    void incrementTotalFrames() override;
+    void incrementMissedFrames() override;
+    void incrementClientCompositionFrames() override;
 
     void setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName,
-                     nsecs_t postTime);
-    void setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime);
-    void setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime);
-    void setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime);
+                     nsecs_t postTime) override;
+    void setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime) override;
+    void setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime) override;
+    void setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime) override;
     void setAcquireFence(int32_t layerID, uint64_t frameNumber,
-                         const std::shared_ptr<FenceTime>& acquireFence);
-    void setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime);
+                         const std::shared_ptr<FenceTime>& acquireFence) override;
+    void setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime) override;
     void setPresentFence(int32_t layerID, uint64_t frameNumber,
-                         const std::shared_ptr<FenceTime>& presentFence);
+                         const std::shared_ptr<FenceTime>& presentFence) override;
     // Clean up the layer record
-    void onDestroy(int32_t layerID);
+    void onDestroy(int32_t layerID) override;
     // If SF skips or rejects a buffer, remove the corresponding TimeRecord.
-    void removeTimeRecord(int32_t layerID, uint64_t frameNumber);
+    void removeTimeRecord(int32_t layerID, uint64_t frameNumber) override;
 
-    void setPowerMode(int32_t powerMode);
-    void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence);
+    void setPowerMode(int32_t powerMode) override;
+    // Source of truth is RefrehRateStats.
+    void recordRefreshRate(uint32_t fps, nsecs_t duration) override;
+    void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) override;
 
     // TODO(zzyiwei): Bound the timeStatsTracker with weighted LRU
     // static const size_t MAX_NUM_LAYER_RECORDS = 200;
@@ -126,4 +161,6 @@
     GlobalRecord mGlobalRecord;
 };
 
+} // namespace impl
+
 } // namespace android
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
index 75ce4be..16d2da0 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
+++ b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
@@ -103,6 +103,11 @@
     StringAppendF(&result, "missedFrames = %d\n", missedFrames);
     StringAppendF(&result, "clientCompositionFrames = %d\n", clientCompositionFrames);
     StringAppendF(&result, "displayOnTime = %" PRId64 " ms\n", displayOnTime);
+    StringAppendF(&result, "displayConfigStats is as below:\n");
+    for (const auto& [fps, duration] : refreshRateStats) {
+        StringAppendF(&result, "%dfps=%ldms ", fps, ns2ms(duration));
+    }
+    result.back() = '\n';
     StringAppendF(&result, "totalP2PTime = %" PRId64 " ms\n", presentToPresent.totalTime());
     StringAppendF(&result, "presentToPresent histogram is as below:\n");
     result.append(presentToPresent.toString());
@@ -141,6 +146,13 @@
     globalProto.set_missed_frames(missedFrames);
     globalProto.set_client_composition_frames(clientCompositionFrames);
     globalProto.set_display_on_time(displayOnTime);
+    for (const auto& ele : refreshRateStats) {
+        SFTimeStatsDisplayConfigBucketProto* configBucketProto =
+                globalProto.add_display_config_stats();
+        SFTimeStatsDisplayConfigProto* configProto = configBucketProto->mutable_config();
+        configProto->set_fps(ele.first);
+        configBucketProto->set_duration_millis(ns2ms(ele.second));
+    }
     for (const auto& histEle : presentToPresent.hist) {
         SFTimeStatsHistogramBucketProto* histProto = globalProto.add_present_to_present();
         histProto->set_time_millis(histEle.first);
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
index 5f40a1a..f2ac7ff 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
+++ b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
@@ -16,6 +16,7 @@
 #pragma once
 
 #include <timestatsproto/TimeStatsProtoHeader.h>
+#include <utils/Timers.h>
 
 #include <optional>
 #include <string>
@@ -61,6 +62,7 @@
         int64_t displayOnTime = 0;
         Histogram presentToPresent;
         std::unordered_map<std::string, TimeStatsLayer> stats;
+        std::unordered_map<uint32_t, nsecs_t> refreshRateStats;
 
         std::string toString(std::optional<uint32_t> maxLayers) const;
         SFTimeStatsGlobalProto toProto(std::optional<uint32_t> maxLayers) const;
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto b/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto
index 377612a..0dacbeb 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto
+++ b/services/surfaceflinger/TimeStats/timestatsproto/timestats.proto
@@ -25,7 +25,7 @@
 // changes to these messages, and keep google3 side proto messages in sync if
 // the end to end pipeline needs to be updated.
 
-// Next tag: 9
+// Next tag: 10
 message SFTimeStatsGlobalProto {
   // The stats start time in UTC as seconds since January 1, 1970
   optional int64 stats_start = 1;
@@ -39,6 +39,8 @@
   optional int32 client_composition_frames = 5;
   // Primary display on time in milliseconds.
   optional int64 display_on_time = 7;
+  // Stats per display configuration.
+  repeated SFTimeStatsDisplayConfigBucketProto display_config_stats = 9;
   // Present to present histogram.
   repeated SFTimeStatsHistogramBucketProto present_to_present = 8;
   // Stats per layer. Apps could have multiple layers.
@@ -80,3 +82,18 @@
   // Number of frames in the bucket.
   optional int32 frame_count = 2;
 }
+
+// Next tag: 3
+message SFTimeStatsDisplayConfigBucketProto {
+    // Metadata desribing a display config.
+    optional SFTimeStatsDisplayConfigProto config = 1;
+    // Duration in milliseconds for how long the display was in this
+    // configuration.
+    optional int64 duration_millis = 2;
+}
+
+// Next tag: 2
+message SFTimeStatsDisplayConfigProto {
+    // Frames per second, rounded to the nearest integer.
+    optional int32 fps = 1;
+}
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 56d3bd4..4f0ded3 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -675,6 +675,8 @@
     void setRelativeZBasicHelper(uint32_t layerType);
     void setRelativeZGroupHelper(uint32_t layerType);
     void setAlphaBasicHelper(uint32_t layerType);
+    void setBackgroundColorHelper(uint32_t layerType, bool priorColor, bool bufferFill, float alpha,
+                                  Color finalColor);
 
 protected:
     LayerRenderPathTestHarness mHarness;
@@ -1330,92 +1332,6 @@
     getScreenCapture()->expectColor(Rect(16, 16, 48, 48), Color::RED);
 }
 
-TEST_P(LayerRenderTypeTransactionTest, SetColorAlpha_Color_NoEffect) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(
-            layer = createLayer("test", 0, 0, ISurfaceComposerClient::eFXSurfaceColor));
-
-    half3 color;
-    color.r = 1.0f;
-    color.g = 0.0f;
-    color.b = 0.0f;
-    Transaction()
-            .setCrop_legacy(layer, Rect(0, 0, 32, 32))
-            .setAlpha(layer, 1.0f)
-            .setColor(layer, color)
-            .setColorAlpha(layer, 0.5f)
-            .apply();
-
-    screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetColorAlpha_BufferQueue_NoEffect) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
-    Transaction().setAlpha(layer, 1.0f).setColorAlpha(layer, 0.5f).apply();
-
-    screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetColorAlpha_BufferState_ColorLayer) {
-    sp<SurfaceControl> bgLayer;
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(bgLayer = createLayer("test bg", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(
-            layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bgLayer, Color::RED, 32, 32));
-
-    // create color layer
-    half3 color;
-    color.r = 0.0f;
-    color.g = 1.0f;
-    color.b = 0.0f;
-    Transaction().setFrame(layer, Rect(0, 0, 32, 32)).setColor(layer, color).apply();
-
-    {
-        SCOPED_TRACE("before alpha");
-        auto shot = screenshot();
-        shot->expectColor(Rect(0, 0, 32, 32), Color::GREEN);
-        shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
-    }
-
-    // apply alpha
-    Transaction().setAlpha(layer, 0.0f).apply();
-    {
-        SCOPED_TRACE("set alpha");
-        auto shot = screenshot();
-        shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
-        shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
-    }
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetColorAlpha_BufferState_NoColorLayer) {
-    sp<SurfaceControl> bgLayer;
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(bgLayer = createLayer("test bg", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(
-            layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bgLayer, Color::RED, 32, 32));
-
-    {
-        SCOPED_TRACE("before alpha");
-        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-    }
-
-    // setting alpha without creating color layer should have no effect
-    Transaction().setFrame(layer, Rect(0, 0, 32, 32)).setAlpha(layer, 0.5f).apply();
-    {
-        SCOPED_TRACE("alpha");
-        auto shot = screenshot();
-        shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
-        shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
-    }
-}
-
 void LayerRenderTypeTransactionTest::setAlphaBasicHelper(uint32_t layerType) {
     sp<SurfaceControl> layer1;
     sp<SurfaceControl> layer2;
@@ -1567,75 +1483,190 @@
     }
 }
 
-TEST_P(LayerRenderTypeTransactionTest, SetBackgroundColor_BufferState_NoPriorColor) {
-    sp<SurfaceControl> bufferQueueLayer;
-    sp<SurfaceControl> bufferStateLayer;
-    ASSERT_NO_FATAL_FAILURE(bufferQueueLayer = createLayer("test bg", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(
-            bufferStateLayer =
-                    createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+// RED: Color layer base color and BufferQueueLayer/BufferStateLayer fill
+// BLUE: prior background color
+// GREEN: final background color
+// BLACK: no color or fill
+void LayerRenderTypeTransactionTest::setBackgroundColorHelper(uint32_t layerType, bool priorColor,
+                                                              bool bufferFill, float alpha,
+                                                              Color finalColor) {
+    sp<SurfaceControl> layer;
+    int32_t width = 500;
+    int32_t height = 500;
 
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferQueueLayer, Color::RED, 32, 32));
-
-    {
-        SCOPED_TRACE("default color");
-        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    Color fillColor = Color::RED;
+    Color priorBgColor = Color::BLUE;
+    Color expectedColor = Color::BLACK;
+    switch (layerType) {
+        case ISurfaceComposerClient::eFXSurfaceColor:
+            ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 0, 0, layerType));
+            Transaction()
+                    .setCrop_legacy(layer, Rect(0, 0, width, height))
+                    .setColor(layer, half3(1.0f, 0, 0))
+                    .apply();
+            expectedColor = fillColor;
+            break;
+        case ISurfaceComposerClient::eFXSurfaceBufferQueue:
+            ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height));
+            if (bufferFill) {
+                ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, fillColor, width, height));
+                expectedColor = fillColor;
+            }
+            Transaction().setCrop_legacy(layer, Rect(0, 0, width, height)).apply();
+            break;
+        case ISurfaceComposerClient::eFXSurfaceBufferState:
+            ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height, layerType));
+            if (bufferFill) {
+                ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, fillColor, width, height));
+                expectedColor = fillColor;
+            }
+            Transaction().setFrame(layer, Rect(0, 0, width, height)).apply();
+            break;
+        default:
+            GTEST_FAIL() << "Unknown layer type in setBackgroundColorHelper";
+            return;
     }
 
-    half3 color;
-    color.r = 0.0f;
-    color.g = 1.0f;
-    color.b = 0.0f;
+    if (priorColor && layerType != ISurfaceComposerClient::eFXSurfaceColor) {
+        Transaction()
+                .setBackgroundColor(layer, half3(0, 0, 1.0f), 1.0f, ui::Dataspace::UNKNOWN)
+                .apply();
+        if (!bufferFill) {
+            expectedColor = priorBgColor;
+        }
+    }
+
+    {
+        SCOPED_TRACE("default before setting background color layer");
+        screenshot()->expectColor(Rect(0, 0, width, height), expectedColor);
+    }
+
     Transaction()
-            .setFrame(bufferStateLayer, Rect(0, 0, 32, 32))
-            .setLayer(bufferStateLayer, mLayerZBase + 1)
-            .setColor(bufferStateLayer, color)
+            .setBackgroundColor(layer, half3(0, 1.0f, 0), alpha, ui::Dataspace::UNKNOWN)
             .apply();
 
     {
-        SCOPED_TRACE("set color");
         auto shot = screenshot();
-        shot->expectColor(Rect(0, 0, 32, 32), Color::GREEN);
-        shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+        shot->expectColor(Rect(0, 0, width, height), finalColor);
+        shot->expectBorder(Rect(0, 0, width, height), Color::BLACK);
     }
 }
 
-TEST_P(LayerRenderTypeTransactionTest, SetBackgroundColor_BufferState_PriorColor) {
-    sp<SurfaceControl> bufferQueueLayer;
-    sp<SurfaceControl> bufferStateLayer;
-    ASSERT_NO_FATAL_FAILURE(bufferQueueLayer = createLayer("test bg", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(
-            bufferStateLayer =
-                    createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+TEST_P(LayerRenderTypeTransactionTest, SetBackgroundColor_Color_NoEffect) {
+    bool priorColor = false;
+    bool bufferFill = false;
+    float alpha = 1.0f;
+    Color finalColor = Color::RED;
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceColor,
+                                                     priorColor, bufferFill, alpha, finalColor));
+}
 
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferQueueLayer, Color::RED, 32, 32));
+TEST_P(LayerRenderTypeTransactionTest,
+       SetBackgroundColor_BufferQueue_BufferFill_NoPriorColor_Basic) {
+    bool priorColor = false;
+    bool bufferFill = true;
+    float alpha = 1.0f;
+    Color finalColor = Color::RED;
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+                                                     priorColor, bufferFill, alpha, finalColor));
+}
 
-    half3 color;
-    color.r = 0.0f;
-    color.g = 1.0f;
-    color.b = 0.0f;
-    Transaction()
-            .setFrame(bufferStateLayer, Rect(0, 0, 32, 32))
-            .setLayer(bufferStateLayer, mLayerZBase + 1)
-            .setColor(bufferStateLayer, color)
-            .apply();
-    {
-        SCOPED_TRACE("default color");
-        auto shot = screenshot();
-        shot->expectColor(Rect(0, 0, 32, 32), Color::GREEN);
-        shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
-    }
+TEST_P(LayerRenderTypeTransactionTest,
+       SetBackgroundColor_BufferQueue_NoBufferFill_NoPriorColor_Basic) {
+    bool priorColor = false;
+    bool bufferFill = false;
+    float alpha = 1.0f;
+    Color finalColor = Color::GREEN;
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+                                                     priorColor, bufferFill, alpha, finalColor));
+}
 
-    color.r = 0.0f;
-    color.g = 0.0f;
-    color.b = 1.0f;
-    Transaction().setColor(bufferStateLayer, color).apply();
-    {
-        SCOPED_TRACE("new color");
-        auto shot = screenshot();
-        shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
-        shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
-    }
+TEST_P(LayerRenderTypeTransactionTest, SetBackgroundColor_BufferQueue_BufferFill_PriorColor_Basic) {
+    bool priorColor = true;
+    bool bufferFill = true;
+    float alpha = 1.0f;
+    Color finalColor = Color::RED;
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+                                                     priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest,
+       SetBackgroundColor_BufferQueue_NoBufferFill_PriorColor_Basic) {
+    bool priorColor = true;
+    bool bufferFill = false;
+    float alpha = 1.0f;
+    Color finalColor = Color::GREEN;
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+                                                     priorColor, bufferFill, alpha, finalColor));
+}
+TEST_P(LayerRenderTypeTransactionTest,
+       SetBackgroundColor_BufferQueue_NoPriorColor_ZeroAlpha_NoEffect) {
+    bool priorColor = false;
+    bool bufferFill = false;
+    float alpha = 0;
+    Color finalColor = Color::BLACK;
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+                                                     priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest,
+       SetBackgroundColor_BufferQueue_PriorColor_ZeroAlpha_DeleteBackground) {
+    bool priorColor = true;
+    bool bufferFill = false;
+    float alpha = 0;
+    Color finalColor = Color::BLACK;
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+                                                     priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest,
+       SetBackgroundColor_BufferState_BufferFill_NoPriorColor_Basic) {
+    bool priorColor = false;
+    bool bufferFill = true;
+    float alpha = 1.0f;
+    Color finalColor = Color::RED;
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+                                                     priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest,
+       SetBackgroundColor_BufferState_NoBufferFill_NoPriorColor_Basic) {
+    bool priorColor = false;
+    bool bufferFill = false;
+    float alpha = 1.0f;
+    Color finalColor = Color::GREEN;
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+                                                     priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest,
+       SetBackgroundColor_BufferState_NoBufferFill_PriorColor_Basic) {
+    bool priorColor = true;
+    bool bufferFill = false;
+    float alpha = 1.0f;
+    Color finalColor = Color::GREEN;
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+                                                     priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest,
+       SetBackgroundColor_BufferState_NoPriorColor_ZeroAlpha_NoEffect) {
+    bool priorColor = false;
+    bool bufferFill = false;
+    float alpha = 0;
+    Color finalColor = Color::BLACK;
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+                                                     priorColor, bufferFill, alpha, finalColor));
+}
+
+TEST_P(LayerRenderTypeTransactionTest,
+       SetBackgroundColor_BufferState_PriorColor_ZeroAlpha_DeleteBackground) {
+    bool priorColor = true;
+    bool bufferFill = false;
+    float alpha = 0;
+    Color finalColor = Color::BLACK;
+    ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue,
+                                                     priorColor, bufferFill, alpha, finalColor));
 }
 
 TEST_P(LayerRenderTypeTransactionTest, SetColorClamped) {
@@ -2491,71 +2522,6 @@
     shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
 }
 
-TEST_P(LayerRenderTypeTransactionTest, SetColorDataspace_ColorLayer_NoEffect) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(
-            layer = createLayer("test", 0, 0, ISurfaceComposerClient::eFXSurfaceColor));
-    half3 color;
-    color.r = 1.0f;
-    color.g = 0.0f;
-    color.b = 0.0f;
-    Transaction()
-            .setCrop_legacy(layer, Rect(0, 0, 32, 32))
-            .setColor(layer, color)
-            .setDataspace(layer, ui::Dataspace::UNKNOWN)
-            .setColorDataspace(layer, ui::Dataspace::BT2020_ITU)
-            .apply();
-
-    screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetColorDataspace_BufferQueue_NoEffect) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
-    Transaction()
-            .setDataspace(layer, ui::Dataspace::UNKNOWN)
-            .setColorDataspace(layer, ui::Dataspace::BT2020_ITU)
-            .apply();
-
-    screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetColorDataspace_BufferState_ColorLayer) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(
-            layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-
-    half3 color;
-    color.r = 1.0f;
-    color.g = 0.0f;
-    color.b = 0.0f;
-    Transaction()
-            .setFrame(layer, Rect(0, 0, 32, 32))
-            .setColor(layer, color)
-            .setColorDataspace(layer, ui::Dataspace::BT2020_ITU)
-            .apply();
-    auto shot = screenshot();
-    shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
-    shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
-}
-
-TEST_P(LayerRenderTypeTransactionTest, SetColorDataspace_BufferState_NoColorLayer) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(
-            layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
-    ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
-
-    Transaction()
-            .setFrame(layer, Rect(0, 0, 32, 32))
-            .setDataspace(layer, ui::Dataspace::UNKNOWN)
-            .setColorDataspace(layer, ui::Dataspace::DCI_P3)
-            .apply();
-
-    screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-}
-
 TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) {
     sp<SurfaceControl> layer;
     ASSERT_NO_FATAL_FAILURE(
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index a2c0611..68cf61e 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -31,6 +31,7 @@
         "libutils",
     ],
     static_libs: [
+        "libcompositionengine",
         "libgmock",
         "librenderengine",
         "libtrace_proto",
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index b2bcb45..b1d45f39 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -58,6 +58,7 @@
         "mock/MockMessageQueue.cpp",
         "mock/MockNativeWindowSurface.cpp",
         "mock/MockSurfaceInterceptor.cpp",
+        "mock/MockTimeStats.cpp",
         "mock/system/window/MockNativeWindow.cpp",
     ],
     static_libs: [
diff --git a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
new file mode 100644
index 0000000..0739f15
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019 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 "Scheduler/PhaseOffsets.h"
+
+namespace android {
+namespace scheduler {
+
+class FakePhaseOffsets : public android::scheduler::PhaseOffsets {
+    nsecs_t FAKE_PHASE_OFFSET_NS = 0;
+
+public:
+    FakePhaseOffsets() = default;
+    ~FakePhaseOffsets() = default;
+
+    nsecs_t getCurrentAppOffset() override { return FAKE_PHASE_OFFSET_NS; }
+    nsecs_t getCurrentSfOffset() override { return FAKE_PHASE_OFFSET_NS; }
+
+    // Returns early, early GL, and late offsets for Apps and SF.
+    PhaseOffsets::Offsets getCurrentOffsets() const override {
+        return Offsets{{FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
+                       {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
+                       {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}};
+    }
+
+    // This function should be called when the device is switching between different
+    // refresh rates, to properly update the offsets.
+    void setRefreshRateType(RefreshRateConfigs::RefreshRateType /*refreshRateType*/) override {}
+
+    // Returns current offsets in human friendly format.
+    void dump(std::string& /*result*/) const override {}
+};
+
+} // namespace scheduler
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
index 0384d9d..3d887ea 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
@@ -23,8 +23,10 @@
 
 #include "Scheduler/RefreshRateStats.h"
 #include "mock/DisplayHardware/MockDisplay.h"
+#include "mock/MockTimeStats.h"
 
 using namespace std::chrono_literals;
+using testing::_;
 
 namespace android {
 namespace scheduler {
@@ -42,6 +44,7 @@
     void init(std::vector<std::shared_ptr<const HWC2::Display::Config>> configs);
 
     std::unique_ptr<RefreshRateStats> mRefreshRateStats;
+    std::shared_ptr<android::mock::TimeStats> mTimeStats;
 };
 
 RefreshRateStatsTest::RefreshRateStatsTest() {
@@ -57,7 +60,8 @@
 }
 
 void RefreshRateStatsTest::init(std::vector<std::shared_ptr<const HWC2::Display::Config>> configs) {
-    mRefreshRateStats = std::make_unique<RefreshRateStats>(configs);
+    mTimeStats = std::make_shared<android::mock::TimeStats>();
+    mRefreshRateStats = std::make_unique<RefreshRateStats>(configs, mTimeStats);
 }
 
 namespace {
@@ -82,6 +86,9 @@
 
     init(configs);
 
+    EXPECT_CALL(*mTimeStats, recordRefreshRate(0, _)).Times(4);
+    EXPECT_CALL(*mTimeStats, recordRefreshRate(90, _)).Times(2);
+
     std::unordered_map<std::string, int64_t> times = mRefreshRateStats->getTotalTimes();
     ASSERT_EQ(2, times.size());
     ASSERT_EQ(0, times["ScreenOff"]);
@@ -136,6 +143,10 @@
 
     init(configs);
 
+    EXPECT_CALL(*mTimeStats, recordRefreshRate(0, _)).Times(6);
+    EXPECT_CALL(*mTimeStats, recordRefreshRate(60, _)).Times(4);
+    EXPECT_CALL(*mTimeStats, recordRefreshRate(90, _)).Times(4);
+
     std::unordered_map<std::string, int64_t> times = mRefreshRateStats->getTotalTimes();
     ASSERT_EQ(3, times.size());
     ASSERT_EQ(0, times["ScreenOff"]);
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index b9b0cf8..e639b4d 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -23,6 +23,7 @@
 #include "ColorLayer.h"
 #include "ContainerLayer.h"
 #include "DisplayDevice.h"
+#include "FakePhaseOffsets.h"
 #include "Layer.h"
 #include "NativeWindowSurface.h"
 #include "StartPropertySetThread.h"
@@ -75,6 +76,10 @@
         return std::make_unique<android::impl::MessageQueue>();
     }
 
+    std::unique_ptr<scheduler::PhaseOffsets> createPhaseOffsets() override {
+        return std::make_unique<scheduler::FakePhaseOffsets>();
+    }
+
     std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)>) override {
         // TODO: Use test-fixture controlled factory
         return nullptr;
@@ -139,9 +144,9 @@
         return nullptr;
     }
 
-    std::unique_ptr<TimeStats> createTimeStats() override {
+    std::shared_ptr<TimeStats> createTimeStats() override {
         // TODO: Use test-fixture controlled factory
-        return std::make_unique<TimeStats>();
+        return std::make_shared<android::impl::TimeStats>();
     }
 
     using CreateBufferQueueFunction =
diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
index 0f95cf9..f35758d 100644
--- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
@@ -17,6 +17,7 @@
 #undef LOG_TAG
 #define LOG_TAG "LibSurfaceFlingerUnittests"
 
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
 #include <log/log.h>
@@ -24,6 +25,7 @@
 #include <utils/Vector.h>
 
 #include <random>
+#include <unordered_set>
 
 #include "TimeStats/TimeStats.h"
 
@@ -35,6 +37,10 @@
 namespace android {
 namespace {
 
+using testing::Contains;
+using testing::SizeIs;
+using testing::UnorderedElementsAre;
+
 // clang-format off
 #define FMT_PROTO          true
 #define FMT_STRING         false
@@ -127,7 +133,7 @@
     }
 
     std::mt19937 mRandomEngine = std::mt19937(std::random_device()());
-    std::unique_ptr<TimeStats> mTimeStats = std::make_unique<TimeStats>();
+    std::unique_ptr<TimeStats> mTimeStats = std::make_unique<impl::TimeStats>();
 };
 
 std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) {
@@ -371,6 +377,63 @@
     }
 }
 
+TEST_F(TimeStatsTest, recordRefreshRateNewConfigs) {
+    EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
+
+    uint32_t fpsOne = 30;
+    uint32_t fpsTwo = 90;
+    uint64_t millisOne = 5000;
+    uint64_t millisTwo = 7000;
+
+    mTimeStats->recordRefreshRate(fpsOne, ms2ns(millisOne));
+    mTimeStats->recordRefreshRate(fpsTwo, ms2ns(millisTwo));
+
+    SFTimeStatsGlobalProto globalProto;
+    ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
+
+    SFTimeStatsDisplayConfigBucketProto expectedBucketOne;
+    SFTimeStatsDisplayConfigProto* expectedConfigOne = expectedBucketOne.mutable_config();
+    expectedConfigOne->set_fps(fpsOne);
+    expectedBucketOne.set_duration_millis(millisOne);
+
+    SFTimeStatsDisplayConfigBucketProto expectedBucketTwo;
+    SFTimeStatsDisplayConfigProto* expectedConfigTwo = expectedBucketTwo.mutable_config();
+    expectedConfigTwo->set_fps(fpsTwo);
+    expectedBucketTwo.set_duration_millis(millisTwo);
+
+    EXPECT_THAT(globalProto.display_config_stats(), SizeIs(2));
+
+    std::unordered_set<uint32_t> seen_fps;
+    for (const auto& bucket : globalProto.display_config_stats()) {
+        seen_fps.emplace(bucket.config().fps());
+        if (fpsOne == bucket.config().fps()) {
+            EXPECT_EQ(millisOne, bucket.duration_millis());
+        } else if (fpsTwo == bucket.config().fps()) {
+            EXPECT_EQ(millisTwo, bucket.duration_millis());
+        } else {
+            FAIL() << "Unknown fps: " << bucket.config().fps();
+        }
+    }
+    EXPECT_THAT(seen_fps, UnorderedElementsAre(fpsOne, fpsTwo));
+}
+
+TEST_F(TimeStatsTest, recordRefreshRateUpdatesConfig) {
+    EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
+
+    uint32_t fps = 30;
+    uint64_t millisOne = 5000;
+    uint64_t millisTwo = 7000;
+
+    mTimeStats->recordRefreshRate(fps, ms2ns(millisOne));
+    mTimeStats->recordRefreshRate(fps, ms2ns(millisTwo));
+
+    SFTimeStatsGlobalProto globalProto;
+    ASSERT_TRUE(globalProto.ParseFromString(inputCommand(InputCommand::DUMP_ALL, FMT_PROTO)));
+    EXPECT_THAT(globalProto.display_config_stats(), SizeIs(1));
+    EXPECT_EQ(fps, globalProto.display_config_stats().Get(0).config().fps());
+    EXPECT_EQ(millisOne + millisTwo, globalProto.display_config_stats().Get(0).duration_millis());
+}
+
 TEST_F(TimeStatsTest, canRemoveTimeRecord) {
     EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
 
@@ -394,7 +457,7 @@
     uint64_t frameNumber = 1;
     nsecs_t ts = 1000000;
     insertTimeRecord(INCOMPLETE_SEQUENCE, LAYER_ID_0, 1, 1000000);
-    for (size_t i = 0; i < TimeStats::MAX_NUM_TIME_RECORDS + 2; i++) {
+    for (size_t i = 0; i < impl::TimeStats::MAX_NUM_TIME_RECORDS + 2; i++) {
         frameNumber++;
         ts += 1000000;
         insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, frameNumber, ts);
diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.cpp b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.cpp
new file mode 100644
index 0000000..d686939
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mock/MockTimeStats.h"
+
+namespace android {
+namespace mock {
+
+// Explicit default instantiation is recommended.
+TimeStats::TimeStats() = default;
+TimeStats::~TimeStats() = default;
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
new file mode 100644
index 0000000..08fdb9d
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019 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 "TimeStats/TimeStats.h"
+
+namespace android {
+namespace mock {
+
+class TimeStats : public android::TimeStats {
+public:
+    TimeStats();
+    ~TimeStats() override;
+
+    MOCK_METHOD3(parseArgs, void(bool, const Vector<String16>&, std::string&));
+    MOCK_METHOD0(isEnabled, bool());
+    MOCK_METHOD0(incrementTotalFrames, void());
+    MOCK_METHOD0(incrementMissedFrames, void());
+    MOCK_METHOD0(incrementClientCompositionFrames, void());
+    MOCK_METHOD4(setPostTime, void(int32_t, uint64_t, const std::string&, nsecs_t));
+    MOCK_METHOD3(setLatchTime, void(int32_t, uint64_t, nsecs_t));
+    MOCK_METHOD3(setDesiredTime, void(int32_t, uint64_t, nsecs_t));
+    MOCK_METHOD3(setAcquireTime, void(int32_t, uint64_t, nsecs_t));
+    MOCK_METHOD3(setAcquireFence, void(int32_t, uint64_t, const std::shared_ptr<FenceTime>&));
+    MOCK_METHOD3(setPresentTime, void(int32_t, uint64_t, nsecs_t));
+    MOCK_METHOD3(setPresentFence, void(int32_t, uint64_t, const std::shared_ptr<FenceTime>&));
+    MOCK_METHOD1(onDestroy, void(int32_t));
+    MOCK_METHOD2(removeTimeRecord, void(int32_t, uint64_t));
+    MOCK_METHOD1(setPowerMode, void(int32_t));
+    MOCK_METHOD2(recordRefreshRate, void(uint32_t, nsecs_t));
+    MOCK_METHOD1(setPresentFenceGlobal, void(const std::shared_ptr<FenceTime>&));
+};
+
+} // namespace mock
+} // namespace android