Merge "Refactor argument parsing in ota preopt"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index cce0579..40566e0 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1621,7 +1621,7 @@
             "  -p: capture screenshot to filename.png (requires -o)\n"
             "  -z: generate zipped file (requires -o)\n"
             "  -s: write output to control socket (for init)\n"
-            "  -S: write file location to control socket (for init; requires -o and -z)"
+            "  -S: write file location to control socket (for init; requires -o and -z)\n"
             "  -q: disable vibrate\n"
             "  -B: send broadcast when finished (requires -o)\n"
             "  -P: send broadcast when started and update system properties on "
@@ -2213,9 +2213,11 @@
     }
 
     /* vibrate a few but shortly times to let user know it's finished */
-    for (int i = 0; i < 3; i++) {
-        Vibrate(75);
-        usleep((75 + 50) * 1000);
+    if (do_vibrate) {
+        for (int i = 0; i < 3; i++) {
+            Vibrate(75);
+            usleep((75 + 50) * 1000);
+        }
     }
 
     /* tell activity manager we're done */
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index abbd62d..013a3c1 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -715,13 +715,20 @@
 static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3;
 static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4;
 
-static void run_profman_merge(const std::vector<unique_fd>& profiles_fd,
-        const unique_fd& reference_profile_fd, const std::vector<unique_fd>* apk_fds = nullptr) {
+static void run_profman(const std::vector<unique_fd>& profile_fds,
+                        const unique_fd& reference_profile_fd,
+                        const std::vector<unique_fd>* apk_fds,
+                        bool copy_and_update) {
     const char* profman_bin = is_debug_runtime() ? "/system/bin/profmand" : "/system/bin/profman";
 
-    std::vector<std::string> profile_args(profiles_fd.size());
-    for (size_t k = 0; k < profiles_fd.size(); k++) {
-        profile_args[k] = "--profile-file-fd=" + std::to_string(profiles_fd[k].get());
+    if (copy_and_update) {
+        CHECK_EQ(1u, profile_fds.size());
+        CHECK(apk_fds != nullptr);
+        CHECK_EQ(1u, apk_fds->size());
+    }
+    std::vector<std::string> profile_args(profile_fds.size());
+    for (size_t k = 0; k < profile_fds.size(); k++) {
+        profile_args[k] = "--profile-file-fd=" + std::to_string(profile_fds[k].get());
     }
     std::string reference_profile_arg = "--reference-profile-file-fd="
             + std::to_string(reference_profile_fd.get());
@@ -734,7 +741,7 @@
     }
 
     // program name, reference profile fd, the final NULL and the profile fds
-    const char* argv[3 + profile_args.size() + apk_args.size()];
+    const char* argv[3 + profile_args.size() + apk_args.size() + (copy_and_update ? 1 : 0)];
     int i = 0;
     argv[i++] = profman_bin;
     argv[i++] = reference_profile_arg.c_str();
@@ -744,6 +751,9 @@
     for (size_t k = 0; k < apk_args.size(); k++) {
         argv[i++] = apk_args[k].c_str();
     }
+    if (copy_and_update) {
+        argv[i++] = "--copy-and-update-profile-key";
+    }
     // Do not add after dex2oat_flags, they should override others for debugging.
     argv[i] = NULL;
 
@@ -752,6 +762,25 @@
     exit(68);   /* only get here on exec failure */
 }
 
+
+static void run_profman_merge(const std::vector<unique_fd>& profiles_fd,
+                              const unique_fd& reference_profile_fd,
+                              const std::vector<unique_fd>* apk_fds = nullptr) {
+    run_profman(profiles_fd, reference_profile_fd, apk_fds, /*copy_and_update*/false);
+}
+
+
+static void run_profman_copy_and_update(unique_fd&& profile_fd,
+                                        unique_fd&& reference_profile_fd,
+                                        unique_fd&& apk_fd) {
+    std::vector<unique_fd> profiles_fd;
+    profiles_fd.push_back(std::move(profile_fd));
+    std::vector<unique_fd> apk_fds;
+    apk_fds.push_back(std::move(apk_fd));
+
+    run_profman(profiles_fd, reference_profile_fd, &apk_fds, /*copy_and_update*/true);
+}
+
 // Decides if profile guided compilation is needed or not based on existing profiles.
 // The location is the package name for primary apks or the dex path for secondary dex files.
 // Returns true if there is enough information in the current profiles that makes it
@@ -2610,7 +2639,7 @@
                          userid_t user_id,
                          appid_t app_id,
                          const std::string& profile_name,
-                         const std::string& code_path ATTRIBUTE_UNUSED,
+                         const std::string& code_path,
                          const std::unique_ptr<std::string>& dex_metadata) {
     // Prepare the current profile.
     std::string cur_profile  = create_current_profile_path(user_id, package_name, profile_name,
@@ -2631,8 +2660,11 @@
             /*read_write*/ true, /*is_secondary_dex*/ false);
     unique_fd dex_metadata_fd(TEMP_FAILURE_RETRY(
             open(dex_metadata->c_str(), O_RDONLY | O_NOFOLLOW)));
-    std::vector<unique_fd> profiles_fd;
-    profiles_fd.push_back(std::move(dex_metadata_fd));
+    unique_fd apk_fd(TEMP_FAILURE_RETRY(open(code_path.c_str(), O_RDONLY | O_NOFOLLOW)));
+    if (apk_fd < 0) {
+        PLOG(ERROR) << "Could not open code path " << code_path;
+        return false;
+    }
 
     pid_t pid = fork();
     if (pid == 0) {
@@ -2640,10 +2672,10 @@
         gid_t app_shared_gid = multiuser_get_shared_gid(user_id, app_id);
         drop_capabilities(app_shared_gid);
 
-        // TODO(calin): the dex metadata profile might embed different names for the
-        // same code path (e.g. YouTube.apk or base.apk, depending on how the initial
-        // profile was captured). We should pass the code path to adjust the names in the profile.
-        run_profman_merge(profiles_fd, ref_profile_fd);
+        // The copy and update takes ownership over the fds.
+        run_profman_copy_and_update(std::move(dex_metadata_fd),
+                                    std::move(ref_profile_fd),
+                                    std::move(apk_fd));
         exit(42);   /* only get here on exec failure */
     }
 
diff --git a/data/etc/android.hardware.vulkan.version-1_1.xml b/data/etc/android.hardware.vulkan.version-1_1.xml
new file mode 100644
index 0000000..9704e0f
--- /dev/null
+++ b/data/etc/android.hardware.vulkan.version-1_1.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- This is the standard feature indicating that the device has a Vulkan
+     driver that supports API version 1.1 (0x00401000) -->
+<permissions>
+    <feature name="android.hardware.vulkan.version" version="4198400" />
+</permissions>
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 939a209..c40cad3 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -615,7 +615,7 @@
                 windowType, ownerUid, &handle, &gbp);
         ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
         if (err == NO_ERROR) {
-            sur = new SurfaceControl(this, handle, gbp);
+            sur = new SurfaceControl(this, handle, gbp, true /* owned */);
         }
     }
     return sur;
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index f5fb8ac..5eafbb3 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -48,8 +48,9 @@
 SurfaceControl::SurfaceControl(
         const sp<SurfaceComposerClient>& client,
         const sp<IBinder>& handle,
-        const sp<IGraphicBufferProducer>& gbp)
-    : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp)
+        const sp<IGraphicBufferProducer>& gbp,
+        bool owned)
+    : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp), mOwned(owned)
 {
 }
 
@@ -60,7 +61,9 @@
 
 void SurfaceControl::destroy()
 {
-    if (isValid()) {
+    // 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);
     }
     // clear all references and trigger an IPC now, to make sure things
@@ -184,9 +187,11 @@
     }
     sp<IBinder> gbp;
     parcel->readNullableStrongBinder(&gbp);
+
+    // We aren't the original owner of the surface.
     return new SurfaceControl(new SurfaceComposerClient(
                     interface_cast<ISurfaceComposerClient>(client)),
-            handle.get(), interface_cast<IGraphicBufferProducer>(gbp));
+            handle.get(), interface_cast<IGraphicBufferProducer>(gbp), false /* owned */);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
index 1416d87..bd987dd 100644
--- a/libs/gui/include/gui/SurfaceControl.h
+++ b/libs/gui/include/gui/SurfaceControl.h
@@ -87,7 +87,8 @@
     SurfaceControl(
             const sp<SurfaceComposerClient>& client,
             const sp<IBinder>& handle,
-            const sp<IGraphicBufferProducer>& gbp);
+            const sp<IGraphicBufferProducer>& gbp,
+            bool owned);
 
     ~SurfaceControl();
 
@@ -100,6 +101,7 @@
     sp<IGraphicBufferProducer>  mGraphicBufferProducer;
     mutable Mutex               mLock;
     mutable sp<Surface>         mSurfaceData;
+    bool                        mOwned;
 };
 
 }; // namespace android
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index 153d35a..b92cbf3 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -42,8 +42,8 @@
         for (const auto bit : hardware::hidl_enum_iterator<BufferUsage>()) {
             bits = bits | bit;
         }
-        // TODO(b/72323293): Remove this mask for EXTERNAL_DISP.
-        bits = bits | (1 << 13);
+        // TODO(b/72323293, b/72703005): Remove these additional bits
+        bits = bits | (1 << 10) | (1 << 13);
 
         return bits;
     }();
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 1c5b2d6..9b6f0c5 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -26,7 +26,6 @@
 includeFiles = [ "include" ]
 
 staticLibraries = [
-    "libsurfaceflingerincludes",
     "libbufferhub",
     "libbufferhubqueue",
     "libdisplay",
@@ -63,8 +62,9 @@
 ]
 
 headerLibraries = [
-    "libdvr_headers",
     "android.hardware.graphics.composer@2.1-command-buffer",
+    "libdvr_headers",
+    "libsurfaceflinger_headers",
 ]
 
 cc_library_static {
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 484e0ba..26ae13d 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -513,11 +513,11 @@
                             found = true;
                         }
                     }
-                    if (found && dp->haveExtension("EGL_KHR_gl_colorspace")) {
-                        stripped = true;
-                    } else {
+                    if (found || !dp->haveExtension("EGL_KHR_gl_colorspace")) {
                         stripped_attrib_list.push_back(attr[0]);
                         stripped_attrib_list.push_back(attr[1]);
+                    } else {
+                        stripped = true;
                     }
                 }
                 break;
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index bd7f0ea..4ed4392 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -1,8 +1,210 @@
-cc_library_static {
-    name: "libsurfaceflingerincludes",
+cc_defaults {
+    name: "surfaceflinger_defaults",
+    cflags: [
+        "-DLOG_TAG=\"SurfaceFlinger\"",
+        "-Wall",
+        "-Werror",
+        "-Wthread-safety",
+        "-Wunused",
+        "-Wunreachable-code",
+    ],
+    cppflags: ["-std=c++1z"],
+}
+
+cc_defaults {
+    name: "libsurfaceflinger_defaults",
+    defaults: ["surfaceflinger_defaults"],
+    cflags: [
+        "-DGL_GLEXT_PROTOTYPES",
+        "-DEGL_EGLEXT_PROTOTYPES",
+    ],
+    shared_libs: [
+        "android.frameworks.vr.composer@1.0",
+        "android.hardware.configstore-utils",
+        "android.hardware.configstore@1.0",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.power@1.0",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "libdl",
+        "libEGL",
+        "libfmq",
+        "libGLESv1_CM",
+        "libGLESv2",
+        "libgui",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblayers_proto",
+        "liblog",
+        "libprotobuf-cpp-lite",
+        "libsync",
+        "libui",
+        "libutils",
+        "libvulkan",
+    ],
+    static_libs: [
+        "libserviceutils",
+        "libtrace_proto",
+        "libvkjson",
+        "libvr_manager",
+        "libvrflinger",
+    ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+    ],
+    export_static_lib_headers: [
+        "libserviceutils",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.composer@2.1",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+    ],
+}
+
+cc_library_headers {
+    name: "libsurfaceflinger_headers",
     export_include_dirs: ["."],
     static_libs = ["libserviceutils"],
     export_static_lib_headers = ["libserviceutils"],
 }
 
-subdirs = ["tests/fakehwc", "layerproto"]
\ No newline at end of file
+filegroup {
+    name: "libsurfaceflinger_sources",
+    srcs: [
+        "BufferLayer.cpp",
+        "BufferLayerConsumer.cpp",
+        "Client.cpp",
+        "ColorLayer.cpp",
+        "DisplayDevice.cpp",
+        "DisplayHardware/ComposerHal.cpp",
+        "DisplayHardware/FramebufferSurface.cpp",
+        "DisplayHardware/HWC2.cpp",
+        "DisplayHardware/HWComposer.cpp",
+        "DisplayHardware/HWComposerBufferCache.cpp",
+        "DisplayHardware/VirtualDisplaySurface.cpp",
+        "DispSync.cpp",
+        "Effects/Daltonizer.cpp",
+        "EventControlThread.cpp",
+        "EventLog/EventLog.cpp",
+        "EventThread.cpp",
+        "FrameTracker.cpp",
+        "GpuService.cpp",
+        "Layer.cpp",
+        "LayerProtoHelper.cpp",
+        "LayerRejecter.cpp",
+        "LayerVector.cpp",
+        "MessageQueue.cpp",
+        "MonitoredProducer.cpp",
+        "RenderArea.cpp",
+        "RenderEngine/Description.cpp",
+        "RenderEngine/GLES20RenderEngine.cpp",
+        "RenderEngine/GLExtensions.cpp",
+        "RenderEngine/Image.cpp",
+        "RenderEngine/Mesh.cpp",
+        "RenderEngine/Program.cpp",
+        "RenderEngine/ProgramCache.cpp",
+        "RenderEngine/RenderEngine.cpp",
+        "RenderEngine/Surface.cpp",
+        "RenderEngine/Texture.cpp",
+        "StartPropertySetThread.cpp",
+        "SurfaceFlinger.cpp",
+        "SurfaceInterceptor.cpp",
+        "SurfaceTracing.cpp",
+        "Transform.cpp",
+    ],
+}
+
+cc_library_shared {
+    name: "libsurfaceflinger",
+    defaults: ["libsurfaceflinger_defaults"],
+    cflags: [
+        "-fvisibility=hidden",
+        "-Werror=format",
+    ],
+    srcs: [
+        ":libsurfaceflinger_sources",
+    ],
+    logtags: ["EventLog/EventLogTags.logtags"],
+    include_dirs: [
+        "external/vulkan-validation-layers/libs/vkjson",
+        "frameworks/native/vulkan/include",
+    ],
+    cppflags: [
+        "-fwhole-program-vtables",  // requires ThinLTO
+    ],
+    lto: {
+        thin: true,
+    },
+}
+
+cc_binary {
+    name: "surfaceflinger",
+    defaults: ["surfaceflinger_defaults"],
+    init_rc: ["surfaceflinger.rc"],
+    srcs: ["main_surfaceflinger.cpp"],
+    whole_static_libs: [
+        "libsigchain",
+    ],
+    shared_libs: [
+        "android.frameworks.displayservice@1.0",
+        "android.hardware.configstore-utils",
+        "android.hardware.configstore@1.0",
+        "android.hardware.graphics.allocator@2.0",
+        "libbinder",
+        "libcutils",
+        "libdisplayservicehidl",
+        "libhidlbase",
+        "libhidltransport",
+        "liblayers_proto",
+        "liblog",
+        "libsurfaceflinger",
+        "libutils",
+    ],
+    static_libs: [
+        "libserviceutils",
+        "libtrace_proto",
+    ],
+    ldflags: ["-Wl,--export-dynamic"],
+
+    // TODO(b/71715793): These version-scripts are required due to the use of
+    // whole_static_libs to pull in libsigchain. To work, the files had to be
+    // locally duplicated from their original location
+    // $ANDROID_ROOT/art/sigchainlib/
+    multilib: {
+        lib32: {
+            version_script: "version-script32.txt",
+        },
+        lib64: {
+            version_script: "version-script64.txt",
+        },
+    },
+}
+
+cc_library_shared {
+    name: "libsurfaceflinger_ddmconnection",
+    defaults: ["surfaceflinger_defaults"],
+    srcs: ["DdmConnection.cpp"],
+    shared_libs: [
+        "libcutils",
+        "libdl",
+        "liblog",
+    ],
+    product_variables: {
+        // uses jni which may not be available in PDK
+        pdk: {
+            enabled: false,
+        },
+    },
+}
+
+subdirs = [
+    "layerproto",
+    "tests",
+]
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
deleted file mode 100644
index 6c54ec3..0000000
--- a/services/surfaceflinger/Android.mk
+++ /dev/null
@@ -1,183 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_CLANG := true
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_SRC_FILES := \
-    Client.cpp \
-    DisplayDevice.cpp \
-    DispSync.cpp \
-    EventControlThread.cpp \
-    StartPropertySetThread.cpp \
-    EventThread.cpp \
-    FrameTracker.cpp \
-    GpuService.cpp \
-    Layer.cpp \
-    BufferLayer.cpp \
-    BufferLayerConsumer.cpp \
-    ColorLayer.cpp \
-    LayerRejecter.cpp \
-    LayerVector.cpp \
-    MessageQueue.cpp \
-    MonitoredProducer.cpp \
-    SurfaceFlinger.cpp \
-    SurfaceInterceptor.cpp \
-    SurfaceTracing.cpp \
-    Transform.cpp \
-    DisplayHardware/ComposerHal.cpp \
-    DisplayHardware/FramebufferSurface.cpp \
-    DisplayHardware/HWC2.cpp \
-    DisplayHardware/HWComposer.cpp \
-    DisplayHardware/HWComposerBufferCache.cpp \
-    DisplayHardware/VirtualDisplaySurface.cpp \
-    Effects/Daltonizer.cpp \
-    EventLog/EventLogTags.logtags \
-    EventLog/EventLog.cpp \
-    RenderEngine/Description.cpp \
-    RenderEngine/Image.cpp \
-    RenderEngine/Mesh.cpp \
-    RenderEngine/Program.cpp \
-    RenderEngine/ProgramCache.cpp \
-    RenderEngine/GLExtensions.cpp \
-    RenderEngine/RenderEngine.cpp \
-    RenderEngine/Surface.cpp \
-    RenderEngine/Texture.cpp \
-    RenderEngine/GLES20RenderEngine.cpp \
-    LayerProtoHelper.cpp \
-    RenderArea.cpp \
-
-LOCAL_MODULE := libsurfaceflinger
-LOCAL_C_INCLUDES := \
-    frameworks/native/vulkan/include \
-    external/vulkan-validation-layers/libs/vkjson \
-    system/libhwbinder/fast_msgq/include \
-
-LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
-LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-
-LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
-
-LOCAL_STATIC_LIBRARIES := \
-    libtrace_proto \
-    libvkjson \
-    libvr_manager \
-    libvrflinger \
-    libserviceutils
-
-LOCAL_HEADER_LIBRARIES := \
-    android.hardware.graphics.composer@2.1-command-buffer
-
-LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := libserviceutils
-
-LOCAL_SHARED_LIBRARIES := \
-    android.frameworks.vr.composer@1.0 \
-    android.hardware.graphics.allocator@2.0 \
-    android.hardware.graphics.composer@2.1 \
-    android.hardware.configstore@1.0 \
-    android.hardware.configstore-utils \
-    libcutils \
-    liblog \
-    libdl \
-    libfmq \
-    libhardware \
-    libhidlbase \
-    libhidltransport \
-    libhwbinder \
-    libutils \
-    libEGL \
-    libGLESv1_CM \
-    libGLESv2 \
-    libbinder \
-    libui \
-    libgui \
-    libvulkan \
-    libsync \
-    libprotobuf-cpp-lite \
-    libbase \
-    android.hardware.power@1.0 \
-    liblayers_proto
-
-LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \
-    android.hardware.graphics.allocator@2.0 \
-    android.hardware.graphics.composer@2.1 \
-    libhidlbase \
-    libhidltransport \
-    libhwbinder
-
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code -std=c++1z
-
-include $(BUILD_SHARED_LIBRARY)
-
-###############################################################
-# build surfaceflinger's executable
-include $(CLEAR_VARS)
-
-LOCAL_CLANG := true
-
-LOCAL_LDFLAGS_32 := -Wl,--version-script,art/sigchainlib/version-script32.txt -Wl,--export-dynamic
-LOCAL_LDFLAGS_64 := -Wl,--version-script,art/sigchainlib/version-script64.txt -Wl,--export-dynamic
-LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
-
-LOCAL_INIT_RC := surfaceflinger.rc
-
-LOCAL_SRC_FILES := \
-    main_surfaceflinger.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    android.frameworks.displayservice@1.0 \
-    android.hardware.configstore@1.0 \
-    android.hardware.configstore-utils \
-    android.hardware.graphics.allocator@2.0 \
-    libsurfaceflinger \
-    libcutils \
-    libdisplayservicehidl \
-    liblog \
-    libbinder \
-    libhidlbase \
-    libhidltransport \
-    libutils \
-    libui \
-    libgui \
-    libdl \
-    liblayers_proto
-
-LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain
-LOCAL_STATIC_LIBRARIES := libtrace_proto \
-    libserviceutils
-
-LOCAL_MODULE := surfaceflinger
-
-ifdef TARGET_32_BIT_SURFACEFLINGER
-LOCAL_32_BIT_ONLY := true
-endif
-
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code -std=c++1z
-
-include $(BUILD_EXECUTABLE)
-
-###############################################################
-# uses jni which may not be available in PDK
-ifneq ($(wildcard libnativehelper/include),)
-include $(CLEAR_VARS)
-
-LOCAL_CLANG := true
-
-LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
-
-LOCAL_SRC_FILES := \
-    DdmConnection.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    liblog \
-    libdl
-
-LOCAL_MODULE := libsurfaceflinger_ddmconnection
-
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
-
-include $(BUILD_SHARED_LIBRARY)
-endif # libnativehelper
-
-include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index bef12ea..9e01fd0 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -33,8 +33,8 @@
 #include <ui/FenceTime.h>
 
 #include "DispSync.h"
-#include "SurfaceFlinger.h"
 #include "EventLog/EventLog.h"
+#include "SurfaceFlinger.h"
 
 using std::max;
 using std::min;
@@ -53,15 +53,14 @@
 // needed to re-synchronize the software vsync model with the hardware.  The
 // error metric used is the mean of the squared difference between each
 // present time and the nearest software-predicted vsync.
-static const nsecs_t kErrorThreshold = 160000000000;    // 400 usec squared
+static const nsecs_t kErrorThreshold = 160000000000; // 400 usec squared
 
 #undef LOG_TAG
 #define LOG_TAG "DispSyncThread"
-class DispSyncThread: public Thread {
+class DispSyncThread : public Thread {
 public:
-
-    explicit DispSyncThread(const char* name):
-            mName(name),
+    explicit DispSyncThread(const char* name)
+          : mName(name),
             mStop(false),
             mPeriod(0),
             mPhase(0),
@@ -78,8 +77,8 @@
         mPhase = phase;
         mReferenceTime = referenceTime;
         ALOGV("[%s] updateModel: mPeriod = %" PRId64 ", mPhase = %" PRId64
-                " mReferenceTime = %" PRId64, mName, ns2us(mPeriod),
-                ns2us(mPhase), ns2us(mReferenceTime));
+              " mReferenceTime = %" PRId64,
+              mName, ns2us(mPeriod), ns2us(mPhase), ns2us(mReferenceTime));
         mCond.signal();
     }
 
@@ -115,8 +114,7 @@
                 if (mPeriod == 0) {
                     err = mCond.wait(mMutex);
                     if (err != NO_ERROR) {
-                        ALOGE("error waiting for new events: %s (%d)",
-                                strerror(-err), err);
+                        ALOGE("error waiting for new events: %s (%d)", strerror(-err), err);
                         return false;
                     }
                     continue;
@@ -133,16 +131,14 @@
                         ALOGV("[%s] Waiting forever", mName);
                         err = mCond.wait(mMutex);
                     } else {
-                        ALOGV("[%s] Waiting until %" PRId64, mName,
-                                ns2us(targetTime));
+                        ALOGV("[%s] Waiting until %" PRId64, mName, ns2us(targetTime));
                         err = mCond.waitRelative(mMutex, targetTime - now);
                     }
 
                     if (err == TIMED_OUT) {
                         isWakeup = true;
                     } else if (err != NO_ERROR) {
-                        ALOGE("error waiting for next event: %s (%d)",
-                                strerror(-err), err);
+                        ALOGE("error waiting for next event: %s (%d)", strerror(-err), err);
                         return false;
                     }
                 }
@@ -153,8 +149,7 @@
                 static const nsecs_t kMaxWakeupLatency = us2ns(1500);
 
                 if (isWakeup) {
-                    mWakeupLatency = ((mWakeupLatency * 63) +
-                            (now - targetTime)) / 64;
+                    mWakeupLatency = ((mWakeupLatency * 63) + (now - targetTime)) / 64;
                     mWakeupLatency = min(mWakeupLatency, kMaxWakeupLatency);
                     if (kTraceDetailedInfo) {
                         ATRACE_INT64("DispSync:WakeupLat", now - targetTime);
@@ -173,8 +168,7 @@
         return false;
     }
 
-    status_t addEventListener(const char* name, nsecs_t phase,
-            const sp<DispSync::Callback>& callback) {
+    status_t addEventListener(const char* name, nsecs_t phase, DispSync::Callback* callback) {
         if (kTraceDetailedInfo) ATRACE_CALL();
         Mutex::Autolock lock(mMutex);
 
@@ -191,8 +185,7 @@
 
         // We want to allow the firstmost future event to fire without
         // allowing any past events to fire
-        listener.mLastEventTime = systemTime() - mPeriod / 2 + mPhase -
-                mWakeupLatency;
+        listener.mLastEventTime = systemTime() - mPeriod / 2 + mPhase - mWakeupLatency;
 
         mEventListeners.push(listener);
 
@@ -201,7 +194,7 @@
         return NO_ERROR;
     }
 
-    status_t removeEventListener(const sp<DispSync::Callback>& callback) {
+    status_t removeEventListener(DispSync::Callback* callback) {
         if (kTraceDetailedInfo) ATRACE_CALL();
         Mutex::Autolock lock(mMutex);
 
@@ -225,16 +218,15 @@
     }
 
 private:
-
     struct EventListener {
         const char* mName;
         nsecs_t mPhase;
         nsecs_t mLastEventTime;
-        sp<DispSync::Callback> mCallback;
+        DispSync::Callback* mCallback;
     };
 
     struct CallbackInvocation {
-        sp<DispSync::Callback> mCallback;
+        DispSync::Callback* mCallback;
         nsecs_t mEventTime;
     };
 
@@ -243,8 +235,7 @@
         ALOGV("[%s] computeNextEventTimeLocked", mName);
         nsecs_t nextEventTime = INT64_MAX;
         for (size_t i = 0; i < mEventListeners.size(); i++) {
-            nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i],
-                    now);
+            nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i], now);
 
             if (t < nextEventTime) {
                 nextEventTime = t;
@@ -257,22 +248,19 @@
 
     Vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now) {
         if (kTraceDetailedInfo) ATRACE_CALL();
-        ALOGV("[%s] gatherCallbackInvocationsLocked @ %" PRId64, mName,
-                ns2us(now));
+        ALOGV("[%s] gatherCallbackInvocationsLocked @ %" PRId64, mName, ns2us(now));
 
         Vector<CallbackInvocation> callbackInvocations;
         nsecs_t onePeriodAgo = now - mPeriod;
 
         for (size_t i = 0; i < mEventListeners.size(); i++) {
-            nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i],
-                    onePeriodAgo);
+            nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i], onePeriodAgo);
 
             if (t < now) {
                 CallbackInvocation ci;
                 ci.mCallback = mEventListeners[i].mCallback;
                 ci.mEventTime = t;
-                ALOGV("[%s] [%s] Preparing to fire", mName,
-                        mEventListeners[i].mName);
+                ALOGV("[%s] [%s] Preparing to fire", mName, mEventListeners[i].mName);
                 callbackInvocations.push(ci);
                 mEventListeners.editItemAt(i).mLastEventTime = t;
             }
@@ -281,18 +269,16 @@
         return callbackInvocations;
     }
 
-    nsecs_t computeListenerNextEventTimeLocked(const EventListener& listener,
-            nsecs_t baseTime) {
+    nsecs_t computeListenerNextEventTimeLocked(const EventListener& listener, nsecs_t baseTime) {
         if (kTraceDetailedInfo) ATRACE_CALL();
-        ALOGV("[%s] [%s] computeListenerNextEventTimeLocked(%" PRId64 ")",
-                mName, listener.mName, ns2us(baseTime));
+        ALOGV("[%s] [%s] computeListenerNextEventTimeLocked(%" PRId64 ")", mName, listener.mName,
+              ns2us(baseTime));
 
         nsecs_t lastEventTime = listener.mLastEventTime + mWakeupLatency;
         ALOGV("[%s] lastEventTime: %" PRId64, mName, ns2us(lastEventTime));
         if (baseTime < lastEventTime) {
             baseTime = lastEventTime;
-            ALOGV("[%s] Clamping baseTime to lastEventTime -> %" PRId64, mName,
-                    ns2us(baseTime));
+            ALOGV("[%s] Clamping baseTime to lastEventTime -> %" PRId64, mName, ns2us(baseTime));
         }
 
         baseTime -= mReferenceTime;
@@ -374,11 +360,8 @@
     bool mParity;
 };
 
-DispSync::DispSync(const char* name) :
-        mName(name),
-        mRefreshSkipCount(0),
-        mThread(new DispSyncThread(name)) {
-}
+DispSync::DispSync(const char* name)
+      : mName(name), mRefreshSkipCount(0), mThread(new DispSyncThread(name)) {}
 
 DispSync::~DispSync() {}
 
@@ -404,7 +387,8 @@
         // not needed because any time there is an event registered we will
         // turn on the HW vsync events.
         if (!mIgnorePresentFences && kEnableZeroPhaseTracer) {
-            addEventListener("ZeroPhaseTracer", 0, new ZeroPhaseTracer());
+            mZeroPhaseTracer = std::make_unique<ZeroPhaseTracer>();
+            addEventListener("ZeroPhaseTracer", 0, mZeroPhaseTracer.get());
         }
     }
 }
@@ -451,8 +435,8 @@
         mPhase = 0;
         mReferenceTime = timestamp;
         ALOGV("[%s] First resync sample: mPeriod = %" PRId64 ", mPhase = 0, "
-                "mReferenceTime = %" PRId64, mName, ns2us(mPeriod),
-                ns2us(mReferenceTime));
+              "mReferenceTime = %" PRId64,
+              mName, ns2us(mPeriod), ns2us(mReferenceTime));
         mThread->updateModel(mPeriod, mPhase, mReferenceTime);
     }
 
@@ -480,16 +464,13 @@
     // Check against kErrorThreshold / 2 to add some hysteresis before having to
     // resync again
     bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2);
-    ALOGV("[%s] addResyncSample returning %s", mName,
-            modelLocked ? "locked" : "unlocked");
+    ALOGV("[%s] addResyncSample returning %s", mName, modelLocked ? "locked" : "unlocked");
     return !modelLocked;
 }
 
-void DispSync::endResync() {
-}
+void DispSync::endResync() {}
 
-status_t DispSync::addEventListener(const char* name, nsecs_t phase,
-        const sp<Callback>& callback) {
+status_t DispSync::addEventListener(const char* name, nsecs_t phase, Callback* callback) {
     Mutex::Autolock lock(mMutex);
     return mThread->addEventListener(name, phase, callback);
 }
@@ -501,7 +482,7 @@
     updateModelLocked();
 }
 
-status_t DispSync::removeEventListener(const sp<Callback>& callback) {
+status_t DispSync::removeEventListener(Callback* callback) {
     Mutex::Autolock lock(mMutex);
     return mThread->removeEventListener(callback);
 }
@@ -597,8 +578,7 @@
         // call getSignalTime() periodically so the cache is updated when the
         // fence signals.
         nsecs_t time = mPresentFences[i]->getCachedSignalTime();
-        if (time == Fence::SIGNAL_TIME_PENDING ||
-                time == Fence::SIGNAL_TIME_INVALID) {
+        if (time == Fence::SIGNAL_TIME_PENDING || time == Fence::SIGNAL_TIME_INVALID) {
             continue;
         }
 
@@ -622,9 +602,8 @@
         mError = 0;
         // Use mod ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT to avoid log spam.
         mZeroErrSamplesCount++;
-        ALOGE_IF(
-                (mZeroErrSamplesCount % ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT) == 0,
-                "No present times for model error.");
+        ALOGE_IF((mZeroErrSamplesCount % ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT) == 0,
+                 "No present times for model error.");
     }
 
     if (kTraceDetailedInfo) {
@@ -650,17 +629,14 @@
 
 void DispSync::dump(String8& result) const {
     Mutex::Autolock lock(mMutex);
-    result.appendFormat("present fences are %s\n",
-            mIgnorePresentFences ? "ignored" : "used");
-    result.appendFormat("mPeriod: %" PRId64 " ns (%.3f fps; skipCount=%d)\n",
-            mPeriod, 1000000000.0 / mPeriod, mRefreshSkipCount);
+    result.appendFormat("present fences are %s\n", mIgnorePresentFences ? "ignored" : "used");
+    result.appendFormat("mPeriod: %" PRId64 " ns (%.3f fps; skipCount=%d)\n", mPeriod,
+                        1000000000.0 / mPeriod, mRefreshSkipCount);
     result.appendFormat("mPhase: %" PRId64 " ns\n", mPhase);
-    result.appendFormat("mError: %" PRId64 " ns (sqrt=%.1f)\n",
-            mError, sqrt(mError));
+    result.appendFormat("mError: %" PRId64 " ns (sqrt=%.1f)\n", mError, sqrt(mError));
     result.appendFormat("mNumResyncSamplesSincePresent: %d (limit %d)\n",
-            mNumResyncSamplesSincePresent, MAX_RESYNC_SAMPLES_WITHOUT_PRESENT);
-    result.appendFormat("mNumResyncSamples: %zd (max %d)\n",
-            mNumResyncSamples, MAX_RESYNC_SAMPLES);
+                        mNumResyncSamplesSincePresent, MAX_RESYNC_SAMPLES_WITHOUT_PRESENT);
+    result.appendFormat("mNumResyncSamples: %zd (max %d)\n", mNumResyncSamples, MAX_RESYNC_SAMPLES);
 
     result.appendFormat("mResyncSamples:\n");
     nsecs_t previous = -1;
@@ -670,14 +646,13 @@
         if (i == 0) {
             result.appendFormat("  %" PRId64 "\n", sampleTime);
         } else {
-            result.appendFormat("  %" PRId64 " (+%" PRId64 ")\n",
-                    sampleTime, sampleTime - previous);
+            result.appendFormat("  %" PRId64 " (+%" PRId64 ")\n", sampleTime,
+                                sampleTime - previous);
         }
         previous = sampleTime;
     }
 
-    result.appendFormat("mPresentFences [%d]:\n",
-            NUM_PRESENT_SAMPLES);
+    result.appendFormat("mPresentFences [%d]:\n", NUM_PRESENT_SAMPLES);
     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
     previous = Fence::SIGNAL_TIME_INVALID;
     for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
@@ -685,17 +660,16 @@
         nsecs_t presentTime = mPresentFences[idx]->getSignalTime();
         if (presentTime == Fence::SIGNAL_TIME_PENDING) {
             result.appendFormat("  [unsignaled fence]\n");
-        } else if(presentTime == Fence::SIGNAL_TIME_INVALID) {
+        } else if (presentTime == Fence::SIGNAL_TIME_INVALID) {
             result.appendFormat("  [invalid fence]\n");
         } else if (previous == Fence::SIGNAL_TIME_PENDING ||
-                previous == Fence::SIGNAL_TIME_INVALID) {
+                   previous == Fence::SIGNAL_TIME_INVALID) {
             result.appendFormat("  %" PRId64 "  (%.3f ms ago)\n", presentTime,
-                    (now - presentTime) / 1000000.0);
+                                (now - presentTime) / 1000000.0);
         } else {
-            result.appendFormat("  %" PRId64 " (+%" PRId64 " / %.3f)  (%.3f ms ago)\n",
-                    presentTime, presentTime - previous,
-                    (presentTime - previous) / (double) mPeriod,
-                    (now - presentTime) / 1000000.0);
+            result.appendFormat("  %" PRId64 " (+%" PRId64 " / %.3f)  (%.3f ms ago)\n", presentTime,
+                                presentTime - previous, (presentTime - previous) / (double)mPeriod,
+                                (now - presentTime) / 1000000.0);
         }
         previous = presentTime;
     }
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index 880a24d..9336f4d 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -20,8 +20,8 @@
 #include <stddef.h>
 
 #include <utils/Mutex.h>
-#include <utils/Timers.h>
 #include <utils/RefBase.h>
+#include <utils/Timers.h>
 
 #include <ui/FenceTime.h>
 
@@ -47,12 +47,10 @@
 // false to indicate that a resynchronization (via addResyncSample) is not
 // needed.
 class DispSync {
-
 public:
-
-    class Callback: public virtual RefBase {
+    class Callback {
     public:
-        virtual ~Callback() {};
+        virtual ~Callback(){};
         virtual void onDispSyncEvent(nsecs_t when) = 0;
     };
 
@@ -108,13 +106,12 @@
     // given phase offset from the hardware vsync events.  The callback is
     // called from a separate thread and it should return reasonably quickly
     // (i.e. within a few hundred microseconds).
-    status_t addEventListener(const char* name, nsecs_t phase,
-            const sp<Callback>& callback);
+    status_t addEventListener(const char* name, nsecs_t phase, Callback* callback);
 
     // removeEventListener removes an already-registered event callback.  Once
     // this method returns that callback will no longer be called by the
     // DispSync object.
-    status_t removeEventListener(const sp<Callback>& callback);
+    status_t removeEventListener(Callback* callback);
 
     // computeNextRefresh computes when the next refresh is expected to begin.
     // The periodOffset value can be used to move forward or backward; an
@@ -126,7 +123,6 @@
     void dump(String8& result) const;
 
 private:
-
     void updateModelLocked();
     void updateErrorLocked();
     void resetErrorLocked();
@@ -174,8 +170,7 @@
 
     // These member variables store information about the present fences used
     // to validate the currently computed model.
-    std::shared_ptr<FenceTime>
-            mPresentFences[NUM_PRESENT_SAMPLES] {FenceTime::NO_FENCE};
+    std::shared_ptr<FenceTime> mPresentFences[NUM_PRESENT_SAMPLES]{FenceTime::NO_FENCE};
     size_t mPresentSampleOffset;
 
     int mRefreshSkipCount;
@@ -193,8 +188,10 @@
     // Ignore present (retire) fences if the device doesn't have support for the
     // sync framework
     bool mIgnorePresentFences;
+
+    std::unique_ptr<Callback> mZeroPhaseTracer;
 };
 
-}
+} // namespace android
 
 #endif // ANDROID_DISPSYNC_H
diff --git a/services/surfaceflinger/EventControlThread.cpp b/services/surfaceflinger/EventControlThread.cpp
index 02eea47..ac54059 100644
--- a/services/surfaceflinger/EventControlThread.cpp
+++ b/services/surfaceflinger/EventControlThread.cpp
@@ -14,50 +14,57 @@
  * limitations under the License.
  */
 
+#include <pthread.h>
+#include <sched.h>
+#include <sys/resource.h>
+
+#include <cutils/sched_policy.h>
+#include <log/log.h>
+#include <system/thread_defs.h>
+
 #include "EventControlThread.h"
-#include "SurfaceFlinger.h"
 
 namespace android {
 
-EventControlThread::EventControlThread(const sp<SurfaceFlinger>& flinger):
-        mFlinger(flinger),
-        mVsyncEnabled(false) {
+EventControlThread::EventControlThread(EventControlThread::SetVSyncEnabledFunction function)
+      : mSetVSyncEnabled(function) {
+    pthread_setname_np(mThread.native_handle(), "EventControlThread");
+
+    pid_t tid = pthread_gettid_np(mThread.native_handle());
+    setpriority(PRIO_PROCESS, tid, ANDROID_PRIORITY_URGENT_DISPLAY);
+    set_sched_policy(tid, SP_FOREGROUND);
+}
+
+EventControlThread::~EventControlThread() {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mKeepRunning = false;
+        mCondition.notify_all();
+    }
+    mThread.join();
 }
 
 void EventControlThread::setVsyncEnabled(bool enabled) {
-    Mutex::Autolock lock(mMutex);
+    std::lock_guard<std::mutex> lock(mMutex);
     mVsyncEnabled = enabled;
-    mCond.signal();
+    mCondition.notify_all();
 }
 
-bool EventControlThread::threadLoop() {
-    enum class VsyncState {Unset, On, Off};
-    auto currentVsyncState = VsyncState::Unset;
+// Unfortunately std::unique_lock gives warnings with -Wthread-safety
+void EventControlThread::threadMain() NO_THREAD_SAFETY_ANALYSIS {
+    auto keepRunning = true;
+    auto currentVsyncEnabled = false;
 
-    while (true) {
-        auto requestedVsyncState = VsyncState::On;
-        {
-            Mutex::Autolock lock(mMutex);
-            requestedVsyncState =
-                    mVsyncEnabled ? VsyncState::On : VsyncState::Off;
-            while (currentVsyncState == requestedVsyncState) {
-                status_t err = mCond.wait(mMutex);
-                if (err != NO_ERROR) {
-                    ALOGE("error waiting for new events: %s (%d)",
-                          strerror(-err), err);
-                    return false;
-                }
-                requestedVsyncState =
-                        mVsyncEnabled ? VsyncState::On : VsyncState::Off;
-            }
-        }
+    while (keepRunning) {
+        mSetVSyncEnabled(currentVsyncEnabled);
 
-        bool enable = requestedVsyncState == VsyncState::On;
-        mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, enable);
-        currentVsyncState = requestedVsyncState;
+        std::unique_lock<std::mutex> lock(mMutex);
+        mCondition.wait(lock, [this, currentVsyncEnabled, keepRunning]() NO_THREAD_SAFETY_ANALYSIS {
+            return currentVsyncEnabled != mVsyncEnabled || keepRunning != mKeepRunning;
+        });
+        currentVsyncEnabled = mVsyncEnabled;
+        keepRunning = mKeepRunning;
     }
-
-    return false;
 }
 
 } // namespace android
diff --git a/services/surfaceflinger/EventControlThread.h b/services/surfaceflinger/EventControlThread.h
index 1b1ef75..321fb79 100644
--- a/services/surfaceflinger/EventControlThread.h
+++ b/services/surfaceflinger/EventControlThread.h
@@ -14,35 +14,41 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_EVENTCONTROLTHREAD_H
-#define ANDROID_EVENTCONTROLTHREAD_H
+#pragma once
 
-#include <stddef.h>
+#include <cstddef>
+#include <condition_variable>
+#include <functional>
+#include <mutex>
+#include <thread>
 
-#include <utils/Mutex.h>
-#include <utils/Thread.h>
+#include <android-base/thread_annotations.h>
 
 namespace android {
 
 class SurfaceFlinger;
 
-class EventControlThread: public Thread {
+class EventControlThread {
 public:
+    using SetVSyncEnabledFunction = std::function<void(bool)>;
 
-    explicit EventControlThread(const sp<SurfaceFlinger>& flinger);
-    virtual ~EventControlThread() {}
+    explicit EventControlThread(SetVSyncEnabledFunction function);
+    ~EventControlThread();
 
     void setVsyncEnabled(bool enabled);
-    virtual bool threadLoop();
 
 private:
-    sp<SurfaceFlinger> mFlinger;
-    bool mVsyncEnabled;
+    void threadMain();
 
-    Mutex mMutex;
-    Condition mCond;
+    std::mutex mMutex;
+    std::condition_variable mCondition;
+
+    const SetVSyncEnabledFunction mSetVSyncEnabled;
+    bool mVsyncEnabled GUARDED_BY(mMutex) = false;
+    bool mKeepRunning GUARDED_BY(mMutex) = true;
+
+    // Must be last so that everything is initialized before the thread starts.
+    std::thread mThread{&EventControlThread::threadMain, this};
 };
 
-}
-
-#endif // ANDROID_EVENTCONTROLTHREAD_H
+} // namespace android
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 5c0e3b3..53d95e2 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -16,13 +16,17 @@
 
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include <stdint.h>
+#include <pthread.h>
+#include <sched.h>
 #include <sys/types.h>
+#include <chrono>
+#include <cstdint>
 
 #include <cutils/compiler.h>
+#include <cutils/sched_policy.h>
 
-#include <gui/IDisplayEventConnection.h>
 #include <gui/DisplayEventReceiver.h>
+#include <gui/IDisplayEventConnection.h>
 
 #include <utils/Errors.h>
 #include <utils/String8.h>
@@ -31,109 +35,126 @@
 #include "EventThread.h"
 #include "SurfaceFlinger.h"
 
+using namespace std::chrono_literals;
+
 // ---------------------------------------------------------------------------
+
 namespace android {
+
 // ---------------------------------------------------------------------------
 
-EventThread::EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger, bool interceptVSyncs)
-    : mVSyncSource(src),
-      mFlinger(flinger),
-      mUseSoftwareVSync(false),
-      mVsyncEnabled(false),
-      mDebugVsyncEnabled(false),
-      mInterceptVSyncs(interceptVSyncs) {
-
-    for (int32_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
-        mVSyncEvent[i].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
-        mVSyncEvent[i].header.id = 0;
-        mVSyncEvent[i].header.timestamp = 0;
-        mVSyncEvent[i].vsync.count =  0;
+EventThread::EventThread(VSyncSource* src, SurfaceFlinger& flinger, bool interceptVSyncs,
+                         const char* threadName)
+      : mVSyncSource(src), mFlinger(flinger), mInterceptVSyncs(interceptVSyncs) {
+    for (auto& event : mVSyncEvent) {
+        event.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
+        event.header.id = 0;
+        event.header.timestamp = 0;
+        event.vsync.count = 0;
     }
+
+    mThread = std::thread(&EventThread::threadMain, this);
+
+    pthread_setname_np(mThread.native_handle(), threadName);
+
+    pid_t tid = pthread_gettid_np(mThread.native_handle());
+
+    // Use SCHED_FIFO to minimize jitter
+    constexpr int EVENT_THREAD_PRIORITY = 2;
+    struct sched_param param = {0};
+    param.sched_priority = EVENT_THREAD_PRIORITY;
+    if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, &param) != 0) {
+        ALOGE("Couldn't set SCHED_FIFO for EventThread");
+    }
+
+    set_sched_policy(tid, SP_FOREGROUND);
+}
+
+EventThread::~EventThread() {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mKeepRunning = false;
+        mCondition.notify_all();
+    }
+    mThread.join();
 }
 
 void EventThread::setPhaseOffset(nsecs_t phaseOffset) {
-    Mutex::Autolock _l(mLock);
+    std::lock_guard<std::mutex> lock(mMutex);
     mVSyncSource->setPhaseOffset(phaseOffset);
 }
 
-void EventThread::onFirstRef() {
-    run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
-}
-
 sp<EventThread::Connection> EventThread::createEventConnection() const {
     return new Connection(const_cast<EventThread*>(this));
 }
 
 status_t EventThread::registerDisplayEventConnection(
         const sp<EventThread::Connection>& connection) {
-    Mutex::Autolock _l(mLock);
+    std::lock_guard<std::mutex> lock(mMutex);
     mDisplayEventConnections.add(connection);
-    mCondition.broadcast();
+    mCondition.notify_all();
     return NO_ERROR;
 }
 
-void EventThread::removeDisplayEventConnection(
-        const wp<EventThread::Connection>& connection) {
-    Mutex::Autolock _l(mLock);
+void EventThread::removeDisplayEventConnection(const wp<EventThread::Connection>& connection) {
+    std::lock_guard<std::mutex> lock(mMutex);
     mDisplayEventConnections.remove(connection);
 }
 
-void EventThread::setVsyncRate(uint32_t count,
-        const sp<EventThread::Connection>& connection) {
+void EventThread::setVsyncRate(uint32_t count, const sp<EventThread::Connection>& connection) {
     if (int32_t(count) >= 0) { // server must protect against bad params
-        Mutex::Autolock _l(mLock);
+        std::lock_guard<std::mutex> lock(mMutex);
         const int32_t new_count = (count == 0) ? -1 : count;
         if (connection->count != new_count) {
             connection->count = new_count;
-            mCondition.broadcast();
+            mCondition.notify_all();
         }
     }
 }
 
-void EventThread::requestNextVsync(
-        const sp<EventThread::Connection>& connection) {
-    Mutex::Autolock _l(mLock);
+void EventThread::requestNextVsync(const sp<EventThread::Connection>& connection) {
+    std::lock_guard<std::mutex> lock(mMutex);
 
     mFlinger.resyncWithRateLimit();
 
     if (connection->count < 0) {
         connection->count = 0;
-        mCondition.broadcast();
+        mCondition.notify_all();
     }
 }
 
 void EventThread::onScreenReleased() {
-    Mutex::Autolock _l(mLock);
+    std::lock_guard<std::mutex> lock(mMutex);
     if (!mUseSoftwareVSync) {
         // disable reliance on h/w vsync
         mUseSoftwareVSync = true;
-        mCondition.broadcast();
+        mCondition.notify_all();
     }
 }
 
 void EventThread::onScreenAcquired() {
-    Mutex::Autolock _l(mLock);
+    std::lock_guard<std::mutex> lock(mMutex);
     if (mUseSoftwareVSync) {
         // resume use of h/w vsync
         mUseSoftwareVSync = false;
-        mCondition.broadcast();
+        mCondition.notify_all();
     }
 }
 
 void EventThread::onVSyncEvent(nsecs_t timestamp) {
-    Mutex::Autolock _l(mLock);
+    std::lock_guard<std::mutex> lock(mMutex);
     mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
     mVSyncEvent[0].header.id = 0;
     mVSyncEvent[0].header.timestamp = timestamp;
     mVSyncEvent[0].vsync.count++;
-    mCondition.broadcast();
+    mCondition.notify_all();
 }
 
 void EventThread::onHotplugReceived(int type, bool connected) {
     ALOGE_IF(type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES,
-            "received hotplug event for an invalid display (id=%d)", type);
+             "received hotplug event for an invalid display (id=%d)", type);
 
-    Mutex::Autolock _l(mLock);
+    std::lock_guard<std::mutex> lock(mMutex);
     if (type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
         DisplayEventReceiver::Event event;
         event.header.type = DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG;
@@ -141,54 +162,54 @@
         event.header.timestamp = systemTime();
         event.hotplug.connected = connected;
         mPendingEvents.add(event);
-        mCondition.broadcast();
+        mCondition.notify_all();
     }
 }
 
-bool EventThread::threadLoop() {
-    DisplayEventReceiver::Event event;
-    Vector< sp<EventThread::Connection> > signalConnections;
-    signalConnections = waitForEvent(&event);
+void EventThread::threadMain() NO_THREAD_SAFETY_ANALYSIS {
+    std::unique_lock<std::mutex> lock(mMutex);
+    while (mKeepRunning) {
+        DisplayEventReceiver::Event event;
+        Vector<sp<EventThread::Connection> > signalConnections;
+        signalConnections = waitForEventLocked(&lock, &event);
 
-    // dispatch events to listeners...
-    const size_t count = signalConnections.size();
-    for (size_t i=0 ; i<count ; i++) {
-        const sp<Connection>& conn(signalConnections[i]);
-        // now see if we still need to report this event
-        status_t err = conn->postEvent(event);
-        if (err == -EAGAIN || err == -EWOULDBLOCK) {
-            // The destination doesn't accept events anymore, it's probably
-            // full. For now, we just drop the events on the floor.
-            // FIXME: Note that some events cannot be dropped and would have
-            // to be re-sent later.
-            // Right-now we don't have the ability to do this.
-            ALOGW("EventThread: dropping event (%08x) for connection %p",
-                    event.header.type, conn.get());
-        } else if (err < 0) {
-            // handle any other error on the pipe as fatal. the only
-            // reasonable thing to do is to clean-up this connection.
-            // The most common error we'll get here is -EPIPE.
-            removeDisplayEventConnection(signalConnections[i]);
+        // dispatch events to listeners...
+        const size_t count = signalConnections.size();
+        for (size_t i = 0; i < count; i++) {
+            const sp<Connection>& conn(signalConnections[i]);
+            // now see if we still need to report this event
+            status_t err = conn->postEvent(event);
+            if (err == -EAGAIN || err == -EWOULDBLOCK) {
+                // The destination doesn't accept events anymore, it's probably
+                // full. For now, we just drop the events on the floor.
+                // FIXME: Note that some events cannot be dropped and would have
+                // to be re-sent later.
+                // Right-now we don't have the ability to do this.
+                ALOGW("EventThread: dropping event (%08x) for connection %p", event.header.type,
+                      conn.get());
+            } else if (err < 0) {
+                // handle any other error on the pipe as fatal. the only
+                // reasonable thing to do is to clean-up this connection.
+                // The most common error we'll get here is -EPIPE.
+                removeDisplayEventConnection(signalConnections[i]);
+            }
         }
     }
-    return true;
 }
 
 // This will return when (1) a vsync event has been received, and (2) there was
 // at least one connection interested in receiving it when we started waiting.
-Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
-        DisplayEventReceiver::Event* event)
-{
-    Mutex::Autolock _l(mLock);
-    Vector< sp<EventThread::Connection> > signalConnections;
+Vector<sp<EventThread::Connection> > EventThread::waitForEventLocked(
+        std::unique_lock<std::mutex>* lock, DisplayEventReceiver::Event* event) {
+    Vector<sp<EventThread::Connection> > signalConnections;
 
-    do {
+    while (signalConnections.isEmpty() && mKeepRunning) {
         bool eventPending = false;
         bool waitForVSync = false;
 
         size_t vsyncCount = 0;
         nsecs_t timestamp = 0;
-        for (int32_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
+        for (int32_t i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; i++) {
             timestamp = mVSyncEvent[i].header.timestamp;
             if (timestamp) {
                 // we have a vsync event to dispatch
@@ -214,7 +235,7 @@
 
         // find out connections waiting for events
         size_t count = mDisplayEventConnections.size();
-        for (size_t i=0 ; i<count ; ) {
+        for (size_t i = 0; i < count;) {
             sp<Connection> connection(mDisplayEventConnections[i].promote());
             if (connection != nullptr) {
                 bool added = false;
@@ -231,7 +252,7 @@
                             signalConnections.add(connection);
                             added = true;
                         } else if (connection->count == 1 ||
-                                (vsyncCount % connection->count) == 0) {
+                                   (vsyncCount % connection->count) == 0) {
                             // continuous event, and time to report it
                             signalConnections.add(connection);
                             added = true;
@@ -285,8 +306,8 @@
                 // use a (long) timeout when waiting for h/w vsync, and
                 // generate fake events when necessary.
                 bool softwareSync = mUseSoftwareVSync;
-                nsecs_t timeout = softwareSync ? ms2ns(16) : ms2ns(1000);
-                if (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) {
+                auto timeout = softwareSync ? 16ms : 1000ms;
+                if (mCondition.wait_for(*lock, timeout) == std::cv_status::timeout) {
                     if (!softwareSync) {
                         ALOGW("Timed out waiting for hw vsync; faking it");
                     }
@@ -302,10 +323,10 @@
                 // h/w vsync should be disabled, so this will wait until we
                 // get a new connection, or an existing connection becomes
                 // interested in receiving vsync again.
-                mCondition.wait(mLock);
+                mCondition.wait(*lock);
             }
         }
-    } while (signalConnections.isEmpty());
+    }
 
     // here we're guaranteed to have a timestamp and some connections to signal
     // (The connections might have dropped out of mDisplayEventConnections
@@ -318,7 +339,7 @@
         // never enable h/w VSYNC when screen is off
         if (!mVsyncEnabled) {
             mVsyncEnabled = true;
-            mVSyncSource->setCallback(static_cast<VSyncSource::Callback*>(this));
+            mVSyncSource->setCallback(this);
             mVSyncSource->setVSyncEnabled(true);
         }
     }
@@ -334,29 +355,23 @@
 }
 
 void EventThread::dump(String8& result) const {
-    Mutex::Autolock _l(mLock);
-    result.appendFormat("VSYNC state: %s\n",
-            mDebugVsyncEnabled?"enabled":"disabled");
-    result.appendFormat("  soft-vsync: %s\n",
-            mUseSoftwareVSync?"enabled":"disabled");
+    std::lock_guard<std::mutex> lock(mMutex);
+    result.appendFormat("VSYNC state: %s\n", mDebugVsyncEnabled ? "enabled" : "disabled");
+    result.appendFormat("  soft-vsync: %s\n", mUseSoftwareVSync ? "enabled" : "disabled");
     result.appendFormat("  numListeners=%zu,\n  events-delivered: %u\n",
-            mDisplayEventConnections.size(),
-            mVSyncEvent[DisplayDevice::DISPLAY_PRIMARY].vsync.count);
-    for (size_t i=0 ; i<mDisplayEventConnections.size() ; i++) {
-        sp<Connection> connection =
-                mDisplayEventConnections.itemAt(i).promote();
-        result.appendFormat("    %p: count=%d\n",
-                connection.get(), connection != nullptr ? connection->count : 0);
+                        mDisplayEventConnections.size(),
+                        mVSyncEvent[DisplayDevice::DISPLAY_PRIMARY].vsync.count);
+    for (size_t i = 0; i < mDisplayEventConnections.size(); i++) {
+        sp<Connection> connection = mDisplayEventConnections.itemAt(i).promote();
+        result.appendFormat("    %p: count=%d\n", connection.get(),
+                            connection != nullptr ? connection->count : 0);
     }
 }
 
 // ---------------------------------------------------------------------------
 
-EventThread::Connection::Connection(
-        const sp<EventThread>& eventThread)
-    : count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize)
-{
-}
+EventThread::Connection::Connection(EventThread* eventThread)
+      : count(-1), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {}
 
 EventThread::Connection::~Connection() {
     // do nothing here -- clean-up will happen automatically
@@ -382,12 +397,11 @@
     mEventThread->requestNextVsync(this);
 }
 
-status_t EventThread::Connection::postEvent(
-        const DisplayEventReceiver::Event& event) {
+status_t EventThread::Connection::postEvent(const DisplayEventReceiver::Event& event) {
     ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
     return size < 0 ? status_t(size) : status_t(NO_ERROR);
 }
 
 // ---------------------------------------------------------------------------
 
-}; // namespace android
+} // namespace android
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 0823839..9ae8fb2 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -14,18 +14,21 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_SURFACE_FLINGER_EVENT_THREAD_H
-#define ANDROID_SURFACE_FLINGER_EVENT_THREAD_H
+#pragma once
 
 #include <stdint.h>
 #include <sys/types.h>
+#include <condition_variable>
+#include <mutex>
+#include <thread>
 
-#include <private/gui/BitTube.h>
+#include <android-base/thread_annotations.h>
+
 #include <gui/DisplayEventReceiver.h>
 #include <gui/IDisplayEventConnection.h>
+#include <private/gui/BitTube.h>
 
 #include <utils/Errors.h>
-#include <utils/threads.h>
 #include <utils/SortedVector.h>
 
 #include "DisplayDevice.h"
@@ -39,10 +42,9 @@
 
 // ---------------------------------------------------------------------------
 
-
-class VSyncSource : public virtual RefBase {
+class VSyncSource {
 public:
-    class Callback: public virtual RefBase {
+    class Callback {
     public:
         virtual ~Callback() {}
         virtual void onVSyncEvent(nsecs_t when) = 0;
@@ -50,14 +52,14 @@
 
     virtual ~VSyncSource() {}
     virtual void setVSyncEnabled(bool enable) = 0;
-    virtual void setCallback(const sp<Callback>& callback) = 0;
+    virtual void setCallback(Callback* callback) = 0;
     virtual void setPhaseOffset(nsecs_t phaseOffset) = 0;
 };
 
-class EventThread : public Thread, private VSyncSource::Callback {
+class EventThread : private VSyncSource::Callback {
     class Connection : public BnDisplayEventConnection {
     public:
-        explicit Connection(const sp<EventThread>& eventThread);
+        explicit Connection(EventThread* eventThread);
         status_t postEvent(const DisplayEventReceiver::Event& event);
 
         // count >= 1 : continuous event. count is the vsync rate
@@ -70,14 +72,15 @@
         virtual void onFirstRef();
         status_t stealReceiveChannel(gui::BitTube* outChannel) override;
         status_t setVsyncRate(uint32_t count) override;
-        void requestNextVsync() override;    // asynchronous
-        sp<EventThread> const mEventThread;
+        void requestNextVsync() override; // asynchronous
+        EventThread* const mEventThread;
         gui::BitTube mChannel;
     };
 
 public:
-
-    EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger, bool interceptVSyncs);
+    EventThread(VSyncSource* src, SurfaceFlinger& flinger, bool interceptVSyncs,
+                const char* threadName);
+    ~EventThread();
 
     sp<Connection> createEventConnection() const;
     status_t registerDisplayEventConnection(const sp<Connection>& connection);
@@ -94,47 +97,46 @@
     // called when receiving a hotplug event
     void onHotplugReceived(int type, bool connected);
 
-    Vector< sp<EventThread::Connection> > waitForEvent(
-            DisplayEventReceiver::Event* event);
-
     void dump(String8& result) const;
 
     void setPhaseOffset(nsecs_t phaseOffset);
 
 private:
-    virtual bool        threadLoop();
-    virtual void        onFirstRef();
-
-    virtual void onVSyncEvent(nsecs_t timestamp);
+    void threadMain();
+    Vector<sp<EventThread::Connection>> waitForEventLocked(std::unique_lock<std::mutex>* lock,
+                                                           DisplayEventReceiver::Event* event)
+            REQUIRES(mMutex);
 
     void removeDisplayEventConnection(const wp<Connection>& connection);
-    void enableVSyncLocked();
-    void disableVSyncLocked();
+    void enableVSyncLocked() REQUIRES(mMutex);
+    void disableVSyncLocked() REQUIRES(mMutex);
+
+    // Implements VSyncSource::Callback
+    void onVSyncEvent(nsecs_t timestamp) override;
 
     // constants
-    sp<VSyncSource> mVSyncSource;
+    VSyncSource* mVSyncSource GUARDED_BY(mMutex) = nullptr;
     SurfaceFlinger& mFlinger;
 
-    mutable Mutex mLock;
-    mutable Condition mCondition;
+    std::thread mThread;
+    mutable std::mutex mMutex;
+    mutable std::condition_variable mCondition;
 
     // protected by mLock
-    SortedVector< wp<Connection> > mDisplayEventConnections;
-    Vector< DisplayEventReceiver::Event > mPendingEvents;
-    DisplayEventReceiver::Event mVSyncEvent[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES];
-    bool mUseSoftwareVSync;
-    bool mVsyncEnabled;
+    SortedVector<wp<Connection>> mDisplayEventConnections GUARDED_BY(mMutex);
+    Vector<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);
+    DisplayEventReceiver::Event mVSyncEvent[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES] GUARDED_BY(
+            mMutex);
+    bool mUseSoftwareVSync GUARDED_BY(mMutex) = false;
+    bool mVsyncEnabled GUARDED_BY(mMutex) = false;
+    bool mKeepRunning GUARDED_BY(mMutex) = true;
 
     // for debugging
-    bool mDebugVsyncEnabled;
+    bool mDebugVsyncEnabled GUARDED_BY(mMutex) = false;
 
-    const bool mInterceptVSyncs;
+    const bool mInterceptVSyncs = false;
 };
 
 // ---------------------------------------------------------------------------
 
 }; // namespace android
-
-// ---------------------------------------------------------------------------
-
-#endif /* ANDROID_SURFACE_FLINGER_EVENT_THREAD_H */
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index 0b1199c..5a6ff4d 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -14,32 +14,29 @@
  * limitations under the License.
  */
 
-#include <stdint.h>
 #include <errno.h>
+#include <stdint.h>
 #include <sys/types.h>
 
 #include <binder/IPCThreadState.h>
 
-#include <utils/threads.h>
-#include <utils/Timers.h>
 #include <utils/Log.h>
+#include <utils/Timers.h>
+#include <utils/threads.h>
 
 #include <gui/IDisplayEventConnection.h>
 
-#include "MessageQueue.h"
 #include "EventThread.h"
+#include "MessageQueue.h"
 #include "SurfaceFlinger.h"
 
 namespace android {
 
 // ---------------------------------------------------------------------------
 
-MessageBase::MessageBase()
-    : MessageHandler() {
-}
+MessageBase::MessageBase() : MessageHandler() {}
 
-MessageBase::~MessageBase() {
-}
+MessageBase::~MessageBase() {}
 
 void MessageBase::handleMessage(const Message&) {
     this->handler();
@@ -75,22 +72,17 @@
 
 // ---------------------------------------------------------------------------
 
-MessageQueue::MessageQueue()
-{
-}
+MessageQueue::MessageQueue() {}
 
-MessageQueue::~MessageQueue() {
-}
+MessageQueue::~MessageQueue() {}
 
-void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
-{
+void MessageQueue::init(const sp<SurfaceFlinger>& flinger) {
     mFlinger = flinger;
     mLooper = new Looper(true);
     mHandler = new Handler(*this);
 }
 
-void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
-{
+void MessageQueue::setEventThread(EventThread* eventThread) {
     if (mEventThread == eventThread) {
         return;
     }
@@ -102,8 +94,8 @@
     mEventThread = eventThread;
     mEvents = eventThread->createEventConnection();
     mEvents->stealReceiveChannel(&mEventTube);
-    mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
-            MessageQueue::cb_eventReceiver, this);
+    mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
+                   this);
 }
 
 void MessageQueue::waitMessage() {
@@ -128,9 +120,7 @@
     } while (true);
 }
 
-status_t MessageQueue::postMessage(
-        const sp<MessageBase>& messageHandler, nsecs_t relTime)
-{
+status_t MessageQueue::postMessage(const sp<MessageBase>& messageHandler, nsecs_t relTime) {
     const Message dummyMessage;
     if (relTime > 0) {
         mLooper->sendMessageDelayed(relTime, messageHandler, dummyMessage);
@@ -140,7 +130,6 @@
     return NO_ERROR;
 }
 
-
 void MessageQueue::invalidate() {
     mEvents->requestNextVsync();
 }
@@ -150,7 +139,7 @@
 }
 
 int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
-    MessageQueue* queue = reinterpret_cast<MessageQueue *>(data);
+    MessageQueue* queue = reinterpret_cast<MessageQueue*>(data);
     return queue->eventReceiver(fd, events);
 }
 
@@ -158,7 +147,7 @@
     ssize_t n;
     DisplayEventReceiver::Event buffer[8];
     while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) {
-        for (int i=0 ; i<n ; i++) {
+        for (int i = 0; i < n; i++) {
             if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
                 mHandler->dispatchInvalidate();
                 break;
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index 14f50bb..dcfc716 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -17,16 +17,16 @@
 #ifndef ANDROID_MESSAGE_QUEUE_H
 #define ANDROID_MESSAGE_QUEUE_H
 
-#include <stdint.h>
 #include <errno.h>
+#include <stdint.h>
 #include <sys/types.h>
 
-#include <utils/threads.h>
-#include <utils/Timers.h>
 #include <utils/Looper.h>
+#include <utils/Timers.h>
+#include <utils/threads.h>
 
-#include <private/gui/BitTube.h>
 #include <gui/DisplayEventReceiver.h>
+#include <private/gui/BitTube.h>
 
 #include "Barrier.h"
 
@@ -40,11 +40,10 @@
 
 // ---------------------------------------------------------------------------
 
-class MessageBase : public MessageHandler
-{
+class MessageBase : public MessageHandler {
 public:
     MessageBase();
-    
+
     // return true if message has a handler
     virtual bool handler() = 0;
 
@@ -79,15 +78,12 @@
 
 class MessageQueue {
     class Handler : public MessageHandler {
-        enum {
-            eventMaskInvalidate     = 0x1,
-            eventMaskRefresh        = 0x2,
-            eventMaskTransaction    = 0x4
-        };
+        enum { eventMaskInvalidate = 0x1, eventMaskRefresh = 0x2, eventMaskTransaction = 0x4 };
         MessageQueue& mQueue;
         int32_t mEventMask;
+
     public:
-        explicit Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) { }
+        explicit Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) {}
         virtual void handleMessage(const Message& message);
         void dispatchRefresh();
         void dispatchInvalidate();
@@ -97,28 +93,27 @@
 
     sp<SurfaceFlinger> mFlinger;
     sp<Looper> mLooper;
-    sp<EventThread> mEventThread;
+    EventThread* mEventThread;
     sp<IDisplayEventConnection> mEvents;
     gui::BitTube mEventTube;
     sp<Handler> mHandler;
 
-
     static int cb_eventReceiver(int fd, int events, void* data);
     int eventReceiver(int fd, int events);
 
 public:
     enum {
-        INVALIDATE  = 0,
-        REFRESH     = 1,
+        INVALIDATE = 0,
+        REFRESH = 1,
     };
 
     MessageQueue();
     ~MessageQueue();
     void init(const sp<SurfaceFlinger>& flinger);
-    void setEventThread(const sp<EventThread>& events);
+    void setEventThread(EventThread* events);
 
     void waitMessage();
-    status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0);
+    status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime = 0);
 
     // sends INVALIDATE message at next VSYNC
     void invalidate();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index d8740d9..1054c32 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -424,7 +424,7 @@
     postMessageAsync(new MessageDestroyGLTexture(getRenderEngine(), texture));
 }
 
-class DispSyncSource : public VSyncSource, private DispSync::Callback {
+class DispSyncSource final : public VSyncSource, private DispSync::Callback {
 public:
     DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
         const char* name) :
@@ -435,14 +435,13 @@
             mVsyncEventLabel(String8::format("VSYNC-%s", name)),
             mDispSync(dispSync),
             mCallbackMutex(),
-            mCallback(),
             mVsyncMutex(),
             mPhaseOffset(phaseOffset),
             mEnabled(false) {}
 
-    virtual ~DispSyncSource() {}
+    ~DispSyncSource() override = default;
 
-    virtual void setVSyncEnabled(bool enable) {
+    void setVSyncEnabled(bool enable) override {
         Mutex::Autolock lock(mVsyncMutex);
         if (enable) {
             status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
@@ -464,12 +463,12 @@
         mEnabled = enable;
     }
 
-    virtual void setCallback(const sp<VSyncSource::Callback>& callback) {
+    void setCallback(VSyncSource::Callback* callback) override{
         Mutex::Autolock lock(mCallbackMutex);
         mCallback = callback;
     }
 
-    virtual void setPhaseOffset(nsecs_t phaseOffset) {
+    void setPhaseOffset(nsecs_t phaseOffset) override {
         Mutex::Autolock lock(mVsyncMutex);
 
         // Normalize phaseOffset to [0, period)
@@ -506,7 +505,7 @@
 
 private:
     virtual void onDispSyncEvent(nsecs_t when) {
-        sp<VSyncSource::Callback> callback;
+        VSyncSource::Callback* callback;
         {
             Mutex::Autolock lock(mCallbackMutex);
             callback = mCallback;
@@ -533,37 +532,36 @@
     DispSync* mDispSync;
 
     Mutex mCallbackMutex; // Protects the following
-    sp<VSyncSource::Callback> mCallback;
+    VSyncSource::Callback* mCallback = nullptr;
 
     Mutex mVsyncMutex; // Protects the following
     nsecs_t mPhaseOffset;
     bool mEnabled;
 };
 
-class InjectVSyncSource : public VSyncSource {
+class InjectVSyncSource final : public VSyncSource {
 public:
-    InjectVSyncSource() {}
+    InjectVSyncSource() = default;
+    ~InjectVSyncSource() override = default;
 
-    virtual ~InjectVSyncSource() {}
-
-    virtual void setCallback(const sp<VSyncSource::Callback>& callback) {
+    void setCallback(VSyncSource::Callback* callback) override {
         std::lock_guard<std::mutex> lock(mCallbackMutex);
         mCallback = callback;
     }
 
-    virtual void onInjectSyncEvent(nsecs_t when) {
+    void onInjectSyncEvent(nsecs_t when) {
         std::lock_guard<std::mutex> lock(mCallbackMutex);
         if (mCallback) {
             mCallback->onVSyncEvent(when);
         }
     }
 
-    virtual void setVSyncEnabled(bool) {}
-    virtual void setPhaseOffset(nsecs_t) {}
+    void setVSyncEnabled(bool) override {}
+    void setPhaseOffset(nsecs_t) override {}
 
 private:
     std::mutex mCallbackMutex; // Protects the following
-    sp<VSyncSource::Callback> mCallback;
+    VSyncSource::Callback* mCallback = nullptr;
 };
 
 // Do not call property_set on main thread which will be blocked by init
@@ -577,23 +575,16 @@
     Mutex::Autolock _l(mStateLock);
 
     // start the EventThread
-    sp<VSyncSource> vsyncSrc =
-            new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs, true, "app");
-    mEventThread = new EventThread(vsyncSrc, *this, false);
-    sp<VSyncSource> sfVsyncSrc =
-            new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
-    mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
-    mEventQueue.setEventThread(mSFEventThread);
 
-    // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
-    struct sched_param param = {0};
-    param.sched_priority = 2;
-    if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, &param) != 0) {
-        ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
-    }
-    if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, &param) != 0) {
-        ALOGE("Couldn't set SCHED_FIFO for EventThread");
-    }
+    mEventThreadSource = std::make_unique<DispSyncSource>(
+            &mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs, true, "app");
+    mEventThread = std::make_unique<EventThread>(
+            mEventThreadSource.get(), *this, false, "sfEventThread");
+    mSfEventThreadSource = std::make_unique<DispSyncSource>(
+            &mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
+    mSFEventThread = std::make_unique<EventThread>(
+            mSfEventThreadSource.get(), *this, true, "appEventThread");
+    mEventQueue.setEventThread(mSFEventThread.get());
 
     // Get a RenderEngine for the given display / config (can't fail)
     getBE().mRenderEngine = RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888,
@@ -636,8 +627,9 @@
         }
     }
 
-    mEventControlThread = new EventControlThread(this);
-    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
+    mEventControlThread = std::make_unique<EventControlThread>([this](bool enabled) {
+        setVsyncEnabled(HWC_DISPLAY_PRIMARY, enabled);
+    });
 
     // initialize our drawing state
     mDrawingState = mCurrentState;
@@ -1072,13 +1064,14 @@
         if (enable) {
             ALOGV("VSync Injections enabled");
             if (mVSyncInjector.get() == nullptr) {
-                mVSyncInjector = new InjectVSyncSource();
-                mInjectorEventThread = new EventThread(mVSyncInjector, *this, false);
+                mVSyncInjector = std::make_unique<InjectVSyncSource>();
+                mInjectorEventThread = std::make_unique<EventThread>(
+                        mVSyncInjector.get(), *this, false, "injEvThread");
             }
-            mEventQueue.setEventThread(mInjectorEventThread);
+            mEventQueue.setEventThread(mInjectorEventThread.get());
         } else {
             ALOGV("VSync Injections disabled");
-            mEventQueue.setEventThread(mSFEventThread);
+            mEventQueue.setEventThread(mSFEventThread.get());
         }
 
         mInjectVSyncs = enable;
@@ -1101,7 +1094,8 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const {
+status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const
+        NO_THREAD_SAFETY_ANALYSIS {
     IPCThreadState* ipc = IPCThreadState::self();
     const int pid = ipc->getCallingPid();
     const int uid = ipc->getCallingUid();
@@ -3567,7 +3561,8 @@
 
 // ---------------------------------------------------------------------------
 
-status_t SurfaceFlinger::doDump(int fd, const Vector<String16>& args, bool asProto) {
+status_t SurfaceFlinger::doDump(int fd, const Vector<String16>& args, bool asProto)
+        NO_THREAD_SAFETY_ANALYSIS {
     String8 result;
 
     IPCThreadState* ipc = IPCThreadState::self();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1349bec..19dd059 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -316,6 +316,9 @@
     friend class BufferLayer;
     friend class MonitoredProducer;
 
+    // For unit tests
+    friend class TestableSurfaceFlinger;
+
     // This value is specified in number of frames.  Log frame stats at most
     // every half hour.
     enum { LOG_FRAME_STATS_PERIOD =  30*60*60 };
@@ -716,11 +719,13 @@
     // constant members (no synchronization needed for access)
     nsecs_t mBootTime;
     bool mGpuToCpuSupported;
-    sp<EventThread> mEventThread;
-    sp<EventThread> mSFEventThread;
-    sp<EventThread> mInjectorEventThread;
-    sp<InjectVSyncSource> mVSyncInjector;
-    sp<EventControlThread> mEventControlThread;
+    std::unique_ptr<EventThread> mEventThread;
+    std::unique_ptr<EventThread> mSFEventThread;
+    std::unique_ptr<EventThread> mInjectorEventThread;
+    std::unique_ptr<VSyncSource> mEventThreadSource;
+    std::unique_ptr<VSyncSource> mSfEventThreadSource;
+    std::unique_ptr<InjectVSyncSource> mVSyncInjector;
+    std::unique_ptr<EventControlThread> mEventControlThread;
     sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES];
 
     // Can only accessed from the main thread, these members
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
new file mode 100644
index 0000000..7d3da32
--- /dev/null
+++ b/services/surfaceflinger/tests/Android.bp
@@ -0,0 +1,50 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_test {
+    name: "SurfaceFlinger_test",
+    defaults: ["surfaceflinger_defaults"],
+    tags: ["test"],
+    test_suites: ["device-tests"],
+    srcs: [
+        "Stress_test.cpp",
+        "SurfaceInterceptor_test.cpp",
+        "Transaction_test.cpp",
+    ],
+    data: ["SurfaceFlinger_test.filter"],
+    static_libs: [
+        "libtrace_proto",
+    ],
+    shared_libs: [
+        "libandroid",
+        "libbinder",
+        "libcutils",
+        "libEGL",
+        "libGLESv2",
+        "libgui",
+        "liblog",
+        "libprotobuf-cpp-full",
+        "libui",
+        "libutils",
+    ]
+
+}
+
+subdirs = [
+    "fakehwc",
+    "hwc2",
+    "unittests",
+    "vsync",
+    "waitforvsync",
+]
diff --git a/services/surfaceflinger/tests/Android.mk b/services/surfaceflinger/tests/Android.mk
deleted file mode 100644
index 43e22a0..0000000
--- a/services/surfaceflinger/tests/Android.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-# Build the unit tests,
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE := SurfaceFlinger_test
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
-   Transaction_test.cpp \
-   Stress_test.cpp \
-   SurfaceInterceptor_test.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libEGL \
-    libGLESv2 \
-    libbinder \
-    libcutils \
-    libgui \
-    libprotobuf-cpp-full \
-    libui \
-    libutils \
-    libandroid \
-    liblog
-
-LOCAL_STATIC_LIBRARIES := libtrace_proto
-
-LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
-
-LOCAL_TEST_DATA = SurfaceFlinger_test.filter
-
-# Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
-# to integrate with auto-test framework.
-include $(BUILD_NATIVE_TEST)
-
-# Include subdirectory makefiles
-# ============================================================
-
-# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
-# team really wants is to build the stuff defined by this makefile.
-ifeq (,$(ONE_SHOT_MAKEFILE))
-include $(call first-makefiles-under,$(LOCAL_PATH))
-endif
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index eeb0f54..8e0ba83 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -1,5 +1,8 @@
 cc_test {
     name: "sffakehwc_test",
+    defaults: ["surfaceflinger_defaults"],
+    tags: ["test"],
+    test_suites: ["device-tests"],
     srcs: [
          "FakeComposerClient.cpp",
          "FakeComposerService.cpp",
@@ -7,36 +10,31 @@
          "SFFakeHwc_test.cpp"
     ],
     shared_libs: [
-        "libcutils",
-        "libutils",
-        "libbinder",
-        "libui",
-        "libgui",
-        "liblog",
-        "libnativewindow",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.mapper@2.0",
-        "libhwbinder",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "libfmq",
+        "libgui",
         "libhardware",
         "libhidlbase",
-        "libsync",
-        "libfmq",
-        "libbase",
         "libhidltransport",
-        "liblayers_proto"
+        "libhwbinder",
+        "liblayers_proto",
+        "liblog",
+        "libnativewindow",
+        "libsync",
+        "libui",
+        "libutils",
     ],
     static_libs: [
         "libhwcomposer-client",
-        "libsurfaceflingerincludes",
         "libtrace_proto",
         "libgmock"
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
+        "libsurfaceflinger_headers",
     ],
-    cppflags: [
-        "-std=c++1z",
-    ],
-    tags: ["tests"],
-    test_suites: ["device-tests"]
 }
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/hwc2/Android.bp b/services/surfaceflinger/tests/hwc2/Android.bp
new file mode 100644
index 0000000..e980522
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Android.bp
@@ -0,0 +1,56 @@
+// 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.
+
+cc_test {
+    name: "test-hwc2",
+    defaults: ["surfaceflinger_defaults"],
+    tags: ["test"],
+    cflags: [
+        "-DEGL_EGLEXT_PROTOTYPES",
+        "-DGL_GLEXT_PROTOTYPES",
+        "-fno-builtin",
+        "-fstack-protector-all",
+        "-g",
+        "-Wextra",
+    ],
+    srcs: [
+        "Hwc2Test.cpp",
+        "Hwc2TestProperties.cpp",
+        "Hwc2TestLayer.cpp",
+        "Hwc2TestLayers.cpp",
+        "Hwc2TestBuffer.cpp",
+        "Hwc2TestClientTarget.cpp",
+        "Hwc2TestVirtualDisplay.cpp",
+        "Hwc2TestPixelComparator.cpp",
+    ],
+    static_libs: [
+        "libadf",
+        "libadfhwc",
+        "libbase",
+        "libmath",
+    ],
+    shared_libs: [
+        "android.hardware.graphics.common@1.0",
+        "libcutils",
+        "libEGL",
+        "libGLESv2",
+        "libgui",
+        "libhardware",
+        "libhwui",
+        "liblog",
+        "libsync",
+        "libui",
+        "libutils",
+    ],
+}
diff --git a/services/surfaceflinger/tests/hwc2/Android.mk b/services/surfaceflinger/tests/hwc2/Android.mk
deleted file mode 100644
index 010ac9c..0000000
--- a/services/surfaceflinger/tests/hwc2/Android.mk
+++ /dev/null
@@ -1,57 +0,0 @@
-#
-# Copyright (C) 2016 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := test-hwc2
-LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS += \
-    -fstack-protector-all \
-    -g \
-    -Wall -Wextra \
-    -Werror \
-    -fno-builtin \
-    -DEGL_EGLEXT_PROTOTYPES \
-    -DGL_GLEXT_PROTOTYPES
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libutils \
-    libhardware \
-    libEGL \
-    libGLESv2 \
-    libui \
-    libgui \
-    liblog \
-    libsync \
-    libhwui \
-    android.hardware.graphics.common@1.0
-LOCAL_STATIC_LIBRARIES := \
-    libbase \
-    libadf \
-    libadfhwc \
-    libmath
-LOCAL_SRC_FILES := \
-    Hwc2Test.cpp \
-    Hwc2TestProperties.cpp \
-    Hwc2TestLayer.cpp \
-    Hwc2TestLayers.cpp \
-    Hwc2TestBuffer.cpp \
-    Hwc2TestClientTarget.cpp \
-    Hwc2TestVirtualDisplay.cpp \
-    Hwc2TestPixelComparator.cpp
-
-include $(BUILD_NATIVE_TEST)
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
new file mode 100644
index 0000000..72e0a0f
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -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.
+
+cc_test {
+    name: "libsurfaceflinger_unittest",
+    tags: ["test"],
+    defaults: ["libsurfaceflinger_defaults"],
+    test_suites: ["device-tests"],
+    srcs: [
+        ":libsurfaceflinger_sources",
+        "DisplayTransactionTest.cpp",
+    ],
+    static_libs: [
+        "libgmock",
+    ],
+    header_libs: [
+        "libsurfaceflinger_headers",
+    ],
+}
diff --git a/services/surfaceflinger/tests/unittests/AndroidTest.xml b/services/surfaceflinger/tests/unittests/AndroidTest.xml
new file mode 100644
index 0000000..5e8b03b
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for libsurfaceflinger_unittest">
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="libsurfaceflinger_unittest->/data/local/tmp/libsurfaceflinger_unittest" />
+    </target_preparer>
+    <option name="test-suite-tag" value="apct" />
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="libsurfaceflinger_unittest" />
+    </test>
+</configuration>
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
new file mode 100644
index 0000000..fc1b564
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "LibSurfaceFlingerUnittests"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <log/log.h>
+
+#include "TestableSurfaceFlinger.h"
+
+namespace android {
+namespace {
+
+class DisplayTransactionTest : public testing::Test {
+protected:
+    DisplayTransactionTest();
+    ~DisplayTransactionTest() override;
+
+    void setupComposer(int virtualDisplayCount);
+    void setupPrimaryDisplay(int width, int height);
+
+    TestableSurfaceFlinger mFlinger;
+};
+
+DisplayTransactionTest::DisplayTransactionTest() {
+    const ::testing::TestInfo* const test_info =
+            ::testing::UnitTest::GetInstance()->current_test_info();
+    ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+}
+
+DisplayTransactionTest::~DisplayTransactionTest() {
+    const ::testing::TestInfo* const test_info =
+            ::testing::UnitTest::GetInstance()->current_test_info();
+    ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
+}
+
+TEST_F(DisplayTransactionTest, PlaceholderTrivialTest) {
+    auto result = mFlinger.getDefaultDisplayDeviceLocked();
+    EXPECT_EQ(nullptr, result.get());
+
+    EXPECT_EQ(nullptr, mFlinger.mutableBuiltinDisplays()[0].get());
+    mFlinger.mutableBuiltinDisplays()[0] = new BBinder();
+    EXPECT_NE(nullptr, mFlinger.mutableBuiltinDisplays()[0].get());
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
new file mode 100644
index 0000000..4aa59a5
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -0,0 +1,45 @@
+/*
+ * 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 "DisplayDevice.h"
+#include "SurfaceFlinger.h"
+
+namespace android {
+
+class TestableSurfaceFlinger {
+public:
+    // Extend this as needed for accessing SurfaceFlinger private (and public)
+    // functions.
+
+    /* ------------------------------------------------------------------------
+     * Forwarding for functions being tested
+     */
+    auto getDefaultDisplayDeviceLocked() const { return mFlinger->getDefaultDisplayDeviceLocked(); }
+
+    auto processDisplayChangesLocked() { return mFlinger->processDisplayChangesLocked(); }
+
+    /* ------------------------------------------------------------------------
+     * Read-write access to private data to set up preconditions and assert
+     * post-conditions.
+     */
+    auto& mutableBuiltinDisplays() { return mFlinger->mBuiltinDisplays; }
+
+    sp<SurfaceFlinger> mFlinger = new SurfaceFlinger();
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/vsync/Android.bp b/services/surfaceflinger/tests/vsync/Android.bp
new file mode 100644
index 0000000..d04efda
--- /dev/null
+++ b/services/surfaceflinger/tests/vsync/Android.bp
@@ -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.
+
+cc_binary {
+    name: "test-vsync-events",
+    defaults: ["surfaceflinger_defaults"],
+    tags: ["test"],
+    srcs: [
+        "vsync.cpp",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libcutils",
+        "libgui",
+        "libui",
+        "libutils",
+    ]
+
+}
diff --git a/services/surfaceflinger/tests/vsync/Android.mk b/services/surfaceflinger/tests/vsync/Android.mk
deleted file mode 100644
index 8e41617..0000000
--- a/services/surfaceflinger/tests/vsync/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	vsync.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libutils \
-	libbinder \
-    libui \
-    libgui
-
-LOCAL_MODULE:= test-vsync-events
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -Werror
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/tests/waitforvsync/Android.bp b/services/surfaceflinger/tests/waitforvsync/Android.bp
new file mode 100644
index 0000000..cb6d0fd
--- /dev/null
+++ b/services/surfaceflinger/tests/waitforvsync/Android.bp
@@ -0,0 +1,26 @@
+// 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.
+
+cc_binary {
+    name: "test-waitforvsync",
+    cflags: [
+        "-Werror",
+    ],
+    srcs: [
+        "waitforvsync.cpp",
+    ],
+    shared_libs: [
+        "libcutils",
+    ]
+}
diff --git a/services/surfaceflinger/tests/waitforvsync/Android.mk b/services/surfaceflinger/tests/waitforvsync/Android.mk
deleted file mode 100644
index 932d2be..0000000
--- a/services/surfaceflinger/tests/waitforvsync/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	waitforvsync.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-
-LOCAL_MODULE:= test-waitforvsync
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -Werror
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/version-script32.txt b/services/surfaceflinger/version-script32.txt
new file mode 100644
index 0000000..2340785
--- /dev/null
+++ b/services/surfaceflinger/version-script32.txt
@@ -0,0 +1,12 @@
+{
+global:
+  EnsureFrontOfChain;
+  AddSpecialSignalHandlerFn;
+  RemoveSpecialSignalHandlerFn;
+  bsd_signal;
+  sigaction;
+  signal;
+  sigprocmask;
+local:
+  *;
+};
diff --git a/services/surfaceflinger/version-script64.txt b/services/surfaceflinger/version-script64.txt
new file mode 100644
index 0000000..acf3630
--- /dev/null
+++ b/services/surfaceflinger/version-script64.txt
@@ -0,0 +1,11 @@
+{
+global:
+  EnsureFrontOfChain;
+  AddSpecialSignalHandlerFn;
+  RemoveSpecialSignalHandlerFn;
+  sigaction;
+  signal;
+  sigprocmask;
+local:
+  *;
+};
diff --git a/vulkan/libvulkan/stubhal.cpp b/vulkan/libvulkan/stubhal.cpp
index 726e854..7404b94 100644
--- a/vulkan/libvulkan/stubhal.cpp
+++ b/vulkan/libvulkan/stubhal.cpp
@@ -97,6 +97,14 @@
     return VK_SUCCESS;
 }
 
+VKAPI_ATTR VkResult
+EnumeratePhysicalDeviceGroups(VkInstance /*instance*/,
+                              uint32_t* count,
+                              VkPhysicalDeviceGroupProperties* /*properties*/) {
+    *count = 0;
+    return VK_SUCCESS;
+}
+
 VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance,
                                                   const char* name) {
     if (strcmp(name, "vkCreateInstance") == 0)
@@ -108,6 +116,9 @@
             EnumerateInstanceExtensionProperties);
     if (strcmp(name, "vkEnumeratePhysicalDevices") == 0)
         return reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices);
+    if (strcmp(name, "vkEnumeratePhysicalDeviceGroups") == 0)
+        return reinterpret_cast<PFN_vkVoidFunction>(
+            EnumeratePhysicalDeviceGroups);
     if (strcmp(name, "vkGetInstanceProcAddr") == 0)
         return reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr);
     // Per the spec, return NULL if instance is NULL.