Merge "gralloc: add mapper 3.0 to composer makefiles"
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 53b3a00..bd3d2d8 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -99,30 +99,31 @@
 
 /* Tracing categories */
 static const TracingCategory k_categories[] = {
-    { "gfx",        "Graphics",         ATRACE_TAG_GRAPHICS, { } },
-    { "input",      "Input",            ATRACE_TAG_INPUT, { } },
-    { "view",       "View System",      ATRACE_TAG_VIEW, { } },
-    { "webview",    "WebView",          ATRACE_TAG_WEBVIEW, { } },
-    { "wm",         "Window Manager",   ATRACE_TAG_WINDOW_MANAGER, { } },
-    { "am",         "Activity Manager", ATRACE_TAG_ACTIVITY_MANAGER, { } },
-    { "sm",         "Sync Manager",     ATRACE_TAG_SYNC_MANAGER, { } },
-    { "audio",      "Audio",            ATRACE_TAG_AUDIO, { } },
-    { "video",      "Video",            ATRACE_TAG_VIDEO, { } },
-    { "camera",     "Camera",           ATRACE_TAG_CAMERA, { } },
-    { "hal",        "Hardware Modules", ATRACE_TAG_HAL, { } },
-    { "res",        "Resource Loading", ATRACE_TAG_RESOURCES, { } },
-    { "dalvik",     "Dalvik VM",        ATRACE_TAG_DALVIK, { } },
-    { "rs",         "RenderScript",     ATRACE_TAG_RS, { } },
-    { "bionic",     "Bionic C Library", ATRACE_TAG_BIONIC, { } },
-    { "power",      "Power Management", ATRACE_TAG_POWER, { } },
-    { "pm",         "Package Manager",  ATRACE_TAG_PACKAGE_MANAGER, { } },
-    { "ss",         "System Server",    ATRACE_TAG_SYSTEM_SERVER, { } },
-    { "database",   "Database",         ATRACE_TAG_DATABASE, { } },
-    { "network",    "Network",          ATRACE_TAG_NETWORK, { } },
-    { "adb",        "ADB",              ATRACE_TAG_ADB, { } },
-    { "vibrator",   "Vibrator",         ATRACE_TAG_VIBRATOR, { } },
-    { "aidl",       "AIDL calls",       ATRACE_TAG_AIDL, { } },
-    { "nnapi",      "NNAPI",            ATRACE_TAG_NNAPI, { } },
+    { "gfx",        "Graphics",                 ATRACE_TAG_GRAPHICS, { } },
+    { "input",      "Input",                    ATRACE_TAG_INPUT, { } },
+    { "view",       "View System",              ATRACE_TAG_VIEW, { } },
+    { "webview",    "WebView",                  ATRACE_TAG_WEBVIEW, { } },
+    { "wm",         "Window Manager",           ATRACE_TAG_WINDOW_MANAGER, { } },
+    { "am",         "Activity Manager",         ATRACE_TAG_ACTIVITY_MANAGER, { } },
+    { "sm",         "Sync Manager",             ATRACE_TAG_SYNC_MANAGER, { } },
+    { "audio",      "Audio",                    ATRACE_TAG_AUDIO, { } },
+    { "video",      "Video",                    ATRACE_TAG_VIDEO, { } },
+    { "camera",     "Camera",                   ATRACE_TAG_CAMERA, { } },
+    { "hal",        "Hardware Modules",         ATRACE_TAG_HAL, { } },
+    { "res",        "Resource Loading",         ATRACE_TAG_RESOURCES, { } },
+    { "dalvik",     "Dalvik VM",                ATRACE_TAG_DALVIK, { } },
+    { "rs",         "RenderScript",             ATRACE_TAG_RS, { } },
+    { "bionic",     "Bionic C Library",         ATRACE_TAG_BIONIC, { } },
+    { "power",      "Power Management",         ATRACE_TAG_POWER, { } },
+    { "pm",         "Package Manager",          ATRACE_TAG_PACKAGE_MANAGER, { } },
+    { "ss",         "System Server",            ATRACE_TAG_SYSTEM_SERVER, { } },
+    { "database",   "Database",                 ATRACE_TAG_DATABASE, { } },
+    { "network",    "Network",                  ATRACE_TAG_NETWORK, { } },
+    { "adb",        "ADB",                      ATRACE_TAG_ADB, { } },
+    { "vibrator",   "Vibrator",                 ATRACE_TAG_VIBRATOR, { } },
+    { "aidl",       "AIDL calls",               ATRACE_TAG_AIDL, { } },
+    { "nnapi",      "NNAPI",                    ATRACE_TAG_NNAPI, { } },
+    { "rro",        "Runtime Resource Overlay", ATRACE_TAG_RRO, { } },
     { k_coreServiceCategory, "Core services", 0, { } },
     { k_pdxServiceCategory, "PDX services", 0, { } },
     { "sched",      "CPU Scheduling",   0, {
diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc
index 5c28c9d..6c86c21 100644
--- a/cmds/atrace/atrace_userdebug.rc
+++ b/cmds/atrace/atrace_userdebug.rc
@@ -5,6 +5,12 @@
 # Access control to these files is now entirely in selinux policy.
 
 on post-fs
+    # On userdebug allow to enable any event via the generic
+    # set_event interface:
+    # echo sched/foo > set_event == echo 1 > events/sched/foo/enable.
+    chmod 0666 /sys/kernel/tracing/set_event
+    chmod 0666 /sys/kernel/debug/tracing/set_event
+
     chmod 0666 /sys/kernel/tracing/events/workqueue/enable
     chmod 0666 /sys/kernel/debug/tracing/events/workqueue/enable
     chmod 0666 /sys/kernel/tracing/events/regulator/enable
diff --git a/cmds/cmd/Android.bp b/cmds/cmd/Android.bp
index d91184a..8ea71cd 100644
--- a/cmds/cmd/Android.bp
+++ b/cmds/cmd/Android.bp
@@ -1,7 +1,31 @@
+cc_library_static {
+    name: "libcmd",
+
+    srcs: ["cmd.cpp"],
+    export_include_dirs: ["."],
+
+    shared_libs: [
+        "libutils",
+        "liblog",
+        "libselinux",
+        "libbinder",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-DXP_UNIX",
+    ],
+}
+
 cc_binary {
     name: "cmd",
 
-    srcs: ["cmd.cpp"],
+    srcs: ["main.cpp"],
+
+    static_libs: [
+        "libcmd",
+    ],
 
     shared_libs: [
         "libutils",
diff --git a/cmds/cmd/cmd.cpp b/cmds/cmd/cmd.cpp
index 0616add..7b4aeb2 100644
--- a/cmds/cmd/cmd.cpp
+++ b/cmds/cmd/cmd.cpp
@@ -40,6 +40,8 @@
 #include "selinux/selinux.h"
 #include "selinux/android.h"
 
+#include "cmd.h"
+
 #define DEBUG 0
 
 using namespace android;
@@ -59,8 +61,11 @@
 class MyShellCallback : public BnShellCallback
 {
 public:
+    TextOutput& mErrorLog;
     bool mActive = true;
 
+    MyShellCallback(TextOutput& errorLog) : mErrorLog(errorLog) {}
+
     virtual int openFile(const String16& path, const String16& seLinuxContext,
             const String16& mode) {
         String8 path8(path);
@@ -69,7 +74,7 @@
         String8 fullPath(cwd);
         fullPath.appendPath(path8);
         if (!mActive) {
-            aerr << "Open attempt after active for: " << fullPath << endl;
+            mErrorLog << "Open attempt after active for: " << fullPath << endl;
             return -EPERM;
         }
 #if DEBUG
@@ -78,20 +83,20 @@
         int flags = 0;
         bool checkRead = false;
         bool checkWrite = false;
-        if (mode == String16("w")) {
+        if (mode == u"w") {
             flags = O_WRONLY|O_CREAT|O_TRUNC;
             checkWrite = true;
-        } else if (mode == String16("w+")) {
+        } else if (mode == u"w+") {
             flags = O_RDWR|O_CREAT|O_TRUNC;
             checkRead = checkWrite = true;
-        } else if (mode == String16("r")) {
+        } else if (mode == u"r") {
             flags = O_RDONLY;
             checkRead = true;
-        } else if (mode == String16("r+")) {
+        } else if (mode == u"r+") {
             flags = O_RDWR;
             checkRead = checkWrite = true;
         } else {
-            aerr << "Invalid mode requested: " << mode.string() << endl;
+            mErrorLog << "Invalid mode requested: " << mode.string() << endl;
             return -EINVAL;
         }
         int fd = open(fullPath.string(), flags, S_IRWXU|S_IRWXG);
@@ -114,9 +119,7 @@
                     ALOGD("openFile: failed selinux write check!");
 #endif
                     close(fd);
-                    aerr << "System server has no access to write file context " << context.get()
-                            << " (from path " << fullPath.string() << ", context "
-                            << seLinuxContext8.string() << ")" << endl;
+                    mErrorLog << "System server has no access to write file context " << context.get() << " (from path " << fullPath.string() << ", context " << seLinuxContext8.string() << ")" << endl;
                     return -EPERM;
                 }
             }
@@ -128,9 +131,7 @@
                     ALOGD("openFile: failed selinux read check!");
 #endif
                     close(fd);
-                    aerr << "System server has no access to read file context " << context.get()
-                            << " (from path " << fullPath.string() << ", context "
-                            << seLinuxContext8.string() << ")" << endl;
+                    mErrorLog << "System server has no access to read file context " << context.get() << " (from path " << fullPath.string() << ", context " << seLinuxContext8.string() << ")" << endl;
                     return -EPERM;
                 }
             }
@@ -163,9 +164,8 @@
     }
 };
 
-int main(int argc, char* const argv[])
-{
-    signal(SIGPIPE, SIG_IGN);
+int cmdMain(const std::vector<std::string_view>& argv, TextOutput& outputLog, TextOutput& errorLog,
+            int in, int out, int err, RunMode runMode) {
     sp<ProcessState> proc = ProcessState::self();
     proc->startThreadPool();
 
@@ -173,68 +173,77 @@
     ALOGD("cmd: starting");
 #endif
     sp<IServiceManager> sm = defaultServiceManager();
-    fflush(stdout);
+    if (runMode == RunMode::kStandalone) {
+        fflush(stdout);
+    }
     if (sm == nullptr) {
         ALOGW("Unable to get default service manager!");
-        aerr << "cmd: Unable to get default service manager!" << endl;
+        errorLog << "cmd: Unable to get default service manager!" << endl;
         return 20;
     }
 
-    if (argc == 1) {
-        aerr << "cmd: No service specified; use -l to list all services" << endl;
+    int argc = argv.size();
+
+    if (argc == 0) {
+        errorLog << "cmd: No service specified; use -l to list all services" << endl;
         return 20;
     }
 
-    if ((argc == 2) && (strcmp(argv[1], "-l") == 0)) {
+    if ((argc == 1) && (argv[0] == "-l")) {
         Vector<String16> services = sm->listServices();
         services.sort(sort_func);
-        aout << "Currently running services:" << endl;
+        outputLog << "Currently running services:" << endl;
 
         for (size_t i=0; i<services.size(); i++) {
             sp<IBinder> service = sm->checkService(services[i]);
             if (service != nullptr) {
-                aout << "  " << services[i] << endl;
+                outputLog << "  " << services[i] << endl;
             }
         }
         return 0;
     }
 
+    const auto cmd = argv[0];
+
     Vector<String16> args;
-    for (int i=2; i<argc; i++) {
-        args.add(String16(argv[i]));
+    String16 serviceName = String16(cmd.data(), cmd.size());
+    for (int i = 1; i < argc; i++) {
+        args.add(String16(argv[i].data(), argv[i].size()));
     }
-    String16 cmd = String16(argv[1]);
-    sp<IBinder> service = sm->checkService(cmd);
+    sp<IBinder> service = sm->checkService(serviceName);
     if (service == nullptr) {
-        ALOGW("Can't find service %s", argv[1]);
-        aerr << "cmd: Can't find service: " << argv[1] << endl;
+        if (runMode == RunMode::kStandalone) {
+            ALOGW("Can't find service %.*s", static_cast<int>(cmd.size()), cmd.data());
+        }
+        errorLog << "cmd: Can't find service: " << cmd << endl;
         return 20;
     }
 
-    sp<MyShellCallback> cb = new MyShellCallback();
+    sp<MyShellCallback> cb = new MyShellCallback(errorLog);
     sp<MyResultReceiver> result = new MyResultReceiver();
 
 #if DEBUG
-    ALOGD("cmd: Invoking %s in=%d, out=%d, err=%d", argv[1], STDIN_FILENO, STDOUT_FILENO,
-            STDERR_FILENO);
+    ALOGD("cmd: Invoking %s in=%d, out=%d, err=%d", cmd, in, out, err);
 #endif
 
     // TODO: block until a result is returned to MyResultReceiver.
-    status_t err = IBinder::shellCommand(service, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, args,
-            cb, result);
-    if (err < 0) {
+    status_t error = IBinder::shellCommand(service, in, out, err, args, cb, result);
+    if (error < 0) {
         const char* errstr;
-        switch (err) {
+        switch (error) {
             case BAD_TYPE: errstr = "Bad type"; break;
             case FAILED_TRANSACTION: errstr = "Failed transaction"; break;
             case FDS_NOT_ALLOWED: errstr = "File descriptors not allowed"; break;
             case UNEXPECTED_NULL: errstr = "Unexpected null"; break;
-            default: errstr = strerror(-err); break;
+            default: errstr = strerror(-error); break;
         }
-        ALOGW("Failure calling service %s: %s (%d)", argv[1], errstr, -err);
-        aout << "cmd: Failure calling service " << argv[1] << ": " << errstr << " ("
-                << (-err) << ")" << endl;
-        return err;
+        if (runMode == RunMode::kStandalone) {
+            ALOGW("Failure calling service %.*s: %s (%d)", static_cast<int>(cmd.size()), cmd.data(),
+                  errstr, -error);
+        }
+        outputLog << "cmd: Failure calling service " << cmd << ": " << errstr << " (" << (-error)
+                  << ")" << endl;
+        return error;
     }
 
     cb->mActive = false;
diff --git a/cmds/cmd/cmd.h b/cmds/cmd/cmd.h
new file mode 100644
index 0000000..a91e009
--- /dev/null
+++ b/cmds/cmd/cmd.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <binder/TextOutput.h>
+
+#include <string_view>
+#include <vector>
+
+enum class RunMode {
+    kStandalone,
+    kLibrary,
+};
+
+int cmdMain(const std::vector<std::string_view>& argv, android::TextOutput& outputLog,
+            android::TextOutput& errorLog, int in, int out, int err, RunMode runMode);
diff --git a/cmds/cmd/main.cpp b/cmds/cmd/main.cpp
new file mode 100644
index 0000000..2256e2a
--- /dev/null
+++ b/cmds/cmd/main.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015 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 <unistd.h>
+
+#include "cmd.h"
+
+int main(int argc, char* const argv[]) {
+    signal(SIGPIPE, SIG_IGN);
+
+    std::vector<std::string_view> arguments;
+    arguments.reserve(argc - 1);
+    // 0th argument is a program name, skipping.
+    for (int i = 1; i < argc; ++i) {
+        arguments.emplace_back(argv[i]);
+    }
+
+    return cmdMain(arguments, android::aout, android::aerr, STDIN_FILENO, STDOUT_FILENO,
+                   STDERR_FILENO, RunMode::kStandalone);
+}
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 849eb44..6596fa2 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -98,9 +98,10 @@
     return binder::Status::ok();
 }
 
-binder::Status DumpstateService::startBugreport(int, int bugreport_mode, int32_t* returned_id) {
-    // TODO(111441001): return a request id here.
-    *returned_id = -1;
+binder::Status DumpstateService::startBugreport(const android::base::unique_fd& bugreport_fd,
+                                                const android::base::unique_fd& screenshot_fd,
+                                                int bugreport_mode,
+                                                const sp<IDumpstateListener>& listener) {
     MYLOGI("startBugreport() with mode: %d\n", bugreport_mode);
 
     if (bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_FULL &&
@@ -114,9 +115,20 @@
                          StringPrintf("Invalid bugreport mode: %d", bugreport_mode));
     }
 
+    if (bugreport_fd.get() == -1 || screenshot_fd.get() == -1) {
+        return exception(binder::Status::EX_ILLEGAL_ARGUMENT, "Invalid file descriptor");
+    }
+
     std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
-    options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode));
+    options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_fd,
+                        screenshot_fd);
+
+    std::lock_guard<std::mutex> lock(lock_);
+    // TODO(b/111441001): Disallow multiple simultaneous bugreports.
     ds_.SetOptions(std::move(options));
+    if (listener != nullptr) {
+        ds_.listener_ = listener;
+    }
 
     pthread_t thread;
     status_t err = pthread_create(&thread, nullptr, callAndNotify, &ds_);
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index 58095b3..1705317 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -20,6 +20,7 @@
 #include <mutex>
 #include <vector>
 
+#include <android-base/unique_fd.h>
 #include <binder/BinderService.h>
 
 #include "android/os/BnDumpstate.h"
@@ -41,7 +42,9 @@
                                bool getSectionDetails,
                                sp<IDumpstateToken>* returned_token) override;
 
-    binder::Status startBugreport(int fd, int bugreport_mode, int32_t* returned_id) override;
+    binder::Status startBugreport(const android::base::unique_fd& bugreport_fd,
+                                  const android::base::unique_fd& screenshot_fd, int bugreport_mode,
+                                  const sp<IDumpstateListener>& listener) override;
 
   private:
     Dumpstate& ds_;
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index 617eab3..d24c953 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -25,8 +25,6 @@
   * {@hide}
   */
 interface IDumpstate {
-
-
     // TODO: remove method once startBugReport is used by Shell.
     /*
      * Sets the listener for this dumpstate progress.
@@ -63,6 +61,12 @@
 
     /*
      * Starts a bugreport in the background.
+     *
+     * @param bugreportFd the file to which the zipped bugreport should be written
+     * @param screenshotFd the file to which screenshot should be written; optional
+     * @param bugreportMode the mode that specifies other run time options; must be one of above
+     * @param listener callback for updates; optional
      */
-    int startBugreport(int fd, int bugreportMode);
+    void startBugreport(FileDescriptor bugreportFd, FileDescriptor screenshotFd, int bugreportMode,
+                        IDumpstateListener listener);
 }
diff --git a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
index 030d69d..2966c86 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstateListener.aidl
@@ -22,18 +22,48 @@
   * {@hide}
   */
 interface IDumpstateListener {
+    /**
+     * Called when there is a progress update.
+     *
+     * @param progress the progress in [0, 100]
+     */
+    oneway void onProgress(int progress);
+
+    /* Options specified are invalid or incompatible */
+    const int BUGREPORT_ERROR_INVALID_INPUT = 1;
+
+    /* Bugreport encountered a runtime error */
+    const int BUGREPORT_ERROR_RUNTIME_ERROR = 2;
+
+    /**
+     * Called on an error condition with one of the error codes listed above.
+     */
+    oneway void onError(int errorCode);
+
+    /**
+     * Called when taking bugreport finishes successfully
+     *
+     * @param durationMs time capturing bugreport took in milliseconds
+     * @param title title for the bugreport; helpful in reminding the user why they took it
+     * @param description detailed description for the bugreport
+     */
+     oneway void onFinished(long durationMs, @utf8InCpp String title,
+                            @utf8InCpp String description);
+
+    // TODO(b/111441001): Remove old methods when not used anymore.
     void onProgressUpdated(int progress);
     void onMaxProgressUpdated(int maxProgress);
 
     /**
-    * Called after every section is complete.
-    * @param  name          section name
-    * @param  status        values from status_t
-    *                       {@code OK} section completed successfully
-    *                       {@code TIMEOUT} dump timed out
-    *                       {@code != OK} error
-    * @param  size          size in bytes, may be invalid if status != OK
-    * @param  durationMs    duration in ms
-    */
+     * Called after every section is complete.
+     *
+     * @param  name          section name
+     * @param  status        values from status_t
+     *                       {@code OK} section completed successfully
+     *                       {@code TIMEOUT} dump timed out
+     *                       {@code != OK} error
+     * @param  size          size in bytes, may be invalid if status != OK
+     * @param  durationMs    duration in ms
+     */
     void onSectionComplete(@utf8InCpp String name, int status, int size, int durationMs);
 }
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 516e3d8..4e5d68d 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1572,6 +1572,15 @@
     RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
                SEC_TO_MSEC(10));
 
+    if (ds.IsZipping()) {
+        RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
+                   CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
+        DumpHals();
+    } else {
+        RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
+                   CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
+    }
+
     printf("========================================================\n");
     printf("== dumpstate: done (id %d)\n", ds.id_);
     printf("========================================================\n");
@@ -1692,7 +1701,7 @@
     printf("*** See dumpstate-board.txt entry ***\n");
 }
 
-static void ShowUsageAndExit(int exit_code = 1) {
+static void ShowUsage() {
     fprintf(stderr,
             "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
             "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
@@ -1712,12 +1721,6 @@
             "  -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
             "shouldn't be used with -P)\n"
             "  -v: prints the dumpstate header and exit\n");
-    exit(exit_code);
-}
-
-static void ExitOnInvalidArgs() {
-    fprintf(stderr, "invalid combination of args\n");
-    ShowUsageAndExit();
 }
 
 static void register_sig_handler() {
@@ -1878,8 +1881,9 @@
     ds.tmp_path_ = ds.GetPath(".tmp");
     ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
 
-    std::string destination = ds.options_->fd != -1 ? StringPrintf("[fd:%d]", ds.options_->fd)
-                                                    : ds.bugreport_dir_.c_str();
+    std::string destination = ds.options_->bugreport_fd.get() != -1
+                                  ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
+                                  : ds.bugreport_dir_.c_str();
     MYLOGD(
         "Bugreport dir: %s\n"
         "Internal Bugreport dir: %s\n"
@@ -1957,8 +1961,8 @@
             }
             // The zip file lives in an internal directory. Copy it over to output.
             bool copy_succeeded = false;
-            if (ds.options_->fd != -1) {
-                copy_succeeded = android::os::CopyFileToFd(ds.path_, ds.options_->fd);
+            if (ds.options_->bugreport_fd.get() != -1) {
+                copy_succeeded = android::os::CopyFileToFd(ds.path_, ds.options_->bugreport_fd.get());
             } else {
                 ds.final_path_ = ds.GetPath(ds.bugreport_dir_, ".zip");
                 copy_succeeded = android::os::CopyFileToFile(ds.path_, ds.final_path_);
@@ -2161,7 +2165,7 @@
     MYLOGI("telephony_only: %d\n", options.telephony_only);
     MYLOGI("wifi_only: %d\n", options.wifi_only);
     MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
-    MYLOGI("fd: %d\n", options.fd);
+    MYLOGI("fd: %d\n", options.bugreport_fd.get());
     MYLOGI("use_outfile: %s\n", options.use_outfile.c_str());
     MYLOGI("extra_options: %s\n", options.extra_options.c_str());
     MYLOGI("args: %s\n", options.args.c_str());
@@ -2169,14 +2173,17 @@
     MYLOGI("notification_description: %s\n", options.notification_description.c_str());
 }
 
-void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode) {
+void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
+                                        const android::base::unique_fd& bugreport_fd_in,
+                                        const android::base::unique_fd& screenshot_fd_in) {
     // In the new API world, date is always added; output is always a zip file.
     // TODO(111441001): remove these options once they are obsolete.
     do_add_date = true;
     do_zip_file = true;
 
-    // STOPSHIP b/111441001: Remove hardcoded output file path; accept fd.
-    use_outfile = "/data/user_de/0/com.android.shell/files/bugreports/bugreport";
+    // Duplicate the fds because the passed in fds don't outlive the binder transaction.
+    bugreport_fd.reset(dup(bugreport_fd_in.get()));
+    screenshot_fd.reset(dup(screenshot_fd_in.get()));
 
     extra_options = ModeToString(bugreport_mode);
     SetOptionsFromMode(bugreport_mode, this);
@@ -2227,11 +2234,11 @@
 }
 
 bool Dumpstate::DumpOptions::ValidateOptions() const {
-    if (fd != -1 && !do_zip_file) {
+    if (bugreport_fd.get() != -1 && !do_zip_file) {
         return false;
     }
 
-    bool has_out_file_options = !use_outfile.empty() || fd != -1;
+    bool has_out_file_options = !use_outfile.empty() || bugreport_fd.get() != -1;
     if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) &&
         !has_out_file_options) {
         return false;
@@ -2514,17 +2521,18 @@
 
     switch (status) {
         case Dumpstate::RunStatus::OK:
-            return 0;
-            // TODO(b/111441001): Exit directly in the following cases.
+            exit(0);
         case Dumpstate::RunStatus::HELP:
-            ShowUsageAndExit(0 /* exit code */);
-            break;
+            ShowUsage();
+            exit(0);
         case Dumpstate::RunStatus::INVALID_INPUT:
-            ExitOnInvalidArgs();
-            break;
+            fprintf(stderr, "Invalid combination of args\n");
+            ShowUsage();
+            exit(1);
         case Dumpstate::RunStatus::ERROR:
-            exit(-1);
-            break;
+            exit(2);
+        default:
+            fprintf(stderr, "Unknown status: %d\n", status);
+            exit(2);
     }
-    return 0;
 }
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 7ac25e4..529111e 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -342,9 +342,11 @@
         bool wifi_only = false;
         // Whether progress updates should be published.
         bool do_progress_updates = false;
-        // File descriptor to output zip file. -1 indicates not set. Takes precedence over
-        // use_outfile.
-        int fd = -1;
+        // File descriptor to output zip file. Takes precedence over use_outfile.
+        android::base::unique_fd bugreport_fd;
+        // File descriptor to screenshot file.
+        // TODO(b/111441001): Use this fd.
+        android::base::unique_fd screenshot_fd;
         // Partial path to output file.
         std::string use_outfile;
         // TODO: rename to MODE.
@@ -360,7 +362,8 @@
         RunStatus Initialize(int argc, char* argv[]);
 
         /* Initializes options from the requested mode. */
-        void Initialize(BugreportMode bugreport_mode);
+        void Initialize(BugreportMode bugreport_mode, const android::base::unique_fd& bugreport_fd,
+                        const android::base::unique_fd& screenshot_fd);
 
         /* Returns true if the options set so far are consistent. */
         bool ValidateOptions() const;
diff --git a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
index 61a5ef5..c57775f 100644
--- a/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_smoke_test.cpp
@@ -53,6 +53,19 @@
     DumpstateListener(int fd, std::shared_ptr<std::vector<SectionInfo>> sections)
         : outFd_(fd), max_progress_(5000), sections_(sections) {
     }
+    binder::Status onProgress(int32_t progress) override {
+        dprintf(outFd_, "\rIn progress %d", progress);
+        return binder::Status::ok();
+    }
+    binder::Status onError(int32_t error_code) override {
+        dprintf(outFd_, "\rError %d", error_code);
+        return binder::Status::ok();
+    }
+    binder::Status onFinished(int64_t duration_ms, const ::std::string&,
+                              const ::std::string&) override {
+        dprintf(outFd_, "\rFinished in %lld", (long long) duration_ms);
+        return binder::Status::ok();
+    }
     binder::Status onProgressUpdated(int32_t progress) override {
         dprintf(outFd_, "\rIn progress %d/%d", progress, max_progress_);
         return binder::Status::ok();
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index fcf9371..98ee1b0 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -59,6 +59,10 @@
 
 class DumpstateListenerMock : public IDumpstateListener {
   public:
+    MOCK_METHOD1(onProgress, binder::Status(int32_t progress));
+    MOCK_METHOD1(onError, binder::Status(int32_t error_code));
+    MOCK_METHOD3(onFinished, binder::Status(int64_t duration_ms, const ::std::string& title,
+                                            const ::std::string& description));
     MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress));
     MOCK_METHOD1(onMaxProgressUpdated, binder::Status(int32_t max_progress));
     MOCK_METHOD4(onSectionComplete, binder::Status(const ::std::string& name, int32_t status,
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index d97ffbf..990fd43 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -871,7 +871,11 @@
             is_java_process ? 5 : 20, fd);
 
         if (ret == -1) {
-            dprintf(fd, "dumping failed, likely due to a timeout\n");
+            // For consistency, the header and footer to this message match those
+            // dumped by debuggerd in the success case.
+            dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
+            dprintf(fd, "Dump failed, likely due to a timeout.\n");
+            dprintf(fd, "---- end %d ----", pid);
             timeout_failures++;
             continue;
         }
diff --git a/cmds/lshal/Command.h b/cmds/lshal/Command.h
index 4f128ab..e19e3f7 100644
--- a/cmds/lshal/Command.h
+++ b/cmds/lshal/Command.h
@@ -27,7 +27,7 @@
 // Base class for all *Commands
 class Command {
 public:
-    Command(Lshal& lshal) : mLshal(lshal) {}
+    explicit Command(Lshal& lshal) : mLshal(lshal) {}
     virtual ~Command() = default;
     // Expect optind to be set by Lshal::main and points to the next argument
     // to process.
diff --git a/cmds/lshal/DebugCommand.h b/cmds/lshal/DebugCommand.h
index 6e12008..3c3f56f 100644
--- a/cmds/lshal/DebugCommand.h
+++ b/cmds/lshal/DebugCommand.h
@@ -31,7 +31,7 @@
 
 class DebugCommand : public Command {
 public:
-    DebugCommand(Lshal &lshal) : Command(lshal) {}
+    explicit DebugCommand(Lshal &lshal) : Command(lshal) {}
     ~DebugCommand() = default;
     Status main(const Arg &arg) override;
     void usage() const override;
diff --git a/cmds/lshal/HelpCommand.h b/cmds/lshal/HelpCommand.h
index cc709f8..da0cba6 100644
--- a/cmds/lshal/HelpCommand.h
+++ b/cmds/lshal/HelpCommand.h
@@ -31,7 +31,7 @@
 
 class HelpCommand : public Command {
 public:
-    HelpCommand(Lshal &lshal) : Command(lshal) {}
+    explicit HelpCommand(Lshal &lshal) : Command(lshal) {}
     ~HelpCommand() = default;
     Status main(const Arg &arg) override;
     void usage() const override;
diff --git a/cmds/lshal/ListCommand.h b/cmds/lshal/ListCommand.h
index 3f7321d..85195fc 100644
--- a/cmds/lshal/ListCommand.h
+++ b/cmds/lshal/ListCommand.h
@@ -57,7 +57,7 @@
 
 class ListCommand : public Command {
 public:
-    ListCommand(Lshal &lshal) : Command(lshal) {}
+    explicit ListCommand(Lshal &lshal) : Command(lshal) {}
     virtual ~ListCommand() = default;
     Status main(const Arg &arg) override;
     void usage() const override;
diff --git a/cmds/lshal/NullableOStream.h b/cmds/lshal/NullableOStream.h
index ab37a04..737d3a2 100644
--- a/cmds/lshal/NullableOStream.h
+++ b/cmds/lshal/NullableOStream.h
@@ -25,8 +25,8 @@
 template<typename S>
 class NullableOStream {
 public:
-    NullableOStream(S &os) : mOs(&os) {}
-    NullableOStream(S *os) : mOs(os) {}
+    explicit NullableOStream(S &os) : mOs(&os) {}
+    explicit NullableOStream(S *os) : mOs(os) {}
     NullableOStream &operator=(S &os) {
         mOs = &os;
         return *this;
@@ -57,7 +57,7 @@
     S& buf() const {
         return *mOs;
     }
-    operator bool() const {
+    operator bool() const { // NOLINT(google-explicit-constructor)
         return mOs != nullptr;
     }
 private:
diff --git a/cmds/lshal/TableEntry.h b/cmds/lshal/TableEntry.h
index 7294b0a..601b7e2 100644
--- a/cmds/lshal/TableEntry.h
+++ b/cmds/lshal/TableEntry.h
@@ -149,7 +149,7 @@
 
 class MergedTable {
 public:
-    MergedTable(std::vector<const Table*>&& tables) : mTables(std::move(tables)) {}
+    explicit MergedTable(std::vector<const Table*>&& tables) : mTables(std::move(tables)) {}
     TextTable createTextTable();
 private:
     std::vector<const Table*> mTables;
diff --git a/cmds/lshal/TextTable.h b/cmds/lshal/TextTable.h
index 91d522a..301b4bd 100644
--- a/cmds/lshal/TextTable.h
+++ b/cmds/lshal/TextTable.h
@@ -33,11 +33,11 @@
     TextTableRow() {}
 
     // A row of cells.
-    TextTableRow(std::vector<std::string>&& v) : mFields(std::move(v)) {}
+    explicit TextTableRow(std::vector<std::string>&& v) : mFields(std::move(v)) {}
 
     // A single comment string.
-    TextTableRow(std::string&& s) : mLine(std::move(s)) {}
-    TextTableRow(const std::string& s) : mLine(s) {}
+    explicit TextTableRow(std::string&& s) : mLine(std::move(s)) {}
+    explicit TextTableRow(const std::string& s) : mLine(s) {}
 
     // Whether this row is an actual row of cells.
     bool isRow() const { return !fields().empty(); }
diff --git a/cmds/lshal/Timeout.h b/cmds/lshal/Timeout.h
index 58119a6..46d8177 100644
--- a/cmds/lshal/Timeout.h
+++ b/cmds/lshal/Timeout.h
@@ -29,7 +29,7 @@
 
 class BackgroundTaskState {
 public:
-    BackgroundTaskState(std::function<void(void)> &&func)
+    explicit BackgroundTaskState(std::function<void(void)> &&func)
             : mFunc(std::forward<decltype(func)>(func)) {}
     void notify() {
         std::unique_lock<std::mutex> lock(mMutex);
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index 8d7405b..fc8d58b 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -191,7 +191,7 @@
 // expose protected fields and methods for ListCommand
 class MockListCommand : public ListCommand {
 public:
-    MockListCommand(Lshal* lshal) : ListCommand(*lshal) {}
+    explicit MockListCommand(Lshal* lshal) : ListCommand(*lshal) {}
 
     Status parseArgs(const Arg& arg) { return ListCommand::parseArgs(arg); }
     Status main(const Arg& arg) { return ListCommand::main(arg); }
@@ -308,7 +308,7 @@
 // Fake service returned by mocked IServiceManager::get.
 class TestService : public IBase {
 public:
-    TestService(pid_t id) : mId(id) {}
+    explicit TestService(pid_t id) : mId(id) {}
     hardware::Return<void> getDebugInfo(getDebugInfo_cb cb) override {
         cb({ mId /* pid */, getPtr(mId), DebugInfo::Architecture::IS_64BIT });
         return hardware::Void();
diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c
index fade8cf..cf3b172 100644
--- a/cmds/servicemanager/binder.c
+++ b/cmds/servicemanager/binder.c
@@ -146,7 +146,19 @@
 
 int binder_become_context_manager(struct binder_state *bs)
 {
-    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
+    struct flat_binder_object obj;
+    memset(&obj, 0, sizeof(obj));
+    obj.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
+
+    int result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR_EXT, &obj);
+
+    // fallback to original method
+    if (result != 0) {
+        android_errorWriteLog(0x534e4554, "121035042");
+
+        result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
+    }
+    return result;
 }
 
 int binder_write(struct binder_state *bs, void *data, size_t len)
@@ -240,13 +252,28 @@
 #endif
             ptr += sizeof(struct binder_ptr_cookie);
             break;
+        case BR_TRANSACTION_SEC_CTX:
         case BR_TRANSACTION: {
-            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
-            if ((end - ptr) < sizeof(*txn)) {
-                ALOGE("parse: txn too small!\n");
-                return -1;
+            struct binder_transaction_data_secctx txn;
+            if (cmd == BR_TRANSACTION_SEC_CTX) {
+                if ((end - ptr) < sizeof(struct binder_transaction_data_secctx)) {
+                    ALOGE("parse: txn too small (binder_transaction_data_secctx)!\n");
+                    return -1;
+                }
+                memcpy(&txn, (void*) ptr, sizeof(struct binder_transaction_data_secctx));
+                ptr += sizeof(struct binder_transaction_data_secctx);
+            } else /* BR_TRANSACTION */ {
+                if ((end - ptr) < sizeof(struct binder_transaction_data)) {
+                    ALOGE("parse: txn too small (binder_transaction_data)!\n");
+                    return -1;
+                }
+                memcpy(&txn.transaction_data, (void*) ptr, sizeof(struct binder_transaction_data));
+                ptr += sizeof(struct binder_transaction_data);
+
+                txn.secctx = 0;
             }
-            binder_dump_txn(txn);
+
+            binder_dump_txn(&txn.transaction_data);
             if (func) {
                 unsigned rdata[256/4];
                 struct binder_io msg;
@@ -254,15 +281,14 @@
                 int res;
 
                 bio_init(&reply, rdata, sizeof(rdata), 4);
-                bio_init_from_txn(&msg, txn);
-                res = func(bs, txn, &msg, &reply);
-                if (txn->flags & TF_ONE_WAY) {
-                    binder_free_buffer(bs, txn->data.ptr.buffer);
+                bio_init_from_txn(&msg, &txn.transaction_data);
+                res = func(bs, &txn, &msg, &reply);
+                if (txn.transaction_data.flags & TF_ONE_WAY) {
+                    binder_free_buffer(bs, txn.transaction_data.data.ptr.buffer);
                 } else {
-                    binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
+                    binder_send_reply(bs, &reply, txn.transaction_data.data.ptr.buffer, res);
                 }
             }
-            ptr += sizeof(*txn);
             break;
         }
         case BR_REPLY: {
diff --git a/cmds/servicemanager/binder.h b/cmds/servicemanager/binder.h
index c95b33f..70be3b4 100644
--- a/cmds/servicemanager/binder.h
+++ b/cmds/servicemanager/binder.h
@@ -5,7 +5,8 @@
 #define _BINDER_H_
 
 #include <sys/ioctl.h>
-#include <linux/android/binder.h>
+
+#include "binder_kernel.h"
 
 struct binder_state;
 
@@ -42,7 +43,7 @@
 };
 
 typedef int (*binder_handler)(struct binder_state *bs,
-                              struct binder_transaction_data *txn,
+                              struct binder_transaction_data_secctx *txn,
                               struct binder_io *msg,
                               struct binder_io *reply);
 
diff --git a/cmds/servicemanager/binder_kernel.h b/cmds/servicemanager/binder_kernel.h
new file mode 100644
index 0000000..19fd773
--- /dev/null
+++ b/cmds/servicemanager/binder_kernel.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef ANDROID_BINDER_KERNEL_H
+#define ANDROID_BINDER_KERNEL_H
+
+#include <linux/android/binder.h>
+
+/**
+ * This file exists because the uapi kernel headers in bionic are built
+ * from upstream kernel headers only, and not all of the hwbinder kernel changes
+ * have made it upstream yet. Therefore, the modifications to the
+ * binder header are added locally in this file.
+ */
+
+enum {
+        FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000,
+};
+
+#define BINDER_SET_CONTEXT_MGR_EXT      _IOW('b', 13, struct flat_binder_object)
+
+struct binder_transaction_data_secctx {
+        struct binder_transaction_data transaction_data;
+        binder_uintptr_t secctx;
+};
+
+enum {
+        BR_TRANSACTION_SEC_CTX = _IOR('r', 2,
+                              struct binder_transaction_data_secctx),
+};
+
+
+#endif // ANDROID_BINDER_KERNEL_H
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 79cd6b5..ec3fac5 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -61,14 +61,14 @@
 static char *service_manager_context;
 static struct selabel_handle* sehandle;
 
-static bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char *perm, const char *name)
+static bool check_mac_perms(pid_t spid, const char* sid, uid_t uid, const char *tctx, const char *perm, const char *name)
 {
-    char *sctx = NULL;
+    char *lookup_sid = NULL;
     const char *class = "service_manager";
     bool allowed;
     struct audit_data ad;
 
-    if (getpidcon(spid, &sctx) < 0) {
+    if (sid == NULL && getpidcon(spid, &lookup_sid) < 0) {
         ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);
         return false;
     }
@@ -77,19 +77,23 @@
     ad.uid = uid;
     ad.name = name;
 
-    int result = selinux_check_access(sctx, tctx, class, perm, (void *) &ad);
+    if (sid == NULL) {
+        android_errorWriteLog(0x534e4554, "121035042");
+    }
+
+    int result = selinux_check_access(sid ? sid : lookup_sid, tctx, class, perm, (void *) &ad);
     allowed = (result == 0);
 
-    freecon(sctx);
+    freecon(lookup_sid);
     return allowed;
 }
 
-static bool check_mac_perms_from_getcon(pid_t spid, uid_t uid, const char *perm)
+static bool check_mac_perms_from_getcon(pid_t spid, const char* sid, uid_t uid, const char *perm)
 {
-    return check_mac_perms(spid, uid, service_manager_context, perm, NULL);
+    return check_mac_perms(spid, sid, uid, service_manager_context, perm, NULL);
 }
 
-static bool check_mac_perms_from_lookup(pid_t spid, uid_t uid, const char *perm, const char *name)
+static bool check_mac_perms_from_lookup(pid_t spid, const char* sid, uid_t uid, const char *perm, const char *name)
 {
     bool allowed;
     char *tctx = NULL;
@@ -104,12 +108,12 @@
         return false;
     }
 
-    allowed = check_mac_perms(spid, uid, tctx, perm, name);
+    allowed = check_mac_perms(spid, sid, uid, tctx, perm, name);
     freecon(tctx);
     return allowed;
 }
 
-static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
+static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
 {
     const char *perm = "add";
 
@@ -117,19 +121,19 @@
         return 0; /* Don't allow apps to register services */
     }
 
-    return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
+    return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
 }
 
-static int svc_can_list(pid_t spid, uid_t uid)
+static int svc_can_list(pid_t spid, const char* sid, uid_t uid)
 {
     const char *perm = "list";
-    return check_mac_perms_from_getcon(spid, uid, perm) ? 1 : 0;
+    return check_mac_perms_from_getcon(spid, sid, uid, perm) ? 1 : 0;
 }
 
-static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
+static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, const char* sid, uid_t uid)
 {
     const char *perm = "find";
-    return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
+    return check_mac_perms_from_lookup(spid, sid, uid, perm, str8(name, name_len)) ? 1 : 0;
 }
 
 struct svcinfo
@@ -175,7 +179,7 @@
 };
 
 
-uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid)
+uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid, const char* sid)
 {
     struct svcinfo *si = find_svc(s, len);
 
@@ -192,7 +196,7 @@
         }
     }
 
-    if (!svc_can_find(s, len, spid, uid)) {
+    if (!svc_can_find(s, len, spid, sid, uid)) {
         return 0;
     }
 
@@ -200,7 +204,7 @@
 }
 
 int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle,
-                   uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid) {
+                   uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid, const char* sid) {
     struct svcinfo *si;
 
     //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
@@ -209,7 +213,7 @@
     if (!handle || (len == 0) || (len > 127))
         return -1;
 
-    if (!svc_can_register(s, len, spid, uid)) {
+    if (!svc_can_register(s, len, spid, sid, uid)) {
         ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
              str8(s, len), handle, uid);
         return -1;
@@ -248,7 +252,7 @@
 }
 
 int svcmgr_handler(struct binder_state *bs,
-                   struct binder_transaction_data *txn,
+                   struct binder_transaction_data_secctx *txn_secctx,
                    struct binder_io *msg,
                    struct binder_io *reply)
 {
@@ -260,6 +264,8 @@
     int allow_isolated;
     uint32_t dumpsys_priority;
 
+    struct binder_transaction_data *txn = &txn_secctx->transaction_data;
+
     //ALOGI("target=%p code=%d pid=%d uid=%d\n",
     //      (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
 
@@ -305,7 +311,8 @@
         if (s == NULL) {
             return -1;
         }
-        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
+        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid,
+                                 (const char*) txn_secctx->secctx);
         if (!handle)
             break;
         bio_put_ref(reply, handle);
@@ -320,7 +327,7 @@
         allow_isolated = bio_get_uint32(msg) ? 1 : 0;
         dumpsys_priority = bio_get_uint32(msg);
         if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
-                           txn->sender_pid))
+                           txn->sender_pid, (const char*) txn_secctx->secctx))
             return -1;
         break;
 
@@ -328,7 +335,7 @@
         uint32_t n = bio_get_uint32(msg);
         uint32_t req_dumpsys_priority = bio_get_uint32(msg);
 
-        if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
+        if (!svc_can_list(txn->sender_pid, (const char*) txn_secctx->secctx, txn->sender_euid)) {
             ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
                     txn->sender_euid);
             return -1;
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index 384f21f..34886a9 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -286,10 +286,6 @@
             std::thread(&Replayer::createSurfaceControl, this, increment.surface_creation(), event)
                     .detach();
         } break;
-        case increment.kSurfaceDeletion: {
-            std::thread(&Replayer::deleteSurfaceControl, this, increment.surface_deletion(), event)
-                    .detach();
-        } break;
         case increment.kBufferUpdate: {
             std::lock_guard<std::mutex> lock1(mLayerLock);
             std::lock_guard<std::mutex> lock2(mBufferQueueSchedulerLock);
@@ -628,47 +624,10 @@
     return NO_ERROR;
 }
 
-status_t Replayer::deleteSurfaceControl(
-        const SurfaceDeletion& delete_, const std::shared_ptr<Event>& event) {
-    ALOGV("Deleting %d Surface Control", delete_.id());
-    event->readyToExecute();
-
-    std::lock_guard<std::mutex> lock1(mPendingLayersLock);
-
-    mLayersPendingRemoval.push_back(delete_.id());
-
-    const auto& iterator = mBufferQueueSchedulers.find(delete_.id());
-    if (iterator != mBufferQueueSchedulers.end()) {
-        (*iterator).second->stopScheduling();
-    }
-
-    std::lock_guard<std::mutex> lock2(mLayerLock);
-    if (mLayers[delete_.id()] != nullptr) {
-        mComposerClient->destroySurface(mLayers[delete_.id()]->getHandle());
-    }
-
-    return NO_ERROR;
-}
-
-void Replayer::doDeleteSurfaceControls() {
-    std::lock_guard<std::mutex> lock1(mPendingLayersLock);
-    std::lock_guard<std::mutex> lock2(mLayerLock);
-    if (!mLayersPendingRemoval.empty()) {
-        for (int id : mLayersPendingRemoval) {
-            mLayers.erase(id);
-            mColors.erase(id);
-            mBufferQueueSchedulers.erase(id);
-        }
-        mLayersPendingRemoval.clear();
-    }
-}
-
 status_t Replayer::injectVSyncEvent(
         const VSyncEvent& vSyncEvent, const std::shared_ptr<Event>& event) {
     ALOGV("Injecting VSync Event");
 
-    doDeleteSurfaceControls();
-
     event->readyToExecute();
 
     SurfaceComposerClient::injectVSync(vSyncEvent.when());
diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h
index 120dd9b..ad807ee 100644
--- a/cmds/surfacereplayer/replayer/Replayer.h
+++ b/cmds/surfacereplayer/replayer/Replayer.h
@@ -70,8 +70,6 @@
     status_t doTransaction(const Transaction& transaction, const std::shared_ptr<Event>& event);
     status_t createSurfaceControl(const SurfaceCreation& create,
             const std::shared_ptr<Event>& event);
-    status_t deleteSurfaceControl(const SurfaceDeletion& delete_,
-            const std::shared_ptr<Event>& event);
     status_t injectVSyncEvent(const VSyncEvent& vsyncEvent, const std::shared_ptr<Event>& event);
     void createDisplay(const DisplayCreation& create, const std::shared_ptr<Event>& event);
     void deleteDisplay(const DisplayDeletion& delete_, const std::shared_ptr<Event>& event);
@@ -120,7 +118,6 @@
     void setDisplayProjection(SurfaceComposerClient::Transaction& t,
             display_id id, const ProjectionChange& pc);
 
-    void doDeleteSurfaceControls();
     void waitUntilTimestamp(int64_t timestamp);
     void waitUntilDeferredTransactionLayerExists(
             const DeferredTransactionChange& dtc, std::unique_lock<std::mutex>& lock);
diff --git a/headers/media_plugin/media/drm/DrmAPI.h b/headers/media_plugin/media/drm/DrmAPI.h
index aa8bd3d..2ed1cca 100644
--- a/headers/media_plugin/media/drm/DrmAPI.h
+++ b/headers/media_plugin/media/drm/DrmAPI.h
@@ -84,6 +84,7 @@
             kDrmPluginEventSessionReclaimed,
             kDrmPluginEventExpirationUpdate,
             kDrmPluginEventKeysChange,
+            kDrmPluginEventSessionLostState,
         };
 
         // Drm keys can be for offline content or for online streaming.
diff --git a/include/OWNERS b/include/OWNERS
new file mode 100644
index 0000000..22be776
--- /dev/null
+++ b/include/OWNERS
@@ -0,0 +1,14 @@
+alexeykuzmin@google.com
+dangittik@google.com
+lajos@google.com
+mathias@google.com
+michaelwr@google.com
+racarr@google.com
+romainguy@android.com
+santoscordon@google.com
+stoza@google.com
+svv@google.com
+
+# For multinetwork.h only.
+lorenzo@google.com
+
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index fa7d908..05d96ff 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -112,26 +112,43 @@
 
 #if __ANDROID_API__ >= 29
 
+enum ResNsendFlags : uint32_t {
+    // Send a single request to a single resolver and fail on timeout or network errors
+    ANDROID_RESOLV_NO_RETRY = 1 << 0,
+
+    // Do not cache the result of the lookup. The lookup may return a result that is already
+    // in the cache, unless the ANDROID_RESOLV_NO_CACHE_LOOKUP flag is also specified.
+    ANDROID_RESOLV_NO_CACHE_STORE = 1 << 1,
+
+    // Don't lookup the request in cache, do not write back the response into the cache
+    ANDROID_RESOLV_NO_CACHE_LOOKUP = 1 << 2,
+};
+
 /**
  * Look up the {|ns_class|, |ns_type|} Resource Record (RR) associated
  * with Domain Name |dname| on the given |network|.
  * The typical value for |ns_class| is ns_c_in, while |type| can be any
  * record type (for instance, ns_t_aaaa or ns_t_txt).
+ * |flags| is a additional config to control actual querying behavior, see
+ * ResNsendFlags for detail.
  *
  * Returns a file descriptor to watch for read events, or a negative
  * POSIX error code (see errno.h) if an immediate error occurs.
  */
 int android_res_nquery(net_handle_t network,
-        const char *dname, int ns_class, int ns_type) __INTRODUCED_IN(29);
+        const char *dname, int ns_class, int ns_type,
+        enum ResNsendFlags flags) __INTRODUCED_IN(29);
 
 /**
  * Issue the query |msg| on the given |network|.
+ * |flags| is a additional config to control actual querying behavior, see
+ * ResNsendFlags for detail.
  *
  * Returns a file descriptor to watch for read events, or a negative
  * POSIX error code (see errno.h) if an immediate error occurs.
  */
 int android_res_nsend(net_handle_t network,
-        const uint8_t *msg, size_t msglen) __INTRODUCED_IN(29);
+        const uint8_t *msg, size_t msglen, enum ResNsendFlags flags) __INTRODUCED_IN(29);
 
 /**
  * Read a result for the query associated with the |fd| descriptor.
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
new file mode 100644
index 0000000..13b630b
--- /dev/null
+++ b/include/android/surface_control.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @addtogroup NativeActivity Native Activity
+ * @{
+ */
+
+/**
+ * @file surface_control.h
+ */
+
+#ifndef ANDROID_SURFACE_CONTROL_H
+#define ANDROID_SURFACE_CONTROL_H
+
+#include <sys/cdefs.h>
+
+#include <android/hardware_buffer.h>
+#include <android/native_window.h>
+
+__BEGIN_DECLS
+
+#if __ANDROID_API__ >= 29
+
+struct ASurfaceControl;
+
+/**
+ * The SurfaceControl API can be used to provide a heirarchy of surfaces for
+ * composition to the system compositor. ASurfaceControl represents a content node in
+ * this heirarchy.
+ */
+typedef struct ASurfaceControl ASurfaceControl;
+
+/*
+ * Creates an ASurfaceControl with either ANativeWindow or an ASurfaceControl as its parent.
+ * |debug_name| is a debug name associated with this surface. It can be used to
+ * identify this surface in the SurfaceFlinger's layer tree. It must not be
+ * null.
+ *
+ * The caller takes ownership of the ASurfaceControl returned and must release it
+ * using ASurfaceControl_release below.
+ */
+ASurfaceControl* ASurfaceControl_createFromWindow(ANativeWindow* parent, const char* debug_name)
+                                                  __INTRODUCED_IN(29);
+
+ASurfaceControl* ASurfaceControl_create(ASurfaceControl* parent, const char* debug_name)
+                                        __INTRODUCED_IN(29);
+
+/**
+ * Destroys the |surface_control| object. After releasing the ASurfaceControl the caller no longer
+ * has ownership of the AsurfaceControl.
+ */
+void ASurfaceControl_destroy(ASurfaceControl* surface_control) __INTRODUCED_IN(29);
+
+struct ASurfaceTransaction;
+
+/**
+ * ASurfaceTransaction is a collection of updates to the surface tree that must
+ * be applied atomically.
+ */
+typedef struct ASurfaceTransaction ASurfaceTransaction;
+
+/**
+ * The caller takes ownership of the transaction and must release it using
+ * ASurfaceControl_delete below.
+ */
+ASurfaceTransaction* ASurfaceTransaction_create() __INTRODUCED_IN(29);
+
+/**
+ * Destroys the |transaction| object.
+ */
+void ASurfaceTransaction_delete(ASurfaceTransaction* transaction) __INTRODUCED_IN(29);
+
+/**
+ * Applies the updates accumulated in |transaction|.
+ *
+ * Note that the transaction is guaranteed to be applied atomically. The
+ * transactions which are applied on the same thread are also guaranteed to be
+ * applied in order.
+ */
+void ASurfaceTransaction_apply(ASurfaceTransaction* transaction) __INTRODUCED_IN(29);
+
+/**
+ * Since the transactions are applied asynchronously, the
+ * ASurfaceTransaction_OnComplete callback can be used to be notified when a frame
+ * including the updates in a transaction was presented.
+ *
+ * |context| is the optional context provided by the client that is passed into
+ * the callback.
+ * |present_fence| is the sync fence that signals when the transaction has been presented.
+ * The recipient of the callback takes ownership of the present_fence and is responsible for closing
+ * it.
+ *
+ * It is safe to assume that once the present fence singals, that reads for all buffers,
+ * submitted in previous transactions, which are not in the surface tree after a transaction is
+ * applied, are finished and the buffers may be reused.
+ *
+ * THREADING
+ * The transaction completed callback can be invoked on any thread.
+ */
+typedef void (*ASurfaceTransaction_OnComplete)(void* context, int32_t present_fence);
+
+/**
+ * Sets the callback that will be invoked when the updates from this transaction
+ * are presented. For details on the callback semantics and data, see the
+ * comments on the ASurfaceTransaction_OnComplete declaration above.
+ */
+void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* transaction, void* context,
+                                       ASurfaceTransaction_OnComplete func) __INTRODUCED_IN(29);
+
+/* Parameter for ASurfaceTransaction_setVisibility */
+enum {
+    ASURFACE_TRANSACTION_VISIBILITY_HIDE = 0,
+    ASURFACE_TRANSACTION_VISIBILITY_SHOW = 1,
+};
+/**
+ * Updates the visibility of |surface_control|. If show is set to
+ * ASURFACE_TRANSACTION_VISIBILITY_HIDE, the |surface_control| and all surfaces in its subtree will
+ * be hidden.
+ */
+void ASurfaceTransaction_setVisibility(ASurfaceTransaction* transaction,
+                                       ASurfaceControl* surface_control, int8_t visibility)
+                                       __INTRODUCED_IN(29);
+
+/**
+ * Updates the z order index for |surface_control|. Note that the z order for a surface
+ * is relative to other surfaces which are siblings of this surface. The behavior of sibilings with
+ * the same z order is undefined.
+ *
+ * Z orders may be from MIN_INT32 to MAX_INT32. A layer's default z order index is 0.
+ */
+void ASurfaceTransaction_setZOrder(ASurfaceTransaction* transaction,
+                                   ASurfaceControl* surface_control, int32_t z_order)
+                                   __INTRODUCED_IN(29);
+
+/**
+ * Updates the AHardwareBuffer displayed for |surface_control|. If not -1, the
+ * fence_fd should be a file descriptor that is signaled when all pending work
+ * for the buffer is complete and the buffer can be safely read.
+ *
+ * The frameworks takes ownership of the |fence_fd| passed and is responsible
+ * for closing it.
+ */
+void ASurfaceTransaction_setBuffer(ASurfaceTransaction* transaction,
+                                   ASurfaceControl* surface_control, AHardwareBuffer* buffer,
+                                   int fence_fd = -1) __INTRODUCED_IN(29);
+
+/**
+ * |source| the sub-rect within the buffer's content to be rendered inside the surface's area
+ * The surface's source rect is clipped by the bounds of its current buffer. The source rect's width
+ * and height must be > 0.
+ *
+ * |destination| specifies the rect in the parent's space where this surface will be drawn. The post
+ * source rect bounds are scaled to fit the destination rect. The surface's destination rect is
+ * clipped by the bounds of its parent. The destination rect's width and height must be > 0.
+ *
+ * |transform| the transform applied after the source rect is applied to the buffer. This parameter
+ * should be set to 0 for no transform. To specify a transfrom use the NATIVE_WINDOW_TRANSFORM_*
+ * enum.
+ */
+void ASurfaceTransaction_setGeometry(ASurfaceTransaction* transaction,
+                                     ASurfaceControl* surface_control, const ARect& source,
+                                     const ARect& destination, int32_t transform)
+                                     __INTRODUCED_IN(29);
+
+
+/* Parameter for ASurfaceTransaction_setBufferTransparency */
+enum {
+    ASURFACE_TRANSACTION_TRANSPARENCY_TRANSPARENT = 0,
+    ASURFACE_TRANSACTION_TRANSPARENCY_TRANSLUCENT = 1,
+    ASURFACE_TRANSACTION_TRANSPARENCY_OPAQUE = 2,
+};
+/**
+ * Updates whether the content for the buffer associated with this surface is
+ * completely opaque. If true, every pixel of content inside the buffer must be
+ * opaque or visual errors can occur.
+ */
+void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* transaction,
+                                         ASurfaceControl* surface_control, int8_t transparency)
+                                         __INTRODUCED_IN(29);
+
+/**
+ * Updates the region for the content on this surface updated in this
+ * transaction. If unspecified, the complete surface is assumed to be damaged.
+ */
+void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* transaction,
+                                         ASurfaceControl* surface_control, const ARect rects[],
+                                         uint32_t count) __INTRODUCED_IN(29);
+
+#endif // __ANDROID_API__ >= 29
+
+__END_DECLS
+
+#endif // ANDROID_SURFACE_CONTROL_H
diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h
index 610834d..ff443c6 100644
--- a/include/input/IInputFlinger.h
+++ b/include/input/IInputFlinger.h
@@ -36,7 +36,7 @@
     DECLARE_META_INTERFACE(InputFlinger)
 
     virtual void setInputWindows(const Vector<InputWindowInfo>& inputHandles) = 0;
-
+    virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0;
     virtual void registerInputChannel(const sp<InputChannel>& channel) = 0;
     virtual void unregisterInputChannel(const sp<InputChannel>& channel) = 0;
 };
@@ -50,7 +50,8 @@
     enum {
         SET_INPUT_WINDOWS_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
         REGISTER_INPUT_CHANNEL_TRANSACTION,
-        UNREGISTER_INPUT_CHANNEL_TRANSACTION
+        UNREGISTER_INPUT_CHANNEL_TRANSACTION,
+        TRANSFER_TOUCH_FOCUS
     };
 
     virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/include/input/Input.h b/include/input/Input.h
index 037270c..2c4a511 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -220,6 +220,27 @@
     POLICY_FLAG_PASS_TO_USER = 0x40000000,
 };
 
+/**
+ * Classifications of the current gesture, if available.
+ *
+ * The following values must be kept in sync with MotionEvent.java
+ */
+enum class MotionClassification : uint8_t {
+    /**
+     * No classification is available.
+     */
+    NONE = 0,
+    /**
+     * Too early to classify the current gesture. Need more events. Look for changes in the
+     * upcoming motion events.
+     */
+    AMBIGUOUS_GESTURE = 1,
+    /**
+     * The current gesture likely represents a user intentionally exerting force on the touchscreen.
+     */
+    DEEP_PRESS = 2,
+};
+
 /*
  * Pointer coordinate data.
  */
@@ -419,6 +440,8 @@
 
     inline void setButtonState(int32_t buttonState) { mButtonState = buttonState; }
 
+    inline MotionClassification getClassification() const { return mClassification; }
+
     inline int32_t getActionButton() const { return mActionButton; }
 
     inline void setActionButton(int32_t button) { mActionButton = button; }
@@ -582,6 +605,7 @@
             int32_t edgeFlags,
             int32_t metaState,
             int32_t buttonState,
+            MotionClassification classification,
             float xOffset,
             float yOffset,
             float xPrecision,
@@ -635,6 +659,7 @@
     int32_t mEdgeFlags;
     int32_t mMetaState;
     int32_t mButtonState;
+    MotionClassification mClassification;
     float mXOffset;
     float mYOffset;
     float mXPrecision;
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 8df83f1..1d4e234 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -23,7 +23,9 @@
 #include <binder/BpBinder.h>
 #include <binder/TextOutput.h>
 
+#include <android-base/macros.h>
 #include <cutils/sched_policy.h>
+#include <utils/CallStack.h>
 #include <utils/Log.h>
 #include <utils/SystemClock.h>
 #include <utils/threads.h>
@@ -661,6 +663,16 @@
     }
 
     if ((flags & TF_ONE_WAY) == 0) {
+        if (UNLIKELY(mCallRestriction != ProcessState::CallRestriction::NONE)) {
+            if (mCallRestriction == ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY) {
+                ALOGE("Process making non-oneway call but is restricted.");
+                CallStack::logStack("non-oneway call", CallStack::getCurrent(10).get(),
+                    ANDROID_LOG_ERROR);
+            } else /* FATAL_IF_NOT_ONEWAY */ {
+                LOG_ALWAYS_FATAL("Process may not make oneway calls.");
+            }
+        }
+
         #if 0
         if (code == 4) { // relayout
             ALOGI(">>>>>> CALLING transaction 4");
@@ -783,7 +795,8 @@
       mWorkSource(kUnsetWorkSource),
       mPropagateWorkSource(false),
       mStrictModePolicy(0),
-      mLastTransactionBinderFlags(0)
+      mLastTransactionBinderFlags(0),
+      mCallRestriction(mProcess->mCallRestriction)
 {
     pthread_setspecific(gTLS, this);
     clearCaller();
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 53f8ddd..3798b61 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -234,6 +234,12 @@
     return count;
 }
 
+void ProcessState::setCallRestriction(CallRestriction restriction) {
+    LOG_ALWAYS_FATAL_IF(IPCThreadState::selfOrNull(), "Call restrictions must be set before the threadpool is started.");
+
+    mCallRestriction = restriction;
+}
+
 ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
 {
     const size_t N=mHandleToObject.size();
@@ -426,6 +432,7 @@
     , mBinderContextUserData(nullptr)
     , mThreadPoolStarted(false)
     , mThreadPoolSeq(1)
+    , mCallRestriction(CallRestriction::NONE)
 {
     if (mDriverFD >= 0) {
         // mmap the binder, providing a chunk of virtual address space to receive transactions.
diff --git a/libs/binder/Value.cpp b/libs/binder/Value.cpp
index a28a618..19c57ba 100644
--- a/libs/binder/Value.cpp
+++ b/libs/binder/Value.cpp
@@ -97,7 +97,7 @@
 template<typename T> class Value::Content : public Value::ContentBase {
 public:
     Content() = default;
-    Content(const T & value) : mValue(value) { }
+    explicit Content(const T & value) : mValue(value) { }
 
     virtual ~Content() = default;
 
diff --git a/libs/binder/include/binder/BufferedTextOutput.h b/libs/binder/include/binder/BufferedTextOutput.h
index 9a7c43b..feae93d 100644
--- a/libs/binder/include/binder/BufferedTextOutput.h
+++ b/libs/binder/include/binder/BufferedTextOutput.h
@@ -32,7 +32,7 @@
         MULTITHREADED = 0x0001
     };
     
-                        BufferedTextOutput(uint32_t flags = 0);
+    explicit            BufferedTextOutput(uint32_t flags = 0);
     virtual             ~BufferedTextOutput();
     
     virtual status_t    print(const char* txt, size_t len);
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index 5ec02b1..f6381f7 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -124,7 +124,9 @@
 
 
 #define CHECK_INTERFACE(interface, data, reply)                         \
-    if (!(data).checkInterface(this)) { return PERMISSION_DENIED; }     \
+    do {                                                                \
+      if (!(data).checkInterface(this)) { return PERMISSION_DENIED; }   \
+    } while (false)                                                     \
 
 
 // ----------------------------------------------------------------------
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 26e8c0b..a6b0f7e 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -183,6 +183,8 @@
             int32_t             mStrictModePolicy;
             int32_t             mLastTransactionBinderFlags;
             IPCThreadStateBase  *mIPCThreadStateBase;
+
+            ProcessState::CallRestriction mCallRestriction;
 };
 
 }; // namespace android
diff --git a/libs/binder/include/binder/IpPrefix.h b/libs/binder/include/binder/IpPrefix.h
index dd5bc3a..c7e7a50 100644
--- a/libs/binder/include/binder/IpPrefix.h
+++ b/libs/binder/include/binder/IpPrefix.h
@@ -74,8 +74,8 @@
 private:
     union InternalUnion {
         InternalUnion() = default;
-        InternalUnion(const struct in6_addr &addr):mIn6Addr(addr) { };
-        InternalUnion(const struct in_addr &addr):mInAddr(addr) { };
+        explicit InternalUnion(const struct in6_addr &addr):mIn6Addr(addr) { };
+        explicit InternalUnion(const struct in_addr &addr):mInAddr(addr) { };
         struct in6_addr mIn6Addr;
         struct in_addr mInAddr;
     } mUnion;
diff --git a/libs/binder/include/binder/MemoryDealer.h b/libs/binder/include/binder/MemoryDealer.h
index fe5a31d..b483be0 100644
--- a/libs/binder/include/binder/MemoryDealer.h
+++ b/libs/binder/include/binder/MemoryDealer.h
@@ -34,7 +34,7 @@
 class MemoryDealer : public RefBase
 {
 public:
-    MemoryDealer(size_t size, const char* name = nullptr,
+    explicit MemoryDealer(size_t size, const char* name = nullptr,
             uint32_t flags = 0 /* or bits such as MemoryHeapBase::READ_ONLY */ );
 
     virtual sp<IMemory> allocate(size_t size);
diff --git a/libs/binder/include/binder/MemoryHeapBase.h b/libs/binder/include/binder/MemoryHeapBase.h
index 2f5039d..100d784 100644
--- a/libs/binder/include/binder/MemoryHeapBase.h
+++ b/libs/binder/include/binder/MemoryHeapBase.h
@@ -47,12 +47,12 @@
     /*
      * maps memory from the given device
      */
-    MemoryHeapBase(const char* device, size_t size = 0, uint32_t flags = 0);
+    explicit MemoryHeapBase(const char* device, size_t size = 0, uint32_t flags = 0);
 
     /*
      * maps memory from ashmem, with the given name for debugging
      */
-    MemoryHeapBase(size_t size, uint32_t flags = 0, char const* name = nullptr);
+    explicit MemoryHeapBase(size_t size, uint32_t flags = 0, char const* name = nullptr);
 
     virtual ~MemoryHeapBase();
 
diff --git a/libs/binder/include/binder/ParcelFileDescriptor.h b/libs/binder/include/binder/ParcelFileDescriptor.h
index ad950af..662e56e 100644
--- a/libs/binder/include/binder/ParcelFileDescriptor.h
+++ b/libs/binder/include/binder/ParcelFileDescriptor.h
@@ -31,7 +31,7 @@
 public:
     ParcelFileDescriptor();
     explicit ParcelFileDescriptor(android::base::unique_fd fd);
-    explicit ParcelFileDescriptor(ParcelFileDescriptor&& other) : mFd(std::move(other.mFd)) { }
+    ParcelFileDescriptor(ParcelFileDescriptor&& other) : mFd(std::move(other.mFd)) { }
     ~ParcelFileDescriptor() override;
 
     int get() const { return mFd.get(); }
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 13f67ba..224cb36 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -77,10 +77,22 @@
 
             ssize_t             getKernelReferences(size_t count, uintptr_t* buf);
 
+            enum class CallRestriction {
+                // all calls okay
+                NONE,
+                // log when calls are blocking
+                ERROR_IF_NOT_ONEWAY,
+                // abort process on blocking calls
+                FATAL_IF_NOT_ONEWAY,
+            };
+            // Sets calling restrictions for all transactions in this process. This must be called
+            // before any threads are spawned.
+            void setCallRestriction(CallRestriction restriction);
+
 private:
     friend class IPCThreadState;
     
-                                ProcessState(const char* driver);
+            explicit            ProcessState(const char* driver);
                                 ~ProcessState();
 
                                 ProcessState(const ProcessState& o);
@@ -123,6 +135,8 @@
             String8             mRootDir;
             bool                mThreadPoolStarted;
     volatile int32_t            mThreadPoolSeq;
+
+            CallRestriction     mCallRestriction;
 };
     
 }; // namespace android
diff --git a/libs/binder/include/binder/TextOutput.h b/libs/binder/include/binder/TextOutput.h
index 851e01f..5b5f766 100644
--- a/libs/binder/include/binder/TextOutput.h
+++ b/libs/binder/include/binder/TextOutput.h
@@ -38,7 +38,7 @@
     
     class Bundle {
     public:
-        inline Bundle(TextOutput& to) : mTO(to) { to.pushBundle(); }
+        inline explicit Bundle(TextOutput& to) : mTO(to) { to.pushBundle(); }
         inline ~Bundle() { mTO.popBundle(); }
     private:
         TextOutput&     mTO;
@@ -80,7 +80,7 @@
 class TypeCode
 {
 public:
-    inline TypeCode(uint32_t code);
+    inline explicit TypeCode(uint32_t code);
     inline ~TypeCode();
 
     inline uint32_t typeCode() const;
diff --git a/libs/binder/include/binder/Value.h b/libs/binder/include/binder/Value.h
index 4dee3d8..735f40e 100644
--- a/libs/binder/include/binder/Value.h
+++ b/libs/binder/include/binder/Value.h
@@ -74,20 +74,20 @@
     bool operator!=(const Value& rhs) const { return !this->operator==(rhs); }
 
     Value(const Value& value);
-    Value(const bool& value);
-    Value(const int8_t& value);
-    Value(const int32_t& value);
-    Value(const int64_t& value);
-    Value(const double& value);
-    Value(const String16& value);
-    Value(const std::vector<bool>& value);
-    Value(const std::vector<uint8_t>& value);
-    Value(const std::vector<int32_t>& value);
-    Value(const std::vector<int64_t>& value);
-    Value(const std::vector<double>& value);
-    Value(const std::vector<String16>& value);
-    Value(const os::PersistableBundle& value);
-    Value(const binder::Map& value);
+    Value(const bool& value); // NOLINT(google-explicit-constructor)
+    Value(const int8_t& value); // NOLINT(google-explicit-constructor)
+    Value(const int32_t& value); // NOLINT(google-explicit-constructor)
+    Value(const int64_t& value); // NOLINT(google-explicit-constructor)
+    Value(const double& value); // NOLINT(google-explicit-constructor)
+    Value(const String16& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<bool>& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<uint8_t>& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<int32_t>& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<int64_t>& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<double>& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<String16>& value); // NOLINT(google-explicit-constructor)
+    Value(const os::PersistableBundle& value); // NOLINT(google-explicit-constructor)
+    Value(const binder::Map& value); // NOLINT(google-explicit-constructor)
 
     Value& operator=(const Value& rhs);
     Value& operator=(const int8_t& rhs);
@@ -153,8 +153,8 @@
     // String Convenience Adapters
     // ---------------------------
 
-    Value(const String8& value):               Value(String16(value)) { }
-    Value(const ::std::string& value):         Value(String8(value.c_str())) { }
+    explicit Value(const String8& value):               Value(String16(value)) { }
+    explicit Value(const ::std::string& value):         Value(String8(value.c_str())) { }
     void putString(const String8& value)       { return putString(String16(value)); }
     void putString(const ::std::string& value) { return putString(String8(value.c_str())); }
     Value& operator=(const String8& rhs)       { return *this = String16(rhs); }
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 1b69dfd..05655c1 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -23,7 +23,11 @@
         "include_apex",
     ],
 
-    cflags: ["-Wall", "-Wextra", "-Werror"],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
 
     srcs: [
         "ibinder.cpp",
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index ac592ea..7852298 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -34,7 +34,7 @@
 struct ABpBinder;
 
 struct AIBinder : public virtual ::android::RefBase {
-    AIBinder(const AIBinder_Class* clazz);
+    explicit AIBinder(const AIBinder_Class* clazz);
     virtual ~AIBinder();
 
     bool associateClass(const AIBinder_Class* clazz);
@@ -97,7 +97,7 @@
     ABpBinder* asABpBinder() override { return this; }
 
    private:
-    ABpBinder(const ::android::sp<::android::IBinder>& binder);
+    explicit ABpBinder(const ::android::sp<::android::IBinder>& binder);
 };
 
 struct AIBinder_Class {
@@ -141,7 +141,7 @@
         const AIBinder_DeathRecipient_onBinderDied& mOnDied;
     };
 
-    AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied);
+    explicit AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied);
     binder_status_t linkToDeath(AIBinder* binder, void* cookie);
     binder_status_t unlinkToDeath(AIBinder* binder, void* cookie);
 
diff --git a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
index ff1860e..80773f3 100644
--- a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -51,7 +51,7 @@
      * Convenience operator for implicitly constructing an SpAIBinder from nullptr. This is not
      * explicit because it is not taking ownership of anything.
      */
-    SpAIBinder(std::nullptr_t) : SpAIBinder() {}
+    SpAIBinder(std::nullptr_t) : SpAIBinder() {}  // NOLINT(google-explicit-constructor)
 
     /**
      * This will delete the underlying object if it exists. See operator=.
diff --git a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
index 1532725..a42c60b 100644
--- a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
@@ -137,7 +137,7 @@
 template <typename INTERFACE>
 class BpCInterface : public INTERFACE {
    public:
-    BpCInterface(const SpAIBinder& binder) : mBinder(binder) {}
+    explicit BpCInterface(const SpAIBinder& binder) : mBinder(binder) {}
     virtual ~BpCInterface() {}
 
     SpAIBinder asBinder() override;
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index ee7132f..f0d25f7 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -87,6 +87,11 @@
     AStatus_getStatus;
     AStatus_isOk;
     AStatus_newOk;
+    ABinderProcess_joinThreadPool; # apex
+    ABinderProcess_setThreadPoolMaxThreadCount; # apex
+    ABinderProcess_startThreadPool; # apex
+    AServiceManager_addService; # apex
+    AServiceManager_getService; # apex
   local:
     *;
 };
diff --git a/libs/binder/ndk/parcel_internal.h b/libs/binder/ndk/parcel_internal.h
index f292309..6b7295e 100644
--- a/libs/binder/ndk/parcel_internal.h
+++ b/libs/binder/ndk/parcel_internal.h
@@ -27,7 +27,8 @@
     const ::android::Parcel* get() const { return mParcel; }
     ::android::Parcel* get() { return mParcel; }
 
-    AParcel(const AIBinder* binder) : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
+    explicit AParcel(const AIBinder* binder)
+        : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
     AParcel(const AIBinder* binder, ::android::Parcel* parcel, bool owns)
         : mBinder(binder), mParcel(parcel), mOwns(owns) {}
 
diff --git a/libs/binder/ndk/scripts/init_map.sh b/libs/binder/ndk/scripts/init_map.sh
index 1f74e43..3529b72 100755
--- a/libs/binder/ndk/scripts/init_map.sh
+++ b/libs/binder/ndk/scripts/init_map.sh
@@ -10,6 +10,10 @@
     grep -oP "AParcel_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_parcel.h;
     grep -oP "AStatus_[a-zA-Z0-9_]+(?=\()" include_ndk/android/binder_status.h;
 } | sort | uniq | awk '{ print "    " $0 ";"; }'
+{
+    grep -oP "AServiceManager_[a-zA-Z0-9_]+(?=\()" include_apex/android/binder_manager.h;
+    grep -oP "ABinderProcess_[a-zA-Z0-9_]+(?=\()" include_apex/android/binder_process.h;
+} | sort | uniq | awk '{ print "    " $0 "; # apex"; }'
 echo "  local:"
 echo "    *;"
 echo "};"
diff --git a/libs/binder/ndk/status_internal.h b/libs/binder/ndk/status_internal.h
index d39f0d8..f6227f7 100644
--- a/libs/binder/ndk/status_internal.h
+++ b/libs/binder/ndk/status_internal.h
@@ -23,7 +23,7 @@
 
 struct AStatus {
     AStatus() {}  // ok
-    AStatus(::android::binder::Status&& status) : mStatus(std::move(status)) {}
+    explicit AStatus(::android::binder::Status&& status) : mStatus(std::move(status)) {}
 
     ::android::binder::Status* get() { return &mStatus; }
     const ::android::binder::Status* get() const { return &mStatus; }
diff --git a/libs/binder/ndk/test/iface.cpp b/libs/binder/ndk/test/iface.cpp
index 6ef964e..64832f3 100644
--- a/libs/binder/ndk/test/iface.cpp
+++ b/libs/binder/ndk/test/iface.cpp
@@ -74,7 +74,7 @@
 
 class BpFoo : public IFoo {
    public:
-    BpFoo(AIBinder* binder) : mBinder(binder) {}
+    explicit BpFoo(AIBinder* binder) : mBinder(binder) {}
     virtual ~BpFoo() { AIBinder_decStrong(mBinder); }
 
     virtual binder_status_t doubleNumber(int32_t in, int32_t* out) {
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index ae04b0f..78f1159 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -233,7 +233,7 @@
 {
     public:
         BinderLibTestBundle(void) {}
-        BinderLibTestBundle(const Parcel *source) : m_isValid(false) {
+        explicit BinderLibTestBundle(const Parcel *source) : m_isValid(false) {
             int32_t mark;
             int32_t bundleLen;
             size_t pos;
@@ -1079,7 +1079,7 @@
 class BinderLibTestService : public BBinder
 {
     public:
-        BinderLibTestService(int32_t id)
+        explicit BinderLibTestService(int32_t id)
             : m_id(id)
             , m_nextServerId(id + 1)
             , m_serverStartRequested(false)
diff --git a/libs/binder/tests/schd-dbg.cpp b/libs/binder/tests/schd-dbg.cpp
index 6cf7f36..ec9534a 100644
--- a/libs/binder/tests/schd-dbg.cpp
+++ b/libs/binder/tests/schd-dbg.cpp
@@ -218,7 +218,7 @@
   uint64_t m_total_time = 0;
   uint64_t m_miss = 0;
   bool tracing;
-  Results(bool _tracing) : tracing(_tracing) {
+  explicit Results(bool _tracing) : tracing(_tracing) {
   }
   inline bool miss_deadline(uint64_t nano) {
     return nano > deadline_us * 1000;
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index d1c732b..3521e89 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -121,6 +121,7 @@
     ],
 
     shared_libs: [
+        "android.frameworks.bufferhub@1.0",
         "android.hardware.graphics.common@1.1",
         "libbase",
         "libsync",
@@ -153,6 +154,7 @@
                 "BufferHubProducer.cpp",
             ],
             exclude_shared_libs: [
+                "android.frameworks.bufferhub@1.0",
                 "libbufferhub",
                 "libbufferhubqueue",
                 "libpdx_default_transport",
diff --git a/libs/gui/BufferHubProducer.cpp b/libs/gui/BufferHubProducer.cpp
index 16952a6..4be014f 100644
--- a/libs/gui/BufferHubProducer.cpp
+++ b/libs/gui/BufferHubProducer.cpp
@@ -64,13 +64,13 @@
     } else if (buffers_[slot].mGraphicBuffer != nullptr) {
         ALOGE("requestBuffer: slot %d is not empty.", slot);
         return BAD_VALUE;
-    } else if (buffers_[slot].mBufferProducer == nullptr) {
+    } else if (buffers_[slot].mProducerBuffer == nullptr) {
         ALOGE("requestBuffer: slot %d is not dequeued.", slot);
         return BAD_VALUE;
     }
 
-    const auto& buffer_producer = buffers_[slot].mBufferProducer;
-    sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
+    const auto& producer_buffer = buffers_[slot].mProducerBuffer;
+    sp<GraphicBuffer> graphic_buffer = producer_buffer->buffer()->buffer();
 
     buffers_[slot].mGraphicBuffer = graphic_buffer;
     buffers_[slot].mRequestBufferCalled = true;
@@ -158,19 +158,19 @@
     }
 
     size_t slot = 0;
-    std::shared_ptr<BufferProducer> buffer_producer;
+    std::shared_ptr<ProducerBuffer> producer_buffer;
 
     for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
         LocalHandle fence;
         auto buffer_status = queue_->Dequeue(dequeue_timeout_ms_, &slot, &fence);
         if (!buffer_status) return NO_MEMORY;
 
-        buffer_producer = buffer_status.take();
-        if (!buffer_producer) return NO_MEMORY;
+        producer_buffer = buffer_status.take();
+        if (!producer_buffer) return NO_MEMORY;
 
-        if (width == buffer_producer->width() && height == buffer_producer->height() &&
-            uint32_t(format) == buffer_producer->format()) {
-            // The producer queue returns a buffer producer matches the request.
+        if (width == producer_buffer->width() && height == producer_buffer->height() &&
+            uint32_t(format) == producer_buffer->format()) {
+            // The producer queue returns a producer buffer matches the request.
             break;
         }
 
@@ -179,8 +179,8 @@
         ALOGI("dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different "
               "from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need "
               "re-allocattion.",
-              width, height, format, slot, buffer_producer->width(), buffer_producer->height(),
-              buffer_producer->format());
+              width, height, format, slot, producer_buffer->width(), producer_buffer->height(),
+              producer_buffer->format());
         // Mark the slot as reallocating, so that later we can set
         // BUFFER_NEEDS_REALLOCATION when the buffer actually get dequeued.
         buffers_[slot].mIsReallocating = true;
@@ -249,18 +249,18 @@
         ALOGE("detachBuffer: buffer in slot %zu has not been requested", slot);
         return BAD_VALUE;
     }
-    std::shared_ptr<BufferProducer> buffer_producer = queue_->GetBuffer(slot);
-    if (buffer_producer == nullptr || buffer_producer->buffer() == nullptr) {
-        ALOGE("detachBuffer: Invalid BufferProducer at slot %zu.", slot);
+    std::shared_ptr<ProducerBuffer> producer_buffer = queue_->GetBuffer(slot);
+    if (producer_buffer == nullptr || producer_buffer->buffer() == nullptr) {
+        ALOGE("detachBuffer: Invalid ProducerBuffer at slot %zu.", slot);
         return BAD_VALUE;
     }
-    sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
+    sp<GraphicBuffer> graphic_buffer = producer_buffer->buffer()->buffer();
     if (graphic_buffer == nullptr) {
         ALOGE("detachBuffer: Invalid GraphicBuffer at slot %zu.", slot);
         return BAD_VALUE;
     }
 
-    // Remove the BufferProducer from the ProducerQueue.
+    // Remove the ProducerBuffer from the ProducerQueue.
     status_t error = RemoveBuffer(slot);
     if (error != NO_ERROR) {
         ALOGE("detachBuffer: Failed to remove buffer, slot=%zu, error=%d.", slot, error);
@@ -269,9 +269,9 @@
 
     // Here we need to convert the existing ProducerBuffer into a DetachedBufferHandle and inject
     // the handle into the GraphicBuffer object at the requested slot.
-    auto status_or_handle = buffer_producer->Detach();
+    auto status_or_handle = producer_buffer->Detach();
     if (!status_or_handle.ok()) {
-        ALOGE("detachBuffer: Failed to detach from a BufferProducer at slot %zu, error=%d.", slot,
+        ALOGE("detachBuffer: Failed to detach from a ProducerBuffer at slot %zu, error=%d.", slot,
               status_or_handle.error());
         return BAD_VALUE;
     }
@@ -301,14 +301,14 @@
     // sequence, except for two things:
     //
     // 1) It is unnecessary to know the dimensions, format, or usage of the next buffer, i.e. the
-    // function just returns whatever BufferProducer is available from the ProducerQueue and no
+    // function just returns whatever ProducerBuffer is available from the ProducerQueue and no
     // buffer allocation or re-allocation will happen.
     // 2) It will not block, since if it cannot find an appropriate buffer to return, it will return
     // an error instead.
     size_t slot = 0;
     LocalHandle fence;
 
-    // First, dequeue a BufferProducer from the ProducerQueue with no timeout. Report error
+    // First, dequeue a ProducerBuffer from the ProducerQueue with no timeout. Report error
     // immediately if ProducerQueue::Dequeue() fails.
     auto status_or_buffer = queue_->Dequeue(/*timeout=*/0, &slot, &fence);
     if (!status_or_buffer.ok()) {
@@ -316,8 +316,8 @@
         return NO_MEMORY;
     }
 
-    std::shared_ptr<BufferProducer> buffer_producer = status_or_buffer.take();
-    if (buffer_producer == nullptr) {
+    std::shared_ptr<ProducerBuffer> producer_buffer = status_or_buffer.take();
+    if (producer_buffer == nullptr) {
         ALOGE("detachNextBuffer: Dequeued buffer is null.");
         return NO_MEMORY;
     }
@@ -331,14 +331,14 @@
               buffers_[slot].mBufferState.string());
         return BAD_VALUE;
     }
-    if (buffers_[slot].mBufferProducer == nullptr) {
-        ALOGE("detachNextBuffer: BufferProducer at slot %zu is null.", slot);
+    if (buffers_[slot].mProducerBuffer == nullptr) {
+        ALOGE("detachNextBuffer: ProducerBuffer at slot %zu is null.", slot);
         return BAD_VALUE;
     }
-    if (buffers_[slot].mBufferProducer->id() != buffer_producer->id()) {
-        ALOGE("detachNextBuffer: BufferProducer at slot %zu has mismatched id, actual: "
+    if (buffers_[slot].mProducerBuffer->id() != producer_buffer->id()) {
+        ALOGE("detachNextBuffer: ProducerBuffer at slot %zu has mismatched id, actual: "
               "%d, expected: %d.",
-              slot, buffers_[slot].mBufferProducer->id(), buffer_producer->id());
+              slot, buffers_[slot].mProducerBuffer->id(), producer_buffer->id());
         return BAD_VALUE;
     }
 
@@ -347,8 +347,8 @@
     buffers_[slot].mBufferState.dequeue();
 
     // Second, request the buffer.
-    sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
-    buffers_[slot].mGraphicBuffer = buffer_producer->buffer()->buffer();
+    sp<GraphicBuffer> graphic_buffer = producer_buffer->buffer()->buffer();
+    buffers_[slot].mGraphicBuffer = producer_buffer->buffer()->buffer();
 
     // Finally, detach the buffer and then return.
     status_t error = DetachBufferLocked(slot);
@@ -452,11 +452,11 @@
         return BAD_VALUE;
     }
 
-    // Post the buffer producer with timestamp in the metadata.
-    const auto& buffer_producer = buffers_[slot].mBufferProducer;
+    // Post the producer buffer with timestamp in the metadata.
+    const auto& producer_buffer = buffers_[slot].mProducerBuffer;
 
     // Check input crop is not out of boundary of current buffer.
-    Rect buffer_rect(buffer_producer->width(), buffer_producer->height());
+    Rect buffer_rect(producer_buffer->width(), producer_buffer->height());
     Rect cropped_rect(Rect::EMPTY_RECT);
     crop.intersect(buffer_rect, &cropped_rect);
     if (cropped_rect != crop) {
@@ -477,11 +477,11 @@
     meta_data.scaling_mode = int32_t(scaling_mode);
     meta_data.transform = int32_t(transform);
 
-    buffer_producer->PostAsync(&meta_data, fence_fd);
+    producer_buffer->PostAsync(&meta_data, fence_fd);
     buffers_[slot].mBufferState.queue();
 
-    output->width = buffer_producer->width();
-    output->height = buffer_producer->height();
+    output->width = producer_buffer->width();
+    output->height = producer_buffer->height();
     output->transformHint = 0; // default value, we don't use it yet.
 
     // |numPendingBuffers| counts of the number of buffers that has been enqueued
@@ -519,8 +519,8 @@
         return BAD_VALUE;
     }
 
-    auto buffer_producer = buffers_[slot].mBufferProducer;
-    queue_->Enqueue(buffer_producer, size_t(slot), 0U);
+    auto producer_buffer = buffers_[slot].mProducerBuffer;
+    queue_->Enqueue(producer_buffer, size_t(slot), 0U);
     buffers_[slot].mBufferState.cancel();
     buffers_[slot].mFence = fence;
     ALOGV("cancelBuffer: slot %d", slot);
@@ -791,12 +791,12 @@
     }
 
     size_t slot = status.get();
-    auto buffer_producer = queue_->GetBuffer(slot);
+    auto producer_buffer = queue_->GetBuffer(slot);
 
-    LOG_ALWAYS_FATAL_IF(buffer_producer == nullptr, "Failed to get buffer producer at slot: %zu",
-                        slot);
+    LOG_ALWAYS_FATAL_IF(producer_buffer == nullptr,
+                        "Failed to get the producer buffer at slot: %zu", slot);
 
-    buffers_[slot].mBufferProducer = buffer_producer;
+    buffers_[slot].mProducerBuffer = producer_buffer;
 
     return NO_ERROR;
 }
@@ -810,7 +810,7 @@
     }
 
     // Reset in memory objects related the the buffer.
-    buffers_[slot].mBufferProducer = nullptr;
+    buffers_[slot].mProducerBuffer = nullptr;
     buffers_[slot].mBufferState.detachProducer();
     buffers_[slot].mFence = Fence::NO_FENCE;
     buffers_[slot].mGraphicBuffer = nullptr;
@@ -821,7 +821,7 @@
 status_t BufferHubProducer::FreeAllBuffers() {
     for (size_t slot = 0; slot < BufferHubQueue::kMaxQueueCapacity; slot++) {
         // Reset in memory objects related the the buffer.
-        buffers_[slot].mBufferProducer = nullptr;
+        buffers_[slot].mProducerBuffer = nullptr;
         buffers_[slot].mBufferState.reset();
         buffers_[slot].mFence = Fence::NO_FENCE;
         buffers_[slot].mGraphicBuffer = nullptr;
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index 96e9a85..c04d907 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -158,7 +158,7 @@
 namespace {
 
 struct FrameNumberEqual {
-    FrameNumberEqual(uint64_t frameNumber) : mFrameNumber(frameNumber) {}
+    explicit FrameNumberEqual(uint64_t frameNumber) : mFrameNumber(frameNumber) {}
     bool operator()(const FrameEvents& frame) {
         return frame.valid && mFrameNumber == frame.frameNumber;
     }
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 68a6b1f..d997674 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -536,7 +536,7 @@
 class HpGraphicBufferProducer : public HpInterface<
         BpGraphicBufferProducer, H2BGraphicBufferProducer> {
 public:
-    HpGraphicBufferProducer(const sp<IBinder>& base) : PBase(base) {}
+    explicit HpGraphicBufferProducer(const sp<IBinder>& base) : PBase(base) {}
 
     status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override {
         return mBase->requestBuffer(slot, buf);
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 2d6be26..a481e81 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -63,21 +63,10 @@
         return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
     }
 
-    virtual sp<ISurfaceComposerClient> createScopedConnection(
-            const sp<IGraphicBufferProducer>& parent)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        data.writeStrongBinder(IInterface::asBinder(parent));
-        remote()->transact(BnSurfaceComposer::CREATE_SCOPED_CONNECTION, data, &reply);
-        return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
-    }
-
-    virtual void setTransactionState(
-            const Vector<ComposerState>& state,
-            const Vector<DisplayState>& displays,
-            uint32_t flags)
-    {
+    virtual void setTransactionState(const Vector<ComposerState>& state,
+                                     const Vector<DisplayState>& displays, uint32_t flags,
+                                     const sp<IBinder>& applyToken,
+                                     const InputWindowCommands& commands) {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
 
@@ -92,6 +81,8 @@
         }
 
         data.writeUint32(flags);
+        data.writeStrongBinder(applyToken);
+        commands.write(data);
         remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
     }
 
@@ -710,14 +701,6 @@
             reply->writeStrongBinder(b);
             return NO_ERROR;
         }
-        case CREATE_SCOPED_CONNECTION: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            sp<IGraphicBufferProducer> bufferProducer =
-                interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
-            sp<IBinder> b = IInterface::asBinder(createScopedConnection(bufferProducer));
-            reply->writeStrongBinder(b);
-            return NO_ERROR;
-        }
         case SET_TRANSACTION_STATE: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
 
@@ -750,7 +733,10 @@
             }
 
             uint32_t stateFlags = data.readUint32();
-            setTransactionState(state, displays, stateFlags);
+            sp<IBinder> applyToken = data.readStrongBinder();
+            InputWindowCommands inputWindowCommands;
+            inputWindowCommands.read(data);
+            setTransactionState(state, displays, stateFlags, applyToken, inputWindowCommands);
             return NO_ERROR;
         }
         case BOOT_FINISHED: {
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index a6890ee..928ef95 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -31,7 +31,7 @@
 
 enum class Tag : uint32_t {
     CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
-    DESTROY_SURFACE,
+    CREATE_WITH_SURFACE_PARENT,
     CLEAR_LAYER_FRAME_STATS,
     GET_LAYER_FRAME_STATS,
     LAST = GET_LAYER_FRAME_STATS,
@@ -57,9 +57,16 @@
                                                                             handle, gbp);
     }
 
-    status_t destroySurface(const sp<IBinder>& handle) override {
-        return callRemote<decltype(&ISurfaceComposerClient::destroySurface)>(Tag::DESTROY_SURFACE,
-                                                                             handle);
+    status_t createWithSurfaceParent(const String8& name, uint32_t width, uint32_t height,
+                                     PixelFormat format, uint32_t flags,
+                                     const sp<IGraphicBufferProducer>& parent, int32_t windowType,
+                                     int32_t ownerUid, sp<IBinder>* handle,
+                                     sp<IGraphicBufferProducer>* gbp) override {
+        return callRemote<decltype(
+                &ISurfaceComposerClient::createWithSurfaceParent)>(Tag::CREATE_WITH_SURFACE_PARENT,
+                                                                   name, width, height, format,
+                                                                   flags, parent, windowType,
+                                                                   ownerUid, handle, gbp);
     }
 
     status_t clearLayerFrameStats(const sp<IBinder>& handle) const override {
@@ -92,8 +99,8 @@
     switch (tag) {
         case Tag::CREATE_SURFACE:
             return callLocal(data, reply, &ISurfaceComposerClient::createSurface);
-        case Tag::DESTROY_SURFACE:
-            return callLocal(data, reply, &ISurfaceComposerClient::destroySurface);
+        case Tag::CREATE_WITH_SURFACE_PARENT:
+            return callLocal(data, reply, &ISurfaceComposerClient::createWithSurfaceParent);
         case Tag::CLEAR_LAYER_FRAME_STATS:
             return callLocal(data, reply, &ISurfaceComposerClient::clearLayerFrameStats);
         case Tag::GET_LAYER_FRAME_STATS:
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 35ce6e3..e5170ab 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -379,4 +379,36 @@
     }
 }
 
+// ------------------------------- InputWindowCommands ----------------------------------------
+
+void InputWindowCommands::merge(const InputWindowCommands& other) {
+    transferTouchFocusCommands
+            .insert(transferTouchFocusCommands.end(),
+                    std::make_move_iterator(other.transferTouchFocusCommands.begin()),
+                    std::make_move_iterator(other.transferTouchFocusCommands.end()));
+}
+
+void InputWindowCommands::clear() {
+    transferTouchFocusCommands.clear();
+}
+
+void InputWindowCommands::write(Parcel& output) const {
+    output.writeUint32(static_cast<uint32_t>(transferTouchFocusCommands.size()));
+    for (const auto& transferTouchFocusCommand : transferTouchFocusCommands) {
+        output.writeStrongBinder(transferTouchFocusCommand.fromToken);
+        output.writeStrongBinder(transferTouchFocusCommand.toToken);
+    }
+}
+
+void InputWindowCommands::read(const Parcel& input) {
+    size_t count = input.readUint32();
+    transferTouchFocusCommands.clear();
+    for (size_t i = 0; i < count; i++) {
+        TransferTouchFocusCommand transferTouchFocusCommand;
+        transferTouchFocusCommand.fromToken = input.readStrongBinder();
+        transferTouchFocusCommand.toToken = input.readStrongBinder();
+        transferTouchFocusCommands.emplace_back(transferTouchFocusCommand);
+    }
+}
+
 }; // namespace android
diff --git a/libs/gui/OWNERS b/libs/gui/OWNERS
new file mode 100644
index 0000000..a7c7e79
--- /dev/null
+++ b/libs/gui/OWNERS
@@ -0,0 +1,8 @@
+brianderson@google.com
+jessehall@google.com
+jwcai@google.com
+mathias@google.com
+olv@google.com
+pceballos@google.com
+racarr@google.com
+stoza@google.com
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 9586219..8b9e4d7 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -166,6 +166,7 @@
     mEarlyWakeup(other.mEarlyWakeup) {
     mDisplayStates = other.mDisplayStates;
     mComposerStates = other.mComposerStates;
+    mInputWindowCommands = other.mInputWindowCommands;
 }
 
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) {
@@ -199,9 +200,27 @@
     }
     other.mListenerCallbacks.clear();
 
+    mInputWindowCommands.merge(other.mInputWindowCommands);
+
     return *this;
 }
 
+void SurfaceComposerClient::doDropReferenceTransaction(const sp<IBinder>& handle,
+        const sp<ISurfaceComposerClient>& client) {
+    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+    Vector<ComposerState> composerStates;
+    Vector<DisplayState> displayStates;
+
+    ComposerState s;
+    s.client = client;
+    s.state.surface = handle;
+    s.state.what |= layer_state_t::eReparent;
+    s.state.parentHandleForChild = nullptr;
+
+    composerStates.add(s);
+    sf->setTransactionState(composerStates, displayStates, 0, nullptr, {});
+}
+
 status_t SurfaceComposerClient::Transaction::apply(bool synchronous) {
     if (mStatus != NO_ERROR) {
         return mStatus;
@@ -264,7 +283,9 @@
     mAnimation = false;
     mEarlyWakeup = false;
 
-    sf->setTransactionState(composerStates, displayStates, flags);
+    sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
+    sf->setTransactionState(composerStates, displayStates, flags, applyToken, mInputWindowCommands);
+    mInputWindowCommands.clear();
     mStatus = NO_ERROR;
     return NO_ERROR;
 }
@@ -802,19 +823,18 @@
     s->what |= layer_state_t::eInputInfoChanged;
     return *this;
 }
-#endif
 
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::destroySurface(
-        const sp<SurfaceControl>& sc) {
-    layer_state_t* s = getLayerState(sc);
-    if (!s) {
-        mStatus = BAD_INDEX;
-        return *this;
-    }
-    s->what |= layer_state_t::eDestroySurface;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::transferTouchFocus(
+        const sp<IBinder>& fromToken, const sp<IBinder>& toToken) {
+    InputWindowCommands::TransferTouchFocusCommand transferTouchFocusCommand;
+    transferTouchFocusCommand.fromToken = fromToken;
+    transferTouchFocusCommand.toToken = toToken;
+    mInputWindowCommands.transferTouchFocusCommands.emplace_back(transferTouchFocusCommand);
     return *this;
 }
 
+#endif
+
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColorTransform(
     const sp<SurfaceControl>& sc, const mat3& matrix, const vec3& translation) {
     layer_state_t* s = getLayerState(sc);
@@ -895,11 +915,6 @@
 {
 }
 
-SurfaceComposerClient::SurfaceComposerClient(const sp<IGraphicBufferProducer>& root)
-    : mStatus(NO_INIT), mParent(root)
-{
-}
-
 SurfaceComposerClient::SurfaceComposerClient(const sp<ISurfaceComposerClient>& client)
     : mStatus(NO_ERROR), mClient(client)
 {
@@ -908,10 +923,8 @@
 void SurfaceComposerClient::onFirstRef() {
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
     if (sf != nullptr && mStatus == NO_INIT) {
-        auto rootProducer = mParent.promote();
         sp<ISurfaceComposerClient> conn;
-        conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
-                sf->createConnection();
+        conn = sf->createConnection();
         if (conn != nullptr) {
             mClient = conn;
             mStatus = NO_ERROR;
@@ -964,6 +977,29 @@
     return s;
 }
 
+sp<SurfaceControl> SurfaceComposerClient::createWithSurfaceParent(const String8& name, uint32_t w,
+                                                                  uint32_t h, PixelFormat format,
+                                                                  uint32_t flags, Surface* parent,
+                                                                  int32_t windowType,
+                                                                  int32_t ownerUid) {
+    sp<SurfaceControl> sur;
+    status_t err = mStatus;
+
+    if (mStatus == NO_ERROR) {
+        sp<IBinder> handle;
+        sp<IGraphicBufferProducer> parentGbp = parent->getIGraphicBufferProducer();
+        sp<IGraphicBufferProducer> gbp;
+
+        err = mClient->createWithSurfaceParent(name, w, h, format, flags, parentGbp, windowType,
+                                               ownerUid, &handle, &gbp);
+        ALOGE_IF(err, "SurfaceComposerClient::createWithSurfaceParent error %s", strerror(-err));
+        if (err == NO_ERROR) {
+            return new SurfaceControl(this, handle, gbp, true /* owned */);
+        }
+    }
+    return nullptr;
+}
+
 status_t SurfaceComposerClient::createSurfaceChecked(
         const String8& name,
         uint32_t w,
@@ -996,13 +1032,6 @@
     return err;
 }
 
-status_t SurfaceComposerClient::destroySurface(const sp<IBinder>& sid) {
-    if (mStatus != NO_ERROR)
-        return mStatus;
-    status_t err = mClient->destroySurface(sid);
-    return err;
-}
-
 status_t SurfaceComposerClient::clearLayerFrameStats(const sp<IBinder>& token) const {
     if (mStatus != NO_ERROR) {
         return mStatus;
@@ -1126,6 +1155,7 @@
     return ComposerService::getComposerService()->getDisplayedContentSample(display, maxFrames,
                                                                             timestamp, outStats);
 }
+
 // ----------------------------------------------------------------------------
 
 status_t ScreenshotClient::capture(const sp<IBinder>& display, const ui::Dataspace reqDataSpace,
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 3a6dfda..8e500a4 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -54,9 +54,22 @@
 {
 }
 
+SurfaceControl::SurfaceControl(const sp<SurfaceControl>& other) {
+    mClient = other->mClient;
+    mHandle = other->mHandle;
+    mGraphicBufferProducer = other->mGraphicBufferProducer;
+    mOwned = false;
+}
+
 SurfaceControl::~SurfaceControl()
 {
-    destroy();
+    if (mClient != nullptr && mHandle != nullptr && mOwned) {
+        SurfaceComposerClient::doDropReferenceTransaction(mHandle, mClient->getClient());
+    }
+    mClient.clear();
+    mHandle.clear();
+    mGraphicBufferProducer.clear();
+    IPCThreadState::self()->flushCommands();
 }
 
 void SurfaceControl::destroy()
@@ -64,7 +77,7 @@
     // Avoid destroying the server-side surface if we are not the owner of it, meaning that we
     // retrieved it from another process.
     if (isValid() && mOwned) {
-        mClient->destroySurface(mHandle);
+        SurfaceComposerClient::Transaction().reparent(this, nullptr).apply();
     }
     // clear all references and trigger an IPC now, to make sure things
     // happen without delay, since these resources are quite heavy.
diff --git a/libs/gui/include/gui/BufferHubProducer.h b/libs/gui/include/gui/BufferHubProducer.h
index f7af19b..0e925ce 100644
--- a/libs/gui/include/gui/BufferHubProducer.h
+++ b/libs/gui/include/gui/BufferHubProducer.h
@@ -203,10 +203,10 @@
     // requested buffer usage or geometry differs from that of the buffer
     // allocated to a slot.
     struct BufferHubSlot : public BufferSlot {
-        BufferHubSlot() : mBufferProducer(nullptr), mIsReallocating(false) {}
+        BufferHubSlot() : mProducerBuffer(nullptr), mIsReallocating(false) {}
         // BufferSlot comes from android framework, using m prefix to comply with
         // the name convention with the reset of data fields from BufferSlot.
-        std::shared_ptr<dvr::BufferProducer> mBufferProducer;
+        std::shared_ptr<dvr::ProducerBuffer> mProducerBuffer;
         bool mIsReallocating;
     };
     BufferHubSlot buffers_[dvr::BufferHubQueue::kMaxQueueCapacity];
diff --git a/libs/gui/include/gui/BufferQueueConsumer.h b/libs/gui/include/gui/BufferQueueConsumer.h
index d108120..aa13c0c 100644
--- a/libs/gui/include/gui/BufferQueueConsumer.h
+++ b/libs/gui/include/gui/BufferQueueConsumer.h
@@ -31,7 +31,7 @@
 class BufferQueueConsumer : public BnGraphicBufferConsumer {
 
 public:
-    BufferQueueConsumer(const sp<BufferQueueCore>& core);
+    explicit BufferQueueConsumer(const sp<BufferQueueCore>& core);
     ~BufferQueueConsumer() override;
 
     // acquireBuffer attempts to acquire ownership of the next pending buffer in
diff --git a/libs/gui/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h
index 5c7ffb4..73bc5dd 100644
--- a/libs/gui/include/gui/BufferQueueProducer.h
+++ b/libs/gui/include/gui/BufferQueueProducer.h
@@ -29,7 +29,8 @@
 public:
     friend class BufferQueue; // Needed to access binderDied
 
-    BufferQueueProducer(const sp<BufferQueueCore>& core, bool consumerIsSurfaceFlinger = false);
+    explicit BufferQueueProducer(const sp<BufferQueueCore>& core,
+                                 bool consumerIsSurfaceFlinger = false);
     ~BufferQueueProducer() override;
 
     // requestBuffer returns the GraphicBuffer for slot N.
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index 32ce59a..a4102df 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -84,7 +84,7 @@
      * or requestNextVsync to receive them.
      * Other events start being delivered immediately.
      */
-    DisplayEventReceiver(
+    explicit DisplayEventReceiver(
             ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp);
 
     /*
diff --git a/libs/gui/include/gui/GLConsumer.h b/libs/gui/include/gui/GLConsumer.h
index 46a99e1..ddd868d 100644
--- a/libs/gui/include/gui/GLConsumer.h
+++ b/libs/gui/include/gui/GLConsumer.h
@@ -301,7 +301,7 @@
     // also only creating new EGLImages from buffers when required.
     class EglImage : public LightRefBase<EglImage>  {
     public:
-        EglImage(sp<GraphicBuffer> graphicBuffer);
+        explicit EglImage(sp<GraphicBuffer> graphicBuffer);
 
         // createIfNeeded creates an EGLImage if required (we haven't created
         // one yet, or the EGLDisplay or crop-rect has changed).
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 3052c0b..1534fca 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -42,6 +42,7 @@
 struct DisplayState;
 struct DisplayInfo;
 struct DisplayStatInfo;
+struct InputWindowCommands;
 class LayerDebugInfo;
 class HdrCapabilities;
 class IDisplayEventConnection;
@@ -86,22 +87,11 @@
         eVsyncSourceSurfaceFlinger = 1
     };
 
-    /* create connection with surface flinger, requires
-     * ACCESS_SURFACE_FLINGER permission
+    /* 
+     * Create a connection with SurfaceFlinger.
      */
     virtual sp<ISurfaceComposerClient> createConnection() = 0;
 
-    /** create a scoped connection with surface flinger.
-     * Surfaces produced with this connection will act
-     * as children of the passed in GBP. That is to say
-     * SurfaceFlinger will draw them relative and confined to
-     * drawing of buffers from the layer associated with parent.
-     * As this is graphically equivalent in reach to just drawing
-     * pixels into the parent buffers, it requires no special permission.
-     */
-    virtual sp<ISurfaceComposerClient> createScopedConnection(
-            const sp<IGraphicBufferProducer>& parent) = 0;
-
     /* return an IDisplayEventConnection */
     virtual sp<IDisplayEventConnection> createDisplayEventConnection(
             VsyncSource vsyncSource = eVsyncSourceApp) = 0;
@@ -124,7 +114,9 @@
 
     /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
     virtual void setTransactionState(const Vector<ComposerState>& state,
-            const Vector<DisplayState>& displays, uint32_t flags) = 0;
+                                     const Vector<DisplayState>& displays, uint32_t flags,
+                                     const sp<IBinder>& applyToken,
+                                     const InputWindowCommands& inputWindowCommands) = 0;
 
     /* signal that we're done booting.
      * Requires ACCESS_SURFACE_FLINGER permission
@@ -353,7 +345,6 @@
         ENABLE_VSYNC_INJECTIONS,
         INJECT_VSYNC,
         GET_LAYER_DEBUG_INFO,
-        CREATE_SCOPED_CONNECTION,
         GET_COMPOSITION_PREFERENCE,
         GET_COLOR_MANAGEMENT,
         GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES,
diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h
index 82b01b8..f443df8 100644
--- a/libs/gui/include/gui/ISurfaceComposerClient.h
+++ b/libs/gui/include/gui/ISurfaceComposerClient.h
@@ -58,7 +58,12 @@
     /*
      * Requires ACCESS_SURFACE_FLINGER permission
      */
-    virtual status_t destroySurface(const sp<IBinder>& handle) = 0;
+    virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
+                                             PixelFormat format, uint32_t flags,
+                                             const sp<IGraphicBufferProducer>& parent,
+                                             int32_t windowType, int32_t ownerUid,
+                                             sp<IBinder>* handle,
+                                             sp<IGraphicBufferProducer>* gbp) = 0;
 
     /*
      * Requires ACCESS_SURFACE_FLINGER permission
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 02c6be2..e7564f5 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -228,6 +228,20 @@
     status_t read(const Parcel& input);
 };
 
+struct InputWindowCommands {
+    struct TransferTouchFocusCommand {
+        sp<IBinder> fromToken;
+        sp<IBinder> toToken;
+    };
+
+    std::vector<TransferTouchFocusCommand> transferTouchFocusCommands;
+
+    void merge(const InputWindowCommands& other);
+    void clear();
+    void write(Parcel& output) const;
+    void read(const Parcel& input);
+};
+
 static inline int compare_type(const ComposerState& lhs, const ComposerState& rhs) {
     if (lhs.client < rhs.client) return -1;
     if (lhs.client > rhs.client) return 1;
diff --git a/libs/gui/include/gui/StreamSplitter.h b/libs/gui/include/gui/StreamSplitter.h
index 8f47eb4..b4eef29 100644
--- a/libs/gui/include/gui/StreamSplitter.h
+++ b/libs/gui/include/gui/StreamSplitter.h
@@ -128,7 +128,7 @@
 
     class BufferTracker : public LightRefBase<BufferTracker> {
     public:
-        BufferTracker(const sp<GraphicBuffer>& buffer);
+        explicit BufferTracker(const sp<GraphicBuffer>& buffer);
 
         const sp<GraphicBuffer>& getBuffer() const { return mBuffer; }
         const sp<Fence>& getMergedFence() const { return mMergedFence; }
@@ -154,7 +154,7 @@
     };
 
     // Only called from createSplitter
-    StreamSplitter(const sp<IGraphicBufferConsumer>& inputQueue);
+    explicit StreamSplitter(const sp<IGraphicBufferConsumer>& inputQueue);
 
     // Must be accessed through RefBase
     virtual ~StreamSplitter();
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 8e3ba78..f16f781 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -90,7 +90,6 @@
 public:
                 SurfaceComposerClient();
                 SurfaceComposerClient(const sp<ISurfaceComposerClient>& client);
-                SurfaceComposerClient(const sp<IGraphicBufferProducer>& parent);
     virtual     ~SurfaceComposerClient();
 
     // Always make sure we could initialize
@@ -146,6 +145,13 @@
                                              ui::Dataspace* wideColorGamutDataspace,
                                              ui::PixelFormat* wideColorGamutPixelFormat);
 
+    /**
+     * Called from SurfaceControl d'tor to 'destroy' the surface (or rather, reparent it
+     * to null), but without needing an sp<SurfaceControl> to avoid infinite ressurection.
+     */
+    static void doDropReferenceTransaction(const sp<IBinder>& handle,
+            const sp<ISurfaceComposerClient>& client);
+
     // ------------------------------------------------------------------------
     // surface creation / destruction
 
@@ -162,15 +168,27 @@
     );
 
     status_t createSurfaceChecked(
-            const String8& name,// name of the surface
-            uint32_t w,         // width in pixel
-            uint32_t h,         // height in pixel
-            PixelFormat format, // pixel-format desired
+            const String8& name, // name of the surface
+            uint32_t w,          // width in pixel
+            uint32_t h,          // height in pixel
+            PixelFormat format,  // pixel-format desired
             sp<SurfaceControl>* outSurface,
-            uint32_t flags = 0, // usage flags
+            uint32_t flags = 0,               // usage flags
             SurfaceControl* parent = nullptr, // parent
             int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.)
-            int32_t ownerUid = -1 // UID of the task
+            int32_t ownerUid = -1    // UID of the task
+    );
+
+    //! Create a surface
+    sp<SurfaceControl> createWithSurfaceParent(
+            const String8& name,       // name of the surface
+            uint32_t w,                // width in pixel
+            uint32_t h,                // height in pixel
+            PixelFormat format,        // pixel-format desired
+            uint32_t flags = 0,        // usage flags
+            Surface* parent = nullptr, // parent
+            int32_t windowType = -1,   // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.)
+            int32_t ownerUid = -1      // UID of the task
     );
 
     //! Create a virtual display
@@ -219,6 +237,7 @@
         bool                        mAnimation = false;
         bool                        mEarlyWakeup = false;
 
+        InputWindowCommands mInputWindowCommands;
         int mStatus = NO_ERROR;
 
         layer_state_t* getLayerState(const sp<SurfaceControl>& sc);
@@ -335,10 +354,9 @@
 
 #ifndef NO_INPUT
         Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const InputWindowInfo& info);
+        Transaction& transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
 #endif
 
-        Transaction& destroySurface(const sp<SurfaceControl>& sc);
-
         // Set a color transform matrix on the given layer on the built-in display.
         Transaction& setColorTransform(const sp<SurfaceControl>& sc, const mat3& matrix,
                                        const vec3& translation);
@@ -367,8 +385,6 @@
         void setEarlyWakeup();
     };
 
-    status_t    destroySurface(const sp<IBinder>& id);
-
     status_t clearLayerFrameStats(const sp<IBinder>& token) const;
     status_t getLayerFrameStats(const sp<IBinder>& token, FrameStats* outStats) const;
     static status_t clearAnimationFrameStats();
@@ -400,7 +416,6 @@
     mutable     Mutex                       mLock;
                 status_t                    mStatus;
                 sp<ISurfaceComposerClient>  mClient;
-                wp<IGraphicBufferProducer>  mParent;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
index ccb30fa..9bba766 100644
--- a/libs/gui/include/gui/SurfaceControl.h
+++ b/libs/gui/include/gui/SurfaceControl.h
@@ -75,6 +75,8 @@
     status_t getLayerFrameStats(FrameStats* outStats) const;
 
     sp<SurfaceComposerClient> getClient() const;
+    
+    explicit SurfaceControl(const sp<SurfaceControl>& other);
 
 private:
     // can't be copied
diff --git a/libs/gui/include/gui/bufferqueue/1.0/B2HProducerListener.h b/libs/gui/include/gui/bufferqueue/1.0/B2HProducerListener.h
index fa6c2d9..0f6fb45 100644
--- a/libs/gui/include/gui/bufferqueue/1.0/B2HProducerListener.h
+++ b/libs/gui/include/gui/bufferqueue/1.0/B2HProducerListener.h
@@ -50,7 +50,7 @@
 
 struct B2HProducerListener : public HProducerListener {
     sp<BProducerListener> mBase;
-    B2HProducerListener(sp<BProducerListener> const& base);
+    explicit B2HProducerListener(sp<BProducerListener> const& base);
     Return<void> onBufferReleased() override;
     Return<bool> needsReleaseNotify() override;
 };
diff --git a/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h b/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
index 74850b4..c92fa9d 100644
--- a/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
+++ b/libs/gui/include/gui/bufferqueue/1.0/H2BGraphicBufferProducer.h
@@ -59,7 +59,7 @@
         HGraphicBufferProducer,
         BGraphicBufferProducer,
         BnGraphicBufferProducer> {
-    H2BGraphicBufferProducer(sp<HGraphicBufferProducer> const& base) : CBase(base) {}
+    explicit H2BGraphicBufferProducer(sp<HGraphicBufferProducer> const& base) : CBase(base) {}
 
     status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override;
     status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) override;
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 60542bd..7fc69ff 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -133,6 +133,27 @@
         EXPECT_EQ(AMOTION_EVENT_ACTION_UP, mev->getAction());
     }
 
+    void expectMotionEvent(int motionEventType, int x, int y) {
+        InputEvent *ev = consumeEvent();
+        ASSERT_NE(ev, nullptr);
+        ASSERT_EQ(ev->getType(), AINPUT_EVENT_TYPE_MOTION);
+        MotionEvent *mev = static_cast<MotionEvent *>(ev);
+        EXPECT_EQ(motionEventType, mev->getAction());
+        EXPECT_EQ(x, mev->getX(0));
+        EXPECT_EQ(y, mev->getY(0));
+    }
+
+    void expectNoMotionEvent(int motionEventType) {
+        InputEvent *ev = consumeEvent();
+        if (ev == nullptr || ev->getType() != AINPUT_EVENT_TYPE_MOTION) {
+            // Didn't find an event or a motion event so assume action didn't occur.
+            return;
+        }
+
+        MotionEvent *mev = static_cast<MotionEvent *>(ev);
+        EXPECT_NE(motionEventType, mev->getAction());
+    }
+
     ~InputSurface() {
         mInputFlinger->unregisterInputChannel(mServerChannel);
     }
@@ -255,6 +276,15 @@
     }
 }
 
+void injectMotionEvent(std::string event, int x, int y) {
+    char *buf1, *buf2;
+    asprintf(&buf1, "%d", x);
+    asprintf(&buf2, "%d", y);
+    if (fork() == 0) {
+        execlp("input", "input", "motionevent", event.c_str(), buf1, buf2, NULL);
+    }
+}
+
 TEST_F(InputSurfacesTest, can_receive_input) {
     std::unique_ptr<InputSurface> surface = makeSurface(100, 100);
     surface->showAt(100, 100);
@@ -439,5 +469,25 @@
     injectTap(11, 11);
     bgSurface->expectTap(1, 1);
 }
+
+TEST_F(InputSurfacesTest, transfer_touch_focus) {
+    std::unique_ptr<InputSurface> fromSurface = makeSurface(100, 100);
+
+    fromSurface->showAt(10, 10);
+    injectMotionEvent("DOWN", 11, 11);
+    fromSurface->expectMotionEvent(AMOTION_EVENT_ACTION_DOWN, 1, 1);
+
+    std::unique_ptr<InputSurface> toSurface = makeSurface(100, 100);
+    toSurface->showAt(10, 10);
+
+    sp<IBinder> fromToken = fromSurface->mServerChannel->getToken();
+    sp<IBinder> toToken = toSurface->mServerChannel->getToken();
+    SurfaceComposerClient::Transaction t;
+    t.transferTouchFocus(fromToken, toToken).apply(true);
+
+    injectMotionEvent("UP", 11, 11);
+    toSurface->expectMotionEvent(AMOTION_EVENT_ACTION_UP, 1, 1);
+    fromSurface->expectNoMotionEvent(AMOTION_EVENT_ACTION_UP);
+}
 }
 }
diff --git a/libs/gui/tests/Malicious.cpp b/libs/gui/tests/Malicious.cpp
index bb6b8a5..acd4297 100644
--- a/libs/gui/tests/Malicious.cpp
+++ b/libs/gui/tests/Malicious.cpp
@@ -27,7 +27,7 @@
 
 class ProxyBQP : public BnGraphicBufferProducer {
 public:
-    ProxyBQP(const sp<IGraphicBufferProducer>& producer) : mProducer(producer) {}
+    explicit ProxyBQP(const sp<IGraphicBufferProducer>& producer) : mProducer(producer) {}
 
     // Pass through calls to mProducer
     status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override {
@@ -102,7 +102,7 @@
 
 class MaliciousBQP : public ProxyBQP {
 public:
-    MaliciousBQP(const sp<IGraphicBufferProducer>& producer) : ProxyBQP(producer) {}
+    explicit MaliciousBQP(const sp<IGraphicBufferProducer>& producer) : ProxyBQP(producer) {}
 
     void beMalicious(int32_t value) { mMaliciousValue = value; }
 
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 67afbd6..60173dc 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -545,10 +545,6 @@
     }
 
     sp<ISurfaceComposerClient> createConnection() override { return nullptr; }
-    sp<ISurfaceComposerClient> createScopedConnection(
-            const sp<IGraphicBufferProducer>& /* parent */) override {
-        return nullptr;
-    }
     sp<IDisplayEventConnection> createDisplayEventConnection(ISurfaceComposer::VsyncSource)
             override {
         return nullptr;
@@ -558,8 +554,9 @@
     void destroyDisplay(const sp<IBinder>& /*display */) override {}
     sp<IBinder> getBuiltInDisplay(int32_t /*id*/) override { return nullptr; }
     void setTransactionState(const Vector<ComposerState>& /*state*/,
-            const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/)
-            override {}
+                             const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
+                             const sp<IBinder>& /*applyToken*/,
+                             const InputWindowCommands& /*inputWindowCommands*/) override {}
     void bootFinished() override {}
     bool authenticateSurfaceTexture(
             const sp<IGraphicBufferProducer>& /*surface*/) const override {
@@ -669,8 +666,7 @@
 
 class FakeProducerFrameEventHistory : public ProducerFrameEventHistory {
 public:
-    FakeProducerFrameEventHistory(FenceToFenceTimeMap* fenceMap)
-        : mFenceMap(fenceMap) {}
+    explicit FakeProducerFrameEventHistory(FenceToFenceTimeMap* fenceMap) : mFenceMap(fenceMap) {}
 
     ~FakeProducerFrameEventHistory() {}
 
diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp
index 139570a..acf40bc 100644
--- a/libs/input/IInputFlinger.cpp
+++ b/libs/input/IInputFlinger.cpp
@@ -42,6 +42,16 @@
                 IBinder::FLAG_ONEWAY);
     }
 
+    virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
+
+        data.writeStrongBinder(fromToken);
+        data.writeStrongBinder(toToken);
+        remote()->transact(BnInputFlinger::TRANSFER_TOUCH_FOCUS, data, &reply,
+                IBinder::FLAG_ONEWAY);
+    }
+
     virtual void registerInputChannel(const sp<InputChannel>& channel) {
         Parcel data, reply;
         data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor());
@@ -90,6 +100,13 @@
         unregisterInputChannel(channel);
         break;
     }
+    case TRANSFER_TOUCH_FOCUS: {
+        CHECK_INTERFACE(IInputFlinger, data, reply);
+        sp<IBinder> fromToken = data.readStrongBinder();
+        sp<IBinder> toToken = data.readStrongBinder();
+        transferTouchFocus(fromToken, toToken);
+        break;
+    }
     default:
         return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index a558970..db86c8e 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -234,6 +234,7 @@
         int32_t edgeFlags,
         int32_t metaState,
         int32_t buttonState,
+        MotionClassification classification,
         float xOffset,
         float yOffset,
         float xPrecision,
@@ -250,6 +251,7 @@
     mEdgeFlags = edgeFlags;
     mMetaState = metaState;
     mButtonState = buttonState;
+    mClassification = classification;
     mXOffset = xOffset;
     mYOffset = yOffset;
     mXPrecision = xPrecision;
@@ -270,6 +272,7 @@
     mEdgeFlags = other->mEdgeFlags;
     mMetaState = other->mMetaState;
     mButtonState = other->mButtonState;
+    mClassification = other->mClassification;
     mXOffset = other->mXOffset;
     mYOffset = other->mYOffset;
     mXPrecision = other->mXPrecision;
@@ -451,6 +454,7 @@
     mEdgeFlags = parcel->readInt32();
     mMetaState = parcel->readInt32();
     mButtonState = parcel->readInt32();
+    mClassification = static_cast<MotionClassification>(parcel->readByte());
     mXOffset = parcel->readFloat();
     mYOffset = parcel->readFloat();
     mXPrecision = parcel->readFloat();
@@ -501,6 +505,7 @@
     parcel->writeInt32(mEdgeFlags);
     parcel->writeInt32(mMetaState);
     parcel->writeInt32(mButtonState);
+    parcel->writeByte(static_cast<int8_t>(mClassification));
     parcel->writeFloat(mXOffset);
     parcel->writeFloat(mYOffset);
     parcel->writeFloat(mXPrecision);
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index f33b210..0ddee44 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -1112,6 +1112,7 @@
             msg->body.motion.edgeFlags,
             msg->body.motion.metaState,
             msg->body.motion.buttonState,
+            MotionClassification::NONE,
             msg->body.motion.xOffset,
             msg->body.motion.yOffset,
             msg->body.motion.xPrecision,
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index 99f83ba..e4c1514 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -260,7 +260,7 @@
     event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE, 0,
             AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
             AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,
-            X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
+            MotionClassification::NONE, X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
             ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME,
             2, pointerProperties, pointerCoords);
 
@@ -572,8 +572,11 @@
         pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, angle);
     }
     MotionEvent event;
-    event.initialize(0, 0, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
+    event.initialize(0 /*deviceId*/, AINPUT_SOURCE_UNKNOWN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE,
+            0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE,
+            AMETA_NONE, 0 /*buttonState*/, MotionClassification::NONE,
+            0 /*xOffset*/, 0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/,
+            0 /*downTime*/, 0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords);
     float originalRawX = 0 + 3;
     float originalRawY = -RADIUS + 2;
 
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index af97c34..3c67542 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -90,7 +90,8 @@
 
     MotionEvent* event = new MotionEvent();
     PointerCoords coords;
-    PointerProperties properties[1];
+    constexpr size_t pointerCount = 1;
+    PointerProperties properties[pointerCount];
 
     properties[0].id = DEFAULT_POINTER_ID;
     properties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
@@ -98,8 +99,11 @@
     // First sample added separately with initialize
     coords.setAxisValue(AMOTION_EVENT_AXIS_X, positions[0].x);
     coords.setAxisValue(AMOTION_EVENT_AXIS_Y, positions[0].y);
-    event->initialize(0, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, positions[0].time, 1, properties, &coords);
+    event->initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
+            AMOTION_EVENT_ACTION_MOVE, 0 /*actionButton*/, 0 /*flags*/,
+            AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/, MotionClassification::NONE,
+            0 /*xOffset*/, 0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/,
+            0 /*downTime*/, positions[0].time, pointerCount, properties, &coords);
 
     for (size_t i = 1; i < numSamples; i++) {
         coords.setAxisValue(AMOTION_EVENT_AXIS_X, positions[i].x);
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index a19fe17..6ea1270 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -268,7 +268,11 @@
     AHardwareBuffer_Desc trialDesc = *desc;
     trialDesc.width = 4;
     trialDesc.height = desc->format == AHARDWAREBUFFER_FORMAT_BLOB ? 1 : 4;
-    trialDesc.layers = desc->layers == 1 ? 1 : 2;
+    if (desc->usage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP) {
+        trialDesc.layers = desc->layers == 6 ? 6 : 12;
+    } else {
+        trialDesc.layers = desc->layers == 1 ? 1 : 2;
+    }
     AHardwareBuffer* trialBuffer = nullptr;
     int result = AHardwareBuffer_allocate(&trialDesc, &trialBuffer);
     if (result == NO_ERROR) {
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index 03545a6..2796c75 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -208,6 +208,17 @@
      */
     AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT       = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER,
     /**
+     * The buffer will be used as a composer HAL overlay layer.
+     *
+     * This flag is currently only needed when using ASurfaceTransaction_setBuffer
+     * to set a buffer. In all other cases, the framework adds this flag
+     * internally to buffers that could be presented in a composer overlay.
+     * ASurfaceTransaction_setBuffer is special because it uses buffers allocated
+     * directly through AHardwareBuffer_allocate instead of buffers allocated
+     * by the framework.
+     */
+    AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY       = 1ULL << 11,
+    /**
      * The buffer is protected from direct CPU access or being read by
      * non-secure hardware, such as video encoders.
      *
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index d872f02..36211ca 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -26,6 +26,7 @@
         "libgui",
         "liblog",
         "libnativewindow",
+        "libsync",
         "libui",
         "libutils",
     ],
@@ -79,3 +80,19 @@
         thin: true,
     },
 }
+
+cc_library_static {
+    name: "librenderengine_mocks",
+    defaults: ["librenderengine_defaults"],
+    srcs: [
+        "mock/Framebuffer.cpp",
+        "mock/Image.cpp",
+        "mock/RenderEngine.cpp",
+    ],
+    static_libs: [
+        "libgtest",
+        "libgmock",
+    ],
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+}
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 51cf188..2915bb8 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -24,14 +24,17 @@
 #include <math.h>
 #include <fstream>
 #include <sstream>
+#include <unordered_set>
 
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 #include <android-base/stringprintf.h>
 #include <cutils/compiler.h>
+#include <cutils/properties.h>
 #include <renderengine/Mesh.h>
 #include <renderengine/Texture.h>
 #include <renderengine/private/Description.h>
+#include <sync/sync.h>
 #include <ui/ColorSpace.h>
 #include <ui/DebugUtils.h>
 #include <ui/Rect.h>
@@ -414,6 +417,13 @@
         mBt2020ToSrgb = mXyzToSrgb * mBt2020ToXyz;
         mBt2020ToDisplayP3 = mXyzToDisplayP3 * mBt2020ToXyz;
     }
+
+    char value[PROPERTY_VALUE_MAX];
+    property_get("debug.egl.traceGpuCompletion", value, "0");
+    if (atoi(value)) {
+        mTraceGpuCompletion = true;
+        mFlushTracer = std::make_unique<FlushTracer>(this);
+    }
 }
 
 GLESRenderEngine::~GLESRenderEngine() {
@@ -459,6 +469,12 @@
         ALOGW("failed to dup EGL native fence sync: %#x", eglGetError());
     }
 
+    // Only trace if we have a valid fence, as current usage falls back to
+    // calling finish() if the fence fd is invalid.
+    if (CC_UNLIKELY(mTraceGpuCompletion && mFlushTracer) && fenceFd.get() >= 0) {
+        mFlushTracer->queueSync(eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr));
+    }
+
     return fenceFd;
 }
 
@@ -474,8 +490,15 @@
         return false;
     }
 
-    EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
-                                         2000000000 /*2 sec*/);
+    if (CC_UNLIKELY(mTraceGpuCompletion && mFlushTracer)) {
+        mFlushTracer->queueSync(eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr));
+    }
+
+    return waitSync(sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR);
+}
+
+bool GLESRenderEngine::waitSync(EGLSyncKHR sync, EGLint flags) {
+    EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, flags, 2000000000 /*2 sec*/);
     EGLint error = eglGetError();
     eglDestroySyncKHR(mEGLDisplay, sync);
     if (result != EGL_CONDITION_SATISFIED_KHR) {
@@ -584,6 +607,65 @@
     }
 }
 
+status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer,
+                                                     sp<Fence> bufferFence) {
+    std::unique_ptr<Image> newImage = createImage();
+
+    bool created = newImage->setNativeWindowBuffer(buffer->getNativeBuffer(),
+                                                   buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
+    if (!created) {
+        ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
+              buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
+              buffer->getPixelFormat());
+        bindExternalTextureImage(texName, *createImage());
+        return NO_INIT;
+    }
+
+    bindExternalTextureImage(texName, *newImage);
+
+    // Wait for the new buffer to be ready.
+    if (bufferFence != nullptr && bufferFence->isValid()) {
+        if (GLExtensions::getInstance().hasWaitSync()) {
+            base::unique_fd fenceFd(bufferFence->dup());
+            if (fenceFd == -1) {
+                ALOGE("error dup'ing fence fd: %d", errno);
+                return -errno;
+            }
+            if (!waitFence(std::move(fenceFd))) {
+                ALOGE("failed to wait on fence fd");
+                return UNKNOWN_ERROR;
+            }
+        } else {
+            status_t err = bufferFence->waitForever("RenderEngine::bindExternalTextureBuffer");
+            if (err != NO_ERROR) {
+                ALOGE("error waiting for fence: %d", err);
+                return err;
+            }
+        }
+    }
+
+    return NO_ERROR;
+}
+
+FloatRect GLESRenderEngine::setupLayerCropping(const LayerSettings& layer, Mesh& mesh) {
+    // Translate win by the rounded corners rect coordinates, to have all values in
+    // layer coordinate space.
+    FloatRect cropWin = layer.geometry.boundaries;
+    const FloatRect& roundedCornersCrop = layer.geometry.roundedCornersCrop;
+    cropWin.left -= roundedCornersCrop.left;
+    cropWin.right -= roundedCornersCrop.left;
+    cropWin.top -= roundedCornersCrop.top;
+    cropWin.bottom -= roundedCornersCrop.top;
+    Mesh::VertexArray<vec2> cropCoords(mesh.getCropCoordArray<vec2>());
+    cropCoords[0] = vec2(cropWin.left, cropWin.top);
+    cropCoords[1] = vec2(cropWin.left, cropWin.top + cropWin.getHeight());
+    cropCoords[2] = vec2(cropWin.right, cropWin.top + cropWin.getHeight());
+    cropCoords[3] = vec2(cropWin.right, cropWin.top);
+
+    setupCornerRadiusCropSize(roundedCornersCrop.getWidth(), roundedCornersCrop.getHeight());
+    return cropWin;
+}
+
 status_t GLESRenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {
     GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(framebuffer);
     EGLImageKHR eglImage = glFramebuffer->getEGLImage();
@@ -672,33 +754,68 @@
     setDisplayMaxLuminance(display.maxLuminance);
 
     mat4 projectionMatrix = mState.projectionMatrix * display.globalTransform;
+    mState.projectionMatrix = projectionMatrix;
+    if (!display.clearRegion.isEmpty()) {
+        fillRegionWithColor(display.clearRegion, 0.0, 0.0, 0.0, 1.0);
+    }
 
-    Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2);
+    Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2, 2);
     for (auto layer : layers) {
-        // for now, assume that all pixel sources are solid colors.
-        // TODO(alecmouri): support buffer sources
-        if (layer.source.buffer.buffer != nullptr) {
-            continue;
-        }
-
-        setColorTransform(display.colorTransform * layer.colorTransform);
-
         mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform;
 
-        FloatRect bounds = layer.geometry.boundaries;
+        const FloatRect bounds = layer.geometry.boundaries;
         Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
         position[0] = vec2(bounds.left, bounds.top);
         position[1] = vec2(bounds.left, bounds.bottom);
         position[2] = vec2(bounds.right, bounds.bottom);
         position[3] = vec2(bounds.right, bounds.top);
 
-        half3 solidColor = layer.source.solidColor;
-        half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha);
-        setupLayerBlending(/*premultipliedAlpha=*/true, /*opaque=*/false, /*disableTexture=*/true,
-                           color, /*cornerRadius=*/0.0);
+        setupLayerCropping(layer, mesh);
+        setColorTransform(display.colorTransform * layer.colorTransform);
+
+        bool usePremultipliedAlpha = true;
+        bool disableTexture = true;
+
+        if (layer.source.buffer.buffer != nullptr) {
+            disableTexture = false;
+
+            sp<GraphicBuffer> gBuf = layer.source.buffer.buffer;
+
+            bindExternalTextureBuffer(layer.source.buffer.textureName, gBuf,
+                                      layer.source.buffer.fence);
+
+            usePremultipliedAlpha = layer.source.buffer.usePremultipliedAlpha;
+            Texture texture(Texture::TEXTURE_EXTERNAL, layer.source.buffer.textureName);
+            texture.setMatrix(layer.source.buffer.textureTransform.asArray());
+            texture.setFiltering(layer.source.buffer.useTextureFiltering);
+
+            texture.setDimensions(gBuf->getWidth(), gBuf->getHeight());
+            setSourceY410BT2020(layer.source.buffer.isY410BT2020);
+
+            renderengine::Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
+            texCoords[0] = vec2(0.0, 1.0);
+            texCoords[1] = vec2(0.0, 0.0);
+            texCoords[2] = vec2(1.0, 0.0);
+            texCoords[3] = vec2(1.0, 1.0);
+            setupLayerTexturing(texture);
+        }
+
+        const half3 solidColor = layer.source.solidColor;
+        const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha);
+        // Buffer sources will have a black solid color ignored in the shader,
+        // so in that scenario the solid color passed here is arbitrary.
+        setupLayerBlending(usePremultipliedAlpha, layer.source.buffer.isOpaque, disableTexture,
+                           color, layer.geometry.roundedCornersRadius);
         setSourceDataSpace(layer.sourceDataspace);
 
         drawMesh(mesh);
+
+        // Cleanup if there's a buffer source
+        if (layer.source.buffer.buffer != nullptr) {
+            disableBlending();
+            setSourceY410BT2020(false);
+            disableTexturing();
+        }
     }
 
     *drawFence = flush();
@@ -1128,6 +1245,61 @@
     return (isInputHdrDataSpace || isOutputHdrDataSpace) && inputTransfer != outputTransfer;
 }
 
+// FlushTracer implementation
+GLESRenderEngine::FlushTracer::FlushTracer(GLESRenderEngine* engine) : mEngine(engine) {
+    mThread = std::thread(&GLESRenderEngine::FlushTracer::loop, this);
+}
+
+GLESRenderEngine::FlushTracer::~FlushTracer() {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mRunning = false;
+    }
+    mCondition.notify_all();
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+}
+
+void GLESRenderEngine::FlushTracer::queueSync(EGLSyncKHR sync) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    char name[64];
+    const uint64_t frameNum = mFramesQueued++;
+    snprintf(name, sizeof(name), "Queueing sync for frame: %lu",
+             static_cast<unsigned long>(frameNum));
+    ATRACE_NAME(name);
+    mQueue.push({sync, frameNum});
+    ATRACE_INT("GPU Frames Outstanding", mQueue.size());
+    mCondition.notify_one();
+}
+
+void GLESRenderEngine::FlushTracer::loop() {
+    while (mRunning) {
+        QueueEntry entry;
+        {
+            std::lock_guard<std::mutex> lock(mMutex);
+
+            mCondition.wait(mMutex,
+                            [&]() REQUIRES(mMutex) { return !mQueue.empty() && !mRunning; });
+
+            if (!mRunning) {
+                // if mRunning is false, then FlushTracer is being destroyed, so
+                // bail out now.
+                break;
+            }
+            entry = mQueue.front();
+            mQueue.pop();
+        }
+        {
+            char name[64];
+            snprintf(name, sizeof(name), "waiting for frame %lu",
+                     static_cast<unsigned long>(entry.mFrameNum));
+            ATRACE_NAME(name);
+            mEngine->waitSync(entry.mSync, 0);
+        }
+    }
+}
+
 } // namespace gl
 } // namespace renderengine
 } // namespace android
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index b6fff33..b596242 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -17,8 +17,13 @@
 #ifndef SF_GLESRENDERENGINE_H_
 #define SF_GLESRENDERENGINE_H_
 
+#include <android-base/thread_annotations.h>
 #include <stdint.h>
 #include <sys/types.h>
+#include <condition_variable>
+#include <mutex>
+#include <queue>
+#include <thread>
 
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
@@ -119,6 +124,7 @@
                                        Protection protection);
     static EGLSurface createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
                                                    int hwcFormat, Protection protection);
+    bool waitSync(EGLSyncKHR sync, EGLint flags);
 
     // A data space is considered HDR data space if it has BT2020 color space
     // with PQ or HLG transfer function.
@@ -127,6 +133,10 @@
     // Defines the viewport, and sets the projection matrix to the projection
     // defined by the clip.
     void setViewportAndProjection(Rect viewport, Rect clip);
+    status_t bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer, sp<Fence> fence);
+    // Computes the cropping window for the layer and sets up cropping
+    // coordinates for the mesh.
+    FloatRect setupLayerCropping(const LayerSettings& layer, Mesh& mesh);
 
     EGLDisplay mEGLDisplay;
     EGLConfig mEGLConfig;
@@ -155,6 +165,8 @@
     mat4 mBt2020ToDisplayP3;
 
     bool mInProtectedContext = false;
+    // If set to true, then enables tracing flush() and finish() to systrace.
+    bool mTraceGpuCompletion = false;
     int32_t mFboHeight = 0;
 
     // Current dataspace of layer being rendered
@@ -166,6 +178,30 @@
     // Whether device supports color management, currently color management
     // supports sRGB, DisplayP3 color spaces.
     const bool mUseColorManagement = false;
+
+    class FlushTracer {
+    public:
+        FlushTracer(GLESRenderEngine* engine);
+        ~FlushTracer();
+        void queueSync(EGLSyncKHR sync) EXCLUDES(mMutex);
+
+        struct QueueEntry {
+            EGLSyncKHR mSync = nullptr;
+            uint64_t mFrameNum = 0;
+        };
+
+    private:
+        void loop();
+        GLESRenderEngine* const mEngine;
+        std::thread mThread;
+        std::condition_variable_any mCondition;
+        std::mutex mMutex;
+        std::queue<QueueEntry> mQueue GUARDED_BY(mMutex);
+        uint64_t mFramesQueued GUARDED_BY(mMutex) = 0;
+        bool mRunning = true;
+    };
+    friend class FlushTracer;
+    std::unique_ptr<FlushTracer> mFlushTracer;
 };
 
 } // namespace gl
diff --git a/libs/renderengine/include/renderengine/DisplaySettings.h b/libs/renderengine/include/renderengine/DisplaySettings.h
index 0c92353..af8de23 100644
--- a/libs/renderengine/include/renderengine/DisplaySettings.h
+++ b/libs/renderengine/include/renderengine/DisplaySettings.h
@@ -51,9 +51,10 @@
     // to the output dataspace.
     mat4 colorTransform = mat4();
 
-    // Region that will be cleared to (0, 0, 0, 0) prior to rendering.
-    // clearRegion will first be transformed by globalTransform so that it will
-    // be in the same coordinate space as the rendered layers.
+    // Region that will be cleared to (0, 0, 0, 1) prior to rendering.
+    // RenderEngine will transform the clearRegion passed in here, by
+    // globalTransform, so that it will be in the same coordinate space as the
+    // rendered layers.
     Region clearRegion = Region::INVALID_REGION;
 };
 
diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h
index 93abf5c..4d53205 100644
--- a/libs/renderengine/include/renderengine/LayerSettings.h
+++ b/libs/renderengine/include/renderengine/LayerSettings.h
@@ -19,6 +19,7 @@
 #include <math/mat4.h>
 #include <math/vec3.h>
 #include <renderengine/Texture.h>
+#include <ui/Fence.h>
 #include <ui/FloatRect.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/GraphicTypes.h>
@@ -36,6 +37,9 @@
     // ignored.
     sp<GraphicBuffer> buffer = nullptr;
 
+    // Fence that will fire when the buffer is ready to be bound.
+    sp<Fence> fence = nullptr;
+
     // Texture identifier to bind the external texture to.
     // TODO(alecmouri): This is GL-specific...make the type backend-agnostic.
     uint32_t textureName = 0;
@@ -49,6 +53,11 @@
     // Wheteher to use pre-multiplied alpha
     bool usePremultipliedAlpha = true;
 
+    // Override flag that alpha for each pixel in the buffer *must* be 1.0.
+    // LayerSettings::alpha is still used if isOpaque==true - this flag only
+    // overrides the alpha channel of the buffer.
+    bool isOpaque = false;
+
     // HDR color-space setting for Y410.
     bool isY410BT2020 = false;
 };
@@ -60,6 +69,20 @@
 
     // Transform matrix to apply to mesh coordinates.
     mat4 positionTransform = mat4();
+
+    // Radius of rounded corners, if greater than 0. Otherwise, this layer's
+    // corners are not rounded.
+    // Having corner radius will force GPU composition on the layer and its children, drawing it
+    // with a special shader. The shader will receive the radius and the crop rectangle as input,
+    // modifying the opacity of the destination texture, multiplying it by a number between 0 and 1.
+    // We query Layer#getRoundedCornerState() to retrieve the radius as well as the rounded crop
+    // rectangle to figure out how to apply the radius for this layer. The crop rectangle will be
+    // in local layer coordinate space, so we have to take the layer transform into account when
+    // walking up the tree.
+    float roundedCornersRadius = 0.0;
+
+    // Rectangle within which corners will be rounded.
+    FloatRect roundedCornersCrop = FloatRect();
 };
 
 // Descriptor of the source pixels for this layer.
@@ -81,15 +104,15 @@
     // Source pixels for this layer.
     PixelSource source = PixelSource();
 
-    // Alpha option to apply to the source pixels
+    // Alpha option to blend with the source pixels
     half alpha = half(0.0);
 
     // Color space describing how the source pixels should be interpreted.
-    ui::Dataspace sourceDataspace;
+    ui::Dataspace sourceDataspace = ui::Dataspace::UNKNOWN;
 
     // Additional layer-specific color transform to be applied before the global
     // transform.
-    mat4 colorTransform;
+    mat4 colorTransform = mat4();
 };
 
 } // namespace renderengine
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/libs/renderengine/include/renderengine/mock/Framebuffer.h
similarity index 63%
copy from services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
copy to libs/renderengine/include/renderengine/mock/Framebuffer.h
index fbfbc3f..7695885 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
+++ b/libs/renderengine/include/renderengine/mock/Framebuffer.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,23 +14,22 @@
  * limitations under the License.
  */
 
-#include "mock/RenderEngine/MockRenderEngine.h"
+#pragma once
 
-#include <ui/Region.h>
+#include <gmock/gmock.h>
+#include <renderengine/Framebuffer.h>
 
 namespace android {
 namespace renderengine {
 namespace mock {
 
-// Explicit default instantiation is recommended.
-RenderEngine::RenderEngine() = default;
-RenderEngine::~RenderEngine() = default;
+class Framebuffer : public renderengine::Framebuffer {
+public:
+    Framebuffer();
+    ~Framebuffer() override;
 
-Image::Image() = default;
-Image::~Image() = default;
-
-Framebuffer::Framebuffer() = default;
-Framebuffer::~Framebuffer() = default;
+    MOCK_METHOD2(setNativeWindowBuffer, bool(ANativeWindowBuffer*, bool));
+};
 
 } // namespace mock
 } // namespace renderengine
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/libs/renderengine/include/renderengine/mock/Image.h
similarity index 63%
copy from services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
copy to libs/renderengine/include/renderengine/mock/Image.h
index fbfbc3f..2b0eed1 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
+++ b/libs/renderengine/include/renderengine/mock/Image.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,23 +14,22 @@
  * limitations under the License.
  */
 
-#include "mock/RenderEngine/MockRenderEngine.h"
+#pragma once
 
-#include <ui/Region.h>
+#include <gmock/gmock.h>
+#include <renderengine/Image.h>
 
 namespace android {
 namespace renderengine {
 namespace mock {
 
-// Explicit default instantiation is recommended.
-RenderEngine::RenderEngine() = default;
-RenderEngine::~RenderEngine() = default;
+class Image : public renderengine::Image {
+public:
+    Image();
+    ~Image() override;
 
-Image::Image() = default;
-Image::~Image() = default;
-
-Framebuffer::Framebuffer() = default;
-Framebuffer::~Framebuffer() = default;
+    MOCK_METHOD2(setNativeWindowBuffer, bool(ANativeWindowBuffer* buffer, bool isProtected));
+};
 
 } // namespace mock
 } // namespace renderengine
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
similarity index 82%
rename from services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
rename to libs/renderengine/include/renderengine/mock/RenderEngine.h
index 81a7768..b4c7c96 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,13 +18,12 @@
 
 #include <gmock/gmock.h>
 #include <renderengine/DisplaySettings.h>
-#include <renderengine/Framebuffer.h>
-#include <renderengine/Image.h>
 #include <renderengine/LayerSettings.h>
 #include <renderengine/Mesh.h>
 #include <renderengine/RenderEngine.h>
 #include <renderengine/Texture.h>
 #include <ui/GraphicBuffer.h>
+#include <ui/Region.h>
 
 namespace android {
 namespace renderengine {
@@ -35,7 +34,7 @@
     RenderEngine();
     ~RenderEngine() override;
 
-    MOCK_METHOD0(createFramebuffer, std::unique_ptr<Framebuffer>());
+    MOCK_METHOD0(createFramebuffer, std::unique_ptr<renderengine::Framebuffer>());
     MOCK_METHOD0(createImage, std::unique_ptr<renderengine::Image>());
     MOCK_CONST_METHOD0(primeCache, void());
     MOCK_METHOD1(dump, void(std::string&));
@@ -69,9 +68,9 @@
     MOCK_METHOD1(setSourceDataSpace, void(ui::Dataspace));
     MOCK_METHOD1(setOutputDataSpace, void(ui::Dataspace));
     MOCK_METHOD1(setDisplayMaxLuminance, void(const float));
-    MOCK_METHOD1(bindFrameBuffer, status_t(Framebuffer*));
-    MOCK_METHOD1(unbindFrameBuffer, void(Framebuffer*));
-    MOCK_METHOD1(drawMesh, void(const Mesh&));
+    MOCK_METHOD1(bindFrameBuffer, status_t(renderengine::Framebuffer*));
+    MOCK_METHOD1(unbindFrameBuffer, void(renderengine::Framebuffer*));
+    MOCK_METHOD1(drawMesh, void(const renderengine::Mesh&));
     MOCK_CONST_METHOD0(getMaxTextureSize, size_t());
     MOCK_CONST_METHOD0(getMaxViewportDims, size_t());
     MOCK_CONST_METHOD0(isProtected, bool());
@@ -82,22 +81,6 @@
                           ANativeWindowBuffer*, base::unique_fd*));
 };
 
-class Image : public renderengine::Image {
-public:
-    Image();
-    ~Image() override;
-
-    MOCK_METHOD2(setNativeWindowBuffer, bool(ANativeWindowBuffer*, bool));
-};
-
-class Framebuffer : public renderengine::Framebuffer {
-public:
-    Framebuffer();
-    ~Framebuffer() override;
-
-    MOCK_METHOD2(setNativeWindowBuffer, bool(ANativeWindowBuffer*, bool));
-};
-
 } // namespace mock
 } // namespace renderengine
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/libs/renderengine/mock/Framebuffer.cpp
similarity index 70%
copy from services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
copy to libs/renderengine/mock/Framebuffer.cpp
index fbfbc3f..fbdcaab 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
+++ b/libs/renderengine/mock/Framebuffer.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,21 +14,14 @@
  * limitations under the License.
  */
 
-#include "mock/RenderEngine/MockRenderEngine.h"
-
-#include <ui/Region.h>
+#include <renderengine/mock/Framebuffer.h>
 
 namespace android {
 namespace renderengine {
 namespace mock {
 
-// Explicit default instantiation is recommended.
-RenderEngine::RenderEngine() = default;
-RenderEngine::~RenderEngine() = default;
-
-Image::Image() = default;
-Image::~Image() = default;
-
+// The Google Mock documentation recommends explicit non-header instantiations
+// for better compile time performance.
 Framebuffer::Framebuffer() = default;
 Framebuffer::~Framebuffer() = default;
 
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/libs/renderengine/mock/Image.cpp
similarity index 68%
copy from services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
copy to libs/renderengine/mock/Image.cpp
index fbfbc3f..57f4346 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
+++ b/libs/renderengine/mock/Image.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,24 +14,17 @@
  * limitations under the License.
  */
 
-#include "mock/RenderEngine/MockRenderEngine.h"
-
-#include <ui/Region.h>
+#include <renderengine/mock/Image.h>
 
 namespace android {
 namespace renderengine {
 namespace mock {
 
-// Explicit default instantiation is recommended.
-RenderEngine::RenderEngine() = default;
-RenderEngine::~RenderEngine() = default;
-
+// The Google Mock documentation recommends explicit non-header instantiations
+// for better compile time performance.
 Image::Image() = default;
 Image::~Image() = default;
 
-Framebuffer::Framebuffer() = default;
-Framebuffer::~Framebuffer() = default;
-
 } // namespace mock
 } // namespace renderengine
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/libs/renderengine/mock/RenderEngine.cpp
similarity index 71%
rename from services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
rename to libs/renderengine/mock/RenderEngine.cpp
index fbfbc3f..261636d 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
+++ b/libs/renderengine/mock/RenderEngine.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,24 +14,17 @@
  * limitations under the License.
  */
 
-#include "mock/RenderEngine/MockRenderEngine.h"
-
-#include <ui/Region.h>
+#include <renderengine/mock/RenderEngine.h>
 
 namespace android {
 namespace renderengine {
 namespace mock {
 
-// Explicit default instantiation is recommended.
+// The Google Mock documentation recommends explicit non-header instantiations
+// for better compile time performance.
 RenderEngine::RenderEngine() = default;
 RenderEngine::~RenderEngine() = default;
 
-Image::Image() = default;
-Image::~Image() = default;
-
-Framebuffer::Framebuffer() = default;
-Framebuffer::~Framebuffer() = default;
-
 } // namespace mock
 } // namespace renderengine
 } // namespace android
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index a0542dd..bef25a8 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -27,15 +27,30 @@
 namespace android {
 
 struct RenderEngineTest : public ::testing::Test {
-    sp<GraphicBuffer> allocateDefaultBuffer() {
+    static sp<GraphicBuffer> allocateDefaultBuffer() {
         return new GraphicBuffer(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT,
                                  HAL_PIXEL_FORMAT_RGBA_8888, 1,
-                                 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
+                                         GRALLOC_USAGE_HW_RENDER,
                                  "output");
     }
 
+    // Allocates a 1x1 buffer to fill with a solid color
+    static sp<GraphicBuffer> allocateSourceBuffer(uint32_t width, uint32_t height) {
+        return new GraphicBuffer(width, height, HAL_PIXEL_FORMAT_RGBA_8888, 1,
+                                 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
+                                         GRALLOC_USAGE_HW_TEXTURE,
+                                 "input");
+    }
+
     RenderEngineTest() { mBuffer = allocateDefaultBuffer(); }
 
+    ~RenderEngineTest() {
+        for (uint32_t texName : mTexNames) {
+            sRE->deleteTextures(1, &texName);
+        }
+    }
+
     void expectBufferColor(const Rect& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a,
                            uint8_t tolerance = 0) {
         uint8_t* pixels;
@@ -146,27 +161,112 @@
     void fillBufferCheckersRotate270();
 
     template <typename SourceVariant>
+    void fillBufferWithLayerTransform();
+
+    template <typename SourceVariant>
     void fillBufferLayerTransform();
 
     template <typename SourceVariant>
+    void fillBufferWithColorTransform();
+
+    template <typename SourceVariant>
     void fillBufferColorTransform();
 
+    template <typename SourceVariant>
+    void fillRedBufferWithRoundedCorners();
+
+    template <typename SourceVariant>
+    void fillBufferWithRoundedCorners();
+
+    void fillRedBufferTextureTransform();
+
+    void fillBufferTextureTransform();
+
+    void fillRedBufferWithPremultiplyAlpha();
+
+    void fillBufferWithPremultiplyAlpha();
+
+    void fillRedBufferWithoutPremultiplyAlpha();
+
+    void fillBufferWithoutPremultiplyAlpha();
+
+    void fillGreenColorBufferThenClearRegion();
+
+    void clearLeftRegion();
+
+    void fillBufferThenClearRegion();
+
     // Dumb hack to get aroud the fact that tear-down for renderengine isn't
     // well defined right now, so we can't create multiple instances
     static std::unique_ptr<renderengine::RenderEngine> sRE;
 
     sp<GraphicBuffer> mBuffer;
+
+    std::vector<uint32_t> mTexNames;
 };
 
 std::unique_ptr<renderengine::RenderEngine> RenderEngineTest::sRE =
         renderengine::RenderEngine::create(static_cast<int32_t>(ui::PixelFormat::RGBA_8888), 0);
 
 struct ColorSourceVariant {
-    static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b) {
+    static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b,
+                          RenderEngineTest* /*fixture*/) {
         layer.source.solidColor = half3(r, g, b);
     }
 };
 
+struct RelaxOpaqueBufferVariant {
+    static void setOpaqueBit(renderengine::LayerSettings& layer) {
+        layer.source.buffer.isOpaque = false;
+    }
+
+    static uint8_t getAlphaChannel() { return 255; }
+};
+
+struct ForceOpaqueBufferVariant {
+    static void setOpaqueBit(renderengine::LayerSettings& layer) {
+        layer.source.buffer.isOpaque = true;
+    }
+
+    static uint8_t getAlphaChannel() {
+        // The isOpaque bit will override the alpha channel, so this should be
+        // arbitrary.
+        return 10;
+    }
+};
+
+template <typename OpaquenessVariant>
+struct BufferSourceVariant {
+    static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b,
+                          RenderEngineTest* fixture) {
+        sp<GraphicBuffer> buf = RenderEngineTest::allocateSourceBuffer(1, 1);
+        uint32_t texName;
+        RenderEngineTest::sRE->genTextures(1, &texName);
+        fixture->mTexNames.push_back(texName);
+
+        uint8_t* pixels;
+        buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+                  reinterpret_cast<void**>(&pixels));
+
+        for (int32_t j = 0; j < buf->getHeight(); j++) {
+            uint8_t* iter = pixels + (buf->getStride() * j) * 4;
+            for (int32_t i = 0; i < buf->getWidth(); i++) {
+                iter[0] = uint8_t(r * 255);
+                iter[1] = uint8_t(g * 255);
+                iter[2] = uint8_t(b * 255);
+                iter[3] = OpaquenessVariant::getAlphaChannel();
+                iter += 4;
+            }
+        }
+
+        buf->unlock();
+
+        layer.source.buffer.buffer = buf;
+        layer.source.buffer.textureName = texName;
+        OpaquenessVariant::setOpaqueBit(layer);
+    }
+};
+
 template <typename SourceVariant>
 void RenderEngineTest::fillBuffer(half r, half g, half b, half a) {
     renderengine::DisplaySettings settings;
@@ -177,7 +277,7 @@
 
     renderengine::LayerSettings layer;
     layer.geometry.boundaries = fullscreenRect().toFloatRect();
-    SourceVariant::fillColor(layer, r, g, b);
+    SourceVariant::fillColor(layer, r, g, b, this);
     layer.alpha = a;
 
     layers.push_back(layer);
@@ -219,7 +319,7 @@
 
     renderengine::LayerSettings layer;
     layer.geometry.boundaries = offsetRectAtZero().toFloatRect();
-    SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f);
+    SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
     layer.alpha = 1.0f;
 
     layers.push_back(layer);
@@ -253,19 +353,19 @@
     renderengine::LayerSettings layerOne;
     Rect rectOne(0, 0, 1, 1);
     layerOne.geometry.boundaries = rectOne.toFloatRect();
-    SourceVariant::fillColor(layerOne, 1.0f, 0.0f, 0.0f);
+    SourceVariant::fillColor(layerOne, 1.0f, 0.0f, 0.0f, this);
     layerOne.alpha = 1.0f;
 
     renderengine::LayerSettings layerTwo;
     Rect rectTwo(0, 1, 1, 2);
     layerTwo.geometry.boundaries = rectTwo.toFloatRect();
-    SourceVariant::fillColor(layerTwo, 0.0f, 1.0f, 0.0f);
+    SourceVariant::fillColor(layerTwo, 0.0f, 1.0f, 0.0f, this);
     layerTwo.alpha = 1.0f;
 
     renderengine::LayerSettings layerThree;
     Rect rectThree(1, 0, 2, 1);
     layerThree.geometry.boundaries = rectThree.toFloatRect();
-    SourceVariant::fillColor(layerThree, 0.0f, 0.0f, 1.0f);
+    SourceVariant::fillColor(layerThree, 0.0f, 0.0f, 1.0f, this);
     layerThree.alpha = 1.0f;
 
     layers.push_back(layerOne);
@@ -343,7 +443,7 @@
 }
 
 template <typename SourceVariant>
-void RenderEngineTest::fillBufferLayerTransform() {
+void RenderEngineTest::fillBufferWithLayerTransform() {
     renderengine::DisplaySettings settings;
     settings.physicalDisplay = fullscreenRect();
     // Here logical space is 2x2
@@ -355,13 +455,18 @@
     layer.geometry.boundaries = Rect(1, 1).toFloatRect();
     // Translate one pixel diagonally
     layer.geometry.positionTransform = mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1);
+    SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
     layer.source.solidColor = half3(1.0f, 0.0f, 0.0f);
     layer.alpha = 1.0f;
 
     layers.push_back(layer);
 
     invokeDraw(settings, layers, mBuffer);
+}
 
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferLayerTransform() {
+    fillBufferWithLayerTransform<SourceVariant>();
     expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT / 2), 0, 0, 0, 0);
     expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 0);
     expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2,
@@ -370,7 +475,7 @@
 }
 
 template <typename SourceVariant>
-void RenderEngineTest::fillBufferColorTransform() {
+void RenderEngineTest::fillBufferWithColorTransform() {
     renderengine::DisplaySettings settings;
     settings.physicalDisplay = fullscreenRect();
     settings.clip = Rect(1, 1);
@@ -379,7 +484,7 @@
 
     renderengine::LayerSettings layer;
     layer.geometry.boundaries = Rect(1, 1).toFloatRect();
-    layer.source.solidColor = half3(0.5f, 0.25f, 0.125f);
+    SourceVariant::fillColor(layer, 0.5f, 0.25f, 0.125f, this);
     layer.alpha = 1.0f;
 
     // construct a fake color matrix
@@ -388,13 +493,208 @@
     // set red channel to red + green
     layer.colorTransform = mat4(1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
 
+    layer.alpha = 1.0f;
+    layer.geometry.boundaries = Rect(1, 1).toFloatRect();
+
     layers.push_back(layer);
 
     invokeDraw(settings, layers, mBuffer);
+}
 
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferColorTransform() {
+    fillBufferWithColorTransform<SourceVariant>();
     expectBufferColor(fullscreenRect(), 191, 0, 0, 255);
 }
 
+template <typename SourceVariant>
+void RenderEngineTest::fillRedBufferWithRoundedCorners() {
+    renderengine::DisplaySettings settings;
+    settings.physicalDisplay = fullscreenRect();
+    settings.clip = fullscreenRect();
+
+    std::vector<renderengine::LayerSettings> layers;
+
+    renderengine::LayerSettings layer;
+    layer.geometry.boundaries = fullscreenRect().toFloatRect();
+    layer.geometry.roundedCornersRadius = 5.0f;
+    layer.geometry.roundedCornersCrop = fullscreenRect().toFloatRect();
+    SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
+    layer.alpha = 1.0f;
+
+    layers.push_back(layer);
+
+    invokeDraw(settings, layers, mBuffer);
+}
+
+template <typename SourceVariant>
+void RenderEngineTest::fillBufferWithRoundedCorners() {
+    fillRedBufferWithRoundedCorners<SourceVariant>();
+    // Corners should be ignored...
+    expectBufferColor(Rect(0, 0, 1, 1), 0, 0, 0, 0);
+    expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH - 1, 0, DEFAULT_DISPLAY_WIDTH, 1), 0, 0, 0, 0);
+    expectBufferColor(Rect(0, DEFAULT_DISPLAY_HEIGHT - 1, 1, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 0);
+    expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH - 1, DEFAULT_DISPLAY_HEIGHT - 1,
+                           DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+                      0, 0, 0, 0);
+    // ...And the non-rounded portion should be red.
+    // Other pixels may be anti-aliased, so let's not check those.
+    expectBufferColor(Rect(5, 5, DEFAULT_DISPLAY_WIDTH - 5, DEFAULT_DISPLAY_HEIGHT - 5), 255, 0, 0,
+                      255);
+}
+
+void RenderEngineTest::fillRedBufferTextureTransform() {
+    renderengine::DisplaySettings settings;
+    settings.physicalDisplay = fullscreenRect();
+    settings.clip = Rect(1, 1);
+
+    std::vector<renderengine::LayerSettings> layers;
+
+    renderengine::LayerSettings layer;
+    // Here will allocate a checker board texture, but transform texture
+    // coordinates so that only the upper left is applied.
+    sp<GraphicBuffer> buf = allocateSourceBuffer(2, 2);
+    uint32_t texName;
+    RenderEngineTest::sRE->genTextures(1, &texName);
+    this->mTexNames.push_back(texName);
+
+    uint8_t* pixels;
+    buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+              reinterpret_cast<void**>(&pixels));
+    // Red top left, Green top right, Blue bottom left, Black bottom right
+    pixels[0] = 255;
+    pixels[1] = 0;
+    pixels[2] = 0;
+    pixels[3] = 255;
+    pixels[4] = 0;
+    pixels[5] = 255;
+    pixels[6] = 0;
+    pixels[7] = 255;
+    pixels[8] = 0;
+    pixels[9] = 0;
+    pixels[10] = 255;
+    pixels[11] = 255;
+    buf->unlock();
+
+    layer.source.buffer.buffer = buf;
+    layer.source.buffer.textureName = texName;
+    // Transform coordinates to only be inside the red quadrant.
+    layer.source.buffer.textureTransform = mat4::scale(vec4(0.2, 0.2, 1, 1));
+    layer.alpha = 1.0f;
+    layer.geometry.boundaries = Rect(1, 1).toFloatRect();
+
+    layers.push_back(layer);
+
+    invokeDraw(settings, layers, mBuffer);
+}
+
+void RenderEngineTest::fillBufferTextureTransform() {
+    fillRedBufferTextureTransform();
+    expectBufferColor(fullscreenRect(), 255, 0, 0, 255);
+}
+
+void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() {
+    renderengine::DisplaySettings settings;
+    settings.physicalDisplay = fullscreenRect();
+    // Here logical space is 1x1
+    settings.clip = Rect(1, 1);
+
+    std::vector<renderengine::LayerSettings> layers;
+
+    renderengine::LayerSettings layer;
+    sp<GraphicBuffer> buf = allocateSourceBuffer(1, 1);
+    uint32_t texName;
+    RenderEngineTest::sRE->genTextures(1, &texName);
+    this->mTexNames.push_back(texName);
+
+    uint8_t* pixels;
+    buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+              reinterpret_cast<void**>(&pixels));
+    pixels[0] = 255;
+    pixels[1] = 0;
+    pixels[2] = 0;
+    pixels[3] = 255;
+    buf->unlock();
+
+    layer.source.buffer.buffer = buf;
+    layer.source.buffer.textureName = texName;
+    layer.source.buffer.usePremultipliedAlpha = true;
+    layer.alpha = 0.5f;
+    layer.geometry.boundaries = Rect(1, 1).toFloatRect();
+
+    layers.push_back(layer);
+
+    invokeDraw(settings, layers, mBuffer);
+}
+
+void RenderEngineTest::fillBufferWithPremultiplyAlpha() {
+    fillRedBufferWithPremultiplyAlpha();
+    expectBufferColor(fullscreenRect(), 128, 0, 0, 128);
+}
+
+void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() {
+    renderengine::DisplaySettings settings;
+    settings.physicalDisplay = fullscreenRect();
+    // Here logical space is 1x1
+    settings.clip = Rect(1, 1);
+
+    std::vector<renderengine::LayerSettings> layers;
+
+    renderengine::LayerSettings layer;
+    sp<GraphicBuffer> buf = allocateSourceBuffer(1, 1);
+    uint32_t texName;
+    RenderEngineTest::sRE->genTextures(1, &texName);
+    this->mTexNames.push_back(texName);
+
+    uint8_t* pixels;
+    buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+              reinterpret_cast<void**>(&pixels));
+    pixels[0] = 255;
+    pixels[1] = 0;
+    pixels[2] = 0;
+    pixels[3] = 255;
+    buf->unlock();
+
+    layer.source.buffer.buffer = buf;
+    layer.source.buffer.textureName = texName;
+    layer.source.buffer.usePremultipliedAlpha = false;
+    layer.alpha = 0.5f;
+    layer.geometry.boundaries = Rect(1, 1).toFloatRect();
+
+    layers.push_back(layer);
+
+    invokeDraw(settings, layers, mBuffer);
+}
+
+void RenderEngineTest::fillBufferWithoutPremultiplyAlpha() {
+    fillRedBufferWithoutPremultiplyAlpha();
+    expectBufferColor(fullscreenRect(), 128, 0, 0, 64, 1);
+}
+
+void RenderEngineTest::clearLeftRegion() {
+    renderengine::DisplaySettings settings;
+    settings.physicalDisplay = fullscreenRect();
+    // Here logical space is 4x4
+    settings.clip = Rect(4, 4);
+    settings.globalTransform = mat4::scale(vec4(2, 4, 0, 1));
+    settings.clearRegion = Region(Rect(1, 1));
+    std::vector<renderengine::LayerSettings> layers;
+    // dummy layer, without bounds should not render anything
+    renderengine::LayerSettings layer;
+    layers.push_back(layer);
+    invokeDraw(settings, layers, mBuffer);
+}
+
+void RenderEngineTest::fillBufferThenClearRegion() {
+    fillGreenBuffer<ColorSourceVariant>();
+    // Reuse mBuffer
+    clearLeftRegion();
+    expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 255);
+    expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
+                           DEFAULT_DISPLAY_HEIGHT),
+                      0, 255, 0, 255);
+}
+
 TEST_F(RenderEngineTest, drawLayers_noLayersToDraw) {
     drawEmptyLayers();
 }
@@ -443,4 +743,120 @@
     fillBufferLayerTransform<ColorSourceVariant>();
 }
 
+TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_colorSource) {
+    fillBufferWithRoundedCorners<ColorSourceVariant>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillRedBuffer_opaqueBufferSource) {
+    fillRedBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillGreenBuffer_opaqueBufferSource) {
+    fillGreenBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBlueBuffer_opaqueBufferSource) {
+    fillBlueBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillRedTransparentBuffer_opaqueBufferSource) {
+    fillRedTransparentBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_opaqueBufferSource) {
+    fillBufferPhysicalOffset<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_opaqueBufferSource) {
+    fillBufferCheckersRotate0<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_opaqueBufferSource) {
+    fillBufferCheckersRotate90<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_opaqueBufferSource) {
+    fillBufferCheckersRotate180<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_opaqueBufferSource) {
+    fillBufferCheckersRotate270<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferLayerTransform_opaqueBufferSource) {
+    fillBufferLayerTransform<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransform_opaqueBufferSource) {
+    fillBufferLayerTransform<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_opaqueBufferSource) {
+    fillBufferWithRoundedCorners<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillRedBuffer_bufferSource) {
+    fillRedBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillGreenBuffer_bufferSource) {
+    fillGreenBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBlueBuffer_bufferSource) {
+    fillBlueBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillRedTransparentBuffer_bufferSource) {
+    fillRedTransparentBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferPhysicalOffset_bufferSource) {
+    fillBufferPhysicalOffset<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate0_bufferSource) {
+    fillBufferCheckersRotate0<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate90_bufferSource) {
+    fillBufferCheckersRotate90<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate180_bufferSource) {
+    fillBufferCheckersRotate180<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferCheckersRotate270_bufferSource) {
+    fillBufferCheckersRotate270<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferLayerTransform_bufferSource) {
+    fillBufferLayerTransform<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferColorTransform_bufferSource) {
+    fillBufferLayerTransform<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferRoundedCorners_bufferSource) {
+    fillBufferWithRoundedCorners<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferTextureTransform) {
+    fillBufferTextureTransform();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBuffer_premultipliesAlpha) {
+    fillBufferWithPremultiplyAlpha();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBuffer_withoutPremultiplyingAlpha) {
+    fillBufferWithoutPremultiplyAlpha();
+}
+
+TEST_F(RenderEngineTest, drawLayers_fillBufferThenClearRegion) {
+    fillBufferThenClearRegion();
+}
+
 } // namespace android
diff --git a/libs/sensorprivacy/SensorPrivacyManager.cpp b/libs/sensorprivacy/SensorPrivacyManager.cpp
index 1da79a0..f973cba 100644
--- a/libs/sensorprivacy/SensorPrivacyManager.cpp
+++ b/libs/sensorprivacy/SensorPrivacyManager.cpp
@@ -85,4 +85,22 @@
     return false;
 }
 
+status_t SensorPrivacyManager::linkToDeath(const sp<IBinder::DeathRecipient>& recipient)
+{
+    sp<hardware::ISensorPrivacyManager> service = getService();
+    if (service != nullptr) {
+        return IInterface::asBinder(service)->linkToDeath(recipient);
+    }
+    return INVALID_OPERATION;
+}
+
+status_t SensorPrivacyManager::unlinkToDeath(const sp<IBinder::DeathRecipient>& recipient)
+{
+    sp<hardware::ISensorPrivacyManager> service = getService();
+    if (service != nullptr) {
+        return IInterface::asBinder(service)->unlinkToDeath(recipient);
+    }
+    return INVALID_OPERATION;
+}
+
 }; // namespace android
diff --git a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
index 8826595..2546a68 100644
--- a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
+++ b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
@@ -34,6 +34,9 @@
     void removeSensorPrivacyListener(const sp<hardware::ISensorPrivacyListener>& listener);
     bool isSensorPrivacyEnabled();
 
+    status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient);
+    status_t unlinkToDeath(const sp<IBinder::DeathRecipient>& recipient);
+
 private:
     Mutex mLock;
     sp<hardware::ISensorPrivacyManager> mService;
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 956465c..d089bf6 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -77,6 +77,7 @@
     ],
 
     shared_libs: [
+        "android.frameworks.bufferhub@1.0",
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.2",
         "android.hardware.graphics.mapper@2.0",
@@ -93,7 +94,6 @@
         "libutils",
         "libutilscallstack",
         "liblog",
-        "libpdx_default_transport",  // TODO(b/112338294): Remove this once BufferHub moved to use Binder.
     ],
 
     export_shared_lib_headers: [
@@ -121,6 +121,7 @@
                 "libnativewindow_headers",
             ],
             exclude_shared_libs: [
+                "android.frameworks.bufferhub@1.0",
                 "libpdx_default_transport",
             ],
         },
@@ -148,9 +149,6 @@
         "libhardware_headers",
         "libui_headers",
     ],
-
-    // TODO(b/117568153): Temporarily opt out using libcrt.
-    no_libcrt: true,
 }
 
 cc_library_headers {
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index 0582e1a..6310f29 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -14,151 +14,190 @@
  * limitations under the License.
  */
 
-// We would eliminate the clang warnings introduced by libdpx.
-// TODO(b/112338294): Remove those once BufferHub moved to use Binder
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wdouble-promotion"
-#pragma clang diagnostic ignored "-Wgnu-case-range"
-#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
-#pragma clang diagnostic ignored "-Winconsistent-missing-destructor-override"
-#pragma clang diagnostic ignored "-Wnested-anon-types"
-#pragma clang diagnostic ignored "-Wpacked"
-#pragma clang diagnostic ignored "-Wshadow"
-#pragma clang diagnostic ignored "-Wsign-conversion"
-#pragma clang diagnostic ignored "-Wswitch-enum"
-#pragma clang diagnostic ignored "-Wundefined-func-template"
-#pragma clang diagnostic ignored "-Wunused-template"
-#pragma clang diagnostic ignored "-Wweak-vtables"
-#include <pdx/default_transport/client_channel.h>
-#include <pdx/default_transport/client_channel_factory.h>
-#include <pdx/file_handle.h>
-#include <private/dvr/bufferhub_rpc.h>
-#pragma clang diagnostic pop
-
 #include <poll.h>
 
 #include <android-base/unique_fd.h>
+#include <android/frameworks/bufferhub/1.0/IBufferHub.h>
+#include <log/log.h>
 #include <ui/BufferHubBuffer.h>
 #include <ui/BufferHubDefs.h>
+#include <utils/Trace.h>
 
-using android::base::unique_fd;
-using android::dvr::BufferTraits;
-using android::dvr::DetachedBufferRPC;
-using android::dvr::NativeHandleWrapper;
-
-// TODO(b/112338294): Remove PDX dependencies from libui.
-using android::pdx::LocalChannelHandle;
-using android::pdx::LocalHandle;
-using android::pdx::Status;
-using android::pdx::default_transport::ClientChannel;
-using android::pdx::default_transport::ClientChannelFactory;
+using ::android::base::unique_fd;
+using ::android::BufferHubDefs::AnyClientAcquired;
+using ::android::BufferHubDefs::AnyClientGained;
+using ::android::BufferHubDefs::IsClientAcquired;
+using ::android::BufferHubDefs::IsClientGained;
+using ::android::BufferHubDefs::IsClientPosted;
+using ::android::BufferHubDefs::IsClientReleased;
+using ::android::frameworks::bufferhub::V1_0::BufferHubStatus;
+using ::android::frameworks::bufferhub::V1_0::BufferTraits;
+using ::android::frameworks::bufferhub::V1_0::IBufferClient;
+using ::android::frameworks::bufferhub::V1_0::IBufferHub;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::graphics::common::V1_2::HardwareBufferDescription;
 
 namespace android {
 
-namespace {
-
-// TODO(b/112338294): Remove this string literal after refactoring BufferHub
-// to use Binder.
-static constexpr char kBufferHubClientPath[] = "system/buffer_hub/client";
-
-using BufferHubDefs::AnyClientAcquired;
-using BufferHubDefs::AnyClientGained;
-using BufferHubDefs::AnyClientPosted;
-using BufferHubDefs::IsClientAcquired;
-using BufferHubDefs::IsClientGained;
-using BufferHubDefs::IsClientPosted;
-using BufferHubDefs::IsClientReleased;
-using BufferHubDefs::kHighBitsMask;
-
-} // namespace
-
-BufferHubClient::BufferHubClient() : Client(ClientChannelFactory::Create(kBufferHubClientPath)) {}
-
-BufferHubClient::BufferHubClient(LocalChannelHandle mChannelHandle)
-      : Client(ClientChannel::Create(std::move(mChannelHandle))) {}
-
-BufferHubClient::~BufferHubClient() {}
-
-bool BufferHubClient::IsValid() const {
-    return IsConnected() && GetChannelHandle().valid();
+std::unique_ptr<BufferHubBuffer> BufferHubBuffer::Create(uint32_t width, uint32_t height,
+                                                         uint32_t layerCount, uint32_t format,
+                                                         uint64_t usage, size_t userMetadataSize) {
+    auto buffer = std::unique_ptr<BufferHubBuffer>(
+            new BufferHubBuffer(width, height, layerCount, format, usage, userMetadataSize));
+    return buffer->IsValid() ? std::move(buffer) : nullptr;
 }
 
-LocalChannelHandle BufferHubClient::TakeChannelHandle() {
-    if (IsConnected()) {
-        return std::move(GetChannelHandle());
-    } else {
-        return {};
+std::unique_ptr<BufferHubBuffer> BufferHubBuffer::Import(const native_handle_t* token) {
+    if (token == nullptr) {
+        ALOGE("%s: token cannot be nullptr!", __FUNCTION__);
+        return nullptr;
     }
+
+    auto buffer = std::unique_ptr<BufferHubBuffer>(new BufferHubBuffer(token));
+    return buffer->IsValid() ? std::move(buffer) : nullptr;
 }
 
 BufferHubBuffer::BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount,
-                                 uint32_t format, uint64_t usage, size_t mUserMetadataSize) {
+                                 uint32_t format, uint64_t usage, size_t userMetadataSize) {
     ATRACE_CALL();
-    ALOGD("%s: width=%u height=%u layerCount=%u, format=%u usage=%" PRIx64 " mUserMetadataSize=%zu",
-          __FUNCTION__, width, height, layerCount, format, usage, mUserMetadataSize);
+    ALOGD("%s: width=%u height=%u layerCount=%u, format=%u "
+          "usage=%" PRIx64 " mUserMetadataSize=%zu",
+          __FUNCTION__, width, height, layerCount, format, usage, userMetadataSize);
 
-    auto status =
-            mClient.InvokeRemoteMethod<DetachedBufferRPC::Create>(width, height, layerCount, format,
-                                                                  usage, mUserMetadataSize);
-    if (!status) {
-        ALOGE("%s: Failed to create detached buffer: %s", __FUNCTION__,
-              status.GetErrorMessage().c_str());
-        mClient.Close(-status.error());
+    sp<IBufferHub> bufferhub = IBufferHub::getService();
+    if (bufferhub.get() == nullptr) {
+        ALOGE("%s: BufferHub service not found!", __FUNCTION__);
+        return;
     }
 
-    const int ret = ImportGraphicBuffer();
-    if (ret < 0) {
-        ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-ret));
-        mClient.Close(ret);
+    AHardwareBuffer_Desc aDesc = {width, height,         layerCount,   format,
+                                  usage, /*stride=*/0UL, /*rfu0=*/0UL, /*rfu1=*/0ULL};
+    HardwareBufferDescription desc;
+    memcpy(&desc, &aDesc, sizeof(HardwareBufferDescription));
+
+    BufferHubStatus ret;
+    sp<IBufferClient> client;
+    BufferTraits bufferTraits;
+    IBufferHub::allocateBuffer_cb alloc_cb = [&](const auto& status, const auto& outClient,
+                                                 const auto& traits) {
+        ret = status;
+        client = std::move(outClient);
+        bufferTraits = std::move(traits);
+    };
+
+    if (!bufferhub->allocateBuffer(desc, static_cast<uint32_t>(userMetadataSize), alloc_cb)
+                 .isOk()) {
+        ALOGE("%s: allocateBuffer transaction failed!", __FUNCTION__);
+        return;
+    } else if (ret != BufferHubStatus::NO_ERROR) {
+        ALOGE("%s: allocateBuffer failed with error %u.", __FUNCTION__, ret);
+        return;
+    } else if (client == nullptr) {
+        ALOGE("%s: allocateBuffer got null BufferClient.", __FUNCTION__);
+        return;
+    }
+
+    const int importRet = initWithBufferTraits(bufferTraits);
+    if (importRet < 0) {
+        ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-importRet));
+        client->close();
+    }
+    mBufferClient = std::move(client);
+}
+
+BufferHubBuffer::BufferHubBuffer(const native_handle_t* token) {
+    sp<IBufferHub> bufferhub = IBufferHub::getService();
+    if (bufferhub.get() == nullptr) {
+        ALOGE("%s: BufferHub service not found!", __FUNCTION__);
+        return;
+    }
+
+    BufferHubStatus ret;
+    sp<IBufferClient> client;
+    BufferTraits bufferTraits;
+    IBufferHub::importBuffer_cb import_cb = [&](const auto& status, const auto& outClient,
+                                                const auto& traits) {
+        ret = status;
+        client = std::move(outClient);
+        bufferTraits = std::move(traits);
+    };
+
+    // hidl_handle(native_handle_t*) simply creates a raw pointer reference withouth ownership
+    // transfer.
+    if (!bufferhub->importBuffer(hidl_handle(token), import_cb).isOk()) {
+        ALOGE("%s: importBuffer transaction failed!", __FUNCTION__);
+        return;
+    } else if (ret != BufferHubStatus::NO_ERROR) {
+        ALOGE("%s: importBuffer failed with error %u.", __FUNCTION__, ret);
+        return;
+    } else if (client == nullptr) {
+        ALOGE("%s: importBuffer got null BufferClient.", __FUNCTION__);
+        return;
+    }
+
+    const int importRet = initWithBufferTraits(bufferTraits);
+    if (importRet < 0) {
+        ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-importRet));
+        client->close();
+    }
+    mBufferClient = std::move(client);
+}
+
+BufferHubBuffer::~BufferHubBuffer() {
+    // Close buffer client to avoid possible race condition: user could first duplicate and hold
+    // token with the original buffer gone, and then try to import the token. The close function
+    // will explicitly invalidate the token to avoid this.
+    if (mBufferClient != nullptr) {
+        if (!mBufferClient->close().isOk()) {
+            ALOGE("%s: close BufferClient transaction failed!", __FUNCTION__);
+        }
     }
 }
 
-BufferHubBuffer::BufferHubBuffer(LocalChannelHandle mChannelHandle)
-      : mClient(std::move(mChannelHandle)) {
-    const int ret = ImportGraphicBuffer();
-    if (ret < 0) {
-        ALOGE("%s: Failed to import buffer: %s", __FUNCTION__, strerror(-ret));
-        mClient.Close(ret);
-    }
-}
-
-int BufferHubBuffer::ImportGraphicBuffer() {
+int BufferHubBuffer::initWithBufferTraits(const BufferTraits& bufferTraits) {
     ATRACE_CALL();
 
-    auto status = mClient.InvokeRemoteMethod<DetachedBufferRPC::Import>();
-    if (!status) {
-        ALOGE("%s: Failed to import GraphicBuffer: %s", __FUNCTION__,
-              status.GetErrorMessage().c_str());
-        return -status.error();
+    if (bufferTraits.bufferInfo.getNativeHandle() == nullptr) {
+        ALOGE("%s: missing buffer info handle.", __FUNCTION__);
+        return -EINVAL;
     }
 
-    BufferTraits<LocalHandle> bufferTraits = status.take();
-    if (bufferTraits.id() < 0) {
-        ALOGE("%s: Received an invalid id!", __FUNCTION__);
-        return -EIO;
+    if (bufferTraits.bufferHandle.getNativeHandle() == nullptr) {
+        ALOGE("%s: missing gralloc handle.", __FUNCTION__);
+        return -EINVAL;
     }
 
-    // Stash the buffer id to replace the value in mId.
-    const int bufferId = bufferTraits.id();
+    int bufferId = bufferTraits.bufferInfo->data[1];
+    if (bufferId < 0) {
+        ALOGE("%s: Received an invalid (negative) id!", __FUNCTION__);
+        return -EINVAL;
+    }
 
-    // Import the metadata.
-    LocalHandle metadataHandle = bufferTraits.take_metadata_handle();
-    unique_fd metadataFd(metadataHandle.Release());
-    mMetadata = BufferHubMetadata::Import(std::move(metadataFd));
+    uint32_t clientBitMask;
+    memcpy(&clientBitMask, &bufferTraits.bufferInfo->data[2], sizeof(clientBitMask));
+    if (clientBitMask == 0U) {
+        ALOGE("%s: Received a invalid client state mask!", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    // Import the metadata. Dup since hidl_handle owns the fd
+    unique_fd ashmemFd(fcntl(bufferTraits.bufferInfo->data[0], F_DUPFD_CLOEXEC, 0));
+    mMetadata = BufferHubMetadata::Import(std::move(ashmemFd));
 
     if (!mMetadata.IsValid()) {
         ALOGE("%s: invalid metadata.", __FUNCTION__);
-        return -ENOMEM;
+        return -EINVAL;
     }
 
-    if (mMetadata.metadata_size() != bufferTraits.metadata_size()) {
-        ALOGE("%s: metadata buffer too small: %zu, expected: %" PRIu64 ".", __FUNCTION__,
-              mMetadata.metadata_size(), bufferTraits.metadata_size());
-        return -ENOMEM;
+    uint32_t userMetadataSize;
+    memcpy(&userMetadataSize, &bufferTraits.bufferInfo->data[3], sizeof(userMetadataSize));
+    if (mMetadata.user_metadata_size() != userMetadataSize) {
+        ALOGE("%s: user metadata size not match: expected %u, actual %zu.", __FUNCTION__,
+              userMetadataSize, mMetadata.user_metadata_size());
+        return -EINVAL;
     }
 
-    size_t metadataSize = static_cast<size_t>(bufferTraits.metadata_size());
+    size_t metadataSize = static_cast<size_t>(mMetadata.metadata_size());
     if (metadataSize < BufferHubDefs::kMetadataHeaderSize) {
         ALOGE("%s: metadata too small: %zu", __FUNCTION__, metadataSize);
         return -EINVAL;
@@ -179,24 +218,14 @@
 
     // Import the buffer: We only need to hold on the native_handle_t here so that
     // GraphicBuffer instance can be created in future.
-    mBufferHandle = bufferTraits.take_buffer_handle();
+    mBufferHandle = std::move(bufferTraits.bufferHandle);
+    memcpy(&mBufferDesc, &bufferTraits.bufferDesc, sizeof(AHardwareBuffer_Desc));
 
-    // Populate buffer desc based on buffer traits.
-    mBufferDesc.width = bufferTraits.width();
-    mBufferDesc.height = bufferTraits.height();
-    mBufferDesc.layers = bufferTraits.layer_count();
-    mBufferDesc.format = bufferTraits.format();
-    mBufferDesc.usage = bufferTraits.usage();
-    mBufferDesc.stride = bufferTraits.stride();
-    mBufferDesc.rfu0 = 0U;
-    mBufferDesc.rfu1 = 0U;
-
-    // If all imports succeed, replace the previous buffer and id.
     mId = bufferId;
-    mClientStateMask = bufferTraits.client_state_mask();
+    mClientStateMask = clientBitMask;
 
     // TODO(b/112012161) Set up shared fences.
-    ALOGD("%s: id=%d, buffer_state=%" PRIx32 ".", __FUNCTION__, id(),
+    ALOGD("%s: id=%d, buffer_state=%" PRIx32 ".", __FUNCTION__, mId,
           buffer_state_->load(std::memory_order_acquire));
     return 0;
 }
@@ -226,8 +255,7 @@
 
 int BufferHubBuffer::Post() {
     uint32_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
-    uint32_t current_active_clients_bit_mask = 0U;
-    uint32_t updated_buffer_state = 0U;
+    uint32_t updated_buffer_state = (~mClientStateMask) & BufferHubDefs::kHighBitsMask;
     do {
         if (!IsClientGained(current_buffer_state, mClientStateMask)) {
             ALOGE("%s: Cannot post a buffer that is not gained by this client. buffer_id=%d "
@@ -236,9 +264,7 @@
             return -EBUSY;
         }
         // Set the producer client buffer state to released, other clients' buffer state to posted.
-        current_active_clients_bit_mask = active_clients_bit_mask_->load(std::memory_order_acquire);
-        updated_buffer_state =
-                current_active_clients_bit_mask & (~mClientStateMask) & kHighBitsMask;
+        // Post to all existing and non-existing clients.
     } while (!buffer_state_->compare_exchange_weak(current_buffer_state, updated_buffer_state,
                                                    std::memory_order_acq_rel,
                                                    std::memory_order_acquire));
@@ -287,24 +313,37 @@
     return 0;
 }
 
-int BufferHubBuffer::Poll(int timeoutMs) {
-    ATRACE_CALL();
-
-    pollfd p = {mClient.event_fd(), POLLIN, 0};
-    return poll(&p, 1, timeoutMs);
+bool BufferHubBuffer::IsValid() const {
+    // TODO(b/68770788): check eventFd once implemented
+    return mBufferHandle.getNativeHandle() != nullptr && mId >= 0 && mClientStateMask != 0U &&
+            mMetadata.IsValid() && mBufferClient != nullptr;
 }
 
-Status<LocalChannelHandle> BufferHubBuffer::Duplicate() {
-    ATRACE_CALL();
-    ALOGD("%s: id=%d.", __FUNCTION__, mId);
-
-    auto statusOrHandle = mClient.InvokeRemoteMethod<DetachedBufferRPC::Duplicate>();
-
-    if (!statusOrHandle.ok()) {
-        ALOGE("%s: Failed to duplicate buffer (id=%d): %s.", __FUNCTION__, mId,
-              statusOrHandle.GetErrorMessage().c_str());
+native_handle_t* BufferHubBuffer::Duplicate() {
+    if (mBufferClient == nullptr) {
+        ALOGE("%s: missing BufferClient!", __FUNCTION__);
+        return nullptr;
     }
-    return statusOrHandle;
+
+    hidl_handle token;
+    BufferHubStatus ret;
+    IBufferClient::duplicate_cb dup_cb = [&](const auto& outToken, const auto& status) {
+        token = std::move(outToken);
+        ret = status;
+    };
+
+    if (!mBufferClient->duplicate(dup_cb).isOk()) {
+        ALOGE("%s: duplicate transaction failed!", __FUNCTION__);
+        return nullptr;
+    } else if (ret != BufferHubStatus::NO_ERROR) {
+        ALOGE("%s: duplicate failed with error %u.", __FUNCTION__, ret);
+        return nullptr;
+    } else if (token.getNativeHandle() == nullptr) {
+        ALOGE("%s: duplicate got null token.", __FUNCTION__);
+        return nullptr;
+    }
+
+    return native_handle_clone(token.getNativeHandle());
 }
 
 } // namespace android
diff --git a/libs/ui/include/ui/BufferHubBuffer.h b/libs/ui/include/ui/BufferHubBuffer.h
index 90dd391..c6a4a23 100644
--- a/libs/ui/include/ui/BufferHubBuffer.h
+++ b/libs/ui/include/ui/BufferHubBuffer.h
@@ -17,73 +17,43 @@
 #ifndef ANDROID_BUFFER_HUB_BUFFER_H_
 #define ANDROID_BUFFER_HUB_BUFFER_H_
 
-// We would eliminate the clang warnings introduced by libdpx.
-// TODO(b/112338294): Remove those once BufferHub moved to use Binder
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wdouble-promotion"
-#pragma clang diagnostic ignored "-Wgnu-case-range"
-#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
-#pragma clang diagnostic ignored "-Winconsistent-missing-destructor-override"
-#pragma clang diagnostic ignored "-Wnested-anon-types"
-#pragma clang diagnostic ignored "-Wpacked"
-#pragma clang diagnostic ignored "-Wshadow"
-#pragma clang diagnostic ignored "-Wsign-conversion"
-#pragma clang diagnostic ignored "-Wswitch-enum"
-#pragma clang diagnostic ignored "-Wundefined-func-template"
-#pragma clang diagnostic ignored "-Wunused-template"
-#pragma clang diagnostic ignored "-Wweak-vtables"
-#include <pdx/client.h>
-#include <private/dvr/native_handle_wrapper.h>
-#pragma clang diagnostic pop
-
+#include <android/frameworks/bufferhub/1.0/IBufferClient.h>
 #include <android/hardware_buffer.h>
+#include <cutils/native_handle.h>
 #include <ui/BufferHubDefs.h>
 #include <ui/BufferHubMetadata.h>
 
 namespace android {
 
-class BufferHubClient : public pdx::Client {
-public:
-    BufferHubClient();
-    virtual ~BufferHubClient();
-    explicit BufferHubClient(pdx::LocalChannelHandle mChannelHandle);
-
-    bool IsValid() const;
-    pdx::LocalChannelHandle TakeChannelHandle();
-
-    using pdx::Client::Close;
-    using pdx::Client::event_fd;
-    using pdx::Client::GetChannel;
-    using pdx::Client::InvokeRemoteMethod;
-};
-
 class BufferHubBuffer {
 public:
-    // Allocates a standalone BufferHubBuffer not associated with any producer consumer set.
+    // Allocates a standalone BufferHubBuffer.
     static std::unique_ptr<BufferHubBuffer> Create(uint32_t width, uint32_t height,
                                                    uint32_t layerCount, uint32_t format,
-                                                   uint64_t usage, size_t userMetadataSize) {
-        return std::unique_ptr<BufferHubBuffer>(
-                new BufferHubBuffer(width, height, layerCount, format, usage, userMetadataSize));
-    }
+                                                   uint64_t usage, size_t userMetadataSize);
 
-    // Imports the given channel handle to a BufferHubBuffer, taking ownership.
-    static std::unique_ptr<BufferHubBuffer> Import(pdx::LocalChannelHandle mChannelHandle) {
-        return std::unique_ptr<BufferHubBuffer>(new BufferHubBuffer(std::move(mChannelHandle)));
-    }
+    // Imports the given token to a BufferHubBuffer. Not taking ownership of the token. Caller
+    // should close and destroy the token after calling this function regardless of output.
+    // TODO(b/122543147): use a movable wrapper for token
+    static std::unique_ptr<BufferHubBuffer> Import(const native_handle_t* token);
 
     BufferHubBuffer(const BufferHubBuffer&) = delete;
     void operator=(const BufferHubBuffer&) = delete;
 
+    virtual ~BufferHubBuffer();
+
     // Gets ID of the buffer client. All BufferHubBuffer clients derived from the same buffer in
-    // bufferhubd share the same buffer id.
+    // BufferHub share the same buffer id.
     int id() const { return mId; }
 
-    // Returns the buffer description, which is guaranteed to be faithful values from bufferhubd.
+    // Returns the buffer description, which is guaranteed to be faithful values from BufferHub.
     const AHardwareBuffer_Desc& desc() const { return mBufferDesc; }
 
-    const native_handle_t* DuplicateHandle() { return mBufferHandle.DuplicateHandle(); }
+    // Duplicate the underlying Gralloc buffer handle. Caller is responsible to free the handle
+    // after use.
+    native_handle_t* DuplicateHandle() {
+        return native_handle_clone(mBufferHandle.getNativeHandle());
+    }
 
     // Returns the current value of MetadataHeader::buffer_state.
     uint32_t buffer_state() {
@@ -96,12 +66,12 @@
 
     size_t user_metadata_size() const { return mMetadata.user_metadata_size(); }
 
-    // Returns true if the buffer holds an open PDX channels towards bufferhubd.
-    bool IsConnected() const { return mClient.IsValid(); }
+    // Returns true if the BufferClient is still alive.
+    bool IsConnected() const { return mBufferClient->ping().isOk(); }
 
-    // Returns true if the buffer holds an valid native buffer handle that's availble for the client
-    // to read from and/or write into.
-    bool IsValid() const { return mBufferHandle.IsValid(); }
+    // Returns true if the buffer is valid: non-null buffer handle, valid id, valid client bit mask,
+    // valid metadata and valid buffer client
+    bool IsValid() const;
 
     // Gains the buffer for exclusive write permission. Read permission is implied once a buffer is
     // gained.
@@ -124,33 +94,24 @@
     // current cycle of the usage of the buffer.
     int Release();
 
-    // Returns the event mask for all the events that are pending on this buffer (see sys/poll.h for
-    // all possible bits).
-    pdx::Status<int> GetEventMask(int events) {
-        if (auto* channel = mClient.GetChannel()) {
-            return channel->GetEventMask(events);
-        } else {
-            return pdx::ErrorStatus(EINVAL);
-        }
-    }
-
-    // Polls the fd for |timeoutMs| milliseconds (-1 for infinity).
-    int Poll(int timeoutMs);
-
-    // Creates a BufferHubBuffer client from an existing one. The new client will
-    // share the same underlying gralloc buffer and ashmem region for metadata.
-    pdx::Status<pdx::LocalChannelHandle> Duplicate();
+    // Creates a token that stands for this BufferHubBuffer client and could be used for Import to
+    // create another BufferHubBuffer. The new BufferHubBuffer will share the same underlying
+    // gralloc buffer and ashmem region for metadata. Note that the caller owns the token and
+    // should free it after use.
+    // Returns a valid token on success, nullptr on failure.
+    // TODO(b/122543147): use a movable wrapper for token
+    native_handle_t* Duplicate();
 
 private:
     BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format,
                     uint64_t usage, size_t userMetadataSize);
 
-    BufferHubBuffer(pdx::LocalChannelHandle mChannelHandle);
+    BufferHubBuffer(const native_handle_t* token);
 
-    int ImportGraphicBuffer();
+    int initWithBufferTraits(const frameworks::bufferhub::V1_0::BufferTraits& bufferTraits);
 
     // Global id for the buffer that is consistent across processes.
-    int mId = -1;
+    int mId = 0;
 
     // Client state mask of this BufferHubBuffer object. It is unique amoung all
     // clients/users of the buffer.
@@ -159,8 +120,8 @@
     // Stores ground truth of the buffer.
     AHardwareBuffer_Desc mBufferDesc;
 
-    // Wrapps the gralloc buffer handle of this buffer.
-    dvr::NativeHandleWrapper<pdx::LocalHandle> mBufferHandle;
+    // Wraps the gralloc buffer handle of this buffer.
+    hardware::hidl_handle mBufferHandle;
 
     // An ashmem-based metadata object. The same shared memory are mapped to the
     // bufferhubd daemon and all buffer clients.
@@ -170,8 +131,8 @@
     std::atomic<uint32_t>* fence_state_ = nullptr;
     std::atomic<uint32_t>* active_clients_bit_mask_ = nullptr;
 
-    // PDX backend.
-    BufferHubClient mClient;
+    // HwBinder backend
+    sp<frameworks::bufferhub::V1_0::IBufferClient> mBufferClient;
 };
 
 } // namespace android
diff --git a/libs/ui/include/ui/BufferHubDefs.h b/libs/ui/include/ui/BufferHubDefs.h
index d259fef..069f0dc 100644
--- a/libs/ui/include/ui/BufferHubDefs.h
+++ b/libs/ui/include/ui/BufferHubDefs.h
@@ -158,6 +158,29 @@
 static_assert(sizeof(MetadataHeader) == 128, "Unexpected MetadataHeader size");
 static constexpr size_t kMetadataHeaderSize = sizeof(MetadataHeader);
 
+/**
+ * android.frameworks.bufferhub@1.0::BufferTraits.bufferInfo is an opaque handle. See
+ * https://cs.corp.google.com/android/frameworks/hardware/interfaces/bufferhub/1.0/types.hal for
+ * more details about android.frameworks.bufferhub@1.0::BufferTraits.
+ *
+ * This definition could be changed, but implementation of BufferHubService::buildBufferInfo
+ * (frameworks/native/services/bufferhub), VtsHalBufferHubV1_0TargetTest
+ * (frameworks/hardware/interfaces/bufferhub) and BufferHubBuffer::readBufferTraits (libui) will
+ * also need to be updated.
+ *
+ * It's definition should follow the following format:
+ * {
+ *   NumFds = 1,
+ *   NumInts = 3,
+ *   data[0] = Ashmem fd for BufferHubMetadata,
+ *   data[1] = buffer id,
+ *   data[2] = client state bit mask,
+ *   data[3] = user metadata size,
+ * }
+ */
+static constexpr int kBufferInfoNumFds = 1;
+static constexpr int kBufferInfoNumInts = 3;
+
 } // namespace BufferHubDefs
 
 } // namespace android
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index a670b3c..665469e 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -31,12 +31,14 @@
 cc_test {
     name: "GraphicBuffer_test",
     header_libs: [
-        "libbufferhub_headers",
         "libdvr_headers",
         "libnativewindow_headers",
     ],
     shared_libs: [
-        "libpdx_default_transport",
+        "android.frameworks.bufferhub@1.0",
+        "libcutils",
+        "libhidlbase",
+        "libhwbinder",
         "libui",
         "libutils",
     ],
@@ -47,7 +49,6 @@
 cc_test {
     name: "BufferHub_test",
     header_libs: [
-        "libbufferhub_headers",
         "libdvr_headers",
         "libnativewindow_headers",
     ],
@@ -60,7 +61,6 @@
         "libhidlbase",
         "libhwbinder",
         "liblog",
-        "libpdx_default_transport",
         "libui",
         "libutils"
     ],
diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp
index 1b339a0..cd744cd 100644
--- a/libs/ui/tests/BufferHubBuffer_test.cpp
+++ b/libs/ui/tests/BufferHubBuffer_test.cpp
@@ -16,10 +16,9 @@
 
 #define LOG_TAG "BufferHubBufferTest"
 
-#include <android/frameworks/bufferhub/1.0/IBufferClient.h>
-#include <android/frameworks/bufferhub/1.0/IBufferHub.h>
 #include <android/hardware_buffer.h>
 #include <cutils/native_handle.h>
+#include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <hidl/ServiceManagement.h>
 #include <hwbinder/IPCThreadState.h>
@@ -29,36 +28,38 @@
 
 namespace {
 
+using ::android::BufferHubDefs::AnyClientAcquired;
+using ::android::BufferHubDefs::AnyClientGained;
+using ::android::BufferHubDefs::AnyClientPosted;
+using ::android::BufferHubDefs::IsBufferReleased;
+using ::android::BufferHubDefs::IsClientAcquired;
+using ::android::BufferHubDefs::IsClientGained;
+using ::android::BufferHubDefs::IsClientPosted;
+using ::android::BufferHubDefs::IsClientReleased;
+using ::android::BufferHubDefs::kMetadataHeaderSize;
+using ::testing::IsNull;
+using ::testing::NotNull;
+
 const int kWidth = 640;
 const int kHeight = 480;
 const int kLayerCount = 1;
 const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
 const int kUsage = 0;
-const size_t kUserMetadataSize = 0;
-
-using BufferHubDefs::AnyClientAcquired;
-using BufferHubDefs::AnyClientGained;
-using BufferHubDefs::AnyClientPosted;
-using BufferHubDefs::IsBufferReleased;
-using BufferHubDefs::IsClientAcquired;
-using BufferHubDefs::IsClientGained;
-using BufferHubDefs::IsClientPosted;
-using BufferHubDefs::IsClientReleased;
-using BufferHubDefs::kFirstClientBitMask;
-using BufferHubDefs::kMetadataHeaderSize;
-using frameworks::bufferhub::V1_0::BufferHubStatus;
-using frameworks::bufferhub::V1_0::IBufferClient;
-using frameworks::bufferhub::V1_0::IBufferHub;
-using hardware::hidl_handle;
-using hardware::graphics::common::V1_2::HardwareBufferDescription;
-using hidl::base::V1_0::IBase;
-using pdx::LocalChannelHandle;
+const AHardwareBuffer_Desc kDesc = {kWidth, kHeight,        kLayerCount,  kFormat,
+                                    kUsage, /*stride=*/0UL, /*rfu0=*/0UL, /*rfu1=*/0ULL};
+const size_t kUserMetadataSize = 1;
 
 class BufferHubBufferTest : public ::testing::Test {
 protected:
     void SetUp() override { android::hardware::ProcessState::self()->startThreadPool(); }
 };
 
+bool cmpAHardwareBufferDesc(const AHardwareBuffer_Desc& desc, const AHardwareBuffer_Desc& other) {
+    // Not comparing stride because it's unknown before allocation
+    return desc.format == other.format && desc.height == other.height &&
+            desc.layers == other.layers && desc.usage == other.usage && desc.width == other.width;
+}
+
 class BufferHubBufferStateTransitionTest : public BufferHubBufferTest {
 protected:
     void SetUp() override {
@@ -67,9 +68,9 @@
     }
 
     std::unique_ptr<BufferHubBuffer> b1;
-    uint64_t b1ClientMask = 0U;
+    uint32_t b1ClientMask = 0U;
     std::unique_ptr<BufferHubBuffer> b2;
-    uint64_t b2ClientMask = 0U;
+    uint32_t b2ClientMask = 0U;
 
 private:
     // Creates b1 and b2 as the clients of the same buffer for testing.
@@ -78,91 +79,126 @@
 
 void BufferHubBufferStateTransitionTest::CreateTwoClientsOfABuffer() {
     b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize);
+    ASSERT_THAT(b1, NotNull());
     b1ClientMask = b1->client_state_mask();
     ASSERT_NE(b1ClientMask, 0U);
-    auto statusOrHandle = b1->Duplicate();
-    ASSERT_TRUE(statusOrHandle);
-    LocalChannelHandle h2 = statusOrHandle.take();
-    b2 = BufferHubBuffer::Import(std::move(h2));
+
+    native_handle_t* token = b1->Duplicate();
+    ASSERT_THAT(token, NotNull());
+
+    // TODO(b/122543147): use a movalbe wrapper for token
+    b2 = BufferHubBuffer::Import(token);
+    native_handle_close(token);
+    native_handle_delete(token);
+    ASSERT_THAT(b2, NotNull());
+
     b2ClientMask = b2->client_state_mask();
     ASSERT_NE(b2ClientMask, 0U);
     ASSERT_NE(b2ClientMask, b1ClientMask);
 }
 
-TEST_F(BufferHubBufferTest, CreateBufferHubBufferFails) {
+TEST_F(BufferHubBufferTest, CreateBufferFails) {
     // Buffer Creation will fail: BLOB format requires height to be 1.
     auto b1 = BufferHubBuffer::Create(kWidth, /*height=*/2, kLayerCount,
                                       /*format=*/HAL_PIXEL_FORMAT_BLOB, kUsage, kUserMetadataSize);
 
-    EXPECT_FALSE(b1->IsConnected());
-    EXPECT_FALSE(b1->IsValid());
+    EXPECT_THAT(b1, IsNull());
 
     // Buffer Creation will fail: user metadata size too large.
     auto b2 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
                                       /*userMetadataSize=*/std::numeric_limits<size_t>::max());
 
-    EXPECT_FALSE(b2->IsConnected());
-    EXPECT_FALSE(b2->IsValid());
+    EXPECT_THAT(b2, IsNull());
 
     // Buffer Creation will fail: user metadata size too large.
     const size_t userMetadataSize = std::numeric_limits<size_t>::max() - kMetadataHeaderSize;
     auto b3 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
                                       userMetadataSize);
 
-    EXPECT_FALSE(b3->IsConnected());
-    EXPECT_FALSE(b3->IsValid());
+    EXPECT_THAT(b3, IsNull());
 }
 
-TEST_F(BufferHubBufferTest, CreateBufferHubBuffer) {
+TEST_F(BufferHubBufferTest, CreateBuffer) {
     auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
                                       kUserMetadataSize);
+    ASSERT_THAT(b1, NotNull());
     EXPECT_TRUE(b1->IsConnected());
     EXPECT_TRUE(b1->IsValid());
-    EXPECT_NE(b1->id(), 0);
+    EXPECT_TRUE(cmpAHardwareBufferDesc(b1->desc(), kDesc));
+    EXPECT_EQ(b1->user_metadata_size(), kUserMetadataSize);
 }
 
-TEST_F(BufferHubBufferTest, DuplicateBufferHubBuffer) {
+TEST_F(BufferHubBufferTest, DuplicateAndImportBuffer) {
     auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
                                       kUserMetadataSize);
-    int id1 = b1->id();
-    uint64_t bufferStateMask1 = b1->client_state_mask();
-    EXPECT_NE(bufferStateMask1, 0U);
+    ASSERT_THAT(b1, NotNull());
     EXPECT_TRUE(b1->IsValid());
-    EXPECT_EQ(b1->user_metadata_size(), kUserMetadataSize);
 
-    auto statusOrHandle = b1->Duplicate();
-    EXPECT_TRUE(statusOrHandle);
+    native_handle_t* token = b1->Duplicate();
+    EXPECT_TRUE(token);
 
     // The detached buffer should still be valid.
     EXPECT_TRUE(b1->IsConnected());
     EXPECT_TRUE(b1->IsValid());
 
-    // Gets the channel handle for the duplicated buffer.
-    LocalChannelHandle h2 = statusOrHandle.take();
-    EXPECT_TRUE(h2.valid());
+    std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(token);
+    native_handle_close(token);
+    native_handle_delete(token);
 
-    std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(std::move(h2));
-    EXPECT_FALSE(h2.valid());
-    ASSERT_TRUE(b2 != nullptr);
+    ASSERT_THAT(b2, NotNull());
     EXPECT_TRUE(b2->IsValid());
-    EXPECT_EQ(b2->user_metadata_size(), kUserMetadataSize);
 
-    int id2 = b2->id();
-    uint64_t bufferStateMask2 = b2->client_state_mask();
-    EXPECT_NE(bufferStateMask2, 0U);
+    EXPECT_TRUE(cmpAHardwareBufferDesc(b1->desc(), b2->desc()));
+    EXPECT_EQ(b1->user_metadata_size(), b2->user_metadata_size());
 
     // These two buffer instances are based on the same physical buffer under the
     // hood, so they should share the same id.
-    EXPECT_EQ(id1, id2);
+    EXPECT_EQ(b1->id(), b2->id());
     // We use client_state_mask() to tell those two instances apart.
-    EXPECT_NE(bufferStateMask1, bufferStateMask2);
+    EXPECT_NE(b1->client_state_mask(), b2->client_state_mask());
 
     // Both buffer instances should be in released state currently.
     EXPECT_TRUE(IsBufferReleased(b1->buffer_state()));
     EXPECT_TRUE(IsBufferReleased(b2->buffer_state()));
+}
 
-    // TODO(b/112338294): rewrite test after migration
-    return;
+TEST_F(BufferHubBufferTest, ImportFreedBuffer) {
+    auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+                                      kUserMetadataSize);
+    ASSERT_THAT(b1, NotNull());
+    EXPECT_TRUE(b1->IsValid());
+
+    native_handle_t* token = b1->Duplicate();
+    EXPECT_TRUE(token);
+
+    // Explicitly destroy b1. Backend buffer should be freed and token becomes invalid
+    b1.reset();
+
+    // TODO(b/122543147): use a movalbe wrapper for token
+    std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(token);
+    native_handle_close(token);
+    native_handle_delete(token);
+
+    // Import should fail with INVALID_TOKEN
+    EXPECT_THAT(b2, IsNull());
+}
+
+// nullptr must not crash the service
+TEST_F(BufferHubBufferTest, ImportNullToken) {
+    auto b1 = BufferHubBuffer::Import(nullptr);
+    EXPECT_THAT(b1, IsNull());
+}
+
+// TODO(b/118180214): remove the comment after ag/5856474 landed
+// This test has a very little chance to fail (number of existing tokens / 2 ^ 32)
+TEST_F(BufferHubBufferTest, ImportInvalidToken) {
+    native_handle_t* token = native_handle_create(/*numFds=*/0, /*numInts=*/1);
+    token->data[0] = 0;
+
+    auto b1 = BufferHubBuffer::Import(token);
+    native_handle_delete(token);
+
+    EXPECT_THAT(b1, IsNull());
 }
 
 TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromReleasedState) {
@@ -340,5 +376,67 @@
     EXPECT_EQ(b2->Release(), 0);
 }
 
+TEST_F(BufferHubBufferStateTransitionTest, BasicUsage) {
+    // 1 producer buffer and 1 consumer buffer initialised in testcase setup.
+    // Test if this set of basic operation succeed:
+    // Producer post three times to the consumer, and released by consumer.
+    for (int i = 0; i < 3; ++i) {
+        ASSERT_EQ(b1->Gain(), 0);
+        ASSERT_EQ(b1->Post(), 0);
+        ASSERT_EQ(b2->Acquire(), 0);
+        ASSERT_EQ(b2->Release(), 0);
+    }
+}
+
+TEST_F(BufferHubBufferTest, createNewConsumerAfterGain) {
+    // Create a poducer buffer and gain.
+    std::unique_ptr<BufferHubBuffer> b1 =
+            BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+                                    kUserMetadataSize);
+    ASSERT_THAT(b1, NotNull());
+    ASSERT_EQ(b1->Gain(), 0);
+
+    // Create a consumer of the buffer and test if the consumer can acquire the
+    // buffer if producer posts.
+    // TODO(b/122543147): use a movalbe wrapper for token
+    native_handle_t* token = b1->Duplicate();
+    ASSERT_TRUE(token);
+
+    std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(token);
+    native_handle_close(token);
+    native_handle_delete(token);
+
+    ASSERT_THAT(b2, NotNull());
+    ASSERT_NE(b1->client_state_mask(), b2->client_state_mask());
+
+    ASSERT_EQ(b1->Post(), 0);
+    EXPECT_EQ(b2->Acquire(), 0);
+}
+
+TEST_F(BufferHubBufferTest, createNewConsumerAfterPost) {
+    // Create a poducer buffer and post.
+    std::unique_ptr<BufferHubBuffer> b1 =
+            BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+                                    kUserMetadataSize);
+    ASSERT_EQ(b1->Gain(), 0);
+    ASSERT_EQ(b1->Post(), 0);
+
+    // Create a consumer of the buffer and test if the consumer can acquire the
+    // buffer if producer posts.
+    // TODO(b/122543147): use a movalbe wrapper for token
+    native_handle_t* token = b1->Duplicate();
+    ASSERT_TRUE(token);
+
+    std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(token);
+    native_handle_close(token);
+    native_handle_delete(token);
+
+    ASSERT_THAT(b2, NotNull());
+    ASSERT_NE(b1->client_state_mask(), b2->client_state_mask());
+
+    EXPECT_EQ(b2->Acquire(), 0);
+}
+
 } // namespace
+
 } // namespace android
diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp
index 81ab3ac..5b46454 100644
--- a/libs/ui/tests/GraphicBuffer_test.cpp
+++ b/libs/ui/tests/GraphicBuffer_test.cpp
@@ -39,7 +39,7 @@
     std::unique_ptr<BufferHubBuffer> b1 =
             BufferHubBuffer::Create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
                                     kTestUsage, /*userMetadataSize=*/0);
-    EXPECT_NE(b1, nullptr);
+    ASSERT_NE(b1, nullptr);
     EXPECT_TRUE(b1->IsValid());
 
     sp<GraphicBuffer> gb(new GraphicBuffer(std::move(b1)));
diff --git a/libs/vr/OWNERS b/libs/vr/OWNERS
new file mode 100644
index 0000000..ec2d712
--- /dev/null
+++ b/libs/vr/OWNERS
@@ -0,0 +1,4 @@
+hendrikw@google.com
+jwcai@google.com
+steventhomas@google.com
+
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index 1359f4c..ed5a992 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -5,7 +5,6 @@
 #include <private/dvr/producer_buffer.h>
 #include <sys/epoll.h>
 #include <sys/eventfd.h>
-#include <ui/BufferHubBuffer.h>
 #include <ui/BufferHubDefs.h>
 
 #include <mutex>
@@ -20,9 +19,6 @@
     return result;                            \
   })()
 
-using android::BufferHubBuffer;
-using android::GraphicBuffer;
-using android::sp;
 using android::BufferHubDefs::AnyClientAcquired;
 using android::BufferHubDefs::AnyClientGained;
 using android::BufferHubDefs::AnyClientPosted;
@@ -31,19 +27,15 @@
 using android::BufferHubDefs::IsClientPosted;
 using android::BufferHubDefs::IsClientReleased;
 using android::BufferHubDefs::kFirstClientBitMask;
-using android::BufferHubDefs::kMetadataHeaderSize;
 using android::dvr::ConsumerBuffer;
 using android::dvr::ProducerBuffer;
-using android::pdx::LocalChannelHandle;
 using android::pdx::LocalHandle;
 using android::pdx::Status;
 
 const int kWidth = 640;
 const int kHeight = 480;
-const int kLayerCount = 1;
 const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
 const int kUsage = 0;
-const size_t kUserMetadataSize = 0;
 // Maximum number of consumers for the buffer that only has one producer in the
 // test.
 const size_t kMaxConsumerCount =
@@ -361,9 +353,11 @@
   ASSERT_TRUE(p.get() != nullptr);
   ASSERT_EQ(0, p->GainAsync());
   ASSERT_EQ(0, p->Post(LocalHandle()));
-  // Producer state bit is in released state after post. The overall state of
-  // the buffer is also released because there is no consumer of this buffer.
-  ASSERT_TRUE(IsBufferReleased(p->buffer_state()));
+  // Producer state bit is in released state after post, other clients shall be
+  // in posted state although there is no consumer of this buffer yet.
+  ASSERT_TRUE(IsClientReleased(p->buffer_state(), p->client_state_mask()));
+  ASSERT_FALSE(IsBufferReleased(p->buffer_state()));
+  ASSERT_TRUE(AnyClientPosted(p->buffer_state()));
 
   // Gain in released state should succeed.
   LocalHandle invalid_fence;
@@ -450,27 +444,17 @@
   LocalHandle invalid_fence;
 
   // Post the gained buffer before any consumer gets created.
-  // The buffer should be in released state because it is not expected to be
-  // read by any clients.
   EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
-  EXPECT_TRUE(IsBufferReleased(p->buffer_state()));
+  EXPECT_FALSE(IsBufferReleased(p->buffer_state()));
   EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
 
-  // Newly created consumer will not be signalled for the posted buffer before
-  // its creation. It cannot acquire the buffer immediately.
+  // Newly created consumer will be signalled for the posted buffer although it
+  // is created after producer posting.
   std::unique_ptr<ConsumerBuffer> c =
       ConsumerBuffer::Import(p->CreateConsumer());
   ASSERT_TRUE(c.get() != nullptr);
-  EXPECT_FALSE(IsClientPosted(c->buffer_state(), c->client_state_mask()));
-  EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
-
-  // Producer should be able to gain back and post the buffer
-  EXPECT_EQ(0, p->GainAsync());
-  EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
-
-  // Consumer should be able to pick up the buffer this time.
+  EXPECT_TRUE(IsClientPosted(c->buffer_state(), c->client_state_mask()));
   EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
-  EXPECT_TRUE(IsClientAcquired(c->buffer_state(), c->client_state_mask()));
 }
 
 TEST_F(LibBufferHubTest, TestCreateConsumerWhenBufferReleased) {
@@ -816,7 +800,7 @@
   // TODO(b/112338294) rewrite test after migration
   return;
 
-  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
+  /* std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   std::unique_ptr<ConsumerBuffer> c =
       ConsumerBuffer::Import(p->CreateConsumer());
@@ -884,49 +868,14 @@
   EXPECT_TRUE(d->IsConnected());
   EXPECT_TRUE(d->IsValid());
 
-  EXPECT_EQ(d->id(), p_id);
-}
-
-TEST_F(LibBufferHubTest, TestCreateBufferHubBufferFails) {
-  // Buffer Creation will fail: BLOB format requires height to be 1.
-  auto b1 = BufferHubBuffer::Create(kWidth, /*height=2*/ 2, kLayerCount,
-                                    /*format=*/HAL_PIXEL_FORMAT_BLOB, kUsage,
-                                    kUserMetadataSize);
-
-  EXPECT_FALSE(b1->IsConnected());
-  EXPECT_FALSE(b1->IsValid());
-
-  // Buffer Creation will fail: user metadata size too large.
-  auto b2 = BufferHubBuffer::Create(
-      kWidth, kHeight, kLayerCount, kFormat, kUsage,
-      /*user_metadata_size=*/std::numeric_limits<size_t>::max());
-
-  EXPECT_FALSE(b2->IsConnected());
-  EXPECT_FALSE(b2->IsValid());
-
-  // Buffer Creation will fail: user metadata size too large.
-  auto b3 = BufferHubBuffer::Create(
-      kWidth, kHeight, kLayerCount, kFormat, kUsage,
-      /*user_metadata_size=*/std::numeric_limits<size_t>::max() -
-          kMetadataHeaderSize);
-
-  EXPECT_FALSE(b3->IsConnected());
-  EXPECT_FALSE(b3->IsValid());
-}
-
-TEST_F(LibBufferHubTest, TestCreateBufferHubBuffer) {
-  auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
-                                    kUsage, kUserMetadataSize);
-  EXPECT_TRUE(b1->IsConnected());
-  EXPECT_TRUE(b1->IsValid());
-  EXPECT_NE(b1->id(), 0);
+  EXPECT_EQ(d->id(), p_id); */
 }
 
 TEST_F(LibBufferHubTest, TestDetach) {
   // TODO(b/112338294) rewrite test after migration
   return;
 
-  std::unique_ptr<ProducerBuffer> p1 = ProducerBuffer::Create(
+  /* std::unique_ptr<ProducerBuffer> p1 = ProducerBuffer::Create(
       kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
   ASSERT_TRUE(p1.get() != nullptr);
   int p1_id = p1->id();
@@ -944,47 +893,5 @@
   EXPECT_FALSE(h1.valid());
   EXPECT_TRUE(b1->IsValid());
   int b1_id = b1->id();
-  EXPECT_EQ(b1_id, p1_id);
-}
-
-TEST_F(LibBufferHubTest, TestDuplicateBufferHubBuffer) {
-  auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
-                                    kUsage, kUserMetadataSize);
-  int b1_id = b1->id();
-  EXPECT_TRUE(b1->IsValid());
-  EXPECT_EQ(b1->user_metadata_size(), kUserMetadataSize);
-  EXPECT_NE(b1->client_state_mask(), 0U);
-
-  auto status_or_handle = b1->Duplicate();
-  EXPECT_TRUE(status_or_handle);
-
-  // The detached buffer should still be valid.
-  EXPECT_TRUE(b1->IsConnected());
-  EXPECT_TRUE(b1->IsValid());
-
-  // Gets the channel handle for the duplicated buffer.
-  LocalChannelHandle h2 = status_or_handle.take();
-  EXPECT_TRUE(h2.valid());
-
-  std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(std::move(h2));
-  EXPECT_FALSE(h2.valid());
-  ASSERT_TRUE(b2 != nullptr);
-  EXPECT_TRUE(b2->IsValid());
-  EXPECT_EQ(b2->user_metadata_size(), kUserMetadataSize);
-  EXPECT_NE(b2->client_state_mask(), 0U);
-
-  int b2_id = b2->id();
-
-  // These two buffer instances are based on the same physical buffer under the
-  // hood, so they should share the same id.
-  EXPECT_EQ(b1_id, b2_id);
-  // We use client_state_mask() to tell those two instances apart.
-  EXPECT_NE(b1->client_state_mask(), b2->client_state_mask());
-
-  // Both buffer instances should be in gained state.
-  EXPECT_TRUE(IsBufferReleased(b1->buffer_state()));
-  EXPECT_TRUE(IsBufferReleased(b2->buffer_state()));
-
-  // TODO(b/112338294) rewrite test after migration
-  return;
+  EXPECT_EQ(b1_id, p1_id); */
 }
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 440a59d..889763a 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
@@ -94,6 +94,12 @@
     return buffer_state_->load(std::memory_order_acquire);
   };
 
+  // Returns whether the buffer is already released by all current clients.
+  bool is_released() {
+    return (buffer_state() &
+            active_clients_bit_mask_->load(std::memory_order_acquire)) == 0;
+  }
+
   // A state mask which is unique to a buffer hub client among all its siblings
   // sharing the same concrete graphic buffer.
   uint32_t client_state_mask() const { return client_state_mask_; }
diff --git a/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h b/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
index 7aa50b1..726f035 100644
--- a/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
@@ -6,16 +6,6 @@
 namespace android {
 namespace dvr {
 
-// BufferConsumer was originally poorly named and gets easily confused with
-// IGraphicBufferConsumer. Actually, BufferConsumer is a single buffer that can
-// consume (i.e. read) data from a buffer, but it doesn't consume buffer. On
-// the other hand, IGraphicBufferConsumer is the consumer end of a BufferQueue
-// and it is used to consume buffers.
-//
-// TODO(b/116855254): Remove this typedef once rename is complete in other
-// projects and/or branches.
-typedef class ConsumerBuffer BufferConsumer;
-
 // This is a connection to a producer buffer, which can be located in another
 // application. When that buffer is Post()ed, this fd will be signaled and
 // Acquire allows read access. The user is responsible for making sure that
diff --git a/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h b/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h
index 2761416..7ec345c 100644
--- a/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h
@@ -6,23 +6,13 @@
 namespace android {
 namespace dvr {
 
-// BufferProducer was originally poorly named and gets easily confused with
-// IGraphicBufferProducer. Actually, BufferProducer is a single buffer that can
-// produce (i.e. write) data into a buffer, but it doesn't produce buffer. On
-// the other hand, IGraphicBufferProducer is the producer end of a BufferQueue
-// and it is used to produce buffers.
-//
-// TODO(b/116855254): Remove this typedef once rename is complete in other
-// projects and/or branches.
-typedef class ProducerBuffer BufferProducer;
-
 // This represents a writable buffer. Calling Post notifies all clients and
 // makes the buffer read-only. Call Gain to acquire write access. A buffer
 // may have many consumers.
 //
 // The user of ProducerBuffer is responsible with making sure that the Post() is
 // done with the correct metadata type and size. The user is also responsible
-// for making sure that remote ends (BufferConsumers) are also using the correct
+// for making sure that remote ends (ConsumerBuffers) are also using the correct
 // metadata when acquiring the buffer. The API guarantees that a Post() with a
 // metadata of wrong size will fail. However, it currently does not do any
 // type checking.
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
index 5274bf2..edfdddf 100644
--- a/libs/vr/libbufferhub/producer_buffer.cpp
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -89,13 +89,10 @@
     return -EBUSY;
   }
 
-  // Set the producer client buffer state to released, other clients' buffer
-  // state to posted.
-  uint32_t current_active_clients_bit_mask =
-      active_clients_bit_mask_->load(std::memory_order_acquire);
-  uint32_t updated_buffer_state = current_active_clients_bit_mask &
-                                  (~client_state_mask()) &
-                                  BufferHubDefs::kHighBitsMask;
+  // Set the producer client buffer state to released, that of all other clients
+  // (both existing and non-existing clients) to posted.
+  uint32_t updated_buffer_state =
+      (~client_state_mask()) & BufferHubDefs::kHighBitsMask;
   while (!buffer_state_->compare_exchange_weak(
       current_buffer_state, updated_buffer_state, std::memory_order_acq_rel,
       std::memory_order_acquire)) {
@@ -176,7 +173,9 @@
   }
   if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
       BufferHubDefs::AnyClientGained(current_buffer_state) ||
-      (BufferHubDefs::AnyClientPosted(current_buffer_state) &&
+      (BufferHubDefs::AnyClientPosted(
+           current_buffer_state &
+           active_clients_bit_mask_->load(std::memory_order_acquire)) &&
        !gain_posted_buffer)) {
     ALOGE("%s: not released id=%d state=%" PRIx32 ".", __FUNCTION__, id(),
           current_buffer_state);
@@ -198,7 +197,9 @@
 
     if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
         BufferHubDefs::AnyClientGained(current_buffer_state) ||
-        (BufferHubDefs::AnyClientPosted(current_buffer_state) &&
+        (BufferHubDefs::AnyClientPosted(
+             current_buffer_state &
+             active_clients_bit_mask_->load(std::memory_order_acquire)) &&
          !gain_posted_buffer)) {
       ALOGE(
           "%s: Failed to gain the buffer. The buffer is no longer released. "
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 9c4f73f..d7833f3 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -480,7 +480,7 @@
 
     // Note that import might (though very unlikely) fail. If so, buffer_handle
     // will be closed and included in returned buffer_slots.
-    if (AddBuffer(BufferProducer::Import(std::move(buffer_handle)),
+    if (AddBuffer(ProducerBuffer::Import(std::move(buffer_handle)),
                   buffer_slot)) {
       ALOGD_IF(TRACE, "ProducerQueue::AllocateBuffers: new buffer at slot: %zu",
                buffer_slot);
@@ -517,7 +517,7 @@
 }
 
 Status<void> ProducerQueue::AddBuffer(
-    const std::shared_ptr<BufferProducer>& buffer, size_t slot) {
+    const std::shared_ptr<ProducerBuffer>& buffer, size_t slot) {
   ALOGD_IF(TRACE, "ProducerQueue::AddBuffer: queue_id=%d buffer_id=%d slot=%zu",
            id(), buffer->id(), slot);
   // For producer buffer, we need to enqueue the newly added buffer
@@ -530,7 +530,7 @@
 }
 
 Status<size_t> ProducerQueue::InsertBuffer(
-    const std::shared_ptr<BufferProducer>& buffer) {
+    const std::shared_ptr<ProducerBuffer>& buffer) {
   if (buffer == nullptr ||
       !BufferHubDefs::IsClientGained(buffer->buffer_state(),
                                      buffer->client_state_mask())) {
@@ -554,7 +554,7 @@
   size_t slot = status_or_slot.get();
 
   // Note that we are calling AddBuffer() from the base class to explicitly
-  // avoid Enqueue() the BufferProducer.
+  // avoid Enqueue() the ProducerBuffer.
   auto status = BufferHubQueue::AddBuffer(buffer, slot);
   if (!status) {
     ALOGE("ProducerQueue::InsertBuffer: Failed to add buffer: %s.",
@@ -576,13 +576,13 @@
   return BufferHubQueue::RemoveBuffer(slot);
 }
 
-Status<std::shared_ptr<BufferProducer>> ProducerQueue::Dequeue(
+Status<std::shared_ptr<ProducerBuffer>> ProducerQueue::Dequeue(
     int timeout, size_t* slot, LocalHandle* release_fence) {
   DvrNativeBufferMetadata canonical_meta;
   return Dequeue(timeout, slot, &canonical_meta, release_fence);
 }
 
-pdx::Status<std::shared_ptr<BufferProducer>> ProducerQueue::Dequeue(
+pdx::Status<std::shared_ptr<ProducerBuffer>> ProducerQueue::Dequeue(
     int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
     pdx::LocalHandle* release_fence, bool gain_posted_buffer) {
   ATRACE_NAME("ProducerQueue::Dequeue");
@@ -591,14 +591,14 @@
     return ErrorStatus(EINVAL);
   }
 
-  std::shared_ptr<BufferProducer> buffer;
+  std::shared_ptr<ProducerBuffer> buffer;
   Status<std::shared_ptr<BufferHubBase>> dequeue_status =
       BufferHubQueue::Dequeue(timeout, slot);
   if (dequeue_status.ok()) {
-    buffer = std::static_pointer_cast<BufferProducer>(dequeue_status.take());
+    buffer = std::static_pointer_cast<ProducerBuffer>(dequeue_status.take());
   } else {
     if (gain_posted_buffer) {
-      Status<std::shared_ptr<BufferProducer>> dequeue_unacquired_status =
+      Status<std::shared_ptr<ProducerBuffer>> dequeue_unacquired_status =
           ProducerQueue::DequeueUnacquiredBuffer(slot);
       if (!dequeue_unacquired_status.ok()) {
         ALOGE("%s: DequeueUnacquiredBuffer returned error: %d", __FUNCTION__,
@@ -618,7 +618,7 @@
   return {std::move(buffer)};
 }
 
-Status<std::shared_ptr<BufferProducer>> ProducerQueue::DequeueUnacquiredBuffer(
+Status<std::shared_ptr<ProducerBuffer>> ProducerQueue::DequeueUnacquiredBuffer(
     size_t* slot) {
   if (unavailable_buffers_slot_.size() < 1) {
     ALOGE(
@@ -632,7 +632,7 @@
   // unavailable_buffers_slot_.
   for (auto iter = unavailable_buffers_slot_.begin();
        iter != unavailable_buffers_slot_.end(); iter++) {
-    std::shared_ptr<BufferProducer> buffer = ProducerQueue::GetBuffer(*iter);
+    std::shared_ptr<ProducerBuffer> buffer = ProducerQueue::GetBuffer(*iter);
     if (buffer == nullptr) {
       ALOGE("%s failed. Buffer slot %d is  null.", __FUNCTION__,
             static_cast<int>(*slot));
@@ -718,9 +718,9 @@
     ALOGD_IF(TRACE, ": buffer_handle=%d", __FUNCTION__,
              buffer_handle_slot.first.value());
 
-    std::unique_ptr<BufferConsumer> buffer_consumer =
-        BufferConsumer::Import(std::move(buffer_handle_slot.first));
-    if (!buffer_consumer) {
+    std::unique_ptr<ConsumerBuffer> consumer_buffer =
+        ConsumerBuffer::Import(std::move(buffer_handle_slot.first));
+    if (!consumer_buffer) {
       ALOGE("%s: Failed to import buffer: slot=%zu", __FUNCTION__,
             buffer_handle_slot.second);
       last_error = ErrorStatus(EPIPE);
@@ -728,7 +728,7 @@
     }
 
     auto add_status =
-        AddBuffer(std::move(buffer_consumer), buffer_handle_slot.second);
+        AddBuffer(std::move(consumer_buffer), buffer_handle_slot.second);
     if (!add_status) {
       ALOGE("%s: Failed to add buffer: %s", __FUNCTION__,
             add_status.GetErrorMessage().c_str());
@@ -745,13 +745,13 @@
 }
 
 Status<void> ConsumerQueue::AddBuffer(
-    const std::shared_ptr<BufferConsumer>& buffer, size_t slot) {
+    const std::shared_ptr<ConsumerBuffer>& buffer, size_t slot) {
   ALOGD_IF(TRACE, "%s: queue_id=%d buffer_id=%d slot=%zu", __FUNCTION__, id(),
            buffer->id(), slot);
   return BufferHubQueue::AddBuffer(buffer, slot);
 }
 
-Status<std::shared_ptr<BufferConsumer>> ConsumerQueue::Dequeue(
+Status<std::shared_ptr<ConsumerBuffer>> ConsumerQueue::Dequeue(
     int timeout, size_t* slot, void* meta, size_t user_metadata_size,
     LocalHandle* acquire_fence) {
   if (user_metadata_size != user_metadata_size_) {
@@ -780,7 +780,7 @@
   return status;
 }
 
-Status<std::shared_ptr<BufferConsumer>> ConsumerQueue::Dequeue(
+Status<std::shared_ptr<ConsumerBuffer>> ConsumerQueue::Dequeue(
     int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
     pdx::LocalHandle* acquire_fence) {
   ATRACE_NAME("ConsumerQueue::Dequeue");
@@ -793,7 +793,7 @@
   if (!status)
     return status.error_status();
 
-  auto buffer = std::static_pointer_cast<BufferConsumer>(status.take());
+  auto buffer = std::static_pointer_cast<ConsumerBuffer>(status.take());
   const int ret = buffer->AcquireAsync(out_meta, acquire_fence);
   if (ret < 0)
     return ErrorStatus(-ret);
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index 53ab2b2..74b4b3d 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -131,8 +131,8 @@
   bool hung_up() const { return hung_up_; }
 
  protected:
-  BufferHubQueue(pdx::LocalChannelHandle channel);
-  BufferHubQueue(const std::string& endpoint_path);
+  explicit BufferHubQueue(pdx::LocalChannelHandle channel);
+  explicit BufferHubQueue(const std::string& endpoint_path);
 
   // Imports the queue parameters by querying BufferHub for the parameters for
   // this channel.
@@ -307,12 +307,12 @@
     return BASE::Create(std::move(handle));
   }
 
-  // Get a buffer producer. Note that the method doesn't check whether the
+  // Get a producer buffer. Note that the method doesn't check whether the
   // buffer slot has a valid buffer that has been allocated already. When no
   // buffer has been imported before it returns nullptr; otherwise it returns
-  // a shared pointer to a BufferProducer.
-  std::shared_ptr<BufferProducer> GetBuffer(size_t slot) const {
-    return std::static_pointer_cast<BufferProducer>(
+  // a shared pointer to a ProducerBuffer.
+  std::shared_ptr<ProducerBuffer> GetBuffer(size_t slot) const {
+    return std::static_pointer_cast<ProducerBuffer>(
         BufferHubQueue::GetBuffer(slot));
   }
 
@@ -333,7 +333,7 @@
 
   // Add a producer buffer to populate the queue. Once added, a producer buffer
   // is available to use (i.e. in GAINED state).
-  pdx::Status<void> AddBuffer(const std::shared_ptr<BufferProducer>& buffer,
+  pdx::Status<void> AddBuffer(const std::shared_ptr<ProducerBuffer>& buffer,
                               size_t slot);
 
   // Inserts a ProducerBuffer into the queue. On success, the method returns the
@@ -341,7 +341,7 @@
   // being inserted should be in Gain'ed state prior to the call and it's
   // considered as already Dequeued when the function returns.
   pdx::Status<size_t> InsertBuffer(
-      const std::shared_ptr<BufferProducer>& buffer);
+      const std::shared_ptr<ProducerBuffer>& buffer);
 
   // Remove producer buffer from the queue.
   pdx::Status<void> RemoveBuffer(size_t slot) override;
@@ -355,7 +355,7 @@
   // and caller should call Post() once it's done writing to release the buffer
   // to the consumer side.
   // @return a buffer in gained state, which was originally in released state.
-  pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
+  pdx::Status<std::shared_ptr<ProducerBuffer>> Dequeue(
       int timeout, size_t* slot, pdx::LocalHandle* release_fence);
 
   // Dequeue a producer buffer to write. The returned buffer in |Gain|'ed mode,
@@ -363,7 +363,7 @@
   // to the consumer side.
   //
   // @param timeout to dequeue a buffer.
-  // @param slot is the slot of the output BufferProducer.
+  // @param slot is the slot of the output ProducerBuffer.
   // @param release_fence for gaining a buffer.
   // @param out_meta metadata of the output buffer.
   // @param gain_posted_buffer whether to gain posted buffer if no released
@@ -375,12 +375,12 @@
   // libdvrtracking from starving when there are non-responding clients. This
   // gain_posted_buffer param can be removed once libdvrtracking start to use
   // the new AHardwareBuffer API.
-  pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
+  pdx::Status<std::shared_ptr<ProducerBuffer>> Dequeue(
       int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
       pdx::LocalHandle* release_fence, bool gain_posted_buffer = false);
 
   // Enqueues a producer buffer in the queue.
-  pdx::Status<void> Enqueue(const std::shared_ptr<BufferProducer>& buffer,
+  pdx::Status<void> Enqueue(const std::shared_ptr<ProducerBuffer>& buffer,
                             size_t slot, uint64_t index) {
     return BufferHubQueue::Enqueue({buffer, slot, index});
   }
@@ -406,18 +406,18 @@
   // @param slot the slot of the returned buffer.
   // @return a buffer in gained state, which was originally in posted state or
   //     released state.
-  pdx::Status<std::shared_ptr<BufferProducer>> DequeueUnacquiredBuffer(
+  pdx::Status<std::shared_ptr<ProducerBuffer>> DequeueUnacquiredBuffer(
       size_t* slot);
 };
 
 class ConsumerQueue : public BufferHubQueue {
  public:
-  // Get a buffer consumer. Note that the method doesn't check whether the
+  // Get a consumer buffer. Note that the method doesn't check whether the
   // buffer slot has a valid buffer that has been imported already. When no
   // buffer has been imported before it returns nullptr; otherwise returns a
-  // shared pointer to a BufferConsumer.
-  std::shared_ptr<BufferConsumer> GetBuffer(size_t slot) const {
-    return std::static_pointer_cast<BufferConsumer>(
+  // shared pointer to a ConsumerBuffer.
+  std::shared_ptr<ConsumerBuffer> GetBuffer(size_t slot) const {
+    return std::static_pointer_cast<ConsumerBuffer>(
         BufferHubQueue::GetBuffer(slot));
   }
 
@@ -435,36 +435,36 @@
   // Dequeue a consumer buffer to read. The returned buffer in |Acquired|'ed
   // mode, and caller should call Releasse() once it's done writing to release
   // the buffer to the producer side. |meta| is passed along from BufferHub,
-  // The user of BufferProducer is responsible with making sure that the
+  // The user of ProducerBuffer is responsible with making sure that the
   // Dequeue() is done with the corect metadata type and size with those used
   // when the buffer is orignally created.
   template <typename Meta>
-  pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+  pdx::Status<std::shared_ptr<ConsumerBuffer>> Dequeue(
       int timeout, size_t* slot, Meta* meta, pdx::LocalHandle* acquire_fence) {
     return Dequeue(timeout, slot, meta, sizeof(*meta), acquire_fence);
   }
-  pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+  pdx::Status<std::shared_ptr<ConsumerBuffer>> Dequeue(
       int timeout, size_t* slot, pdx::LocalHandle* acquire_fence) {
     return Dequeue(timeout, slot, nullptr, 0, acquire_fence);
   }
 
-  pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+  pdx::Status<std::shared_ptr<ConsumerBuffer>> Dequeue(
       int timeout, size_t* slot, void* meta, size_t user_metadata_size,
       pdx::LocalHandle* acquire_fence);
-  pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+  pdx::Status<std::shared_ptr<ConsumerBuffer>> Dequeue(
       int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
       pdx::LocalHandle* acquire_fence);
 
  private:
   friend BufferHubQueue;
 
-  ConsumerQueue(pdx::LocalChannelHandle handle);
+  explicit ConsumerQueue(pdx::LocalChannelHandle handle);
 
   // Add a consumer buffer to populate the queue. Once added, a consumer buffer
   // is NOT available to use until the producer side |Post| it. |WaitForBuffers|
   // will catch the |Post| and |Acquire| the buffer to make it available for
   // consumer.
-  pdx::Status<void> AddBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+  pdx::Status<void> AddBuffer(const std::shared_ptr<ConsumerBuffer>& buffer,
                               size_t slot);
 
   pdx::Status<void> OnBufferAllocated() override;
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
index ad3f56b..36ab5f6 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_parcelable.h
@@ -35,7 +35,7 @@
   }
 
   // Constructs an parcelable contains the channel parcelable.
-  BufferHubQueueParcelable(
+  explicit BufferHubQueueParcelable(
       std::unique_ptr<pdx::ChannelParcelable> channel_parcelable)
       : channel_parcelable_(std::move(channel_parcelable)) {}
 
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index 159d6dc..6ae603b 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -125,7 +125,7 @@
 }
 
 TEST_F(BufferHubQueueTest,
-       TestDequeuePostedBufferIfNoAvailableReleasedBuffer_withBufferConsumer) {
+       TestDequeuePostedBufferIfNoAvailableReleasedBuffer_withConsumerBuffer) {
   ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
 
   // Allocate 3 buffers to use.
@@ -205,7 +205,7 @@
 }
 
 TEST_F(BufferHubQueueTest,
-       TestDequeuePostedBufferIfNoAvailableReleasedBuffer_noBufferConsumer) {
+       TestDequeuePostedBufferIfNoAvailableReleasedBuffer_noConsumerBuffer) {
   ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
 
   // Allocate 4 buffers to use.
@@ -332,7 +332,7 @@
   EXPECT_EQ(producer_queue_->capacity(), 0);
   EXPECT_EQ(consumer_queue_->capacity(), 0);
 
-  std::shared_ptr<BufferProducer> p1 = BufferProducer::Create(
+  std::shared_ptr<ProducerBuffer> p1 = ProducerBuffer::Create(
       kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage, 0);
   ASSERT_TRUE(p1 != nullptr);
   ASSERT_EQ(p1->GainAsync(), 0);
@@ -345,7 +345,7 @@
   EXPECT_EQ(status_or_slot.error(), EINVAL);
 
   // Inserting a gained buffer will succeed.
-  std::shared_ptr<BufferProducer> p2 = BufferProducer::Create(
+  std::shared_ptr<ProducerBuffer> p2 = ProducerBuffer::Create(
       kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage);
   ASSERT_EQ(p2->GainAsync(), 0);
   ASSERT_TRUE(p2 != nullptr);
@@ -382,7 +382,7 @@
   // Dequeue all the buffers and keep track of them in an array. This prevents
   // the producer queue ring buffer ref counts from interfering with the tests.
   struct Entry {
-    std::shared_ptr<BufferProducer> buffer;
+    std::shared_ptr<ProducerBuffer> buffer;
     LocalHandle fence;
     size_t slot;
   };
@@ -848,10 +848,10 @@
   size_t slot;
   LocalHandle fence;
   pdx::Status<void> status;
-  pdx::Status<std::shared_ptr<BufferConsumer>> consumer_status;
-  pdx::Status<std::shared_ptr<BufferProducer>> producer_status;
-  std::shared_ptr<BufferConsumer> consumer_buffer;
-  std::shared_ptr<BufferProducer> producer_buffer;
+  pdx::Status<std::shared_ptr<ConsumerBuffer>> consumer_status;
+  pdx::Status<std::shared_ptr<ProducerBuffer>> producer_status;
+  std::shared_ptr<ConsumerBuffer> consumer_buffer;
+  std::shared_ptr<ProducerBuffer> producer_buffer;
   DvrNativeBufferMetadata mi, mo;
 
   ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
@@ -994,7 +994,7 @@
   auto s3 = producer_queue_->Dequeue(0, &slot, &producer_meta, &fence);
   EXPECT_TRUE(s3.ok());
 
-  std::shared_ptr<BufferProducer> p1 = s3.take();
+  std::shared_ptr<ProducerBuffer> p1 = s3.take();
   ASSERT_NE(p1, nullptr);
 
   producer_meta.timestamp = 42;
@@ -1061,7 +1061,7 @@
   auto s2 = producer_queue_->Dequeue(0, &slot, &producer_meta, &fence);
   EXPECT_TRUE(s2.ok());
 
-  std::shared_ptr<BufferProducer> p1 = s2.take();
+  std::shared_ptr<ProducerBuffer> p1 = s2.take();
   ASSERT_NE(p1, nullptr);
 
   producer_meta.timestamp = 42;
diff --git a/libs/vr/libdisplay/include/private/dvr/display_protocol.h b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
index eff50ba..3786d1d 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_protocol.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_protocol.h
@@ -60,11 +60,13 @@
   using Base = Flags<Integer>;
   using Type = Integer;
 
+  // NOLINTNEXTLINE(google-explicit-constructor)
   Flags(const Integer& value) : value_{value} {}
   Flags(const Flags&) = default;
   Flags& operator=(const Flags&) = default;
 
   Integer value() const { return value_; }
+  // NOLINTNEXTLINE(google-explicit-constructor)
   operator Integer() const { return value_; }
 
   bool IsSet(Integer bits) const { return (value_ & bits) == bits; }
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index f4c6600..1ca653c 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -8,10 +8,10 @@
 #include "dvr_buffer_queue_internal.h"
 
 using namespace android;
-using android::dvr::BufferConsumer;
 using android::dvr::BufferHubBase;
-using android::dvr::BufferProducer;
+using android::dvr::ConsumerBuffer;
 using android::dvr::ConsumerQueue;
+using android::dvr::ProducerBuffer;
 using android::dvr::ProducerQueue;
 using android::dvr::ProducerQueueConfigBuilder;
 using android::dvr::UsagePolicy;
@@ -103,13 +103,13 @@
         "DvrWriteBufferQueue::GainBuffer: Buffer slot is not empty: %zu", slot);
     write_buffers_[slot]->write_buffer = std::move(buffer_status.take());
 
-    const auto& buffer_producer = write_buffers_[slot]->write_buffer;
-    if (!buffer_producer)
+    const auto& producer_buffer = write_buffers_[slot]->write_buffer;
+    if (!producer_buffer)
       return -ENOMEM;
 
-    if (width_ == buffer_producer->width() &&
-        height_ == buffer_producer->height() &&
-        format_ == buffer_producer->format()) {
+    if (width_ == producer_buffer->width() &&
+        height_ == producer_buffer->height() &&
+        format_ == producer_buffer->format()) {
       // Producer queue returns a buffer matches the current request.
       break;
     }
@@ -122,14 +122,14 @@
              "DvrWriteBufferQueue::Dequeue: requested buffer at slot: %zu "
              "(w=%u, h=%u, fmt=%u) is different from the buffer returned "
              "(w=%u, h=%u, fmt=%u). Need re-allocation.",
-             slot, width_, height_, format_, buffer_producer->width(),
-             buffer_producer->height(), buffer_producer->format());
+             slot, width_, height_, format_, producer_buffer->width(),
+             producer_buffer->height(), producer_buffer->format());
 
     // Currently, we are not storing |layer_count| and |usage| in queue
     // configuration. Copy those setup from the last buffer dequeued before we
     // remove it.
-    uint32_t old_layer_count = buffer_producer->layer_count();
-    uint64_t old_usage = buffer_producer->usage();
+    uint32_t old_layer_count = producer_buffer->layer_count();
+    uint64_t old_usage = producer_buffer->usage();
 
     // Allocate a new producer buffer with new buffer configs. Note that if
     // there are already multiple available buffers in the queue, the next one
@@ -443,7 +443,7 @@
           // When buffer is removed from the queue, the slot is already invalid.
           auto read_buffer = std::make_unique<DvrReadBuffer>();
           read_buffer->read_buffer =
-              std::static_pointer_cast<BufferConsumer>(buffer);
+              std::static_pointer_cast<ConsumerBuffer>(buffer);
           callback(read_buffer.release(), context);
         });
   }
diff --git a/libs/vr/libdvr/dvr_display_manager.cpp b/libs/vr/libdvr/dvr_display_manager.cpp
index fe91b14..7f631e3 100644
--- a/libs/vr/libdvr/dvr_display_manager.cpp
+++ b/libs/vr/libdvr/dvr_display_manager.cpp
@@ -10,10 +10,10 @@
 #include "dvr_internal.h"
 #include "dvr_buffer_queue_internal.h"
 
-using android::dvr::BufferConsumer;
+using android::dvr::ConsumerBuffer;
 using android::dvr::display::DisplayManagerClient;
-using android::dvr::display::SurfaceAttributes;
 using android::dvr::display::SurfaceAttribute;
+using android::dvr::display::SurfaceAttributes;
 using android::dvr::display::SurfaceState;
 using android::pdx::rpc::EmptyVariant;
 
diff --git a/libs/vr/libdvr/dvr_internal.h b/libs/vr/libdvr/dvr_internal.h
index df8125a..f845cd8 100644
--- a/libs/vr/libdvr/dvr_internal.h
+++ b/libs/vr/libdvr/dvr_internal.h
@@ -16,21 +16,11 @@
 namespace android {
 namespace dvr {
 
-// TODO(b/116855254): Remove this typedef once rename is complete in libdvr.
-// Note that the dvr::BufferProducer and dvr::BufferConsumer were poorly named,
-// they should really be named as ProducerBuffer and ConsumerBuffer.
-typedef class ProducerBuffer BufferProducer;
-typedef class ConsumerBuffer BufferConsumer;
 class IonBuffer;
 
 DvrBuffer* CreateDvrBufferFromIonBuffer(
     const std::shared_ptr<IonBuffer>& ion_buffer);
 
-DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
-    const std::shared_ptr<BufferConsumer>& buffer_consumer);
-DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
-    const std::shared_ptr<BufferProducer>& buffer_producer);
-
 }  // namespace dvr
 }  // namespace android
 
@@ -42,7 +32,7 @@
   // DvrWriteBuffer acquired from a DvrWriteBufferQueue.
   int32_t slot = -1;
 
-  std::shared_ptr<android::dvr::BufferProducer> write_buffer;
+  std::shared_ptr<android::dvr::ProducerBuffer> write_buffer;
 };
 
 struct DvrReadBuffer {
@@ -51,7 +41,7 @@
   // DvrReadBuffer acquired from a DvrReadBufferQueue.
   int32_t slot = -1;
 
-  std::shared_ptr<android::dvr::BufferConsumer> read_buffer;
+  std::shared_ptr<android::dvr::ConsumerBuffer> read_buffer;
 };
 
 struct DvrBuffer {
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index a3a47f1..0c7ec01 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -14,7 +14,6 @@
 using android::dvr::display::Surface;
 using android::dvr::display::SurfaceAttributes;
 using android::dvr::display::SurfaceAttributeValue;
-using android::dvr::CreateDvrReadBufferFromBufferConsumer;
 using android::pdx::rpc::EmptyVariant;
 
 namespace {
diff --git a/libs/vr/libpdx/private/pdx/channel_handle.h b/libs/vr/libpdx/private/pdx/channel_handle.h
index daa08f4..bd04305 100644
--- a/libs/vr/libpdx/private/pdx/channel_handle.h
+++ b/libs/vr/libpdx/private/pdx/channel_handle.h
@@ -26,7 +26,7 @@
 class ChannelHandleBase {
  public:
   ChannelHandleBase() = default;
-  ChannelHandleBase(const int32_t& value) : value_{value} {}
+  explicit ChannelHandleBase(const int32_t& value) : value_{value} {}
 
   ChannelHandleBase(const ChannelHandleBase&) = delete;
   ChannelHandleBase& operator=(const ChannelHandleBase&) = delete;
diff --git a/libs/vr/libpdx/private/pdx/client.h b/libs/vr/libpdx/private/pdx/client.h
index c35dabd..7e2d55c 100644
--- a/libs/vr/libpdx/private/pdx/client.h
+++ b/libs/vr/libpdx/private/pdx/client.h
@@ -206,7 +206,7 @@
 class Transaction final : public OutputResourceMapper,
                           public InputResourceMapper {
  public:
-  Transaction(Client& client);
+  explicit Transaction(Client& client);
   ~Transaction();
 
   template <typename T>
diff --git a/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
index 0421220..43184dd 100644
--- a/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/buffer_wrapper.h
@@ -110,10 +110,10 @@
   using const_iterator = typename BufferType::const_iterator;
 
   BufferWrapper() {}
-  BufferWrapper(const BufferType& buffer) : buffer_(buffer) {}
+  explicit BufferWrapper(const BufferType& buffer) : buffer_(buffer) {}
   BufferWrapper(const BufferType& buffer, const Allocator& allocator)
       : buffer_(buffer, allocator) {}
-  BufferWrapper(BufferType&& buffer) : buffer_(std::move(buffer)) {}
+  explicit BufferWrapper(BufferType&& buffer) : buffer_(std::move(buffer)) {}
   BufferWrapper(BufferType&& buffer, const Allocator& allocator)
       : buffer_(std::move(buffer), allocator) {}
   BufferWrapper(const BufferWrapper&) = default;
diff --git a/libs/vr/libpdx/private/pdx/rpc/payload.h b/libs/vr/libpdx/private/pdx/rpc/payload.h
index a48a64c..d2df14f 100644
--- a/libs/vr/libpdx/private/pdx/rpc/payload.h
+++ b/libs/vr/libpdx/private/pdx/rpc/payload.h
@@ -83,7 +83,7 @@
                        public MessageWriter,
                        public MessageReader {
  public:
-  ServicePayload(Message& message) : message_(message) {}
+  explicit ServicePayload(Message& message) : message_(message) {}
 
   // MessageWriter
   void* GetNextWriteBufferSection(size_t size) override {
@@ -120,7 +120,8 @@
       MessageBuffer<ThreadLocalTypeSlot<ClientPayload<Slot>>, 1024u, int>;
   using BufferType = typename ContainerType::BufferType;
 
-  ClientPayload(Transaction& transaction) : transaction_{transaction} {}
+  explicit ClientPayload(Transaction& transaction)
+      : transaction_{transaction} {}
 
   // MessageWriter
   void* GetNextWriteBufferSection(size_t size) override {
diff --git a/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h b/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
index 1cb85de..88868fe 100644
--- a/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
+++ b/libs/vr/libpdx/private/pdx/rpc/pointer_wrapper.h
@@ -13,7 +13,7 @@
  public:
   using BaseType = T;
 
-  PointerWrapper(T* pointer) : pointer_(pointer) {}
+  explicit PointerWrapper(T* pointer) : pointer_(pointer) {}
   PointerWrapper(const PointerWrapper&) = default;
   PointerWrapper(PointerWrapper&&) noexcept = default;
   PointerWrapper& operator=(const PointerWrapper&) = default;
diff --git a/libs/vr/libpdx/private/pdx/rpc/serialization.h b/libs/vr/libpdx/private/pdx/rpc/serialization.h
index f12aef1..914ea66 100644
--- a/libs/vr/libpdx/private/pdx/rpc/serialization.h
+++ b/libs/vr/libpdx/private/pdx/rpc/serialization.h
@@ -134,7 +134,7 @@
 
   // ErrorType constructor for generic error codes. Explicitly not explicit,
   // implicit conversion from ErrorCode to ErrorType is desirable behavior.
-  // NOLINTNEXTLINE(runtime/explicit)
+  // NOLINTNEXTLINE(google-explicit-constructor)
   ErrorType(ErrorCode error_code) : error_code_(error_code) {}
 
   // ErrorType constructor for encoding type errors.
@@ -148,6 +148,7 @@
   // Evaluates to true if the ErrorType represents an error.
   explicit operator bool() const { return error_code_ != ErrorCode::NO_ERROR; }
 
+  // NOLINTNEXTLINE(google-explicit-constructor)
   operator ErrorCode() const { return error_code_; }
   ErrorCode error_code() const { return error_code_; }
 
@@ -159,6 +160,7 @@
     return unexpected_encoding_.encoding_type;
   }
 
+  // NOLINTNEXTLINE(google-explicit-constructor)
   operator std::string() const {
     std::ostringstream stream;
 
diff --git a/libs/vr/libpdx/private/pdx/service.h b/libs/vr/libpdx/private/pdx/service.h
index d38b174..f5a2d5e 100644
--- a/libs/vr/libpdx/private/pdx/service.h
+++ b/libs/vr/libpdx/private/pdx/service.h
@@ -95,7 +95,7 @@
 class Message : public OutputResourceMapper, public InputResourceMapper {
  public:
   Message();
-  Message(const MessageInfo& info);
+  explicit Message(const MessageInfo& info);
   ~Message();
 
   /*
diff --git a/libs/vr/libpdx/private/pdx/status.h b/libs/vr/libpdx/private/pdx/status.h
index 7e51a52..498dd6d 100644
--- a/libs/vr/libpdx/private/pdx/status.h
+++ b/libs/vr/libpdx/private/pdx/status.h
@@ -11,6 +11,7 @@
 // This is a helper class for constructing Status<T> with an error code.
 struct ErrorStatus {
  public:
+  // NOLINTNEXTLINE(google-explicit-constructor)
   ErrorStatus(int error) : error_{error} {}
   int error() const { return error_; }
 
@@ -31,12 +32,14 @@
   // Value copy/move constructors. These are intentionally not marked as
   // explicit to allow direct value returns from functions without having
   // to explicitly wrap them into Status<T>().
-  Status(const T& value) : value_{value} {}        // NOLINT(runtime/explicit)
-  Status(T&& value) : value_{std::move(value)} {}  // NOLINT(runtime/explicit)
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  Status(const T& value) : value_{value} {}
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  Status(T&& value) : value_{std::move(value)} {}
 
   // Constructor for storing an error code inside the Status object.
-  Status(const ErrorStatus& error_status)  // NOLINT(runtime/explicit)
-      : error_{error_status.error()} {}
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  Status(const ErrorStatus& error_status) : error_{error_status.error()} {}
 
   // Copy/move constructors. Move constructor leaves |other| object in empty
   // state.
@@ -135,8 +138,8 @@
 class Status<void> {
  public:
   Status() = default;
-  Status(const ErrorStatus& error_status)  // NOLINT(runtime/explicit)
-      : error_{error_status.error()} {}
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  Status(const ErrorStatus& error_status) : error_{error_status.error()} {}
   void SetValue() { error_ = 0; }
   void SetError(int error) { error_ = error; }
 
diff --git a/libs/vr/libpdx/serialization_tests.cpp b/libs/vr/libpdx/serialization_tests.cpp
index 5ad1047..ee800f6 100644
--- a/libs/vr/libpdx/serialization_tests.cpp
+++ b/libs/vr/libpdx/serialization_tests.cpp
@@ -70,7 +70,7 @@
   FileHandleType fd;
 
   TestTemplateType() {}
-  TestTemplateType(FileHandleType fd) : fd(std::move(fd)) {}
+  explicit TestTemplateType(FileHandleType fd) : fd(std::move(fd)) {}
 
   bool operator==(const TestTemplateType& other) const {
     return fd.Get() == other.fd.Get();
diff --git a/libs/vr/libpdx/variant_tests.cpp b/libs/vr/libpdx/variant_tests.cpp
index e3520f5..a977fd3 100644
--- a/libs/vr/libpdx/variant_tests.cpp
+++ b/libs/vr/libpdx/variant_tests.cpp
@@ -14,18 +14,22 @@
 namespace {
 
 struct BaseType {
+  // NOLINTNEXTLINE(google-explicit-constructor)
   BaseType(int value) : value(value) {}
   int value;
 };
 
 struct DerivedType : BaseType {
+  // NOLINTNEXTLINE(google-explicit-constructor)
   DerivedType(int value) : BaseType{value} {};
 };
 
 template <typename T>
 class TestType {
  public:
+  // NOLINTNEXTLINE(google-explicit-constructor)
   TestType(const T& value) : value_(value) {}
+  // NOLINTNEXTLINE(google-explicit-constructor)
   TestType(T&& value) : value_(std::move(value)) {}
   TestType(const TestType&) = default;
   TestType(TestType&&) = default;
@@ -43,7 +47,9 @@
 template <typename T>
 class InstrumentType {
  public:
+  // NOLINTNEXTLINE(google-explicit-constructor)
   InstrumentType(const T& value) : value_(value) { constructor_count_++; }
+  // NOLINTNEXTLINE(google-explicit-constructor)
   InstrumentType(T&& value) : value_(std::move(value)) { constructor_count_++; }
   InstrumentType(const InstrumentType& other) : value_(other.value_) {
     constructor_count_++;
@@ -51,9 +57,11 @@
   InstrumentType(InstrumentType&& other) : value_(std::move(other.value_)) {
     constructor_count_++;
   }
+  // NOLINTNEXTLINE(google-explicit-constructor)
   InstrumentType(const TestType<T>& other) : value_(other.get()) {
     constructor_count_++;
   }
+  // NOLINTNEXTLINE(google-explicit-constructor)
   InstrumentType(TestType<T>&& other) : value_(other.take()) {
     constructor_count_++;
   }
@@ -1101,6 +1109,7 @@
 TEST(Variant, IsConstructible) {
   using ArrayType = const float[3];
   struct ImplicitBool {
+    // NOLINTNEXTLINE(google-explicit-constructor)
     operator bool() const { return true; }
   };
   struct ExplicitBool {
diff --git a/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp b/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp
index f72dabc..5c9e74c 100644
--- a/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp
+++ b/libs/vr/libpdx_default_transport/pdx_benchmarks.cpp
@@ -82,7 +82,7 @@
 class SchedStats {
  public:
   SchedStats() : SchedStats(gettid()) {}
-  SchedStats(pid_t task_id) : task_id_(task_id) {}
+  explicit SchedStats(pid_t task_id) : task_id_(task_id) {}
   SchedStats(const SchedStats&) = default;
   SchedStats& operator=(const SchedStats&) = default;
 
@@ -379,7 +379,7 @@
  private:
   friend BASE;
 
-  BenchmarkService(std::unique_ptr<Endpoint> endpoint)
+  explicit BenchmarkService(std::unique_ptr<Endpoint> endpoint)
       : BASE("BenchmarkService", std::move(endpoint)),
         send_buffer(kMaxMessageSize),
         receive_buffer(kMaxMessageSize) {}
@@ -492,7 +492,7 @@
  private:
   friend BASE;
 
-  BenchmarkClient(const std::string& service_path)
+  explicit BenchmarkClient(const std::string& service_path)
       : BASE(ClientChannelFactory::Create(service_path),
              ProgramOptions.timeout) {}
 
diff --git a/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h b/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h
index 81bb17b..3ebab86 100644
--- a/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h
+++ b/libs/vr/libpdx_default_transport/private/pdx/default_transport/service_utility.h
@@ -41,7 +41,8 @@
  private:
   friend BASE;
 
-  ServiceUtility(const std::string& endpoint_path, int* error = nullptr)
+  explicit ServiceUtility(const std::string& endpoint_path,
+                          int* error = nullptr)
       : BASE(ClientChannelFactory::Create(endpoint_path), 0) {
     if (error)
       *error = Client::error();
diff --git a/libs/vr/libpdx_uds/client_channel_tests.cpp b/libs/vr/libpdx_uds/client_channel_tests.cpp
index 1560030..c9c5d15 100644
--- a/libs/vr/libpdx_uds/client_channel_tests.cpp
+++ b/libs/vr/libpdx_uds/client_channel_tests.cpp
@@ -45,7 +45,7 @@
 
 class TestService : public ServiceBase<TestService> {
  public:
-  TestService(std::unique_ptr<Endpoint> endpoint)
+  explicit TestService(std::unique_ptr<Endpoint> endpoint)
       : ServiceBase{"TestService", std::move(endpoint)} {}
 
   Status<void> HandleMessage(Message& message) override {
@@ -78,7 +78,7 @@
 
 class TestServiceRunner {
  public:
-  TestServiceRunner(LocalHandle channel_socket) {
+  explicit TestServiceRunner(LocalHandle channel_socket) {
     auto endpoint = Endpoint::CreateFromSocketFd(LocalHandle{});
     endpoint->RegisterNewChannelForTests(std::move(channel_socket));
     service_ = TestService::Create(std::move(endpoint));
diff --git a/libs/vr/libpdx_uds/private/uds/ipc_helper.h b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
index 63b5b10..704a569 100644
--- a/libs/vr/libpdx_uds/private/uds/ipc_helper.h
+++ b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
@@ -57,7 +57,7 @@
 
 class SendPayload : public MessageWriter, public OutputResourceMapper {
  public:
-  SendPayload(SendInterface* sender = nullptr) : sender_{sender} {}
+  explicit SendPayload(SendInterface* sender = nullptr) : sender_{sender} {}
   Status<void> Send(const BorrowedHandle& socket_fd);
   Status<void> Send(const BorrowedHandle& socket_fd, const ucred* cred,
                     const iovec* data_vec = nullptr, size_t vec_count = 0);
@@ -85,7 +85,8 @@
 
 class ReceivePayload : public MessageReader, public InputResourceMapper {
  public:
-  ReceivePayload(RecvInterface* receiver = nullptr) : receiver_{receiver} {}
+  explicit ReceivePayload(RecvInterface* receiver = nullptr)
+      : receiver_{receiver} {}
   Status<void> Receive(const BorrowedHandle& socket_fd);
   Status<void> Receive(const BorrowedHandle& socket_fd, ucred* cred);
 
diff --git a/libs/vr/libpdx_uds/private/uds/service_endpoint.h b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
index 01ebf65..50fc484 100644
--- a/libs/vr/libpdx_uds/private/uds/service_endpoint.h
+++ b/libs/vr/libpdx_uds/private/uds/service_endpoint.h
@@ -117,7 +117,7 @@
   // This class must be instantiated using Create() static methods above.
   Endpoint(const std::string& endpoint_path, bool blocking,
            bool use_init_socket_fd = true);
-  Endpoint(LocalHandle socket_fd);
+  explicit Endpoint(LocalHandle socket_fd);
 
   void Init(LocalHandle socket_fd);
 
diff --git a/libs/vr/libpdx_uds/remote_method_tests.cpp b/libs/vr/libpdx_uds/remote_method_tests.cpp
index 3f25776..4f0670e 100644
--- a/libs/vr/libpdx_uds/remote_method_tests.cpp
+++ b/libs/vr/libpdx_uds/remote_method_tests.cpp
@@ -94,7 +94,7 @@
   FileHandleType fd;
 
   TestTemplateType() {}
-  TestTemplateType(FileHandleType fd) : fd(std::move(fd)) {}
+  explicit TestTemplateType(FileHandleType fd) : fd(std::move(fd)) {}
 
  private:
   PDX_SERIALIZABLE_MEMBERS(TestTemplateType<FileHandleType>, fd);
@@ -328,7 +328,7 @@
  private:
   friend BASE;
 
-  TestClient(LocalChannelHandle channel_handle)
+  explicit TestClient(LocalChannelHandle channel_handle)
       : BASE{android::pdx::uds::ClientChannel::Create(
             std::move(channel_handle))} {}
   TestClient()
diff --git a/libs/vr/libvrflinger/acquired_buffer.cpp b/libs/vr/libvrflinger/acquired_buffer.cpp
index 5d873d1..c360dee 100644
--- a/libs/vr/libvrflinger/acquired_buffer.cpp
+++ b/libs/vr/libvrflinger/acquired_buffer.cpp
@@ -8,11 +8,11 @@
 namespace android {
 namespace dvr {
 
-AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer,
                                LocalHandle acquire_fence, std::size_t slot)
     : buffer_(buffer), acquire_fence_(std::move(acquire_fence)), slot_(slot) {}
 
-AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer,
                                int* error) {
   LocalHandle fence;
   const int ret = buffer->Acquire(&fence);
@@ -75,7 +75,7 @@
   return std::move(acquire_fence_);
 }
 
-std::shared_ptr<BufferConsumer> AcquiredBuffer::ClaimBuffer() {
+std::shared_ptr<ConsumerBuffer> AcquiredBuffer::ClaimBuffer() {
   return std::move(buffer_);
 }
 
diff --git a/libs/vr/libvrflinger/acquired_buffer.h b/libs/vr/libvrflinger/acquired_buffer.h
index 9e35a39..7643e75 100644
--- a/libs/vr/libvrflinger/acquired_buffer.h
+++ b/libs/vr/libvrflinger/acquired_buffer.h
@@ -9,42 +9,42 @@
 namespace android {
 namespace dvr {
 
-// Manages the ACQUIRE/RELEASE ownership cycle of a BufferConsumer.
+// Manages the ACQUIRE/RELEASE ownership cycle of a ConsumerBuffer.
 class AcquiredBuffer {
  public:
   static constexpr int kEmptyFence = pdx::LocalHandle::kEmptyFileHandle;
 
   AcquiredBuffer() : buffer_(nullptr), acquire_fence_(kEmptyFence) {}
 
-  // Constructs an AcquiredBuffer from a BufferConsumer pointer and an acquire
-  // fence. The BufferConsumer MUST be in the ACQUIRED state prior to calling
+  // Constructs an AcquiredBuffer from a ConsumerBuffer pointer and an acquire
+  // fence. The ConsumerBuffer MUST be in the ACQUIRED state prior to calling
   // this constructor; the constructor does not attempt to ACQUIRE the buffer
   // itself.
-  AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+  AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer,
                  pdx::LocalHandle acquire_fence, std::size_t slot = 0);
 
-  // Constructs an AcquiredBuffer from a BufferConsumer. The BufferConsumer MUST
+  // Constructs an AcquiredBuffer from a ConsumerBuffer. The ConsumerBuffer MUST
   // be in the POSTED state prior to calling this constructor, as this
   // constructor attempts to ACQUIRE the buffer. If ACQUIRING the buffer fails
   // this instance is left in the empty state. An optional error code is
   // returned in |error|, which may be nullptr if not needed.
-  AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer, int* error);
+  AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer, int* error);
 
   // Move constructor. Behaves similarly to the move assignment operator below.
   AcquiredBuffer(AcquiredBuffer&& other) noexcept;
 
   ~AcquiredBuffer();
 
-  // Move assignment operator. Moves the BufferConsumer and acquire fence from
-  // |other| into this instance after RELEASING the current BufferConsumer and
+  // Move assignment operator. Moves the ConsumerBuffer and acquire fence from
+  // |other| into this instance after RELEASING the current ConsumerBuffer and
   // closing the acquire fence. After the move |other| is left in the empty
   // state.
   AcquiredBuffer& operator=(AcquiredBuffer&& other) noexcept;
 
-  // Accessors for the underlying BufferConsumer, the acquire fence, and the
+  // Accessors for the underlying ConsumerBuffer, the acquire fence, and the
   // use-case specific sequence value from the acquisition (see
   // private/dvr/consumer_buffer.h).
-  std::shared_ptr<BufferConsumer> buffer() const { return buffer_; }
+  std::shared_ptr<ConsumerBuffer> buffer() const { return buffer_; }
   int acquire_fence() const { return acquire_fence_.Get(); }
 
   // When non-empty, returns true if the acquired fence was signaled (or if the
@@ -58,11 +58,11 @@
 
   // Returns the buffer, passing ownership to the caller. Caller is responsible
   // for calling Release on the returned buffer.
-  std::shared_ptr<BufferConsumer> ClaimBuffer();
+  std::shared_ptr<ConsumerBuffer> ClaimBuffer();
 
-  // Releases the BufferConsumer, passing the release fence in |release_fence|
-  // to the producer. On success, the BufferConsumer and acquire fence are set
-  // to empty state; if release fails, the BufferConsumer and acquire fence are
+  // Releases the ConsumerBuffer, passing the release fence in |release_fence|
+  // to the producer. On success, the ConsumerBuffer and acquire fence are set
+  // to empty state; if release fails, the ConsumerBuffer and acquire fence are
   // left in place and a negative error code is returned.
   int Release(pdx::LocalHandle release_fence = {});
 
@@ -71,7 +71,7 @@
   std::size_t slot() const { return slot_; }
 
  private:
-  std::shared_ptr<BufferConsumer> buffer_;
+  std::shared_ptr<ConsumerBuffer> buffer_;
   // Mutable so that the fence can be closed when it is determined to be
   // signaled during IsAvailable().
   mutable pdx::LocalHandle acquire_fence_;
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 6d259bd..e1240d6 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -104,7 +104,7 @@
 class TraceArgs {
  public:
   template <typename... Args>
-  TraceArgs(const char* format, Args&&... args) {
+  explicit TraceArgs(const char* format, Args&&... args) {
     std::array<char, 1024> buffer;
     snprintf(buffer.data(), buffer.size(), format, std::forward<Args>(args)...);
     atrace_begin(ATRACE_TAG, buffer.data());
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index 6c25b3e..db0d6a7 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -195,7 +195,7 @@
     AcquiredBuffer acquired_buffer;
     pdx::LocalHandle release_fence;
 
-    SourceSurface(const std::shared_ptr<DirectDisplaySurface>& surface)
+    explicit SourceSurface(const std::shared_ptr<DirectDisplaySurface>& surface)
         : surface(surface) {}
 
     // Attempts to acquire a new buffer from the surface and return a tuple with
diff --git a/libs/vr/libvrflinger/hwc_types.h b/libs/vr/libvrflinger/hwc_types.h
index cbf636c..8b5c3b3 100644
--- a/libs/vr/libvrflinger/hwc_types.h
+++ b/libs/vr/libvrflinger/hwc_types.h
@@ -116,19 +116,24 @@
   Wrapper(const Wrapper&) = default;
 
   // Implicit conversion from ValueType.
+  // NOLINTNEXTLINE(google-explicit-constructor)
   Wrapper(ValueType value) : value(value) {}
 
   // Implicit conversion from BaseType.
+  // NOLINTNEXTLINE(google-explicit-constructor)
   Wrapper(BaseType value) : value(static_cast<ValueType>(value)) {}
 
   // Implicit conversion from an enum type of the same underlying type.
   template <typename T, typename = EnableIfMatchingEnum<T, ValueType>>
+  // NOLINTNEXTLINE(google-explicit-constructor)
   Wrapper(const T& value) : value(static_cast<ValueType>(value)) {}
 
   // Implicit conversion to BaseType.
+  // NOLINTNEXTLINE(google-explicit-constructor)
   operator BaseType() const { return static_cast<BaseType>(value); }
 
   // Implicit conversion to ValueType.
+  // NOLINTNEXTLINE(google-explicit-constructor)
   operator ValueType() const { return value; }
 
   template <typename T, typename = EnableIfMatchingEnum<T, ValueType>>
@@ -275,8 +280,10 @@
 struct Color final {
   Color(const Color&) = default;
   Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a) {}
+  // NOLINTNEXTLINE(google-explicit-constructor)
   Color(hwc_color_t color) : r(color.r), g(color.g), b(color.b), a(color.a) {}
 
+  // NOLINTNEXTLINE(google-explicit-constructor)
   operator hwc_color_t() const { return {r, g, b, a}; }
 
   uint8_t r __attribute__((aligned(1)));
diff --git a/libs/vr/libvrflinger/include/dvr/vr_flinger.h b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
index c740dde..ae52076 100644
--- a/libs/vr/libvrflinger/include/dvr/vr_flinger.h
+++ b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
@@ -49,7 +49,8 @@
   // Needs to be a separate class for binder's ref counting
   class PersistentVrStateCallback : public BnPersistentVrStateCallbacks {
    public:
-    PersistentVrStateCallback(RequestDisplayCallback request_display_callback)
+    explicit PersistentVrStateCallback(
+        RequestDisplayCallback request_display_callback)
         : request_display_callback_(request_display_callback) {}
     void onPersistentVrStateChanged(bool enabled) override;
    private:
diff --git a/libs/vr/libvrsensor/include/private/dvr/latency_model.h b/libs/vr/libvrsensor/include/private/dvr/latency_model.h
index 40b4638..bf0e687 100644
--- a/libs/vr/libvrsensor/include/private/dvr/latency_model.h
+++ b/libs/vr/libvrsensor/include/private/dvr/latency_model.h
@@ -10,7 +10,7 @@
 // window_size measurements and return their average after that.
 class LatencyModel {
  public:
-  LatencyModel(size_t window_size);
+  explicit LatencyModel(size_t window_size);
   ~LatencyModel() = default;
 
   void AddLatency(int64_t latency_ns);
diff --git a/libs/vr/libvrsensor/pose_client.cpp b/libs/vr/libvrsensor/pose_client.cpp
index c72f75e..4ff6a09 100644
--- a/libs/vr/libvrsensor/pose_client.cpp
+++ b/libs/vr/libvrsensor/pose_client.cpp
@@ -221,7 +221,7 @@
       return -status.error();
     }
 
-    auto buffer = BufferConsumer::Import(status.take());
+    auto buffer = ConsumerBuffer::Import(status.take());
     if (!buffer) {
       ALOGE("Pose failed to import ring buffer");
       return -EIO;
@@ -290,7 +290,7 @@
   const DvrVsyncPoseBuffer* mapped_vsync_pose_buffer_ = nullptr;
 
   struct ControllerClientState {
-    std::unique_ptr<BufferConsumer> pose_buffer;
+    std::unique_ptr<ConsumerBuffer> pose_buffer;
     const DvrPoseAsync* mapped_pose_buffer = nullptr;
   };
   ControllerClientState controllers_[MAX_CONTROLLERS];
diff --git a/opengl/libs/EGL/egl_angle_platform.cpp b/opengl/libs/EGL/egl_angle_platform.cpp
index 297e0c4..00caff2 100644
--- a/opengl/libs/EGL/egl_angle_platform.cpp
+++ b/opengl/libs/EGL/egl_angle_platform.cpp
@@ -106,7 +106,7 @@
             .flags = ANDROID_DLEXT_USE_NAMESPACE,
             .library_namespace = ns,
     };
-    void* so = android_dlopen_ext("libEGL_angle.so", RTLD_LOCAL | RTLD_NOW, &dlextinfo);
+    void* so = android_dlopen_ext("libGLESv2_angle.so", RTLD_LOCAL | RTLD_NOW, &dlextinfo);
     angleGetDisplayPlatform =
             reinterpret_cast<GetDisplayPlatformFunc>(dlsym(so, "ANGLEGetDisplayPlatform"));
 
diff --git a/opengl/tests/hwc/hwcCommit.cpp b/opengl/tests/hwc/hwcCommit.cpp
index 3686dab..0a6ff55 100644
--- a/opengl/tests/hwc/hwcCommit.cpp
+++ b/opengl/tests/hwc/hwcCommit.cpp
@@ -183,7 +183,7 @@
     uint32_t lower(void) { return _l; }
     uint32_t upper(void) { return _u; }
 
-    operator string();
+    operator string(); // NOLINT(google-explicit-constructor)
 
 private:
     uint32_t _l; // lower
@@ -216,7 +216,9 @@
     static void double2Rational(double f, Range nRange, Range dRange,
                                Rational& lower, Rational& upper);
         
+    // NOLINTNEXTLINE(google-explicit-constructor)
     operator string() const;
+    // NOLINTNEXTLINE(google-explicit-constructor)
     operator double() const { return (double) _n / (double) _d; }
 
 
diff --git a/opengl/tests/hwc/hwcTestLib.h b/opengl/tests/hwc/hwcTestLib.h
index 922fc19..5a49393 100644
--- a/opengl/tests/hwc/hwcTestLib.h
+++ b/opengl/tests/hwc/hwcTestLib.h
@@ -58,7 +58,7 @@
     float c2(void) const { return _c2; }
     float c3(void) const { return _c3; }
 
-    operator std::string();
+    operator std::string(); // NOLINT(google-explicit-constructor)
 
   private:
     float _c1;
@@ -71,7 +71,7 @@
 class ColorRGB {
   public:
     ColorRGB(): _r(0.0), _g(0.0), _b(0.0) {};
-    ColorRGB(float f): _r(f), _g(f), _b(f) {}; // Gray, NOLINT(implicit)
+    ColorRGB(float f): _r(f), _g(f), _b(f) {}; // Gray, NOLINT(google-explicit-constructor)
     ColorRGB(float r, float g, float b): _r(r), _g(g), _b(b) {};
     float r(void) const { return _r; }
     float g(void) const { return _g; }
@@ -93,8 +93,8 @@
     void setWidth(uint32_t w) { _w = w; }
     void setHeight(uint32_t h) { _h = h; }
 
-    operator std::string();
-    operator hwc_rect() const;
+    operator std::string(); // NOLINT(google-explicit-constructor)
+    operator hwc_rect() const; // NOLINT(google-explicit-constructor)
 
   private:
     uint32_t _w;
diff --git a/services/bufferhub/Android.bp b/services/bufferhub/Android.bp
index 72d210c..a4b81fe 100644
--- a/services/bufferhub/Android.bp
+++ b/services/bufferhub/Android.bp
@@ -34,6 +34,7 @@
     ],
     shared_libs: [
         "android.frameworks.bufferhub@1.0",
+        "libcrypto",
         "libcutils",
         "libhidlbase",
         "libhidltransport",
@@ -60,6 +61,7 @@
     shared_libs: [
         "android.frameworks.bufferhub@1.0",
         "libbufferhubservice",
+        "libcrypto",
         "libcutils",
         "libhidltransport",
         "libhwbinder",
diff --git a/services/bufferhub/BufferHubIdGenerator.cpp b/services/bufferhub/BufferHubIdGenerator.cpp
index 6444a03..2c12f0e 100644
--- a/services/bufferhub/BufferHubIdGenerator.cpp
+++ b/services/bufferhub/BufferHubIdGenerator.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <bufferhub/BufferHubIdGenerator.h>
+#include <log/log.h>
 
 namespace android {
 namespace frameworks {
@@ -22,20 +23,18 @@
 namespace V1_0 {
 namespace implementation {
 
-constexpr uint32_t BufferHubIdGenerator::kInvalidId;
-
 BufferHubIdGenerator& BufferHubIdGenerator::getInstance() {
     static BufferHubIdGenerator generator;
 
     return generator;
 }
 
-uint32_t BufferHubIdGenerator::getId() {
+int BufferHubIdGenerator::getId() {
     std::lock_guard<std::mutex> lock(mIdsInUseMutex);
 
     do {
-        if (++mLastId >= std::numeric_limits<uint32_t>::max()) {
-            mLastId = kInvalidId + 1;
+        if (++mLastId >= std::numeric_limits<int>::max()) {
+            mLastId = 0;
         }
     } while (mIdsInUse.find(mLastId) != mIdsInUse.end());
 
@@ -43,15 +42,14 @@
     return mLastId;
 }
 
-bool BufferHubIdGenerator::freeId(uint32_t id) {
+void BufferHubIdGenerator::freeId(int id) {
     std::lock_guard<std::mutex> lock(mIdsInUseMutex);
     auto iter = mIdsInUse.find(id);
     if (iter != mIdsInUse.end()) {
         mIdsInUse.erase(iter);
-        return true;
+    } else {
+        ALOGW("%s: Cannot free nonexistent id #%d", __FUNCTION__, id);
     }
-
-    return false;
 }
 
 } // namespace implementation
diff --git a/services/bufferhub/BufferHubService.cpp b/services/bufferhub/BufferHubService.cpp
index 2663812..a40443d 100644
--- a/services/bufferhub/BufferHubService.cpp
+++ b/services/bufferhub/BufferHubService.cpp
@@ -14,10 +14,21 @@
  * limitations under the License.
  */
 
+#include <array>
+#include <iomanip>
+#include <random>
+#include <sstream>
+
 #include <android/hardware_buffer.h>
 #include <bufferhub/BufferHubService.h>
 #include <cutils/native_handle.h>
 #include <log/log.h>
+#include <openssl/hmac.h>
+#include <system/graphics-base.h>
+#include <ui/BufferHubDefs.h>
+
+using ::android::BufferHubDefs::MetadataHeader;
+using ::android::hardware::Void;
 
 namespace android {
 namespace frameworks {
@@ -25,7 +36,12 @@
 namespace V1_0 {
 namespace implementation {
 
-using hardware::Void;
+BufferHubService::BufferHubService() {
+    std::mt19937_64 randomEngine;
+    randomEngine.seed(time(nullptr));
+
+    mKey = randomEngine();
+}
 
 Return<void> BufferHubService::allocateBuffer(const HardwareBufferDescription& description,
                                               const uint32_t userMetadataSize,
@@ -49,10 +65,12 @@
     std::lock_guard<std::mutex> lock(mClientSetMutex);
     mClientSet.emplace(client);
 
+    hidl_handle bufferInfo =
+            buildBufferInfo(node->id(), node->AddNewActiveClientsBitToMask(),
+                            node->user_metadata_size(), node->metadata().ashmem_fd());
     BufferTraits bufferTraits = {/*bufferDesc=*/description,
                                  /*bufferHandle=*/hidl_handle(node->buffer_handle()),
-                                 // TODO(b/116681016): return real data to client
-                                 /*bufferInfo=*/hidl_handle()};
+                                 /*bufferInfo=*/bufferInfo};
 
     _hidl_cb(/*status=*/BufferHubStatus::NO_ERROR, /*bufferClient=*/client,
              /*bufferTraits=*/bufferTraits);
@@ -61,27 +79,49 @@
 
 Return<void> BufferHubService::importBuffer(const hidl_handle& tokenHandle,
                                             importBuffer_cb _hidl_cb) {
-    if (!tokenHandle.getNativeHandle() || tokenHandle->numFds != 0 || tokenHandle->numInts != 1) {
+    if (!tokenHandle.getNativeHandle() || tokenHandle->numFds != 0 || tokenHandle->numInts <= 1) {
         // nullptr handle or wrong format
         _hidl_cb(/*status=*/BufferHubStatus::INVALID_TOKEN, /*bufferClient=*/nullptr,
                  /*bufferTraits=*/{});
         return Void();
     }
 
-    uint32_t token = tokenHandle->data[0];
+    int tokenId = tokenHandle->data[0];
 
     wp<BufferClient> originClientWp;
     {
-        std::lock_guard<std::mutex> lock(mTokenMapMutex);
-        auto iter = mTokenMap.find(token);
+        std::lock_guard<std::mutex> lock(mTokenMutex);
+        auto iter = mTokenMap.find(tokenId);
         if (iter == mTokenMap.end()) {
-            // Invalid token
+            // Token Id not exist
+            ALOGD("%s: token #%d not found.", __FUNCTION__, tokenId);
             _hidl_cb(/*status=*/BufferHubStatus::INVALID_TOKEN, /*bufferClient=*/nullptr,
                      /*bufferTraits=*/{});
             return Void();
         }
 
-        originClientWp = iter->second;
+        const std::vector<uint8_t>& tokenHMAC = iter->second.first;
+
+        int numIntsForHMAC = (int)ceil(tokenHMAC.size() * sizeof(uint8_t) / (double)sizeof(int));
+        if (tokenHandle->numInts - 1 != numIntsForHMAC) {
+            // HMAC size not match
+            ALOGD("%s: token #%d HMAC size not match. Expected: %d Actual: %d", __FUNCTION__,
+                  tokenId, numIntsForHMAC, tokenHandle->numInts - 1);
+            _hidl_cb(/*status=*/BufferHubStatus::INVALID_TOKEN, /*bufferClient=*/nullptr,
+                     /*bufferTraits=*/{});
+            return Void();
+        }
+
+        size_t hmacSize = tokenHMAC.size() * sizeof(uint8_t);
+        if (memcmp(tokenHMAC.data(), &tokenHandle->data[1], hmacSize) != 0) {
+            // HMAC not match
+            ALOGD("%s: token #%d HMAC not match.", __FUNCTION__, tokenId);
+            _hidl_cb(/*status=*/BufferHubStatus::INVALID_TOKEN, /*bufferClient=*/nullptr,
+                     /*bufferTraits=*/{});
+            return Void();
+        }
+
+        originClientWp = iter->second.second;
         mTokenMap.erase(iter);
     }
 
@@ -114,32 +154,181 @@
     HardwareBufferDescription bufferDesc;
     memcpy(&bufferDesc, &node->buffer_desc(), sizeof(HardwareBufferDescription));
 
+    hidl_handle bufferInfo =
+            buildBufferInfo(node->id(), clientStateMask, node->user_metadata_size(),
+                            node->metadata().ashmem_fd());
     BufferTraits bufferTraits = {/*bufferDesc=*/bufferDesc,
                                  /*bufferHandle=*/hidl_handle(node->buffer_handle()),
-                                 // TODO(b/116681016): return real data to client
-                                 /*bufferInfo=*/hidl_handle()};
+                                 /*bufferInfo=*/bufferInfo};
 
     _hidl_cb(/*status=*/BufferHubStatus::NO_ERROR, /*bufferClient=*/client,
              /*bufferTraits=*/bufferTraits);
     return Void();
 }
 
-hidl_handle BufferHubService::registerToken(const wp<BufferClient>& client) {
-    uint32_t token;
-    std::lock_guard<std::mutex> lock(mTokenMapMutex);
-    do {
-        token = mTokenEngine();
-    } while (mTokenMap.find(token) != mTokenMap.end());
+Return<void> BufferHubService::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) {
+    if (fd.getNativeHandle() == nullptr || fd->numFds < 1) {
+        ALOGE("%s: missing fd for writing.", __FUNCTION__);
+        return Void();
+    }
 
-    // native_handle_t use int[], so here need one slots to fit in uint32_t
-    native_handle_t* handle = native_handle_create(/*numFds=*/0, /*numInts=*/1);
-    handle->data[0] = token;
+    FILE* out = fdopen(dup(fd->data[0]), "w");
+
+    if (args.size() != 0) {
+        fprintf(out,
+                "Note: lshal bufferhub currently does not support args. Input arguments are "
+                "ignored.\n");
+    }
+
+    std::ostringstream stream;
+
+    // Get the number of clients of each buffer.
+    // Map from bufferId to bufferNode_clientCount pair.
+    std::map<int, std::pair<const std::shared_ptr<BufferNode>, uint32_t>> clientCount;
+    {
+        std::lock_guard<std::mutex> lock(mClientSetMutex);
+        for (auto iter = mClientSet.begin(); iter != mClientSet.end(); ++iter) {
+            sp<BufferClient> client = iter->promote();
+            if (client != nullptr) {
+                const std::shared_ptr<BufferNode> node = client->getBufferNode();
+                auto mapIter = clientCount.find(node->id());
+                if (mapIter != clientCount.end()) {
+                    ++mapIter->second.second;
+                } else {
+                    clientCount.emplace(node->id(),
+                                        std::pair<std::shared_ptr<BufferNode>, uint32_t>(node, 1U));
+                }
+            }
+        }
+    }
+
+    stream << "Active Buffers:\n";
+    stream << std::right;
+    stream << std::setw(6) << "Id";
+    stream << " ";
+    stream << std::setw(9) << "Clients";
+    stream << " ";
+    stream << std::setw(14) << "Geometry";
+    stream << " ";
+    stream << std::setw(6) << "Format";
+    stream << " ";
+    stream << std::setw(10) << "Usage";
+    stream << " ";
+    stream << std::setw(10) << "State";
+    stream << " ";
+    stream << std::setw(8) << "Index";
+    stream << std::endl;
+
+    for (auto iter = clientCount.begin(); iter != clientCount.end(); ++iter) {
+        const std::shared_ptr<BufferNode> node = std::move(iter->second.first);
+        const uint32_t clientCount = iter->second.second;
+        AHardwareBuffer_Desc desc = node->buffer_desc();
+
+        MetadataHeader* metadataHeader =
+                const_cast<BufferHubMetadata*>(&node->metadata())->metadata_header();
+        const uint32_t state = metadataHeader->buffer_state.load(std::memory_order_acquire);
+        const uint64_t index = metadataHeader->queue_index;
+
+        stream << std::right;
+        stream << std::setw(6) << /*Id=*/node->id();
+        stream << " ";
+        stream << std::setw(9) << /*Clients=*/clientCount;
+        stream << " ";
+        if (desc.format == HAL_PIXEL_FORMAT_BLOB) {
+            std::string size = std::to_string(desc.width) + " B";
+            stream << std::setw(14) << /*Geometry=*/size;
+        } else {
+            std::string dimensions = std::to_string(desc.width) + "x" +
+                    std::to_string(desc.height) + "x" + std::to_string(desc.layers);
+            stream << std::setw(14) << /*Geometry=*/dimensions;
+        }
+        stream << " ";
+        stream << std::setw(6) << /*Format=*/desc.format;
+        stream << " ";
+        stream << "0x" << std::hex << std::setfill('0');
+        stream << std::setw(8) << /*Usage=*/desc.usage;
+        stream << std::dec << std::setfill(' ');
+        stream << " ";
+        stream << "0x" << std::hex << std::setfill('0');
+        stream << std::setw(8) << /*State=*/state;
+        stream << std::dec << std::setfill(' ');
+        stream << " ";
+        stream << std::setw(8) << /*Index=*/index;
+        stream << std::endl;
+    }
+
+    stream << std::endl;
+
+    // Get the number of tokens of each buffer.
+    // Map from bufferId to tokenCount
+    std::map<int, uint32_t> tokenCount;
+    {
+        std::lock_guard<std::mutex> lock(mTokenMutex);
+        for (auto iter = mTokenMap.begin(); iter != mTokenMap.end(); ++iter) {
+            sp<BufferClient> client = iter->second.second.promote();
+            if (client != nullptr) {
+                const std::shared_ptr<BufferNode> node = client->getBufferNode();
+                auto mapIter = tokenCount.find(node->id());
+                if (mapIter != tokenCount.end()) {
+                    ++mapIter->second;
+                } else {
+                    tokenCount.emplace(node->id(), 1U);
+                }
+            }
+        }
+    }
+
+    stream << "Unused Tokens:\n";
+    stream << std::right;
+    stream << std::setw(8) << "Buffer Id";
+    stream << " ";
+    stream << std::setw(6) << "Tokens";
+    stream << std::endl;
+
+    for (auto iter = tokenCount.begin(); iter != tokenCount.end(); ++iter) {
+        stream << std::right;
+        stream << std::setw(8) << /*Buffer Id=*/iter->first;
+        stream << " ";
+        stream << std::setw(6) << /*Tokens=*/iter->second;
+        stream << std::endl;
+    }
+
+    fprintf(out, "%s", stream.str().c_str());
+
+    fclose(out);
+    return Void();
+}
+
+hidl_handle BufferHubService::registerToken(const wp<BufferClient>& client) {
+    // Find next available token id
+    std::lock_guard<std::mutex> lock(mTokenMutex);
+    do {
+        ++mLastTokenId;
+    } while (mTokenMap.find(mLastTokenId) != mTokenMap.end());
+
+    std::array<uint8_t, EVP_MAX_MD_SIZE> hmac;
+    uint32_t hmacSize = 0U;
+
+    HMAC(/*evp_md=*/EVP_sha256(), /*key=*/&mKey, /*key_len=*/kKeyLen,
+         /*data=*/(uint8_t*)&mLastTokenId, /*data_len=*/mTokenIdSize,
+         /*out=*/hmac.data(), /*out_len=*/&hmacSize);
+
+    int numIntsForHMAC = (int)ceil(hmacSize / (double)sizeof(int));
+    native_handle_t* handle = native_handle_create(/*numFds=*/0, /*numInts=*/1 + numIntsForHMAC);
+    handle->data[0] = mLastTokenId;
+    // Set all the the bits of last int to 0 since it might not be fully overwritten
+    handle->data[numIntsForHMAC] = 0;
+    memcpy(&handle->data[1], hmac.data(), hmacSize);
 
     // returnToken owns the native_handle_t* thus doing lifecycle management
     hidl_handle returnToken;
     returnToken.setTo(handle, /*shoudOwn=*/true);
 
-    mTokenMap.emplace(token, client);
+    std::vector<uint8_t> hmacVec;
+    hmacVec.resize(hmacSize);
+    memcpy(hmacVec.data(), hmac.data(), hmacSize);
+    mTokenMap.emplace(mLastTokenId, std::pair(hmacVec, client));
+
     return returnToken;
 }
 
@@ -153,11 +342,31 @@
     }
 }
 
+// Implementation of this function should be consistent with the definition of bufferInfo handle in
+// ui/BufferHubDefs.h.
+hidl_handle BufferHubService::buildBufferInfo(int bufferId, uint32_t clientBitMask,
+                                              uint32_t userMetadataSize, const int metadataFd) {
+    native_handle_t* infoHandle = native_handle_create(BufferHubDefs::kBufferInfoNumFds,
+                                                       BufferHubDefs::kBufferInfoNumInts);
+
+    infoHandle->data[0] = dup(metadataFd);
+    infoHandle->data[1] = bufferId;
+    // Use memcpy to convert to int without missing digit.
+    // TOOD(b/121345852): use bit_cast to unpack bufferInfo when C++20 becomes available.
+    memcpy(&infoHandle->data[2], &clientBitMask, sizeof(clientBitMask));
+    memcpy(&infoHandle->data[3], &userMetadataSize, sizeof(userMetadataSize));
+
+    hidl_handle bufferInfo;
+    bufferInfo.setTo(infoHandle, /*shouldOwn=*/true);
+
+    return bufferInfo;
+}
+
 void BufferHubService::removeTokenByClient(const BufferClient* client) {
-    std::lock_guard<std::mutex> lock(mTokenMapMutex);
+    std::lock_guard<std::mutex> lock(mTokenMutex);
     auto iter = mTokenMap.begin();
     while (iter != mTokenMap.end()) {
-        if (iter->second == client) {
+        if (iter->second.second == client) {
             auto oldIter = iter;
             ++iter;
             mTokenMap.erase(oldIter);
diff --git a/services/bufferhub/BufferNode.cpp b/services/bufferhub/BufferNode.cpp
index da19a6f..5106390 100644
--- a/services/bufferhub/BufferNode.cpp
+++ b/services/bufferhub/BufferNode.cpp
@@ -30,7 +30,7 @@
 
 // Allocates a new BufferNode.
 BufferNode::BufferNode(uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
-                       uint64_t usage, size_t user_metadata_size, uint32_t id)
+                       uint64_t usage, size_t user_metadata_size, int id)
       : mId(id) {
     uint32_t out_stride = 0;
     // graphicBufferId is not used in GraphicBufferAllocator::allocate
@@ -73,12 +73,8 @@
     }
 
     // Free the id, if valid
-    if (id() != BufferHubIdGenerator::kInvalidId) {
-        if (BufferHubIdGenerator::getInstance().freeId(id())) {
-            ALOGI("%s: id #%u is freed.", __FUNCTION__, id());
-        } else {
-            ALOGE("%s: Cannot free nonexistent id #%u", __FUNCTION__, id());
-        }
+    if (mId >= 0) {
+        BufferHubIdGenerator::getInstance().freeId(mId);
     }
 }
 
diff --git a/services/bufferhub/include/bufferhub/BufferHubIdGenerator.h b/services/bufferhub/include/bufferhub/BufferHubIdGenerator.h
index b51fcda..ef7c077 100644
--- a/services/bufferhub/include/bufferhub/BufferHubIdGenerator.h
+++ b/services/bufferhub/include/bufferhub/BufferHubIdGenerator.h
@@ -28,30 +28,28 @@
 namespace V1_0 {
 namespace implementation {
 
-// A thread-safe incremental uint32_t id generator.
+// A thread-safe, non-negative, incremental, int id generator.
 class BufferHubIdGenerator {
 public:
-    // 0 is considered invalid
-    static constexpr uint32_t kInvalidId = 0U;
-
     // Get the singleton instance of this class
     static BufferHubIdGenerator& getInstance();
 
-    // Gets next available id. If next id is greater than std::numeric_limits<uint32_t>::max() (2 ^
-    // 32 - 1), it will try to get an id start from 1 again.
-    uint32_t getId();
+    // Gets next available id. If next id is greater than std::numeric_limits<int32_t>::max(), it
+    // will try to get an id start from 0 again.
+    int getId();
 
-    // Free a specific id. Return true on freed, false on not found.
-    bool freeId(uint32_t id);
+    // Free a specific id.
+    void freeId(int id);
 
 private:
     BufferHubIdGenerator() = default;
     ~BufferHubIdGenerator() = default;
 
+    // Start from -1 so all valid ids will be >= 0
+    int mLastId = -1;
+
     std::mutex mIdsInUseMutex;
-    // Start from kInvalidID to avoid generating it.
-    uint32_t mLastId = kInvalidId;
-    std::set<uint32_t> mIdsInUse GUARDED_BY(mIdsInUseMutex);
+    std::set<int> mIdsInUse GUARDED_BY(mIdsInUseMutex);
 };
 
 } // namespace implementation
diff --git a/services/bufferhub/include/bufferhub/BufferHubService.h b/services/bufferhub/include/bufferhub/BufferHubService.h
index f2c8ef8..23e664e 100644
--- a/services/bufferhub/include/bufferhub/BufferHubService.h
+++ b/services/bufferhub/include/bufferhub/BufferHubService.h
@@ -17,8 +17,10 @@
 #ifndef ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_HUB_SERVICE_H
 #define ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_HUB_SERVICE_H
 
+#include <map>
 #include <mutex>
-#include <random>
+#include <set>
+#include <vector>
 
 #include <android/frameworks/bufferhub/1.0/IBufferHub.h>
 #include <bufferhub/BufferClient.h>
@@ -32,16 +34,22 @@
 namespace implementation {
 
 using hardware::hidl_handle;
+using hardware::hidl_string;
+using hardware::hidl_vec;
 using hardware::Return;
 using hardware::graphics::common::V1_2::HardwareBufferDescription;
 
 class BufferHubService : public IBufferHub {
 public:
+    BufferHubService();
+
     Return<void> allocateBuffer(const HardwareBufferDescription& description,
                                 const uint32_t userMetadataSize,
                                 allocateBuffer_cb _hidl_cb) override;
     Return<void> importBuffer(const hidl_handle& tokenHandle, importBuffer_cb _hidl_cb) override;
 
+    Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) override;
+
     // Non-binder functions
     // Internal help function for IBufferClient::duplicate.
     hidl_handle registerToken(const wp<BufferClient>& client);
@@ -49,6 +57,10 @@
     void onClientClosed(const BufferClient* client);
 
 private:
+    // Helper function to build BufferTraits.bufferInfo handle
+    hidl_handle buildBufferInfo(int bufferId, uint32_t clientBitMask, uint32_t userMetadataSize,
+                                const int metadataFd);
+
     // Helper function to remove all the token belongs to a specific client.
     void removeTokenByClient(const BufferClient* client);
 
@@ -56,11 +68,19 @@
     std::mutex mClientSetMutex;
     std::set<wp<BufferClient>> mClientSet GUARDED_BY(mClientSetMutex);
 
-    // TODO(b/118180214): use a more secure implementation
-    std::mt19937 mTokenEngine;
-    // The mapping from token to the client creates it.
-    std::mutex mTokenMapMutex;
-    std::map<uint32_t, const wp<BufferClient>> mTokenMap GUARDED_BY(mTokenMapMutex);
+    // Token generation related
+    // A random number used as private key for HMAC
+    uint64_t mKey;
+    static constexpr size_t kKeyLen = sizeof(uint64_t);
+
+    std::mutex mTokenMutex;
+    // The first TokenId will be 1. TokenId could be negative.
+    int mLastTokenId GUARDED_BY(mTokenMutex) = 0;
+    static constexpr size_t mTokenIdSize = sizeof(int);
+    // A map from token id to the token-buffer_client pair. Using token id as the key to reduce
+    // looking up time
+    std::map<int, std::pair<std::vector<uint8_t>, const wp<BufferClient>>> mTokenMap
+            GUARDED_BY(mTokenMutex);
 };
 
 } // namespace implementation
diff --git a/services/bufferhub/include/bufferhub/BufferNode.h b/services/bufferhub/include/bufferhub/BufferNode.h
index cf56c33..b7a195b 100644
--- a/services/bufferhub/include/bufferhub/BufferNode.h
+++ b/services/bufferhub/include/bufferhub/BufferNode.h
@@ -16,15 +16,14 @@
 public:
     // Allocates a new BufferNode.
     BufferNode(uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
-               uint64_t usage, size_t user_metadata_size,
-               uint32_t id = BufferHubIdGenerator::kInvalidId);
+               uint64_t usage, size_t user_metadata_size, int id = -1);
 
     ~BufferNode();
 
     // Returns whether the object holds a valid metadata.
     bool IsValid() const { return metadata_.IsValid(); }
 
-    uint32_t id() const { return mId; }
+    int id() const { return mId; }
 
     size_t user_metadata_size() const { return metadata_.user_metadata_size(); }
 
@@ -64,10 +63,10 @@
     // Metadata in shared memory.
     BufferHubMetadata metadata_;
 
-    // A system-unique id generated by bufferhub from 1 to std::numeric_limits<uint32_t>::max().
-    // BufferNodes not created by bufferhub will have id = 0, meaning "not specified".
-    // TODO(b/118891412): remove default id = 0 and update comments after pdx is no longer in use
-    const uint32_t mId = 0;
+    // A system-unique id generated by bufferhub from 0 to std::numeric_limits<int>::max().
+    // BufferNodes not created by bufferhub will have id < 0, meaning "not specified".
+    // TODO(b/118891412): remove default id = -1 and update comments after pdx is no longer in use
+    const int mId = -1;
 
     // The following variables are atomic variables in metadata_ that are visible
     // to Bn object and Bp objects. Please find more info in
diff --git a/services/bufferhub/tests/BufferHubIdGenerator_test.cpp b/services/bufferhub/tests/BufferHubIdGenerator_test.cpp
index fe01013..fb6de0d 100644
--- a/services/bufferhub/tests/BufferHubIdGenerator_test.cpp
+++ b/services/bufferhub/tests/BufferHubIdGenerator_test.cpp
@@ -15,25 +15,28 @@
 };
 
 TEST_F(BufferHubIdGeneratorTest, TestGenerateAndFreeID) {
-    uint32_t id = mIdGenerator->getId();
-    EXPECT_NE(id, BufferHubIdGenerator::kInvalidId);
+    int id = mIdGenerator->getId();
+    EXPECT_GE(id, 0);
 
-    EXPECT_TRUE(mIdGenerator->freeId(id));
-    EXPECT_FALSE(mIdGenerator->freeId(id));
+    mIdGenerator->freeId(id);
 }
 
 TEST_F(BufferHubIdGeneratorTest, TestGenerateUniqueIncrementalID) {
     // 10 IDs should not overflow the UniqueIdGenerator to cause a roll back to start, so the
     // resulting IDs should still keep incresing.
-    const size_t kTestSize = 10U;
-    uint32_t ids[kTestSize];
-    for (size_t i = 0UL; i < kTestSize; ++i) {
+    const int kTestSize = 10;
+    int ids[kTestSize];
+    for (int i = 0; i < kTestSize; ++i) {
         ids[i] = mIdGenerator->getId();
-        EXPECT_NE(ids[i], BufferHubIdGenerator::kInvalidId);
+        EXPECT_GE(ids[i], 0);
         if (i >= 1) {
             EXPECT_GT(ids[i], ids[i - 1]);
         }
     }
+
+    for (int i = 0; i < kTestSize; ++i) {
+        mIdGenerator->freeId(ids[i]);
+    }
 }
 
 } // namespace
diff --git a/services/displayservice/include/displayservice/DisplayEventReceiver.h b/services/displayservice/include/displayservice/DisplayEventReceiver.h
index 5d569b6..042a054 100644
--- a/services/displayservice/include/displayservice/DisplayEventReceiver.h
+++ b/services/displayservice/include/displayservice/DisplayEventReceiver.h
@@ -45,7 +45,7 @@
     using FwkReceiver = ::android::DisplayEventReceiver;
 
     struct AttachedEvent : LooperCallback {
-        AttachedEvent(const sp<IEventCallback> &callback);
+        explicit AttachedEvent(const sp<IEventCallback> &callback);
         ~AttachedEvent();
 
         bool detach();
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 0d8d34f..843eb37 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -22,6 +22,7 @@
 
     shared_libs: [
         "libinputflinger_base",
+        "libinputreporter",
         "libinputreader",
         "libbase",
         "libbinder",
@@ -125,6 +126,35 @@
     ],
 }
 
+cc_library_shared {
+    name: "libinputreporter",
+
+    srcs: [
+        "InputReporter.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libutils",
+    ],
+
+    header_libs: [
+        "libinputflinger_headers",
+    ],
+
+    export_header_lib_headers: [
+        "libinputflinger_headers",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wno-unused-parameter",
+    ],
+}
+
 subdirs = [
     "host",
     "tests",
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index b2d2f14..cf9d3c7 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -40,6 +40,7 @@
 #include <hardware_legacy/power.h>
 
 #include <android-base/stringprintf.h>
+#include <cutils/properties.h>
 #include <openssl/sha.h>
 #include <utils/Log.h>
 #include <utils/Timers.h>
@@ -108,6 +109,19 @@
     return strstr(name, "v4l-touch") == name;
 }
 
+/**
+ * Returns true if V4L devices should be scanned.
+ *
+ * The system property ro.input.video_enabled can be used to control whether
+ * EventHub scans and opens V4L devices. As V4L does not support multiple
+ * clients, EventHub effectively blocks access to these devices when it opens
+ * them. This property enables other clients to read these devices for testing
+ * and development.
+ */
+static bool isV4lScanningEnabled() {
+  return property_get_bool("ro.input.video_enabled", true /* default_value */);
+}
+
 static nsecs_t processEventTimestamp(const struct input_event& event) {
     // Use the time specified in the event instead of the current time
     // so that downstream code can get more accurate estimates of
@@ -220,7 +234,6 @@
 
 // --- EventHub ---
 
-const int EventHub::EPOLL_SIZE_HINT;
 const int EventHub::EPOLL_MAX_EVENTS;
 
 EventHub::EventHub(void) :
@@ -238,9 +251,14 @@
     mInputWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
     LOG_ALWAYS_FATAL_IF(mInputWd < 0, "Could not register INotify for %s: %s",
             DEVICE_PATH, strerror(errno));
-    mVideoWd = inotify_add_watch(mINotifyFd, VIDEO_DEVICE_PATH, IN_DELETE | IN_CREATE);
-    LOG_ALWAYS_FATAL_IF(mVideoWd < 0, "Could not register INotify for %s: %s",
-            VIDEO_DEVICE_PATH, strerror(errno));
+    if (isV4lScanningEnabled()) {
+        mVideoWd = inotify_add_watch(mINotifyFd, VIDEO_DEVICE_PATH, IN_DELETE | IN_CREATE);
+        LOG_ALWAYS_FATAL_IF(mVideoWd < 0, "Could not register INotify for %s: %s",
+                VIDEO_DEVICE_PATH, strerror(errno));
+    } else {
+        mVideoWd = -1;
+        ALOGI("Video device scanning disabled");
+    }
 
     struct epoll_event eventItem;
     memset(&eventItem, 0, sizeof(eventItem));
@@ -762,13 +780,27 @@
     return nullptr;
 }
 
+/**
+ * The file descriptor could be either input device, or a video device (associated with a
+ * specific input device). Check both cases here, and return the device that this event
+ * belongs to. Caller can compare the fd's once more to determine event type.
+ * Looks through all input devices, and only attached video devices. Unattached video
+ * devices are ignored.
+ */
 EventHub::Device* EventHub::getDeviceByFdLocked(int fd) const {
     for (size_t i = 0; i < mDevices.size(); i++) {
         Device* device = mDevices.valueAt(i);
         if (device->fd == fd) {
+            // This is an input device event
+            return device;
+        }
+        if (device->videoDevice && device->videoDevice->getFd() == fd) {
+            // This is a video device event
             return device;
         }
     }
+    // We do not check mUnattachedVideoDevices here because they should not participate in epoll,
+    // and therefore should never be looked up by fd.
     return nullptr;
 }
 
@@ -874,12 +906,33 @@
             }
 
             Device* device = getDeviceByFdLocked(eventItem.data.fd);
-            if (device == nullptr) {
-                ALOGW("Received unexpected epoll event 0x%08x for unknown device fd %d.",
+            if (!device) {
+                ALOGE("Received unexpected epoll event 0x%08x for unknown fd %d.",
                         eventItem.events, eventItem.data.fd);
+                ALOG_ASSERT(!DEBUG);
                 continue;
             }
-
+            if (device->videoDevice && eventItem.data.fd == device->videoDevice->getFd()) {
+                if (eventItem.events & EPOLLIN) {
+                    size_t numFrames = device->videoDevice->readAndQueueFrames();
+                    if (numFrames == 0) {
+                        ALOGE("Received epoll event for video device %s, but could not read frame",
+                                device->videoDevice->getName().c_str());
+                    }
+                } else if (eventItem.events & EPOLLHUP) {
+                    // TODO(b/121395353) - consider adding EPOLLRDHUP
+                    ALOGI("Removing video device %s due to epoll hang-up event.",
+                            device->videoDevice->getName().c_str());
+                    unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
+                    device->videoDevice = nullptr;
+                } else {
+                    ALOGW("Received unexpected epoll event 0x%08x for device %s.",
+                            eventItem.events, device->videoDevice->getName().c_str());
+                    ALOG_ASSERT(!DEBUG);
+                }
+                continue;
+            }
+            // This must be an input event
             if (eventItem.events & EPOLLIN) {
                 int32_t readSize = read(device->fd, readBuffer,
                         sizeof(struct input_event) * capacity);
@@ -994,6 +1047,16 @@
     return event - buffer;
 }
 
+std::vector<TouchVideoFrame> EventHub::getVideoFrames(int32_t deviceId) {
+    AutoMutex _l(mLock);
+
+    Device* device = getDeviceLocked(deviceId);
+    if (!device || !device->videoDevice) {
+        return {};
+    }
+    return device->videoDevice->consumeFrames();
+}
+
 void EventHub::wake() {
     ALOGV("wake() called");
 
@@ -1012,9 +1075,11 @@
     if(result < 0) {
         ALOGE("scan dir failed for %s", DEVICE_PATH);
     }
-    result = scanVideoDirLocked(VIDEO_DEVICE_PATH);
-    if (result != OK) {
-        ALOGE("scan video dir failed for %s", VIDEO_DEVICE_PATH);
+    if (isV4lScanningEnabled()) {
+        result = scanVideoDirLocked(VIDEO_DEVICE_PATH);
+        if (result != OK) {
+            ALOGE("scan video dir failed for %s", VIDEO_DEVICE_PATH);
+        }
     }
     if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) {
         createVirtualKeyboardLocked();
@@ -1044,6 +1109,7 @@
 };
 
 status_t EventHub::registerFdForEpoll(int fd) {
+    // TODO(b/121395353) - consider adding EPOLLRDHUP
     struct epoll_event eventItem = {};
     eventItem.events = EPOLLIN | EPOLLWAKEUP;
     eventItem.data.fd = fd;
@@ -1072,10 +1138,21 @@
     status_t result = registerFdForEpoll(device->fd);
     if (result != OK) {
         ALOGE("Could not add input device fd to epoll for device %" PRId32, device->id);
+        return result;
+    }
+    if (device->videoDevice) {
+        registerVideoDeviceForEpollLocked(*device->videoDevice);
     }
     return result;
 }
 
+void EventHub::registerVideoDeviceForEpollLocked(const TouchVideoDevice& videoDevice) {
+    status_t result = registerFdForEpoll(videoDevice.getFd());
+    if (result != OK) {
+        ALOGE("Could not add video device %s to epoll", videoDevice.getName().c_str());
+    }
+}
+
 status_t EventHub::unregisterDeviceFromEpollLocked(Device* device) {
     if (device->hasValidFd()) {
         status_t result = unregisterFdFromEpoll(device->fd);
@@ -1084,10 +1161,23 @@
             return result;
         }
     }
+    if (device->videoDevice) {
+        unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
+    }
     return OK;
 }
 
-status_t EventHub::openDeviceLocked(const char *devicePath) {
+void EventHub::unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& videoDevice) {
+    if (videoDevice.hasValidFd()) {
+        status_t result = unregisterFdFromEpoll(videoDevice.getFd());
+        if (result != OK) {
+            ALOGW("Could not remove video device fd from epoll for device: %s",
+                    videoDevice.getName().c_str());
+        }
+    }
+}
+
+status_t EventHub::openDeviceLocked(const char* devicePath) {
     char buffer[80];
 
     ALOGV("Opening device: %s", devicePath);
@@ -1345,6 +1435,7 @@
     }
 
     // Find a matching video device by comparing device names
+    // This should be done before registerDeviceForEpollLocked, so that both fds are added to epoll
     for (std::unique_ptr<TouchVideoDevice>& videoDevice : mUnattachedVideoDevices) {
         if (device->identifier.name == videoDevice->getName()) {
             device->videoDevice = std::move(videoDevice);
@@ -1422,6 +1513,9 @@
         Device* device = mDevices.valueAt(i);
         if (videoDevice->getName() == device->identifier.name) {
             device->videoDevice = std::move(videoDevice);
+            if (device->enabled) {
+                registerVideoDeviceForEpollLocked(*device->videoDevice);
+            }
             return;
         }
     }
@@ -1632,6 +1726,7 @@
     for (size_t i = 0; i < mDevices.size(); i++) {
         Device* device = mDevices.valueAt(i);
         if (device->videoDevice && device->videoDevice->getPath() == devicePath) {
+            unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
             device->videoDevice = nullptr;
             return;
         }
@@ -1662,6 +1757,7 @@
 
     unregisterDeviceFromEpollLocked(device);
     if (device->videoDevice) {
+        // This must be done after the video device is removed from epoll
         mUnattachedVideoDevices.push_back(std::move(device->videoDevice));
     }
 
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 7fa9cb6..9af189a 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -257,6 +257,7 @@
     mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
     mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
     mLooper = new Looper(false);
+    mReporter = createInputReporter();
 
     mKeyRepeatState.lastKeyEntry = nullptr;
 
@@ -841,6 +842,7 @@
     if (*dropReason != DROP_REASON_NOT_DROPPED) {
         setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
                 ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
+        mReporter->reportDroppedKey(entry->sequenceNum);
         return true;
     }
 
@@ -2384,7 +2386,8 @@
             }
 
             InputTarget target;
-            sp<InputWindowHandle> windowHandle = getWindowHandleLocked(connection->inputChannel);
+            sp<InputWindowHandle> windowHandle = getWindowHandleLocked(
+                    connection->inputChannel->getToken());
             if (windowHandle != nullptr) {
                 const InputWindowInfo* windowInfo = windowHandle->getInfo();
                 target.xOffset = -windowInfo->frameLeft;
@@ -2688,7 +2691,7 @@
             event.initialize(args->deviceId, args->source, args->displayId,
                     args->action, args->actionButton,
                     args->flags, args->edgeFlags, args->metaState, args->buttonState,
-                    0, 0, args->xPrecision, args->yPrecision,
+                    args->classification, 0, 0, args->xPrecision, args->yPrecision,
                     args->downTime, args->eventTime,
                     args->pointerCount, args->pointerProperties, args->pointerCoords);
 
@@ -3022,13 +3025,13 @@
 }
 
 sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
-        const sp<InputChannel>& inputChannel) const {
+        const sp<IBinder>& windowHandleToken) const {
     for (auto& it : mWindowHandlesByDisplay) {
         const Vector<sp<InputWindowHandle>> windowHandles = it.second;
         size_t numWindows = windowHandles.size();
         for (size_t i = 0; i < numWindows; i++) {
             const sp<InputWindowHandle>& windowHandle = windowHandles.itemAt(i);
-            if (windowHandle->getToken() == inputChannel->getToken()) {
+            if (windowHandle->getToken() == windowHandleToken) {
                 return windowHandle;
             }
         }
@@ -3128,7 +3131,9 @@
 
             for (size_t i = 0; i < newHandles.size(); i++) {
                 const sp<InputWindowHandle>& windowHandle = newHandles.itemAt(i);
-                if (windowHandle->getInfo()->hasFocus && windowHandle->getInfo()->visible) {
+                // Set newFocusedWindowHandle to the top most focused window instead of the last one
+                if (!newFocusedWindowHandle && windowHandle->getInfo()->hasFocus
+                        && windowHandle->getInfo()->visible) {
                     newFocusedWindowHandle = windowHandle;
                 }
                 if (windowHandle == mLastHoverWindowHandle) {
@@ -3172,7 +3177,7 @@
             }
 
             if (mFocusedDisplayId == displayId) {
-                onFocusChangedLocked(newFocusedWindowHandle);
+                onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
             }
 
         }
@@ -3290,7 +3295,7 @@
             // Sanity check
             sp<InputWindowHandle> newFocusedWindowHandle =
                     getValueByKey(mFocusedWindowHandlesByDisplay, displayId);
-            onFocusChangedLocked(newFocusedWindowHandle);
+            onFocusChangedLocked(oldFocusedWindowHandle, newFocusedWindowHandle);
 
             if (newFocusedWindowHandle == nullptr) {
                 ALOGW("Focused display #%" PRId32 " does not have a focused window.", displayId);
@@ -3371,29 +3376,27 @@
     mLooper->wake();
 }
 
-bool InputDispatcher::transferTouchFocus(const sp<InputChannel>& fromChannel,
-        const sp<InputChannel>& toChannel) {
+bool InputDispatcher::transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) {
+    if (fromToken == toToken) {
 #if DEBUG_FOCUS
-    ALOGD("transferTouchFocus: fromChannel=%s, toChannel=%s",
-            fromChannel->getName().c_str(), toChannel->getName().c_str());
+        ALOGD("Trivial transfer to same window.");
 #endif
+        return true;
+    }
+
     { // acquire lock
         AutoMutex _l(mLock);
 
-        sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromChannel);
-        sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toChannel);
+        sp<InputWindowHandle> fromWindowHandle = getWindowHandleLocked(fromToken);
+        sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(toToken);
         if (fromWindowHandle == nullptr || toWindowHandle == nullptr) {
-#if DEBUG_FOCUS
-            ALOGD("Cannot transfer focus because from or to window not found.");
-#endif
+            ALOGW("Cannot transfer focus because from or to window not found.");
             return false;
         }
-        if (fromWindowHandle == toWindowHandle) {
 #if DEBUG_FOCUS
-            ALOGD("Trivial transfer to same window.");
+        ALOGD("transferTouchFocus: fromWindowHandle=%s, toWindowHandle=%s",
+            fromWindowHandle->getName().c_str(), toWindowHandle->getName().c_str());
 #endif
-            return true;
-        }
         if (fromWindowHandle->getInfo()->displayId != toWindowHandle->getInfo()->displayId) {
 #if DEBUG_FOCUS
             ALOGD("Cannot transfer focus because windows are on different displays.");
@@ -3431,6 +3434,9 @@
             return false;
         }
 
+
+        sp<InputChannel> fromChannel = getInputChannelLocked(fromToken);
+        sp<InputChannel> toChannel = getInputChannelLocked(toToken);
         ssize_t fromConnectionIndex = getConnectionIndexLocked(fromChannel);
         ssize_t toConnectionIndex = getConnectionIndexLocked(toChannel);
         if (fromConnectionIndex >= 0 && toConnectionIndex >= 0) {
@@ -3851,11 +3857,14 @@
     commandEntry->connection = connection;
 }
 
-void InputDispatcher::onFocusChangedLocked(const sp<InputWindowHandle>& newFocus) {
-    sp<IBinder> token = newFocus != nullptr ? newFocus->getToken() : nullptr;
+void InputDispatcher::onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
+        const sp<InputWindowHandle>& newFocus) {
+    sp<IBinder> oldToken = oldFocus != nullptr ? oldFocus->getToken() : nullptr;
+    sp<IBinder> newToken = newFocus != nullptr ? newFocus->getToken() : nullptr;
     CommandEntry* commandEntry = postCommandLocked(
             & InputDispatcher::doNotifyFocusChangedLockedInterruptible);
-    commandEntry->token = token;
+    commandEntry->oldToken = oldToken;
+    commandEntry->newToken = newToken;
 }
 
 void InputDispatcher::onANRLocked(
@@ -3917,9 +3926,10 @@
 
 void InputDispatcher::doNotifyFocusChangedLockedInterruptible(
         CommandEntry* commandEntry) {
-    sp<IBinder> token = commandEntry->token;
+    sp<IBinder> oldToken = commandEntry->oldToken;
+    sp<IBinder> newToken = commandEntry->newToken;
     mLock.unlock();
-    mPolicy->notifyFocusChanged(token);
+    mPolicy->notifyFocusChanged(oldToken, newToken);
     mLock.lock();
 }
 
@@ -4025,6 +4035,10 @@
 bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection,
         DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled) {
     if (keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK) {
+        if (!handled) {
+            // Report the key as unhandled, since the fallback was not handled.
+            mReporter->reportUnhandledKey(keyEntry->sequenceNum);
+        }
         return false;
     }
 
@@ -4192,6 +4206,9 @@
 #if DEBUG_OUTBOUND_EVENT_DETAILS
             ALOGD("Unhandled key event: No fallback key.");
 #endif
+
+            // Report the key as unhandled, since there is no fallback key.
+            mReporter->reportUnhandledKey(keyEntry->sequenceNum);
         }
     }
     return false;
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 05b5dad..49de6f3 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -37,6 +37,7 @@
 #include <unordered_map>
 
 #include "InputListener.h"
+#include "InputReporterInterface.h"
 
 
 namespace android {
@@ -216,7 +217,7 @@
 
     /* Notifies the system that an input channel is unrecoverably broken. */
     virtual void notifyInputChannelBroken(const sp<IBinder>& token) = 0;
-    virtual void notifyFocusChanged(const sp<IBinder>& token) = 0;
+    virtual void notifyFocusChanged(const sp<IBinder>& oldToken, const sp<IBinder>& newToken) = 0;
 
     /* Gets the input dispatcher configuration. */
     virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0;
@@ -342,13 +343,11 @@
      */
     virtual void setInputFilterEnabled(bool enabled) = 0;
 
-    /* Transfers touch focus from the window associated with one channel to the
-     * window associated with the other channel.
+    /* Transfers touch focus from one window to another window.
      *
      * Returns true on success.  False if the window did not actually have touch focus.
      */
-    virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
-            const sp<InputChannel>& toChannel) = 0;
+    virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0;
 
     /* Registers input channels that may be used as targets for input events.
      * If inputWindowHandle is null, and displayId is not ADISPLAY_ID_NONE,
@@ -413,8 +412,7 @@
     virtual void setInputDispatchMode(bool enabled, bool frozen);
     virtual void setInputFilterEnabled(bool enabled);
 
-    virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
-            const sp<InputChannel>& toChannel);
+    virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
 
     virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
             int32_t displayId);
@@ -630,7 +628,8 @@
         uint32_t seq;
         bool handled;
         sp<InputChannel> inputChannel;
-        sp<IBinder> token;
+        sp<IBinder> oldToken;
+        sp<IBinder> newToken;
     };
 
     // Generic queue implementation.
@@ -994,7 +993,7 @@
     std::unordered_map<int32_t, Vector<sp<InputWindowHandle>>> mWindowHandlesByDisplay;
     // Get window handles by display, return an empty vector if not found.
     Vector<sp<InputWindowHandle>> getWindowHandlesLocked(int32_t displayId) const;
-    sp<InputWindowHandle> getWindowHandleLocked(const sp<InputChannel>& inputChannel) const;
+    sp<InputWindowHandle> getWindowHandleLocked(const sp<IBinder>& windowHandleToken) const;
     sp<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken) const;
     bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const;
 
@@ -1160,7 +1159,8 @@
             nsecs_t currentTime, const sp<Connection>& connection, uint32_t seq, bool handled);
     void onDispatchCycleBrokenLocked(
             nsecs_t currentTime, const sp<Connection>& connection);
-    void onFocusChangedLocked(const sp<InputWindowHandle>& newFocus);
+    void onFocusChangedLocked(const sp<InputWindowHandle>& oldFocus,
+            const sp<InputWindowHandle>& newFocus);
     void onANRLocked(
             nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
             const sp<InputWindowHandle>& windowHandle,
@@ -1186,6 +1186,8 @@
     void traceInboundQueueLengthLocked();
     void traceOutboundQueueLengthLocked(const sp<Connection>& connection);
     void traceWaitQueueLengthLocked(const sp<Connection>& connection);
+
+    sp<InputReporterInterface> mReporter;
 };
 
 /* Enqueues and dispatches input events, endlessly. */
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index b4eb370..b349c73 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -71,8 +71,8 @@
 NotifyMotionArgs::NotifyMotionArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId,
         uint32_t source, int32_t displayId, uint32_t policyFlags,
         int32_t action, int32_t actionButton, int32_t flags, int32_t metaState,
-        int32_t buttonState, int32_t edgeFlags, uint32_t deviceTimestamp,
-        uint32_t pointerCount,
+        int32_t buttonState, MotionClassification classification,
+        int32_t edgeFlags, uint32_t deviceTimestamp, uint32_t pointerCount,
         const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
         float xPrecision, float yPrecision, nsecs_t downTime,
         const std::vector<TouchVideoFrame>& videoFrames) :
@@ -80,7 +80,7 @@
         displayId(displayId), policyFlags(policyFlags),
         action(action), actionButton(actionButton),
         flags(flags), metaState(metaState), buttonState(buttonState),
-        edgeFlags(edgeFlags), deviceTimestamp(deviceTimestamp),
+        classification(classification), edgeFlags(edgeFlags), deviceTimestamp(deviceTimestamp),
         pointerCount(pointerCount),
         xPrecision(xPrecision), yPrecision(yPrecision), downTime(downTime),
         videoFrames(videoFrames) {
@@ -95,7 +95,7 @@
         source(other.source), displayId(other.displayId), policyFlags(other.policyFlags),
         action(other.action), actionButton(other.actionButton), flags(other.flags),
         metaState(other.metaState), buttonState(other.buttonState),
-        edgeFlags(other.edgeFlags),
+        classification(other.classification), edgeFlags(other.edgeFlags),
         deviceTimestamp(other.deviceTimestamp), pointerCount(other.pointerCount),
         xPrecision(other.xPrecision), yPrecision(other.yPrecision), downTime(other.downTime),
         videoFrames(other.videoFrames) {
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 15d8070..1d7ea00 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -111,6 +111,10 @@
     }
 }
 
+void InputManager::transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) {
+    mDispatcher->transferTouchFocus(fromToken, toToken);
+}
+
 // Used by tests only.
 void InputManager::registerInputChannel(const sp<InputChannel>& channel) {
     IPCThreadState* ipc = IPCThreadState::self();
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 8f7551e..ab309b1 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -91,6 +91,7 @@
     virtual sp<InputDispatcherInterface> getDispatcher();
 
     virtual void setInputWindows(const Vector<InputWindowInfo>& handles);
+    virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
 
     virtual void registerInputChannel(const sp<InputChannel>& channel);
     virtual void unregisterInputChannel(const sp<InputChannel>& channel);
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 73fcb11..2b31f6e 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -2641,6 +2641,11 @@
                 mOrientation = internalViewport->orientation;
             }
         }
+
+        // Update the PointerController if viewports changed.
+        if (mParameters.hasAssociatedDisplay) {
+            getPolicy()->obtainPointerController(getDeviceId());
+        }
         bumpGeneration();
     }
 }
@@ -2786,7 +2791,7 @@
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
-        displayId = ADISPLAY_ID_DEFAULT;
+        displayId = mPointerController->getDisplayId();
     } else {
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
@@ -2829,7 +2834,8 @@
                 NotifyMotionArgs releaseArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
                         mSource, displayId, policyFlags,
                         AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
-                        metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                        metaState, buttonState,
+                        MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
                         /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
                         mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
                 getListener()->notifyMotion(&releaseArgs);
@@ -2838,7 +2844,7 @@
 
         NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), mSource,
                 displayId, policyFlags, motionEventAction, 0, 0, metaState, currentButtonState,
-                AMOTION_EVENT_EDGE_FLAG_NONE,
+                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
                 /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
                 mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
         getListener()->notifyMotion(&args);
@@ -2850,7 +2856,8 @@
                 buttonState |= actionButton;
                 NotifyMotionArgs pressArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
                         mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_BUTTON_PRESS,
-                        actionButton, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                        actionButton, 0, metaState, buttonState,
+                        MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
                         /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
                         mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
                 getListener()->notifyMotion(&pressArgs);
@@ -2864,7 +2871,8 @@
                 && (mSource == AINPUT_SOURCE_MOUSE)) {
             NotifyMotionArgs hoverArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
                     mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
-                    metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                    metaState, currentButtonState,
+                    MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
                     /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
                     mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
             getListener()->notifyMotion(&hoverArgs);
@@ -2878,7 +2886,7 @@
             NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
                     mSource, displayId, policyFlags,
                     AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, currentButtonState,
-                    AMOTION_EVENT_EDGE_FLAG_NONE,
+                    MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
                     /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
                     mXPrecision, mYPrecision, downTime, /* videoFrames */ {});
             getListener()->notifyMotion(&scrollArgs);
@@ -3009,8 +3017,8 @@
 
         NotifyMotionArgs scrollArgs(mContext->getNextSequenceNum(), when, getDeviceId(),
                 mSource, displayId, policyFlags,
-                AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, 0,
-                AMOTION_EVENT_EDGE_FLAG_NONE,
+                AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, /* buttonState */ 0,
+                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
                 /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
                 0, 0, 0, /* videoFrames */ {});
         getListener()->notifyMotion(&scrollArgs);
@@ -3612,10 +3620,10 @@
         mOrientedRanges.clear();
     }
 
-    // Create pointer controller if needed.
+    // Create or update pointer controller if needed.
     if (mDeviceMode == DEVICE_MODE_POINTER ||
             (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
-        if (mPointerController == nullptr) {
+        if (mPointerController == nullptr || viewportChanged) {
             mPointerController = getPolicy()->obtainPointerController(getDeviceId());
         }
     } else {
@@ -5404,10 +5412,11 @@
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
 
+        const int32_t displayId = mPointerController->getDisplayId();
         NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                mSource, mViewport.displayId, policyFlags,
+                mSource, displayId, policyFlags,
                 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
-                metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
+                metaState, buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
                 /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
                 0, 0, mPointerGesture.downTime, /* videoFrames */ {});
         getListener()->notifyMotion(&args);
@@ -6312,6 +6321,7 @@
 void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
         bool down, bool hovering) {
     int32_t metaState = getContext()->getGlobalMetaState();
+    int32_t displayId = mViewport.displayId;
 
     if (mPointerController != nullptr) {
         if (down || hovering) {
@@ -6322,6 +6332,7 @@
         } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
             mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
         }
+        displayId = mPointerController->getDisplayId();
     }
 
     if (mPointerSimple.down && !down) {
@@ -6329,9 +6340,9 @@
 
         // Send up.
         NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
-                mSource, mViewport.displayId, policyFlags,
-                AMOTION_EVENT_ACTION_UP, 0, 0, metaState, mLastRawState.buttonState, 0,
-                /* deviceTimestamp */ 0,
+                mSource, displayId, policyFlags,
+                AMOTION_EVENT_ACTION_UP, 0, 0, metaState, mLastRawState.buttonState,
+                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
                 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
                 mOrientedXPrecision, mOrientedYPrecision,
                 mPointerSimple.downTime, /* videoFrames */ {});
@@ -6342,10 +6353,10 @@
         mPointerSimple.hovering = false;
 
         // Send hover exit.
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), 
-                mSource, mViewport.displayId, policyFlags,
-                AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastRawState.buttonState, 0,
-                /* deviceTimestamp */ 0,
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
+                AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastRawState.buttonState,
+                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
                 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
                 mOrientedXPrecision, mOrientedYPrecision,
                 mPointerSimple.downTime, /* videoFrames */ {});
@@ -6358,9 +6369,10 @@
             mPointerSimple.downTime = when;
 
             // Send down.
-            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), 
-                    mSource, mViewport.displayId, policyFlags,
-                    AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState, mCurrentRawState.buttonState, 0,
+            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                    mSource, displayId, policyFlags,
+                    AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState, mCurrentRawState.buttonState,
+                    MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
                     /* deviceTimestamp */ 0,
                     1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
                     mOrientedXPrecision, mOrientedYPrecision,
@@ -6369,10 +6381,10 @@
         }
 
         // Send move.
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), 
-                mSource, mViewport.displayId, policyFlags,
-                AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, mCurrentRawState.buttonState, 0,
-                /* deviceTimestamp */ 0,
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
+                AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, mCurrentRawState.buttonState,
+                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
                 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
                 mOrientedXPrecision, mOrientedYPrecision,
                 mPointerSimple.downTime, /* videoFrames */ {});
@@ -6384,11 +6396,11 @@
             mPointerSimple.hovering = true;
 
             // Send hover enter.
-            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), 
-                    mSource, mViewport.displayId, policyFlags,
+            NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                    mSource, displayId, policyFlags,
                     AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState,
-                    mCurrentRawState.buttonState, 0,
-                    /* deviceTimestamp */ 0,
+                    mCurrentRawState.buttonState, MotionClassification::NONE,
+                    AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
                     1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
                     mOrientedXPrecision, mOrientedYPrecision,
                     mPointerSimple.downTime, /* videoFrames */ {});
@@ -6396,11 +6408,11 @@
         }
 
         // Send hover move.
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), 
-                mSource, mViewport.displayId, policyFlags,
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
                 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
-                mCurrentRawState.buttonState, 0,
-                /* deviceTimestamp */ 0,
+                mCurrentRawState.buttonState, MotionClassification::NONE,
+                AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
                 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
                 mOrientedXPrecision, mOrientedYPrecision,
                 mPointerSimple.downTime, /* videoFrames */ {});
@@ -6419,10 +6431,10 @@
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
 
-        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), 
-                mSource, mViewport.displayId, policyFlags,
-                AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, mCurrentRawState.buttonState, 0,
-                /* deviceTimestamp */ 0,
+        NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+                mSource, displayId, policyFlags,
+                AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, mCurrentRawState.buttonState,
+                MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0,
                 1, &mPointerSimple.currentProperties, &pointerCoords,
                 mOrientedXPrecision, mOrientedYPrecision,
                 mPointerSimple.downTime, /* videoFrames */ {});
@@ -6482,12 +6494,16 @@
             ALOG_ASSERT(false);
         }
     }
+    const int32_t displayId = mPointerController != nullptr ?
+            mPointerController->getDisplayId() : mViewport.displayId;
 
-    NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(), 
-            source, mViewport.displayId, policyFlags,
-            action, actionButton, flags, metaState, buttonState, edgeFlags,
-            deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
-            xPrecision, yPrecision, downTime, /* videoFrames */ {});
+    const int32_t deviceId = getDeviceId();
+    std::vector<TouchVideoFrame> frames = mDevice->getEventHub()->getVideoFrames(deviceId);
+    NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId,
+            source, displayId, policyFlags,
+            action, actionButton, flags, metaState, buttonState, MotionClassification::NONE,
+            edgeFlags, deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
+            xPrecision, yPrecision, downTime, std::move(frames));
     getListener()->notifyMotion(&args);
 }
 
@@ -7410,9 +7426,9 @@
 
     NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
             AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE, policyFlags,
-            AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
-            /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
-            0, 0, 0, /* videoFrames */ {});
+            AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, MotionClassification::NONE,
+            AMOTION_EVENT_EDGE_FLAG_NONE, /* deviceTimestamp */ 0, 1,
+            &pointerProperties, &pointerCoords, 0, 0, 0, /* videoFrames */ {});
     getListener()->notifyMotion(&args);
 }
 
diff --git a/services/inputflinger/InputReporter.cpp b/services/inputflinger/InputReporter.cpp
new file mode 100644
index 0000000..8d3153c
--- /dev/null
+++ b/services/inputflinger/InputReporter.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 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 "InputReporterInterface.h"
+
+namespace android {
+
+// --- InputReporter ---
+
+class InputReporter : public InputReporterInterface {
+public:
+    void reportUnhandledKey(uint32_t sequenceNum) override;
+    void reportDroppedKey(uint32_t sequenceNum) override;
+};
+
+void InputReporter::reportUnhandledKey(uint32_t sequenceNum) {
+  // do nothing
+}
+
+void InputReporter::reportDroppedKey(uint32_t sequenceNum) {
+  // do nothing
+}
+
+sp<InputReporterInterface> createInputReporter() {
+  return new InputReporter();
+}
+
+} // namespace android
diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h
index 82ff089..9d0be95 100644
--- a/services/inputflinger/host/InputFlinger.h
+++ b/services/inputflinger/host/InputFlinger.h
@@ -40,6 +40,7 @@
 
     virtual status_t dump(int fd, const Vector<String16>& args);
     void setInputWindows(const Vector<InputWindowInfo>&) {}
+    void transferTouchFocus(const sp<IBinder>&, const sp<IBinder>&) {}
     void registerInputChannel(const sp<InputChannel>&) {}
     void unregisterInputChannel(const sp<InputChannel>&) {}
 
diff --git a/services/inputflinger/include/EventHub.h b/services/inputflinger/include/EventHub.h
index ae70169..295aca8 100644
--- a/services/inputflinger/include/EventHub.h
+++ b/services/inputflinger/include/EventHub.h
@@ -211,6 +211,7 @@
      * Returns the number of events obtained, or 0 if the timeout expired.
      */
     virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) = 0;
+    virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) = 0;
 
     /*
      * Query current input state.
@@ -303,6 +304,7 @@
             const int32_t* keyCodes, uint8_t* outFlags) const;
 
     virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize);
+    virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId);
 
     virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const;
     virtual bool hasLed(int32_t deviceId, int32_t led) const;
@@ -381,7 +383,7 @@
         }
     };
 
-    status_t openDeviceLocked(const char *devicePath);
+    status_t openDeviceLocked(const char* devicePath);
     void openVideoDeviceLocked(const std::string& devicePath);
     void createVirtualKeyboardLocked();
     void addDeviceLocked(Device* device);
@@ -400,7 +402,9 @@
     status_t registerFdForEpoll(int fd);
     status_t unregisterFdFromEpoll(int fd);
     status_t registerDeviceForEpollLocked(Device* device);
+    void registerVideoDeviceForEpollLocked(const TouchVideoDevice& videoDevice);
     status_t unregisterDeviceFromEpollLocked(Device* device);
+    void unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& videoDevice);
 
     status_t scanDirLocked(const char *dirname);
     status_t scanVideoDirLocked(const std::string& dirname);
@@ -410,6 +414,10 @@
     Device* getDeviceByDescriptorLocked(const std::string& descriptor) const;
     Device* getDeviceLocked(int32_t deviceId) const;
     Device* getDeviceByPathLocked(const char* devicePath) const;
+    /**
+     * Look through all available fd's (both for input devices and for video devices),
+     * and return the device pointer.
+     */
     Device* getDeviceByFdLocked(int fd) const;
 
     bool hasKeycodeLocked(Device* device, int keycode) const;
@@ -470,9 +478,6 @@
     int mInputWd;
     int mVideoWd;
 
-    // Epoll FD list size hint.
-    static const int EPOLL_SIZE_HINT = 8;
-
     // Maximum number of signalled FDs to handle at a time.
     static const int EPOLL_MAX_EVENTS = 16;
 
diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h
index 2442cc0..53247a0 100644
--- a/services/inputflinger/include/InputListener.h
+++ b/services/inputflinger/include/InputListener.h
@@ -99,6 +99,10 @@
     int32_t flags;
     int32_t metaState;
     int32_t buttonState;
+    /**
+     * Classification of the current touch gesture
+     */
+    MotionClassification classification;
     int32_t edgeFlags;
     /**
      * A timestamp in the input device's time base, not the platform's.
@@ -120,7 +124,7 @@
     NotifyMotionArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
             int32_t displayId, uint32_t policyFlags,
             int32_t action, int32_t actionButton, int32_t flags,
-            int32_t metaState, int32_t buttonState,
+            int32_t metaState, int32_t buttonState, MotionClassification classification,
             int32_t edgeFlags, uint32_t deviceTimestamp, uint32_t pointerCount,
             const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
             float xPrecision, float yPrecision, nsecs_t downTime,
diff --git a/services/inputflinger/include/InputReporterInterface.h b/services/inputflinger/include/InputReporterInterface.h
new file mode 100644
index 0000000..906d7f2
--- /dev/null
+++ b/services/inputflinger/include/InputReporterInterface.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef _UI_INPUT_REPORTER_INTERFACE_H
+#define _UI_INPUT_REPORTER_INTERFACE_H
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+/*
+ * The interface used by the InputDispatcher to report information about input events after
+ * it is sent to the application, such as if a key is unhandled or dropped.
+ */
+class InputReporterInterface : public virtual RefBase {
+protected:
+    virtual ~InputReporterInterface() { }
+
+public:
+    // Report a key that was not handled by the system or apps.
+    // A key event is unhandled if:
+    //   - The event was not handled and there is no fallback key; or
+    //   - The event was not handled and it has a fallback key,
+    //       but the fallback key was not handled.
+    virtual void reportUnhandledKey(uint32_t sequenceNum) = 0;
+
+    // Report a key that was dropped by InputDispatcher.
+    // A key can be dropped for several reasons. See the enum
+    // InputDispatcher::DropReason for details.
+    virtual void reportDroppedKey(uint32_t sequenceNum) = 0;
+};
+
+/*
+ * Factory method for InputReporter.
+ */
+sp<InputReporterInterface> createInputReporter();
+
+} // namespace android
+
+#endif // _UI_INPUT_REPORTER_INTERFACE_H
diff --git a/services/inputflinger/include/PointerControllerInterface.h b/services/inputflinger/include/PointerControllerInterface.h
index e94dd94..bc0f1f9 100644
--- a/services/inputflinger/include/PointerControllerInterface.h
+++ b/services/inputflinger/include/PointerControllerInterface.h
@@ -98,6 +98,9 @@
 
     /* Removes all spots. */
     virtual void clearSpots() = 0;
+
+    /* Gets the id of the display where the pointer should be shown. */
+    virtual int32_t getDisplayId() const = 0;
 };
 
 } // namespace android
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 26f01b7..3edec40 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -63,7 +63,7 @@
     virtual void notifyInputChannelBroken(const sp<IBinder>&) {
     }
 
-    virtual void notifyFocusChanged(const sp<IBinder>&) {
+    virtual void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) {
     }
 
     virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
@@ -160,70 +160,70 @@
         pointerCoords[i].clear();
     }
 
+    // Some constants commonly used below
+    constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
+    constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
+    constexpr int32_t metaState = AMETA_NONE;
+    constexpr MotionClassification classification = MotionClassification::NONE;
+
     // Rejects undefined motion actions.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
-            /*action*/ -1, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerProperties, pointerCoords);
+    event.initialize(DEVICE_ID, source, DISPLAY_ID,
+            /*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with undefined action.";
 
     // Rejects pointer down with invalid index.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
+    event.initialize(DEVICE_ID, source, DISPLAY_ID,
             AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerProperties, pointerCoords);
+            0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with pointer down index too large.";
 
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
+    event.initialize(DEVICE_ID, source, DISPLAY_ID,
             AMOTION_EVENT_ACTION_POINTER_DOWN | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerProperties, pointerCoords);
+            0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with pointer down index too small.";
 
     // Rejects pointer up with invalid index.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
+    event.initialize(DEVICE_ID, source, DISPLAY_ID,
             AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerProperties, pointerCoords);
+            0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with pointer up index too large.";
 
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
+    event.initialize(DEVICE_ID, source, DISPLAY_ID,
             AMOTION_EVENT_ACTION_POINTER_UP | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
-            0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerProperties, pointerCoords);
+            0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with pointer up index too small.";
 
     // Rejects motion events with invalid number of pointers.
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 0, pointerProperties, pointerCoords);
+    event.initialize(DEVICE_ID, source, DISPLAY_ID,
+            AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 0, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with 0 pointers.";
 
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
+    event.initialize(DEVICE_ID, source, DISPLAY_ID,
+            AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
             ARBITRARY_TIME, ARBITRARY_TIME,
             /*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
@@ -233,20 +233,18 @@
 
     // Rejects motion events with invalid pointer ids.
     pointerProperties[0].id = -1;
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerProperties, pointerCoords);
+    event.initialize(DEVICE_ID, source, DISPLAY_ID,
+            AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
             << "Should reject motion events with pointer ids less than 0.";
 
     pointerProperties[0].id = MAX_POINTER_ID + 1;
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 1, pointerProperties, pointerCoords);
+    event.initialize(DEVICE_ID, source, DISPLAY_ID,
+            AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 1, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
@@ -255,10 +253,9 @@
     // Rejects motion events with duplicate pointer ids.
     pointerProperties[0].id = 1;
     pointerProperties[1].id = 1;
-    event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
-            AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
-            ARBITRARY_TIME, ARBITRARY_TIME,
-            /*pointerCount*/ 2, pointerProperties, pointerCoords);
+    event.initialize(DEVICE_ID, source, DISPLAY_ID,
+            AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification, 0, 0, 0, 0,
+            ARBITRARY_TIME, ARBITRARY_TIME, /*pointerCount*/ 2, pointerProperties, pointerCoords);
     ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
             &event,
             INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
@@ -460,7 +457,8 @@
     // Define a valid motion down event.
     event.initialize(DEVICE_ID, source, displayId,
             AMOTION_EVENT_ACTION_DOWN, /* actionButton */0, /* flags */ 0, /* edgeFlags */ 0,
-            AMETA_NONE, /* buttonState */ 0, /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
+            AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
+            /* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
             /* yPrecision */ 0, currentTime, currentTime, /*pointerCount*/ 1, pointerProperties,
             pointerCoords);
 
@@ -517,7 +515,7 @@
     sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
             ADISPLAY_ID_DEFAULT);
 
-    // Set focus application.
+    // Set focused application.
     mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
 
     // Expect one focus window exist in display.
@@ -535,6 +533,32 @@
     windowSecond->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
 }
 
+TEST_F(InputDispatcherTest, SetInputWindow_FocusPriority) {
+    sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+    sp<FakeWindowHandle> windowTop = new FakeWindowHandle(application, mDispatcher, "Top",
+            ADISPLAY_ID_DEFAULT);
+    sp<FakeWindowHandle> windowSecond = new FakeWindowHandle(application, mDispatcher, "Second",
+            ADISPLAY_ID_DEFAULT);
+
+    // Set focused application.
+    mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+
+    // Display has two focused windows. Add them to inputWindowsHandles in z-order (top most first)
+    windowTop->setFocus();
+    windowSecond->setFocus();
+    Vector<sp<InputWindowHandle>> inputWindowHandles;
+    inputWindowHandles.add(windowTop);
+    inputWindowHandles.add(windowSecond);
+
+    mDispatcher->setInputWindows(inputWindowHandles, ADISPLAY_ID_DEFAULT);
+    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectKeyDown(mDispatcher))
+            << "Inject key event should return INPUT_EVENT_INJECTION_SUCCEEDED";
+
+    // Top focused window should receive event.
+    windowTop->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
+    windowSecond->assertNoEvents();
+}
+
 TEST_F(InputDispatcherTest, SetInputWindow_InputWindowInfo) {
     sp<FakeApplicationHandle> application = new FakeApplicationHandle();
 
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index b5d2090..de87e7f 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -57,6 +57,7 @@
     float mMinX, mMinY, mMaxX, mMaxY;
     float mX, mY;
     int32_t mButtonState;
+    int32_t mDisplayId;
 
 protected:
     virtual ~FakePointerController() { }
@@ -64,7 +65,7 @@
 public:
     FakePointerController() :
         mHaveBounds(false), mMinX(0), mMinY(0), mMaxX(0), mMaxY(0), mX(0), mY(0),
-        mButtonState(0) {
+        mButtonState(0), mDisplayId(ADISPLAY_ID_DEFAULT) {
     }
 
     void setBounds(float minX, float minY, float maxX, float maxY) {
@@ -75,6 +76,10 @@
         mMaxY = maxY;
     }
 
+    void setDisplayId(int32_t displayId) {
+        mDisplayId = displayId;
+    }
+
     virtual void setPosition(float x, float y) {
         mX = x;
         mY = y;
@@ -93,6 +98,10 @@
         *outY = mY;
     }
 
+    virtual int32_t getDisplayId() const {
+        return mDisplayId;
+    }
+
 private:
     virtual bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const {
         *outMinX = mMinX;
@@ -692,6 +701,10 @@
         return 1;
     }
 
+    virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) {
+        return {};
+    }
+
     virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const {
         Device* device = getDevice(deviceId);
         if (device) {
@@ -3165,6 +3178,30 @@
     ASSERT_NO_FATAL_FAILURE(assertPosition(mFakePointerController, 110.0f, 220.0f));
 }
 
+TEST_F(CursorInputMapperTest, Process_ShouldHandleDisplayId) {
+    CursorInputMapper* mapper = new CursorInputMapper(mDevice);
+    addMapperAndConfigure(mapper);
+
+    // Setup PointerController for second display.
+    constexpr int32_t SECOND_DISPLAY_ID = 1;
+    mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
+    mFakePointerController->setPosition(100, 200);
+    mFakePointerController->setButtonState(0);
+    mFakePointerController->setDisplayId(SECOND_DISPLAY_ID);
+
+    NotifyMotionArgs args;
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 10);
+    process(mapper, ARBITRARY_TIME, EV_REL, REL_Y, 20);
+    process(mapper, ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0);
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+    ASSERT_EQ(AINPUT_SOURCE_MOUSE, args.source);
+    ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
+    ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+            110.0f, 220.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+    ASSERT_NO_FATAL_FAILURE(assertPosition(mFakePointerController, 110.0f, 220.0f));
+    ASSERT_EQ(SECOND_DISPLAY_ID, args.displayId);
+}
+
 
 // --- TouchInputMapperTest ---
 
@@ -6314,4 +6351,30 @@
     ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
 }
 
+TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
+    // Setup PointerController for second display.
+    sp<FakePointerController> fakePointerController = new FakePointerController();
+    fakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
+    fakePointerController->setPosition(100, 200);
+    fakePointerController->setButtonState(0);
+    fakePointerController->setDisplayId(SECONDARY_DISPLAY_ID);
+    mFakePolicy->setPointerController(mDevice->getId(), fakePointerController);
+
+    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
+    prepareDisplay(DISPLAY_ORIENTATION_0);
+    prepareAxes(POSITION);
+    addMapperAndConfigure(mapper);
+
+    // Check source is mouse that would obtain the PointerController.
+    ASSERT_EQ(AINPUT_SOURCE_MOUSE, mapper->getSources());
+
+    NotifyMotionArgs motionArgs;
+    processPosition(mapper, 100, 100);
+    processSync(mapper);
+
+    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+    ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, motionArgs.action);
+    ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
+}
+
 } // namespace android
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 9b2cd50..189ae36 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -35,6 +35,7 @@
 using namespace android::hardware::sensors::V1_0::implementation;
 using android::hardware::sensors::V2_0::ISensorsCallback;
 using android::hardware::sensors::V2_0::EventQueueFlagBits;
+using android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
 using android::hardware::hidl_vec;
 using android::hardware::Return;
 using android::SensorDeviceUtils::HidlServiceRegistrationWaiter;
@@ -94,6 +95,8 @@
 SensorDevice::SensorDevice()
         : mHidlTransportErrors(20),
           mRestartWaiter(new HidlServiceRegistrationWaiter()),
+          mEventQueueFlag(nullptr),
+          mWakeLockQueueFlag(nullptr),
           mReconnecting(false) {
     if (!connectHidlService()) {
         return;
@@ -137,6 +140,11 @@
         hardware::EventFlag::deleteEventFlag(&mEventQueueFlag);
         mEventQueueFlag = nullptr;
     }
+
+    if (mWakeLockQueueFlag != nullptr) {
+        hardware::EventFlag::deleteEventFlag(&mWakeLockQueueFlag);
+        mWakeLockQueueFlag = nullptr;
+    }
 }
 
 bool SensorDevice::connectHidlService() {
@@ -198,10 +206,16 @@
                 SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT,
                 true /* configureEventFlagWord */);
 
+        hardware::EventFlag::deleteEventFlag(&mEventQueueFlag);
         hardware::EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag);
 
+        hardware::EventFlag::deleteEventFlag(&mWakeLockQueueFlag);
+        hardware::EventFlag::createEventFlag(mWakeLockQueue->getEventFlagWord(),
+                                             &mWakeLockQueueFlag);
+
         CHECK(mSensors != nullptr && mEventQueue != nullptr &&
-                mWakeLockQueue != nullptr && mEventQueueFlag != nullptr);
+                mWakeLockQueue != nullptr && mEventQueueFlag != nullptr &&
+                mWakeLockQueueFlag != nullptr);
 
         status_t status = StatusFromResult(checkReturn(mSensors->initialize(
                 *mEventQueue->getDesc(),
@@ -512,9 +526,12 @@
 }
 
 void SensorDevice::writeWakeLockHandled(uint32_t count) {
-    if (mSensors != nullptr && mSensors->supportsMessageQueues() &&
-            !mWakeLockQueue->write(&count)) {
-        ALOGW("Failed to write wake lock handled");
+    if (mSensors != nullptr && mSensors->supportsMessageQueues()) {
+        if (mWakeLockQueue->write(&count)) {
+            mWakeLockQueueFlag->wake(asBaseType(WakeLockQueueFlagBits::DATA_WRITTEN));
+        } else {
+            ALOGW("Failed to write wake lock handled");
+        }
     }
 }
 
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index e1024ac..2a69654 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -238,6 +238,7 @@
     std::unique_ptr<WakeLockQueue> mWakeLockQueue;
 
     hardware::EventFlag* mEventQueueFlag;
+    hardware::EventFlag* mWakeLockQueueFlag;
 
     std::array<Event, SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT> mEventBuffer;
 
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 0c1ea44..5b3bbca 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -1,7 +1,6 @@
 cc_defaults {
     name: "surfaceflinger_defaults",
     cflags: [
-        "-DLOG_TAG=\"SurfaceFlinger\"",
         "-Wall",
         "-Werror",
         "-Wformat",
@@ -15,6 +14,7 @@
     name: "libsurfaceflinger_defaults",
     defaults: ["surfaceflinger_defaults"],
     cflags: [
+        "-DLOG_TAG=\"SurfaceFlinger\"",
         "-DGL_GLEXT_PROTOTYPES",
         "-DEGL_EGLEXT_PROTOTYPES",
     ],
@@ -55,8 +55,10 @@
         "libui",
         "libinput",
         "libutils",
+        "libutilscallstack",
     ],
     static_libs: [
+        "libcompositionengine",
         "librenderengine",
         "libserviceutils",
         "libtrace_proto",
@@ -69,6 +71,7 @@
         "android.hardware.graphics.composer@2.3-command-buffer",
     ],
     export_static_lib_headers: [
+        "libcompositionengine",
         "librenderengine",
         "libserviceutils",
     ],
@@ -171,6 +174,9 @@
 cc_defaults {
     name: "libsurfaceflinger_binary",
     defaults: ["surfaceflinger_defaults"],
+    cflags: [
+        "-DLOG_TAG=\"SurfaceFlinger\"",
+    ],
     whole_static_libs: [
         "libsigchain",
     ],
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 0a3be71..164a3a6 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -176,7 +176,7 @@
 
     if (!blackOutLayer) {
         // TODO: we could be more subtle with isFixedSize()
-        const bool useFiltering = needsFiltering(renderArea) || isFixedSize();
+        const bool useFiltering = needsFiltering() || renderArea.needsFiltering() || isFixedSize();
 
         // Query the texture matrix given our current filtering mode.
         float textureMatrix[16];
@@ -396,7 +396,6 @@
     }
 
     // Capture the old state of the layer for comparisons later
-    Mutex::Autolock lock(mStateMutex);
     const State& s(getDrawingState());
     const bool oldOpacity = isOpaque(s);
     sp<GraphicBuffer> oldBuffer = mActiveBuffer;
@@ -503,7 +502,7 @@
 
     // FIXME: postedRegion should be dirty & bounds
     // transform the dirty region to window-manager space
-    return getTransformLocked().transform(Region(getBufferSize(s)));
+    return getTransform().transform(Region(getBufferSize(s)));
 }
 
 // transaction
@@ -551,7 +550,7 @@
 
 // h/w composer set-up
 bool BufferLayer::allTransactionsSignaled() {
-    auto headFrameNumber = getHeadFrameNumberLocked();
+    auto headFrameNumber = getHeadFrameNumber();
     bool matchingFramesFound = false;
     bool allTransactionsApplied = true;
     Mutex::Autolock lock(mLocalSyncPointMutex);
@@ -598,13 +597,15 @@
     return true;
 }
 
-bool BufferLayer::needsFiltering(const RenderArea& renderArea) const {
-    return mNeedsFiltering || renderArea.needsFiltering();
+bool BufferLayer::needsFiltering() const {
+    const auto displayFrame = getBE().compositionInfo.hwc.displayFrame;
+    const auto sourceCrop = getBE().compositionInfo.hwc.sourceCrop;
+    return mNeedsFiltering || sourceCrop.getHeight() != displayFrame.getHeight() ||
+            sourceCrop.getWidth() != displayFrame.getWidth();
 }
 
 void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const {
     ATRACE_CALL();
-    Mutex::Autolock lock(mStateMutex);
     const State& s(getDrawingState());
 
     computeGeometry(renderArea, getBE().mMesh, useIdentityTransform);
@@ -623,17 +624,19 @@
      * minimal value)? Or, we could make GL behave like HWC -- but this feel
      * like more of a hack.
      */
-    const Rect bounds{computeBoundsLocked()}; // Rounds from FloatRect
 
-    ui::Transform t = getTransformLocked();
-    Rect win = bounds;
-    const int bufferWidth = getBufferSize(s).getWidth();
-    const int bufferHeight = getBufferSize(s).getHeight();
+    // Convert to Rect so that bounds are clipped to integers.
+    const Rect win{computeCrop(Rect::INVALID_RECT)};
+    // computeCrop() returns the cropping rectangle in buffer space, so we
+    // shouldn't use getBufferSize() since that may return a rectangle specified
+    // in layer space. Otherwise we may compute incorrect texture coordinates.
+    const float bufWidth = float(mActiveBuffer->getWidth());
+    const float bufHeight = float(mActiveBuffer->getHeight());
 
-    const float left = float(win.left) / float(bufferWidth);
-    const float top = float(win.top) / float(bufferHeight);
-    const float right = float(win.right) / float(bufferWidth);
-    const float bottom = float(win.bottom) / float(bufferHeight);
+    const float left = win.left / bufWidth;
+    const float top = win.top / bufHeight;
+    const float right = win.right / bufWidth;
+    const float bottom = win.bottom / bufHeight;
 
     // TODO: we probably want to generate the texture coords with the mesh
     // here we assume that we only have 4 vertices
@@ -644,7 +647,7 @@
     texCoords[2] = vec2(right, 1.0f - bottom);
     texCoords[3] = vec2(right, 1.0f - top);
 
-    const auto roundedCornerState = getRoundedCornerStateLocked();
+    const auto roundedCornerState = getRoundedCornerState();
     const auto cropRect = roundedCornerState.cropRect;
     setupRoundedCornersCropCoordinates(win, cropRect);
 
@@ -666,12 +669,7 @@
 }
 
 uint64_t BufferLayer::getHeadFrameNumber() const {
-    Mutex::Autolock lock(mStateMutex);
-    return getHeadFrameNumberLocked();
-}
-
-uint64_t BufferLayer::getHeadFrameNumberLocked() const {
-    if (hasFrameUpdateLocked()) {
+    if (hasFrameUpdate()) {
         return getFrameNumber();
     } else {
         return mCurrentFrameNumber;
@@ -698,7 +696,7 @@
         std::swap(bufWidth, bufHeight);
     }
 
-    if (getTransformToDisplayInverseLocked()) {
+    if (getTransformToDisplayInverse()) {
         uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform();
         if (invTransform & ui::Transform::ROT_90) {
             std::swap(bufWidth, bufHeight);
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 98ae286..e3b7f2f 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -69,7 +69,7 @@
     bool isOpaque(const Layer::State& s) const override;
 
     // isVisible - true if this layer is visible, false otherwise
-    bool isVisible() const override EXCLUDES(mStateMutex);
+    bool isVisible() const override;
 
     // isProtected - true if the layer may contain protected content in the
     // GRALLOC_USAGE_PROTECTED sense.
@@ -91,7 +91,7 @@
     bool onPostComposition(const std::optional<DisplayId>& displayId,
                            const std::shared_ptr<FenceTime>& glDoneFence,
                            const std::shared_ptr<FenceTime>& presentFence,
-                           const CompositorTiming& compositorTiming) override EXCLUDES(mStateMutex);
+                           const CompositorTiming& compositorTiming) override;
 
     // latchBuffer - called each time the screen is redrawn and returns whether
     // the visible regions need to be recomputed (this is a fairly heavy
@@ -101,13 +101,13 @@
     // releaseFence will be populated with a native fence that fires when
     // composition has completed.
     Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
-                       const sp<Fence>& releaseFence) override EXCLUDES(mStateMutex);
+                       const sp<Fence>& releaseFence) override;
 
     bool isBufferLatched() const override { return mRefreshPending; }
 
     void notifyAvailableFrames() override;
 
-    bool hasReadyFrame() const override EXCLUDES(mStateMutex);
+    bool hasReadyFrame() const override;
 
     // Returns the current scaling mode, unless mOverrideScalingMode
     // is set, in which case, it returns mOverrideScalingMode
@@ -118,24 +118,19 @@
     // Functions that must be implemented by derived classes
     // -----------------------------------------------------------------------
 private:
-    virtual bool fenceHasSignaled() const EXCLUDES(mStateMutex) = 0;
+    virtual bool fenceHasSignaled() const = 0;
 
     virtual nsecs_t getDesiredPresentTime() = 0;
-    std::shared_ptr<FenceTime> getCurrentFenceTime() const EXCLUDES(mStateMutex) {
-        Mutex::Autolock lock(mStateMutex);
-        return getCurrentFenceTimeLocked();
-    }
-
-    virtual std::shared_ptr<FenceTime> getCurrentFenceTimeLocked() const REQUIRES(mStateMutex) = 0;
+    virtual std::shared_ptr<FenceTime> getCurrentFenceTime() const = 0;
 
     virtual void getDrawingTransformMatrix(float *matrix) = 0;
-    virtual uint32_t getDrawingTransform() const REQUIRES(mStateMutex) = 0;
-    virtual ui::Dataspace getDrawingDataSpace() const REQUIRES(mStateMutex) = 0;
-    virtual Rect getDrawingCrop() const REQUIRES(mStateMutex) = 0;
+    virtual uint32_t getDrawingTransform() const = 0;
+    virtual ui::Dataspace getDrawingDataSpace() const = 0;
+    virtual Rect getDrawingCrop() const = 0;
     virtual uint32_t getDrawingScalingMode() const = 0;
-    virtual Region getDrawingSurfaceDamage() const EXCLUDES(mStateMutex) = 0;
-    virtual const HdrMetadata& getDrawingHdrMetadata() const EXCLUDES(mStateMutex) = 0;
-    virtual int getDrawingApi() const EXCLUDES(mStateMutex) = 0;
+    virtual Region getDrawingSurfaceDamage() const = 0;
+    virtual const HdrMetadata& getDrawingHdrMetadata() const = 0;
+    virtual int getDrawingApi() const = 0;
     virtual PixelFormat getPixelFormat() const = 0;
 
     virtual uint64_t getFrameNumber() const = 0;
@@ -143,21 +138,20 @@
     virtual bool getAutoRefresh() const = 0;
     virtual bool getSidebandStreamChanged() const = 0;
 
-    virtual std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions)
-            EXCLUDES(mStateMutex) = 0;
+    virtual std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) = 0;
 
-    virtual bool hasFrameUpdateLocked() const REQUIRES(mStateMutex) = 0;
+    virtual bool hasFrameUpdate() const = 0;
 
     virtual void setFilteringEnabled(bool enabled) = 0;
 
-    virtual status_t bindTextureImage() EXCLUDES(mStateMutex) = 0;
+    virtual status_t bindTextureImage() = 0;
     virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
-                                    const sp<Fence>& flushFence) REQUIRES(mStateMutex) = 0;
+                                    const sp<Fence>& flushFence) = 0;
 
-    virtual status_t updateActiveBuffer() REQUIRES(mStateMutex) = 0;
+    virtual status_t updateActiveBuffer() = 0;
     virtual status_t updateFrameNumber(nsecs_t latchTime) = 0;
 
-    virtual void setHwcLayerBuffer(DisplayId displayId) EXCLUDES(mStateMutex) = 0;
+    virtual void setHwcLayerBuffer(DisplayId displayId) = 0;
 
 protected:
     // Loads the corresponding system property once per process
@@ -166,29 +160,23 @@
     // Check all of the local sync points to ensure that all transactions
     // which need to have been applied prior to the frame which is about to
     // be latched have signaled
-    bool allTransactionsSignaled() REQUIRES(mStateMutex);
+    bool allTransactionsSignaled();
 
     static bool getOpacityForFormat(uint32_t format);
 
-    bool hasFrameUpdate() const EXCLUDES(mStateMutex) {
-        Mutex::Autolock lock(mStateMutex);
-        return hasFrameUpdateLocked();
-    }
-
     // from GLES
     const uint32_t mTextureName;
 
+    bool mRefreshPending{false};
+
 private:
-    // needsLinearFiltering - true if this surface's state requires filtering
-    bool needsFiltering(const RenderArea& renderArea) const;
+    // Returns true if this layer requires filtering
+    bool needsFiltering() const;
 
     // drawing
-    void drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const
-            EXCLUDES(mStateMutex);
+    void drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const;
 
-    uint64_t getHeadFrameNumber() const EXCLUDES(mStateMutex);
-
-    uint64_t getHeadFrameNumberLocked() const REQUIRES(mStateMutex);
+    uint64_t getHeadFrameNumber() const;
 
     uint32_t mCurrentScalingMode{NATIVE_WINDOW_SCALING_MODE_FREEZE};
 
@@ -198,9 +186,7 @@
     // The texture used to draw the layer in GLES composition mode
     mutable renderengine::Texture mTexture;
 
-    bool mRefreshPending{false};
-
-    Rect getBufferSize(const State& s) const override REQUIRES(mStateMutex);
+    Rect getBufferSize(const State& s) const override;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 3341b98..42021d1 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -51,7 +51,7 @@
     return history;
 }
 
-bool BufferQueueLayer::getTransformToDisplayInverseLocked() const {
+bool BufferQueueLayer::getTransformToDisplayInverse() const {
     return mConsumer->getTransformToDisplayInverse();
 }
 
@@ -131,7 +131,7 @@
     return mConsumer->getTimestamp();
 }
 
-std::shared_ptr<FenceTime> BufferQueueLayer::getCurrentFenceTimeLocked() const {
+std::shared_ptr<FenceTime> BufferQueueLayer::getCurrentFenceTime() const {
     return mConsumer->getCurrentFenceTime();
 }
 
@@ -192,7 +192,6 @@
 
 std::optional<Region> BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
     bool sidebandStreamChanged = true;
-    Mutex::Autolock lock(mStateMutex);
     if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false)) {
         // mSidebandStreamChanged was changed to false
         // replicated in LayerBE until FE/BE is ready to be synchronized
@@ -201,15 +200,15 @@
             setTransactionFlags(eTransactionNeeded);
             mFlinger->setTransactionFlags(eTraversalNeeded);
         }
-
         recomputeVisibleRegions = true;
+
         const State& s(getDrawingState());
-        return getTransformLocked().transform(Region(Rect(s.active_legacy.w, s.active_legacy.h)));
+        return getTransform().transform(Region(Rect(s.active_legacy.w, s.active_legacy.h)));
     }
     return {};
 }
 
-bool BufferQueueLayer::hasFrameUpdateLocked() const {
+bool BufferQueueLayer::hasFrameUpdate() const {
     return mQueuedFrames > 0;
 }
 
@@ -229,18 +228,16 @@
     // buffer mode.
     bool queuedBuffer = false;
     const int32_t layerID = getSequence();
-    status_t updateResult;
-    LayerRejecter r(mState.drawing, getCurrentState(), recomputeVisibleRegions,
+    LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
                     getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
-                    getTransformToDisplayInverseLocked(), mFreezeGeometryUpdates);
+                    getTransformToDisplayInverse(), mFreezeGeometryUpdates);
 
     const nsecs_t expectedPresentTime = mFlinger->mUseScheduler
             ? mFlinger->mScheduler->mPrimaryDispSync->expectedPresentTime()
             : mFlinger->mPrimaryDispSync->expectedPresentTime();
-
-    updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh, &queuedBuffer,
-                                             mLastFrameNumberReceived, releaseFence);
-
+    status_t updateResult =
+            mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh, &queuedBuffer,
+                                      mLastFrameNumberReceived, releaseFence);
     if (updateResult == BufferQueue::PRESENT_LATER) {
         // Producer doesn't want buffer to be displayed yet.  Signal a
         // layer update so we check again at the next opportunity.
@@ -355,6 +352,14 @@
 // Interface implementation for BufferLayerConsumer::ContentsChangedListener
 // -----------------------------------------------------------------------
 
+void BufferQueueLayer::fakeVsync() {
+    mRefreshPending = false;
+    bool ignored = false;
+    latchBuffer(ignored, systemTime(), Fence::NO_FENCE);
+    usleep(16000);
+    releasePendingBuffer(systemTime());
+}
+
 void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
     // Add this buffer from our internal queue tracker
     { // Autolock scope
@@ -393,10 +398,7 @@
     // If this layer is orphaned, then we run a fake vsync pulse so that
     // dequeueBuffer doesn't block indefinitely.
     if (isRemovedFromCurrentState()) {
-        bool ignored = false;
-        latchBuffer(ignored, systemTime(), Fence::NO_FENCE);
-        usleep(16000);
-        releasePendingBuffer(systemTime());
+        fakeVsync();
     } else {
         mFlinger->signalLayerUpdate();
     }
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index f9da044..d7c3f6a 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -44,7 +44,7 @@
 
     std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush) override;
 
-    bool getTransformToDisplayInverseLocked() const override REQUIRES(mStateMutex);
+    bool getTransformToDisplayInverse() const override;
 
     // If a buffer was replaced this frame, release the former buffer
     void releasePendingBuffer(nsecs_t dequeueReadyTime) override;
@@ -64,12 +64,12 @@
 
 private:
     nsecs_t getDesiredPresentTime() override;
-    std::shared_ptr<FenceTime> getCurrentFenceTimeLocked() const override REQUIRES(mStateMutex);
+    std::shared_ptr<FenceTime> getCurrentFenceTime() const override;
 
     void getDrawingTransformMatrix(float *matrix) override;
-    uint32_t getDrawingTransform() const override REQUIRES(mStateMutex);
-    ui::Dataspace getDrawingDataSpace() const override REQUIRES(mStateMutex);
-    Rect getDrawingCrop() const override REQUIRES(mStateMutex);
+    uint32_t getDrawingTransform() const override;
+    ui::Dataspace getDrawingDataSpace() const override;
+    Rect getDrawingCrop() const override;
     uint32_t getDrawingScalingMode() const override;
     Region getDrawingSurfaceDamage() const override;
     const HdrMetadata& getDrawingHdrMetadata() const override;
@@ -81,18 +81,17 @@
     bool getAutoRefresh() const override;
     bool getSidebandStreamChanged() const override;
 
-    std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) override
-            EXCLUDES(mStateMutex);
+    std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) override;
 
-    bool hasFrameUpdateLocked() const override REQUIRES(mStateMutex);
+    bool hasFrameUpdate() const override;
 
     void setFilteringEnabled(bool enabled) override;
 
     status_t bindTextureImage() override;
     status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
-                            const sp<Fence>& releaseFence) override REQUIRES(mStateMutex);
+                            const sp<Fence>& releaseFence) override;
 
-    status_t updateActiveBuffer() override REQUIRES(mStateMutex);
+    status_t updateActiveBuffer() override;
     status_t updateFrameNumber(nsecs_t latchTime) override;
 
     void setHwcLayerBuffer(DisplayId displayId) override;
@@ -138,6 +137,8 @@
     // thread-safe
     std::atomic<int32_t> mQueuedFrames{0};
     std::atomic<bool> mSidebandStreamChanged{false};
+
+    void fakeVsync();
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 0e46928..e0d9d23 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -72,31 +72,30 @@
 }
 
 bool BufferStateLayer::willPresentCurrentTransaction() const {
-    Mutex::Autolock lock(mStateMutex);
     // Returns true if the most recent Transaction applied to CurrentState will be presented.
     return getSidebandStreamChanged() || getAutoRefresh() ||
-            (mState.current.modified && mState.current.buffer != nullptr);
+            (mCurrentState.modified && mCurrentState.buffer != nullptr);
 }
 
-bool BufferStateLayer::getTransformToDisplayInverseLocked() const {
-    return mState.current.transformToDisplayInverse;
+bool BufferStateLayer::getTransformToDisplayInverse() const {
+    return mCurrentState.transformToDisplayInverse;
 }
 
-void BufferStateLayer::pushPendingStateLocked() {
-    if (!mState.current.modified) {
+void BufferStateLayer::pushPendingState() {
+    if (!mCurrentState.modified) {
         return;
     }
-    mState.pending.push_back(mState.current);
-    ATRACE_INT(mTransactionName.string(), mState.pending.size());
+    mPendingStates.push_back(mCurrentState);
+    ATRACE_INT(mTransactionName.string(), mPendingStates.size());
 }
 
 bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) {
-    const bool stateUpdateAvailable = !mState.pending.empty();
-    while (!mState.pending.empty()) {
+    const bool stateUpdateAvailable = !mPendingStates.empty();
+    while (!mPendingStates.empty()) {
         popPendingState(stateToCommit);
     }
-    mCurrentStateModified = stateUpdateAvailable && mState.current.modified;
-    mState.current.modified = false;
+    mCurrentStateModified = stateUpdateAvailable && mCurrentState.modified;
+    mCurrentState.modified = false;
     return stateUpdateAvailable;
 }
 
@@ -106,31 +105,28 @@
 }
 
 bool BufferStateLayer::setTransform(uint32_t transform) {
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.transform == transform) return false;
-    mState.current.sequence++;
-    mState.current.transform = transform;
-    mState.current.modified = true;
+    if (mCurrentState.transform == transform) return false;
+    mCurrentState.sequence++;
+    mCurrentState.transform = transform;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInverse) {
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.transformToDisplayInverse == transformToDisplayInverse) return false;
-    mState.current.sequence++;
-    mState.current.transformToDisplayInverse = transformToDisplayInverse;
-    mState.current.modified = true;
+    if (mCurrentState.transformToDisplayInverse == transformToDisplayInverse) return false;
+    mCurrentState.sequence++;
+    mCurrentState.transformToDisplayInverse = transformToDisplayInverse;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setCrop(const Rect& crop) {
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.crop == crop) return false;
-    mState.current.sequence++;
-    mState.current.crop = crop;
-    mState.current.modified = true;
+    if (mCurrentState.crop == crop) return false;
+    mCurrentState.sequence++;
+    mCurrentState.crop = crop;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -141,94 +137,96 @@
     int w = frame.getWidth();
     int h = frame.getHeight();
 
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.active.transform.tx() == x && mState.current.active.transform.ty() == y &&
-        mState.current.active.w == w && mState.current.active.h == h) {
+    if (x < 0) {
+        x = 0;
+        w = frame.right;
+    }
+
+    if (y < 0) {
+        y = 0;
+        h = frame.bottom;
+    }
+
+    if (mCurrentState.active.transform.tx() == x && mCurrentState.active.transform.ty() == y &&
+        mCurrentState.active.w == w && mCurrentState.active.h == h) {
         return false;
     }
 
     if (!frame.isValid()) {
         x = y = w = h = 0;
     }
-    mState.current.active.transform.set(x, y);
-    mState.current.active.w = w;
-    mState.current.active.h = h;
+    mCurrentState.active.transform.set(x, y);
+    mCurrentState.active.w = w;
+    mCurrentState.active.h = h;
 
-    mState.current.sequence++;
-    mState.current.modified = true;
+    mCurrentState.sequence++;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer) {
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.buffer) {
+    if (mCurrentState.buffer) {
         mReleasePreviousBuffer = true;
     }
 
-    mState.current.sequence++;
-    mState.current.buffer = buffer;
-    mState.current.modified = true;
+    mCurrentState.sequence++;
+    mCurrentState.buffer = buffer;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setAcquireFence(const sp<Fence>& fence) {
-    Mutex::Autolock lock(mStateMutex);
     // The acquire fences of BufferStateLayers have already signaled before they are set
     mCallbackHandleAcquireTime = fence->getSignalTime();
 
-    mState.current.acquireFence = fence;
-    mState.current.modified = true;
+    mCurrentState.acquireFence = fence;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setDataspace(ui::Dataspace dataspace) {
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.dataspace == dataspace) return false;
-    mState.current.sequence++;
-    mState.current.dataspace = dataspace;
-    mState.current.modified = true;
+    if (mCurrentState.dataspace == dataspace) return false;
+    mCurrentState.sequence++;
+    mCurrentState.dataspace = dataspace;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setHdrMetadata(const HdrMetadata& hdrMetadata) {
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.hdrMetadata == hdrMetadata) return false;
-    mState.current.sequence++;
-    mState.current.hdrMetadata = hdrMetadata;
-    mState.current.modified = true;
+    if (mCurrentState.hdrMetadata == hdrMetadata) return false;
+    mCurrentState.sequence++;
+    mCurrentState.hdrMetadata = hdrMetadata;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setSurfaceDamageRegion(const Region& surfaceDamage) {
-    Mutex::Autolock lock(mStateMutex);
-    mState.current.sequence++;
-    mState.current.surfaceDamageRegion = surfaceDamage;
-    mState.current.modified = true;
+    mCurrentState.sequence++;
+    mCurrentState.surfaceDamageRegion = surfaceDamage;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setApi(int32_t api) {
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.api == api) return false;
-    mState.current.sequence++;
-    mState.current.api = api;
-    mState.current.modified = true;
+    if (mCurrentState.api == api) return false;
+    mCurrentState.sequence++;
+    mCurrentState.api = api;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool BufferStateLayer::setSidebandStream(const sp<NativeHandle>& sidebandStream) {
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.sidebandStream == sidebandStream) return false;
-    mState.current.sequence++;
-    mState.current.sidebandStream = sidebandStream;
-    mState.current.modified = true;
+    if (mCurrentState.sidebandStream == sidebandStream) return false;
+    mCurrentState.sequence++;
+    mCurrentState.sidebandStream = sidebandStream;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
 
     if (!mSidebandStreamChanged.exchange(true)) {
@@ -262,10 +260,7 @@
             mFlinger->getTransactionCompletedThread().registerPendingLatchedCallbackHandle(handle);
 
             // Store so latched time and release fence can be set
-            {
-                Mutex::Autolock lock(mStateMutex);
-                mState.current.callbackHandles.push_back(handle);
-            }
+            mCurrentState.callbackHandles.push_back(handle);
 
         } else { // If this layer will NOT need to be relatched and presented this frame
             // Notify the transaction completed thread this handle is done
@@ -280,9 +275,8 @@
 }
 
 bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) {
-    Mutex::Autolock lock(mStateMutex);
-    mState.current.transparentRegionHint = transparent;
-    mState.current.modified = true;
+    mCurrentState.transparentRegionHint = transparent;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -318,7 +312,6 @@
         return true;
     }
 
-    Mutex::Autolock lock(mStateMutex);
     return getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled;
 }
 
@@ -327,7 +320,7 @@
     return 0;
 }
 
-std::shared_ptr<FenceTime> BufferStateLayer::getCurrentFenceTimeLocked() const {
+std::shared_ptr<FenceTime> BufferStateLayer::getCurrentFenceTime() const {
     return std::make_shared<FenceTime>(getDrawingState().acquireFence);
 }
 
@@ -374,17 +367,14 @@
 }
 
 Region BufferStateLayer::getDrawingSurfaceDamage() const {
-    Mutex::Autolock lock(mStateMutex);
     return getDrawingState().surfaceDamageRegion;
 }
 
 const HdrMetadata& BufferStateLayer::getDrawingHdrMetadata() const {
-    Mutex::Autolock lock(mStateMutex);
     return getDrawingState().hdrMetadata;
 }
 
 int BufferStateLayer::getDrawingApi() const {
-    Mutex::Autolock lock(mStateMutex);
     return getDrawingState().api;
 }
 
@@ -409,7 +399,6 @@
 }
 
 std::optional<Region> BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
-    Mutex::Autolock lock(mStateMutex);
     if (mSidebandStreamChanged.exchange(false)) {
         const State& s(getDrawingState());
         // mSidebandStreamChanged was true
@@ -421,12 +410,12 @@
         }
         recomputeVisibleRegions = true;
 
-        return getTransformLocked().transform(Region(Rect(s.active.w, s.active.h)));
+        return getTransform().transform(Region(Rect(s.active.w, s.active.h)));
     }
     return {};
 }
 
-bool BufferStateLayer::hasFrameUpdateLocked() const {
+bool BufferStateLayer::hasFrameUpdate() const {
     return mCurrentStateModified && getCurrentState().buffer != nullptr;
 }
 
@@ -436,10 +425,6 @@
 }
 
 status_t BufferStateLayer::bindTextureImage() {
-    Mutex::Autolock lock(mStateMutex);
-    return bindTextureImageLocked();
-}
-status_t BufferStateLayer::bindTextureImageLocked() {
     const State& s(getDrawingState());
     auto& engine(mFlinger->getRenderEngine());
 
@@ -544,7 +529,7 @@
         auto incomingStatus = releaseFence->getStatus();
         if (incomingStatus == Fence::Status::Invalid) {
             ALOGE("New fence has invalid state");
-            mState.drawing.acquireFence = releaseFence;
+            mDrawingState.acquireFence = releaseFence;
             mFlinger->mTimeStats->onDestroy(layerID);
             return BAD_VALUE;
         }
@@ -555,16 +540,16 @@
             char fenceName[32] = {};
             snprintf(fenceName, 32, "%.28s:%d", mName.string(), mFrameNumber);
             sp<Fence> mergedFence =
-                    Fence::merge(fenceName, mState.drawing.acquireFence, releaseFence);
+                    Fence::merge(fenceName, mDrawingState.acquireFence, releaseFence);
             if (!mergedFence.get()) {
                 ALOGE("failed to merge release fences");
                 // synchronization is broken, the best we can do is hope fences
                 // signal in order so the new fence will act like a union
-                mState.drawing.acquireFence = releaseFence;
+                mDrawingState.acquireFence = releaseFence;
                 mFlinger->mTimeStats->onDestroy(layerID);
                 return BAD_VALUE;
             }
-            mState.drawing.acquireFence = mergedFence;
+            mDrawingState.acquireFence = mergedFence;
         } else if (incomingStatus == Fence::Status::Unsignaled) {
             // If one fence has signaled and the other hasn't, the unsignaled
             // fence will approximately correspond with the correct timestamp.
@@ -573,7 +558,7 @@
             // by this point, they will have both signaled and only the timestamp
             // will be slightly off; any dependencies after this point will
             // already have been met.
-            mState.drawing.acquireFence = releaseFence;
+            mDrawingState.acquireFence = releaseFence;
         }
     } else {
         // Bind the new buffer to the GL texture.
@@ -582,7 +567,7 @@
         // by glEGLImageTargetTexture2DOES, which this method calls.  Newer
         // devices will either call this in Layer::onDraw, or (if it's not
         // a GL-composited layer) not at all.
-        status_t err = bindTextureImageLocked();
+        status_t err = bindTextureImage();
         if (err != NO_ERROR) {
             mFlinger->mTimeStats->onDestroy(layerID);
             return BAD_VALUE;
@@ -591,7 +576,7 @@
 
     // TODO(marissaw): properly support mTimeStats
     mFlinger->mTimeStats->setPostTime(layerID, getFrameNumber(), getName().c_str(), latchTime);
-    mFlinger->mTimeStats->setAcquireFence(layerID, getFrameNumber(), getCurrentFenceTimeLocked());
+    mFlinger->mTimeStats->setAcquireFence(layerID, getFrameNumber(), getCurrentFenceTime());
     mFlinger->mTimeStats->setLatchTime(layerID, getFrameNumber(), latchTime);
 
     return NO_ERROR;
@@ -618,7 +603,6 @@
 }
 
 void BufferStateLayer::setHwcLayerBuffer(DisplayId displayId) {
-    Mutex::Autolock lock(mStateMutex);
     auto& hwcInfo = getBE().mHwcLayers[displayId];
     auto& hwcLayer = hwcInfo.layer;
 
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 655353c..3f891d3 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -41,14 +41,13 @@
 
     bool shouldPresentNow(nsecs_t expectedPresentTime) const override;
 
-    bool getTransformToDisplayInverseLocked() const override REQUIRES(mStateMutex);
+    bool getTransformToDisplayInverse() const override;
 
     uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override {
         return flags;
     }
-
-    void pushPendingStateLocked() override REQUIRES(mStateMutex);
-    bool applyPendingStates(Layer::State* stateToCommit) override REQUIRES(mStateMutex);
+    void pushPendingState() override;
+    bool applyPendingStates(Layer::State* stateToCommit) override;
 
     uint32_t getActiveWidth(const Layer::State& s) const override { return s.active.w; }
     uint32_t getActiveHeight(const Layer::State& s) const override { return s.active.h; }
@@ -60,20 +59,18 @@
     }
     Rect getCrop(const Layer::State& s) const;
 
-    bool setTransform(uint32_t transform) override EXCLUDES(mStateMutex);
-    bool setTransformToDisplayInverse(bool transformToDisplayInverse) override
-            EXCLUDES(mStateMutex);
-    bool setCrop(const Rect& crop) override EXCLUDES(mStateMutex);
-    bool setFrame(const Rect& frame) override EXCLUDES(mStateMutex);
-    bool setBuffer(const sp<GraphicBuffer>& buffer) override EXCLUDES(mStateMutex);
-    bool setAcquireFence(const sp<Fence>& fence) override EXCLUDES(mStateMutex);
-    bool setDataspace(ui::Dataspace dataspace) override EXCLUDES(mStateMutex);
-    bool setHdrMetadata(const HdrMetadata& hdrMetadata) override EXCLUDES(mStateMutex);
-    bool setSurfaceDamageRegion(const Region& surfaceDamage) override EXCLUDES(mStateMutex);
-    bool setApi(int32_t api) override EXCLUDES(mStateMutex);
-    bool setSidebandStream(const sp<NativeHandle>& sidebandStream) override EXCLUDES(mStateMutex);
-    bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles) override
-            EXCLUDES(mStateMutex);
+    bool setTransform(uint32_t transform) override;
+    bool setTransformToDisplayInverse(bool transformToDisplayInverse) override;
+    bool setCrop(const Rect& crop) override;
+    bool setFrame(const Rect& frame) override;
+    bool setBuffer(const sp<GraphicBuffer>& buffer) override;
+    bool setAcquireFence(const sp<Fence>& fence) override;
+    bool setDataspace(ui::Dataspace dataspace) override;
+    bool setHdrMetadata(const HdrMetadata& hdrMetadata) override;
+    bool setSurfaceDamageRegion(const Region& surfaceDamage) override;
+    bool setApi(int32_t api) override;
+    bool setSidebandStream(const sp<NativeHandle>& sidebandStream) override;
+    bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles) override;
 
     // Override to ignore legacy layer state properties that are not used by BufferStateLayer
     bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; }
@@ -90,26 +87,26 @@
     void deferTransactionUntil_legacy(const sp<Layer>& /*barrierLayer*/,
                                       uint64_t /*frameNumber*/) override {}
 
-    Rect getBufferSize(const State& s) const override REQUIRES(mStateMutex);
+    Rect getBufferSize(const State& s) const override;
     // -----------------------------------------------------------------------
 
     // -----------------------------------------------------------------------
     // Interface implementation for BufferLayer
     // -----------------------------------------------------------------------
-    bool fenceHasSignaled() const override EXCLUDES(mStateMutex);
+    bool fenceHasSignaled() const override;
 
 private:
     nsecs_t getDesiredPresentTime() override;
-    std::shared_ptr<FenceTime> getCurrentFenceTimeLocked() const override REQUIRES(mStateMutex);
+    std::shared_ptr<FenceTime> getCurrentFenceTime() const override;
 
     void getDrawingTransformMatrix(float *matrix) override;
-    uint32_t getDrawingTransform() const override REQUIRES(mStateMutex);
-    ui::Dataspace getDrawingDataSpace() const override REQUIRES(mStateMutex);
-    Rect getDrawingCrop() const override REQUIRES(mStateMutex);
+    uint32_t getDrawingTransform() const override;
+    ui::Dataspace getDrawingDataSpace() const override;
+    Rect getDrawingCrop() const override;
     uint32_t getDrawingScalingMode() const override;
-    Region getDrawingSurfaceDamage() const override EXCLUDES(mStateMutex);
-    const HdrMetadata& getDrawingHdrMetadata() const override EXCLUDES(mStateMutex);
-    int getDrawingApi() const override EXCLUDES(mStateMutex);
+    Region getDrawingSurfaceDamage() const override;
+    const HdrMetadata& getDrawingHdrMetadata() const override;
+    int getDrawingApi() const override;
     PixelFormat getPixelFormat() const override;
 
     uint64_t getFrameNumber() const override;
@@ -117,26 +114,24 @@
     bool getAutoRefresh() const override;
     bool getSidebandStreamChanged() const override;
 
-    std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) override
-            EXCLUDES(mStateMutex);
+    std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) override;
 
-    bool hasFrameUpdateLocked() const override REQUIRES(mStateMutex);
+    bool hasFrameUpdate() const override;
 
     void setFilteringEnabled(bool enabled) override;
 
-    status_t bindTextureImage() override EXCLUDES(mStateMutex);
+    status_t bindTextureImage() override;
     status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
-                            const sp<Fence>& releaseFence) override REQUIRES(mStateMutex);
+                            const sp<Fence>& releaseFence) override;
 
-    status_t updateActiveBuffer() override REQUIRES(mStateMutex);
+    status_t updateActiveBuffer() override;
     status_t updateFrameNumber(nsecs_t latchTime) override;
 
-    void setHwcLayerBuffer(DisplayId displayId) override EXCLUDES(mStateMutex);
+    void setHwcLayerBuffer(DisplayId displayId) override;
 
 private:
     void onFirstRef() override;
     bool willPresentCurrentTransaction() const;
-    status_t bindTextureImageLocked() REQUIRES(mStateMutex);
 
     static const std::array<float, 16> IDENTITY_MATRIX;
 
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 0b59147..0e447d8 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -35,55 +35,10 @@
 // ---------------------------------------------------------------------------
 
 Client::Client(const sp<SurfaceFlinger>& flinger)
-    : Client(flinger, nullptr)
+    : mFlinger(flinger)
 {
 }
 
-Client::Client(const sp<SurfaceFlinger>& flinger, const sp<Layer>& parentLayer)
-    : mFlinger(flinger),
-      mParentLayer(parentLayer)
-{
-}
-
-Client::~Client()
-{
-    // We need to post a message to remove our remaining layers rather than
-    // do so directly by acquiring the SurfaceFlinger lock. If we were to
-    // attempt to directly call the lock it becomes effectively impossible
-    // to use sp<Client> while holding the SF lock as descoping it could
-    // then trigger a dead-lock.
-
-    const size_t count = mLayers.size();
-    for (size_t i=0 ; i<count ; i++) {
-        sp<Layer> l = mLayers.valueAt(i).promote();
-        if (l == nullptr) {
-            continue;
-        }
-        mFlinger->postMessageAsync(new LambdaMessage([flinger = mFlinger, l]() {
-            flinger->removeLayer(l);
-        }));
-    }
-}
-
-void Client::updateParent(const sp<Layer>& parentLayer) {
-    Mutex::Autolock _l(mLock);
-
-    // If we didn't ever have a parent, then we must instead be
-    // relying on permissions and we never need a parent.
-    if (mParentLayer != nullptr) {
-        mParentLayer = parentLayer;
-    }
-}
-
-sp<Layer> Client::getParentLayer(bool* outParentDied) const {
-    Mutex::Autolock _l(mLock);
-    sp<Layer> parent = mParentLayer.promote();
-    if (outParentDied != nullptr) {
-        *outParentDied = (mParentLayer != nullptr && parent == nullptr);
-    }
-    return parent;
-}
-
 status_t Client::initCheck() const {
     return NO_ERROR;
 }
@@ -119,32 +74,6 @@
 }
 
 
-status_t Client::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    // these must be checked
-     IPCThreadState* ipc = IPCThreadState::self();
-     const int pid = ipc->getCallingPid();
-     const int uid = ipc->getCallingUid();
-     const int self_pid = getpid();
-     // If we are called from another non root process without the GRAPHICS, SYSTEM, or ROOT
-     // uid we require the sAccessSurfaceFlinger permission.
-     // We grant an exception in the case that the Client has a "parent layer", as its
-     // effects will be scoped to that layer.
-     if (CC_UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != AID_SYSTEM && uid != 0)
-             && (getParentLayer() == nullptr)) {
-         // we're called from a different process, do the real check
-         if (!PermissionCache::checkCallingPermission(sAccessSurfaceFlinger))
-         {
-             ALOGE("Permission Denial: "
-                     "can't openGlobalTransaction pid=%d, uid<=%d", pid, uid);
-             return PERMISSION_DENIED;
-         }
-     }
-     return BnSurfaceComposerClient::onTransact(code, data, reply, flags);
-}
-
-
 status_t Client::createSurface(
         const String8& name,
         uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
@@ -160,22 +89,30 @@
             return NAME_NOT_FOUND;
         }
     }
-    if (parent == nullptr) {
-        bool parentDied;
-        parent = getParentLayer(&parentDied);
-        // If we had a parent, but it died, we've lost all
-        // our capabilities.
-        if (parentDied) {
-            return NAME_NOT_FOUND;
-        }
-    }
 
+    // We rely on createLayer to check permissions.
     return mFlinger->createLayer(name, this, w, h, format, flags, windowType,
                                  ownerUid, handle, gbp, &parent);
 }
 
-status_t Client::destroySurface(const sp<IBinder>& handle) {
-    return mFlinger->onLayerRemoved(this, handle);
+status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
+                                         PixelFormat format, uint32_t flags,
+                                         const sp<IGraphicBufferProducer>& parent,
+                                         int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
+                                         sp<IGraphicBufferProducer>* gbp) {
+    if (mFlinger->authenticateSurfaceTexture(parent) == false) {
+        return BAD_VALUE;
+    }
+
+    const auto& layer = (static_cast<MonitoredProducer*>(parent.get()))->getLayer();
+    if (layer == nullptr) {
+        return BAD_VALUE;
+    }
+
+    sp<IBinder> parentHandle = layer->getHandle();
+
+    return createSurface(name, w, h, format, flags, parentHandle, windowType, ownerUid, handle,
+                         gbp);
 }
 
 status_t Client::clearLayerFrameStats(const sp<IBinder>& handle) const {
diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h
index 49437ed..0f5ee4c 100644
--- a/services/surfaceflinger/Client.h
+++ b/services/surfaceflinger/Client.h
@@ -39,20 +39,16 @@
 {
 public:
     explicit Client(const sp<SurfaceFlinger>& flinger);
-    Client(const sp<SurfaceFlinger>& flinger, const sp<Layer>& parentLayer);
-    ~Client();
+    ~Client() = default;
 
     status_t initCheck() const;
 
     // protected by SurfaceFlinger::mStateLock
     void attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer);
-
     void detachLayer(const Layer* layer);
 
     sp<Layer> getLayerUser(const sp<IBinder>& handle) const;
 
-    void updateParent(const sp<Layer>& parentLayer);
-
 private:
     // ISurfaceComposerClient interface
     virtual status_t createSurface(
@@ -62,23 +58,21 @@
             sp<IBinder>* handle,
             sp<IGraphicBufferProducer>* gbp);
 
-    virtual status_t destroySurface(const sp<IBinder>& handle);
+    virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
+                                             PixelFormat format, uint32_t flags,
+                                             const sp<IGraphicBufferProducer>& parent,
+                                             int32_t windowType, int32_t ownerUid,
+                                             sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp);
 
     virtual status_t clearLayerFrameStats(const sp<IBinder>& handle) const;
 
     virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const;
 
-    virtual status_t onTransact(
-        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
-
-    sp<Layer> getParentLayer(bool* outParentDied = nullptr) const;
-
     // constant
     sp<SurfaceFlinger> mFlinger;
 
     // protected by mLock
     DefaultKeyedVector< wp<IBinder>, wp<Layer> > mLayers;
-    wp<Layer> mParentLayer;
 
     // thread-safe
     mutable Mutex mLock;
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index cb7642e..f27f6aa 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -40,16 +40,15 @@
 
 void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */,
                         bool useIdentityTransform) {
-    Mutex::Autolock lock(mStateMutex);
     half4 color = getColor();
     if (color.a > 0) {
         renderengine::Mesh mesh(renderengine::Mesh::TRIANGLE_FAN, 4, 2);
         computeGeometry(renderArea, mesh, useIdentityTransform);
         auto& engine(mFlinger->getRenderEngine());
 
-        Rect win{computeBoundsLocked()};
+        Rect win{computeBounds()};
 
-        const auto roundedCornerState = getRoundedCornerStateLocked();
+        const auto roundedCornerState = getRoundedCornerState();
         const auto cropRect = roundedCornerState.cropRect;
         setupRoundedCornersCropCoordinates(win, cropRect);
 
@@ -92,7 +91,6 @@
     }
     getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace;
 
-    Mutex::Autolock lock(mStateMutex);
     half4 color = getColor();
     error = hwcLayer->setColor({static_cast<uint8_t>(std::round(255.0f * color.r)),
                                 static_cast<uint8_t>(std::round(255.0f * color.g)),
@@ -113,12 +111,12 @@
     }
     getBE().compositionInfo.hwc.transform = HWC2::Transform::None;
 
-    error = hwcLayer->setColorTransform(getColorTransformLocked());
+    error = hwcLayer->setColorTransform(getColorTransform());
     if (error != HWC2::Error::None) {
         ALOGE("[%s] Failed to setColorTransform: %s (%d)", mName.string(),
                 to_string(error).c_str(), static_cast<int32_t>(error));
     }
-    getBE().compositionInfo.hwc.colorTransform = getColorTransformLocked();
+    getBE().compositionInfo.hwc.colorTransform = getColorTransform();
 
     error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
     if (error != HWC2::Error::None) {
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index 5850a2e..aecde9f 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -29,17 +29,17 @@
     ~ColorLayer() override;
 
     virtual const char* getTypeId() const { return "ColorLayer"; }
-    virtual void onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform)
-            EXCLUDES(mStateMutex);
-    bool isVisible() const override EXCLUDES(mStateMutex);
+    virtual void onDraw(const RenderArea& renderArea, const Region& clip,
+                        bool useIdentityTransform);
+    bool isVisible() const override;
 
     void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport,
-                         int32_t supportedPerFrameMetadata) override EXCLUDES(mStateMutex);
+                         int32_t supportedPerFrameMetadata) override;
 
     bool onPreComposition(nsecs_t /*refreshStartTime*/) override { return false; }
 
 protected:
-    FloatRect computeCrop(const sp<const DisplayDevice>& /*display*/) const override { return {}; }
+    FloatRect computeCrop(const Rect& /*windowbounds*/) const override { return {}; }
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
new file mode 100644
index 0000000..ec5e131
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -0,0 +1,88 @@
+cc_defaults {
+    name: "libcompositionengine_defaults",
+    defaults: ["surfaceflinger_defaults"],
+    cflags: [
+        "-DLOG_TAG=\"CompositionEngine\"",
+    ],
+    shared_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.2",
+        "android.hardware.graphics.composer@2.3",
+        "android.hardware.power@1.0",
+        "android.hardware.power@1.3",
+        "libbase",
+        "libcutils",
+        "libgui",
+        "liblayers_proto",
+        "liblog",
+        "libtimestats_proto",
+        "libui",
+        "libutils",
+    ],
+    static_libs: [
+        "libmath",
+        "librenderengine",
+        "libtrace_proto",
+    ],
+    header_libs: [
+        "libsurfaceflinger_headers",
+    ],
+}
+
+cc_library {
+    name: "libcompositionengine",
+    defaults: ["libcompositionengine_defaults"],
+    srcs: [
+        "src/CompositionEngine.cpp",
+    ],
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+}
+
+cc_library {
+    name: "libcompositionengine_mocks",
+    defaults: ["libcompositionengine_defaults"],
+    srcs: [
+        "mock/CompositionEngine.cpp",
+    ],
+    static_libs: [
+        "libgtest",
+        "libgmock",
+        "libcompositionengine",
+    ],
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+}
+
+cc_test {
+    name: "libcompositionengine_test",
+    test_suites: ["device-tests"],
+    defaults: ["libcompositionengine_defaults"],
+    srcs: [
+        "tests/CompositionEngineTest.cpp",
+        "tests/MockHWComposer.cpp",
+    ],
+    static_libs: [
+        "libcompositionengine",
+        "libcompositionengine_mocks",
+        "librenderengine_mocks",
+        "libgmock",
+        "libgtest",
+    ],
+    sanitize: {
+        // By using the address sanitizer, we not only uncover any issues
+        // with the test, but also any issues with the code under test.
+        //
+        // Note: If you get an runtime link error like:
+        //
+        //   CANNOT LINK EXECUTABLE "/data/local/tmp/libcompositionengine_test": library "libclang_rt.asan-aarch64-android.so" not found
+        //
+        // it is because the address sanitizer shared objects are not installed
+        // by default in the system image.
+        //
+        // You can either "make dist tests" before flashing, or set this
+        // option to false temporarily.
+        address: true,
+    },
+}
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
new file mode 100644
index 0000000..af8515f
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+
+namespace android {
+
+class HWComposer;
+
+namespace renderengine {
+class RenderEngine;
+} // namespace renderengine
+
+namespace compositionengine {
+
+/**
+ * Encapsulates all the interfaces and implementation details for performing
+ * display output composition.
+ */
+class CompositionEngine {
+public:
+    virtual ~CompositionEngine();
+
+    virtual HWComposer& getHwComposer() const = 0;
+    virtual void setHwComposer(std::unique_ptr<HWComposer>) = 0;
+
+    virtual renderengine::RenderEngine& getRenderEngine() const = 0;
+    virtual void setRenderEngine(std::unique_ptr<renderengine::RenderEngine>) = 0;
+};
+
+} // namespace compositionengine
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
new file mode 100644
index 0000000..86d1774
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <compositionengine/CompositionEngine.h>
+
+namespace android::compositionengine::impl {
+
+class CompositionEngine : public compositionengine::CompositionEngine {
+public:
+    CompositionEngine();
+    ~CompositionEngine() override;
+
+    HWComposer& getHwComposer() const override;
+    void setHwComposer(std::unique_ptr<HWComposer>) override;
+
+    renderengine::RenderEngine& getRenderEngine() const override;
+    void setRenderEngine(std::unique_ptr<renderengine::RenderEngine>) override;
+
+private:
+    std::unique_ptr<HWComposer> mHwComposer;
+    std::unique_ptr<renderengine::RenderEngine> mRenderEngine;
+};
+
+std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine();
+
+} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
new file mode 100644
index 0000000..9ba213e
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <compositionengine/CompositionEngine.h>
+#include <gmock/gmock.h>
+#include <renderengine/RenderEngine.h>
+
+#include "DisplayHardware/HWComposer.h"
+
+namespace android::compositionengine::mock {
+
+class CompositionEngine : public compositionengine::CompositionEngine {
+public:
+    CompositionEngine();
+    ~CompositionEngine() override;
+
+    MOCK_CONST_METHOD0(getHwComposer, HWComposer&());
+    MOCK_METHOD1(setHwComposer, void(std::unique_ptr<HWComposer>));
+
+    MOCK_CONST_METHOD0(getRenderEngine, renderengine::RenderEngine&());
+    MOCK_METHOD1(setRenderEngine, void(std::unique_ptr<renderengine::RenderEngine>));
+};
+
+} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/mock/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/mock/CompositionEngine.cpp
new file mode 100644
index 0000000..778a09e
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/mock/CompositionEngine.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <compositionengine/mock/CompositionEngine.h>
+
+namespace android::compositionengine::mock {
+
+// The Google Mock documentation recommends explicit non-header instantiations
+// for better compile time performance.
+CompositionEngine::CompositionEngine() = default;
+CompositionEngine::~CompositionEngine() = default;
+
+} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
new file mode 100644
index 0000000..fbf71b5
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <compositionengine/impl/CompositionEngine.h>
+#include <renderengine/RenderEngine.h>
+
+#include "DisplayHardware/HWComposer.h"
+
+namespace android::compositionengine {
+
+CompositionEngine::~CompositionEngine() = default;
+
+namespace impl {
+
+std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() {
+    return std::make_unique<CompositionEngine>();
+}
+
+CompositionEngine::CompositionEngine() = default;
+CompositionEngine::~CompositionEngine() = default;
+
+HWComposer& CompositionEngine::getHwComposer() const {
+    return *mHwComposer.get();
+}
+
+void CompositionEngine::setHwComposer(std::unique_ptr<HWComposer> hwComposer) {
+    mHwComposer = std::move(hwComposer);
+}
+
+renderengine::RenderEngine& CompositionEngine::getRenderEngine() const {
+    return *mRenderEngine.get();
+}
+
+void CompositionEngine::setRenderEngine(std::unique_ptr<renderengine::RenderEngine> renderEngine) {
+    mRenderEngine = std::move(renderEngine);
+}
+
+} // namespace impl
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
new file mode 100644
index 0000000..3766f27
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <compositionengine/impl/CompositionEngine.h>
+#include <gtest/gtest.h>
+#include <renderengine/mock/RenderEngine.h>
+
+#include "MockHWComposer.h"
+
+namespace android::compositionengine {
+namespace {
+
+using ::testing::StrictMock;
+
+class CompositionEngineTest : public testing::Test {
+public:
+    ~CompositionEngineTest() override;
+    mock::HWComposer* mHwc = new StrictMock<mock::HWComposer>();
+    renderengine::mock::RenderEngine* mRenderEngine =
+            new StrictMock<renderengine::mock::RenderEngine>();
+    impl::CompositionEngine mEngine;
+};
+
+CompositionEngineTest::~CompositionEngineTest() = default;
+
+TEST_F(CompositionEngineTest, canInstantiateCompositionEngine) {
+    auto engine = impl::createCompositionEngine();
+    EXPECT_TRUE(engine.get() != nullptr);
+}
+
+TEST_F(CompositionEngineTest, canSetHWComposer) {
+    mEngine.setHwComposer(std::unique_ptr<android::HWComposer>(mHwc));
+
+    EXPECT_EQ(mHwc, &mEngine.getHwComposer());
+}
+
+TEST_F(CompositionEngineTest, canSetRenderEngine) {
+    mEngine.setRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
+
+    EXPECT_EQ(mRenderEngine, &mEngine.getRenderEngine());
+}
+
+} // namespace
+} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.cpp b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.cpp
new file mode 100644
index 0000000..ae52670
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MockHWComposer.h"
+
+namespace android {
+
+// This will go away once HWComposer is moved into the "backend" library
+HWComposer::~HWComposer() = default;
+
+namespace mock {
+
+// The Google Mock documentation recommends explicit non-header instantiations
+// for better compile time performance.
+HWComposer::HWComposer() = default;
+HWComposer::~HWComposer() = default;
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
new file mode 100644
index 0000000..ece412f
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include "LayerBE.h"
+
+#include "DisplayHardware/HWComposer.h"
+
+namespace android {
+namespace mock {
+
+class HWComposer : public android::HWComposer {
+public:
+    HWComposer();
+    ~HWComposer() override;
+
+    MOCK_METHOD2(registerCallback, void(HWC2::ComposerCallback*, int32_t));
+    MOCK_CONST_METHOD3(getDisplayIdentificationData,
+                       bool(hwc2_display_t, uint8_t*, DisplayIdentificationData*));
+    MOCK_CONST_METHOD1(hasCapability, bool(HWC2::Capability));
+    MOCK_CONST_METHOD2(hasDisplayCapability,
+                       bool(const std::optional<DisplayId>&, HWC2::DisplayCapability));
+
+    MOCK_METHOD3(allocateVirtualDisplay,
+                 std::optional<DisplayId>(uint32_t, uint32_t, ui::PixelFormat*));
+    MOCK_METHOD1(createLayer, HWC2::Layer*(DisplayId));
+    MOCK_METHOD2(destroyLayer, void(DisplayId, HWC2::Layer*));
+    MOCK_METHOD2(prepare, status_t(DisplayId, std::vector<CompositionInfo>&));
+    MOCK_METHOD5(setClientTarget,
+                 status_t(DisplayId, uint32_t, const sp<Fence>&, const sp<GraphicBuffer>&,
+                          ui::Dataspace));
+    MOCK_METHOD1(presentAndGetReleaseFences, status_t(DisplayId));
+    MOCK_METHOD2(setPowerMode, status_t(DisplayId, int));
+    MOCK_METHOD2(setActiveConfig, status_t(DisplayId, size_t));
+    MOCK_METHOD2(setColorTransform, status_t(DisplayId, const mat4&));
+    MOCK_METHOD1(disconnectDisplay, void(DisplayId));
+    MOCK_CONST_METHOD1(hasDeviceComposition, bool(const std::optional<DisplayId>&));
+    MOCK_CONST_METHOD1(hasFlipClientTargetRequest, bool(const std::optional<DisplayId>&));
+    MOCK_CONST_METHOD1(hasClientComposition, bool(const std::optional<DisplayId>&));
+    MOCK_CONST_METHOD1(getPresentFence, sp<Fence>(DisplayId));
+    MOCK_CONST_METHOD2(getLayerReleaseFence, sp<Fence>(DisplayId, HWC2::Layer*));
+    MOCK_METHOD3(setOutputBuffer, status_t(DisplayId, const sp<Fence>&, const sp<GraphicBuffer>&));
+    MOCK_METHOD1(clearReleaseFences, void(DisplayId));
+    MOCK_METHOD2(getHdrCapabilities, status_t(DisplayId, HdrCapabilities*));
+    MOCK_CONST_METHOD1(getSupportedPerFrameMetadata, int32_t(DisplayId));
+    MOCK_CONST_METHOD2(getRenderIntents, std::vector<ui::RenderIntent>(DisplayId, ui::ColorMode));
+    MOCK_METHOD2(getDataspaceSaturationMatrix, mat4(DisplayId, ui::Dataspace));
+    MOCK_METHOD4(getDisplayedContentSamplingAttributes,
+                 status_t(DisplayId, ui::PixelFormat*, ui::Dataspace*, uint8_t*));
+    MOCK_METHOD4(setDisplayContentSamplingEnabled, status_t(DisplayId, bool, uint8_t, uint64_t));
+    MOCK_METHOD4(getDisplayedContentSample,
+                 status_t(DisplayId, uint64_t, uint64_t, DisplayedFrameStats*));
+
+    MOCK_METHOD2(onHotplug,
+                 std::optional<DisplayIdentificationInfo>(hwc2_display_t, HWC2::Connection));
+    MOCK_METHOD2(onVsync, bool(hwc2_display_t, int64_t));
+    MOCK_METHOD2(setVsyncEnabled, void(DisplayId, HWC2::Vsync));
+    MOCK_CONST_METHOD1(getRefreshTimestamp, nsecs_t(DisplayId));
+    MOCK_CONST_METHOD1(isConnected, bool(DisplayId));
+    MOCK_CONST_METHOD1(getConfigs,
+                       std::vector<std::shared_ptr<const HWC2::Display::Config>>(DisplayId));
+    MOCK_CONST_METHOD1(getActiveConfig, std::shared_ptr<const HWC2::Display::Config>(DisplayId));
+    MOCK_CONST_METHOD1(getActiveConfigIndex, int(DisplayId));
+    MOCK_CONST_METHOD1(getColorModes, std::vector<ui::ColorMode>(DisplayId));
+    MOCK_METHOD3(setActiveColorMode, status_t(DisplayId, ui::ColorMode, ui::RenderIntent));
+    MOCK_CONST_METHOD0(isUsingVrComposer, bool());
+
+    MOCK_CONST_METHOD1(dump, void(std::string&));
+    MOCK_CONST_METHOD0(getComposer, android::Hwc2::Composer*());
+    MOCK_CONST_METHOD1(getHwcDisplayId, std::optional<hwc2_display_t>(int32_t));
+    MOCK_CONST_METHOD0(getInternalHwcDisplayId, std::optional<hwc2_display_t>());
+    MOCK_CONST_METHOD0(getExternalHwcDisplayId, std::optional<hwc2_display_t>());
+    MOCK_CONST_METHOD1(toPhysicalDisplayId, std::optional<DisplayId>(hwc2_display_t));
+    MOCK_CONST_METHOD1(fromPhysicalDisplayId, std::optional<hwc2_display_t>(DisplayId));
+};
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index 6c4f7c8..413844b 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -31,7 +31,7 @@
     const char* getTypeId() const override { return "ContainerLayer"; }
     void onDraw(const RenderArea& renderArea, const Region& clip,
                 bool useIdentityTransform) override;
-    bool isVisible() const override EXCLUDES(mStateMutex);
+    bool isVisible() const override;
 
     void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport,
                          int32_t supportedPerFrameMetadata) override;
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 2d91c68..03eafd5 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -40,13 +40,12 @@
 
 class BufferHandle {
 public:
-    BufferHandle(const native_handle_t* buffer)
-    {
+    explicit BufferHandle(const native_handle_t* buffer) {
         // nullptr is not a valid handle to HIDL
         mHandle = (buffer) ? buffer : native_handle_init(mStorage, 0, 0);
     }
 
-    operator const hidl_handle&() const
+    operator const hidl_handle&() const // NOLINT(google-explicit-constructor)
     {
         return mHandle;
     }
@@ -80,7 +79,7 @@
         }
     }
 
-    operator const hidl_handle&() const
+    operator const hidl_handle&() const // NOLINT(google-explicit-constructor)
     {
         return mHandle;
     }
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 9d0d8d9..ba3d2a6 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -285,7 +285,7 @@
 // Composer is a wrapper to IComposer, a proxy to server-side composer.
 class Composer final : public Hwc2::Composer {
 public:
-    Composer(const std::string& serviceName);
+    explicit Composer(const std::string& serviceName);
     ~Composer() override;
 
     std::vector<IComposer::Capability> getCapabilities() override;
@@ -418,7 +418,7 @@
 private:
     class CommandWriter : public CommandWriterBase {
     public:
-        CommandWriter(uint32_t initialMaxSize);
+        explicit CommandWriter(uint32_t initialMaxSize);
         ~CommandWriter() override;
 
         void setLayerInfo(uint32_t type, uint32_t appId);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 0497571..5b4d347 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -66,6 +66,10 @@
 
 namespace android {
 
+HWComposer::~HWComposer() = default;
+
+namespace impl {
+
 HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer)
       : mHwcDevice(std::make_unique<HWC2::Device>(std::move(composer))) {}
 
@@ -98,6 +102,10 @@
 bool HWComposer::hasDisplayCapability(const std::optional<DisplayId>& displayId,
                                       HWC2::DisplayCapability capability) const {
     if (!displayId) {
+        // Checkout global capabilities for displays without a corresponding HWC display.
+        if (capability == HWC2::DisplayCapability::SkipClientColorTransform) {
+            return hasCapability(HWC2::Capability::SkipClientColorTransform);
+        }
         return false;
     }
     RETURN_IF_INVALID_DISPLAY(*displayId, false);
@@ -854,4 +862,5 @@
                                                                            : "External display"};
 }
 
+} // namespace impl
 } // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index d9a0916..f42f860 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -45,134 +45,273 @@
 class Composer;
 } // namespace Hwc2
 
-class HWComposer
-{
+class HWComposer {
+public:
+    virtual ~HWComposer();
+
+    virtual void registerCallback(HWC2::ComposerCallback* callback, int32_t sequenceId) = 0;
+
+    virtual bool getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
+                                              DisplayIdentificationData* outData) const = 0;
+
+    virtual bool hasCapability(HWC2::Capability capability) const = 0;
+    virtual bool hasDisplayCapability(const std::optional<DisplayId>& displayId,
+                                      HWC2::DisplayCapability capability) const = 0;
+
+    // Attempts to allocate a virtual display and returns its ID if created on the HWC device.
+    virtual std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height,
+                                                            ui::PixelFormat* format) = 0;
+
+    // Attempts to create a new layer on this display
+    virtual HWC2::Layer* createLayer(DisplayId displayId) = 0;
+    // Destroy a previously created layer
+    virtual void destroyLayer(DisplayId displayId, HWC2::Layer* layer) = 0;
+
+    // Asks the HAL what it can do
+    virtual status_t prepare(DisplayId displayId,
+                             std::vector<CompositionInfo>& compositionData) = 0;
+
+    virtual status_t setClientTarget(DisplayId displayId, uint32_t slot,
+                                     const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
+                                     ui::Dataspace dataspace) = 0;
+
+    // Present layers to the display and read releaseFences.
+    virtual status_t presentAndGetReleaseFences(DisplayId displayId) = 0;
+
+    // set power mode
+    virtual status_t setPowerMode(DisplayId displayId, int mode) = 0;
+
+    // set active config
+    virtual status_t setActiveConfig(DisplayId displayId, size_t configId) = 0;
+
+    // Sets a color transform to be applied to the result of composition
+    virtual status_t setColorTransform(DisplayId displayId, const mat4& transform) = 0;
+
+    // reset state when an external, non-virtual display is disconnected
+    virtual void disconnectDisplay(DisplayId displayId) = 0;
+
+    // does this display have layers handled by HWC
+    virtual bool hasDeviceComposition(const std::optional<DisplayId>& displayId) const = 0;
+
+    // does this display have pending request to flip client target
+    virtual bool hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const = 0;
+
+    // does this display have layers handled by GLES
+    virtual bool hasClientComposition(const std::optional<DisplayId>& displayId) const = 0;
+
+    // get the present fence received from the last call to present.
+    virtual sp<Fence> getPresentFence(DisplayId displayId) const = 0;
+
+    // Get last release fence for the given layer
+    virtual sp<Fence> getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const = 0;
+
+    // Set the output buffer and acquire fence for a virtual display.
+    // Returns INVALID_OPERATION if displayId is not a virtual display.
+    virtual status_t setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence,
+                                     const sp<GraphicBuffer>& buffer) = 0;
+
+    // After SurfaceFlinger has retrieved the release fences for all the frames,
+    // it can call this to clear the shared pointers in the release fence map
+    virtual void clearReleaseFences(DisplayId displayId) = 0;
+
+    // Fetches the HDR capabilities of the given display
+    virtual status_t getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) = 0;
+
+    virtual int32_t getSupportedPerFrameMetadata(DisplayId displayId) const = 0;
+
+    // Returns the available RenderIntent of the given display.
+    virtual std::vector<ui::RenderIntent> getRenderIntents(DisplayId displayId,
+                                                           ui::ColorMode colorMode) const = 0;
+
+    virtual mat4 getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) = 0;
+
+    // Returns the attributes of the color sampling engine.
+    virtual status_t getDisplayedContentSamplingAttributes(DisplayId displayId,
+                                                           ui::PixelFormat* outFormat,
+                                                           ui::Dataspace* outDataspace,
+                                                           uint8_t* outComponentMask) = 0;
+    virtual status_t setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled,
+                                                      uint8_t componentMask,
+                                                      uint64_t maxFrames) = 0;
+    virtual status_t getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames,
+                                               uint64_t timestamp,
+                                               DisplayedFrameStats* outStats) = 0;
+
+    // Events handling ---------------------------------------------------------
+
+    // Returns stable display ID (and display name on connection of new or previously disconnected
+    // display), or std::nullopt if hotplug event was ignored.
+    virtual std::optional<DisplayIdentificationInfo> onHotplug(hwc2_display_t hwcDisplayId,
+                                                               HWC2::Connection connection) = 0;
+
+    virtual bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) = 0;
+    virtual void setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled) = 0;
+
+    virtual nsecs_t getRefreshTimestamp(DisplayId displayId) const = 0;
+    virtual bool isConnected(DisplayId displayId) const = 0;
+
+    // Non-const because it can update configMap inside of mDisplayData
+    virtual std::vector<std::shared_ptr<const HWC2::Display::Config>> getConfigs(
+            DisplayId displayId) const = 0;
+
+    virtual std::shared_ptr<const HWC2::Display::Config> getActiveConfig(
+            DisplayId displayId) const = 0;
+    virtual int getActiveConfigIndex(DisplayId displayId) const = 0;
+
+    virtual std::vector<ui::ColorMode> getColorModes(DisplayId displayId) const = 0;
+
+    virtual status_t setActiveColorMode(DisplayId displayId, ui::ColorMode mode,
+                                        ui::RenderIntent renderIntent) = 0;
+
+    virtual bool isUsingVrComposer() const = 0;
+
+    // for debugging ----------------------------------------------------------
+    virtual void dump(std::string& out) const = 0;
+
+    virtual Hwc2::Composer* getComposer() const = 0;
+
+    // TODO(b/74619554): Remove special cases for internal/external display.
+    virtual std::optional<hwc2_display_t> getInternalHwcDisplayId() const = 0;
+    virtual std::optional<hwc2_display_t> getExternalHwcDisplayId() const = 0;
+
+    virtual std::optional<DisplayId> toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const = 0;
+    virtual std::optional<hwc2_display_t> fromPhysicalDisplayId(DisplayId displayId) const = 0;
+};
+
+namespace impl {
+
+class HWComposer final : public android::HWComposer {
 public:
     explicit HWComposer(std::unique_ptr<Hwc2::Composer> composer);
 
-    ~HWComposer();
+    ~HWComposer() override;
 
-    void registerCallback(HWC2::ComposerCallback* callback,
-                          int32_t sequenceId);
+    void registerCallback(HWC2::ComposerCallback* callback, int32_t sequenceId) override;
 
     bool getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
-                                      DisplayIdentificationData* outData) const;
+                                      DisplayIdentificationData* outData) const override;
 
-    bool hasCapability(HWC2::Capability capability) const;
+    bool hasCapability(HWC2::Capability capability) const override;
     bool hasDisplayCapability(const std::optional<DisplayId>& displayId,
-                              HWC2::DisplayCapability capability) const;
+                              HWC2::DisplayCapability capability) const override;
 
     // Attempts to allocate a virtual display and returns its ID if created on the HWC device.
     std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height,
-                                                    ui::PixelFormat* format);
+                                                    ui::PixelFormat* format) override;
 
     // Attempts to create a new layer on this display
-    HWC2::Layer* createLayer(DisplayId displayId);
+    HWC2::Layer* createLayer(DisplayId displayId) override;
     // Destroy a previously created layer
-    void destroyLayer(DisplayId displayId, HWC2::Layer* layer);
+    void destroyLayer(DisplayId displayId, HWC2::Layer* layer) override;
 
     // Asks the HAL what it can do
-    status_t prepare(DisplayId displayId, std::vector<CompositionInfo>& compositionData);
+    status_t prepare(DisplayId displayId, std::vector<CompositionInfo>& compositionData) override;
 
     status_t setClientTarget(DisplayId displayId, uint32_t slot, const sp<Fence>& acquireFence,
-                             const sp<GraphicBuffer>& target, ui::Dataspace dataspace);
+                             const sp<GraphicBuffer>& target, ui::Dataspace dataspace) override;
 
     // Present layers to the display and read releaseFences.
-    status_t presentAndGetReleaseFences(DisplayId displayId);
+    status_t presentAndGetReleaseFences(DisplayId displayId) override;
 
     // set power mode
-    status_t setPowerMode(DisplayId displayId, int mode);
+    status_t setPowerMode(DisplayId displayId, int mode) override;
 
     // set active config
-    status_t setActiveConfig(DisplayId displayId, size_t configId);
+    status_t setActiveConfig(DisplayId displayId, size_t configId) override;
 
     // Sets a color transform to be applied to the result of composition
-    status_t setColorTransform(DisplayId displayId, const mat4& transform);
+    status_t setColorTransform(DisplayId displayId, const mat4& transform) override;
 
     // reset state when an external, non-virtual display is disconnected
-    void disconnectDisplay(DisplayId displayId);
+    void disconnectDisplay(DisplayId displayId) override;
 
     // does this display have layers handled by HWC
-    bool hasDeviceComposition(const std::optional<DisplayId>& displayId) const;
+    bool hasDeviceComposition(const std::optional<DisplayId>& displayId) const override;
 
     // does this display have pending request to flip client target
-    bool hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const;
+    bool hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const override;
 
     // does this display have layers handled by GLES
-    bool hasClientComposition(const std::optional<DisplayId>& displayId) const;
+    bool hasClientComposition(const std::optional<DisplayId>& displayId) const override;
 
     // get the present fence received from the last call to present.
-    sp<Fence> getPresentFence(DisplayId displayId) const;
+    sp<Fence> getPresentFence(DisplayId displayId) const override;
 
     // Get last release fence for the given layer
-    sp<Fence> getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const;
+    sp<Fence> getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const override;
 
     // Set the output buffer and acquire fence for a virtual display.
     // Returns INVALID_OPERATION if displayId is not a virtual display.
     status_t setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence,
-                             const sp<GraphicBuffer>& buffer);
+                             const sp<GraphicBuffer>& buffer) override;
 
     // After SurfaceFlinger has retrieved the release fences for all the frames,
     // it can call this to clear the shared pointers in the release fence map
-    void clearReleaseFences(DisplayId displayId);
+    void clearReleaseFences(DisplayId displayId) override;
 
     // Fetches the HDR capabilities of the given display
-    status_t getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities);
+    status_t getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) override;
 
-    int32_t getSupportedPerFrameMetadata(DisplayId displayId) const;
+    int32_t getSupportedPerFrameMetadata(DisplayId displayId) const override;
 
     // Returns the available RenderIntent of the given display.
     std::vector<ui::RenderIntent> getRenderIntents(DisplayId displayId,
-                                                   ui::ColorMode colorMode) const;
+                                                   ui::ColorMode colorMode) const override;
 
-    mat4 getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace);
+    mat4 getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) override;
 
     // Returns the attributes of the color sampling engine.
     status_t getDisplayedContentSamplingAttributes(DisplayId displayId, ui::PixelFormat* outFormat,
                                                    ui::Dataspace* outDataspace,
-                                                   uint8_t* outComponentMask);
+                                                   uint8_t* outComponentMask) override;
     status_t setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled,
-                                              uint8_t componentMask, uint64_t maxFrames);
+                                              uint8_t componentMask, uint64_t maxFrames) override;
     status_t getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames, uint64_t timestamp,
-                                       DisplayedFrameStats* outStats);
+                                       DisplayedFrameStats* outStats) override;
 
     // Events handling ---------------------------------------------------------
 
     // Returns stable display ID (and display name on connection of new or previously disconnected
     // display), or std::nullopt if hotplug event was ignored.
     std::optional<DisplayIdentificationInfo> onHotplug(hwc2_display_t hwcDisplayId,
-                                                       HWC2::Connection connection);
+                                                       HWC2::Connection connection) override;
 
-    bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp);
-    void setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled);
+    bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) override;
+    void setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled) override;
 
-    nsecs_t getRefreshTimestamp(DisplayId displayId) const;
-    bool isConnected(DisplayId displayId) const;
+    nsecs_t getRefreshTimestamp(DisplayId displayId) const override;
+    bool isConnected(DisplayId displayId) const override;
 
     // Non-const because it can update configMap inside of mDisplayData
-    std::vector<std::shared_ptr<const HWC2::Display::Config>> getConfigs(DisplayId displayId) const;
+    std::vector<std::shared_ptr<const HWC2::Display::Config>> getConfigs(
+            DisplayId displayId) const override;
 
-    std::shared_ptr<const HWC2::Display::Config> getActiveConfig(DisplayId displayId) const;
-    int getActiveConfigIndex(DisplayId displayId) const;
+    std::shared_ptr<const HWC2::Display::Config> getActiveConfig(
+            DisplayId displayId) const override;
+    int getActiveConfigIndex(DisplayId displayId) const override;
 
-    std::vector<ui::ColorMode> getColorModes(DisplayId displayId) const;
+    std::vector<ui::ColorMode> getColorModes(DisplayId displayId) const override;
 
     status_t setActiveColorMode(DisplayId displayId, ui::ColorMode mode,
-                                ui::RenderIntent renderIntent);
+                                ui::RenderIntent renderIntent) override;
 
-    bool isUsingVrComposer() const;
+    bool isUsingVrComposer() const override;
 
     // for debugging ----------------------------------------------------------
-    void dump(std::string& out) const;
+    void dump(std::string& out) const override;
 
-    Hwc2::Composer* getComposer() const { return mHwcDevice->getComposer(); }
+    Hwc2::Composer* getComposer() const override { return mHwcDevice->getComposer(); }
 
     // TODO(b/74619554): Remove special cases for internal/external display.
-    std::optional<hwc2_display_t> getInternalHwcDisplayId() const { return mInternalHwcDisplayId; }
-    std::optional<hwc2_display_t> getExternalHwcDisplayId() const { return mExternalHwcDisplayId; }
+    std::optional<hwc2_display_t> getInternalHwcDisplayId() const override {
+        return mInternalHwcDisplayId;
+    }
+    std::optional<hwc2_display_t> getExternalHwcDisplayId() const override {
+        return mExternalHwcDisplayId;
+    }
 
-    std::optional<DisplayId> toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const;
-    std::optional<hwc2_display_t> fromPhysicalDisplayId(DisplayId displayId) const;
+    std::optional<DisplayId> toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const override;
+    std::optional<hwc2_display_t> fromPhysicalDisplayId(DisplayId displayId) const override;
 
 private:
     // For unit tests
@@ -223,6 +362,7 @@
     uint32_t mRemainingHwcVirtualDisplays{mHwcDevice->getMaxVirtualDisplayCount()};
 };
 
+} // namespace impl
 } // namespace android
 
 #endif // ANDROID_SF_HWCOMPOSER_H
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index f4b3cdd..ee49610 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -83,35 +83,35 @@
 
     mTransactionName = String8("TX - ") + mName;
 
-    mState.current.active_legacy.w = args.w;
-    mState.current.active_legacy.h = args.h;
-    mState.current.flags = layerFlags;
-    mState.current.active_legacy.transform.set(0, 0);
-    mState.current.crop_legacy.makeInvalid();
-    mState.current.requestedCrop_legacy = mState.current.crop_legacy;
-    mState.current.z = 0;
-    mState.current.color.a = 1.0f;
-    mState.current.layerStack = 0;
-    mState.current.sequence = 0;
-    mState.current.requested_legacy = mState.current.active_legacy;
-    mState.current.appId = 0;
-    mState.current.type = 0;
-    mState.current.active.w = UINT32_MAX;
-    mState.current.active.h = UINT32_MAX;
-    mState.current.active.transform.set(0, 0);
-    mState.current.transform = 0;
-    mState.current.transformToDisplayInverse = false;
-    mState.current.crop.makeInvalid();
-    mState.current.acquireFence = new Fence(-1);
-    mState.current.dataspace = ui::Dataspace::UNKNOWN;
-    mState.current.hdrMetadata.validTypes = 0;
-    mState.current.surfaceDamageRegion.clear();
-    mState.current.cornerRadius = 0.0f;
-    mState.current.api = -1;
-    mState.current.hasColorTransform = false;
+    mCurrentState.active_legacy.w = args.w;
+    mCurrentState.active_legacy.h = args.h;
+    mCurrentState.flags = layerFlags;
+    mCurrentState.active_legacy.transform.set(0, 0);
+    mCurrentState.crop_legacy.makeInvalid();
+    mCurrentState.requestedCrop_legacy = mCurrentState.crop_legacy;
+    mCurrentState.z = 0;
+    mCurrentState.color.a = 1.0f;
+    mCurrentState.layerStack = 0;
+    mCurrentState.sequence = 0;
+    mCurrentState.requested_legacy = mCurrentState.active_legacy;
+    mCurrentState.appId = 0;
+    mCurrentState.type = 0;
+    mCurrentState.active.w = UINT32_MAX;
+    mCurrentState.active.h = UINT32_MAX;
+    mCurrentState.active.transform.set(0, 0);
+    mCurrentState.transform = 0;
+    mCurrentState.transformToDisplayInverse = false;
+    mCurrentState.crop.makeInvalid();
+    mCurrentState.acquireFence = new Fence(-1);
+    mCurrentState.dataspace = ui::Dataspace::UNKNOWN;
+    mCurrentState.hdrMetadata.validTypes = 0;
+    mCurrentState.surfaceDamageRegion.clear();
+    mCurrentState.cornerRadius = 0.0f;
+    mCurrentState.api = -1;
+    mCurrentState.hasColorTransform = false;
 
     // drawing state & current state are identical
-    mState.drawing = mState.current;
+    mDrawingState = mCurrentState;
 
     CompositorTiming compositorTiming;
     args.flinger->getCompositorTiming(&compositorTiming);
@@ -148,17 +148,14 @@
 void Layer::onRemovedFromCurrentState() {
     mRemovedFromCurrentState = true;
 
-    {
-        Mutex::Autolock lock(mStateMutex);
-        // the layer is removed from SF mState.current to mLayersPendingRemoval
-        if (mState.current.zOrderRelativeOf != nullptr) {
-            sp<Layer> strongRelative = mState.current.zOrderRelativeOf.promote();
-            if (strongRelative != nullptr) {
-                strongRelative->removeZOrderRelative(this);
-                mFlinger->setTransactionFlags(eTraversalNeeded);
-            }
-            mState.current.zOrderRelativeOf = nullptr;
+    // the layer is removed from SF mCurrentState to mLayersPendingRemoval
+    if (mCurrentState.zOrderRelativeOf != nullptr) {
+        sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
+        if (strongRelative != nullptr) {
+            strongRelative->removeZOrderRelative(this);
+            mFlinger->setTransactionFlags(eTraversalNeeded);
         }
+        mCurrentState.zOrderRelativeOf = nullptr;
     }
 
     // Since we are no longer reachable from CurrentState SurfaceFlinger
@@ -182,6 +179,8 @@
     for (const auto& child : mCurrentChildren) {
         child->onRemovedFromCurrentState();
     }
+
+    mFlinger->markLayerPendingRemovalLocked(this);
 }
 
 void Layer::addToCurrentState() {
@@ -297,32 +296,21 @@
 }
 
 Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const {
-    Mutex::Autolock lock(mStateMutex);
     const State& s(getDrawingState());
     Region transparentRegion = reduceTransparentRegion ? getActiveTransparentRegion(s) : Region();
-    FloatRect bounds = computeBoundsLocked(transparentRegion);
-    ui::Transform t = getTransformLocked();
+    FloatRect bounds = computeBounds(transparentRegion);
+    ui::Transform t = getTransform();
     // Transform to screen space.
     bounds = t.transform(bounds);
     return Rect{bounds};
 }
 
 FloatRect Layer::computeBounds() const {
-    Mutex::Autolock lock(mStateMutex);
-    return computeBoundsLocked();
-}
-
-FloatRect Layer::computeBoundsLocked() const {
     const State& s(getDrawingState());
-    return computeBoundsLocked(getActiveTransparentRegion(s));
+    return computeBounds(getActiveTransparentRegion(s));
 }
 
 FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const {
-    Mutex::Autolock lock(mStateMutex);
-    return computeBoundsLocked(activeTransparentRegion);
-}
-
-FloatRect Layer::computeBoundsLocked(const Region& activeTransparentRegion) const {
     const State& s(getDrawingState());
     Rect bounds = getCroppedBufferSize(s);
     FloatRect floatBounds = bounds.toFloatRect();
@@ -375,7 +363,6 @@
         // child bounds as well.
         ui::Transform t = s.active_legacy.transform;
         croppedBounds = t.transform(croppedBounds);
-        Mutex::Autolock lock(p->mStateMutex);
         croppedBounds = p->cropChildBounds(croppedBounds);
         croppedBounds = t.inverse().transform(croppedBounds);
     }
@@ -393,7 +380,7 @@
     return size;
 }
 
-Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& display) const {
+Rect Layer::computeInitialCrop(const Rect& windowBounds) const {
     // the crop is the area of the window that gets cropped, but not
     // scaled in any ways.
     const State& s(getDrawingState());
@@ -403,13 +390,18 @@
     // if there are no window scaling involved, this operation will map to full
     // pixels in the buffer.
 
-    FloatRect activeCropFloat = computeBoundsLocked();
-    ui::Transform t = getTransformLocked();
-    // Transform to screen space.
-    activeCropFloat = t.transform(activeCropFloat);
-    activeCropFloat = activeCropFloat.intersect(display->getViewport().toFloatRect());
-    // Back to layer space to work with the content crop.
-    activeCropFloat = t.inverse().transform(activeCropFloat);
+    FloatRect activeCropFloat = computeBounds();
+
+    // If we have valid window boundaries then we need to crop to the window
+    // boundaries in layer space.
+    if (windowBounds.isValid()) {
+        const ui::Transform t = getTransform();
+        // Transform to screen space.
+        activeCropFloat = t.transform(activeCropFloat);
+        activeCropFloat = activeCropFloat.intersect(windowBounds.toFloatRect());
+        // Back to layer space to work with the content crop.
+        activeCropFloat = t.inverse().transform(activeCropFloat);
+    }
     // This needs to be here as transform.transform(Rect) computes the
     // transformed rect and then takes the bounding box of the result before
     // returning. This means
@@ -439,7 +431,7 @@
     cropCoords[3] = vec2(win.right, win.top);
 }
 
-FloatRect Layer::computeCrop(const sp<const DisplayDevice>& display) const {
+FloatRect Layer::computeCrop(const Rect& windowBounds) const {
     // the content crop is the area of the content that gets scaled to the
     // layer's size. This is in buffer space.
     FloatRect crop = getContentCrop().toFloatRect();
@@ -447,14 +439,14 @@
     // In addition there is a WM-specified crop we pull from our drawing state.
     const State& s(getDrawingState());
 
-    Rect activeCrop = computeInitialCrop(display);
+    Rect activeCrop = computeInitialCrop(windowBounds);
     Rect bufferSize = getBufferSize(s);
 
     // Transform the window crop to match the buffer coordinate system,
     // which means using the inverse of the current transform set on the
     // SurfaceFlingerConsumer.
     uint32_t invTransform = mCurrentTransform;
-    if (getTransformToDisplayInverseLocked()) {
+    if (getTransformToDisplayInverse()) {
         /*
          * the code below applies the primary display's inverse transform to the
          * buffer
@@ -505,7 +497,6 @@
 }
 
 void Layer::setGeometry(const sp<const DisplayDevice>& display, uint32_t z) {
-    Mutex::Autolock lock(mStateMutex);
     const auto displayId = display->getId();
     LOG_ALWAYS_FATAL_IF(!displayId);
     RETURN_IF_NO_HWC_LAYER(*displayId);
@@ -514,7 +505,7 @@
     // enable this layer
     hwcInfo.forceClientComposition = false;
 
-    if (isSecureLocked() && !display->isSecure()) {
+    if (isSecure() && !display->isSecure()) {
         hwcInfo.forceClientComposition = true;
     }
 
@@ -524,7 +515,7 @@
     const State& s(getDrawingState());
     const Rect bufferSize = getBufferSize(s);
     auto blendMode = HWC2::BlendMode::None;
-    if (!isOpaque(s) || getAlphaLocked() != 1.0f) {
+    if (!isOpaque(s) || getAlpha() != 1.0f) {
         blendMode =
                 mPremultipliedAlpha ? HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage;
     }
@@ -539,7 +530,7 @@
     // apply the layer's transform, followed by the display's global transform
     // here we're guaranteed that the layer's transform preserves rects
     Region activeTransparentRegion(getActiveTransparentRegion(s));
-    ui::Transform t = getTransformLocked();
+    ui::Transform t = getTransform();
     Rect activeCrop = getCrop(s);
     if (!activeCrop.isEmpty() && bufferSize.isValid()) {
         activeCrop = t.transform(activeCrop);
@@ -567,7 +558,7 @@
 
     // computeBounds returns a FloatRect to provide more accuracy during the
     // transformation. We then round upon constructing 'frame'.
-    Rect frame{t.transform(computeBoundsLocked(activeTransparentRegion))};
+    Rect frame{t.transform(computeBounds(activeTransparentRegion))};
     if (!frame.intersect(display->getViewport(), &frame)) {
         frame.clear();
     }
@@ -595,7 +586,7 @@
     }
     getBE().compositionInfo.hwc.sourceCrop = sourceCrop;
 
-    float alpha = static_cast<float>(getAlphaLocked());
+    float alpha = static_cast<float>(getAlpha());
     error = hwcLayer->setPlaneAlpha(alpha);
     ALOGE_IF(error != HWC2::Error::None,
              "[%s] Failed to set plane alpha %.3f: "
@@ -612,7 +603,6 @@
     int appId = s.appId;
     sp<Layer> parent = mDrawingParent.promote();
     if (parent.get()) {
-        Mutex::Autolock lock(parent->mStateMutex);
         auto& parentState = parent->getDrawingState();
         if (parentState.type >= 0 || parentState.appId >= 0) {
             type = parentState.type;
@@ -638,7 +628,7 @@
     const ui::Transform bufferOrientation(mCurrentTransform);
     ui::Transform transform(tr * t * bufferOrientation);
 
-    if (getTransformToDisplayInverseLocked()) {
+    if (getTransformToDisplayInverse()) {
         /*
          * the code below applies the primary display's inverse transform to the
          * buffer
@@ -688,7 +678,6 @@
 }
 
 void Layer::updateCursorPosition(const sp<const DisplayDevice>& display) {
-    Mutex::Autolock lock(mStateMutex);
     const auto displayId = display->getId();
     LOG_ALWAYS_FATAL_IF(!displayId);
     if (!hasHwcLayer(*displayId) || getCompositionType(displayId) != HWC2::Composition::Cursor) {
@@ -703,7 +692,7 @@
     Rect win = getCroppedBufferSize(s);
     // Subtract the transparent region and snap to the bounds
     Rect bounds = reduce(win, getActiveTransparentRegion(s));
-    Rect frame(getTransformLocked().transform(bounds));
+    Rect frame(getTransform().transform(bounds));
     frame.intersect(display->getViewport(), &frame);
     auto& displayTransform = display->getTransform();
     auto position = displayTransform.transform(frame);
@@ -733,7 +722,6 @@
 void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue,
                             float alpha) const {
     auto& engine(mFlinger->getRenderEngine());
-    Mutex::Autolock lock(mStateMutex);
     computeGeometry(renderArea, getBE().mMesh, false);
     engine.setupFillWithColor(red, green, blue, alpha);
     engine.drawMesh(getBE().mMesh);
@@ -818,14 +806,14 @@
                             renderengine::Mesh& mesh,
                             bool useIdentityTransform) const {
     const ui::Transform renderAreaTransform(renderArea.getTransform());
-    FloatRect win = computeBoundsLocked();
+    FloatRect win = computeBounds();
 
     vec2 lt = vec2(win.left, win.top);
     vec2 lb = vec2(win.left, win.bottom);
     vec2 rb = vec2(win.right, win.bottom);
     vec2 rt = vec2(win.right, win.top);
 
-    ui::Transform layerTransform = getTransformLocked();
+    ui::Transform layerTransform = getTransform();
     if (!useIdentityTransform) {
         lt = layerTransform.transform(lt);
         lb = layerTransform.transform(lb);
@@ -841,12 +829,7 @@
 }
 
 bool Layer::isSecure() const {
-    Mutex::Autolock lock(mStateMutex);
-    return isSecureLocked();
-}
-
-bool Layer::isSecureLocked() const {
-    const State& s(mState.drawing);
+    const State& s(mDrawingState);
     return (s.flags & layer_state_t::eLayerSecure);
 }
 
@@ -874,13 +857,9 @@
 // ----------------------------------------------------------------------------
 // transaction
 // ----------------------------------------------------------------------------
-void Layer::pushPendingState() {
-    Mutex::Autolock lock(mStateMutex);
-    pushPendingStateLocked();
-}
 
-void Layer::pushPendingStateLocked() {
-    if (!mState.current.modified) {
+void Layer::pushPendingState() {
+    if (!mCurrentState.modified) {
         return;
     }
 
@@ -888,22 +867,22 @@
     // point and send it to the remote layer.
     // We don't allow installing sync points after we are removed from the current state
     // as we won't be able to signal our end.
-    if (mState.current.barrierLayer_legacy != nullptr && !isRemovedFromCurrentState()) {
-        sp<Layer> barrierLayer = mState.current.barrierLayer_legacy.promote();
+    if (mCurrentState.barrierLayer_legacy != nullptr && !isRemovedFromCurrentState()) {
+        sp<Layer> barrierLayer = mCurrentState.barrierLayer_legacy.promote();
         if (barrierLayer == nullptr) {
             ALOGE("[%s] Unable to promote barrier Layer.", mName.string());
             // If we can't promote the layer we are intended to wait on,
             // then it is expired or otherwise invalid. Allow this transaction
             // to be applied as per normal (no synchronization).
-            mState.current.barrierLayer_legacy = nullptr;
+            mCurrentState.barrierLayer_legacy = nullptr;
         } else {
-            auto syncPoint = std::make_shared<SyncPoint>(mState.current.frameNumber_legacy);
+            auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber_legacy);
             if (barrierLayer->addSyncPoint(syncPoint)) {
                 mRemoteSyncPoints.push_back(std::move(syncPoint));
             } else {
                 // We already missed the frame we're supposed to synchronize
                 // on, so go ahead and apply the state update
-                mState.current.barrierLayer_legacy = nullptr;
+                mCurrentState.barrierLayer_legacy = nullptr;
             }
         }
 
@@ -911,21 +890,21 @@
         setTransactionFlags(eTransactionNeeded);
         mFlinger->setTransactionFlags(eTraversalNeeded);
     }
-    mState.pending.push_back(mState.current);
-    ATRACE_INT(mTransactionName.string(), mState.pending.size());
+    mPendingStates.push_back(mCurrentState);
+    ATRACE_INT(mTransactionName.string(), mPendingStates.size());
 }
 
 void Layer::popPendingState(State* stateToCommit) {
-    *stateToCommit = mState.pending[0];
+    *stateToCommit = mPendingStates[0];
 
-    mState.pending.removeAt(0);
-    ATRACE_INT(mTransactionName.string(), mState.pending.size());
+    mPendingStates.removeAt(0);
+    ATRACE_INT(mTransactionName.string(), mPendingStates.size());
 }
 
 bool Layer::applyPendingStates(State* stateToCommit) {
     bool stateUpdateAvailable = false;
-    while (!mState.pending.empty()) {
-        if (mState.pending[0].barrierLayer_legacy != nullptr) {
+    while (!mPendingStates.empty()) {
+        if (mPendingStates[0].barrierLayer_legacy != nullptr) {
             if (mRemoteSyncPoints.empty()) {
                 // If we don't have a sync point for this, apply it anyway. It
                 // will be visually wrong, but it should keep us from getting
@@ -937,7 +916,7 @@
             }
 
             if (mRemoteSyncPoints.front()->getFrameNumber() !=
-                mState.pending[0].frameNumber_legacy) {
+                mPendingStates[0].frameNumber_legacy) {
                 ALOGE("[%s] Unexpected sync point frame number found", mName.string());
 
                 // Signal our end of the sync point and then dispose of it
@@ -965,12 +944,12 @@
 
     // If we still have pending updates, wake SurfaceFlinger back up and point
     // it at this layer so we can process them
-    if (!mState.pending.empty()) {
+    if (!mPendingStates.empty()) {
         setTransactionFlags(eTransactionNeeded);
         mFlinger->setTransactionFlags(eTraversalNeeded);
     }
 
-    mState.current.modified = false;
+    mCurrentState.modified = false;
     return stateUpdateAvailable;
 }
 
@@ -1067,8 +1046,7 @@
         return 0;
     }
 
-    Mutex::Autolock lock(mStateMutex);
-    pushPendingStateLocked();
+    pushPendingState();
     State c = getCurrentState();
     if (!applyPendingStates(&c)) {
         return 0;
@@ -1100,60 +1078,49 @@
         clearSyncPoints();
     }
 
-    if (mState.current.inputInfoChanged) {
+    if (mCurrentState.inputInfoChanged) {
         flags |= eInputInfoChanged;
-        mState.current.inputInfoChanged = false;
+        mCurrentState.inputInfoChanged = false;
     }
 
     // Commit the transaction
     commitTransaction(c);
-    mState.current.callbackHandles = {};
+    mCurrentState.callbackHandles = {};
     return flags;
 }
 
 void Layer::commitTransaction(const State& stateToCommit) {
-    mState.drawing = stateToCommit;
-}
-
-uint32_t Layer::getTransactionFlags() const {
-    Mutex::Autolock lock(mStateMutex);
-    return mState.transactionFlags;
+    mDrawingState = stateToCommit;
 }
 
 uint32_t Layer::getTransactionFlags(uint32_t flags) {
-    Mutex::Autolock lock(mStateMutex);
-    uint32_t and_flags = mState.transactionFlags & flags;
-    mState.transactionFlags &= ~flags;
-    return and_flags;
+    return mTransactionFlags.fetch_and(~flags) & flags;
 }
 
 uint32_t Layer::setTransactionFlags(uint32_t flags) {
-    uint32_t old_flags = mState.transactionFlags;
-    mState.transactionFlags |= flags;
-    return old_flags;
+    return mTransactionFlags.fetch_or(flags);
 }
 
 bool Layer::setPosition(float x, float y, bool immediate) {
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.requested_legacy.transform.tx() == x &&
-        mState.current.requested_legacy.transform.ty() == y)
+    if (mCurrentState.requested_legacy.transform.tx() == x &&
+        mCurrentState.requested_legacy.transform.ty() == y)
         return false;
-    mState.current.sequence++;
+    mCurrentState.sequence++;
 
     // We update the requested and active position simultaneously because
     // we want to apply the position portion of the transform matrix immediately,
     // but still delay scaling when resizing a SCALING_MODE_FREEZE layer.
-    mState.current.requested_legacy.transform.set(x, y);
+    mCurrentState.requested_legacy.transform.set(x, y);
     if (immediate && !mFreezeGeometryUpdates) {
         // Here we directly update the active state
         // unlike other setters, because we store it within
         // the transform, but use different latching rules.
         // b/38182305
-        mState.current.active_legacy.transform.set(x, y);
+        mCurrentState.active_legacy.transform.set(x, y);
     }
     mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
 
-    mState.current.modified = true;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1186,44 +1153,38 @@
 }
 
 bool Layer::setLayer(int32_t z) {
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.z == z && !usingRelativeZLocked(LayerVector::StateSet::Current))
-        return false;
-
-    mState.current.sequence++;
-    mState.current.z = z;
-    mState.current.modified = true;
+    if (mCurrentState.z == z && !usingRelativeZ(LayerVector::StateSet::Current)) return false;
+    mCurrentState.sequence++;
+    mCurrentState.z = z;
+    mCurrentState.modified = true;
 
     // Discard all relative layering.
-    if (mState.current.zOrderRelativeOf != nullptr) {
-        sp<Layer> strongRelative = mState.current.zOrderRelativeOf.promote();
+    if (mCurrentState.zOrderRelativeOf != nullptr) {
+        sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
         if (strongRelative != nullptr) {
             strongRelative->removeZOrderRelative(this);
         }
-        mState.current.zOrderRelativeOf = nullptr;
+        mCurrentState.zOrderRelativeOf = nullptr;
     }
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 void Layer::removeZOrderRelative(const wp<Layer>& relative) {
-    Mutex::Autolock lock(mStateMutex);
-    mState.current.zOrderRelatives.remove(relative);
-    mState.current.sequence++;
-    mState.current.modified = true;
+    mCurrentState.zOrderRelatives.remove(relative);
+    mCurrentState.sequence++;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
 }
 
 void Layer::addZOrderRelative(const wp<Layer>& relative) {
-    Mutex::Autolock lock(mStateMutex);
-    mState.current.zOrderRelatives.add(relative);
-    mState.current.modified = true;
-    mState.current.sequence++;
+    mCurrentState.zOrderRelatives.add(relative);
+    mCurrentState.modified = true;
+    mCurrentState.sequence++;
     setTransactionFlags(eTransactionNeeded);
 }
 
 bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ) {
-    Mutex::Autolock lock(mStateMutex);
     sp<Handle> handle = static_cast<Handle*>(relativeToHandle.get());
     if (handle == nullptr) {
         return false;
@@ -1233,20 +1194,20 @@
         return false;
     }
 
-    if (mState.current.z == relativeZ && usingRelativeZLocked(LayerVector::StateSet::Current) &&
-        mState.current.zOrderRelativeOf == relative) {
+    if (mCurrentState.z == relativeZ && usingRelativeZ(LayerVector::StateSet::Current) &&
+        mCurrentState.zOrderRelativeOf == relative) {
         return false;
     }
 
-    mState.current.sequence++;
-    mState.current.modified = true;
-    mState.current.z = relativeZ;
+    mCurrentState.sequence++;
+    mCurrentState.modified = true;
+    mCurrentState.z = relativeZ;
 
-    auto oldZOrderRelativeOf = mState.current.zOrderRelativeOf.promote();
+    auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote();
     if (oldZOrderRelativeOf != nullptr) {
         oldZOrderRelativeOf->removeZOrderRelative(this);
     }
-    mState.current.zOrderRelativeOf = relative;
+    mCurrentState.zOrderRelativeOf = relative;
     relative->addZOrderRelative(this);
 
     setTransactionFlags(eTransactionNeeded);
@@ -1255,51 +1216,47 @@
 }
 
 bool Layer::setSize(uint32_t w, uint32_t h) {
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.requested_legacy.w == w && mState.current.requested_legacy.h == h)
+    if (mCurrentState.requested_legacy.w == w && mCurrentState.requested_legacy.h == h)
         return false;
-    mState.current.requested_legacy.w = w;
-    mState.current.requested_legacy.h = h;
-    mState.current.modified = true;
+    mCurrentState.requested_legacy.w = w;
+    mCurrentState.requested_legacy.h = h;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
 
     // record the new size, from this point on, when the client request
     // a buffer, it'll get the new size.
-    setDefaultBufferSize(mState.current.requested_legacy.w, mState.current.requested_legacy.h);
+    setDefaultBufferSize(mCurrentState.requested_legacy.w, mCurrentState.requested_legacy.h);
     return true;
 }
 bool Layer::setAlpha(float alpha) {
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.color.a == alpha) return false;
-    mState.current.sequence++;
-    mState.current.color.a = alpha;
-    mState.current.modified = true;
+    if (mCurrentState.color.a == alpha) return false;
+    mCurrentState.sequence++;
+    mCurrentState.color.a = alpha;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setColor(const half3& color) {
-    Mutex::Autolock lock(mStateMutex);
-    if (color.r == mState.current.color.r && color.g == mState.current.color.g &&
-        color.b == mState.current.color.b)
+    if (color.r == mCurrentState.color.r && color.g == mCurrentState.color.g &&
+        color.b == mCurrentState.color.b)
         return false;
 
-    mState.current.sequence++;
-    mState.current.color.r = color.r;
-    mState.current.color.g = color.g;
-    mState.current.color.b = color.b;
-    mState.current.modified = true;
+    mCurrentState.sequence++;
+    mCurrentState.color.r = color.r;
+    mCurrentState.color.g = color.g;
+    mCurrentState.color.b = color.b;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setCornerRadius(float cornerRadius) {
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.cornerRadius == cornerRadius) return false;
+    if (mCurrentState.cornerRadius == cornerRadius) return false;
 
-    mState.current.sequence++;
-    mState.current.cornerRadius = cornerRadius;
-    mState.current.modified = true;
+    mCurrentState.sequence++;
+    mCurrentState.cornerRadius = cornerRadius;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1313,50 +1270,45 @@
         ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER ignored");
         return false;
     }
-    Mutex::Autolock lock(mStateMutex);
-    mState.current.sequence++;
-    mState.current.requested_legacy.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx,
-                                                  matrix.dsdy);
-    mState.current.modified = true;
+    mCurrentState.sequence++;
+    mCurrentState.requested_legacy.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx,
+                                                 matrix.dsdy);
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setTransparentRegionHint(const Region& transparent) {
-    Mutex::Autolock lock(mStateMutex);
-    mState.current.requestedTransparentRegion_legacy = transparent;
-    mState.current.modified = true;
+    mCurrentState.requestedTransparentRegion_legacy = transparent;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 bool Layer::setFlags(uint8_t flags, uint8_t mask) {
-    Mutex::Autolock lock(mStateMutex);
-    const uint32_t newFlags = (mState.current.flags & ~mask) | (flags & mask);
-    if (mState.current.flags == newFlags) return false;
-    mState.current.sequence++;
-    mState.current.flags = newFlags;
-    mState.current.modified = true;
+    const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask);
+    if (mCurrentState.flags == newFlags) return false;
+    mCurrentState.sequence++;
+    mCurrentState.flags = newFlags;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setCrop_legacy(const Rect& crop, bool immediate) {
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.requestedCrop_legacy == crop) return false;
-    mState.current.sequence++;
-    mState.current.requestedCrop_legacy = crop;
+    if (mCurrentState.requestedCrop_legacy == crop) return false;
+    mCurrentState.sequence++;
+    mCurrentState.requestedCrop_legacy = crop;
     if (immediate && !mFreezeGeometryUpdates) {
-        mState.current.crop_legacy = crop;
+        mCurrentState.crop_legacy = crop;
     }
     mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
 
-    mState.current.modified = true;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 bool Layer::setOverrideScalingMode(int32_t scalingMode) {
-    Mutex::Autolock lock(mStateMutex);
     if (scalingMode == mOverrideScalingMode) return false;
     mOverrideScalingMode = scalingMode;
     setTransactionFlags(eTransactionNeeded);
@@ -1364,29 +1316,22 @@
 }
 
 void Layer::setInfo(int32_t type, int32_t appId) {
-    Mutex::Autolock lock(mStateMutex);
-    mState.current.appId = appId;
-    mState.current.type = type;
-    mState.current.modified = true;
+    mCurrentState.appId = appId;
+    mCurrentState.type = type;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
 }
 
 bool Layer::setLayerStack(uint32_t layerStack) {
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.layerStack == layerStack) return false;
-    mState.current.sequence++;
-    mState.current.layerStack = layerStack;
-    mState.current.modified = true;
+    if (mCurrentState.layerStack == layerStack) return false;
+    mCurrentState.sequence++;
+    mCurrentState.layerStack = layerStack;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 uint32_t Layer::getLayerStack() const {
-    Mutex::Autolock lock(mStateMutex);
-    return getLayerStackLocked();
-}
-
-uint32_t Layer::getLayerStackLocked() const {
     auto p = mDrawingParent.promote();
     if (p == nullptr) {
         return getDrawingState().layerStack;
@@ -1395,16 +1340,15 @@
 }
 
 void Layer::deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber) {
-    Mutex::Autolock lock(mStateMutex);
-    mState.current.barrierLayer_legacy = barrierLayer;
-    mState.current.frameNumber_legacy = frameNumber;
+    mCurrentState.barrierLayer_legacy = barrierLayer;
+    mCurrentState.frameNumber_legacy = frameNumber;
     // We don't set eTransactionNeeded, because just receiving a deferral
     // request without any other state updates shouldn't actually induce a delay
-    mState.current.modified = true;
-    pushPendingStateLocked();
-    mState.current.barrierLayer_legacy = nullptr;
-    mState.current.frameNumber_legacy = 0;
-    mState.current.modified = false;
+    mCurrentState.modified = true;
+    pushPendingState();
+    mCurrentState.barrierLayer_legacy = nullptr;
+    mCurrentState.frameNumber_legacy = 0;
+    mCurrentState.modified = false;
 }
 
 void Layer::deferTransactionUntil_legacy(const sp<IBinder>& barrierHandle, uint64_t frameNumber) {
@@ -1417,8 +1361,7 @@
 // ----------------------------------------------------------------------------
 
 bool Layer::isHiddenByPolicy() const {
-    Mutex::Autolock lock(mStateMutex);
-    const State& s(mState.drawing);
+    const State& s(mDrawingState);
     const auto& parent = mDrawingParent.promote();
     if (parent != nullptr && parent->isHiddenByPolicy()) {
         return true;
@@ -1463,7 +1406,6 @@
 
 // TODO(marissaw): add new layer state info to layer debugging
 LayerDebugInfo Layer::getLayerDebugInfo() const {
-    Mutex::Autolock lock(mStateMutex);
     LayerDebugInfo info;
     const State& ds = getDrawingState();
     info.mName = getName();
@@ -1473,7 +1415,7 @@
     info.mTransparentRegion = ds.activeTransparentRegion_legacy;
     info.mVisibleRegion = visibleRegion;
     info.mSurfaceDamageRegion = surfaceDamageRegion;
-    info.mLayerStack = getLayerStackLocked();
+    info.mLayerStack = getLayerStack();
     info.mX = ds.active_legacy.transform.tx();
     info.mY = ds.active_legacy.transform.ty();
     info.mZ = ds.z;
@@ -1509,13 +1451,6 @@
     return info;
 }
 
-std::tuple<uint32_t, int32_t> Layer::getLayerStackAndZ(StateSet stateSet) {
-    Mutex::Autolock lock(mStateMutex);
-    const State& state = (stateSet == StateSet::Current) ? mState.current : mState.drawing;
-
-    return {state.layerStack, state.z};
-}
-
 void Layer::miniDumpHeader(std::string& result) {
     result.append("-------------------------------");
     result.append("-------------------------------");
@@ -1532,7 +1467,6 @@
 }
 
 void Layer::miniDump(std::string& result, DisplayId displayId) const {
-    Mutex::Autolock lock(mStateMutex);
     if (!hasHwcLayer(displayId)) {
         return;
     }
@@ -1644,6 +1578,7 @@
 
 ssize_t Layer::removeChild(const sp<Layer>& layer) {
     layer->setParent(nullptr);
+
     return mCurrentChildren.remove(layer);
 }
 
@@ -1661,16 +1596,10 @@
     }
 
     if (attachChildren()) {
-        Mutex::Autolock lock(mStateMutex);
         setTransactionFlags(eTransactionNeeded);
     }
     for (const sp<Layer>& child : mCurrentChildren) {
         newParent->addChild(child);
-
-        sp<Client> client(child->mClientRef.promote());
-        if (client != nullptr) {
-            client->updateParent(newParent);
-        }
     }
     mCurrentChildren.clear();
 
@@ -1684,14 +1613,14 @@
 }
 
 bool Layer::reparent(const sp<IBinder>& newParentHandle) {
-    if (newParentHandle == nullptr) {
-        return false;
-    }
+    bool callSetTransactionFlags = false;
 
-    auto handle = static_cast<Handle*>(newParentHandle.get());
-    sp<Layer> newParent = handle->owner.promote();
-    if (newParent == nullptr) {
-        ALOGE("Unable to promote Layer handle");
+    // While layers are detached, we allow most operations
+    // and simply halt performing the actual transaction. However
+    // for reparent != null we would enter the mRemovedFromCurrentState
+    // state, regardless of whether doTransaction was called, and
+    // so we need to prevent the update here.
+    if (mLayerDetached && newParentHandle == nullptr) {
         return false;
     }
 
@@ -1699,25 +1628,31 @@
     if (parent != nullptr) {
         parent->removeChild(this);
     }
-    newParent->addChild(this);
 
-    if (!newParent->isRemovedFromCurrentState()) {
-        addToCurrentState();
+    if (newParentHandle != nullptr) {
+        auto handle = static_cast<Handle*>(newParentHandle.get());
+        sp<Layer> newParent = handle->owner.promote();
+        if (newParent == nullptr) {
+            ALOGE("Unable to promote Layer handle");
+            return false;
+        }
+
+        newParent->addChild(this);
+        if (!newParent->isRemovedFromCurrentState()) {
+            addToCurrentState();
+        } else {
+            onRemovedFromCurrentState();
+        }
+
+        if (mLayerDetached) {
+            mLayerDetached = false;
+            callSetTransactionFlags = true;
+        }
+    } else {
+        onRemovedFromCurrentState();
     }
 
-    sp<Client> client(mClientRef.promote());
-    sp<Client> newParentClient(newParent->mClientRef.promote());
-
-    if (client != newParentClient) {
-        client->updateParent(newParent);
-    }
-
-    Mutex::Autolock lock(mStateMutex);
-    if (mLayerDetached) {
-        mLayerDetached = false;
-        setTransactionFlags(eTransactionNeeded);
-    }
-    if (attachChildren()) {
+    if (callSetTransactionFlags || attachChildren()) {
         setTransactionFlags(eTransactionNeeded);
     }
     return true;
@@ -1756,24 +1691,18 @@
 bool Layer::setColorTransform(const mat4& matrix) {
     static const mat4 identityMatrix = mat4();
 
-    Mutex::Autolock lock(mStateMutex);
-    if (mState.current.colorTransform == matrix) {
+    if (mCurrentState.colorTransform == matrix) {
         return false;
     }
-    ++mState.current.sequence;
-    mState.current.colorTransform = matrix;
-    mState.current.hasColorTransform = matrix != identityMatrix;
-    mState.current.modified = true;
+    ++mCurrentState.sequence;
+    mCurrentState.colorTransform = matrix;
+    mCurrentState.hasColorTransform = matrix != identityMatrix;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
 mat4 Layer::getColorTransform() const {
-    Mutex::Autolock lock(mStateMutex);
-    return getColorTransformLocked();
-}
-
-mat4 Layer::getColorTransformLocked() const {
     mat4 colorTransform = mat4(getDrawingState().colorTransform);
     if (sp<Layer> parent = mDrawingParent.promote(); parent != nullptr) {
         colorTransform = parent->getColorTransform() * colorTransform;
@@ -1782,7 +1711,6 @@
 }
 
 bool Layer::hasColorTransform() const {
-    Mutex::Autolock lock(mStateMutex);
     bool hasColorTransform = getDrawingState().hasColorTransform;
     if (sp<Layer> parent = mDrawingParent.promote(); parent != nullptr) {
         hasColorTransform = hasColorTransform || parent->hasColorTransform();
@@ -1813,18 +1741,12 @@
 }
 
 int32_t Layer::getZ() const {
-    Mutex::Autolock lock(mStateMutex);
-    return mState.drawing.z;
+    return mDrawingState.z;
 }
 
 bool Layer::usingRelativeZ(LayerVector::StateSet stateSet) {
-    Mutex::Autolock lock(mStateMutex);
-    return usingRelativeZLocked(stateSet);
-}
-
-bool Layer::usingRelativeZLocked(LayerVector::StateSet stateSet) {
     const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
-    const State& state = useDrawing ? mState.drawing : mState.current;
+    const State& state = useDrawing ? mDrawingState : mCurrentState;
     return state.zOrderRelativeOf != nullptr;
 }
 
@@ -1834,7 +1756,7 @@
                         "makeTraversalList received invalid stateSet");
     const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
     const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
-    const State& state = useDrawing ? mState.drawing : mState.current;
+    const State& state = useDrawing ? mDrawingState : mCurrentState;
 
     if (state.zOrderRelatives.size() == 0) {
         *outSkipRelativeZUsers = true;
@@ -1850,7 +1772,7 @@
     }
 
     for (const sp<Layer>& child : children) {
-        const State& childState = useDrawing ? child->mState.drawing : child->mState.current;
+        const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState;
         if (childState.zOrderRelativeOf != nullptr) {
             continue;
         }
@@ -1889,6 +1811,7 @@
     visitor(this);
     for (; i < list.size(); i++) {
         const auto& relative = list[i];
+
         if (skipRelativeZUsers && relative->usingRelativeZ(stateSet)) {
             continue;
         }
@@ -1936,7 +1859,7 @@
                         "makeTraversalList received invalid stateSet");
     const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
     const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
-    const State& state = useDrawing ? mState.drawing : mState.current;
+    const State& state = useDrawing ? mDrawingState : mCurrentState;
 
     LayerVector traverse(stateSet);
     for (const wp<Layer>& weakRelative : state.zOrderRelatives) {
@@ -1949,7 +1872,7 @@
     }
 
     for (const sp<Layer>& child : children) {
-        const State& childState = useDrawing ? child->mState.drawing : child->mState.current;
+        const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState;
         // If a layer has a relativeOf layer, only ignore if the layer it's relative to is a
         // descendent of the top most parent of the tree. If it's not a descendent, then just add
         // the child here since it won't be added later as a relative.
@@ -2006,16 +1929,10 @@
 }
 
 ui::Transform Layer::getTransform() const {
-    Mutex::Autolock lock(mStateMutex);
-    return getTransformLocked();
-}
-
-ui::Transform Layer::getTransformLocked() const {
     ui::Transform t;
     const auto& p = mDrawingParent.promote();
     if (p != nullptr) {
-        Mutex::Autolock lock(p->mStateMutex);
-        t = p->getTransformLocked();
+        t = p->getTransform();
 
         // If the parent is not using NATIVE_WINDOW_SCALING_MODE_FREEZE (e.g.
         // it isFixedSize) then there may be additional scaling not accounted
@@ -2043,27 +1960,18 @@
 }
 
 half Layer::getAlpha() const {
-    Mutex::Autolock lock(mStateMutex);
-    return getAlphaLocked();
-}
-
-half Layer::getAlphaLocked() const {
     const auto& p = mDrawingParent.promote();
+
     half parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0_hf;
     return parentAlpha * getDrawingState().color.a;
 }
 
 half4 Layer::getColor() const {
     const half4 color(getDrawingState().color);
-    return half4(color.r, color.g, color.b, getAlphaLocked());
+    return half4(color.r, color.g, color.b, getAlpha());
 }
 
 Layer::RoundedCornerState Layer::getRoundedCornerState() const {
-    Mutex::Autolock lock(mStateMutex);
-    return getRoundedCornerStateLocked();
-}
-
-Layer::RoundedCornerState Layer::getRoundedCornerStateLocked() const {
     const auto& p = mDrawingParent.promote();
     if (p != nullptr) {
         RoundedCornerState parentState = p->getRoundedCornerState();
@@ -2080,7 +1988,7 @@
         }
     }
     const float radius = getDrawingState().cornerRadius;
-    return radius > 0 ? RoundedCornerState(computeBoundsLocked(), radius) : RoundedCornerState();
+    return radius > 0 ? RoundedCornerState(computeBounds(), radius) : RoundedCornerState();
 }
 
 void Layer::commitChildList() {
@@ -2093,21 +2001,19 @@
 }
 
 void Layer::setInputInfo(const InputWindowInfo& info) {
-    Mutex::Autolock lock(mStateMutex);
-    mState.current.inputInfo = info;
-    mState.current.modified = true;
-    mState.current.inputInfoChanged = true;
+    mCurrentState.inputInfo = info;
+    mCurrentState.modified = true;
+    mCurrentState.inputInfoChanged = true;
     setTransactionFlags(eTransactionNeeded);
 }
 
 void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) {
-    Mutex::Autolock lock(mStateMutex);
     const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
     const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
-    const State& state = useDrawing ? mState.drawing : mState.current;
+    const State& state = useDrawing ? mDrawingState : mCurrentState;
 
     ui::Transform requestedTransform = state.active_legacy.transform;
-    ui::Transform transform = getTransformLocked();
+    ui::Transform transform = getTransform();
 
     layerInfo->set_id(sequence);
     layerInfo->set_name(getName().c_str());
@@ -2129,7 +2035,7 @@
     LayerProtoHelper::writeToProto(visibleRegion, layerInfo->mutable_visible_region());
     LayerProtoHelper::writeToProto(surfaceDamageRegion, layerInfo->mutable_damage_region());
 
-    layerInfo->set_layer_stack(getLayerStackLocked());
+    layerInfo->set_layer_stack(getLayerStack());
     layerInfo->set_z(state.z);
 
     PositionProto* position = layerInfo->mutable_position();
@@ -2145,7 +2051,7 @@
     size->set_h(state.active_legacy.h);
 
     LayerProtoHelper::writeToProto(state.crop_legacy, layerInfo->mutable_crop());
-    layerInfo->set_corner_radius(getRoundedCornerStateLocked().radius);
+    layerInfo->set_corner_radius(getRoundedCornerState().radius);
 
     layerInfo->set_is_opaque(isOpaque(state));
     layerInfo->set_invalidate(contentDirty);
@@ -2186,7 +2092,7 @@
     layerInfo->set_curr_frame(mCurrentFrameNumber);
     layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
 
-    for (const auto& pendingState : mState.pending) {
+    for (const auto& pendingState : mPendingStates) {
         auto barrierLayer = pendingState.barrierLayer_legacy.promote();
         if (barrierLayer != nullptr) {
             BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer();
@@ -2230,25 +2136,19 @@
 }
 
 InputWindowInfo Layer::fillInputInfo(const Rect& screenBounds) {
-    InputWindowInfo info;
-    ui::Transform t;
-    Rect layerBounds;
-    {
-        Mutex::Autolock lock(mStateMutex);
-        info = mState.drawing.inputInfo;
-        t = getTransformLocked();
-        const float xScale = t.sx();
-        const float yScale = t.sy();
-        if (xScale != 1.0f || yScale != 1.0f) {
-            info.windowXScale *= 1.0f / xScale;
-            info.windowYScale *= 1.0f / yScale;
-            info.touchableRegion.scaleSelf(xScale, yScale);
-        }
+    InputWindowInfo info = mDrawingState.inputInfo;
 
-        // Transform layer size to screen space and inset it by surface insets.
-        layerBounds = getCroppedBufferSize(getDrawingState());
+    ui::Transform t = getTransform();
+    const float xScale = t.sx();
+    const float yScale = t.sy();
+    if (xScale != 1.0f || yScale != 1.0f) {
+        info.windowXScale *= 1.0f / xScale;
+        info.windowYScale *= 1.0f / yScale;
+        info.touchableRegion.scaleSelf(xScale, yScale);
     }
 
+    // Transform layer size to screen space and inset it by surface insets.
+    Rect layerBounds = getCroppedBufferSize(getDrawingState());
     layerBounds = t.transform(layerBounds);
     layerBounds.inset(info.surfaceInset, info.surfaceInset, info.surfaceInset, info.surfaceInset);
 
@@ -2271,8 +2171,7 @@
 }
 
 bool Layer::hasInput() const {
-    Mutex::Autolock lock(mStateMutex);
-    return mState.drawing.inputInfo.token != nullptr;
+    return mDrawingState.inputInfo.token != nullptr;
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index fb75e4c..7bc7a82 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -55,7 +55,6 @@
 #include "RenderArea.h"
 
 using namespace android::surfaceflinger;
-using StateSet = android::LayerVector::StateSet;
 
 namespace android {
 
@@ -240,7 +239,7 @@
     // also the rendered size of the layer prior to any transformations. Parent
     // or local matrix transformations will not affect the size of the buffer,
     // but may affect it's on-screen size or clipping.
-    virtual bool setSize(uint32_t w, uint32_t h) EXCLUDES(mStateMutex);
+    virtual bool setSize(uint32_t w, uint32_t h);
     // Set a 2x2 transformation matrix on the layer. This transform
     // will be applied after parent transforms, but before any final
     // producer specified transform.
@@ -255,76 +254,58 @@
 
     // setPosition operates in parent buffer space (pre parent-transform) or display
     // space for top-level layers.
-    virtual bool setPosition(float x, float y, bool immediate) EXCLUDES(mStateMutex);
+    virtual bool setPosition(float x, float y, bool immediate);
     // Buffer space
-    virtual bool setCrop_legacy(const Rect& crop, bool immediate) EXCLUDES(mStateMutex);
+    virtual bool setCrop_legacy(const Rect& crop, bool immediate);
 
     // TODO(b/38182121): Could we eliminate the various latching modes by
     // using the layer hierarchy?
     // -----------------------------------------------------------------------
-    virtual bool setLayer(int32_t z) EXCLUDES(mStateMutex);
-    virtual bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ)
-            EXCLUDES(mStateMutex);
+    virtual bool setLayer(int32_t z);
+    virtual bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ);
 
-    virtual bool setAlpha(float alpha) EXCLUDES(mStateMutex);
-    virtual bool setColor(const half3& color) EXCLUDES(mStateMutex);
+    virtual bool setAlpha(float alpha);
+    virtual bool setColor(const half3& color);
 
     // Set rounded corner radius for this layer and its children.
     //
     // We only support 1 radius per layer in the hierarchy, where parent layers have precedence.
     // The shape of the rounded corner rectangle is specified by the crop rectangle of the layer
     // from which we inferred the rounded corner radius.
-    virtual bool setCornerRadius(float cornerRadius) EXCLUDES(mStateMutex);
-    virtual bool setTransparentRegionHint(const Region& transparent) EXCLUDES(mStateMutex);
-    virtual bool setFlags(uint8_t flags, uint8_t mask) EXCLUDES(mStateMutex);
-    virtual bool setLayerStack(uint32_t layerStack) EXCLUDES(mStateMutex);
-    virtual uint32_t getLayerStack() const EXCLUDES(mStateMutex);
+    virtual bool setCornerRadius(float cornerRadius);
+    virtual bool setTransparentRegionHint(const Region& transparent);
+    virtual bool setFlags(uint8_t flags, uint8_t mask);
+    virtual bool setLayerStack(uint32_t layerStack);
+    virtual uint32_t getLayerStack() const;
     virtual void deferTransactionUntil_legacy(const sp<IBinder>& barrierHandle,
                                               uint64_t frameNumber);
-    virtual void deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber)
-            EXCLUDES(mStateMutex);
-    virtual bool setOverrideScalingMode(int32_t overrideScalingMode) EXCLUDES(mStateMutex);
-    virtual void setInfo(int32_t type, int32_t appId) EXCLUDES(mStateMutex);
-    virtual bool reparentChildren(const sp<IBinder>& layer) EXCLUDES(mStateMutex);
+    virtual void deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber);
+    virtual bool setOverrideScalingMode(int32_t overrideScalingMode);
+    virtual void setInfo(int32_t type, int32_t appId);
+    virtual bool reparentChildren(const sp<IBinder>& layer);
     virtual void setChildrenDrawingParent(const sp<Layer>& layer);
-    virtual bool reparent(const sp<IBinder>& newParentHandle) EXCLUDES(mStateMutex);
+    virtual bool reparent(const sp<IBinder>& newParentHandle);
     virtual bool detachChildren();
     bool attachChildren();
     bool isLayerDetached() const { return mLayerDetached; }
-    virtual bool setColorTransform(const mat4& matrix) EXCLUDES(mStateMutex);
-    mat4 getColorTransform() const EXCLUDES(mStateMutex);
-    virtual mat4 getColorTransformLocked() const REQUIRES(mStateMutex);
-    virtual bool hasColorTransform() const EXCLUDES(mStateMutex);
-    ;
+    virtual bool setColorTransform(const mat4& matrix);
+    virtual mat4 getColorTransform() const;
+    virtual bool hasColorTransform() const;
 
     // Used only to set BufferStateLayer state
-    virtual bool setTransform(uint32_t /*transform*/) EXCLUDES(mStateMutex) { return false; };
-    virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/)
-            EXCLUDES(mStateMutex) {
-        return false;
-    };
-    virtual bool setCrop(const Rect& /*crop*/) EXCLUDES(mStateMutex) { return false; };
-    virtual bool setFrame(const Rect& /*frame*/) EXCLUDES(mStateMutex) { return false; };
-    virtual bool setBuffer(const sp<GraphicBuffer>& /*buffer*/) EXCLUDES(mStateMutex) {
-        return false;
-    };
-    virtual bool setAcquireFence(const sp<Fence>& /*fence*/) EXCLUDES(mStateMutex) {
-        return false;
-    };
-    virtual bool setDataspace(ui::Dataspace /*dataspace*/) EXCLUDES(mStateMutex) { return false; };
-    virtual bool setHdrMetadata(const HdrMetadata& /*hdrMetadata*/) EXCLUDES(mStateMutex) {
-        return false;
-    };
-    virtual bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/) EXCLUDES(mStateMutex) {
-        return false;
-    };
-    virtual bool setApi(int32_t /*api*/) EXCLUDES(mStateMutex) { return false; };
-    virtual bool setSidebandStream(const sp<NativeHandle>& /*sidebandStream*/)
-            EXCLUDES(mStateMutex) {
-        return false;
-    };
+    virtual bool setTransform(uint32_t /*transform*/) { return false; };
+    virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; };
+    virtual bool setCrop(const Rect& /*crop*/) { return false; };
+    virtual bool setFrame(const Rect& /*frame*/) { return false; };
+    virtual bool setBuffer(const sp<GraphicBuffer>& /*buffer*/) { return false; };
+    virtual bool setAcquireFence(const sp<Fence>& /*fence*/) { return false; };
+    virtual bool setDataspace(ui::Dataspace /*dataspace*/) { return false; };
+    virtual bool setHdrMetadata(const HdrMetadata& /*hdrMetadata*/) { return false; };
+    virtual bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/) { return false; };
+    virtual bool setApi(int32_t /*api*/) { return false; };
+    virtual bool setSidebandStream(const sp<NativeHandle>& /*sidebandStream*/) { return false; };
     virtual bool setTransactionCompletedListeners(
-            const std::vector<sp<CallbackHandle>>& /*handles*/) EXCLUDES(mStateMutex) {
+            const std::vector<sp<CallbackHandle>>& /*handles*/) {
         return false;
     };
 
@@ -343,21 +324,18 @@
     virtual void useSurfaceDamage() {}
     virtual void useEmptyDamage() {}
 
-    uint32_t getTransactionFlags() const EXCLUDES(mStateMutex);
-    uint32_t getTransactionFlags(uint32_t flags) EXCLUDES(mStateMutex);
-    uint32_t setTransactionFlags(uint32_t flags) REQUIRES(mStateMutex);
+    uint32_t getTransactionFlags() const { return mTransactionFlags; }
+    uint32_t getTransactionFlags(uint32_t flags);
+    uint32_t setTransactionFlags(uint32_t flags);
 
-    bool belongsToDisplay(uint32_t layerStack, bool isPrimaryDisplay) const EXCLUDES(mStateMutex) {
+    bool belongsToDisplay(uint32_t layerStack, bool isPrimaryDisplay) const {
         return getLayerStack() == layerStack && (!mPrimaryDisplayOnly || isPrimaryDisplay);
     }
 
     void computeGeometry(const RenderArea& renderArea, renderengine::Mesh& mesh,
-                         bool useIdentityTransform) const REQUIRES(mStateMutex);
-    FloatRect computeBounds(const Region& activeTransparentRegion) const EXCLUDES(mStateMutex);
-    FloatRect computeBoundsLocked(const Region& activeTransparentRegion) const
-            REQUIRES(mStateMutex);
-    FloatRect computeBounds() const EXCLUDES(mStateMutex);
-    FloatRect computeBoundsLocked() const REQUIRES(mStateMutex);
+                         bool useIdentityTransform) const;
+    FloatRect computeBounds(const Region& activeTransparentRegion) const;
+    FloatRect computeBounds() const;
 
     int32_t getSequence() const { return sequence; }
 
@@ -374,21 +352,16 @@
      */
     virtual bool isOpaque(const Layer::State&) const { return false; }
 
-    virtual bool isDrawingOpaque() const EXCLUDES(mStateMutex) {
-        Mutex::Autolock lock(mStateMutex);
-        return isOpaque(mState.drawing);
-    }
-
     /*
      * isSecure - true if this surface is secure, that is if it prevents
      * screenshots or VNC servers.
      */
-    bool isSecure() const EXCLUDES(mStateMutex);
+    bool isSecure() const;
 
     /*
      * isVisible - true if this layer is visible, false otherwise
      */
-    virtual bool isVisible() const EXCLUDES(mStateMutex) = 0;
+    virtual bool isVisible() const = 0;
 
     /*
      * isHiddenByPolicy - true if this layer has been forced invisible.
@@ -396,7 +369,7 @@
      * For example if this layer has no active buffer, it may not be hidden by
      * policy, but it still can not be visible.
      */
-    bool isHiddenByPolicy() const EXCLUDES(mStateMutex);
+    bool isHiddenByPolicy() const;
 
     /*
      * isProtected - true if the layer may contain protected content in the
@@ -417,8 +390,7 @@
     bool isRemovedFromCurrentState() const;
 
     void writeToProto(LayerProto* layerInfo,
-                      LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing)
-            EXCLUDES(mStateMutex);
+                      LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
 
     void writeToProto(LayerProto* layerInfo, DisplayId displayId);
 
@@ -431,32 +403,25 @@
     virtual Region getActiveTransparentRegion(const Layer::State& s) const {
         return s.activeTransparentRegion_legacy;
     }
-
-    virtual Region getDrawingActiveTransparentRegion() const EXCLUDES(mStateMutex) {
-        Mutex::Autolock lock(mStateMutex);
-        return getActiveTransparentRegion(mState.drawing);
-    }
-
     virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; }
 
 protected:
     /*
      * onDraw - draws the surface.
      */
-    virtual void onDraw(const RenderArea& renderArea, const Region& clip, bool useIdentityTransform)
-            EXCLUDES(mStateMutex) = 0;
+    virtual void onDraw(const RenderArea& renderArea, const Region& clip,
+                        bool useIdentityTransform) = 0;
 
 public:
     virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {}
 
     virtual bool isHdrY410() const { return false; }
 
-    void setGeometry(const sp<const DisplayDevice>& display, uint32_t z) EXCLUDES(mStateMutex);
+    void setGeometry(const sp<const DisplayDevice>& display, uint32_t z);
     void forceClientComposition(DisplayId displayId);
     bool getForceClientComposition(DisplayId displayId);
     virtual void setPerFrameData(DisplayId displayId, const ui::Transform& transform,
-                                 const Rect& viewport, int32_t supportedPerFrameMetadata)
-            EXCLUDES(mStateMutex) = 0;
+                                 const Rect& viewport, int32_t supportedPerFrameMetadata) = 0;
 
     // callIntoHwc exists so we can update our local state and call
     // acceptDisplayChanges without unnecessarily updating the device's state
@@ -464,7 +429,7 @@
     HWC2::Composition getCompositionType(const std::optional<DisplayId>& displayId) const;
     void setClearClientTarget(DisplayId displayId, bool clear);
     bool getClearClientTarget(DisplayId displayId) const;
-    void updateCursorPosition(const sp<const DisplayDevice>& display) EXCLUDES(mStateMutex);
+    void updateCursorPosition(const sp<const DisplayDevice>& display);
 
     /*
      * called after page-flip
@@ -487,8 +452,7 @@
     virtual bool onPostComposition(const std::optional<DisplayId>& /*displayId*/,
                                    const std::shared_ptr<FenceTime>& /*glDoneFence*/,
                                    const std::shared_ptr<FenceTime>& /*presentFence*/,
-                                   const CompositorTiming& /*compositorTiming*/)
-            EXCLUDES(mStateMutex) {
+                                   const CompositorTiming& /*compositorTiming*/) {
         return false;
     }
 
@@ -500,14 +464,14 @@
      * draw - performs some global clipping optimizations
      * and calls onDraw().
      */
-    void draw(const RenderArea& renderArea, const Region& clip) EXCLUDES(mStateMutex);
-    void draw(const RenderArea& renderArea, bool useIdentityTransform) EXCLUDES(mStateMutex);
+    void draw(const RenderArea& renderArea, const Region& clip);
+    void draw(const RenderArea& renderArea, bool useIdentityTransform);
 
     /*
      * doTransaction - process the transaction. This is a good place to figure
      * out which attributes of the surface have changed.
      */
-    uint32_t doTransaction(uint32_t transactionFlags) EXCLUDES(mStateMutex);
+    uint32_t doTransaction(uint32_t transactionFlags);
 
     /*
      * setVisibleRegion - called to set the new visible region. This gives
@@ -540,17 +504,17 @@
      * to figure out if the content or size of a surface has changed.
      */
     virtual Region latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/,
-                               const sp<Fence>& /*releaseFence*/) EXCLUDES(mStateMutex) {
+                               const sp<Fence>& /*releaseFence*/) {
         return {};
     }
 
     virtual bool isBufferLatched() const { return false; }
 
     /*
-     * called with SurfaceFlinger mStateLock a binder thread when the layer is
+     * called with the state lock from a binder thread when the layer is
      * removed from the current list to the pending removal list
      */
-    void onRemovedFromCurrentState() EXCLUDES(mStateMutex);
+    void onRemovedFromCurrentState();
 
     /*
      * Called when the layer is added back to the current state list.
@@ -570,7 +534,7 @@
     /*
      * Returns if a frame is ready
      */
-    virtual bool hasReadyFrame() const EXCLUDES(mStateMutex) { return false; }
+    virtual bool hasReadyFrame() const { return false; }
 
     virtual int32_t getQueuedFrameCount() const { return 0; }
 
@@ -599,32 +563,17 @@
     }
 
     // -----------------------------------------------------------------------
-    void clearWithOpenGL(const RenderArea& renderArea) const EXCLUDES(mStateMutex);
+    void clearWithOpenGL(const RenderArea& renderArea) const;
 
-    inline const State& getDrawingState() const REQUIRES(mStateMutex) { return mState.drawing; }
+    inline const State& getDrawingState() const { return mDrawingState; }
+    inline const State& getCurrentState() const { return mCurrentState; }
+    inline State& getCurrentState() { return mCurrentState; }
 
-    inline const State& getCurrentState() const REQUIRES(mStateMutex) { return mState.current; }
-
-    inline State& getCurrentState() REQUIRES(mStateMutex) { return mState.current; }
-
-    std::tuple<uint32_t, int32_t> getLayerStackAndZ(StateSet stateSet) EXCLUDES(mStateMutex);
-    wp<Layer> getZOrderRelativeOf(StateSet stateSet) EXCLUDES(mStateMutex) {
-        Mutex::Autolock lock(mStateMutex);
-        const State& state = (stateSet == StateSet::Current) ? mState.current : mState.drawing;
-
-        return state.zOrderRelativeOf;
-    }
-
-    uint8_t getCurrentFlags() EXCLUDES(mStateMutex) {
-        Mutex::Autolock lock(mStateMutex);
-        return mState.current.flags;
-    }
-
-    LayerDebugInfo getLayerDebugInfo() const EXCLUDES(mStateMutex);
+    LayerDebugInfo getLayerDebugInfo() const;
 
     /* always call base class first */
     static void miniDumpHeader(std::string& result);
-    void miniDump(std::string& result, DisplayId displayId) const EXCLUDES(mStateMutex);
+    void miniDump(std::string& result, DisplayId displayId) const;
     void dumpFrameStats(std::string& result) const;
     void dumpFrameEvents(std::string& result);
     void clearFrameStats();
@@ -639,29 +588,22 @@
     void addAndGetFrameTimestamps(const NewFrameEventsEntry* newEntry,
                                   FrameEventHistoryDelta* outDelta);
 
-    bool getTransformToDisplayInverse() const EXCLUDES(mStateMutex) {
-        Mutex::Autolock lock(mStateMutex);
-        return getTransformToDisplayInverseLocked();
-    }
+    virtual bool getTransformToDisplayInverse() const { return false; }
 
-    virtual bool getTransformToDisplayInverseLocked() const REQUIRES(mStateMutex) { return false; }
-
-    ui::Transform getTransform() const EXCLUDES(mStateMutex);
-    ui::Transform getTransformLocked() const REQUIRES(mStateMutex);
+    ui::Transform getTransform() const;
 
     // Returns the Alpha of the Surface, accounting for the Alpha
     // of parent Surfaces in the hierarchy (alpha's will be multiplied
     // down the hierarchy).
-    half getAlpha() const EXCLUDES(mStateMutex);
-    half4 getColor() const REQUIRES(mStateMutex);
+    half getAlpha() const;
+    half4 getColor() const;
 
     // Returns how rounded corners should be drawn for this layer.
     // This will traverse the hierarchy until it reaches its root, finding topmost rounded
     // corner definition and converting it into current layer's coordinates.
     // As of now, only 1 corner radius per display list is supported. Subsequent ones will be
     // ignored.
-    RoundedCornerState getRoundedCornerState() const EXCLUDES(mStateMutex);
-    RoundedCornerState getRoundedCornerStateLocked() const REQUIRES(mStateMutex);
+    RoundedCornerState getRoundedCornerState() const;
 
     void traverseInReverseZOrder(LayerVector::StateSet stateSet,
                                  const LayerVector::Visitor& visitor);
@@ -681,7 +623,7 @@
     ssize_t removeChild(const sp<Layer>& layer);
     sp<Layer> getParent() const { return mCurrentParent.promote(); }
     bool hasParent() const { return getParent() != nullptr; }
-    Rect computeScreenBounds(bool reduceTransparentRegion = true) const EXCLUDES(mStateMutex);
+    Rect computeScreenBounds(bool reduceTransparentRegion = true) const;
     bool setChildLayer(const sp<Layer>& childLayer, int32_t z);
     bool setChildRelativeLayer(const sp<Layer>& childLayer,
             const sp<IBinder>& relativeToHandle, int32_t relativeZ);
@@ -689,23 +631,14 @@
     // Copy the current list of children to the drawing state. Called by
     // SurfaceFlinger to complete a transaction.
     void commitChildList();
-    int32_t getZ() const EXCLUDES(mStateMutex);
-    void pushPendingState() EXCLUDES(mStateMutex);
-    virtual void pushPendingStateLocked() REQUIRES(mStateMutex);
+    int32_t getZ() const;
+    virtual void pushPendingState();
 
     /**
      * Returns active buffer size in the correct orientation. Buffer size is determined by undoing
      * any buffer transformations. If the layer has no buffer then return INVALID_RECT.
      */
-    virtual Rect getBufferSize(const Layer::State&) const REQUIRES(mStateMutex) {
-        return Rect::INVALID_RECT;
-    }
-
-    virtual Rect getBufferSize(StateSet stateSet) const EXCLUDES(mStateMutex) {
-        Mutex::Autolock lock(mStateMutex);
-        const State& state = (stateSet == StateSet::Current) ? mState.current : mState.drawing;
-        return getBufferSize(state);
-    }
+    virtual Rect getBufferSize(const Layer::State&) const { return Rect::INVALID_RECT; }
 
 protected:
     // constant
@@ -734,17 +667,26 @@
     // For unit tests
     friend class TestableSurfaceFlinger;
 
-    void commitTransaction(const State& stateToCommit) REQUIRES(mStateMutex);
+    void commitTransaction(const State& stateToCommit);
 
     uint32_t getEffectiveUsage(uint32_t usage) const;
 
-    virtual FloatRect computeCrop(const sp<const DisplayDevice>& display) const
-            REQUIRES(mStateMutex);
+    // Computes the crop applied to this layer. windowBounds is the boundary of
+    // layer-stack space, so the cropping rectangle will be clipped to those
+    // bounds in that space. The crop rectangle is returned in buffer space. If
+    // windowBounds is invalid, then it is ignored.
+    virtual FloatRect computeCrop(const Rect& windowBounds) const;
+
+    // See the above method, but pulls the window boundaries from the display.
+    FloatRect computeCrop(const sp<const DisplayDevice>& display) const {
+        return computeCrop(display->getViewport());
+    }
     // Compute the initial crop as specified by parent layers and the
     // SurfaceControl for this layer. Does not include buffer crop from the
     // IGraphicBufferProducer client, as that should not affect child clipping.
     // Returns in screen space.
-    Rect computeInitialCrop(const sp<const DisplayDevice>& display) const REQUIRES(mStateMutex);
+    Rect computeInitialCrop(const Rect& windowBounds) const;
+
     /**
      * Setup rounded corners coordinates of this layer, taking into account the layer bounds and
      * crop coordinates, transforming them into layer space.
@@ -752,13 +694,13 @@
     void setupRoundedCornersCropCoordinates(Rect win, const FloatRect& roundedCornersCrop) const;
 
     // drawing
-    void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b, float alpha) const
-            EXCLUDES(mStateMutex);
+    void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b,
+                         float alpha) const;
     void setParent(const sp<Layer>& layer);
 
     LayerVector makeTraversalList(LayerVector::StateSet stateSet, bool* outSkipRelativeZUsers);
-    void addZOrderRelative(const wp<Layer>& relative) EXCLUDES(mStateMutex);
-    void removeZOrderRelative(const wp<Layer>& relative) EXCLUDES(mStateMutex);
+    void addZOrderRelative(const wp<Layer>& relative);
+    void removeZOrderRelative(const wp<Layer>& relative);
 
     class SyncPoint {
     public:
@@ -794,10 +736,9 @@
     // Returns false if the relevant frame has already been latched
     bool addSyncPoint(const std::shared_ptr<SyncPoint>& point);
 
-    void popPendingState(State* stateToCommit) REQUIRES(mStateMutex);
-    virtual bool applyPendingStates(State* stateToCommit) REQUIRES(mStateMutex);
-    virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit)
-            REQUIRES(mStateMutex);
+    void popPendingState(State* stateToCommit);
+    virtual bool applyPendingStates(State* stateToCommit);
+    virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit);
 
     void clearSyncPoints();
 
@@ -830,15 +771,14 @@
     bool getPremultipledAlpha() const;
 
     bool mPendingHWCDestroy{false};
-    void setInputInfo(const InputWindowInfo& info) EXCLUDES(mStateMutex);
+    void setInputInfo(const InputWindowInfo& info);
 
-    InputWindowInfo fillInputInfo(const Rect& screenBounds) EXCLUDES(mStateMutex);
-    bool hasInput() const EXCLUDES(mStateMutex);
+    InputWindowInfo fillInputInfo(const Rect& screenBounds);
+    bool hasInput() const;
 
 protected:
     // -----------------------------------------------------------------------
-    bool usingRelativeZ(LayerVector::StateSet stateSet) EXCLUDES(mStateMutex);
-    bool usingRelativeZLocked(LayerVector::StateSet stateSet) REQUIRES(mStateMutex);
+    bool usingRelativeZ(LayerVector::StateSet stateSet);
 
     bool mPremultipliedAlpha{true};
     String8 mName;
@@ -846,14 +786,14 @@
 
     bool mPrimaryDisplayOnly = false;
 
+    // these are protected by an external lock
+    State mCurrentState;
+    State mDrawingState;
+    std::atomic<uint32_t> mTransactionFlags{0};
+
     // Accessed from main thread and binder threads
-    mutable Mutex mStateMutex;
-    struct {
-        State current;
-        State drawing;
-        uint32_t transactionFlags{0};
-        Vector<State> pending;
-    } mState GUARDED_BY(mStateMutex);
+    Mutex mPendingStateMutex;
+    Vector<State> mPendingStates;
 
     // Timestamp history for UIAutomation. Thread safe.
     FrameTracker mFrameTracker;
@@ -926,7 +866,7 @@
      * The cropped bounds must be transformed back from parent layer space to child layer space by
      * applying the inverse of the child's transformation.
      */
-    FloatRect cropChildBounds(const FloatRect& childBounds) const REQUIRES(mStateMutex);
+    FloatRect cropChildBounds(const FloatRect& childBounds) const;
 
     /**
      * Returns the cropped buffer size or the layer crop if the layer has no buffer. Return
@@ -934,12 +874,7 @@
      * A layer with an invalid buffer size and no crop is considered to be boundless. The layer
      * bounds are constrained by its parent bounds.
      */
-    Rect getCroppedBufferSize(const Layer::State& s) const REQUIRES(mStateMutex);
-
-    // locked version of public methods
-    bool isSecureLocked() const REQUIRES(mStateMutex);
-    virtual uint32_t getLayerStackLocked() const REQUIRES(mStateMutex);
-    half getAlphaLocked() const REQUIRES(mStateMutex);
+    Rect getCroppedBufferSize(const Layer::State& s) const;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp
index a7db23e..8494524 100644
--- a/services/surfaceflinger/LayerVector.cpp
+++ b/services/surfaceflinger/LayerVector.cpp
@@ -38,12 +38,18 @@
     const auto& l = *reinterpret_cast<const sp<Layer>*>(lhs);
     const auto& r = *reinterpret_cast<const sp<Layer>*>(rhs);
 
-    const auto& [ls, lz] = l->getLayerStackAndZ(mStateSet);
-    const auto& [rs, rz] = r->getLayerStackAndZ(mStateSet);
+    const auto& lState =
+            (mStateSet == StateSet::Current) ? l->getCurrentState() : l->getDrawingState();
+    const auto& rState =
+            (mStateSet == StateSet::Current) ? r->getCurrentState() : r->getDrawingState();
 
+    uint32_t ls = lState.layerStack;
+    uint32_t rs = rState.layerStack;
     if (ls != rs)
         return (ls > rs) ? 1 : -1;
 
+    int32_t lz = lState.z;
+    int32_t rz = rState.z;
     if (lz != rz)
         return (lz > rz) ? 1 : -1;
 
@@ -56,8 +62,9 @@
 void LayerVector::traverseInZOrder(StateSet stateSet, const Visitor& visitor) const {
     for (size_t i = 0; i < size(); i++) {
         const auto& layer = (*this)[i];
-        auto zOrderRelativeOf = layer->getZOrderRelativeOf(stateSet);
-        if (zOrderRelativeOf != nullptr) {
+        auto& state = (stateSet == StateSet::Current) ? layer->getCurrentState()
+                                                      : layer->getDrawingState();
+        if (state.zOrderRelativeOf != nullptr) {
             continue;
         }
         layer->traverseInZOrder(stateSet, visitor);
@@ -67,8 +74,9 @@
 void LayerVector::traverseInReverseZOrder(StateSet stateSet, const Visitor& visitor) const {
     for (auto i = static_cast<int64_t>(size()) - 1; i >= 0; i--) {
         const auto& layer = (*this)[i];
-        auto zOrderRelativeOf = layer->getZOrderRelativeOf(stateSet);
-        if (zOrderRelativeOf != nullptr) {
+        auto& state = (stateSet == StateSet::Current) ? layer->getCurrentState()
+                                                      : layer->getDrawingState();
+        if (state.zOrderRelativeOf != nullptr) {
             continue;
         }
         layer->traverseInReverseZOrder(stateSet, visitor);
diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS
new file mode 100644
index 0000000..dc2b300
--- /dev/null
+++ b/services/surfaceflinger/OWNERS
@@ -0,0 +1,5 @@
+chaviw@google.com
+lpy@google.com
+marissaw@google.com
+racarr@google.com
+stoza@google.com
\ No newline at end of file
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 1683982..bf925b2 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -67,7 +67,13 @@
 }
 
 void EventThreadConnection::requestNextVsync() {
-    mEventThread->requestNextVsync(this);
+    ATRACE_NAME("requestNextVsync");
+    mEventThread->requestNextVsync(this, true);
+}
+
+void EventThreadConnection::requestNextVsyncForHWC() {
+    ATRACE_NAME("requestNextVsyncForHWC");
+    mEventThread->requestNextVsync(this, false);
 }
 
 status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
@@ -184,16 +190,17 @@
     }
 }
 
-void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
-    std::lock_guard<std::mutex> lock(mMutex);
-    if (mResetIdleTimer) {
+void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection, bool reset) {
+    if (mResetIdleTimer && reset) {
+        ATRACE_NAME("resetIdleTimer");
         mResetIdleTimer();
     }
-
     if (mResyncWithRateLimitCallback) {
         mResyncWithRateLimitCallback();
     }
 
+    std::lock_guard<std::mutex> lock(mMutex);
+
     if (connection->count < 0) {
         connection->count = 0;
         mCondition.notify_all();
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 66f54bd..e110488 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -68,6 +68,9 @@
     status_t stealReceiveChannel(gui::BitTube* outChannel) override;
     status_t setVsyncRate(uint32_t count) override;
     void requestNextVsync() override; // asynchronous
+    // Requesting Vsync for HWC does not reset the idle timer, since HWC requires a refresh
+    // in order to update the configs.
+    void requestNextVsyncForHWC();
 
     // count >= 1 : continuous event. count is the vsync rate
     // count == 0 : one-shot event that has not fired
@@ -105,7 +108,9 @@
     virtual status_t registerDisplayEventConnection(
             const sp<EventThreadConnection>& connection) = 0;
     virtual void setVsyncRate(uint32_t count, const sp<EventThreadConnection>& connection) = 0;
-    virtual void requestNextVsync(const sp<EventThreadConnection>& connection) = 0;
+    // Requests the next vsync. If resetIdleTimer is set to true, it resets the idle timer.
+    virtual void requestNextVsync(const sp<EventThreadConnection>& connection,
+                                  bool resetIdleTimer) = 0;
 };
 
 namespace impl {
@@ -129,7 +134,8 @@
 
     status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override;
     void setVsyncRate(uint32_t count, const sp<EventThreadConnection>& connection) override;
-    void requestNextVsync(const sp<EventThreadConnection>& connection) override;
+    void requestNextVsync(const sp<EventThreadConnection>& connection,
+                          bool resetIdleTimer) override;
 
     // called before the screen is turned off from main thread
     void onScreenReleased() override;
@@ -166,6 +172,9 @@
     // Implements VSyncSource::Callback
     void onVSyncEvent(nsecs_t timestamp) override;
 
+    // Acquires mutex and requests next vsync.
+    void requestNextVsyncInternal(const sp<EventThreadConnection>& connection) EXCLUDES(mMutex);
+
     // TODO(b/113612090): Once the Scheduler is complete this pointer will become obsolete.
     VSyncSource* mVSyncSource GUARDED_BY(mMutex) = nullptr;
     std::unique_ptr<VSyncSource> mVSyncSourceUnique GUARDED_BY(mMutex) = nullptr;
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index 36403cc..66f42bb 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -148,6 +148,10 @@
     mEvents->requestNextVsync();
 }
 
+void MessageQueue::invalidateForHWC() {
+    mEvents->requestNextVsyncForHWC();
+}
+
 void MessageQueue::refresh() {
     mHandler->dispatchRefresh();
 }
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h
index 24a3834..0bf00b0 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.h
+++ b/services/surfaceflinger/Scheduler/MessageQueue.h
@@ -91,6 +91,7 @@
     virtual void waitMessage() = 0;
     virtual status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime = 0) = 0;
     virtual void invalidate() = 0;
+    virtual void invalidateForHWC() = 0;
     virtual void refresh() = 0;
 };
 
@@ -134,6 +135,9 @@
 
     // sends INVALIDATE message at next VSYNC
     void invalidate() override;
+
+    // sends INVALIDATE message at next VSYNC, without resetting the idle timer in the Scheduler
+    void invalidateForHWC();
     // sends REFRESH message at next VSYNC
     void refresh() override;
 };
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index c363ba5..fec53af 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -238,6 +238,16 @@
     mLayerHistory.incrementCounter();
 }
 
+void Scheduler::setExpiredIdleTimerCallback(const ExpiredIdleTimerCallback& expiredTimerCallback) {
+    std::lock_guard<std::mutex> lock(mCallbackLock);
+    mExpiredTimerCallback = expiredTimerCallback;
+}
+
+void Scheduler::setResetIdleTimerCallback(const ResetIdleTimerCallback& resetTimerCallback) {
+    std::lock_guard<std::mutex> lock(mCallbackLock);
+    mResetTimerCallback = resetTimerCallback;
+}
+
 void Scheduler::updateFrameSkipping(const int64_t skipCount) {
     ATRACE_INT("FrameSkipCount", skipCount);
     if (mSkipCount != skipCount) {
@@ -314,12 +324,12 @@
     // TODO(b/113612090): This are current numbers from trial and error while running videos
     // from YouTube at 24, 30, and 60 fps.
     if (mean > 14 && mean < 18) {
-        ATRACE_INT("FPS", 60);
+        ATRACE_INT("MediaFPS", 60);
     } else if (mean > 31 && mean < 34) {
-        ATRACE_INT("FPS", 30);
+        ATRACE_INT("MediaFPS", 30);
         return;
     } else if (mean > 39 && mean < 42) {
-        ATRACE_INT("FPS", 24);
+        ATRACE_INT("MediaFPS", 24);
     }
 }
 
@@ -328,13 +338,19 @@
         mIdleTimer->reset();
         ATRACE_INT("ExpiredIdleTimer", 0);
     }
+
+    std::lock_guard<std::mutex> lock(mCallbackLock);
+    if (mResetTimerCallback) {
+        mResetTimerCallback();
+    }
 }
 
 void Scheduler::expiredTimerCallback() {
-    // TODO(b/113612090): Each time a timer expired, we should record the information into
-    // a circular buffer. Once this has happened a given amount (TBD) of times, we can comfortably
-    // say that the device is sitting in idle.
-    ATRACE_INT("ExpiredIdleTimer", 1);
+    std::lock_guard<std::mutex> lock(mCallbackLock);
+    if (mExpiredTimerCallback) {
+        mExpiredTimerCallback();
+        ATRACE_INT("ExpiredIdleTimer", 1);
+    }
 }
 
 } // namespace android
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 9d7dd4d..3538f31 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -36,6 +36,9 @@
 
 class Scheduler {
 public:
+    using ExpiredIdleTimerCallback = std::function<void()>;
+    using ResetIdleTimerCallback = std::function<void()>;
+
     // Enum to indicate whether to start the transaction early, or at vsync time.
     enum class TransactionStart { EARLY, NORMAL };
 
@@ -111,6 +114,10 @@
                                      const std::string layerName);
     // Increments counter in the layer history to indicate that SF has started a new frame.
     void incrementFrameCounter();
+    // Callback that gets invoked once the idle timer expires.
+    void setExpiredIdleTimerCallback(const ExpiredIdleTimerCallback& expiredTimerCallback);
+    // Callback that gets invoked once the idle timer is reset.
+    void setResetIdleTimerCallback(const ResetIdleTimerCallback& resetTimerCallback);
 
 protected:
     virtual std::unique_ptr<EventThread> makeEventThread(
@@ -173,6 +180,10 @@
     // interval, a callback is fired. Set this variable to >0 to use this feature.
     int64_t mSetIdleTimerMs = 0;
     std::unique_ptr<scheduler::IdleTimer> mIdleTimer;
+
+    std::mutex mCallbackLock;
+    ExpiredIdleTimerCallback mExpiredTimerCallback GUARDED_BY(mCallbackLock);
+    ResetIdleTimerCallback mResetTimerCallback GUARDED_BY(mCallbackLock);
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/StartPropertySetThread.h b/services/surfaceflinger/StartPropertySetThread.h
index a64c21b..bbdcde2 100644
--- a/services/surfaceflinger/StartPropertySetThread.h
+++ b/services/surfaceflinger/StartPropertySetThread.h
@@ -33,7 +33,7 @@
 // Any property_set() will block during init stage so need to be offloaded
 // to this thread. see b/63844978.
 public:
-    StartPropertySetThread(bool timestampPropertyValue);
+    explicit StartPropertySetThread(bool timestampPropertyValue);
     status_t Start();
 private:
     virtual bool threadLoop();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4a93be6..9eff3c6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -35,32 +35,30 @@
 #include <binder/IServiceManager.h>
 #include <binder/PermissionCache.h>
 
+#include <compositionengine/CompositionEngine.h>
 #include <dvr/vr_flinger.h>
-
-#include <input/IInputFlinger.h>
-
-#include <ui/ColorSpace.h>
-#include <ui/DebugUtils.h>
-#include <ui/DisplayInfo.h>
-#include <ui/DisplayStatInfo.h>
-
 #include <gui/BufferQueue.h>
 #include <gui/GuiConfig.h>
 #include <gui/IDisplayEventConnection.h>
 #include <gui/IProducerListener.h>
 #include <gui/LayerDebugInfo.h>
 #include <gui/Surface.h>
+#include <input/IInputFlinger.h>
 #include <renderengine/RenderEngine.h>
+#include <ui/ColorSpace.h>
+#include <ui/DebugUtils.h>
+#include <ui/DisplayInfo.h>
+#include <ui/DisplayStatInfo.h>
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/PixelFormat.h>
 #include <ui/UiConfig.h>
-
-#include <utils/misc.h>
-#include <utils/String8.h>
-#include <utils/String16.h>
+#include <utils/CallStack.h>
 #include <utils/StopWatch.h>
+#include <utils/String16.h>
+#include <utils/String8.h>
 #include <utils/Timers.h>
 #include <utils/Trace.h>
+#include <utils/misc.h>
 
 #include <private/android_filesystem_config.h>
 #include <private/gui/SyncFeatures.h>
@@ -238,7 +236,6 @@
 
 SurfaceFlingerBE::SurfaceFlingerBE()
       : mHwcServiceName(getHwcServiceName()),
-        mRenderEngine(nullptr),
         mFrameBuckets(),
         mTotalTime(0),
         mLastSwapTime(0),
@@ -272,7 +269,8 @@
         mHasPoweredOff(false),
         mNumLayers(0),
         mVrFlingerRequestsDisplay(false),
-        mMainThreadId(std::this_thread::get_id()) {}
+        mMainThreadId(std::this_thread::get_id()),
+        mCompositionEngine{getFactory().createCompositionEngine()} {}
 
 SurfaceFlinger::SurfaceFlinger(surfaceflinger::Factory& factory)
       : SurfaceFlinger(factory, SkipInitialization) {
@@ -458,19 +456,6 @@
     return initClient(new Client(this));
 }
 
-sp<ISurfaceComposerClient> SurfaceFlinger::createScopedConnection(
-        const sp<IGraphicBufferProducer>& gbp) {
-    if (authenticateSurfaceTexture(gbp) == false) {
-        return nullptr;
-    }
-    const auto& layer = (static_cast<MonitoredProducer*>(gbp.get()))->getLayer();
-    if (layer == nullptr) {
-        return nullptr;
-    }
-
-   return initClient(new Client(this, layer));
-}
-
 sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName,
         bool secure)
 {
@@ -544,6 +529,18 @@
     return NO_ERROR;
 }
 
+HWComposer& SurfaceFlinger::getHwComposer() const {
+    return mCompositionEngine->getHwComposer();
+}
+
+renderengine::RenderEngine& SurfaceFlinger::getRenderEngine() const {
+    return mCompositionEngine->getRenderEngine();
+}
+
+compositionengine::CompositionEngine& SurfaceFlinger::getCompositionEngine() const {
+    return *mCompositionEngine.get();
+}
+
 void SurfaceFlinger::bootFinished()
 {
     if (mStartPropertySetThread->join() != NO_ERROR) {
@@ -673,15 +670,14 @@
                             renderengine::RenderEngine::USE_HIGH_PRIORITY_CONTEXT : 0);
 
     // TODO(b/77156734): We need to stop casting and use HAL types when possible.
-    getBE().mRenderEngine =
+    mCompositionEngine->setRenderEngine(
             renderengine::RenderEngine::create(static_cast<int32_t>(defaultCompositionPixelFormat),
-                                               renderEngineFeature);
-    LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine");
+                                               renderEngineFeature));
 
     LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
             "Starting with vr flinger active is not currently supported.");
-    getBE().mHwc = getFactory().createHWComposer(getBE().mHwcServiceName);
-    getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId);
+    mCompositionEngine->setHwComposer(getFactory().createHWComposer(getBE().mHwcServiceName));
+    mCompositionEngine->getHwComposer().registerCallback(this, getBE().mComposerSequenceId);
     // Process any initial hotplug and resulting display changes.
     processDisplayHotplugEventsLocked();
     const auto display = getDefaultDisplayDeviceLocked();
@@ -722,7 +718,7 @@
     // set initial conditions (e.g. unblank default device)
     initializeDisplays();
 
-    getBE().mRenderEngine->primeCache();
+    getRenderEngine().primeCache();
 
     // Inform native graphics APIs whether the present timestamp is supported:
 
@@ -734,6 +730,11 @@
         ALOGE("Run StartPropertySetThread failed!");
     }
 
+    if (mUseScheduler) {
+        mScheduler->setExpiredIdleTimerCallback([this]() { setRefreshRateTo(60.f /* fps */); });
+        mScheduler->setResetIdleTimerCallback([this]() { setRefreshRateTo(90.f /* fps */); });
+    }
+
     ALOGV("Done initializing");
 }
 
@@ -762,11 +763,11 @@
 }
 
 size_t SurfaceFlinger::getMaxTextureSize() const {
-    return getBE().mRenderEngine->getMaxTextureSize();
+    return getRenderEngine().getMaxTextureSize();
 }
 
 size_t SurfaceFlinger::getMaxViewportDims() const {
-    return getBE().mRenderEngine->getMaxViewportDims();
+    return getRenderEngine().getMaxViewportDims();
 }
 
 // ----------------------------------------------------------------------------
@@ -939,14 +940,45 @@
     return display->getActiveConfig();
 }
 
-void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& display, int mode) {
+status_t SurfaceFlinger::setActiveConfigAsync(const sp<IBinder>& displayToken, int mode) {
+    ATRACE_NAME("setActiveConfigAsync");
+    postMessageAsync(new LambdaMessage([=] { setActiveConfigInternal(displayToken, mode); }));
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
+    ATRACE_NAME("setActiveConfigSync");
+    postMessageSync(new LambdaMessage([&] { setActiveConfigInternal(displayToken, mode); }));
+    return NO_ERROR;
+}
+
+void SurfaceFlinger::setActiveConfigInternal(const sp<IBinder>& displayToken, int mode) {
+    Vector<DisplayInfo> configs;
+    getDisplayConfigs(displayToken, &configs);
+    if (mode < 0 || mode >= static_cast<int>(configs.size())) {
+        ALOGE("Attempt to set active config %d for display with %zu configs", mode, configs.size());
+        return;
+    }
+
+    const auto display = getDisplayDevice(displayToken);
+    if (!display) {
+        ALOGE("Attempt to set active config %d for invalid display token %p", mode,
+              displayToken.get());
+        return;
+    }
     if (display->isVirtual()) {
-        ALOGE("%s: Invalid operation on virtual display", __FUNCTION__);
+        ALOGW("Attempt to set active config %d for virtual display", mode);
+        return;
+    }
+    int currentDisplayPowerMode = display->getPowerMode();
+    if (currentDisplayPowerMode != HWC_POWER_MODE_NORMAL) {
+        // Don't change active config when in AoD.
         return;
     }
 
     int currentMode = display->getActiveConfig();
     if (mode == currentMode) {
+        // Don't update config if we are already running in the desired mode.
         return;
     }
 
@@ -955,29 +987,9 @@
 
     display->setActiveConfig(mode);
     getHwComposer().setActiveConfig(*displayId, mode);
-}
 
-status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
-    postMessageSync(new LambdaMessage([&] {
-        Vector<DisplayInfo> configs;
-        getDisplayConfigs(displayToken, &configs);
-        if (mode < 0 || mode >= static_cast<int>(configs.size())) {
-            ALOGE("Attempt to set active config %d for display with %zu configs", mode,
-                  configs.size());
-            return;
-        }
-        const auto display = getDisplayDevice(displayToken);
-        if (!display) {
-            ALOGE("Attempt to set active config %d for invalid display token %p", mode,
-                  displayToken.get());
-        } else if (display->isVirtual()) {
-            ALOGW("Attempt to set active config %d for virtual display", mode);
-        } else {
-            setActiveConfigInternal(display, mode);
-        }
-    }));
-
-    return NO_ERROR;
+    ATRACE_INT("ActiveConfigMode", mode);
+    resyncToHardwareVsync(true);
 }
 
 status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& displayToken,
@@ -1387,6 +1399,49 @@
     *compositorTiming = getBE().mCompositorTiming;
 }
 
+void SurfaceFlinger::setRefreshRateTo(float newFps) {
+    const auto displayId = getInternalDisplayId();
+    if (!displayId || mBootStage != BootStage::FINISHED) {
+        return;
+    }
+    // TODO(b/113612090): There should be a message queue flush here. Because this esentially
+    // runs on a mainthread, we cannot call postMessageSync. This can be resolved in a better
+    // manner, once the setActiveConfig is synchronous, and is executed at a known time in a
+    // refresh cycle.
+
+    // Don't do any updating if the current fps is the same as the new one.
+    const auto activeConfig = getHwComposer().getActiveConfig(*displayId);
+    const nsecs_t currentVsyncPeriod = activeConfig->getVsyncPeriod();
+    if (currentVsyncPeriod == 0) {
+        return;
+    }
+    // TODO(b/113612090): Consider having an enum value for correct refresh rates, rather than
+    // floating numbers.
+    const float currentFps = 1e9 / currentVsyncPeriod;
+    if (std::abs(currentFps - newFps) <= 1) {
+        return;
+    }
+
+    auto configs = getHwComposer().getConfigs(*displayId);
+    for (int i = 0; i < configs.size(); i++) {
+        const nsecs_t vsyncPeriod = configs.at(i)->getVsyncPeriod();
+        if (vsyncPeriod == 0) {
+            continue;
+        }
+        const float fps = 1e9 / vsyncPeriod;
+        // TODO(b/113612090): There should be a better way at determining which config
+        // has the right refresh rate.
+        if (std::abs(fps - newFps) <= 1) {
+            const auto display = getBuiltInDisplay(HWC_DISPLAY_PRIMARY);
+            if (!display) return;
+            // This is posted in async function to avoid deadlock when getDisplayDevice
+            // requires mStateLock.
+            setActiveConfigAsync(display, i);
+            ATRACE_INT("FPS", newFps);
+        }
+    }
+}
+
 void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
                                        HWC2::Connection connection) {
     ALOGV("%s(%d, %" PRIu64 ", %s)", __FUNCTION__, sequenceId, hwcDisplayId,
@@ -1418,7 +1473,7 @@
     if (sequenceId != getBE().mComposerSequenceId) {
         return;
     }
-    repaintEverything();
+    repaintEverythingForHWC();
 }
 
 void SurfaceFlinger::setVsyncEnabled(EventThread::DisplayType /*displayType*/, bool enabled) {
@@ -1449,11 +1504,11 @@
     if (!mVrFlinger)
         return;
     bool vrFlingerRequestsDisplay = mVrFlingerRequestsDisplay;
-    if (vrFlingerRequestsDisplay == getBE().mHwc->isUsingVrComposer()) {
+    if (vrFlingerRequestsDisplay == getHwComposer().isUsingVrComposer()) {
         return;
     }
 
-    if (vrFlingerRequestsDisplay && !getBE().mHwc->getComposer()->isRemote()) {
+    if (vrFlingerRequestsDisplay && !getHwComposer().getComposer()->isRemote()) {
         ALOGE("Vr flinger is only supported for remote hardware composer"
               " service connections. Ignoring request to transition to vr"
               " flinger.");
@@ -1476,12 +1531,13 @@
     }
 
     resetDisplayState();
-    getBE().mHwc.reset(); // Delete the current instance before creating the new one
-    getBE().mHwc = getFactory().createHWComposer(
-            vrFlingerRequestsDisplay ? "vr" : getBE().mHwcServiceName);
-    getBE().mHwc->registerCallback(this, ++getBE().mComposerSequenceId);
+    // Delete the current instance before creating the new one
+    mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>());
+    mCompositionEngine->setHwComposer(getFactory().createHWComposer(
+            vrFlingerRequestsDisplay ? "vr" : getBE().mHwcServiceName));
+    getHwComposer().registerCallback(this, ++getBE().mComposerSequenceId);
 
-    LOG_ALWAYS_FATAL_IF(!getBE().mHwc->getComposer()->isRemote(),
+    LOG_ALWAYS_FATAL_IF(!getHwComposer().getComposer()->isRemote(),
                         "Switched to non-remote hardware composer");
 
     if (vrFlingerRequestsDisplay) {
@@ -1504,9 +1560,10 @@
     // The present fences returned from vr_hwc are not an accurate
     // representation of vsync times.
     if (mUseScheduler) {
-        mScheduler->setIgnorePresentFences(getBE().mHwc->isUsingVrComposer() || !hasSyncFramework);
+        mScheduler->setIgnorePresentFences(getHwComposer().isUsingVrComposer() ||
+                                           !hasSyncFramework);
     } else {
-        mPrimaryDispSync->setIgnorePresentFences(getBE().mHwc->isUsingVrComposer() ||
+        mPrimaryDispSync->setIgnorePresentFences(getHwComposer().isUsingVrComposer() ||
                                                  !hasSyncFramework);
     }
 
@@ -1568,11 +1625,23 @@
 
 bool SurfaceFlinger::handleMessageTransaction() {
     uint32_t transactionFlags = peekTransactionFlags();
+
+    // Apply any ready transactions in the queues if there are still transactions that have not been
+    // applied, wake up during the next vsync period and check again
+    bool transactionNeeded = false;
+    if (!flushTransactionQueues()) {
+        transactionNeeded = true;
+    }
+
     if (transactionFlags) {
         handleTransaction(transactionFlags);
-        return true;
     }
-    return false;
+
+    if (transactionNeeded) {
+        setTransactionFlags(eTransactionNeeded);
+    }
+
+    return transactionFlags;
 }
 
 void SurfaceFlinger::handleMessageRefresh() {
@@ -1599,12 +1668,12 @@
 
     mHadClientComposition = false;
     for (const auto& [token, display] : mDisplays) {
-        mHadClientComposition = mHadClientComposition ||
-                getBE().mHwc->hasClientComposition(display->getId());
+        mHadClientComposition =
+                mHadClientComposition || getHwComposer().hasClientComposition(display->getId());
     }
 
     // Setup RenderEngine sync fences if native sync is supported.
-    if (getBE().mRenderEngine->useNativeFenceSync()) {
+    if (getRenderEngine().useNativeFenceSync()) {
         if (mHadClientComposition) {
             base::unique_fd flushFence(getRenderEngine().flush());
             ALOGE_IF(flushFence < 0, "Failed to flush RenderEngine!");
@@ -1867,22 +1936,78 @@
     getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
 }
 
+// debug patch for b/119477596 - add stack guards to catch stack
+// corruptions and disable clang optimizations.
+// The code below is temporary and planned to be removed once stack
+// corruptions are found.
+#pragma clang optimize off
+class StackGuard {
+public:
+    StackGuard(const char* name, const char* func, int line) {
+        guarders.reserve(MIN_CAPACITY);
+        guarders.push_back({this, name, func, line});
+        validate();
+    }
+    ~StackGuard() {
+        for (auto i = guarders.end() - 1; i >= guarders.begin(); --i) {
+            if (i->guard == this) {
+                guarders.erase(i);
+                break;
+            }
+        }
+    }
+
+    static void validate() {
+        for (const auto& guard : guarders) {
+            if (guard.guard->cookie != COOKIE_VALUE) {
+                ALOGE("%s:%d: Stack corruption detected at %s", guard.func, guard.line, guard.name);
+                CallStack stack(LOG_TAG);
+                abort();
+            }
+        }
+    }
+
+private:
+    uint64_t cookie = COOKIE_VALUE;
+    static constexpr uint64_t COOKIE_VALUE = 0xc0febebedeadbeef;
+    static constexpr size_t MIN_CAPACITY = 16;
+
+    struct GuarderElement {
+        StackGuard* guard;
+        const char* name;
+        const char* func;
+        int line;
+    };
+
+    static std::vector<GuarderElement> guarders;
+};
+std::vector<StackGuard::GuarderElement> StackGuard::guarders;
+
+#define DEFINE_STACK_GUARD(__n) StackGuard __n##StackGuard(#__n, __FUNCTION__, __LINE__);
+
+#define ASSERT_ON_STACK_GUARD() StackGuard::validate();
 void SurfaceFlinger::postComposition()
 {
+    DEFINE_STACK_GUARD(begin);
     ATRACE_CALL();
     ALOGV("postComposition");
 
     // Release any buffers which were replaced this frame
     nsecs_t dequeueReadyTime = systemTime();
+    DEFINE_STACK_GUARD(dequeueReadyTime);
     for (auto& layer : mLayersWithQueuedFrames) {
         layer->releasePendingBuffer(dequeueReadyTime);
     }
+    ASSERT_ON_STACK_GUARD();
 
     // |mStateLock| not needed as we are on the main thread
     const auto display = getDefaultDisplayDeviceLocked();
+    DEFINE_STACK_GUARD(display);
 
     getBE().mGlCompositionDoneTimeline.updateSignalTimes();
     std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
+    DEFINE_STACK_GUARD(glCompositionDoneFenceTime);
+
     if (display && getHwComposer().hasClientComposition(display->getId())) {
         glCompositionDoneFenceTime =
                 std::make_shared<FenceTime>(display->getClientTargetAcquireFence());
@@ -1891,13 +2016,17 @@
         glCompositionDoneFenceTime = FenceTime::NO_FENCE;
     }
 
+    ASSERT_ON_STACK_GUARD();
+
     getBE().mDisplayTimeline.updateSignalTimes();
     mPreviousPresentFence =
             display ? getHwComposer().getPresentFence(*display->getId()) : Fence::NO_FENCE;
     auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFence);
+    DEFINE_STACK_GUARD(presentFenceTime);
     getBE().mDisplayTimeline.push(presentFenceTime);
 
     DisplayStatInfo stats;
+    DEFINE_STACK_GUARD(stats);
     if (mUseScheduler) {
         mScheduler->getDisplayStatInfo(&stats);
     } else {
@@ -1905,34 +2034,46 @@
         stats.vsyncPeriod = mPrimaryDispSync->getPeriod();
     }
 
+    ASSERT_ON_STACK_GUARD();
+
     // We use the mRefreshStartTime which might be sampled a little later than
     // when we started doing work for this frame, but that should be okay
     // since updateCompositorTiming has snapping logic.
     updateCompositorTiming(stats, mRefreshStartTime, presentFenceTime);
     CompositorTiming compositorTiming;
+    DEFINE_STACK_GUARD(compositorTiming);
+
     {
         std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
+        DEFINE_STACK_GUARD(lock);
         compositorTiming = getBE().mCompositorTiming;
+
+        ASSERT_ON_STACK_GUARD();
     }
 
     mDrawingState.traverseInZOrder([&](Layer* layer) {
         bool frameLatched = layer->onPostComposition(display->getId(), glCompositionDoneFenceTime,
                                                      presentFenceTime, compositorTiming);
+        DEFINE_STACK_GUARD(frameLatched);
         if (frameLatched) {
             recordBufferingStats(layer->getName().string(),
                     layer->getOccupancyHistory(false));
         }
+        ASSERT_ON_STACK_GUARD();
     });
 
     if (presentFenceTime->isValid()) {
+        ASSERT_ON_STACK_GUARD();
         if (mUseScheduler) {
             mScheduler->addPresentFence(presentFenceTime);
+            ASSERT_ON_STACK_GUARD();
         } else {
             if (mPrimaryDispSync->addPresentFence(presentFenceTime)) {
                 enableHardwareVsync();
             } else {
                 disableHardwareVsync(false);
             }
+            ASSERT_ON_STACK_GUARD();
         }
     }
 
@@ -1946,61 +2087,86 @@
         }
     }
 
+    ASSERT_ON_STACK_GUARD();
+
     if (mAnimCompositionPending) {
         mAnimCompositionPending = false;
 
         if (presentFenceTime->isValid()) {
             mAnimFrameTracker.setActualPresentFence(
                     std::move(presentFenceTime));
+
+            ASSERT_ON_STACK_GUARD();
         } else if (display && getHwComposer().isConnected(*display->getId())) {
             // The HWC doesn't support present fences, so use the refresh
             // timestamp instead.
             const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(*display->getId());
+            DEFINE_STACK_GUARD(presentTime);
+
             mAnimFrameTracker.setActualPresentTime(presentTime);
+            ASSERT_ON_STACK_GUARD();
         }
         mAnimFrameTracker.advanceFrame();
     }
 
+    ASSERT_ON_STACK_GUARD();
+
     mTimeStats->incrementTotalFrames();
     if (mHadClientComposition) {
         mTimeStats->incrementClientCompositionFrames();
     }
 
+    ASSERT_ON_STACK_GUARD();
+
     mTimeStats->setPresentFenceGlobal(presentFenceTime);
 
+    ASSERT_ON_STACK_GUARD();
+
     if (display && getHwComposer().isConnected(*display->getId()) && !display->isPoweredOn()) {
         return;
     }
 
     nsecs_t currentTime = systemTime();
+    DEFINE_STACK_GUARD(currentTime);
     if (mHasPoweredOff) {
         mHasPoweredOff = false;
     } else {
         nsecs_t elapsedTime = currentTime - getBE().mLastSwapTime;
+        DEFINE_STACK_GUARD(elapsedTime);
         size_t numPeriods = static_cast<size_t>(elapsedTime / stats.vsyncPeriod);
+        DEFINE_STACK_GUARD(numPeriods);
         if (numPeriods < SurfaceFlingerBE::NUM_BUCKETS - 1) {
             getBE().mFrameBuckets[numPeriods] += elapsedTime;
         } else {
             getBE().mFrameBuckets[SurfaceFlingerBE::NUM_BUCKETS - 1] += elapsedTime;
         }
         getBE().mTotalTime += elapsedTime;
+
+        ASSERT_ON_STACK_GUARD();
     }
     getBE().mLastSwapTime = currentTime;
+    ASSERT_ON_STACK_GUARD();
 
     {
         std::lock_guard lock(mTexturePoolMutex);
+        DEFINE_STACK_GUARD(lock);
         const size_t refillCount = mTexturePoolSize - mTexturePool.size();
+        DEFINE_STACK_GUARD(refillCount);
         if (refillCount > 0) {
             const size_t offset = mTexturePool.size();
             mTexturePool.resize(mTexturePoolSize);
             getRenderEngine().genTextures(refillCount, mTexturePool.data() + offset);
             ATRACE_INT("TexturePoolSize", mTexturePool.size());
         }
+        ASSERT_ON_STACK_GUARD();
     }
 
     mTransactionCompletedThread.addPresentFence(mPreviousPresentFence);
     mTransactionCompletedThread.sendCallbacks();
+
+    ASSERT_ON_STACK_GUARD();
 }
+#pragma clang optimize on // b/119477596
 
 void SurfaceFlinger::rebuildLayerStacks() {
     ATRACE_CALL();
@@ -2273,7 +2439,7 @@
         // supply them with the present fence.
         if (!display->getLayersNeedingFences().isEmpty()) {
             sp<Fence> presentFence =
-                    displayId ? getBE().mHwc->getPresentFence(*displayId) : Fence::NO_FENCE;
+                    displayId ? getHwComposer().getPresentFence(*displayId) : Fence::NO_FENCE;
             for (auto& layer : display->getLayersNeedingFences()) {
                 layer->getBE().onLayerDisplayed(presentFence);
             }
@@ -2739,6 +2905,7 @@
     if (inputChanged || mVisibleRegionsDirty) {
         updateInputWindows();
     }
+    executeInputWindowCommands();
 
     updateCursorAsync();
 }
@@ -2763,6 +2930,23 @@
     mInputFlinger->setInputWindows(inputHandles);
 }
 
+void SurfaceFlinger::executeInputWindowCommands() {
+    if (!mInputFlinger) {
+        return;
+    }
+
+    for (const auto& transferTouchFocusCommand : mInputWindowCommands.transferTouchFocusCommands) {
+        if (transferTouchFocusCommand.fromToken != nullptr &&
+            transferTouchFocusCommand.toToken != nullptr &&
+            transferTouchFocusCommand.fromToken != transferTouchFocusCommand.toToken) {
+            mInputFlinger->transferTouchFocus(transferTouchFocusCommand.fromToken,
+                                              transferTouchFocusCommand.toToken);
+        }
+    }
+
+    mInputWindowCommands.clear();
+}
+
 void SurfaceFlinger::updateCursorAsync()
 {
     for (const auto& [token, display] : mDisplays) {
@@ -2800,10 +2984,8 @@
             // showing at its last configured state until we eventually
             // abandon the buffer queue.
             if (l->isRemovedFromCurrentState()) {
-                l->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* child) {
-                    child->destroyHwcLayersForAllDisplays();
-                    latchAndReleaseBuffer(child);
-                });
+                l->destroyHwcLayersForAllDisplays();
+                latchAndReleaseBuffer(l);
             }
         }
         mLayersPendingRemoval.clear();
@@ -2837,6 +3019,9 @@
     outDirtyRegion.clear();
 
     mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
+        // start with the whole surface at its current location
+        const Layer::State& s(layer->getDrawingState());
+
         // only consider the layers on the given layer stack
         if (!layer->belongsToDisplay(display->getLayerStack(), display->isPrimary())) {
             return;
@@ -2874,7 +3059,7 @@
 
         // handle hidden surfaces by setting the visible region to empty
         if (CC_LIKELY(layer->isVisible())) {
-            const bool translucent = !layer->isDrawingOpaque();
+            const bool translucent = !layer->isOpaque(s);
             Rect bounds(layer->computeScreenBounds());
 
             visibleRegion.set(bounds);
@@ -2884,8 +3069,7 @@
                 if (translucent) {
                     if (tr.preserveRects()) {
                         // transform the transparent region
-                        transparentRegion =
-                                tr.transform(layer->getDrawingActiveTransparentRegion());
+                        transparentRegion = tr.transform(layer->getActiveTransparentRegion(s));
                     } else {
                         // transformation too complex, can't do the
                         // transparent region optimization.
@@ -3003,12 +3187,18 @@
         }
     });
 
-    for (auto& layer : mLayersWithQueuedFrames) {
-        const Region dirty(layer->latchBuffer(visibleRegions, latchTime, getBE().flushFence));
-        layer->useSurfaceDamage();
-        invalidateLayerStack(layer, dirty);
-        if (layer->isBufferLatched()) {
-            newDataLatched = true;
+    if (!mLayersWithQueuedFrames.empty()) {
+        // mStateLock is needed for latchBuffer as LayerRejecter::reject()
+        // writes to Layer current state. See also b/119481871
+        Mutex::Autolock lock(mStateLock);
+
+        for (auto& layer : mLayersWithQueuedFrames) {
+            const Region dirty(layer->latchBuffer(visibleRegions, latchTime, getBE().flushFence));
+            layer->useSurfaceDamage();
+            invalidateLayerStack(layer, dirty);
+            if (layer->isBufferLatched()) {
+                newDataLatched = true;
+            }
         }
     }
 
@@ -3070,7 +3260,7 @@
     const Region bounds(display->bounds());
     const DisplayRenderArea renderArea(display);
     const auto displayId = display->getId();
-    const bool hasClientComposition = getBE().mHwc->hasClientComposition(displayId);
+    const bool hasClientComposition = getHwComposer().hasClientComposition(displayId);
     ATRACE_INT("hasClientComposition", hasClientComposition);
 
     mat4 colorMatrix;
@@ -3105,15 +3295,15 @@
         if (display->hasWideColorGamut()) {
             outputDataspace = display->getCompositionDataSpace();
         }
-        getBE().mRenderEngine->setOutputDataSpace(outputDataspace);
-        getBE().mRenderEngine->setDisplayMaxLuminance(
+        getRenderEngine().setOutputDataSpace(outputDataspace);
+        getRenderEngine().setDisplayMaxLuminance(
                 display->getHdrCapabilities().getDesiredMaxLuminance());
 
-        const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(displayId);
+        const bool hasDeviceComposition = getHwComposer().hasDeviceComposition(displayId);
         const bool skipClientColorTransform =
-                getBE().mHwc
-                        ->hasDisplayCapability(displayId,
-                                               HWC2::DisplayCapability::SkipClientColorTransform);
+                getHwComposer()
+                        .hasDisplayCapability(displayId,
+                                              HWC2::DisplayCapability::SkipClientColorTransform);
 
         // Compute the global color transform matrix.
         applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform;
@@ -3130,7 +3320,7 @@
             // remove where there are opaque FB layers. however, on some
             // GPUs doing a "clean slate" clear might be more efficient.
             // We'll revisit later if needed.
-            getBE().mRenderEngine->clearWithColor(0, 0, 0, 0);
+            getRenderEngine().clearWithColor(0, 0, 0, 0);
         } else {
             // we start with the whole screen area and remove the scissor part
             // we're left with the letterbox region
@@ -3155,7 +3345,7 @@
             // the GL scissor so we don't draw anything where we shouldn't
 
             // enable scissor for this frame
-            getBE().mRenderEngine->setScissor(scissor);
+            getRenderEngine().setScissor(scissor);
         }
     }
 
@@ -3178,8 +3368,9 @@
                 case HWC2::Composition::Sideband:
                 case HWC2::Composition::SolidColor: {
                     LOG_ALWAYS_FATAL_IF(!displayId);
+                    const Layer::State& state(layer->getDrawingState());
                     if (layer->getClearClientTarget(*displayId) && !firstLayer &&
-                        layer->isDrawingOpaque() && (layer->getAlpha() == 1.0f) &&
+                        layer->isOpaque(state) && (layer->getAlpha() == 1.0f) &&
                         layer->getRoundedCornerState().radius == 0.0f && hasClientComposition) {
                         // never clear the very first layer since we're
                         // guaranteed the FB is already cleared
@@ -3213,7 +3404,7 @@
     // Perform some cleanup steps if we used client composition.
     if (hasClientComposition) {
         getRenderEngine().setColorTransform(mat4());
-        getBE().mRenderEngine->disableScissor();
+        getRenderEngine().disableScissor();
         display->finishBuffer();
         // Clear out error flags here so that we don't wait until next
         // composition to log.
@@ -3231,7 +3422,8 @@
         const sp<IBinder>& handle,
         const sp<IGraphicBufferProducer>& gbc,
         const sp<Layer>& lbc,
-        const sp<Layer>& parent)
+        const sp<Layer>& parent,
+        bool addToCurrentState)
 {
     // add this layer to the current state list
     {
@@ -3241,13 +3433,12 @@
                   MAX_LAYERS);
             return NO_MEMORY;
         }
-        if (parent == nullptr) {
+        if (parent == nullptr && addToCurrentState) {
             mCurrentState.layersSortedByZ.add(lbc);
-        } else {
-            if (parent->isRemovedFromCurrentState()) {
+        } else if (parent == nullptr || parent->isRemovedFromCurrentState()) {
                 ALOGE("addClientLayer called with a removed parent");
                 lbc->onRemovedFromCurrentState();
-            }
+        } else {
             parent->addChild(lbc);
         }
 
@@ -3268,30 +3459,6 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer) {
-    Mutex::Autolock _l(mStateLock);
-    return removeLayerLocked(mStateLock, layer);
-}
-
-status_t SurfaceFlinger::removeLayerLocked(const Mutex& lock, const sp<Layer>& layer) {
-    if (layer->isLayerDetached()) {
-        return NO_ERROR;
-    }
-
-    const auto& p = layer->getParent();
-    ssize_t index;
-    if (p != nullptr) {
-        index = p->removeChild(layer);
-    } else {
-        index = mCurrentState.layersSortedByZ.remove(layer);
-    }
-
-    layer->onRemovedFromCurrentState();
-
-    markLayerPendingRemovalLocked(lock, layer);
-    return NO_ERROR;
-}
-
 uint32_t SurfaceFlinger::peekTransactionFlags() {
     return mTransactionFlags;
 }
@@ -3314,6 +3481,26 @@
     return old;
 }
 
+bool SurfaceFlinger::flushTransactionQueues() {
+    Mutex::Autolock _l(mStateLock);
+    auto it = mTransactionQueues.begin();
+    while (it != mTransactionQueues.end()) {
+        auto& [applyToken, transactionQueue] = *it;
+
+        while (!transactionQueue.empty()) {
+            const auto& [states, displays, flags] = transactionQueue.front();
+            if (composerStateContainsUnsignaledFences(states)) {
+                break;
+            }
+            applyTransactionState(states, displays, flags, mInputWindowCommands);
+            transactionQueue.pop();
+        }
+
+        it = (transactionQueue.empty()) ? mTransactionQueues.erase(it) : std::next(it, 1);
+    }
+    return mTransactionQueues.empty();
+}
+
 bool SurfaceFlinger::containsAnyInvalidClientState(const Vector<ComposerState>& states) {
     for (const ComposerState& state : states) {
         // Here we need to check that the interface we're given is indeed
@@ -3336,19 +3523,46 @@
     return false;
 }
 
-void SurfaceFlinger::setTransactionState(
-        const Vector<ComposerState>& states,
-        const Vector<DisplayState>& displays,
-        uint32_t flags)
-{
+bool SurfaceFlinger::composerStateContainsUnsignaledFences(const Vector<ComposerState>& states) {
+    for (const ComposerState& state : states) {
+        const layer_state_t& s = state.state;
+        if (!(s.what & layer_state_t::eAcquireFenceChanged)) {
+            continue;
+        }
+        if (s.acquireFence && s.acquireFence->getStatus() == Fence::Status::Unsignaled) {
+            return true;
+        }
+    }
+    return false;
+}
+
+void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& states,
+                                         const Vector<DisplayState>& displays, uint32_t flags,
+                                         const sp<IBinder>& applyToken,
+                                         const InputWindowCommands& inputWindowCommands) {
     ATRACE_CALL();
     Mutex::Autolock _l(mStateLock);
-    uint32_t transactionFlags = 0;
 
     if (containsAnyInvalidClientState(states)) {
         return;
     }
 
+    // If its TransactionQueue already has a pending TransactionState or if it is pending
+    if (mTransactionQueues.find(applyToken) != mTransactionQueues.end() ||
+        composerStateContainsUnsignaledFences(states)) {
+        mTransactionQueues[applyToken].emplace(states, displays, flags);
+        setTransactionFlags(eTransactionNeeded);
+        return;
+    }
+
+    applyTransactionState(states, displays, flags, inputWindowCommands);
+}
+
+void SurfaceFlinger::applyTransactionState(const Vector<ComposerState>& states,
+                                           const Vector<DisplayState>& displays, uint32_t flags,
+                                           const InputWindowCommands& inputWindowCommands) {
+    uint32_t transactionFlags = 0;
+
     if (flags & eAnimation) {
         // For window updates that are part of an animation we must wait for
         // previous animation "frames" to be handled.
@@ -3379,13 +3593,7 @@
     }
     transactionFlags |= clientStateFlags;
 
-    // Iterate through all layers again to determine if any need to be destroyed. Marking layers
-    // as destroyed should only occur after setting all other states. This is to allow for a
-    // child re-parent to happen before marking its original parent as destroyed (which would
-    // then mark the child as destroyed).
-    for (const ComposerState& state : states) {
-        setDestroyStateLocked(state);
-    }
+    transactionFlags |= addInputWindowCommands(inputWindowCommands);
 
     // If a synchronous transaction is explicitly requested without any changes, force a transaction
     // anyway. This can be used as a flush mechanism for previous async transactions.
@@ -3710,18 +3918,14 @@
     return flags;
 }
 
-void SurfaceFlinger::setDestroyStateLocked(const ComposerState& composerState) {
-    const layer_state_t& state = composerState.state;
-    sp<Client> client(static_cast<Client*>(composerState.client.get()));
-
-    sp<Layer> layer(client->getLayerUser(state.surface));
-    if (layer == nullptr) {
-        return;
+uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& inputWindowCommands) {
+    uint32_t flags = 0;
+    if (!inputWindowCommands.transferTouchFocusCommands.empty()) {
+        flags |= eTraversalNeeded;
     }
 
-    if (state.what & layer_state_t::eDestroySurface) {
-        removeLayerLocked(mStateLock, layer);
-    }
+    mInputWindowCommands.merge(inputWindowCommands);
+    return flags;
 }
 
 status_t SurfaceFlinger::createLayer(
@@ -3793,7 +3997,9 @@
 
     layer->setInfo(windowType, ownerUid);
 
-    result = addClientLayer(client, *handle, *gbp, layer, *parent);
+    bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess();
+    result = addClientLayer(client, *handle, *gbp, layer, *parent,
+            addToCurrentState);
     if (result != NO_ERROR) {
         return result;
     }
@@ -3891,21 +4097,7 @@
 }
 
 
-status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
-{
-    // called by a client when it wants to remove a Layer
-    status_t err = NO_ERROR;
-    sp<Layer> l(client->getLayerUser(handle));
-    if (l != nullptr) {
-        mInterceptor->saveSurfaceDeletion(l);
-        err = removeLayer(l);
-        ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
-                "error removing layer=%p (%s)", l.get(), strerror(-err));
-    }
-    return err;
-}
-
-void SurfaceFlinger::markLayerPendingRemovalLocked(const Mutex&, const sp<Layer>& layer) {
+void SurfaceFlinger::markLayerPendingRemovalLocked(const sp<Layer>& layer) {
     mLayersPendingRemoval.add(layer);
     mLayersRemoved = true;
     setTransactionFlags(eTransactionNeeded);
@@ -3914,7 +4106,14 @@
 void SurfaceFlinger::onHandleDestroyed(sp<Layer>& layer)
 {
     Mutex::Autolock lock(mStateLock);
-    markLayerPendingRemovalLocked(mStateLock, layer);
+    // If a layer has a parent, we allow it to out-live it's handle
+    // with the idea that the parent holds a reference and will eventually
+    // be cleaned up. However no one cleans up the top-level so we do so
+    // here.
+    if (layer->getParent() == nullptr) {
+        mCurrentState.layersSortedByZ.remove(layer);
+    }
+    markLayerPendingRemovalLocked(layer);
     layer.clear();
 }
 
@@ -3938,7 +4137,7 @@
     d.width = 0;
     d.height = 0;
     displays.add(d);
-    setTransactionState(state, displays, 0);
+    setTransactionState(state, displays, 0, nullptr, mInputWindowCommands);
 
     const auto display = getDisplayDevice(displayToken);
     if (!display) return;
@@ -4611,7 +4810,7 @@
     result.append("SurfaceFlinger global state:\n");
     colorizer.reset(result);
 
-    getBE().mRenderEngine->dump(result);
+    getRenderEngine().dump(result);
 
     if (const auto display = getDefaultDisplayDeviceLocked()) {
         display->undefinedRegion.dump(result, "undefinedRegion");
@@ -4757,7 +4956,6 @@
         // access to SF.
         case BOOT_FINISHED:
         case CLEAR_ANIMATION_FRAME_STATS:
-        case CREATE_CONNECTION:
         case CREATE_DISPLAY:
         case DESTROY_DISPLAY:
         case ENABLE_VSYNC_INJECTIONS:
@@ -4804,8 +5002,7 @@
         // Calling setTransactionState is safe, because you need to have been
         // granted a reference to Client* and Handle* to do anything with it.
         case SET_TRANSACTION_STATE:
-        // Creating a scoped connection is safe, as per discussion in ISurfaceComposer.h
-        case CREATE_SCOPED_CONNECTION:
+        case CREATE_CONNECTION:
         case GET_COLOR_MANAGEMENT:
         case GET_COMPOSITION_PREFERENCE: {
             return OK;
@@ -5087,7 +5284,7 @@
             // Is VrFlinger active?
             case 1028: {
                 Mutex::Autolock _l(mStateLock);
-                reply->writeBool(getBE().mHwc->isUsingVrComposer());
+                reply->writeBool(getHwComposer().isUsingVrComposer());
                 return NO_ERROR;
             }
             // Is device color managed?
@@ -5137,6 +5334,11 @@
     signalTransaction();
 }
 
+void SurfaceFlinger::repaintEverythingForHWC() {
+    mRepaintEverything = true;
+    mEventQueue->invalidateForHWC();
+}
+
 // A simple RAII class to disconnect from an ANativeWindow* when it goes out of scope
 class WindowDisconnector {
 public:
@@ -5204,12 +5406,15 @@
                 mFlinger(flinger),
                 mChildrenOnly(childrenOnly) {}
         const ui::Transform& getTransform() const override { return mTransform; }
-        Rect getBounds() const override { return mLayer->getBufferSize(StateSet::Drawing); }
+        Rect getBounds() const override {
+            const Layer::State& layerState(mLayer->getDrawingState());
+            return mLayer->getBufferSize(layerState);
+        }
         int getHeight() const override {
-            return mLayer->getBufferSize(StateSet::Drawing).getHeight();
+            return mLayer->getBufferSize(mLayer->getDrawingState()).getHeight();
         }
         int getWidth() const override {
-            return mLayer->getBufferSize(StateSet::Drawing).getWidth();
+            return mLayer->getBufferSize(mLayer->getDrawingState()).getWidth();
         }
         bool isSecure() const override { return false; }
         bool needsFiltering() const override { return mNeedsFiltering; }
@@ -5276,7 +5481,7 @@
 
     const int uid = IPCThreadState::self()->getCallingUid();
     const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
-    if (!forSystem && parent->getCurrentFlags() & layer_state_t::eLayerSecure) {
+    if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
         ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
         return PERMISSION_DENIED;
     }
@@ -5284,12 +5489,12 @@
     Rect crop(sourceCrop);
     if (sourceCrop.width() <= 0) {
         crop.left = 0;
-        crop.right = parent->getBufferSize(StateSet::Current).getWidth();
+        crop.right = parent->getBufferSize(parent->getCurrentState()).getWidth();
     }
 
     if (sourceCrop.height() <= 0) {
         crop.top = 0;
-        crop.bottom = parent->getBufferSize(StateSet::Current).getHeight();
+        crop.bottom = parent->getBufferSize(parent->getCurrentState()).getHeight();
     }
 
     int32_t reqWidth = crop.width() * frameScale;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index b1bfb3a..134f9c2 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -25,53 +25,46 @@
  * NOTE: Make sure this file doesn't include  anything from <gl/ > or <gl2/ >
  */
 
-#include <cutils/compiler.h>
 #include <cutils/atomic.h>
-
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include <utils/RefBase.h>
-#include <utils/SortedVector.h>
-#include <utils/threads.h>
-#include <utils/Trace.h>
-
-#include <ui/FenceTime.h>
-#include <ui/PixelFormat.h>
-#include <math/mat4.h>
-
+#include <cutils/compiler.h>
+#include <gui/BufferQueue.h>
 #include <gui/FrameTimestamps.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/ISurfaceComposerClient.h>
 #include <gui/LayerState.h>
-
 #include <gui/OccupancyTracker.h>
-#include <gui/BufferQueue.h>
-
 #include <hardware/hwcomposer_defs.h>
-
+#include <layerproto/LayerProtoHeader.h>
+#include <math/mat4.h>
 #include <serviceutils/PriorityDumper.h>
-
 #include <system/graphics.h>
+#include <ui/FenceTime.h>
+#include <ui/PixelFormat.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+#include <utils/SortedVector.h>
+#include <utils/Trace.h>
+#include <utils/threads.h>
 
 #include "Barrier.h"
 #include "DisplayDevice.h"
+#include "DisplayHardware/HWC2.h"
+#include "DisplayHardware/HWComposer.h"
+#include "Effects/Daltonizer.h"
 #include "FrameTracker.h"
 #include "LayerBE.h"
 #include "LayerStats.h"
 #include "LayerVector.h"
-#include "SurfaceFlingerFactory.h"
-#include "SurfaceInterceptor.h"
-#include "SurfaceTracing.h"
-#include "TransactionCompletedThread.h"
-
-#include "DisplayHardware/HWC2.h"
-#include "DisplayHardware/HWComposer.h"
-#include "Effects/Daltonizer.h"
 #include "Scheduler/DispSync.h"
 #include "Scheduler/EventThread.h"
 #include "Scheduler/MessageQueue.h"
 #include "Scheduler/Scheduler.h"
 #include "Scheduler/VSyncModulator.h"
+#include "SurfaceFlingerFactory.h"
+#include "SurfaceInterceptor.h"
+#include "SurfaceTracing.h"
+#include "TransactionCompletedThread.h"
 
 #include <map>
 #include <mutex>
@@ -82,8 +75,6 @@
 #include <unordered_map>
 #include <utility>
 
-#include <layerproto/LayerProtoHeader.h>
-
 using namespace android::surfaceflinger;
 
 namespace android {
@@ -146,35 +137,8 @@
 public:
     SurfaceFlingerBE();
 
-    // The current hardware composer interface.
-    //
-    // The following thread safety rules apply when accessing mHwc, either
-    // directly or via getHwComposer():
-    //
-    // 1. When recreating mHwc, acquire mStateLock. We currently recreate mHwc
-    //    only when switching into and out of vr. Recreating mHwc must only be
-    //    done on the main thread.
-    //
-    // 2. When accessing mHwc on the main thread, it's not necessary to acquire
-    //    mStateLock.
-    //
-    // 3. When accessing mHwc on a thread other than the main thread, we always
-    //    need to acquire mStateLock. This is because the main thread could be
-    //    in the process of destroying the current mHwc instance.
-    //
-    // The above thread safety rules only apply to SurfaceFlinger.cpp. In
-    // SurfaceFlinger_hwc1.cpp we create mHwc at surface flinger init and never
-    // destroy it, so it's always safe to access mHwc from any thread without
-    // acquiring mStateLock.
-    std::unique_ptr<HWComposer> mHwc;
-
     const std::string mHwcServiceName; // "default" for real use, something else for testing.
 
-    // constant members (no synchronization needed for access)
-    std::unique_ptr<renderengine::RenderEngine> mRenderEngine;
-    EGLContext mEGLContext;
-    EGLDisplay mEGLDisplay;
-
     FenceTimeline mGlCompositionDoneTimeline;
     FenceTimeline mDisplayTimeline;
 
@@ -334,8 +298,14 @@
     // force full composition on all displays
     void repaintEverything();
 
+    // force full composition on all displays without resetting the scheduler idle timer.
+    void repaintEverythingForHWC();
+
     surfaceflinger::Factory& getFactory() { return mFactory; }
 
+    // The CompositionEngine encapsulates all composition related interfaces and actions.
+    compositionengine::CompositionEngine& getCompositionEngine() const;
+
     // returns the default Display
     sp<const DisplayDevice> getDefaultDisplayDevice() const {
         Mutex::Autolock _l(mStateLock);
@@ -362,7 +332,7 @@
     // TODO: this should be made accessible only to HWComposer
     const Vector<sp<Layer>>& getLayerSortedByZForHwcDisplay(DisplayId displayId);
 
-    renderengine::RenderEngine& getRenderEngine() const { return *getBE().mRenderEngine; }
+    renderengine::RenderEngine& getRenderEngine() const;
 
     bool authenticateSurfaceTextureLocked(
         const sp<IGraphicBufferProducer>& bufferProducer) const;
@@ -429,76 +399,74 @@
     /* ------------------------------------------------------------------------
      * IBinder interface
      */
-    virtual status_t onTransact(uint32_t code, const Parcel& data,
-        Parcel* reply, uint32_t flags);
-    virtual status_t dump(int fd, const Vector<String16>& args) { return priorityDump(fd, args); }
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
+    status_t dump(int fd, const Vector<String16>& args) override { return priorityDump(fd, args); }
 
     /* ------------------------------------------------------------------------
      * ISurfaceComposer interface
      */
-    virtual sp<ISurfaceComposerClient> createConnection();
-    virtual sp<ISurfaceComposerClient> createScopedConnection(const sp<IGraphicBufferProducer>& gbp);
-    virtual sp<IBinder> createDisplay(const String8& displayName, bool secure);
-    virtual void destroyDisplay(const sp<IBinder>& displayToken);
-    virtual sp<IBinder> getBuiltInDisplay(int32_t id);
-    virtual void setTransactionState(const Vector<ComposerState>& state,
-            const Vector<DisplayState>& displays, uint32_t flags);
-    virtual void bootFinished();
-    virtual bool authenticateSurfaceTexture(
-        const sp<IGraphicBufferProducer>& bufferProducer) const;
-    virtual status_t getSupportedFrameTimestamps(
-            std::vector<FrameEvent>* outSupported) const;
-    virtual sp<IDisplayEventConnection> createDisplayEventConnection(
-            ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp);
-    virtual status_t captureScreen(const sp<IBinder>& displayToken, sp<GraphicBuffer>* outBuffer,
-                                   const ui::Dataspace reqDataspace,
-                                   const ui::PixelFormat reqPixelFormat, Rect sourceCrop,
-                                   uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform,
-                                   ISurfaceComposer::Rotation rotation);
-    virtual status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
-                                   const ui::Dataspace reqDataspace,
-                                   const ui::PixelFormat reqPixelFormat, const Rect& sourceCrop,
-                                   float frameScale, bool childrenOnly);
-    virtual status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats);
-    virtual status_t getDisplayConfigs(const sp<IBinder>& displayToken,
-                                       Vector<DisplayInfo>* configs);
-    virtual int getActiveConfig(const sp<IBinder>& displayToken);
-    virtual status_t getDisplayColorModes(const sp<IBinder>& displayToken,
-                                          Vector<ui::ColorMode>* configs);
-    virtual ui::ColorMode getActiveColorMode(const sp<IBinder>& displayToken);
-    virtual status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode);
-    virtual void setPowerMode(const sp<IBinder>& displayToken, int mode);
-    virtual status_t setActiveConfig(const sp<IBinder>& displayToken, int id);
-    virtual status_t clearAnimationFrameStats();
-    virtual status_t getAnimationFrameStats(FrameStats* outStats) const;
-    virtual status_t getHdrCapabilities(const sp<IBinder>& displayToken,
-                                        HdrCapabilities* outCapabilities) const;
-    virtual status_t enableVSyncInjections(bool enable);
-    virtual status_t injectVSync(nsecs_t when);
-    virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const;
-    virtual status_t getColorManagement(bool* outGetColorManagement) const;
+    sp<ISurfaceComposerClient> createConnection() override;
+    sp<IBinder> createDisplay(const String8& displayName, bool secure) override;
+    void destroyDisplay(const sp<IBinder>& displayToken) override;
+    sp<IBinder> getBuiltInDisplay(int32_t id) override;
+    void setTransactionState(const Vector<ComposerState>& state,
+                             const Vector<DisplayState>& displays, uint32_t flags,
+                             const sp<IBinder>& applyToken,
+                             const InputWindowCommands& inputWindowCommands) override;
+    void bootFinished() override;
+    bool authenticateSurfaceTexture(
+            const sp<IGraphicBufferProducer>& bufferProducer) const override;
+    status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const override;
+    sp<IDisplayEventConnection> createDisplayEventConnection(
+            ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp) override;
+    status_t captureScreen(const sp<IBinder>& displayToken, sp<GraphicBuffer>* outBuffer,
+                           const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
+                           Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+                           bool useIdentityTransform, ISurfaceComposer::Rotation rotation) override;
+    status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
+                           const ui::Dataspace reqDataspace, const ui::PixelFormat reqPixelFormat,
+                           const Rect& sourceCrop, float frameScale, bool childrenOnly) override;
+    status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats) override;
+    status_t getDisplayConfigs(const sp<IBinder>& displayToken,
+                               Vector<DisplayInfo>* configs) override;
+    int getActiveConfig(const sp<IBinder>& displayToken) override;
+    status_t getDisplayColorModes(const sp<IBinder>& displayToken,
+                                  Vector<ui::ColorMode>* configs) override;
+    ui::ColorMode getActiveColorMode(const sp<IBinder>& displayToken) override;
+    status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode) override;
+    void setPowerMode(const sp<IBinder>& displayToken, int mode) override;
+    status_t setActiveConfig(const sp<IBinder>& displayToken, int id) override;
+    status_t clearAnimationFrameStats() override;
+    status_t getAnimationFrameStats(FrameStats* outStats) const override;
+    status_t getHdrCapabilities(const sp<IBinder>& displayToken,
+                                HdrCapabilities* outCapabilities) const override;
+    status_t enableVSyncInjections(bool enable) override;
+    status_t injectVSync(nsecs_t when) override;
+    status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const override;
+    status_t getColorManagement(bool* outGetColorManagement) const override;
     status_t getCompositionPreference(ui::Dataspace* outDataspace, ui::PixelFormat* outPixelFormat,
                                       ui::Dataspace* outWideColorGamutDataspace,
                                       ui::PixelFormat* outWideColorGamutPixelFormat) const override;
-    virtual status_t getDisplayedContentSamplingAttributes(
-            const sp<IBinder>& display, ui::PixelFormat* outFormat, ui::Dataspace* outDataspace,
-            uint8_t* outComponentMask) const override;
-    virtual status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
-                                                      uint8_t componentMask,
-                                                      uint64_t maxFrames) const override;
-    virtual status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
-                                               uint64_t timestamp,
-                                               DisplayedFrameStats* outStats) const override;
+    status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
+                                                   ui::PixelFormat* outFormat,
+                                                   ui::Dataspace* outDataspace,
+                                                   uint8_t* outComponentMask) const override;
+    status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
+                                              uint8_t componentMask,
+                                              uint64_t maxFrames) const override;
+    status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
+                                       uint64_t timestamp,
+                                       DisplayedFrameStats* outStats) const override;
 
     /* ------------------------------------------------------------------------
      * DeathRecipient interface
      */
-    virtual void binderDied(const wp<IBinder>& who);
+    void binderDied(const wp<IBinder>& who) override;
 
     /* ------------------------------------------------------------------------
      * RefBase interface
      */
-    virtual void onFirstRef();
+    void onFirstRef() override;
 
     /* ------------------------------------------------------------------------
      * HWC2::ComposerCallback / HWComposer::EventHandler interface
@@ -521,8 +489,10 @@
 
     // called on the main thread in response to initializeDisplays()
     void onInitializeDisplays();
+    // setActiveConfigInternal() posted on a main thread for async execution
+    status_t setActiveConfigAsync(const sp<IBinder>& displayToken, int mode);
     // called on the main thread in response to setActiveConfig()
-    void setActiveConfigInternal(const sp<DisplayDevice>& display, int mode);
+    void setActiveConfigInternal(const sp<IBinder>& displayToken, int mode);
     // called on the main thread in response to setPowerMode()
     void setPowerModeInternal(const sp<DisplayDevice>& display, int mode);
 
@@ -542,6 +512,7 @@
     void handleTransactionLocked(uint32_t transactionFlags);
 
     void updateInputWindows();
+    void executeInputWindowCommands();
     void updateCursorAsync();
 
     /* handlePageFlip - latch a new buffer if available and compute the dirty
@@ -553,6 +524,10 @@
     /* ------------------------------------------------------------------------
      * Transactions
      */
+    void applyTransactionState(const Vector<ComposerState>& state,
+                               const Vector<DisplayState>& displays, uint32_t flags,
+                               const InputWindowCommands& inputWindowCommands) REQUIRES(mStateLock);
+    bool flushTransactionQueues();
     uint32_t getTransactionFlags(uint32_t flags);
     uint32_t peekTransactionFlags();
     // Can only be called from the main thread or with mStateLock held
@@ -561,9 +536,10 @@
     void latchAndReleaseBuffer(const sp<Layer>& layer);
     void commitTransaction();
     bool containsAnyInvalidClientState(const Vector<ComposerState>& states);
+    bool composerStateContainsUnsignaledFences(const Vector<ComposerState>& states);
     uint32_t setClientStateLocked(const ComposerState& composerState);
     uint32_t setDisplayStateLocked(const DisplayState& s);
-    void setDestroyStateLocked(const ComposerState& composerState);
+    uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands);
 
     /* ------------------------------------------------------------------------
      * Layer management
@@ -592,27 +568,19 @@
 
     String8 getUniqueLayerName(const String8& name);
 
-    // called in response to the window-manager calling
-    // ISurfaceComposerClient::destroySurface()
-    status_t onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle);
-
-    void markLayerPendingRemovalLocked(const Mutex& /* mStateLock */, const sp<Layer>& layer);
-
     // called when all clients have released all their references to
     // this layer meaning it is entirely safe to destroy all
     // resources associated to this layer.
     void onHandleDestroyed(sp<Layer>& layer);
-
-    // remove a layer from SurfaceFlinger immediately
-    status_t removeLayer(const sp<Layer>& layer);
-    status_t removeLayerLocked(const Mutex&, const sp<Layer>& layer);
+    void markLayerPendingRemovalLocked(const sp<Layer>& layer);
 
     // add a layer to SurfaceFlinger
     status_t addClientLayer(const sp<Client>& client,
             const sp<IBinder>& handle,
             const sp<IGraphicBufferProducer>& gbc,
             const sp<Layer>& lbc,
-            const sp<Layer>& parent);
+            const sp<Layer>& parent,
+            bool addToCurrentState);
 
     /* ------------------------------------------------------------------------
      * Boot animation, on/off animations and screen capture
@@ -691,7 +659,27 @@
      * H/W composer
      */
 
-    HWComposer& getHwComposer() const { return *getBE().mHwc; }
+    // The current hardware composer interface.
+    //
+    // The following thread safety rules apply when accessing mHwc, either
+    // directly or via getHwComposer():
+    //
+    // 1. When recreating mHwc, acquire mStateLock. We currently recreate mHwc
+    //    only when switching into and out of vr. Recreating mHwc must only be
+    //    done on the main thread.
+    //
+    // 2. When accessing mHwc on the main thread, it's not necessary to acquire
+    //    mStateLock.
+    //
+    // 3. When accessing mHwc on a thread other than the main thread, we always
+    //    need to acquire mStateLock. This is because the main thread could be
+    //    in the process of destroying the current mHwc instance.
+    //
+    // The above thread safety rules only apply to SurfaceFlinger.cpp. In
+    // SurfaceFlinger_hwc1.cpp we create mHwc at surface flinger init and never
+    // destroy it, so it's always safe to access mHwc from any thread without
+    // acquiring mStateLock.
+    HWComposer& getHwComposer() const;
 
     /* ------------------------------------------------------------------------
      * Compositing
@@ -764,6 +752,9 @@
     void resyncWithRateLimit();
     void getCompositorTiming(CompositorTiming* compositorTiming);
 private:
+    // Sets the refresh rate to newFps by switching active configs, if they are available for
+    // the desired refresh rate.
+    void setRefreshRateTo(float newFps);
 
     /* ------------------------------------------------------------------------
      * Debugging & dumpsys
@@ -965,6 +956,22 @@
     uint32_t mTexturePoolSize = 0;
     std::vector<uint32_t> mTexturePool;
 
+    struct IBinderHash {
+        std::size_t operator()(const sp<IBinder>& strongPointer) const {
+            return std::hash<IBinder*>{}(strongPointer.get());
+        }
+    };
+    struct TransactionState {
+        TransactionState(const Vector<ComposerState>& composerStates,
+                         const Vector<DisplayState>& displayStates, uint32_t transactionFlags)
+              : states(composerStates), displays(displayStates), flags(transactionFlags) {}
+
+        Vector<ComposerState> states;
+        Vector<DisplayState> displays;
+        uint32_t flags;
+    };
+    std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IBinderHash> mTransactionQueues;
+
     /* ------------------------------------------------------------------------
      * Feature prototyping
      */
@@ -991,6 +998,7 @@
     ui::Dataspace mWideColorGamutCompositionDataspace;
 
     SurfaceFlingerBE mBE;
+    std::unique_ptr<compositionengine::CompositionEngine> mCompositionEngine;
 
     bool mUseScheduler = false;
     std::unique_ptr<Scheduler> mScheduler;
@@ -998,6 +1006,8 @@
     sp<Scheduler::ConnectionHandle> mSfConnectionHandle;
 
     sp<IInputFlinger> mInputFlinger;
+
+    InputWindowCommands mInputWindowCommands;
 };
 }; // namespace android
 
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.cpp b/services/surfaceflinger/SurfaceFlingerFactory.cpp
index 88649e3..77679e3 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.cpp
+++ b/services/surfaceflinger/SurfaceFlingerFactory.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <compositionengine/impl/CompositionEngine.h>
 #include <ui/GraphicBuffer.h>
 
 #include "BufferQueueLayer.h"
@@ -59,7 +60,7 @@
         }
 
         std::unique_ptr<HWComposer> createHWComposer(const std::string& serviceName) override {
-            return std::make_unique<HWComposer>(
+            return std::make_unique<android::impl::HWComposer>(
                     std::make_unique<Hwc2::impl::Composer>(serviceName));
         }
 
@@ -102,6 +103,10 @@
             return surfaceflinger::impl::createNativeWindowSurface(producer);
         }
 
+        std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() override {
+            return compositionengine::impl::createCompositionEngine();
+        }
+
         sp<ContainerLayer> createContainerLayer(const LayerCreationArgs& args) override {
             return new ContainerLayer(args);
         }
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h
index 1c27cc7..f747684 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerFactory.h
@@ -49,6 +49,9 @@
 struct DisplayDeviceCreationArgs;
 struct LayerCreationArgs;
 
+namespace compositionengine {
+class CompositionEngine;
+} // namespace compositionengine
 namespace surfaceflinger {
 
 class NativeWindowSurface;
@@ -78,6 +81,8 @@
     virtual std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
             const sp<IGraphicBufferProducer>&) = 0;
 
+    virtual std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() = 0;
+
     virtual sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs& args) = 0;
     virtual sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs& args) = 0;
     virtual sp<ColorLayer> createColorLayer(const LayerCreationArgs& args) = 0;
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index a6dcb7e..7bfe033 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -101,23 +101,22 @@
     transaction->set_animation(layerFlags & BnSurfaceComposer::eAnimation);
 
     const int32_t layerId(getLayerId(layer));
-    Mutex::Autolock lock(layer->mStateMutex);
-    addPositionLocked(transaction, layerId, layer->mState.current.active_legacy.transform.tx(),
-                      layer->mState.current.active_legacy.transform.ty());
-    addDepthLocked(transaction, layerId, layer->mState.current.z);
-    addAlphaLocked(transaction, layerId, layer->mState.current.color.a);
+    addPositionLocked(transaction, layerId, layer->mCurrentState.active_legacy.transform.tx(),
+                      layer->mCurrentState.active_legacy.transform.ty());
+    addDepthLocked(transaction, layerId, layer->mCurrentState.z);
+    addAlphaLocked(transaction, layerId, layer->mCurrentState.color.a);
     addTransparentRegionLocked(transaction, layerId,
-                               layer->mState.current.activeTransparentRegion_legacy);
-    addLayerStackLocked(transaction, layerId, layer->mState.current.layerStack);
-    addCropLocked(transaction, layerId, layer->mState.current.crop_legacy);
-    addCornerRadiusLocked(transaction, layerId, layer->mState.current.cornerRadius);
-    if (layer->mState.current.barrierLayer_legacy != nullptr) {
+                               layer->mCurrentState.activeTransparentRegion_legacy);
+    addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack);
+    addCropLocked(transaction, layerId, layer->mCurrentState.crop_legacy);
+    addCornerRadiusLocked(transaction, layerId, layer->mCurrentState.cornerRadius);
+    if (layer->mCurrentState.barrierLayer_legacy != nullptr) {
         addDeferTransactionLocked(transaction, layerId,
-                                  layer->mState.current.barrierLayer_legacy.promote(),
-                                  layer->mState.current.frameNumber_legacy);
+                                  layer->mCurrentState.barrierLayer_legacy.promote(),
+                                  layer->mCurrentState.frameNumber_legacy);
     }
     addOverrideScalingModeLocked(transaction, layerId, layer->getEffectiveScalingMode());
-    addFlagsLocked(transaction, layerId, layer->mState.current.flags);
+    addFlagsLocked(transaction, layerId, layer->mCurrentState.flags);
 }
 
 void SurfaceInterceptor::addInitialDisplayStateLocked(Increment* increment,
@@ -427,9 +426,8 @@
     SurfaceCreation* creation(increment->mutable_surface_creation());
     creation->set_id(getLayerId(layer));
     creation->set_name(getLayerName(layer));
-    Mutex::Autolock lock(layer->mStateMutex);
-    creation->set_w(layer->mState.current.active_legacy.w);
-    creation->set_h(layer->mState.current.active_legacy.h);
+    creation->set_w(layer->mCurrentState.active_legacy.w);
+    creation->set_h(layer->mCurrentState.active_legacy.h);
 }
 
 void SurfaceInterceptor::addSurfaceDeletionLocked(Increment* increment,
diff --git a/services/surfaceflinger/TEST_MAPPING b/services/surfaceflinger/TEST_MAPPING
new file mode 100644
index 0000000..cab33ae
--- /dev/null
+++ b/services/surfaceflinger/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+  "presubmit": [
+    {
+      "name": "libsurfaceflinger_unittest"
+    },
+    {
+      "name": "libcompositionengine_test"
+    }
+  ]
+}
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 604aa7d..f121a95 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -17,6 +17,7 @@
     defaults: ["surfaceflinger_defaults"],
     test_suites: ["device-tests"],
     srcs: [
+        "BufferGenerator.cpp",
         "Credentials_test.cpp",
         "Stress_test.cpp",
         "SurfaceInterceptor_test.cpp",
diff --git a/services/surfaceflinger/tests/BufferGenerator.cpp b/services/surfaceflinger/tests/BufferGenerator.cpp
new file mode 100644
index 0000000..8ddda60
--- /dev/null
+++ b/services/surfaceflinger/tests/BufferGenerator.cpp
@@ -0,0 +1,381 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gui/BufferItemConsumer.h>
+#include <gui/Surface.h>
+
+#include <GLES3/gl3.h>
+#include <math/vec2.h>
+#include <math/vec3.h>
+#include <math/vec4.h>
+
+#include "BufferGenerator.h"
+#include "BufferGeneratorShader.h"
+
+namespace android {
+
+/* Used to receive the surfaces and fences from egl. The egl buffers are thrown
+ * away. The fences are sent to the requester via a callback */
+class SurfaceManager {
+public:
+    /* Returns a fence from egl */
+    using BufferCallback = std::function<void(const sp<GraphicBuffer>& buffer, int32_t fence)>;
+
+    /* Listens for a new frame, detaches the buffer and returns the fence
+     * through saved callback. */
+    class BufferListener : public ConsumerBase::FrameAvailableListener {
+    public:
+        BufferListener(sp<IGraphicBufferConsumer> consumer, BufferCallback callback)
+              : mConsumer(consumer), mCallback(callback) {}
+
+        void onFrameAvailable(const BufferItem& /*item*/) {
+            BufferItem item;
+
+            if (mConsumer->acquireBuffer(&item, 0)) return;
+            if (mConsumer->detachBuffer(item.mSlot)) return;
+
+            mCallback(item.mGraphicBuffer, item.mFence->dup());
+        }
+
+    private:
+        sp<IGraphicBufferConsumer> mConsumer;
+        BufferCallback mCallback;
+    };
+
+    /* Creates a buffer listener that waits on a new frame from the buffer
+     * queue. */
+    void initialize(uint32_t width, uint32_t height, android_pixel_format_t format,
+                    BufferCallback callback) {
+        sp<IGraphicBufferProducer> producer;
+        sp<IGraphicBufferConsumer> consumer;
+        BufferQueue::createBufferQueue(&producer, &consumer);
+
+        consumer->setDefaultBufferSize(width, height);
+        consumer->setDefaultBufferFormat(format);
+
+        mBufferItemConsumer = new BufferItemConsumer(consumer, 0);
+
+        mListener = new BufferListener(consumer, callback);
+        mBufferItemConsumer->setFrameAvailableListener(mListener);
+
+        mSurface = new Surface(producer, true);
+    }
+
+    /* Used by Egl manager. The surface is never displayed. */
+    sp<Surface> getSurface() const { return mSurface; }
+
+private:
+    sp<BufferItemConsumer> mBufferItemConsumer;
+    sp<BufferListener> mListener;
+    /* Used by Egl manager. The surface is never displayed */
+    sp<Surface> mSurface;
+};
+
+/* Used to generate valid fences. It is not possible to create a dummy sync
+ * fence for testing. Egl can generate buffers along with a valid fence.
+ * The buffer cannot be guaranteed to be the same format across all devices so
+ * a CPU filled buffer is used instead. The Egl fence is used along with the
+ * CPU filled buffer. */
+class EglManager {
+public:
+    EglManager()
+          : mEglDisplay(EGL_NO_DISPLAY), mEglSurface(EGL_NO_SURFACE), mEglContext(EGL_NO_CONTEXT) {}
+
+    ~EglManager() { cleanup(); }
+
+    int initialize(sp<Surface> surface) {
+        mSurface = surface;
+
+        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+        if (mEglDisplay == EGL_NO_DISPLAY) return false;
+
+        EGLint major;
+        EGLint minor;
+        if (!eglInitialize(mEglDisplay, &major, &minor)) {
+            ALOGW("Could not initialize EGL");
+            return false;
+        }
+
+        /* We're going to use a 1x1 pbuffer surface later on
+         * The configuration distance doesn't really matter for what we're
+         * trying to do */
+        EGLint configAttrs[] = {EGL_RENDERABLE_TYPE,
+                                EGL_OPENGL_ES2_BIT,
+                                EGL_RED_SIZE,
+                                8,
+                                EGL_GREEN_SIZE,
+                                8,
+                                EGL_BLUE_SIZE,
+                                8,
+                                EGL_ALPHA_SIZE,
+                                0,
+                                EGL_DEPTH_SIZE,
+                                24,
+                                EGL_STENCIL_SIZE,
+                                0,
+                                EGL_NONE};
+
+        EGLConfig configs[1];
+        EGLint configCnt;
+        if (!eglChooseConfig(mEglDisplay, configAttrs, configs, 1, &configCnt)) {
+            ALOGW("Could not select EGL configuration");
+            eglReleaseThread();
+            eglTerminate(mEglDisplay);
+            return false;
+        }
+
+        if (configCnt <= 0) {
+            ALOGW("Could not find EGL configuration");
+            eglReleaseThread();
+            eglTerminate(mEglDisplay);
+            return false;
+        }
+
+        /* These objects are initialized below but the default "null" values are
+         * used to cleanup properly at any point in the initialization sequence */
+        EGLint attrs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
+        mEglContext = eglCreateContext(mEglDisplay, configs[0], EGL_NO_CONTEXT, attrs);
+        if (mEglContext == EGL_NO_CONTEXT) {
+            ALOGW("Could not create EGL context");
+            cleanup();
+            return false;
+        }
+
+        EGLint majorVersion;
+        if (!eglQueryContext(mEglDisplay, mEglContext, EGL_CONTEXT_CLIENT_VERSION, &majorVersion)) {
+            ALOGW("Could not query EGL version");
+            cleanup();
+            return false;
+        }
+
+        if (majorVersion != 3) {
+            ALOGW("Unsupported EGL version");
+            cleanup();
+            return false;
+        }
+
+        EGLint surfaceAttrs[] = {EGL_NONE};
+        mEglSurface = eglCreateWindowSurface(mEglDisplay, configs[0], mSurface.get(), surfaceAttrs);
+        if (mEglSurface == EGL_NO_SURFACE) {
+            ALOGW("Could not create EGL surface");
+            cleanup();
+            return false;
+        }
+
+        if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
+            ALOGW("Could not change current EGL context");
+            cleanup();
+            return false;
+        }
+
+        return true;
+    }
+
+    void makeCurrent() const { eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext); }
+
+    void present() const { eglSwapBuffers(mEglDisplay, mEglSurface); }
+
+private:
+    void cleanup() {
+        if (mEglDisplay == EGL_NO_DISPLAY) return;
+        if (mEglSurface != EGL_NO_SURFACE) eglDestroySurface(mEglDisplay, mEglSurface);
+        if (mEglContext != EGL_NO_CONTEXT) eglDestroyContext(mEglDisplay, mEglContext);
+
+        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        eglReleaseThread();
+        eglTerminate(mEglDisplay);
+    }
+
+    sp<Surface> mSurface;
+    EGLDisplay mEglDisplay;
+    EGLSurface mEglSurface;
+    EGLContext mEglContext;
+};
+
+class Program {
+public:
+    ~Program() {
+        if (mInitialized) {
+            glDetachShader(mProgram, mVertexShader);
+            glDetachShader(mProgram, mFragmentShader);
+
+            glDeleteShader(mVertexShader);
+            glDeleteShader(mFragmentShader);
+
+            glDeleteProgram(mProgram);
+        }
+    }
+
+    bool initialize(const char* vertex, const char* fragment) {
+        mVertexShader = buildShader(vertex, GL_VERTEX_SHADER);
+        if (!mVertexShader) {
+            return false;
+        }
+
+        mFragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
+        if (!mFragmentShader) {
+            return false;
+        }
+
+        mProgram = glCreateProgram();
+        glAttachShader(mProgram, mVertexShader);
+        glAttachShader(mProgram, mFragmentShader);
+
+        glLinkProgram(mProgram);
+
+        GLint status;
+        glGetProgramiv(mProgram, GL_LINK_STATUS, &status);
+        if (status != GL_TRUE) {
+            GLint length = 0;
+            glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &length);
+            if (length > 1) {
+                GLchar log[length];
+                glGetProgramInfoLog(mProgram, length, nullptr, &log[0]);
+                ALOGE("%s", log);
+            }
+            ALOGE("Error while linking shaders");
+            return false;
+        }
+        mInitialized = true;
+        return true;
+    }
+
+    void use() const { glUseProgram(mProgram); }
+
+    void bindVec4(GLint location, vec4 v) const { glUniform4f(location, v.x, v.y, v.z, v.w); }
+
+    void bindVec3(GLint location, const vec3* v, uint32_t count) const {
+        glUniform3fv(location, count, &(v->x));
+    }
+
+    void bindFloat(GLint location, float v) { glUniform1f(location, v); }
+
+private:
+    GLuint buildShader(const char* source, GLenum type) const {
+        GLuint shader = glCreateShader(type);
+        glShaderSource(shader, 1, &source, nullptr);
+        glCompileShader(shader);
+
+        GLint status;
+        glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+        if (status != GL_TRUE) {
+            ALOGE("Error while compiling shader of type 0x%x:\n===\n%s\n===", type, source);
+            // Some drivers return wrong values for GL_INFO_LOG_LENGTH
+            // use a fixed size instead
+            GLchar log[512];
+            glGetShaderInfoLog(shader, sizeof(log), nullptr, &log[0]);
+            ALOGE("Shader info log: %s", log);
+            return 0;
+        }
+
+        return shader;
+    }
+
+    GLuint mProgram = 0;
+    GLuint mVertexShader = 0;
+    GLuint mFragmentShader = 0;
+    bool mInitialized = false;
+};
+
+BufferGenerator::BufferGenerator()
+      : mSurfaceManager(new SurfaceManager), mEglManager(new EglManager), mProgram(new Program) {
+    const float width = 1000.0;
+    const float height = 1000.0;
+
+    auto setBufferWithContext =
+            std::bind(setBuffer, std::placeholders::_1, std::placeholders::_2, this);
+    mSurfaceManager->initialize(width, height, HAL_PIXEL_FORMAT_RGBA_8888, setBufferWithContext);
+
+    if (!mEglManager->initialize(mSurfaceManager->getSurface())) return;
+
+    mEglManager->makeCurrent();
+
+    if (!mProgram->initialize(VERTEX_SHADER, FRAGMENT_SHADER)) return;
+    mProgram->use();
+    mProgram->bindVec4(0, vec4{width, height, 1.0f / width, 1.0f / height});
+    mProgram->bindVec3(2, &SPHERICAL_HARMONICS[0], 4);
+
+    glEnableVertexAttribArray(0);
+    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, &TRIANGLE[0]);
+
+    mInitialized = true;
+}
+
+BufferGenerator::~BufferGenerator() {
+    mEglManager->makeCurrent();
+}
+
+status_t BufferGenerator::get(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) {
+    // mMutex is used to protect get() from getting called by multiple threads at the same time
+    static std::mutex mMutex;
+    std::lock_guard lock(mMutex);
+
+    if (!mInitialized) {
+        if (outBuffer) {
+            *outBuffer = nullptr;
+        }
+        if (*outFence) {
+            *outFence = nullptr;
+        }
+        return -EINVAL;
+    }
+
+    // Generate a buffer and fence. They will be returned through the setBuffer callback
+    mEglManager->makeCurrent();
+
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    const std::chrono::duration<float> time = std::chrono::steady_clock::now() - mEpoch;
+    mProgram->bindFloat(1, time.count());
+
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+
+    mPending = true;
+    mEglManager->present();
+
+    // Wait for the setBuffer callback
+    if (!mConditionVariable.wait_for(mMutex, std::chrono::seconds(2),
+                                     [this] { return !mPending; })) {
+        ALOGE("failed to set buffer and fence");
+        return -ETIME;
+    }
+
+    // Return buffer and fence
+    if (outBuffer) {
+        *outBuffer = mGraphicBuffer;
+    }
+    if (outFence) {
+        *outFence = new Fence(mFence);
+    } else {
+        close(mFence);
+    }
+    mGraphicBuffer = nullptr;
+    mFence = -1;
+
+    return NO_ERROR;
+}
+
+// static
+void BufferGenerator::setBuffer(const sp<GraphicBuffer>& buffer, int32_t fence,
+                                void* bufferGenerator) {
+    BufferGenerator* generator = static_cast<BufferGenerator*>(bufferGenerator);
+    generator->mGraphicBuffer = buffer;
+    generator->mFence = fence;
+    generator->mPending = false;
+    generator->mConditionVariable.notify_all();
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/BufferGenerator.h b/services/surfaceflinger/tests/BufferGenerator.h
new file mode 100644
index 0000000..a3ffe86
--- /dev/null
+++ b/services/surfaceflinger/tests/BufferGenerator.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <condition_variable>
+#include <mutex>
+
+#include <ui/GraphicBuffer.h>
+
+namespace android {
+
+class SurfaceManager;
+class EglManager;
+class Program;
+
+class BufferGenerator {
+public:
+    BufferGenerator();
+    ~BufferGenerator();
+
+    /* Get a new fence */
+    status_t get(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence);
+
+    /* Static callback that sets the fence on a particular instance */
+    static void setBuffer(const sp<GraphicBuffer>& buffer, int32_t fence, void* fenceGenerator);
+
+private:
+    bool mInitialized = false;
+
+    std::unique_ptr<SurfaceManager> mSurfaceManager;
+    std::unique_ptr<EglManager> mEglManager;
+    std::unique_ptr<Program> mProgram;
+
+    std::condition_variable_any mConditionVariable;
+
+    sp<GraphicBuffer> mGraphicBuffer;
+    int32_t mFence = -1;
+    bool mPending = false;
+
+    using Epoch = std::chrono::time_point<std::chrono::steady_clock>;
+    Epoch mEpoch = std::chrono::steady_clock::now();
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/BufferGeneratorShader.h b/services/surfaceflinger/tests/BufferGeneratorShader.h
new file mode 100644
index 0000000..564cda3
--- /dev/null
+++ b/services/surfaceflinger/tests/BufferGeneratorShader.h
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <GLES3/gl3.h>
+#include <math/vec2.h>
+#include <math/vec3.h>
+#include <math/vec4.h>
+
+static const char* VERTEX_SHADER = R"SHADER__(#version 300 es
+precision highp float;
+
+layout(location = 0) in vec4 mesh_position;
+
+void main() {
+    gl_Position = mesh_position;
+}
+)SHADER__";
+
+static const char* FRAGMENT_SHADER = R"SHADER__(#version 300 es
+precision highp float;
+
+layout(location = 0) uniform vec4 resolution;
+layout(location = 1) uniform float time;
+layout(location = 2) uniform vec3[4] SPHERICAL_HARMONICS;
+
+layout(location = 0) out vec4 fragColor;
+
+#define saturate(x) clamp(x, 0.0, 1.0)
+#define PI 3.14159265359
+
+//------------------------------------------------------------------------------
+// Distance field functions
+//------------------------------------------------------------------------------
+
+float sdPlane(in vec3 p) {
+    return p.y;
+}
+
+float sdSphere(in vec3 p, float s) {
+    return length(p) - s;
+}
+
+float sdTorus(in vec3 p, in vec2 t) {
+    return length(vec2(length(p.xz) - t.x, p.y)) - t.y;
+}
+
+vec2 opUnion(vec2 d1, vec2 d2) {
+    return d1.x < d2.x ? d1 : d2;
+}
+
+vec2 scene(in vec3 position) {
+    vec2 scene = opUnion(
+          vec2(sdPlane(position), 1.0),
+          vec2(sdSphere(position - vec3(0.0, 0.4, 0.0), 0.4), 12.0)
+    );
+    return scene;
+}
+
+//------------------------------------------------------------------------------
+// Ray casting
+//------------------------------------------------------------------------------
+
+float shadow(in vec3 origin, in vec3 direction, in float tmin, in float tmax) {
+    float hit = 1.0;
+
+    for (float t = tmin; t < tmax; ) {
+        float h = scene(origin + direction * t).x;
+        if (h < 0.001) return 0.0;
+        t += h;
+        hit = min(hit, 10.0 * h / t);
+    }
+
+    return clamp(hit, 0.0, 1.0);
+}
+
+vec2 traceRay(in vec3 origin, in vec3 direction) {
+    float tmin = 0.02;
+    float tmax = 20.0;
+
+    float material = -1.0;
+    float t = tmin;
+
+    for ( ; t < tmax; ) {
+        vec2 hit = scene(origin + direction * t);
+        if (hit.x < 0.002 || t > tmax) break;
+        t += hit.x;
+        material = hit.y;
+    }
+
+    if (t > tmax) {
+        material = -1.0;
+    }
+
+    return vec2(t, material);
+}
+
+vec3 normal(in vec3 position) {
+    vec3 epsilon = vec3(0.001, 0.0, 0.0);
+    vec3 n = vec3(
+          scene(position + epsilon.xyy).x - scene(position - epsilon.xyy).x,
+          scene(position + epsilon.yxy).x - scene(position - epsilon.yxy).x,
+          scene(position + epsilon.yyx).x - scene(position - epsilon.yyx).x);
+    return normalize(n);
+}
+
+//------------------------------------------------------------------------------
+// BRDF
+//------------------------------------------------------------------------------
+
+float pow5(float x) {
+    float x2 = x * x;
+    return x2 * x2 * x;
+}
+
+float D_GGX(float linearRoughness, float NoH, const vec3 h) {
+    // Walter et al. 2007, "Microfacet Models for Refraction through Rough Surfaces"
+    float oneMinusNoHSquared = 1.0 - NoH * NoH;
+    float a = NoH * linearRoughness;
+    float k = linearRoughness / (oneMinusNoHSquared + a * a);
+    float d = k * k * (1.0 / PI);
+    return d;
+}
+
+float V_SmithGGXCorrelated(float linearRoughness, float NoV, float NoL) {
+    // Heitz 2014, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs"
+    float a2 = linearRoughness * linearRoughness;
+    float GGXV = NoL * sqrt((NoV - a2 * NoV) * NoV + a2);
+    float GGXL = NoV * sqrt((NoL - a2 * NoL) * NoL + a2);
+    return 0.5 / (GGXV + GGXL);
+}
+
+vec3 F_Schlick(const vec3 f0, float VoH) {
+    // Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"
+    return f0 + (vec3(1.0) - f0) * pow5(1.0 - VoH);
+}
+
+float F_Schlick(float f0, float f90, float VoH) {
+    return f0 + (f90 - f0) * pow5(1.0 - VoH);
+}
+
+float Fd_Burley(float linearRoughness, float NoV, float NoL, float LoH) {
+    // Burley 2012, "Physically-Based Shading at Disney"
+    float f90 = 0.5 + 2.0 * linearRoughness * LoH * LoH;
+    float lightScatter = F_Schlick(1.0, f90, NoL);
+    float viewScatter  = F_Schlick(1.0, f90, NoV);
+    return lightScatter * viewScatter * (1.0 / PI);
+}
+
+float Fd_Lambert() {
+    return 1.0 / PI;
+}
+
+//------------------------------------------------------------------------------
+// Indirect lighting
+//------------------------------------------------------------------------------
+
+vec3 Irradiance_SphericalHarmonics(const vec3 n) {
+    return max(
+          SPHERICAL_HARMONICS[0]
+        + SPHERICAL_HARMONICS[1] * (n.y)
+        + SPHERICAL_HARMONICS[2] * (n.z)
+        + SPHERICAL_HARMONICS[3] * (n.x)
+        , 0.0);
+}
+
+vec2 PrefilteredDFG_Karis(float roughness, float NoV) {
+    // Karis 2014, "Physically Based Material on Mobile"
+    const vec4 c0 = vec4(-1.0, -0.0275, -0.572,  0.022);
+    const vec4 c1 = vec4( 1.0,  0.0425,  1.040, -0.040);
+
+    vec4 r = roughness * c0 + c1;
+    float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y;
+
+    return vec2(-1.04, 1.04) * a004 + r.zw;
+}
+
+//------------------------------------------------------------------------------
+// Tone mapping and transfer functions
+//------------------------------------------------------------------------------
+
+vec3 Tonemap_ACES(const vec3 x) {
+    // Narkowicz 2015, "ACES Filmic Tone Mapping Curve"
+    const float a = 2.51;
+    const float b = 0.03;
+    const float c = 2.43;
+    const float d = 0.59;
+    const float e = 0.14;
+    return (x * (a * x + b)) / (x * (c * x + d) + e);
+}
+
+vec3 OECF_sRGBFast(const vec3 linear) {
+    return pow(linear, vec3(1.0 / 2.2));
+}
+
+//------------------------------------------------------------------------------
+// Rendering
+//------------------------------------------------------------------------------
+
+vec3 render(in vec3 origin, in vec3 direction, out float distance) {
+    // Sky gradient
+    vec3 color = vec3(0.65, 0.85, 1.0) + direction.y * 0.72;
+
+    // (distance, material)
+    vec2 hit = traceRay(origin, direction);
+    distance = hit.x;
+    float material = hit.y;
+
+    // We've hit something in the scene
+    if (material > 0.0) {
+        vec3 position = origin + distance * direction;
+
+        vec3 v = normalize(-direction);
+        vec3 n = normal(position);
+        vec3 l = normalize(vec3(0.6, 0.7, -0.7));
+        vec3 h = normalize(v + l);
+        vec3 r = normalize(reflect(direction, n));
+
+        float NoV = abs(dot(n, v)) + 1e-5;
+        float NoL = saturate(dot(n, l));
+        float NoH = saturate(dot(n, h));
+        float LoH = saturate(dot(l, h));
+
+        vec3 baseColor = vec3(0.0);
+        float roughness = 0.0;
+        float metallic = 0.0;
+
+        float intensity = 2.0;
+        float indirectIntensity = 0.64;
+
+        if (material < 4.0)  {
+            // Checkerboard floor
+            float f = mod(floor(6.0 * position.z) + floor(6.0 * position.x), 2.0);
+            baseColor = 0.4 + f * vec3(0.6);
+            roughness = 0.1;
+        } else if (material < 16.0) {
+            // Metallic objects
+            baseColor = vec3(0.3, 0.0, 0.0);
+            roughness = 0.2;
+        }
+
+        float linearRoughness = roughness * roughness;
+        vec3 diffuseColor = (1.0 - metallic) * baseColor.rgb;
+        vec3 f0 = 0.04 * (1.0 - metallic) + baseColor.rgb * metallic;
+
+        float attenuation = shadow(position, l, 0.02, 2.5);
+
+        // specular BRDF
+        float D = D_GGX(linearRoughness, NoH, h);
+        float V = V_SmithGGXCorrelated(linearRoughness, NoV, NoL);
+        vec3  F = F_Schlick(f0, LoH);
+        vec3 Fr = (D * V) * F;
+
+        // diffuse BRDF
+        vec3 Fd = diffuseColor * Fd_Burley(linearRoughness, NoV, NoL, LoH);
+
+        color = Fd + Fr;
+        color *= (intensity * attenuation * NoL) * vec3(0.98, 0.92, 0.89);
+
+        // diffuse indirect
+        vec3 indirectDiffuse = Irradiance_SphericalHarmonics(n) * Fd_Lambert();
+
+        vec2 indirectHit = traceRay(position, r);
+        vec3 indirectSpecular = vec3(0.65, 0.85, 1.0) + r.y * 0.72;
+        if (indirectHit.y > 0.0) {
+            if (indirectHit.y < 4.0)  {
+                vec3 indirectPosition = position + indirectHit.x * r;
+                // Checkerboard floor
+                float f = mod(floor(6.0 * indirectPosition.z) + floor(6.0 * indirectPosition.x), 2.0);
+                indirectSpecular = 0.4 + f * vec3(0.6);
+            } else if (indirectHit.y < 16.0) {
+                // Metallic objects
+                indirectSpecular = vec3(0.3, 0.0, 0.0);
+            }
+        }
+
+        // indirect contribution
+        vec2 dfg = PrefilteredDFG_Karis(roughness, NoV);
+        vec3 specularColor = f0 * dfg.x + dfg.y;
+        vec3 ibl = diffuseColor * indirectDiffuse + indirectSpecular * specularColor;
+
+        color += ibl * indirectIntensity;
+    }
+
+    return color;
+}
+
+//------------------------------------------------------------------------------
+// Setup and execution
+//------------------------------------------------------------------------------
+
+mat3 setCamera(in vec3 origin, in vec3 target, float rotation) {
+    vec3 forward = normalize(target - origin);
+    vec3 orientation = vec3(sin(rotation), cos(rotation), 0.0);
+    vec3 left = normalize(cross(forward, orientation));
+    vec3 up = normalize(cross(left, forward));
+    return mat3(left, up, forward);
+}
+
+void main() {
+    // Normalized coordinates
+    vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;
+    // Aspect ratio
+    p.x *= resolution.x / resolution.y;
+
+    // Camera position and "look at"
+    vec3 origin = vec3(0.0, 1.0, 0.0);
+    vec3 target = vec3(0.0);
+
+    origin.x += 2.0 * cos(time * 0.2);
+    origin.z += 2.0 * sin(time * 0.2);
+
+    mat3 toWorld = setCamera(origin, target, 0.0);
+    vec3 direction = toWorld * normalize(vec3(p.xy, 2.0));
+
+    // Render scene
+    float distance;
+    vec3 color = render(origin, direction, distance);
+
+    // Tone mapping
+    color = Tonemap_ACES(color);
+
+    // Exponential distance fog
+    color = mix(color, 0.8 * vec3(0.7, 0.8, 1.0), 1.0 - exp2(-0.011 * distance * distance));
+
+    // Gamma compression
+    color = OECF_sRGBFast(color);
+
+    fragColor = vec4(color, 1.0);
+}
+)SHADER__";
+
+static const android::vec3 SPHERICAL_HARMONICS[4] =
+        {{0.754554516862612, 0.748542953903366, 0.790921515418539},
+         {-0.083856548007422, 0.092533500963210, 0.322764661032516},
+         {0.308152705331738, 0.366796330467391, 0.466698181299906},
+         {-0.188884931542396, -0.277402551592231, -0.377844212327557}};
+
+static const android::vec4 TRIANGLE[3] = {{-1.0f, -1.0f, 1.0f, 1.0f},
+                                          {3.0f, -1.0f, 1.0f, 1.0f},
+                                          {-1.0f, 3.0f, 1.0f, 1.0f}};
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index a73ec6c..8560f5e 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -162,10 +162,10 @@
     setSystemUID();
     ASSERT_NO_FATAL_FAILURE(initClient());
 
-    // No one else can init the client.
+    // Anyone else can init the client.
     setBinUID();
     mComposerClient = new SurfaceComposerClient;
-    ASSERT_EQ(NO_INIT, mComposerClient->initCheck());
+    ASSERT_NO_FATAL_FAILURE(initClient());
 }
 
 TEST_F(CredentialsTest, GetBuiltInDisplayAccessTest) {
@@ -222,22 +222,6 @@
     ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
 }
 
-TEST_F(CredentialsTest, CreateSurfaceTest) {
-    sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
-    DisplayInfo info;
-    SurfaceComposerClient::getDisplayInfo(display, &info);
-    const ssize_t displayWidth = info.w;
-    const ssize_t displayHeight = info.h;
-
-    std::function<bool()> condition = [=]() {
-        mBGSurfaceControl =
-                mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
-                                               PIXEL_FORMAT_RGBA_8888, 0);
-        return mBGSurfaceControl != nullptr && mBGSurfaceControl->isValid();
-    };
-    ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
-}
-
 TEST_F(CredentialsTest, CreateDisplayTest) {
     std::function<bool()> condition = [=]() {
         sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
diff --git a/services/surfaceflinger/tests/Stress_test.cpp b/services/surfaceflinger/tests/Stress_test.cpp
index 3e1be8e..89c26f4 100644
--- a/services/surfaceflinger/tests/Stress_test.cpp
+++ b/services/surfaceflinger/tests/Stress_test.cpp
@@ -34,7 +34,7 @@
             auto surf = client->createSurface(String8("t"), 100, 100,
                     PIXEL_FORMAT_RGBA_8888, 0);
             ASSERT_TRUE(surf != nullptr);
-            client->destroySurface(surf->getHandle());
+            surf->clear();
         }
     };
 
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index e506757..8ec3e15 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -806,18 +806,6 @@
             Increment::IncrementCase::kSurfaceCreation);
 }
 
-TEST_F(SurfaceInterceptorTest, InterceptSurfaceDeletionWorks) {
-    enableInterceptor();
-    sp<SurfaceControl> layerToDelete = mComposerClient->createSurface(String8(LAYER_NAME),
-            SIZE_UPDATE, SIZE_UPDATE, PIXEL_FORMAT_RGBA_8888, 0);
-    mComposerClient->destroySurface(layerToDelete->getHandle());
-    disableInterceptor();
-
-    Trace capturedTrace;
-    ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
-    ASSERT_TRUE(singleIncrementFound(capturedTrace, Increment::IncrementCase::kSurfaceDeletion));
-}
-
 TEST_F(SurfaceInterceptorTest, InterceptDisplayCreationWorks) {
     captureTest(&SurfaceInterceptorTest::displayCreation,
             Increment::IncrementCase::kDisplayCreation);
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 037d32f..ef6999d 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -28,7 +28,6 @@
 
 #include <gui/ISurfaceComposer.h>
 #include <gui/LayerState.h>
-
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 #include <private/gui/ComposerService.h>
@@ -41,6 +40,8 @@
 #include <math.h>
 #include <math/vec3.h>
 
+#include "BufferGenerator.h"
+
 namespace android {
 
 namespace {
@@ -301,7 +302,7 @@
 
     void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); }
 
-    ScreenCapture(const sp<GraphicBuffer>& outBuffer) : mOutBuffer(outBuffer) {
+    explicit ScreenCapture(const sp<GraphicBuffer>& outBuffer) : mOutBuffer(outBuffer) {
         mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels));
     }
 
@@ -478,6 +479,11 @@
         return screenshot;
     }
 
+    static status_t getBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) {
+        static BufferGenerator bufferGenerator;
+        return bufferGenerator.get(outBuffer, outFence);
+    }
+
     sp<SurfaceComposerClient> mClient;
 
     sp<IBinder> mDisplay;
@@ -1017,7 +1023,7 @@
             .setRelativeLayer(layerG, layerR->getHandle(), 1)
             .apply();
 
-    mClient->destroySurface(layerG->getHandle());
+    layerG->clear();
     // layerG should have been removed
     screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
 }
@@ -2164,6 +2170,36 @@
 
 TEST_F(LayerTransactionTest, SetFenceBasic_BufferState) {
     sp<SurfaceControl> layer;
+    Transaction transaction;
+    ASSERT_NO_FATAL_FAILURE(
+            layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+    sp<GraphicBuffer> buffer =
+            new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+                              BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                      BufferUsage::COMPOSER_OVERLAY,
+                              "test");
+    fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+
+    sp<Fence> fence;
+    if (getBuffer(nullptr, &fence) != NO_ERROR) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+
+    Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply();
+
+    status_t status = fence->wait(1000);
+    ASSERT_NE(static_cast<status_t>(Fence::Status::Unsignaled), status);
+    std::this_thread::sleep_for(200ms);
+
+    auto shot = screenshot();
+    shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetFenceNull_BufferState) {
+    sp<SurfaceControl> layer;
     ASSERT_NO_FATAL_FAILURE(
             layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
 
@@ -2514,7 +2550,7 @@
     }
 
     void addSurface(ExpectedResult::Transaction transactionResult, const sp<SurfaceControl>& layer,
-                    ExpectedResult::Buffer bufferResult = NOT_ACQUIRED,
+                    ExpectedResult::Buffer bufferResult = ACQUIRED,
                     ExpectedResult::PreviousBuffer previousBufferResult = NOT_RELEASED) {
         mTransactionResult = transactionResult;
         mExpectedSurfaceResults.emplace(std::piecewise_construct,
@@ -2524,7 +2560,7 @@
 
     void addSurfaces(ExpectedResult::Transaction transactionResult,
                      const std::vector<sp<SurfaceControl>>& layers,
-                     ExpectedResult::Buffer bufferResult = NOT_ACQUIRED,
+                     ExpectedResult::Buffer bufferResult = ACQUIRED,
                      ExpectedResult::PreviousBuffer previousBufferResult = NOT_RELEASED) {
         for (const auto& layer : layers) {
             addSurface(transactionResult, layer, bufferResult, previousBufferResult);
@@ -2631,24 +2667,22 @@
         return createLayer(mClient, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState);
     }
 
-    static void fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper,
-                                const sp<SurfaceControl>& layer = nullptr) {
+    static int fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper,
+                               const sp<SurfaceControl>& layer = nullptr) {
         if (layer) {
-            sp<GraphicBuffer> buffer =
-                    new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
-                                      BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
-                                              BufferUsage::COMPOSER_OVERLAY |
-                                              BufferUsage::GPU_TEXTURE,
-                                      "test");
-            fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
-
-            sp<Fence> fence = new Fence(-1);
+            sp<GraphicBuffer> buffer;
+            sp<Fence> fence;
+            int err = getBuffer(&buffer, &fence);
+            if (err != NO_ERROR) {
+                return err;
+            }
 
             transaction.setBuffer(layer, buffer).setAcquireFence(layer, fence);
         }
 
         transaction.addTransactionCompletedCallback(callbackHelper->function,
                                                     callbackHelper->getContext());
+        return NO_ERROR;
     }
 
     static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult,
@@ -2680,7 +2714,11 @@
 
     Transaction transaction;
     CallbackHelper callback;
-    fillTransaction(transaction, &callback, layer);
+    int err = fillTransaction(transaction, &callback, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction.apply();
 
@@ -2695,19 +2733,28 @@
 
     Transaction transaction;
     CallbackHelper callback;
-    fillTransaction(transaction, &callback);
+    int err = fillTransaction(transaction, &callback);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
 
     ExpectedResult expected;
-    expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer);
+    expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer,
+                        ExpectedResult::Buffer::NOT_ACQUIRED);
     EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
 }
 
 TEST_F(LayerCallbackTest, NoStateChange) {
     Transaction transaction;
     CallbackHelper callback;
-    fillTransaction(transaction, &callback);
+    int err = fillTransaction(transaction, &callback);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction.apply();
 
@@ -2721,7 +2768,11 @@
 
     Transaction transaction;
     CallbackHelper callback;
-    fillTransaction(transaction, &callback, layer);
+    int err = fillTransaction(transaction, &callback, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply();
 
@@ -2737,8 +2788,16 @@
 
     Transaction transaction1, transaction2;
     CallbackHelper callback1, callback2;
-    fillTransaction(transaction1, &callback1, layer1);
-    fillTransaction(transaction2, &callback2, layer2);
+    int err = fillTransaction(transaction1, &callback1, layer1);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    err = fillTransaction(transaction2, &callback2, layer2);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
     transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
@@ -2756,8 +2815,16 @@
 
     Transaction transaction1, transaction2;
     CallbackHelper callback;
-    fillTransaction(transaction1, &callback, layer1);
-    fillTransaction(transaction2, &callback, layer2);
+    int err = fillTransaction(transaction1, &callback, layer1);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    err = fillTransaction(transaction2, &callback, layer2);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction2.merge(std::move(transaction1)).apply();
 
@@ -2773,8 +2840,16 @@
 
     Transaction transaction1, transaction2;
     CallbackHelper callback1, callback2;
-    fillTransaction(transaction1, &callback1, layer);
-    fillTransaction(transaction2, &callback2, layer);
+    int err = fillTransaction(transaction1, &callback1, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    err = fillTransaction(transaction2, &callback2, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction2.merge(std::move(transaction1)).apply();
 
@@ -2784,25 +2859,6 @@
     EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
 }
 
-TEST_F(LayerCallbackTest, Merge_SingleBuffer) {
-    sp<SurfaceControl> layer1, layer2;
-    ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
-    ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
-
-    Transaction transaction1, transaction2;
-    CallbackHelper callback1, callback2;
-    fillTransaction(transaction1, &callback1, layer1);
-    fillTransaction(transaction2, &callback2);
-
-    transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
-    transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
-
-    ExpectedResult expected;
-    expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
-    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
-    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
-}
-
 TEST_F(LayerCallbackTest, Merge_DifferentClients) {
     sp<SurfaceComposerClient> client1(new SurfaceComposerClient),
             client2(new SurfaceComposerClient);
@@ -2818,8 +2874,16 @@
 
     Transaction transaction1, transaction2;
     CallbackHelper callback1, callback2;
-    fillTransaction(transaction1, &callback1, layer1);
-    fillTransaction(transaction2, &callback2, layer2);
+    int err = fillTransaction(transaction1, &callback1, layer1);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    err = fillTransaction(transaction2, &callback2, layer2);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
     transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
@@ -2837,13 +2901,17 @@
     Transaction transaction;
     CallbackHelper callback;
     for (size_t i = 0; i < 10; i++) {
-        fillTransaction(transaction, &callback, layer);
+        int err = fillTransaction(transaction, &callback, layer);
+        if (err) {
+            GTEST_SUCCEED() << "test not supported";
+            return;
+        }
 
         transaction.apply();
 
         ExpectedResult expected;
         expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
-                            ExpectedResult::Buffer::NOT_ACQUIRED,
+                            ExpectedResult::Buffer::ACQUIRED,
                             (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED
                                      : ExpectedResult::PreviousBuffer::RELEASED);
         EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected));
@@ -2861,10 +2929,18 @@
         ExpectedResult expected;
 
         if (i == 0) {
-            fillTransaction(transaction, &callback, layer);
+            int err = fillTransaction(transaction, &callback, layer);
+            if (err) {
+                GTEST_SUCCEED() << "test not supported";
+                return;
+            }
             expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
         } else {
-            fillTransaction(transaction, &callback);
+            int err = fillTransaction(transaction, &callback);
+            if (err) {
+                GTEST_SUCCEED() << "test not supported";
+                return;
+            }
         }
 
         transaction.apply();
@@ -2882,9 +2958,17 @@
     CallbackHelper callback;
     for (size_t i = 0; i < 10; i++) {
         if (i == 0) {
-            fillTransaction(transaction, &callback, layer);
+            int err = fillTransaction(transaction, &callback, layer);
+            if (err) {
+                GTEST_SUCCEED() << "test not supported";
+                return;
+            }
         } else {
-            fillTransaction(transaction, &callback);
+            int err = fillTransaction(transaction, &callback);
+            if (err) {
+                GTEST_SUCCEED() << "test not supported";
+                return;
+            }
         }
 
         transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
@@ -2892,7 +2976,9 @@
         ExpectedResult expected;
         expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED
                                      : ExpectedResult::Transaction::NOT_PRESENTED,
-                            layer);
+                            layer,
+                            (i == 0) ? ExpectedResult::Buffer::ACQUIRED
+                                     : ExpectedResult::Buffer::NOT_ACQUIRED);
         EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, i == 0));
     }
     ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState());
@@ -2906,15 +2992,23 @@
     Transaction transaction1, transaction2;
     CallbackHelper callback1, callback2;
     for (size_t i = 0; i < 10; i++) {
-        fillTransaction(transaction1, &callback1, layer1);
-        fillTransaction(transaction2, &callback2, layer2);
+        int err = fillTransaction(transaction1, &callback1, layer1);
+        if (err) {
+            GTEST_SUCCEED() << "test not supported";
+            return;
+        }
+        err = fillTransaction(transaction2, &callback2, layer2);
+        if (err) {
+            GTEST_SUCCEED() << "test not supported";
+            return;
+        }
 
         transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
         transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
 
         ExpectedResult expected;
         expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
-                             ExpectedResult::Buffer::NOT_ACQUIRED,
+                             ExpectedResult::Buffer::ACQUIRED,
                              (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED
                                       : ExpectedResult::PreviousBuffer::RELEASED);
         EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected));
@@ -2939,15 +3033,23 @@
     Transaction transaction1, transaction2;
     CallbackHelper callback1, callback2;
     for (size_t i = 0; i < 10; i++) {
-        fillTransaction(transaction1, &callback1, layer1);
-        fillTransaction(transaction2, &callback2, layer2);
+        int err = fillTransaction(transaction1, &callback1, layer1);
+        if (err) {
+            GTEST_SUCCEED() << "test not supported";
+            return;
+        }
+        err = fillTransaction(transaction2, &callback2, layer2);
+        if (err) {
+            GTEST_SUCCEED() << "test not supported";
+            return;
+        }
 
         transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
         transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
 
         ExpectedResult expected;
         expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
-                             ExpectedResult::Buffer::NOT_ACQUIRED,
+                             ExpectedResult::Buffer::ACQUIRED,
                              (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED
                                       : ExpectedResult::PreviousBuffer::RELEASED);
         EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected));
@@ -2973,8 +3075,16 @@
     CallbackHelper callback1, callback2;
 
     // Normal call to set up test
-    fillTransaction(transaction1, &callback1, layer1);
-    fillTransaction(transaction2, &callback2, layer2);
+    int err = fillTransaction(transaction1, &callback1, layer1);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    err = fillTransaction(transaction2, &callback2, layer2);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
     transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
@@ -2986,8 +3096,16 @@
     expected.reset();
 
     // Test
-    fillTransaction(transaction1, &callback1);
-    fillTransaction(transaction2, &callback2);
+    err = fillTransaction(transaction1, &callback1);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    err = fillTransaction(transaction2, &callback2);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction2.merge(std::move(transaction1)).apply();
 
@@ -3012,8 +3130,16 @@
     CallbackHelper callback1, callback2;
 
     // Normal call to set up test
-    fillTransaction(transaction1, &callback1, layer1);
-    fillTransaction(transaction2, &callback2, layer2);
+    int err = fillTransaction(transaction1, &callback1, layer1);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    err = fillTransaction(transaction2, &callback2, layer2);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
     transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
@@ -3025,12 +3151,21 @@
     expected.reset();
 
     // Test
-    fillTransaction(transaction1, &callback1);
-    fillTransaction(transaction2, &callback2);
+    err = fillTransaction(transaction1, &callback1);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    err = fillTransaction(transaction2, &callback2);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
 
-    expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2);
+    expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2,
+                        ExpectedResult::Buffer::NOT_ACQUIRED);
     EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
     EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
 }
@@ -3047,13 +3182,16 @@
     for (auto& expected : expectedResults) {
         expected.reset();
         expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
-                            ExpectedResult::Buffer::NOT_ACQUIRED, previousBufferResult);
+                            ExpectedResult::Buffer::ACQUIRED, previousBufferResult);
         previousBufferResult = ExpectedResult::PreviousBuffer::RELEASED;
 
-        fillTransaction(transaction, &callback, layer);
+        int err = fillTransaction(transaction, &callback, layer);
+        if (err) {
+            GTEST_SUCCEED() << "test not supported";
+            return;
+        }
 
         transaction.apply();
-        std::this_thread::sleep_for(200ms);
     }
     EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
 }
@@ -3062,23 +3200,33 @@
     sp<SurfaceControl> layer;
     ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
 
+    // Normal call to set up test
     Transaction transaction;
     CallbackHelper callback;
+    int err = fillTransaction(transaction, &callback, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+
+    transaction.apply();
+
+    ExpectedResult expected;
+    expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+
+    // Test
     std::vector<ExpectedResult> expectedResults(50);
-    bool first = true;
     for (auto& expected : expectedResults) {
         expected.reset();
 
-        if (first) {
-            fillTransaction(transaction, &callback, layer);
-            expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
-            first = false;
-        } else {
-            fillTransaction(transaction, &callback);
+        err = fillTransaction(transaction, &callback);
+        if (err) {
+            GTEST_SUCCEED() << "test not supported";
+            return;
         }
 
         transaction.apply();
-        std::this_thread::sleep_for(200ms);
     }
     EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
 }
@@ -3090,7 +3238,11 @@
     // Normal call to set up test
     Transaction transaction;
     CallbackHelper callback;
-    fillTransaction(transaction, &callback, layer);
+    int err = fillTransaction(transaction, &callback, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
 
@@ -3102,13 +3254,16 @@
     std::vector<ExpectedResult> expectedResults(50);
     for (auto& expected : expectedResults) {
         expected.reset();
-        expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer);
+        expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer,
+                            ExpectedResult::Buffer::NOT_ACQUIRED);
 
-        fillTransaction(transaction, &callback);
+        err = fillTransaction(transaction, &callback);
+        if (err) {
+            GTEST_SUCCEED() << "test not supported";
+            return;
+        }
 
         transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
-
-        std::this_thread::sleep_for(200ms);
     }
     EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
 }
@@ -3875,9 +4030,9 @@
     asTransaction([&](Transaction& t) { t.reparent(mChild, nullptr); });
     {
         mCapture = screenshot();
-        // Nothing should have changed.
+        // The surface should now be offscreen.
         mCapture->expectFGColor(64, 64);
-        mCapture->expectChildColor(74, 74);
+        mCapture->expectFGColor(74, 74);
         mCapture->expectFGColor(84, 84);
     }
 }
@@ -4455,7 +4610,7 @@
     ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
 
     auto redLayerHandle = redLayer->getHandle();
-    mClient->destroySurface(redLayerHandle);
+    redLayer->clear();
     SurfaceComposerClient::Transaction().apply(true);
 
     sp<GraphicBuffer> outBuffer;
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
index 973156a..eeb6efe 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
@@ -81,7 +81,7 @@
 
 class DelayedEventGenerator {
 public:
-    DelayedEventGenerator(std::function<void()> onTimerExpired)
+    explicit DelayedEventGenerator(std::function<void()> onTimerExpired)
           : mOnTimerExpired(onTimerExpired), mThread([this]() { loop(); }) {}
 
     ~DelayedEventGenerator() {
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerService.h b/services/surfaceflinger/tests/fakehwc/FakeComposerService.h
index c439b7e..a3fb8a6 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerService.h
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerService.h
@@ -26,7 +26,7 @@
 
 class FakeComposerService : public IComposer {
 public:
-    FakeComposerService(android::sp<ComposerClient>& client);
+    explicit FakeComposerService(android::sp<ComposerClient>& client);
     virtual ~FakeComposerService();
 
     Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
index 1258a97..7d20d3c 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.h
@@ -100,10 +100,7 @@
  */
 class TransactionScope : public android::SurfaceComposerClient::Transaction {
 public:
-    TransactionScope(FakeComposerClient& composer) :
-            Transaction(),
-            mComposer(composer) {
-    }
+    explicit TransactionScope(FakeComposerClient& composer) : Transaction(), mComposer(composer) {}
 
     ~TransactionScope() {
         int frameCount = mComposer.getFrameCount();
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
index d7082f3..06ae314 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
@@ -171,7 +171,7 @@
 
 class Hwc2TestBlendMode : public Hwc2TestProperty<hwc2_blend_mode_t> {
 public:
-    Hwc2TestBlendMode(Hwc2TestCoverage coverage);
+    explicit Hwc2TestBlendMode(Hwc2TestCoverage coverage);
 
     std::string dump() const override;
 
@@ -192,8 +192,8 @@
 
 class Hwc2TestColor : public Hwc2TestProperty<hwc_color_t> {
 public:
-    Hwc2TestColor(Hwc2TestCoverage coverage,
-            hwc2_blend_mode_t blendMode = HWC2_BLEND_MODE_NONE);
+    explicit Hwc2TestColor(Hwc2TestCoverage coverage,
+                           hwc2_blend_mode_t blendMode = HWC2_BLEND_MODE_NONE);
 
     std::string dump() const override;
 
@@ -217,7 +217,7 @@
 
 class Hwc2TestComposition : public Hwc2TestProperty<hwc2_composition_t> {
 public:
-    Hwc2TestComposition(Hwc2TestCoverage coverage);
+    explicit Hwc2TestComposition(Hwc2TestCoverage coverage);
 
     std::string dump() const override;
 
@@ -232,7 +232,7 @@
 
 class Hwc2TestDataspace : public Hwc2TestProperty<android::ui::Dataspace> {
 public:
-    Hwc2TestDataspace(Hwc2TestCoverage coverage);
+    explicit Hwc2TestDataspace(Hwc2TestCoverage coverage);
 
     std::string dump() const override;
 
@@ -248,7 +248,7 @@
 
 class Hwc2TestDisplayDimension : public Hwc2TestProperty<UnsignedArea> {
 public:
-    Hwc2TestDisplayDimension(Hwc2TestCoverage coverage);
+    explicit Hwc2TestDisplayDimension(Hwc2TestCoverage coverage);
 
     std::string dump() const;
 
@@ -291,7 +291,7 @@
 
 class Hwc2TestPlaneAlpha : public Hwc2TestProperty<float> {
 public:
-    Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage);
+    explicit Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage);
 
     std::string dump() const override;
 
@@ -306,7 +306,7 @@
 
 class Hwc2TestSourceCrop : public Hwc2TestProperty<hwc_frect_t> {
 public:
-    Hwc2TestSourceCrop(Hwc2TestCoverage coverage, const Area& bufferArea = {0, 0});
+    explicit Hwc2TestSourceCrop(Hwc2TestCoverage coverage, const Area& bufferArea = {0, 0});
 
     std::string dump() const override;
 
@@ -330,7 +330,7 @@
 
 class Hwc2TestSurfaceDamage : public Hwc2TestProperty<hwc_region_t> {
 public:
-    Hwc2TestSurfaceDamage(Hwc2TestCoverage coverage);
+    explicit Hwc2TestSurfaceDamage(Hwc2TestCoverage coverage);
     ~Hwc2TestSurfaceDamage();
 
     std::string dump() const override;
@@ -356,7 +356,7 @@
 
 class Hwc2TestTransform : public Hwc2TestProperty<hwc_transform_t> {
 public:
-    Hwc2TestTransform(Hwc2TestCoverage coverage);
+    explicit Hwc2TestTransform(Hwc2TestCoverage coverage);
 
     std::string dump() const override;
 
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
index 10c8ef0..5a74a6c 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
@@ -29,7 +29,7 @@
 
 class Hwc2TestVirtualDisplay {
 public:
-    Hwc2TestVirtualDisplay(Hwc2TestCoverage coverage);
+    explicit Hwc2TestVirtualDisplay(Hwc2TestCoverage coverage);
 
     std::string dump() const;
 
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 2f35ae5..f63c911 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -20,6 +20,16 @@
         // Using the address sanitizer not only helps uncover issues in the code
         // covered by the tests, but also covers some of the tricky injection of
         // fakes the unit tests currently do.
+        //
+        // Note: If you get an runtime link error like:
+        //
+        //   CANNOT LINK EXECUTABLE "/data/local/tmp/libsurfaceflinger_unittest": library "libclang_rt.asan-aarch64-android.so" not found
+        //
+        // it is because the address sanitizer shared objects are not installed
+        // by default in the system image.
+        //
+        // You can either "make dist tests" before flashing, or set this
+        // option to false temporarily.
         address: true,
     },
     srcs: [
@@ -46,11 +56,14 @@
         "mock/MockMessageQueue.cpp",
         "mock/MockNativeWindowSurface.cpp",
         "mock/MockSurfaceInterceptor.cpp",
-        "mock/RenderEngine/MockRenderEngine.cpp",
         "mock/system/window/MockNativeWindow.cpp",
     ],
     static_libs: [
         "libgmock",
+        "libcompositionengine",
+        "libcompositionengine_mocks",
+        "librenderengine_mocks",
+
     ],
     header_libs: [
         "libsurfaceflinger_headers",
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index b7c09ed..e417350 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -19,9 +19,11 @@
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
-
 #include <gui/IProducerListener.h>
 #include <log/log.h>
+#include <renderengine/mock/Framebuffer.h>
+#include <renderengine/mock/Image.h>
+#include <renderengine/mock/RenderEngine.h>
 #include <system/window.h>
 #include <utils/String8.h>
 
@@ -36,7 +38,6 @@
 #include "mock/MockEventControlThread.h"
 #include "mock/MockEventThread.h"
 #include "mock/MockMessageQueue.h"
-#include "mock/RenderEngine/MockRenderEngine.h"
 #include "mock/system/window/MockNativeWindow.h"
 
 namespace android {
@@ -767,7 +768,7 @@
 
         const auto displayId = test->mDisplay->getId();
         ASSERT_TRUE(displayId);
-        layer->createHwcLayer(test->mFlinger.mFlinger->getBE().mHwc.get(), *displayId);
+        layer->createHwcLayer(&test->mFlinger.getHwComposer(), *displayId);
 
         Mock::VerifyAndClear(test->mComposer);
 
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index bd9b140..ff84a62 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -21,9 +21,8 @@
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
-
 #include <log/log.h>
-
+#include <renderengine/mock/RenderEngine.h>
 #include <ui/DebugUtils.h>
 
 #include "DisplayIdentificationTest.h"
@@ -36,7 +35,6 @@
 #include "mock/MockMessageQueue.h"
 #include "mock/MockNativeWindowSurface.h"
 #include "mock/MockSurfaceInterceptor.h"
-#include "mock/RenderEngine/MockRenderEngine.h"
 #include "mock/gui/MockGraphicBufferConsumer.h"
 #include "mock/gui/MockGraphicBufferProducer.h"
 #include "mock/system/window/MockNativeWindow.h"
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index acbed51..2d26bb3 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -200,7 +200,7 @@
 
 TEST_F(EventThreadTest, requestNextVsyncPostsASingleVSyncEventToTheConnection) {
     // Signal that we want the next vsync event to be posted to the connection
-    mThread->requestNextVsync(mConnection);
+    mThread->requestNextVsync(mConnection, false);
 
     // EventThread should immediately request a resync.
     EXPECT_TRUE(mResyncCallRecorder.waitForCall().has_value());
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 4da08b8..9ff5e8d 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <compositionengine/impl/CompositionEngine.h>
+
 #include "BufferQueueLayer.h"
 #include "BufferStateLayer.h"
 #include "ColorLayer.h"
@@ -113,6 +115,10 @@
         return mCreateNativeWindowSurface(producer);
     }
 
+    std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() override {
+        return compositionengine::impl::createCompositionEngine();
+    }
+
     sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs&) override {
         // TODO: Use test-fixture controlled factory
         return nullptr;
@@ -148,6 +154,10 @@
             std::function<std::unique_ptr<surfaceflinger::NativeWindowSurface>(
                     const sp<IGraphicBufferProducer>&)>;
     CreateNativeWindowSurfaceFunction mCreateNativeWindowSurface;
+
+    using CreateCompositionEngineFunction =
+            std::function<std::unique_ptr<compositionengine::CompositionEngine>()>;
+    CreateCompositionEngineFunction mCreateCompositionEngine;
 };
 
 } // namespace surfaceflinger::test
@@ -158,11 +168,12 @@
     // functions.
 
     void setupRenderEngine(std::unique_ptr<renderengine::RenderEngine> renderEngine) {
-        mFlinger->getBE().mRenderEngine = std::move(renderEngine);
+        mFlinger->mCompositionEngine->setRenderEngine(std::move(renderEngine));
     }
 
     void setupComposer(std::unique_ptr<Hwc2::Composer> composer) {
-        mFlinger->getBE().mHwc.reset(new HWComposer(std::move(composer)));
+        mFlinger->mCompositionEngine->setHwComposer(
+                std::make_unique<impl::HWComposer>(std::move(composer)));
     }
 
     using CreateBufferQueueFunction = surfaceflinger::test::Factory::CreateBufferQueueFunction;
@@ -178,12 +189,11 @@
 
     using HotplugEvent = SurfaceFlinger::HotplugEvent;
 
-    auto& mutableLayerCurrentState(sp<Layer> layer) { return layer->mState.current; }
-    auto& mutableLayerDrawingState(sp<Layer> layer) { return layer->mState.drawing; }
+    auto& mutableLayerCurrentState(sp<Layer> layer) { return layer->mCurrentState; }
+    auto& mutableLayerDrawingState(sp<Layer> layer) { return layer->mDrawingState; }
 
     void setLayerSidebandStream(sp<Layer> layer, sp<NativeHandle> sidebandStream) {
-        Mutex::Autolock lock(layer->mStateMutex);
-        layer->mState.drawing.sidebandStream = sidebandStream;
+        layer->mDrawingState.sidebandStream = sidebandStream;
         layer->getBE().compositionInfo.hwc.sidebandStream = sidebandStream;
     }
 
@@ -253,6 +263,9 @@
     const auto& getHasPoweredOff() const { return mFlinger->mHasPoweredOff; }
     const auto& getHWVsyncAvailable() const { return mFlinger->mHWVsyncAvailable; }
     const auto& getVisibleRegionsDirty() const { return mFlinger->mVisibleRegionsDirty; }
+    auto& getHwComposer() const {
+        return static_cast<impl::HWComposer&>(mFlinger->getHwComposer());
+    }
 
     const auto& getCompositorTiming() const { return mFlinger->getBE().mCompositorTiming; }
 
@@ -285,13 +298,10 @@
     auto& mutableUseHwcVirtualDisplays() { return mFlinger->mUseHwcVirtualDisplays; }
 
     auto& mutableComposerSequenceId() { return mFlinger->getBE().mComposerSequenceId; }
-    auto& mutableHwcDisplayData() { return mFlinger->getHwComposer().mDisplayData; }
-    auto& mutableHwcPhysicalDisplayIdMap() {
-        return mFlinger->getHwComposer().mPhysicalDisplayIdMap;
-    }
-
-    auto& mutableInternalHwcDisplayId() { return mFlinger->getHwComposer().mInternalHwcDisplayId; }
-    auto& mutableExternalHwcDisplayId() { return mFlinger->getHwComposer().mExternalHwcDisplayId; }
+    auto& mutableHwcDisplayData() { return getHwComposer().mDisplayData; }
+    auto& mutableHwcPhysicalDisplayIdMap() { return getHwComposer().mPhysicalDisplayIdMap; }
+    auto& mutableInternalHwcDisplayId() { return getHwComposer().mInternalHwcDisplayId; }
+    auto& mutableExternalHwcDisplayId() { return getHwComposer().mExternalHwcDisplayId; }
 
     ~TestableSurfaceFlinger() {
         // All these pointer and container clears help ensure that GMock does
@@ -304,8 +314,9 @@
         mutableEventThread().reset();
         mutableInterceptor().reset();
         mutablePrimaryDispSync().reset();
-        mFlinger->getBE().mHwc.reset();
-        mFlinger->getBE().mRenderEngine.reset();
+        mFlinger->mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>());
+        mFlinger->mCompositionEngine->setRenderEngine(
+                std::unique_ptr<renderengine::RenderEngine>());
     }
 
     /* ------------------------------------------------------------------------
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index bb6e183..48d45fa 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -37,7 +37,7 @@
     MOCK_METHOD1(registerDisplayEventConnection,
                  status_t(const sp<android::EventThreadConnection> &));
     MOCK_METHOD2(setVsyncRate, void(uint32_t, const sp<android::EventThreadConnection> &));
-    MOCK_METHOD1(requestNextVsync, void(const sp<android::EventThreadConnection> &));
+    MOCK_METHOD2(requestNextVsync, void(const sp<android::EventThreadConnection> &, bool));
 };
 
 } // namespace mock
diff --git a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
index dc8d606..8c113e2 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
@@ -35,6 +35,7 @@
     MOCK_METHOD0(waitMessage, void());
     MOCK_METHOD2(postMessage, status_t(const sp<MessageBase>&, nsecs_t));
     MOCK_METHOD0(invalidate, void());
+    MOCK_METHOD0(invalidateForHWC, void());
     MOCK_METHOD0(refresh, void());
 };
 
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_hub.h b/services/vr/bufferhubd/include/private/dvr/buffer_hub.h
index 676617d..01520fc 100644
--- a/services/vr/bufferhubd/include/private/dvr/buffer_hub.h
+++ b/services/vr/bufferhubd/include/private/dvr/buffer_hub.h
@@ -41,12 +41,12 @@
 
   // Captures buffer info for use by BufferHubService::DumpState().
   struct BufferInfo {
-    // Common data field shared by BufferProducer and ProducerQueue.
+    // Common data field shared by ProducerBuffer and ProducerQueue.
     int id = -1;
     int type = -1;
     size_t consumer_count = 0;
 
-    // Data field for buffer producer.
+    // Data field for producer buffer.
     uint32_t width = 0;
     uint32_t height = 0;
     uint32_t layer_count = 0;
diff --git a/services/vr/bufferhubd/include/private/dvr/producer_queue_channel.h b/services/vr/bufferhubd/include/private/dvr/producer_queue_channel.h
index c4003da..0456ad8 100644
--- a/services/vr/bufferhubd/include/private/dvr/producer_queue_channel.h
+++ b/services/vr/bufferhubd/include/private/dvr/producer_queue_channel.h
@@ -37,11 +37,11 @@
                                  uint32_t format, uint64_t usage,
                                  size_t buffer_count);
 
-  // Inserts a BufferProducer into the queue. Note that the buffer must be in
+  // Inserts a ProducerBuffer into the queue. Note that the buffer must be in
   // Gain'ed state for the operation to succeed.
   pdx::Status<size_t> OnProducerQueueInsertBuffer(pdx::Message& message, int buffer_cid);
 
-  // Removes a BufferProducer indicated by |slot|. Note that the buffer must be
+  // Removes a ProducerBuffer indicated by |slot|. Note that the buffer must be
   // in Gain'ed state for the operation to succeed.
   pdx::Status<void> OnProducerQueueRemoveBuffer(pdx::Message& message,
                                                 size_t slot);
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 5c484b8..409bce9 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -369,7 +369,9 @@
           (consumer_state_mask & BufferHubDefs::kHighBitsMask);
     }
   }
-  if (update_buffer_state) {
+  if (update_buffer_state || BufferHubDefs::IsClientPosted(
+                                 buffer_state_->load(std::memory_order_acquire),
+                                 consumer_state_mask)) {
     consumer->OnProducerPosted();
   }
 
@@ -455,7 +457,7 @@
   uint32_t buffer_state = buffer_state_->load(std::memory_order_acquire);
   if (!BufferHubDefs::IsClientGained(
       buffer_state, BufferHubDefs::kFirstClientStateMask)) {
-    // Can only detach a BufferProducer when it's in gained state.
+    // Can only detach a ProducerBuffer when it's in gained state.
     ALOGW(
         "ProducerChannel::OnProducerDetach: The buffer (id=%d, state=%"
         PRIx32
@@ -537,8 +539,13 @@
 
   uint32_t current_buffer_state =
       buffer_state_->load(std::memory_order_acquire);
+  uint32_t current_active_clients_bit_mask =
+      active_clients_bit_mask_->load(std::memory_order_acquire);
+  // Signal producer if all current active consumers have released the buffer.
   if (BufferHubDefs::IsBufferReleased(current_buffer_state &
-                                      ~orphaned_consumer_bit_mask_)) {
+                                      ~orphaned_consumer_bit_mask_ &
+                                      current_active_clients_bit_mask)) {
+    buffer_state_->store(0U);
     SignalAvailable();
     if (orphaned_consumer_bit_mask_) {
       ALOGW(
@@ -564,8 +571,13 @@
 
   uint32_t current_buffer_state =
       buffer_state_->load(std::memory_order_acquire);
+  uint32_t current_active_clients_bit_mask =
+      active_clients_bit_mask_->load(std::memory_order_acquire);
+  // Signal producer if all current active consumers have released the buffer.
   if (BufferHubDefs::IsBufferReleased(current_buffer_state &
-                                      ~orphaned_consumer_bit_mask_)) {
+                                      ~orphaned_consumer_bit_mask_ &
+                                      current_active_clients_bit_mask)) {
+    buffer_state_->store(0U);
     SignalAvailable();
   }
 
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.h b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.h
index b478bb5..a82df7f 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.h
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.h
@@ -10,7 +10,7 @@
 class ParcelableComposerFrame : public Parcelable {
  public:
   ParcelableComposerFrame();
-  ParcelableComposerFrame(const ComposerView::Frame& frame);
+  explicit ParcelableComposerFrame(const ComposerView::Frame& frame);
   ~ParcelableComposerFrame() override;
 
   ComposerView::Frame frame() const { return frame_; }
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.h b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.h
index 4cf48f1..6d2ac09 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.h
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.h
@@ -12,7 +12,7 @@
 class ParcelableComposerLayer : public Parcelable {
  public:
   ParcelableComposerLayer();
-  ParcelableComposerLayer(const ComposerView::ComposerLayer& layer);
+  explicit ParcelableComposerLayer(const ComposerView::ComposerLayer& layer);
   ~ParcelableComposerLayer() override;
 
   ComposerView::ComposerLayer layer() const { return layer_; }
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.h b/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.h
index daf9e6d..c4216f6 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.h
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_unique_fd.h
@@ -13,7 +13,7 @@
 class ParcelableUniqueFd : public Parcelable {
  public:
   ParcelableUniqueFd();
-  ParcelableUniqueFd(const base::unique_fd& fence);
+  explicit ParcelableUniqueFd(const base::unique_fd& fence);
   ~ParcelableUniqueFd() override;
 
   void set_fence(const base::unique_fd& fence) {
diff --git a/services/vr/hardware_composer/impl/vr_composer_client.h b/services/vr/hardware_composer/impl/vr_composer_client.h
index de22640..0b7ce5e 100644
--- a/services/vr/hardware_composer/impl/vr_composer_client.h
+++ b/services/vr/hardware_composer/impl/vr_composer_client.h
@@ -35,13 +35,13 @@
 
 class VrComposerClient : public ComposerClient {
  public:
-  VrComposerClient(android::dvr::VrHwc& hal);
+  explicit VrComposerClient(android::dvr::VrHwc& hal);
   virtual ~VrComposerClient();
 
  private:
   class VrCommandEngine : public ComposerCommandEngine {
    public:
-    VrCommandEngine(VrComposerClient& client);
+    explicit VrCommandEngine(VrComposerClient& client);
     ~VrCommandEngine() override;
 
     bool executeCommand(IComposerClient::Command command,
diff --git a/services/vr/hardware_composer/impl/vr_hwc.h b/services/vr/hardware_composer/impl/vr_hwc.h
index f9872b2..e8c0212 100644
--- a/services/vr/hardware_composer/impl/vr_hwc.h
+++ b/services/vr/hardware_composer/impl/vr_hwc.h
@@ -113,9 +113,7 @@
   using Composition =
       hardware::graphics::composer::V2_1::IComposerClient::Composition;
 
-  HwcLayer(Layer new_id) {
-    info.id = new_id;
-  }
+  explicit HwcLayer(Layer new_id) { info.id = new_id; }
 
   void dumpDebugInfo(std::string* result) const;
 
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.h b/services/vr/virtual_touchpad/VirtualTouchpadService.h
index 2c46209..2c88aec 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadService.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadService.h
@@ -13,7 +13,7 @@
 //
 class VirtualTouchpadService : public BnVirtualTouchpadService {
  public:
-  VirtualTouchpadService(std::unique_ptr<VirtualTouchpad> touchpad)
+  explicit VirtualTouchpadService(std::unique_ptr<VirtualTouchpad> touchpad)
       : touchpad_(std::move(touchpad)), client_pid_(0) {}
   ~VirtualTouchpadService() override;