Merge "Fix WM input limitations on secondary displays (2/4)"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 9216e75..4362019 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1290,6 +1290,8 @@
 
     DumpPacketStats();
 
+    RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
+
     DoKmsg();
 
     DumpIpAddrAndRules();
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 9e32bc6..2470a1d 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -95,15 +95,6 @@
 static constexpr size_t kSha256Size = 32;
 static constexpr const char* kPropApkVerityMode = "ro.apk_verity.mode";
 
-// NOTE: keep in sync with Installer
-static constexpr int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
-static constexpr int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9;
-static constexpr int FLAG_USE_QUOTA = 1 << 12;
-static constexpr int FLAG_FREE_CACHE_V2 = 1 << 13;
-static constexpr int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 1 << 14;
-static constexpr int FLAG_FREE_CACHE_NOOP = 1 << 15;
-static constexpr int FLAG_FORCE = 1 << 16;
-
 namespace {
 
 constexpr const char* kDump = "android.permission.DUMP";
@@ -613,6 +604,31 @@
                 remove_path_xattr(path, kXattrInodeCodeCache);
             }
         }
+
+        auto extPath = findDataMediaPath(uuid, userId);
+        if (flags & FLAG_CLEAR_CACHE_ONLY) {
+            // Clear only cached data from shared storage
+            path = StringPrintf("%s/Android/data/%s/cache", extPath.c_str(), pkgname);
+            if (delete_dir_contents(path, true) != 0) {
+                res = error("Failed to delete contents of " + path);
+            }
+        } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
+            // No code cache on shared storage
+        } else {
+            // Clear everything on shared storage
+            path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname);
+            if (delete_dir_contents(path, true) != 0) {
+                res = error("Failed to delete contents of " + path);
+            }
+            path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname);
+            if (delete_dir_contents(path, true) != 0) {
+                res = error("Failed to delete contents of " + path);
+            }
+            path = StringPrintf("%s/Android/obb/%s", extPath.c_str(), pkgname);
+            if (delete_dir_contents(path, true) != 0) {
+                res = error("Failed to delete contents of " + path);
+            }
+        }
     }
     if (flags & FLAG_STORAGE_DE) {
         std::string suffix = "";
@@ -681,6 +697,20 @@
         if (delete_dir_contents_and_dir(path) != 0) {
             res = error("Failed to delete " + path);
         }
+
+        auto extPath = findDataMediaPath(uuid, userId);
+        path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname);
+        if (delete_dir_contents_and_dir(path, true) != 0) {
+            res = error("Failed to delete " + path);
+        }
+        path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname);
+        if (delete_dir_contents_and_dir(path, true) != 0) {
+            res = error("Failed to delete " + path);
+        }
+        path = StringPrintf("%s/Android/obb/%s", extPath.c_str(), pkgname);
+        if (delete_dir_contents_and_dir(path, true) != 0) {
+            res = error("Failed to delete " + path);
+        }
     }
     if (flags & FLAG_STORAGE_DE) {
         auto path = create_data_user_de_package_path(uuid_, userId, pkgname);
diff --git a/cmds/installd/TEST_MAPPING b/cmds/installd/TEST_MAPPING
new file mode 100644
index 0000000..3de5c79
--- /dev/null
+++ b/cmds/installd/TEST_MAPPING
@@ -0,0 +1,19 @@
+{
+  "presubmit": [
+    {
+      "name": "installd_cache_test"
+    },
+    {
+      "name": "installd_dexopt_test"
+    },
+    {
+      "name": "installd_otapreopt_test"
+    },
+    {
+      "name": "installd_service_test"
+    },
+    {
+      "name": "installd_utils_test"
+    }
+  ]
+}
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 91e20b7..89b08e5 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -102,4 +102,17 @@
     boolean prepareAppProfile(@utf8InCpp String packageName,
         int userId, int appId, @utf8InCpp String profileName, @utf8InCpp String codePath,
         @nullable @utf8InCpp String dexMetadata);
+
+    const int FLAG_STORAGE_DE = 0x1;
+    const int FLAG_STORAGE_CE = 0x2;
+
+    const int FLAG_CLEAR_CACHE_ONLY = 0x10;
+    const int FLAG_CLEAR_CODE_CACHE_ONLY = 0x20;
+
+    const int FLAG_FREE_CACHE_V2 = 0x100;
+    const int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 0x200;
+    const int FLAG_FREE_CACHE_NOOP = 0x400;
+
+    const int FLAG_USE_QUOTA = 0x1000;
+    const int FLAG_FORCE = 0x2000;
 }
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 0e78e3a..66dece7 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1692,15 +1692,12 @@
             *dexopt_needed_out = NO_DEXOPT_NEEDED; return true;
         case 1:  // dexoptanalyzer: dex2oat_from_scratch
             *dexopt_needed_out = DEX2OAT_FROM_SCRATCH; return true;
-        case 5:  // dexoptanalyzer: dex2oat_for_bootimage_odex
+        case 4:  // dexoptanalyzer: dex2oat_for_bootimage_odex
             *dexopt_needed_out = -DEX2OAT_FOR_BOOT_IMAGE; return true;
-        case 6:  // dexoptanalyzer: dex2oat_for_filter_odex
+        case 5:  // dexoptanalyzer: dex2oat_for_filter_odex
             *dexopt_needed_out = -DEX2OAT_FOR_FILTER; return true;
-        case 7:  // dexoptanalyzer: dex2oat_for_relocation_odex
-            *dexopt_needed_out = -DEX2OAT_FOR_RELOCATION; return true;
         case 2:  // dexoptanalyzer: dex2oat_for_bootimage_oat
         case 3:  // dexoptanalyzer: dex2oat_for_filter_oat
-        case 4:  // dexoptanalyzer: dex2oat_for_relocation_oat
             *error_msg = StringPrintf("Dexoptanalyzer return the status of an oat file."
                                       " Expected odex file status for secondary dex %s"
                                       " : dexoptanalyzer result=%d",
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index bb6fab3..0db11e1 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -31,7 +31,6 @@
 static constexpr int DEX2OAT_FROM_SCRATCH        = 1;
 static constexpr int DEX2OAT_FOR_BOOT_IMAGE      = 2;
 static constexpr int DEX2OAT_FOR_FILTER          = 3;
-static constexpr int DEX2OAT_FOR_RELOCATION      = 4;
 
 // Clear the reference profile identified by the given profile name.
 bool clear_primary_reference_profile(const std::string& pkgname, const std::string& profile_name);
diff --git a/cmds/installd/tests/installd_cache_test.cpp b/cmds/installd/tests/installd_cache_test.cpp
index 2d58515..db09070 100644
--- a/cmds/installd/tests/installd_cache_test.cpp
+++ b/cmds/installd/tests/installd_cache_test.cpp
@@ -40,8 +40,8 @@
 constexpr int64_t kGbInBytes = 1024 * kMbInBytes;
 constexpr int64_t kTbInBytes = 1024 * kGbInBytes;
 
-static constexpr int FLAG_FREE_CACHE_V2 = 1 << 13;
-static constexpr int FLAG_FREE_CACHE_V2_DEFY_QUOTA = 1 << 14;
+#define FLAG_FREE_CACHE_V2 InstalldNativeService::FLAG_FREE_CACHE_V2
+#define FLAG_FREE_CACHE_V2_DEFY_QUOTA InstalldNativeService::FLAG_FREE_CACHE_V2_DEFY_QUOTA
 
 int get_property(const char *key, char *value, const char *default_value) {
     return property_get(key, value, default_value);
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 279bce8..f216c53 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -84,10 +84,16 @@
     system(cmd.c_str());
 }
 
-static void mkdir(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
-    ::mkdir(path.c_str(), mode);
-    ::chown(path.c_str(), owner, group);
-    ::chmod(path.c_str(), mode);
+static int mkdir(const std::string& path, uid_t owner, gid_t group, mode_t mode) {
+    int ret = ::mkdir(path.c_str(), mode);
+    if (ret != 0) {
+        return ret;
+    }
+    ret = ::chown(path.c_str(), owner, group);
+    if (ret != 0) {
+        return ret;
+    }
+    return ::chmod(path.c_str(), mode);
 }
 
 static int log_callback(int type, const char *fmt, ...) { // NOLINT
@@ -184,7 +190,7 @@
         se_info_ = "default";
         app_apk_dir_ = android_app_dir + package_name_;
 
-        create_mock_app();
+        ASSERT_TRUE(create_mock_app());
     }
 
     virtual void TearDown() {
@@ -198,33 +204,56 @@
         delete service_;
     }
 
-    void create_mock_app() {
+    ::testing::AssertionResult create_mock_app() {
         // Create the oat dir.
         app_oat_dir_ = app_apk_dir_ + "/oat";
-        mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755);
-        service_->createOatDir(app_oat_dir_, kRuntimeIsa);
+        if (mkdir(app_apk_dir_, kSystemUid, kSystemGid, 0755) != 0) {
+            return ::testing::AssertionFailure() << "Could not create app dir " << app_apk_dir_
+                                                 << " : " << strerror(errno);
+        }
+        binder::Status status = service_->createOatDir(app_oat_dir_, kRuntimeIsa);
+        if (!status.isOk()) {
+            return ::testing::AssertionFailure() << "Could not create oat dir: "
+                                                 << status.toString8().c_str();
+        }
 
         // Copy the primary apk.
         apk_path_ = app_apk_dir_ + "/base.jar";
-        ASSERT_TRUE(WriteBase64ToFile(kDexFile, apk_path_, kSystemUid, kSystemGid, 0644));
+        std::string error_msg;
+        if (!WriteBase64ToFile(kDexFile, apk_path_, kSystemUid, kSystemGid, 0644, &error_msg)) {
+            return ::testing::AssertionFailure() << "Could not write base64 file to " << apk_path_
+                                                 << " : " << error_msg;
+        }
 
         // Create the app user data.
-        ASSERT_TRUE(service_->createAppData(
-            volume_uuid_,
-            package_name_,
-            kTestUserId,
-            kAppDataFlags,
-            kTestAppUid,
-            se_info_,
-            kOSdkVersion,
-            &ce_data_inode_).isOk());
+        status = service_->createAppData(
+                volume_uuid_,
+                package_name_,
+                kTestUserId,
+                kAppDataFlags,
+                kTestAppUid,
+                se_info_,
+                kOSdkVersion,
+                &ce_data_inode_);
+        if (!status.isOk()) {
+            return ::testing::AssertionFailure() << "Could not create app data: "
+                                                 << status.toString8().c_str();
+        }
 
         // Create a secondary dex file on CE storage
         const char* volume_uuid_cstr = volume_uuid_ == nullptr ? nullptr : volume_uuid_->c_str();
         app_private_dir_ce_ = create_data_user_ce_package_path(
                 volume_uuid_cstr, kTestUserId, package_name_.c_str());
         secondary_dex_ce_ = app_private_dir_ce_ + "/secondary_ce.jar";
-        ASSERT_TRUE(WriteBase64ToFile(kDexFile, secondary_dex_ce_, kTestAppUid, kTestAppGid, 0600));
+        if (!WriteBase64ToFile(kDexFile,
+                               secondary_dex_ce_,
+                               kTestAppUid,
+                               kTestAppGid,
+                               0600,
+                               &error_msg)) {
+            return ::testing::AssertionFailure() << "Could not write base64 file to "
+                                                 << secondary_dex_ce_ << " : " << error_msg;
+        }
         std::string app_private_dir_ce_link = create_data_user_ce_package_path_as_user_link(
                 volume_uuid_cstr, kTestUserId, package_name_.c_str());
         secondary_dex_ce_link_ = app_private_dir_ce_link + "/secondary_ce.jar";
@@ -233,10 +262,24 @@
         app_private_dir_de_ = create_data_user_de_package_path(
                 volume_uuid_cstr, kTestUserId, package_name_.c_str());
         secondary_dex_de_ = app_private_dir_de_ + "/secondary_de.jar";
-        ASSERT_TRUE(WriteBase64ToFile(kDexFile, secondary_dex_de_, kTestAppUid, kTestAppGid, 0600));
+        if (!WriteBase64ToFile(kDexFile,
+                               secondary_dex_de_,
+                               kTestAppUid,
+                               kTestAppGid,
+                               0600,
+                               &error_msg)) {
+            return ::testing::AssertionFailure() << "Could not write base64 file to "
+                                                 << secondary_dex_de_ << " : " << error_msg;
+        }
 
         // Fix app data uid.
-        ASSERT_TRUE(service_->fixupAppData(volume_uuid_, kTestUserId).isOk());
+        status = service_->fixupAppData(volume_uuid_, kTestUserId);
+        if (!status.isOk()) {
+            return ::testing::AssertionFailure() << "Could not fixup app data: "
+                                                 << status.toString8().c_str();
+        }
+
+        return ::testing::AssertionSuccess();
     }
 
 
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index a5af5d7..9dad995 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -37,7 +37,7 @@
 
 constexpr const char* kTestUuid = "TEST";
 
-static constexpr int FLAG_FORCE = 1 << 16;
+#define FLAG_FORCE InstalldNativeService::FLAG_FORCE
 
 int get_property(const char *key, char *value, const char *default_value) {
     return property_get(key, value, default_value);
diff --git a/cmds/installd/tests/test_utils.h b/cmds/installd/tests/test_utils.h
index b8785c6..a7ef674 100644
--- a/cmds/installd/tests/test_utils.h
+++ b/cmds/installd/tests/test_utils.h
@@ -3,6 +3,7 @@
 #include <sys/capability.h>
 
 #include <android-base/logging.h>
+#include <android-base/stringprintf.h>
 #include <selinux/android.h>
 
 uint8_t kBase64Map[256] = {
@@ -74,7 +75,7 @@
 }
 
 bool WriteBase64ToFile(const char* base64, const std::string& file,
-        uid_t uid, gid_t gid, int mode) {
+        uid_t uid, gid_t gid, int mode, std::string* error_msg) {
     CHECK(base64 != nullptr);
     size_t length;
     std::unique_ptr<uint8_t[]> bytes(DecodeBase64(base64, &length));
@@ -83,8 +84,10 @@
 
     int fd = open(file.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
 
+    using android::base::StringPrintf;
+
     if (fd < 0) {
-        PLOG(ERROR) << "Could not open file " << file;
+        *error_msg = StringPrintf("Could not open file %s: %s", file.c_str(), strerror(errno));
         return false;
     }
 
@@ -92,18 +95,18 @@
     while (wrote < length) {
         ssize_t cur = write(fd, bytes.get() + wrote, length - wrote);
         if (cur == -1) {
-            PLOG(ERROR) << "Could not write file " << file;
+            *error_msg = StringPrintf("Could not write file %s: %s", file.c_str(), strerror(errno));
             return false;
         }
         wrote += cur;
     }
 
     if (::chown(file.c_str(), uid, gid) != 0) {
-        PLOG(ERROR) << "Could not chown file " << file;
+        *error_msg = StringPrintf("Could not chown file %s: %s", file.c_str(), strerror(errno));
         return false;
     }
     if (::chmod(file.c_str(), mode) != 0) {
-        PLOG(ERROR) << "Could not chmod file " << file;
+        *error_msg = StringPrintf("Could not chmod file %s: %s", file.c_str(), strerror(errno));
         return false;
     }
     return true;
diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto
index 0bc08a9..68ddeb0 100644
--- a/cmds/surfacereplayer/proto/src/trace.proto
+++ b/cmds/surfacereplayer/proto/src/trace.proto
@@ -30,14 +30,13 @@
 
 message SurfaceChange {
     required int32 id = 1;
-
+    reserved 7;
     oneof SurfaceChange {
         PositionChange              position                = 2;
         SizeChange                  size                    = 3;
         AlphaChange                 alpha                   = 4;
         LayerChange                 layer                   = 5;
         CropChange                  crop                    = 6;
-        FinalCropChange             final_crop              = 7;
         MatrixChange                matrix                  = 8;
         OverrideScalingModeChange   override_scaling_mode   = 9;
         TransparentRegionHintChange transparent_region_hint = 10;
@@ -71,10 +70,6 @@
     required Rectangle rectangle = 1;
 }
 
-message FinalCropChange {
-    required Rectangle rectangle = 1;
-}
-
 message MatrixChange {
     required float dsdx = 1;
     required float dtdx = 2;
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index d9ff4ba..6602546 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -388,9 +388,6 @@
             case SurfaceChange::SurfaceChangeCase::kMatrix:
                 setMatrix(transaction, change.id(), change.matrix());
                 break;
-            case SurfaceChange::SurfaceChangeCase::kFinalCrop:
-                setFinalCrop(transaction, change.id(), change.final_crop());
-                break;
             case SurfaceChange::SurfaceChangeCase::kOverrideScalingMode:
                 setOverrideScalingMode(transaction, change.id(),
                         change.override_scaling_mode());
@@ -492,16 +489,6 @@
     t.setCrop_legacy(mLayers[id], r);
 }
 
-void Replayer::setFinalCrop(SurfaceComposerClient::Transaction& t,
-        layer_id id, const FinalCropChange& fcc) {
-    ALOGV("Layer %d: Setting Final Crop -- left=%d, top=%d, right=%d, bottom=%d", id,
-            fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(),
-            fcc.rectangle().bottom());
-    Rect r = Rect(fcc.rectangle().left(), fcc.rectangle().top(), fcc.rectangle().right(),
-            fcc.rectangle().bottom());
-    t.setFinalCrop_legacy(mLayers[id], r);
-}
-
 void Replayer::setMatrix(SurfaceComposerClient::Transaction& t,
         layer_id id, const MatrixChange& mc) {
     ALOGV("Layer %d: Setting Matrix -- dsdx=%f, dtdx=%f, dsdy=%f, dtdy=%f", id, mc.dsdx(),
diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h
index 295403e..68390d3 100644
--- a/cmds/surfacereplayer/replayer/Replayer.h
+++ b/cmds/surfacereplayer/replayer/Replayer.h
@@ -92,8 +92,6 @@
             layer_id id, const LayerChange& lc);
     void setCrop(SurfaceComposerClient::Transaction& t,
             layer_id id, const CropChange& cc);
-    void setFinalCrop(SurfaceComposerClient::Transaction& t,
-            layer_id id, const FinalCropChange& fcc);
     void setMatrix(SurfaceComposerClient::Transaction& t,
             layer_id id, const MatrixChange& mc);
     void setOverrideScalingMode(SurfaceComposerClient::Transaction& t,
diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h
index 86da4d3..0f336dd 100644
--- a/include/input/DisplayViewport.h
+++ b/include/input/DisplayViewport.h
@@ -39,13 +39,13 @@
     int32_t physicalBottom;
     int32_t deviceWidth;
     int32_t deviceHeight;
-    String8 uniqueId;
+    std::string uniqueId;
 
     DisplayViewport() :
             displayId(ADISPLAY_ID_NONE), orientation(DISPLAY_ORIENTATION_0),
             logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0),
             physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0),
-            deviceWidth(0), deviceHeight(0) {
+            deviceWidth(0), deviceHeight(0), uniqueId() {
     }
 
     bool operator==(const DisplayViewport& other) const {
diff --git a/include/input/Input.h b/include/input/Input.h
index 7c4379e..819a89f 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -25,7 +25,6 @@
 #include <utils/BitSet.h>
 #include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
-#include <utils/String8.h>
 #include <utils/Timers.h>
 #include <utils/Vector.h>
 #include <stdint.h>
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index 1ea69d3..34d164c 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -31,9 +31,9 @@
     }
 
     // Information provided by the kernel.
-    String8 name;
-    String8 location;
-    String8 uniqueId;
+    std::string name;
+    std::string location;
+    std::string uniqueId;
     uint16_t bus;
     uint16_t vendor;
     uint16_t product;
@@ -45,7 +45,7 @@
     // It is hashed from whatever kernel provided information is available.
     // Ideally, the way this value is computed should not change between Android releases
     // because that would invalidate persistent settings that rely on it.
-    String8 descriptor;
+    std::string descriptor;
 
     // A value added to uniquely identify a device in the absence of a unique id. This
     // is intended to be a minimum way to distinguish from other active devices and may
@@ -73,16 +73,16 @@
     };
 
     void initialize(int32_t id, int32_t generation, int32_t controllerNumber,
-            const InputDeviceIdentifier& identifier, const String8& alias, bool isExternal,
+            const InputDeviceIdentifier& identifier, const std::string& alias, bool isExternal,
             bool hasMic);
 
     inline int32_t getId() const { return mId; }
     inline int32_t getControllerNumber() const { return mControllerNumber; }
     inline int32_t getGeneration() const { return mGeneration; }
     inline const InputDeviceIdentifier& getIdentifier() const { return mIdentifier; }
-    inline const String8& getAlias() const { return mAlias; }
-    inline const String8& getDisplayName() const {
-        return mAlias.isEmpty() ? mIdentifier.name : mAlias;
+    inline const std::string& getAlias() const { return mAlias; }
+    inline const std::string& getDisplayName() const {
+        return mAlias.empty() ? mIdentifier.name : mAlias;
     }
     inline bool isExternal() const { return mIsExternal; }
     inline bool hasMic() const { return mHasMic; }
@@ -121,7 +121,7 @@
     int32_t mGeneration;
     int32_t mControllerNumber;
     InputDeviceIdentifier mIdentifier;
-    String8 mAlias;
+    std::string mAlias;
     bool mIsExternal;
     bool mHasMic;
     uint32_t mSources;
@@ -149,7 +149,7 @@
  *
  * Returns an empty string if not found.
  */
-extern String8 getInputDeviceConfigurationFilePathByDeviceIdentifier(
+extern std::string getInputDeviceConfigurationFilePathByDeviceIdentifier(
         const InputDeviceIdentifier& deviceIdentifier,
         InputDeviceConfigurationFileType type);
 
@@ -162,8 +162,8 @@
  *
  * Returns an empty string if not found.
  */
-extern String8 getInputDeviceConfigurationFilePathByName(
-        const String8& name, InputDeviceConfigurationFileType type);
+extern std::string getInputDeviceConfigurationFilePathByName(
+        const std::string& name, InputDeviceConfigurationFileType type);
 
 } // namespace android
 
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index e8d1345..5fd86b4 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -27,6 +27,8 @@
  * The InputConsumer is used by the application to receive events from the input dispatcher.
  */
 
+#include <string>
+
 #include <input/Input.h>
 #include <utils/Errors.h>
 #include <utils/Timers.h>
diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h
index 33d2757..9f4559f 100644
--- a/include/input/KeyCharacterMap.h
+++ b/include/input/KeyCharacterMap.h
@@ -27,7 +27,6 @@
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
 #include <utils/Tokenizer.h>
-#include <utils/String8.h>
 #include <utils/Unicode.h>
 #include <utils/RefBase.h>
 
@@ -75,10 +74,10 @@
     };
 
     /* Loads a key character map from a file. */
-    static status_t load(const String8& filename, Format format, sp<KeyCharacterMap>* outMap);
+    static status_t load(const std::string& filename, Format format, sp<KeyCharacterMap>* outMap);
 
     /* Loads a key character map from its string contents. */
-    static status_t loadContents(const String8& filename,
+    static status_t loadContents(const std::string& filename,
             const char* contents, Format format, sp<KeyCharacterMap>* outMap);
 
     /* Combines a base key character map and an overlay. */
@@ -221,7 +220,7 @@
         status_t parseKey();
         status_t parseKeyProperty();
         status_t finishKey(Key* key);
-        status_t parseModifier(const String8& token, int32_t* outMetaState);
+        status_t parseModifier(const std::string& token, int32_t* outMetaState);
         status_t parseCharacterLiteral(char16_t* outCharacter);
     };
 
diff --git a/include/input/KeyLayoutMap.h b/include/input/KeyLayoutMap.h
index 1e8de71..73815fe 100644
--- a/include/input/KeyLayoutMap.h
+++ b/include/input/KeyLayoutMap.h
@@ -62,7 +62,7 @@
  */
 class KeyLayoutMap : public RefBase {
 public:
-    static status_t load(const String8& filename, sp<KeyLayoutMap>* outMap);
+    static status_t load(const std::string& filename, sp<KeyLayoutMap>* outMap);
 
     status_t mapKey(int32_t scanCode, int32_t usageCode,
             int32_t* outKeyCode, uint32_t* outFlags) const;
diff --git a/include/input/Keyboard.h b/include/input/Keyboard.h
index d4903e9..8b66f69 100644
--- a/include/input/Keyboard.h
+++ b/include/input/Keyboard.h
@@ -21,7 +21,6 @@
 #include <input/InputDevice.h>
 #include <input/InputEventLabels.h>
 #include <utils/Errors.h>
-#include <utils/String8.h>
 #include <utils/PropertyMap.h>
 
 namespace android {
@@ -43,10 +42,10 @@
  */
 class KeyMap {
 public:
-    String8 keyLayoutFile;
+    std::string keyLayoutFile;
     sp<KeyLayoutMap> keyLayoutMap;
 
-    String8 keyCharacterMapFile;
+    std::string keyCharacterMapFile;
     sp<KeyCharacterMap> keyCharacterMap;
 
     KeyMap();
@@ -56,11 +55,11 @@
             const PropertyMap* deviceConfiguration);
 
     inline bool haveKeyLayout() const {
-        return !keyLayoutFile.isEmpty();
+        return !keyLayoutFile.empty();
     }
 
     inline bool haveKeyCharacterMap() const {
-        return !keyCharacterMapFile.isEmpty();
+        return !keyCharacterMapFile.empty();
     }
 
     inline bool isComplete() const {
@@ -68,12 +67,12 @@
     }
 
 private:
-    bool probeKeyMap(const InputDeviceIdentifier& deviceIdentifier, const String8& name);
-    status_t loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier, const String8& name);
+    bool probeKeyMap(const InputDeviceIdentifier& deviceIdentifier, const std::string& name);
+    status_t loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier, const std::string& name);
     status_t loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifier,
-            const String8& name);
-    String8 getPath(const InputDeviceIdentifier& deviceIdentifier,
-            const String8& name, InputDeviceConfigurationFileType type);
+            const std::string& name);
+    std::string getPath(const InputDeviceIdentifier& deviceIdentifier,
+            const std::string& name, InputDeviceConfigurationFileType type);
 };
 
 /**
diff --git a/include/input/VirtualKeyMap.h b/include/input/VirtualKeyMap.h
index e245ead..24e0e0e 100644
--- a/include/input/VirtualKeyMap.h
+++ b/include/input/VirtualKeyMap.h
@@ -23,7 +23,6 @@
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
 #include <utils/Tokenizer.h>
-#include <utils/String8.h>
 #include <utils/Unicode.h>
 
 namespace android {
@@ -50,7 +49,7 @@
 public:
     ~VirtualKeyMap();
 
-    static status_t load(const String8& filename, VirtualKeyMap** outMap);
+    static status_t load(const std::string& filename, VirtualKeyMap** outMap);
 
     inline const Vector<VirtualKeyDefinition>& getVirtualKeys() const {
         return mVirtualKeys;
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index d516eb1..857bbf9 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -189,7 +189,7 @@
                 // them out without going through the buffer.
                 
                 // Slurp up all of the lines.
-                const char* lastLine = txt+1;
+                const char* lastLine = txt;
                 while (txt < end) {
                     if (*txt++ == '\n') lastLine = txt;
                 }
diff --git a/libs/binder/ndk/ABinderProcess.cpp b/libs/binder/ndk/ABinderProcess.cpp
new file mode 100644
index 0000000..c89caaf
--- /dev/null
+++ b/libs/binder/ndk/ABinderProcess.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_process.h>
+
+#include <mutex>
+
+#include <android-base/logging.h>
+#include <binder/IPCThreadState.h>
+
+using ::android::IPCThreadState;
+using ::android::ProcessState;
+
+void ABinderProcess_startThreadPool() {
+    ProcessState::self()->startThreadPool();
+    ProcessState::self()->giveThreadPoolName();
+}
+bool ABinderProcess_setThreadPoolMaxThreadCount(uint32_t numThreads) {
+    return ProcessState::self()->setThreadPoolMaxThreadCount(numThreads) == 0;
+}
+void ABinderProcess_joinThreadPool() {
+    IPCThreadState::self()->joinThreadPool();
+}
diff --git a/libs/binder/ndk/AIBinder.cpp b/libs/binder/ndk/AIBinder.cpp
new file mode 100644
index 0000000..83972f7
--- /dev/null
+++ b/libs/binder/ndk/AIBinder.cpp
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_ibinder.h>
+#include "AIBinder_internal.h"
+
+#include <android/binder_status.h>
+#include "AParcel_internal.h"
+
+#include <android-base/logging.h>
+
+using ::android::IBinder;
+using ::android::Parcel;
+using ::android::sp;
+using ::android::String16;
+using ::android::wp;
+
+namespace ABBinderTag {
+
+static const void* kId = "ABBinder";
+static void* kValue = static_cast<void*>(new bool{true});
+void cleanId(const void* /*id*/, void* /*obj*/, void* /*cookie*/){/* do nothing */};
+
+static void attach(const sp<IBinder>& binder) {
+    binder->attachObject(kId, kValue, nullptr /*cookie*/, cleanId);
+}
+static bool has(const sp<IBinder>& binder) {
+    return binder != nullptr && binder->findObject(kId) == kValue;
+}
+
+} // namespace ABBinderTag
+
+AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {}
+AIBinder::~AIBinder() {}
+
+bool AIBinder::associateClass(const AIBinder_Class* clazz) {
+    using ::android::String8;
+
+    if (clazz == nullptr) return false;
+    if (mClazz == clazz) return true;
+
+    String8 newDescriptor(clazz->getInterfaceDescriptor());
+
+    if (mClazz != nullptr) {
+        String8 currentDescriptor(mClazz->getInterfaceDescriptor());
+        if (newDescriptor == currentDescriptor) {
+            LOG(ERROR) << __func__ << ": Class descriptors '" << currentDescriptor
+                       << "' match during associateClass, but they are different class objects. "
+                          "Class descriptor collision?";
+        } else {
+            LOG(ERROR) << __func__
+                       << ": Class cannot be associated on object which already has a class. "
+                          "Trying to associate to '"
+                       << newDescriptor.c_str() << "' but already set to '"
+                       << currentDescriptor.c_str() << "'.";
+        }
+
+        // always a failure because we know mClazz != clazz
+        return false;
+    }
+
+    CHECK(asABpBinder() != nullptr); // ABBinder always has a descriptor
+
+    String8 descriptor(getBinder()->getInterfaceDescriptor());
+    if (descriptor != newDescriptor) {
+        LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor.c_str()
+                   << "' but descriptor is actually '" << descriptor.c_str() << "'.";
+        return false;
+    }
+
+    // if this is a local object, it's not one known to libbinder_ndk
+    mClazz = clazz;
+
+    return true;
+}
+
+ABBinder::ABBinder(const AIBinder_Class* clazz, void* userData)
+      : AIBinder(clazz), BBinder(), mUserData(userData) {
+    CHECK(clazz != nullptr);
+}
+ABBinder::~ABBinder() {
+    getClass()->onDestroy(mUserData);
+}
+
+const String16& ABBinder::getInterfaceDescriptor() const {
+    return getClass()->getInterfaceDescriptor();
+}
+
+binder_status_t ABBinder::onTransact(transaction_code_t code, const Parcel& data, Parcel* reply,
+                                     binder_flags_t flags) {
+    if (isUserCommand(code)) {
+        if (!data.checkInterface(this)) {
+            return EX_ILLEGAL_STATE;
+        }
+
+        const AParcel in = AParcel::readOnly(this, &data);
+        AParcel out = AParcel(this, reply, false /*owns*/);
+
+        return getClass()->onTransact(this, code, &in, &out);
+    } else {
+        return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+ABpBinder::ABpBinder(const ::android::sp<::android::IBinder>& binder)
+      : AIBinder(nullptr /*clazz*/), BpRefBase(binder) {
+    CHECK(binder != nullptr);
+}
+ABpBinder::~ABpBinder() {}
+
+sp<AIBinder> ABpBinder::fromBinder(const ::android::sp<::android::IBinder>& binder) {
+    if (binder == nullptr) {
+        return nullptr;
+    }
+    if (ABBinderTag::has(binder)) {
+        return static_cast<ABBinder*>(binder.get());
+    }
+    return new ABpBinder(binder);
+}
+
+struct AIBinder_Weak {
+    wp<AIBinder> binder;
+};
+AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder) {
+    if (binder == nullptr) {
+        return nullptr;
+    }
+
+    return new AIBinder_Weak{wp<AIBinder>(binder)};
+}
+void AIBinder_Weak_delete(AIBinder_Weak** weakBinder) {
+    if (weakBinder == nullptr) {
+        return;
+    }
+
+    delete *weakBinder;
+    *weakBinder = nullptr;
+}
+AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder) {
+    if (weakBinder == nullptr) {
+        return nullptr;
+    }
+
+    sp<AIBinder> binder = weakBinder->binder.promote();
+    AIBinder_incStrong(binder.get());
+    return binder.get();
+}
+
+AIBinder_Class::AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
+                               AIBinder_Class_onDestroy onDestroy,
+                               AIBinder_Class_onTransact onTransact)
+      : onCreate(onCreate),
+        onDestroy(onDestroy),
+        onTransact(onTransact),
+        mInterfaceDescriptor(interfaceDescriptor) {}
+
+AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor,
+                                      AIBinder_Class_onCreate onCreate,
+                                      AIBinder_Class_onDestroy onDestroy,
+                                      AIBinder_Class_onTransact onTransact) {
+    if (interfaceDescriptor == nullptr || onCreate == nullptr || onDestroy == nullptr ||
+        onTransact == nullptr) {
+        return nullptr;
+    }
+
+    return new AIBinder_Class(interfaceDescriptor, onCreate, onDestroy, onTransact);
+}
+
+AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args) {
+    if (clazz == nullptr) {
+        LOG(ERROR) << __func__ << ": Must provide class to construct local binder.";
+        return nullptr;
+    }
+
+    void* userData = clazz->onCreate(args);
+
+    sp<AIBinder> ret = new ABBinder(clazz, userData);
+    ABBinderTag::attach(ret->getBinder());
+
+    AIBinder_incStrong(ret.get());
+    return ret.get();
+}
+
+bool AIBinder_isRemote(const AIBinder* binder) {
+    if (binder == nullptr) {
+        return true;
+    }
+
+    return binder->isRemote();
+}
+
+bool AIBinder_isAlive(const AIBinder* binder) {
+    if (binder == nullptr) {
+        return false;
+    }
+
+    return const_cast<AIBinder*>(binder)->getBinder()->isBinderAlive();
+}
+
+binder_status_t AIBinder_ping(AIBinder* binder) {
+    if (binder == nullptr) {
+        return EX_NULL_POINTER;
+    }
+
+    return binder->getBinder()->pingBinder();
+}
+
+void AIBinder_incStrong(AIBinder* binder) {
+    if (binder == nullptr) {
+        LOG(ERROR) << __func__ << ": on null binder";
+        return;
+    }
+
+    binder->incStrong(nullptr);
+}
+void AIBinder_decStrong(AIBinder* binder) {
+    if (binder == nullptr) {
+        LOG(ERROR) << __func__ << ": on null binder";
+        return;
+    }
+
+    binder->decStrong(nullptr);
+}
+int32_t AIBinder_debugGetRefCount(AIBinder* binder) {
+    if (binder == nullptr) {
+        LOG(ERROR) << __func__ << ": on null binder";
+        return -1;
+    }
+
+    return binder->getStrongCount();
+}
+
+bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz) {
+    if (binder == nullptr) {
+        return false;
+    }
+
+    return binder->associateClass(clazz);
+}
+
+const AIBinder_Class* AIBinder_getClass(AIBinder* binder) {
+    if (binder == nullptr) {
+        return nullptr;
+    }
+
+    return binder->getClass();
+}
+
+void* AIBinder_getUserData(AIBinder* binder) {
+    if (binder == nullptr) {
+        return nullptr;
+    }
+
+    ABBinder* bBinder = binder->asABBinder();
+    if (bBinder == nullptr) {
+        return nullptr;
+    }
+
+    return bBinder->getUserData();
+}
+
+binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) {
+    if (binder == nullptr || in == nullptr) {
+        LOG(ERROR) << __func__ << ": requires non-null parameters.";
+        return EX_NULL_POINTER;
+    }
+    const AIBinder_Class* clazz = binder->getClass();
+    if (clazz == nullptr) {
+        LOG(ERROR) << __func__
+                   << ": Class must be defined for a remote binder transaction. See "
+                      "AIBinder_associateClass.";
+        return EX_ILLEGAL_STATE;
+    }
+
+    *in = new AParcel(binder);
+    binder_status_t status = (**in)->writeInterfaceToken(clazz->getInterfaceDescriptor());
+    if (status != EX_NONE) {
+        delete *in;
+        *in = nullptr;
+    }
+
+    return status;
+}
+
+binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
+                                  AParcel** out, binder_flags_t flags) {
+    if (in == nullptr) {
+        LOG(ERROR) << __func__ << ": requires non-null in parameter";
+        return EX_NULL_POINTER;
+    }
+
+    using AutoParcelDestroyer = std::unique_ptr<AParcel*, void (*)(AParcel**)>;
+    // This object is the input to the transaction. This function takes ownership of it and deletes
+    // it.
+    AutoParcelDestroyer forIn(in, AParcel_delete);
+
+    if (!isUserCommand(code)) {
+        LOG(ERROR) << __func__ << ": Only user-defined transactions can be made from the NDK.";
+        return EX_UNSUPPORTED_OPERATION;
+    }
+
+    if ((flags & ~FLAG_ONEWAY) != 0) {
+        LOG(ERROR) << __func__ << ": Unrecognized flags sent: " << flags;
+        return EX_ILLEGAL_ARGUMENT;
+    }
+
+    if (binder == nullptr || *in == nullptr || out == nullptr) {
+        LOG(ERROR) << __func__ << ": requires non-null parameters.";
+        return EX_NULL_POINTER;
+    }
+
+    if ((*in)->getBinder() != binder) {
+        LOG(ERROR) << __func__ << ": parcel is associated with binder object " << binder
+                   << " but called with " << (*in)->getBinder();
+        return EX_ILLEGAL_STATE;
+    }
+
+    *out = new AParcel(binder);
+
+    binder_status_t parcelStatus =
+            binder->getBinder()->transact(code, *(*in)->operator->(), (*out)->operator->(), flags);
+
+    if (parcelStatus != EX_NONE) {
+        delete *out;
+        *out = nullptr;
+    }
+
+    return parcelStatus;
+}
diff --git a/libs/binder/ndk/AIBinder_internal.h b/libs/binder/ndk/AIBinder_internal.h
new file mode 100644
index 0000000..23949bb
--- /dev/null
+++ b/libs/binder/ndk/AIBinder_internal.h
@@ -0,0 +1,110 @@
+/*
+ * 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 <android/binder_ibinder.h>
+#include "AIBinder_internal.h"
+
+#include <atomic>
+
+#include <binder/Binder.h>
+#include <binder/IBinder.h>
+
+inline bool isUserCommand(transaction_code_t code) {
+    return code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION;
+}
+
+struct ABBinder;
+struct ABpBinder;
+
+struct AIBinder : public virtual ::android::RefBase {
+    AIBinder(const AIBinder_Class* clazz);
+    virtual ~AIBinder();
+
+    bool associateClass(const AIBinder_Class* clazz);
+    const AIBinder_Class* getClass() const { return mClazz; }
+
+    virtual ::android::sp<::android::IBinder> getBinder() = 0;
+    virtual ABBinder* asABBinder() { return nullptr; }
+    virtual ABpBinder* asABpBinder() { return nullptr; }
+
+    bool isRemote() const {
+        ::android::sp<::android::IBinder> binder = const_cast<AIBinder*>(this)->getBinder();
+        return binder->remoteBinder() != nullptr;
+    }
+
+private:
+    // AIBinder instance is instance of this class for a local object. In order to transact on a
+    // remote object, this also must be set for simplicity (although right now, only the
+    // interfaceDescriptor from it is used).
+    const AIBinder_Class* mClazz;
+};
+
+// This is a local AIBinder object with a known class.
+struct ABBinder : public AIBinder, public ::android::BBinder {
+    virtual ~ABBinder();
+
+    void* getUserData() { return mUserData; }
+
+    ::android::sp<::android::IBinder> getBinder() override { return this; }
+    ABBinder* asABBinder() override { return this; }
+
+    const ::android::String16& getInterfaceDescriptor() const override;
+    binder_status_t onTransact(uint32_t code, const ::android::Parcel& data,
+                               ::android::Parcel* reply, binder_flags_t flags) override;
+
+private:
+    ABBinder(const AIBinder_Class* clazz, void* userData);
+
+    // only thing that should create an ABBinder
+    friend AIBinder* AIBinder_new(const AIBinder_Class*, void*);
+
+    // Can contain implementation if this is a local binder. This can still be nullptr for a local
+    // binder. If it is nullptr, the implication is the implementation state is entirely external to
+    // this object and the functionality provided in the AIBinder_Class is sufficient.
+    void* mUserData;
+};
+
+// This binder object may be remote or local (even though it is 'Bp'). It is not yet associated with
+// a class.
+struct ABpBinder : public AIBinder, public ::android::BpRefBase {
+    static ::android::sp<AIBinder> fromBinder(const ::android::sp<::android::IBinder>& binder);
+
+    virtual ~ABpBinder();
+
+    ::android::sp<::android::IBinder> getBinder() override { return remote(); }
+    ABpBinder* asABpBinder() override { return this; }
+
+private:
+    ABpBinder(const ::android::sp<::android::IBinder>& binder);
+};
+
+struct AIBinder_Class {
+    AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
+                   AIBinder_Class_onDestroy onDestroy, AIBinder_Class_onTransact onTransact);
+
+    const ::android::String16& getInterfaceDescriptor() const { return mInterfaceDescriptor; }
+
+    const AIBinder_Class_onCreate onCreate;
+    const AIBinder_Class_onDestroy onDestroy;
+    const AIBinder_Class_onTransact onTransact;
+
+private:
+    // This must be a String16 since BBinder virtual getInterfaceDescriptor returns a reference to
+    // one.
+    const ::android::String16 mInterfaceDescriptor;
+};
diff --git a/libs/binder/ndk/AParcel.cpp b/libs/binder/ndk/AParcel.cpp
new file mode 100644
index 0000000..93384d6
--- /dev/null
+++ b/libs/binder/ndk/AParcel.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_parcel.h>
+#include "AParcel_internal.h"
+
+#include "AIBinder_internal.h"
+
+#include <binder/Parcel.h>
+
+using ::android::IBinder;
+using ::android::Parcel;
+using ::android::sp;
+
+void AParcel_delete(AParcel** parcel) {
+    if (parcel == nullptr) {
+        return;
+    }
+
+    delete *parcel;
+    *parcel = nullptr;
+}
+
+binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) {
+    return (*parcel)->writeStrongBinder(binder->getBinder());
+}
+binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder) {
+    sp<IBinder> readBinder = nullptr;
+    binder_status_t status = (*parcel)->readStrongBinder(&readBinder);
+    if (status != EX_NONE) {
+        return status;
+    }
+    sp<AIBinder> ret = ABpBinder::fromBinder(readBinder);
+    AIBinder_incStrong(ret.get());
+    *binder = ret.get();
+    return status;
+}
+binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder) {
+    sp<IBinder> readBinder = nullptr;
+    binder_status_t status = (*parcel)->readNullableStrongBinder(&readBinder);
+    if (status != EX_NONE) {
+        return status;
+    }
+    sp<AIBinder> ret = ABpBinder::fromBinder(readBinder);
+    AIBinder_incStrong(ret.get());
+    *binder = ret.get();
+    return status;
+}
+
+// See gen_parcel_helper.py. These auto-generated read/write methods use the same types for
+// libbinder and this library.
+// @START
+binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value) {
+    return (*parcel)->writeInt32(value);
+}
+
+binder_status_t AParcel_writeUint32(AParcel* parcel, uint32_t value) {
+    return (*parcel)->writeUint32(value);
+}
+
+binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value) {
+    return (*parcel)->writeInt64(value);
+}
+
+binder_status_t AParcel_writeUint64(AParcel* parcel, uint64_t value) {
+    return (*parcel)->writeUint64(value);
+}
+
+binder_status_t AParcel_writeFloat(AParcel* parcel, float value) {
+    return (*parcel)->writeFloat(value);
+}
+
+binder_status_t AParcel_writeDouble(AParcel* parcel, double value) {
+    return (*parcel)->writeDouble(value);
+}
+
+binder_status_t AParcel_writeBool(AParcel* parcel, bool value) {
+    return (*parcel)->writeBool(value);
+}
+
+binder_status_t AParcel_writeChar(AParcel* parcel, char16_t value) {
+    return (*parcel)->writeChar(value);
+}
+
+binder_status_t AParcel_writeByte(AParcel* parcel, int8_t value) {
+    return (*parcel)->writeByte(value);
+}
+
+binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value) {
+    return (*parcel)->readInt32(value);
+}
+
+binder_status_t AParcel_readUint32(const AParcel* parcel, uint32_t* value) {
+    return (*parcel)->readUint32(value);
+}
+
+binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value) {
+    return (*parcel)->readInt64(value);
+}
+
+binder_status_t AParcel_readUint64(const AParcel* parcel, uint64_t* value) {
+    return (*parcel)->readUint64(value);
+}
+
+binder_status_t AParcel_readFloat(const AParcel* parcel, float* value) {
+    return (*parcel)->readFloat(value);
+}
+
+binder_status_t AParcel_readDouble(const AParcel* parcel, double* value) {
+    return (*parcel)->readDouble(value);
+}
+
+binder_status_t AParcel_readBool(const AParcel* parcel, bool* value) {
+    return (*parcel)->readBool(value);
+}
+
+binder_status_t AParcel_readChar(const AParcel* parcel, char16_t* value) {
+    return (*parcel)->readChar(value);
+}
+
+binder_status_t AParcel_readByte(const AParcel* parcel, int8_t* value) {
+    return (*parcel)->readByte(value);
+}
+
+// @END
diff --git a/libs/binder/ndk/AParcel_internal.h b/libs/binder/ndk/AParcel_internal.h
new file mode 100644
index 0000000..9f30a2f
--- /dev/null
+++ b/libs/binder/ndk/AParcel_internal.h
@@ -0,0 +1,53 @@
+/*
+ * 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 <android/binder_parcel.h>
+
+#include <sys/cdefs.h>
+
+#include <binder/Parcel.h>
+#include "AIBinder_internal.h"
+
+struct AParcel {
+    const ::android::Parcel* operator->() const { return mParcel; }
+    ::android::Parcel* operator->() { return mParcel; }
+
+    AParcel(const AIBinder* binder) : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
+    AParcel(const AIBinder* binder, ::android::Parcel* parcel, bool owns)
+          : mBinder(binder), mParcel(parcel), mOwns(owns) {}
+
+    ~AParcel() {
+        if (mOwns) {
+            delete mParcel;
+        }
+    }
+
+    static const AParcel readOnly(const AIBinder* binder, const ::android::Parcel* parcel) {
+        return AParcel(binder, const_cast<::android::Parcel*>(parcel), false);
+    }
+
+    const AIBinder* getBinder() { return mBinder; }
+
+private:
+    // This object is associated with a calls to a specific AIBinder object. This is used for sanity
+    // checking to make sure that a parcel is one that is expected.
+    const AIBinder* mBinder;
+
+    ::android::Parcel* mParcel;
+    bool mOwns;
+};
diff --git a/libs/binder/ndk/AServiceManager.cpp b/libs/binder/ndk/AServiceManager.cpp
new file mode 100644
index 0000000..3979945
--- /dev/null
+++ b/libs/binder/ndk/AServiceManager.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_manager.h>
+#include "AIBinder_internal.h"
+
+#include <binder/IServiceManager.h>
+
+using ::android::defaultServiceManager;
+using ::android::IBinder;
+using ::android::IServiceManager;
+using ::android::sp;
+using ::android::String16;
+
+binder_status_t AServiceManager_addService(AIBinder* binder, const char* instance) {
+    if (binder == nullptr || instance == nullptr) {
+        return EX_NULL_POINTER;
+    }
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    return sm->addService(String16(instance), binder->getBinder());
+}
+AIBinder* AServiceManager_getService(const char* instance) {
+    if (instance == nullptr) {
+        return nullptr;
+    }
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    sp<IBinder> binder = sm->getService(String16(instance));
+
+    sp<AIBinder> ret = ABpBinder::fromBinder(binder);
+    AIBinder_incStrong(ret.get());
+    return ret.get();
+}
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
new file mode 100644
index 0000000..76d5a73
--- /dev/null
+++ b/libs/binder/ndk/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * 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_library {
+    name: "libbinder_ndk",
+    vendor_available: false,
+
+    export_include_dirs: [
+        "include_ndk",
+        "include_apex",
+    ],
+
+    srcs: [
+        "ABinderProcess.cpp",
+        "AIBinder.cpp",
+        "AParcel.cpp",
+        "AServiceManager.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libutils",
+    ],
+}
diff --git a/libs/binder/ndk/include_apex/android/binder_manager.h b/libs/binder/ndk/include_apex/android/binder_manager.h
new file mode 100644
index 0000000..b8f38ba
--- /dev/null
+++ b/libs/binder/ndk/include_apex/android/binder_manager.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/binder_ibinder.h>
+
+__BEGIN_DECLS
+
+/**
+ * This registers the service with the default service manager under this instance name.
+ */
+binder_status_t AServiceManager_addService(AIBinder* binder, const char* instance);
+
+/**
+ * Gets a binder object with this specific instance name. Blocks for a couple of seconds waiting on
+ * it. This also implicitly calls AIBinder_incStrong (so the caller of this function is responsible
+ * for calling AIBinder_decStrong).
+ */
+__attribute__((warn_unused_result)) AIBinder* AServiceManager_getService(const char* instance);
+
+__END_DECLS
diff --git a/libs/binder/ndk/include_apex/android/binder_process.h b/libs/binder/ndk/include_apex/android/binder_process.h
new file mode 100644
index 0000000..69e6387
--- /dev/null
+++ b/libs/binder/ndk/include_apex/android/binder_process.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/**
+ * This creates a threadpool for incoming binder transactions if it has not already been created.
+ */
+void ABinderProcess_startThreadPool();
+/**
+ * This sets the maximum number of threads that can be started in the threadpool. By default, after
+ * startThreadPool is called, this is one. If it is called additional times, it will only prevent
+ * the kernel from starting new threads and will not delete already existing threads.
+ */
+bool ABinderProcess_setThreadPoolMaxThreadCount(uint32_t numThreads);
+/**
+ * This adds the current thread to the threadpool. This may cause the threadpool to exceed the
+ * maximum size.
+ */
+void ABinderProcess_joinThreadPool();
+
+__END_DECLS
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
new file mode 100644
index 0000000..aa29437
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -0,0 +1,257 @@
+/*
+ * 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 <stdint.h>
+#include <sys/cdefs.h>
+
+#include <android/binder_parcel.h>
+#include <android/binder_status.h>
+
+__BEGIN_DECLS
+
+// Also see TF_* in kernel's binder.h
+typedef uint32_t binder_flags_t;
+enum {
+    /**
+     * The transaction will be dispatched and then returned to the caller. The outgoing process
+     * cannot block a call made by this, and execution of the call will not be waited on. An error
+     * can still be returned if the call is unable to be processed by the binder driver. All oneway
+     * calls are guaranteed to be ordered if they are sent on the same AIBinder object.
+     */
+    FLAG_ONEWAY = 0x01,
+};
+
+// Also see IBinder.h in libbinder
+typedef uint32_t transaction_code_t;
+enum {
+    /**
+     * The first transaction code available for user commands (inclusive).
+     */
+    FIRST_CALL_TRANSACTION = 0x00000001,
+    /**
+     * The last transaction code available for user commands (inclusive).
+     */
+    LAST_CALL_TRANSACTION = 0x00ffffff,
+};
+
+/**
+ * Represents a type of AIBinder object which can be sent out.
+ */
+struct AIBinder_Class;
+typedef struct AIBinder_Class AIBinder_Class;
+
+/**
+ * Represents a local or remote object which can be used for IPC or which can itself be sent.
+ *
+ * This object has a refcount associated with it and will be deleted when its refcount reaches zero.
+ * How methods interactive with this refcount is described below. When using this API, it is
+ * intended for a client of a service to hold a strong reference to that service. This also means
+ * that user data typically should hold a strong reference to a local AIBinder object. A remote
+ * AIBinder object automatically holds a strong reference to the AIBinder object in the server's
+ * process. A typically memory layout looks like this:
+ *
+ * Key:
+ *   --->         Ownership/a strong reference
+ *   ...>         A weak reference
+ *
+ *                         (process boundary)
+ *                                 |
+ * MyInterface ---> AIBinder_Weak  |  ProxyForMyInterface
+ *      ^                .         |          |
+ *      |                .         |          |
+ *      |                v         |          v
+ *   UserData  <---   AIBinder   <-|-      AIBinder
+ *                                 |
+ *
+ * In this way, you'll notice that a proxy for the interface holds a strong reference to the
+ * implementation and that in the server process, the AIBinder object which was sent can be resent
+ * so that the same AIBinder object always represents the same object. This allows, for instance, an
+ * implementation (usually a callback) to transfer all ownership to a remote process and
+ * automatically be deleted when the remote process is done with it or dies. Other memory models are
+ * possible, but this is the standard one.
+ */
+struct AIBinder;
+typedef struct AIBinder AIBinder;
+
+/**
+ * The AIBinder object associated with this can be retrieved if it is still alive so that it can be
+ * re-used. The intention of this is to enable the same AIBinder object to always represent the same
+ * object.
+ */
+struct AIBinder_Weak;
+typedef struct AIBinder_Weak AIBinder_Weak;
+
+/**
+ * This is called whenever a new AIBinder object is needed of a specific class.
+ *
+ * These arguments are passed from AIBinder_new. The return value is stored and can be retrieved
+ * using AIBinder_getUserData.
+ */
+typedef void* (*AIBinder_Class_onCreate)(void* args);
+
+/**
+ * This is called whenever an AIBinder object is no longer referenced and needs destroyed.
+ *
+ * Typically, this just deletes whatever the implementation is.
+ */
+typedef void (*AIBinder_Class_onDestroy)(void* userData);
+
+/**
+ * This is called whenever a transaction needs to be processed by a local implementation.
+ */
+typedef binder_status_t (*AIBinder_Class_onTransact)(AIBinder* binder, transaction_code_t code,
+                                                     const AParcel* in, AParcel* out);
+
+/**
+ * An interfaceDescriptor uniquely identifies the type of object that is being created. This is used
+ * internally for sanity checks on transactions.
+ *
+ * None of these parameters can be nullptr.
+ *
+ * This is created one time during library initialization and cleaned up when the process exits or
+ * execs.
+ */
+__attribute__((warn_unused_result)) AIBinder_Class* AIBinder_Class_define(
+        const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
+        AIBinder_Class_onDestroy onDestroy, AIBinder_Class_onTransact onTransact);
+
+/**
+ * Creates a new binder object of the appropriate class.
+ *
+ * Ownership of args is passed to this object. The lifecycle is implemented with AIBinder_incStrong
+ * and AIBinder_decStrong. When the reference count reaches zero, onDestroy is called.
+ *
+ * When this is called, the refcount is implicitly 1. So, calling decStrong exactly one time is
+ * required to delete this object.
+ */
+__attribute__((warn_unused_result)) AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args);
+
+/**
+ * If this is hosted in a process other than the current one.
+ */
+bool AIBinder_isRemote(const AIBinder* binder);
+
+/**
+ * If this binder is known to be alive. This will not send a transaction to a remote process and
+ * returns a result based on the last known information. That is, whenever a transaction is made,
+ * this is automatically updated to reflect the current alive status of this binder. This will be
+ * updated as the result of a transaction made using AIBinder_transact, but it will also be updated
+ * based on the results of bookkeeping or other transactions made internally.
+ */
+bool AIBinder_isAlive(const AIBinder* binder);
+
+/**
+ * Built-in transaction for all binder objects. This sends a transaction which will immediately
+ * return. Usually this is used to make sure that a binder is alive, as a placeholder call, or as a
+ * sanity check.
+ */
+binder_status_t AIBinder_ping(AIBinder* binder);
+
+/**
+ * This can only be called if a strong reference to this object already exists in process.
+ */
+void AIBinder_incStrong(AIBinder* binder);
+
+/**
+ * This will delete the object and call onDestroy once the refcount reaches zero.
+ */
+void AIBinder_decStrong(AIBinder* binder);
+
+/**
+ * For debugging only!
+ */
+int32_t AIBinder_debugGetRefCount(AIBinder* binder);
+
+/**
+ * This sets the class of an AIBinder object. This checks to make sure the remote object is of
+ * the expected class. A class must be set in order to use transactions on an AIBinder object.
+ * However, if an object is just intended to be passed through to another process or used as a
+ * handle this need not be called.
+ *
+ * This returns true if the class association succeeds. If it fails, no change is made to the
+ * binder object.
+ */
+bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz);
+
+/**
+ * Returns the class that this binder was constructed with or associated with.
+ */
+const AIBinder_Class* AIBinder_getClass(AIBinder* binder);
+
+/**
+ * Value returned by onCreate for a local binder. For stateless classes (if onCreate returns
+ * nullptr), this also returns nullptr. For a remote binder, this will always return nullptr.
+ */
+void* AIBinder_getUserData(AIBinder* binder);
+
+/**
+ * A transaction is a series of calls to these functions which looks this
+ * - call AIBinder_prepareTransaction
+ * - fill out the in parcel with parameters (lifetime of the 'in' variable)
+ * - call AIBinder_transact
+ * - read results from the out parcel (lifetime of the 'out' variable)
+ */
+
+/**
+ * Creates a parcel to start filling out for a transaction. This may add data to the parcel for
+ * security, debugging, or other purposes. This parcel is to be sent via AIBinder_transact and it
+ * represents the input data to the transaction. It is recommended to check if the object is local
+ * and call directly into its user data before calling this as the parceling and unparceling cost
+ * can be avoided. This AIBinder must be either built with a class or associated with a class before
+ * using this API.
+ *
+ * This does not affect the ownership of binder. When this function succeeds, the in parcel's
+ * ownership is passed to the caller. At this point, the parcel can be filled out and passed to
+ * AIBinder_transact. Alternatively, if there is an error while filling out the parcel, it can be
+ * deleted with AParcel_delete.
+ */
+binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in);
+
+/**
+ * Transact using a parcel created from AIBinder_prepareTransaction. This actually communicates with
+ * the object representing this binder object. This also passes out a parcel to be used for the
+ * return transaction. This takes ownership of the in parcel and automatically deletes it after it
+ * is sent to the remote process. The output parcel is the result of the transaction. If the
+ * transaction has FLAG_ONEWAY, the out parcel will be empty. Otherwise, this will block until the
+ * remote process has processed the transaction, and the out parcel will contain the output data
+ * from transaction.
+ *
+ * This does not affect the ownership of binder. The out parcel's ownership is passed to the caller
+ * and must be released with AParcel_delete when finished reading.
+ */
+binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
+                                  AParcel** out, binder_flags_t flags);
+
+/**
+ * This does not take any ownership of the input binder, but it can be used to retrieve it if
+ * something else in some process still holds a reference to it.
+ */
+__attribute__((warn_unused_result)) AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder);
+
+/**
+ * Deletes the weak reference. This will have no impact on the lifetime of the binder.
+ */
+void AIBinder_Weak_delete(AIBinder_Weak** weakBinder);
+
+/**
+ * If promotion succeeds, result will have one strong refcount added to it. Otherwise, this returns
+ * nullptr.
+ */
+__attribute__((warn_unused_result)) AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder);
+
+__END_DECLS
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
new file mode 100644
index 0000000..19925f7
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -0,0 +1,152 @@
+/*
+ * 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 <sys/cdefs.h>
+
+#include <android/binder_status.h>
+
+struct AIBinder;
+typedef struct AIBinder AIBinder;
+
+__BEGIN_DECLS
+
+/**
+ * This object represents a package of data that can be sent between processes. When transacting, an
+ * instance of it is automatically created to be used for the transaction. When two processes use
+ * binder to communicate, they must agree on a format of this parcel to be used in order to transfer
+ * data. This is usually done in an IDL (see AIDL, specificially).
+ */
+struct AParcel;
+typedef struct AParcel AParcel;
+
+/**
+ * Cleans up a parcel and sets it to nullptr.
+ */
+void AParcel_delete(AParcel** parcel);
+
+/**
+ * Writes an AIBinder to the next location in a non-null parcel. Can be null.
+ */
+binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder);
+
+/**
+ * Reads an AIBinder from the next location in a non-null parcel. This will fail if the binder is
+ * non-null. One strong ref-count of ownership is passed to the caller of this function.
+ */
+binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder);
+
+/**
+ * Reads an AIBinder from the next location in a non-null parcel. This may read a null. One strong
+ * ref-count of ownership is passed to the caller of this function.
+ */
+binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder);
+
+// @START
+/**
+ * Writes int32_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value);
+
+/**
+ * Writes uint32_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeUint32(AParcel* parcel, uint32_t value);
+
+/**
+ * Writes int64_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value);
+
+/**
+ * Writes uint64_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeUint64(AParcel* parcel, uint64_t value);
+
+/**
+ * Writes float value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeFloat(AParcel* parcel, float value);
+
+/**
+ * Writes double value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeDouble(AParcel* parcel, double value);
+
+/**
+ * Writes bool value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeBool(AParcel* parcel, bool value);
+
+/**
+ * Writes char16_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeChar(AParcel* parcel, char16_t value);
+
+/**
+ * Writes int8_t value to the next location in a non-null parcel.
+ */
+binder_status_t AParcel_writeByte(AParcel* parcel, int8_t value);
+
+/**
+ * Reads into int32_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value);
+
+/**
+ * Reads into uint32_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readUint32(const AParcel* parcel, uint32_t* value);
+
+/**
+ * Reads into int64_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value);
+
+/**
+ * Reads into uint64_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readUint64(const AParcel* parcel, uint64_t* value);
+
+/**
+ * Reads into float value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readFloat(const AParcel* parcel, float* value);
+
+/**
+ * Reads into double value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readDouble(const AParcel* parcel, double* value);
+
+/**
+ * Reads into bool value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readBool(const AParcel* parcel, bool* value);
+
+/**
+ * Reads into char16_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readChar(const AParcel* parcel, char16_t* value);
+
+/**
+ * Reads into int8_t value from the next location in a non-null parcel.
+ */
+binder_status_t AParcel_readByte(const AParcel* parcel, int8_t* value);
+
+// @END
+
+__END_DECLS
diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h
new file mode 100644
index 0000000..d414c99
--- /dev/null
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+// Keep the exception codes in sync with android/os/Parcel.java.
+enum {
+    EX_NONE = 0,
+    EX_SECURITY = -1,
+    EX_BAD_PARCELABLE = -2,
+    EX_ILLEGAL_ARGUMENT = -3,
+    EX_NULL_POINTER = -4,
+    EX_ILLEGAL_STATE = -5,
+    EX_NETWORK_MAIN_THREAD = -6,
+    EX_UNSUPPORTED_OPERATION = -7,
+    EX_SERVICE_SPECIFIC = -8,
+    EX_PARCELABLE = -9,
+
+    /**
+     * This is special and Java specific; see Parcel.java.
+     * This should be considered a success, and the next readInt32 bytes can be ignored.
+     */
+    EX_HAS_REPLY_HEADER = -128,
+
+    /**
+     * This is special, and indicates to native binder proxies that the
+     * transaction has failed at a low level.
+     */
+    EX_TRANSACTION_FAILED = -129,
+};
+
+/**
+ * One of the above values or -errno.
+ * By convention, positive values are considered to mean service-specific exceptions.
+ */
+typedef int32_t binder_status_t;
+
+__END_DECLS
diff --git a/libs/binder/ndk/runtests.sh b/libs/binder/ndk/runtests.sh
new file mode 100755
index 0000000..6c8527d
--- /dev/null
+++ b/libs/binder/ndk/runtests.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+
+# 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.
+
+if [ -z $ANDROID_BUILD_TOP ]; then
+  echo "You need to source and lunch before you can use this script"
+  exit 1
+fi
+
+set -ex
+
+function run_libbinder_ndk_test() {
+	adb shell /data/nativetest64/libbinder_ndk_test_server/libbinder_ndk_test_server &
+	local pid=$!
+	trap "kill $pid" ERR
+	adb shell /data/nativetest64/libbinder_ndk_test_client/libbinder_ndk_test_client
+	trap '' ERR
+	kill $pid
+}
+
+[ "$1" != "--skip-build" ] && $ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode \
+    MODULES-IN-frameworks-native-libs-binder-ndk
+
+adb root
+adb wait-for-device
+adb sync data
+
+run_libbinder_ndk_test
diff --git a/libs/binder/ndk/scripts/format.sh b/libs/binder/ndk/scripts/format.sh
new file mode 100755
index 0000000..698d291
--- /dev/null
+++ b/libs/binder/ndk/scripts/format.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# 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.
+
+set -e
+
+echo "Formatting code"
+
+bpfmt -w $(find $ANDROID_BUILD_TOP/frameworks/native/libs/binder/ndk/ -name "Android.bp")
+clang-format -i $(find $ANDROID_BUILD_TOP/frameworks/native/libs/binder/ndk/ -\( -name "*.cpp" -o -name "*.h" -\))
diff --git a/libs/binder/ndk/scripts/gen_parcel_helper.py b/libs/binder/ndk/scripts/gen_parcel_helper.py
new file mode 100755
index 0000000..5c0b936
--- /dev/null
+++ b/libs/binder/ndk/scripts/gen_parcel_helper.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python3
+
+# 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.
+
+import os
+import sys
+
+# list (pretty, cpp)
+data_types = [
+    ("Int32", "int32_t"),
+    ("Uint32", "uint32_t"),
+    ("Int64", "int64_t"),
+    ("Uint64", "uint64_t"),
+    ("Float", "float"),
+    ("Double", "double"),
+    ("Bool", "bool"),
+    ("Char", "char16_t"),
+    ("Byte", "int8_t"),
+]
+
+def replaceFileTags(path, content):
+    print("Updating", path)
+    with open(path, "r+") as f:
+        lines = f.readlines()
+
+        start = lines.index("// @START\n")
+        end = lines.index("// @END\n")
+
+        if end <= start or start < 0 or end < 0:
+            print("Failed to find tags in", path)
+            exit(1)
+
+        f.seek(0)
+        f.write("".join(lines[:start+1]) + content + "".join(lines[end:]))
+        f.truncate()
+
+def main():
+    if len(sys.argv) != 1:
+        print("No arguments.")
+        exit(1)
+
+    ABT = os.environ.get('ANDROID_BUILD_TOP', None)
+    if ABT is None:
+        print("Can't get ANDROID_BUILD_TOP. Lunch?")
+        exit(1)
+    ROOT = ABT + "/frameworks/native/libs/binder/ndk/"
+
+    print("Updating auto-generated code")
+
+    header = ""
+    source = ""
+
+    for pretty, cpp in data_types:
+        header += "/**\n"
+        header += " * Writes " + cpp + " value to the next location in a non-null parcel.\n"
+        header += " */\n"
+        header += "binder_status_t AParcel_write" + pretty + "(AParcel* parcel, " + cpp + " value);\n\n"
+        source += "binder_status_t AParcel_write" + pretty + "(AParcel* parcel, " + cpp + " value) {\n"
+        source += "    return (*parcel)->write" + pretty + "(value);\n"
+        source += "}\n\n"
+
+    for pretty, cpp in data_types:
+        header += "/**\n"
+        header += " * Reads into " + cpp + " value from the next location in a non-null parcel.\n"
+        header += " */\n"
+        header += "binder_status_t AParcel_read" + pretty + "(const AParcel* parcel, " + cpp + "* value);\n\n"
+        source += "binder_status_t AParcel_read" + pretty + "(const AParcel* parcel, " + cpp + "* value) {\n"
+        source += "    return (*parcel)->read" + pretty + "(value);\n"
+        source += "}\n\n"
+
+    replaceFileTags(ROOT + "include_ndk/android/binder_parcel.h", header)
+    replaceFileTags(ROOT + "AParcel.cpp", source)
+
+    print("Updating DONE.")
+
+if __name__ == "__main__":
+    main()
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
new file mode 100644
index 0000000..d242138
--- /dev/null
+++ b/libs/binder/ndk/test/Android.bp
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+// This test is a unit test of the low-level API that is presented here.
+// Actual users should use AIDL to generate these complicated stubs.
+
+cc_defaults {
+    name: "test_libbinder_ndk_defaults",
+    shared_libs: [
+        "libbase",
+    ],
+    strip: {
+        none: true,
+    },
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+}
+
+cc_library_static {
+    name: "test_libbinder_ndk_library",
+    defaults: ["test_libbinder_ndk_defaults"],
+    export_include_dirs: ["include"],
+    shared_libs: ["libbinder_ndk"],
+    export_shared_lib_headers: ["libbinder_ndk"],
+    srcs: ["iface.cpp"],
+}
+
+cc_defaults {
+    name: "test_libbinder_ndk_test_defaults",
+    defaults: ["test_libbinder_ndk_defaults"],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libutils",
+    ],
+    static_libs: [
+        "libbinder_ndk",
+        "test_libbinder_ndk_library",
+    ],
+}
+
+cc_test {
+    name: "libbinder_ndk_test_client",
+    defaults: ["test_libbinder_ndk_test_defaults"],
+    srcs: ["main_client.cpp"],
+}
+
+cc_test {
+    name: "libbinder_ndk_test_server",
+    defaults: ["test_libbinder_ndk_test_defaults"],
+    srcs: ["main_server.cpp"],
+    gtest: false,
+}
diff --git a/libs/binder/ndk/test/iface.cpp b/libs/binder/ndk/test/iface.cpp
new file mode 100644
index 0000000..a1aa0fa
--- /dev/null
+++ b/libs/binder/ndk/test/iface.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <iface/iface.h>
+
+using ::android::sp;
+using ::android::wp;
+
+const char* IFoo::kSomeInstanceName = "libbinder_ndk-test-IFoo";
+const char* kIFooDescriptor = "my-special-IFoo-class";
+
+struct IFoo_Class_Data {
+    sp<IFoo> foo;
+};
+
+void* IFoo_Class_onCreate(void* args) {
+    IFoo_Class_Data* foo = static_cast<IFoo_Class_Data*>(args);
+    // This is a foo, but we're currently not verifying that. So, the method newLocalBinder is
+    // coupled with this.
+    return static_cast<void*>(foo);
+}
+
+void IFoo_Class_onDestroy(void* userData) {
+    delete static_cast<IFoo_Class_Data*>(userData);
+}
+
+binder_status_t IFoo_Class_onTransact(AIBinder* binder, transaction_code_t code, const AParcel* in,
+                                      AParcel* out) {
+    binder_status_t stat = EX_UNSUPPORTED_OPERATION;
+
+    sp<IFoo> foo = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder))->foo;
+    CHECK(foo != nullptr) << "Transaction made on already deleted object";
+
+    switch (code) {
+        case IFoo::DOFOO: {
+            int32_t valueIn;
+            stat = AParcel_readInt32(in, &valueIn);
+            if (stat != EX_NONE) break;
+            int32_t valueOut = foo->doubleNumber(valueIn);
+            stat = AParcel_writeInt32(out, valueOut);
+            break;
+        }
+    }
+
+    return stat;
+}
+
+AIBinder_Class* IFoo::kClass = AIBinder_Class_define(kIFooDescriptor, IFoo_Class_onCreate,
+                                                     IFoo_Class_onDestroy, IFoo_Class_onTransact);
+
+class BpFoo : public IFoo {
+public:
+    BpFoo(AIBinder* binder) : mBinder(binder) {}
+    virtual ~BpFoo() { AIBinder_decStrong(mBinder); }
+
+    virtual int32_t doubleNumber(int32_t in) {
+        AParcel* parcelIn;
+        CHECK(EX_NONE == AIBinder_prepareTransaction(mBinder, &parcelIn));
+
+        CHECK(EX_NONE == AParcel_writeInt32(parcelIn, in));
+
+        AParcel* parcelOut;
+        CHECK(EX_NONE ==
+              AIBinder_transact(mBinder, IFoo::DOFOO, &parcelIn, &parcelOut, 0 /*flags*/));
+
+        int32_t out;
+        CHECK(EX_NONE == AParcel_readInt32(parcelOut, &out));
+
+        AParcel_delete(&parcelOut);
+
+        return out;
+    }
+
+private:
+    // Always assumes one refcount
+    AIBinder* mBinder;
+};
+
+IFoo::~IFoo() {
+    AIBinder_Weak_delete(&mWeakBinder);
+}
+
+binder_status_t IFoo::addService(const char* instance) {
+    AIBinder* binder = nullptr;
+
+    if (mWeakBinder != nullptr) {
+        // one strong ref count of binder
+        binder = AIBinder_Weak_promote(mWeakBinder);
+    }
+    if (binder == nullptr) {
+        // or one strong refcount here
+        binder = AIBinder_new(IFoo::kClass, static_cast<void*>(new IFoo_Class_Data{this}));
+        if (mWeakBinder != nullptr) {
+            AIBinder_Weak_delete(&mWeakBinder);
+        }
+        mWeakBinder = AIBinder_Weak_new(binder);
+    }
+
+    binder_status_t status = AServiceManager_addService(binder, instance);
+    // Strong references we care about kept by remote process
+    AIBinder_decStrong(binder);
+    return status;
+}
+
+sp<IFoo> IFoo::getService(const char* instance) {
+    AIBinder* binder = AServiceManager_getService(instance); // maybe nullptr
+    if (binder == nullptr) {
+        return nullptr;
+    }
+
+    if (!AIBinder_associateClass(binder, IFoo::kClass)) {
+        AIBinder_decStrong(binder);
+        return nullptr;
+    }
+
+    if (AIBinder_isRemote(binder)) {
+        sp<IFoo> ret = new BpFoo(binder); // takes ownership of binder
+        return ret;
+    }
+
+    IFoo_Class_Data* data = static_cast<IFoo_Class_Data*>(AIBinder_getUserData(binder));
+
+    CHECK(data != nullptr); // always created with non-null data
+
+    sp<IFoo> ret = data->foo;
+
+    AIBinder* held = AIBinder_Weak_promote(ret->mWeakBinder);
+    CHECK(held == binder);
+    AIBinder_decStrong(held);
+
+    // IFoo only keeps a weak reference to AIBinder, so we can drop this
+    AIBinder_decStrong(binder);
+    return ret;
+}
diff --git a/libs/binder/ndk/test/include/iface/iface.h b/libs/binder/ndk/test/include/iface/iface.h
new file mode 100644
index 0000000..4c61e9d
--- /dev/null
+++ b/libs/binder/ndk/test/include/iface/iface.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/binder_ibinder.h>
+#include <utils/RefBase.h>
+
+class IFoo : public virtual ::android::RefBase {
+public:
+    static const char* kSomeInstanceName;
+    static AIBinder_Class* kClass;
+
+    // Takes ownership of IFoo
+    binder_status_t addService(const char* instance);
+    static ::android::sp<IFoo> getService(const char* instance);
+
+    enum Call {
+        DOFOO = FIRST_CALL_TRANSACTION + 0,
+    };
+
+    virtual ~IFoo();
+    virtual int32_t doubleNumber(int32_t in) = 0;
+
+private:
+    AIBinder_Weak* mWeakBinder = nullptr; // maybe owns AIBinder
+};
diff --git a/libs/binder/ndk/test/main_client.cpp b/libs/binder/ndk/test/main_client.cpp
new file mode 100644
index 0000000..967789f
--- /dev/null
+++ b/libs/binder/ndk/test/main_client.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <gtest/gtest.h>
+#include <iface/iface.h>
+
+using ::android::sp;
+
+constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
+
+// This is too slow
+// TEST(NdkBinder, GetServiceThatDoesntExist) {
+//     sp<IFoo> foo = IFoo::getService("asdfghkl;");
+//     EXPECT_EQ(nullptr, foo.get());
+// }
+
+TEST(NdkBinder, DoubleNumber) {
+    sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName);
+    ASSERT_NE(foo, nullptr);
+    EXPECT_EQ(2, foo->doubleNumber(1));
+}
+
+TEST(NdkBinder, RetrieveNonNdkService) {
+    AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
+    ASSERT_NE(nullptr, binder);
+    EXPECT_TRUE(AIBinder_isRemote(binder));
+    EXPECT_TRUE(AIBinder_isAlive(binder));
+    EXPECT_EQ(EX_NONE, AIBinder_ping(binder));
+
+    AIBinder_decStrong(binder);
+}
+
+class MyTestFoo : public IFoo {
+    int32_t doubleNumber(int32_t in) override {
+        LOG(INFO) << "doubleNumber " << in;
+        return 2 * in;
+    }
+};
+
+TEST(NdkBinder, GetServiceInProcess) {
+    static const char* kInstanceName = "test-get-service-in-process";
+
+    sp<IFoo> foo = new MyTestFoo;
+    EXPECT_EQ(EX_NONE, foo->addService(kInstanceName));
+
+    sp<IFoo> getFoo = IFoo::getService(kInstanceName);
+    EXPECT_EQ(foo.get(), getFoo.get());
+
+    EXPECT_EQ(2, getFoo->doubleNumber(1));
+}
+
+TEST(NdkBinder, AddServiceMultipleTimes) {
+    static const char* kInstanceName1 = "test-multi-1";
+    static const char* kInstanceName2 = "test-multi-2";
+    sp<IFoo> foo = new MyTestFoo;
+    EXPECT_EQ(EX_NONE, foo->addService(kInstanceName1));
+    EXPECT_EQ(EX_NONE, foo->addService(kInstanceName2));
+    EXPECT_EQ(IFoo::getService(kInstanceName1), IFoo::getService(kInstanceName2));
+}
diff --git a/libs/binder/ndk/test/main_server.cpp b/libs/binder/ndk/test/main_server.cpp
new file mode 100644
index 0000000..f3da7da
--- /dev/null
+++ b/libs/binder/ndk/test/main_server.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_process.h>
+#include <iface/iface.h>
+
+using ::android::sp;
+
+class MyFoo : public IFoo {
+    int32_t doubleNumber(int32_t in) override {
+        LOG(INFO) << "doubling " << in;
+        return 2 * in;
+    }
+};
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+    // Strong reference to MyFoo kept by service manager.
+    binder_status_t status = (new MyFoo)->addService(IFoo::kSomeInstanceName);
+
+    if (status != EX_NONE) {
+        LOG(FATAL) << "Could not register: " << status;
+    }
+
+    ABinderProcess_joinThreadPool();
+
+    return 1;
+}
diff --git a/libs/binder/ndk/update.sh b/libs/binder/ndk/update.sh
new file mode 100755
index 0000000..1eba892
--- /dev/null
+++ b/libs/binder/ndk/update.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# 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.
+
+
+set -ex
+
+# This script makes sure that the source code is in sync with the various scripts
+./scripts/gen_parcel_helper.py
+./scripts/format.sh
diff --git a/libs/binder/tests/binderTextOutputTest.cpp b/libs/binder/tests/binderTextOutputTest.cpp
index f6dd22d..ce99f59 100644
--- a/libs/binder/tests/binderTextOutputTest.cpp
+++ b/libs/binder/tests/binderTextOutputTest.cpp
@@ -28,15 +28,14 @@
 #include <binder/TextOutput.h>
 #include <binder/Debug.h>
 
-static void CheckMessage(const CapturedStderr& cap,
+static void CheckMessage(CapturedStderr& cap,
                          const char* expected,
                          bool singleline) {
-    std::string output;
-    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
-    android::base::ReadFdToString(cap.fd(), &output);
+    cap.Stop();
+    std::string output = cap.str();
     if (singleline)
         output.erase(std::remove(output.begin(), output.end(), '\n'));
-    ASSERT_STREQ(output.c_str(), expected);
+    ASSERT_EQ(output, expected);
 }
 
 #define CHECK_LOG_(input, expect, singleline)    \
@@ -60,28 +59,22 @@
 TEST(TextOutput, HandlesStdEndl) {
     CapturedStderr cap;
     android::aerr << "foobar" << std::endl;
-    std::string output;
-    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
-    android::base::ReadFdToString(cap.fd(), &output);
-    ASSERT_STREQ(output.c_str(), "foobar\n");
+    cap.Stop();
+    ASSERT_EQ(cap.str(), "foobar\n");
 }
 
 TEST(TextOutput, HandlesCEndl) {
     CapturedStderr cap;
     android::aerr << "foobar" << "\n";
-    std::string output;
-    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
-    android::base::ReadFdToString(cap.fd(), &output);
-    ASSERT_STREQ(output.c_str(), "foobar\n");
+    cap.Stop();
+    ASSERT_EQ(cap.str(), "foobar\n");
 }
 
 TEST(TextOutput, HandlesAndroidEndl) {
     CapturedStderr cap;
     android::aerr << "foobar" << android::endl;
-    std::string output;
-    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
-    android::base::ReadFdToString(cap.fd(), &output);
-    ASSERT_STREQ(output.c_str(), "foobar\n");
+    cap.Stop();
+    ASSERT_EQ(cap.str(), "foobar\n");
 }
 
 TEST(TextOutput, HandleEmptyString) {
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 5532db4..faf02f3 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -834,10 +834,10 @@
         xform = crop * xform;
     }
 
-    // SurfaceFlinger expects the top of its window textures to be at a Y
-    // coordinate of 0, so GLConsumer must behave the same way.  We don't
-    // want to expose this to applications, however, so we must add an
-    // additional vertical flip to the transform after all the other transforms.
+    // GLConsumer uses the GL convention where (0, 0) is the bottom-left
+    // corner and (1, 1) is the top-right corner.  Add an additional vertical
+    // flip after all other transforms to map from GL convention to buffer
+    // queue memory layout, where (0, 0) is the top-left corner.
     xform = mtxFlipV * xform;
 
     memcpy(outTransform, xform.asArray(), sizeof(xform));
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 81f692d..7f9668f 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -331,34 +331,6 @@
         return result;
     }
 
-    virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) {
-        Parcel data, reply;
-        status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        if (result != NO_ERROR) {
-            ALOGE("getDisplayViewport failed to writeInterfaceToken: %d", result);
-            return result;
-        }
-        result = data.writeStrongBinder(display);
-        if (result != NO_ERROR) {
-            ALOGE("getDisplayViewport failed to writeStrongBinder: %d", result);
-            return result;
-        }
-        result = remote()->transact(BnSurfaceComposer::GET_DISPLAY_VIEWPORT, data, &reply);
-        if (result != NO_ERROR) {
-            ALOGE("getDisplayViewport failed to transact: %d", result);
-            return result;
-        }
-        result = reply.readInt32();
-        if (result == NO_ERROR) {
-            result = reply.read(*outViewport);
-            if (result != NO_ERROR) {
-                ALOGE("getDisplayViewport failed to read: %d", result);
-                return result;
-            }
-        }
-        return result;
-    }
-
     virtual int getActiveConfig(const sp<IBinder>& display)
     {
         Parcel data, reply;
@@ -775,26 +747,6 @@
             }
             return NO_ERROR;
         }
-        case GET_DISPLAY_VIEWPORT: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            Rect outViewport;
-            sp<IBinder> display = nullptr;
-            status_t result = data.readStrongBinder(&display);
-            if (result != NO_ERROR) {
-                ALOGE("getDisplayViewport failed to readStrongBinder: %d", result);
-                return result;
-            }
-            result = getDisplayViewport(display, &outViewport);
-            result = reply->writeInt32(result);
-            if (result == NO_ERROR) {
-                result = reply->write(outViewport);
-                if (result != NO_ERROR) {
-                    ALOGE("getDisplayViewport failed to write: %d", result);
-                    return result;
-                }
-            }
-            return NO_ERROR;
-        }
         case GET_ACTIVE_CONFIG: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> display = data.readStrongBinder();
diff --git a/libs/gui/LayerDebugInfo.cpp b/libs/gui/LayerDebugInfo.cpp
index d3dc16d..ccde9e0 100644
--- a/libs/gui/LayerDebugInfo.cpp
+++ b/libs/gui/LayerDebugInfo.cpp
@@ -42,7 +42,6 @@
     RETURN_ON_ERROR(parcel->writeInt32(mWidth));
     RETURN_ON_ERROR(parcel->writeInt32(mHeight));
     RETURN_ON_ERROR(parcel->write(mCrop));
-    RETURN_ON_ERROR(parcel->write(mFinalCrop));
     RETURN_ON_ERROR(parcel->writeFloat(mColor.r));
     RETURN_ON_ERROR(parcel->writeFloat(mColor.g));
     RETURN_ON_ERROR(parcel->writeFloat(mColor.b));
@@ -81,7 +80,6 @@
     RETURN_ON_ERROR(parcel->readInt32(&mWidth));
     RETURN_ON_ERROR(parcel->readInt32(&mHeight));
     RETURN_ON_ERROR(parcel->read(mCrop));
-    RETURN_ON_ERROR(parcel->read(mFinalCrop));
     mColor.r = parcel->readFloat();
     RETURN_ON_ERROR(parcel->errorCheck());
     mColor.g = parcel->readFloat();
@@ -121,8 +119,7 @@
             info.mLayerStack, info.mZ, static_cast<double>(info.mX), static_cast<double>(info.mY),
             info.mWidth, info.mHeight);
 
-    result.appendFormat("crop=%s, finalCrop=%s, ",
-            to_string(info.mCrop).c_str(), to_string(info.mFinalCrop).c_str());
+    result.appendFormat("crop=%s, ", to_string(info.mCrop).c_str());
     result.appendFormat("isOpaque=%1d, invalidate=%1d, ", info.mIsOpaque, info.mContentDirty);
     result.appendFormat("dataspace=%s, ", dataspaceDetails(info.mDataSpace).c_str());
     result.appendFormat("pixelformat=%s, ", decodePixelFormat(info.mPixelFormat).c_str());
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 931c446..deb8ea8 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -38,7 +38,6 @@
     *reinterpret_cast<layer_state_t::matrix22_t *>(
             output.writeInplace(sizeof(layer_state_t::matrix22_t))) = matrix;
     output.write(crop_legacy);
-    output.write(finalCrop_legacy);
     output.writeStrongBinder(barrierHandle_legacy);
     output.writeStrongBinder(reparentHandle);
     output.writeUint64(frameNumber_legacy);
@@ -99,7 +98,6 @@
         return BAD_VALUE;
     }
     input.read(crop_legacy);
-    input.read(finalCrop_legacy);
     barrierHandle_legacy = input.readStrongBinder();
     reparentHandle = input.readStrongBinder();
     frameNumber_legacy = input.readUint64();
@@ -248,10 +246,6 @@
         barrierGbp_legacy = other.barrierGbp_legacy;
         frameNumber_legacy = other.frameNumber_legacy;
     }
-    if (other.what & eFinalCropChanged_legacy) {
-        what |= eFinalCropChanged_legacy;
-        finalCrop_legacy = other.finalCrop_legacy;
-    }
     if (other.what & eOverrideScalingModeChanged) {
         what |= eOverrideScalingModeChanged;
         overrideScalingMode = other.overrideScalingMode;
@@ -318,6 +312,10 @@
         what |= eSidebandStreamChanged;
         sidebandStream = other.sidebandStream;
     }
+
+    if (other.what != what) {
+        ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating?");
+    }
 }
 
 }; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index b8465e3..7168de4 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -353,18 +353,6 @@
     return *this;
 }
 
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFinalCrop_legacy(
-        const sp<SurfaceControl>& sc, const Rect& crop) {
-    layer_state_t* s = getLayerState(sc);
-    if (!s) {
-        mStatus = BAD_INDEX;
-        return *this;
-    }
-    s->what |= layer_state_t::eFinalCropChanged_legacy;
-    s->finalCrop_legacy = crop;
-    return *this;
-}
-
 SurfaceComposerClient::Transaction&
 SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const sp<SurfaceControl>& sc,
                                                                  const sp<IBinder>& handle,
@@ -839,10 +827,6 @@
     return NO_ERROR;
 }
 
-status_t SurfaceComposerClient::getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) {
-    return ComposerService::getComposerService()->getDisplayViewport(display, outViewport);
-}
-
 int SurfaceComposerClient::getActiveConfig(const sp<IBinder>& display) {
     return ComposerService::getComposerService()->getActiveConfig(display);
 }
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index b9158f1..98ec338 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -157,9 +157,6 @@
     virtual status_t getDisplayStats(const sp<IBinder>& display,
             DisplayStatInfo* stats) = 0;
 
-    /* returns display viewport information of the given display */
-    virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) = 0;
-
     /* indicates which of the configurations returned by getDisplayInfo is
      * currently active */
     virtual int getActiveConfig(const sp<IBinder>& display) = 0;
@@ -253,8 +250,7 @@
         ENABLE_VSYNC_INJECTIONS,
         INJECT_VSYNC,
         GET_LAYER_DEBUG_INFO,
-        CREATE_SCOPED_CONNECTION,
-        GET_DISPLAY_VIEWPORT
+        CREATE_SCOPED_CONNECTION
     };
 
     virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h
index 11261c3..82b01b8 100644
--- a/libs/gui/include/gui/ISurfaceComposerClient.h
+++ b/libs/gui/include/gui/ISurfaceComposerClient.h
@@ -43,6 +43,7 @@
         eFXSurfaceBufferQueue = 0x00000000,
         eFXSurfaceColor = 0x00020000,
         eFXSurfaceBufferState = 0x00040000,
+        eFXSurfaceContainer = 0x00080000,
         eFXSurfaceMask = 0x000F0000,
     };
 
diff --git a/libs/gui/include/gui/LayerDebugInfo.h b/libs/gui/include/gui/LayerDebugInfo.h
index 92bd8c5..66a7b4d 100644
--- a/libs/gui/include/gui/LayerDebugInfo.h
+++ b/libs/gui/include/gui/LayerDebugInfo.h
@@ -52,7 +52,6 @@
     int32_t mWidth = -1;
     int32_t mHeight = -1;
     Rect mCrop = Rect::INVALID_RECT;
-    Rect mFinalCrop = Rect::INVALID_RECT;
     half4 mColor = half4(1.0_hf, 1.0_hf, 1.0_hf, 0.0_hf);
     uint32_t mFlags = 0;
     PixelFormat mPixelFormat = PIXEL_FORMAT_NONE;
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 0981798..0859aff 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -54,25 +54,24 @@
         eLayerStackChanged = 0x00000080,
         eCropChanged_legacy = 0x00000100,
         eDeferTransaction_legacy = 0x00000200,
-        eFinalCropChanged_legacy = 0x00000400,
-        eOverrideScalingModeChanged = 0x00000800,
-        eGeometryAppliesWithResize = 0x00001000,
-        eReparentChildren = 0x00002000,
-        eDetachChildren = 0x00004000,
-        eRelativeLayerChanged = 0x00008000,
-        eReparent = 0x00010000,
-        eColorChanged = 0x00020000,
-        eDestroySurface = 0x00040000,
-        eTransformChanged = 0x00100000,
-        eTransformToDisplayInverseChanged = 0x00200000,
-        eCropChanged = 0x00400000,
-        eBufferChanged = 0x00800000,
-        eAcquireFenceChanged = 0x01000000,
-        eDataspaceChanged = 0x02000000,
-        eHdrMetadataChanged = 0x04000000,
-        eSurfaceDamageRegionChanged = 0x08000000,
-        eApiChanged = 0x10000000,
-        eSidebandStreamChanged = 0x20000000,
+        eOverrideScalingModeChanged = 0x00000400,
+        eGeometryAppliesWithResize = 0x00000800,
+        eReparentChildren = 0x00001000,
+        eDetachChildren = 0x00002000,
+        eRelativeLayerChanged = 0x00004000,
+        eReparent = 0x00008000,
+        eColorChanged = 0x00010000,
+        eDestroySurface = 0x00020000,
+        eTransformChanged = 0x00040000,
+        eTransformToDisplayInverseChanged = 0x00080000,
+        eCropChanged = 0x00100000,
+        eBufferChanged = 0x00200000,
+        eAcquireFenceChanged = 0x00400000,
+        eDataspaceChanged = 0x00800000,
+        eHdrMetadataChanged = 0x01000000,
+        eSurfaceDamageRegionChanged = 0x02000000,
+        eApiChanged = 0x04000000,
+        eSidebandStreamChanged = 0x08000000,
     };
 
     layer_state_t()
@@ -88,7 +87,6 @@
             mask(0),
             reserved(0),
             crop_legacy(Rect::INVALID_RECT),
-            finalCrop_legacy(Rect::INVALID_RECT),
             frameNumber_legacy(0),
             overrideScalingMode(-1),
             transform(0),
@@ -126,7 +124,6 @@
     uint8_t reserved;
     matrix22_t matrix;
     Rect crop_legacy;
-    Rect finalCrop_legacy;
     sp<IBinder> barrierHandle_legacy;
     sp<IBinder> reparentHandle;
     uint64_t frameNumber_legacy;
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 9bd1131..d83ba84 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -79,9 +79,6 @@
     static status_t getDisplayInfo(const sp<IBinder>& display,
             DisplayInfo* info);
 
-    // Get the display viewport for the given display
-    static status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport);
-
     // Get the index of the current active configuration (relative to the list
     // returned by getDisplayInfo)
     static int getActiveConfig(const sp<IBinder>& display);
@@ -204,7 +201,6 @@
         Transaction& setMatrix(const sp<SurfaceControl>& sc,
                 float dsdx, float dtdx, float dtdy, float dsdy);
         Transaction& setCrop_legacy(const sp<SurfaceControl>& sc, const Rect& crop);
-        Transaction& setFinalCrop_legacy(const sp<SurfaceControl>& sc, const Rect& crop);
         Transaction& setLayerStack(const sp<SurfaceControl>& sc, uint32_t layerStack);
         // Defers applying any changes made in this transaction until the Layer
         // identified by handle reaches the given frameNumber. If the Layer identified
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index f22e702..3542aba 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -581,9 +581,6 @@
             Vector<DisplayInfo>* /*configs*/) override { return NO_ERROR; }
     status_t getDisplayStats(const sp<IBinder>& /*display*/,
             DisplayStatInfo* /*stats*/) override { return NO_ERROR; }
-    status_t getDisplayViewport(const sp<IBinder>& /*display*/, Rect* /*outViewport*/) override {
-        return NO_ERROR;
-    }
     int getActiveConfig(const sp<IBinder>& /*display*/) override { return 0; }
     status_t setActiveConfig(const sp<IBinder>& /*display*/, int /*id*/)
             override {
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index 5d27bf6..778c453 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -20,9 +20,12 @@
 #include <unistd.h>
 #include <ctype.h>
 
+#include <android-base/stringprintf.h>
 #include <input/InputDevice.h>
 #include <input/InputEventLabels.h>
 
+using android::base::StringPrintf;
+
 namespace android {
 
 static const char* CONFIGURATION_FILE_DIR[] = {
@@ -41,8 +44,8 @@
     return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_');
 }
 
-static void appendInputDeviceConfigurationFileRelativePath(String8& path,
-        const String8& name, InputDeviceConfigurationFileType type) {
+static void appendInputDeviceConfigurationFileRelativePath(std::string& path,
+        const std::string& name, InputDeviceConfigurationFileType type) {
     path.append(CONFIGURATION_FILE_DIR[type]);
     for (size_t i = 0; i < name.length(); i++) {
         char ch = name[i];
@@ -54,28 +57,28 @@
     path.append(CONFIGURATION_FILE_EXTENSION[type]);
 }
 
-String8 getInputDeviceConfigurationFilePathByDeviceIdentifier(
+std::string getInputDeviceConfigurationFilePathByDeviceIdentifier(
         const InputDeviceIdentifier& deviceIdentifier,
         InputDeviceConfigurationFileType type) {
     if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
         if (deviceIdentifier.version != 0) {
             // Try vendor product version.
-            String8 versionPath(getInputDeviceConfigurationFilePathByName(
-                    String8::format("Vendor_%04x_Product_%04x_Version_%04x",
+            std::string versionPath = getInputDeviceConfigurationFilePathByName(
+                    StringPrintf("Vendor_%04x_Product_%04x_Version_%04x",
                             deviceIdentifier.vendor, deviceIdentifier.product,
                             deviceIdentifier.version),
-                    type));
-            if (!versionPath.isEmpty()) {
+                    type);
+            if (!versionPath.empty()) {
                 return versionPath;
             }
         }
 
         // Try vendor product.
-        String8 productPath(getInputDeviceConfigurationFilePathByName(
-                String8::format("Vendor_%04x_Product_%04x",
+        std::string productPath = getInputDeviceConfigurationFilePathByName(
+                StringPrintf("Vendor_%04x_Product_%04x",
                         deviceIdentifier.vendor, deviceIdentifier.product),
-                type));
-        if (!productPath.isEmpty()) {
+                type);
+        if (!productPath.empty()) {
             return productPath;
         }
     }
@@ -84,22 +87,25 @@
     return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type);
 }
 
-String8 getInputDeviceConfigurationFilePathByName(
-        const String8& name, InputDeviceConfigurationFileType type) {
+std::string getInputDeviceConfigurationFilePathByName(
+        const std::string& name, InputDeviceConfigurationFileType type) {
     // Search system repository.
-    String8 path;
+    std::string path;
 
     // Treblized input device config files will be located /odm/usr or /vendor/usr.
     const char *rootsForPartition[] {"/odm", "/vendor", getenv("ANDROID_ROOT")};
     for (size_t i = 0; i < size(rootsForPartition); i++) {
-        path.setTo(rootsForPartition[i]);
-        path.append("/usr/");
+        if (rootsForPartition[i] == nullptr) {
+            continue;
+        }
+        path = rootsForPartition[i];
+        path += "/usr/";
         appendInputDeviceConfigurationFileRelativePath(path, name, type);
 #if DEBUG_PROBE
         ALOGD("Probing for system provided input device configuration file: path='%s'",
-              path.string());
+              path.c_str());
 #endif
-        if (!access(path.string(), R_OK)) {
+        if (!access(path.c_str(), R_OK)) {
 #if DEBUG_PROBE
             ALOGD("Found");
 #endif
@@ -109,13 +115,17 @@
 
     // Search user repository.
     // TODO Should only look here if not in safe mode.
-    path.setTo(getenv("ANDROID_DATA"));
-    path.append("/system/devices/");
+    path = "";
+    char *androidData = getenv("ANDROID_DATA");
+    if (androidData != nullptr) {
+        path += androidData;
+    }
+    path += "/system/devices/";
     appendInputDeviceConfigurationFileRelativePath(path, name, type);
 #if DEBUG_PROBE
-    ALOGD("Probing for system user input device configuration file: path='%s'", path.string());
+    ALOGD("Probing for system user input device configuration file: path='%s'", path.c_str());
 #endif
-    if (!access(path.string(), R_OK)) {
+    if (!access(path.c_str(), R_OK)) {
 #if DEBUG_PROBE
         ALOGD("Found");
 #endif
@@ -125,16 +135,16 @@
     // Not found.
 #if DEBUG_PROBE
     ALOGD("Probe failed to find input device configuration file: name='%s', type=%d",
-            name.string(), type);
+            name.c_str(), type);
 #endif
-    return String8();
+    return "";
 }
 
 
 // --- InputDeviceInfo ---
 
 InputDeviceInfo::InputDeviceInfo() {
-    initialize(-1, 0, -1, InputDeviceIdentifier(), String8(), false, false);
+    initialize(-1, 0, -1, InputDeviceIdentifier(), "", false, false);
 }
 
 InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
@@ -150,7 +160,7 @@
 }
 
 void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber,
-        const InputDeviceIdentifier& identifier, const String8& alias, bool isExternal,
+        const InputDeviceIdentifier& identifier, const std::string& alias, bool isExternal,
         bool hasMic) {
     mId = id;
     mGeneration = generation;
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index 26747bd..e189d20 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -106,14 +106,14 @@
     }
 }
 
-status_t KeyCharacterMap::load(const String8& filename,
+status_t KeyCharacterMap::load(const std::string& filename,
         Format format, sp<KeyCharacterMap>* outMap) {
     outMap->clear();
 
     Tokenizer* tokenizer;
-    status_t status = Tokenizer::open(filename, &tokenizer);
+    status_t status = Tokenizer::open(String8(filename.c_str()), &tokenizer);
     if (status) {
-        ALOGE("Error %d opening key character map file %s.", status, filename.string());
+        ALOGE("Error %d opening key character map file %s.", status, filename.c_str());
     } else {
         status = load(tokenizer, format, outMap);
         delete tokenizer;
@@ -121,12 +121,12 @@
     return status;
 }
 
-status_t KeyCharacterMap::loadContents(const String8& filename, const char* contents,
+status_t KeyCharacterMap::loadContents(const std::string& filename, const char* contents,
         Format format, sp<KeyCharacterMap>* outMap) {
     outMap->clear();
 
     Tokenizer* tokenizer;
-    status_t status = Tokenizer::fromContents(filename, contents, &tokenizer);
+    status_t status = Tokenizer::fromContents(String8(filename.c_str()), contents, &tokenizer);
     if (status) {
         ALOGE("Error %d opening key character map.", status);
     } else {
@@ -944,7 +944,7 @@
             properties.add(Property(PROPERTY_NUMBER));
         } else {
             int32_t metaState;
-            status_t status = parseModifier(token, &metaState);
+            status_t status = parseModifier(token.string(), &metaState);
             if (status) {
                 ALOGE("%s: Expected a property name or modifier, got '%s'.",
                         mTokenizer->getLocation().string(), token.string());
@@ -1137,7 +1137,7 @@
     return NO_ERROR;
 }
 
-status_t KeyCharacterMap::Parser::parseModifier(const String8& token, int32_t* outMetaState) {
+status_t KeyCharacterMap::Parser::parseModifier(const std::string& token, int32_t* outMetaState) {
     if (token == "base") {
         *outMetaState = 0;
         return NO_ERROR;
@@ -1145,7 +1145,7 @@
 
     int32_t combinedMeta = 0;
 
-    const char* str = token.string();
+    const char* str = token.c_str();
     const char* start = str;
     for (const char* cur = str; ; cur++) {
         char ch = *cur;
@@ -1164,7 +1164,7 @@
             }
             if (combinedMeta & metaState) {
                 ALOGE("%s: Duplicate modifier combination '%s'.",
-                        mTokenizer->getLocation().string(), token.string());
+                        mTokenizer->getLocation().string(), token.c_str());
                 return BAD_VALUE;
             }
 
diff --git a/libs/input/KeyLayoutMap.cpp b/libs/input/KeyLayoutMap.cpp
index c440078..88cb0db 100644
--- a/libs/input/KeyLayoutMap.cpp
+++ b/libs/input/KeyLayoutMap.cpp
@@ -49,13 +49,13 @@
 KeyLayoutMap::~KeyLayoutMap() {
 }
 
-status_t KeyLayoutMap::load(const String8& filename, sp<KeyLayoutMap>* outMap) {
+status_t KeyLayoutMap::load(const std::string& filename, sp<KeyLayoutMap>* outMap) {
     outMap->clear();
 
     Tokenizer* tokenizer;
-    status_t status = Tokenizer::open(filename, &tokenizer);
+    status_t status = Tokenizer::open(String8(filename.c_str()), &tokenizer);
     if (status) {
-        ALOGE("Error %d opening key layout map file %s.", status, filename.string());
+        ALOGE("Error %d opening key layout map file %s.", status, filename.c_str());
     } else {
         sp<KeyLayoutMap> map = new KeyLayoutMap();
         if (!map.get()) {
diff --git a/libs/input/Keyboard.cpp b/libs/input/Keyboard.cpp
index 11842ee..0c22bfe 100644
--- a/libs/input/Keyboard.cpp
+++ b/libs/input/Keyboard.cpp
@@ -45,22 +45,22 @@
         String8 keyLayoutName;
         if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"),
                 keyLayoutName)) {
-            status_t status = loadKeyLayout(deviceIdenfifier, keyLayoutName);
+            status_t status = loadKeyLayout(deviceIdenfifier, keyLayoutName.c_str());
             if (status == NAME_NOT_FOUND) {
                 ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but "
                         "it was not found.",
-                        deviceIdenfifier.name.string(), keyLayoutName.string());
+                        deviceIdenfifier.name.c_str(), keyLayoutName.string());
             }
         }
 
         String8 keyCharacterMapName;
         if (deviceConfiguration->tryGetProperty(String8("keyboard.characterMap"),
                 keyCharacterMapName)) {
-            status_t status = loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName);
+            status_t status = loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName.c_str());
             if (status == NAME_NOT_FOUND) {
                 ALOGE("Configuration for keyboard device '%s' requested keyboard character "
                         "map '%s' but it was not found.",
-                        deviceIdenfifier.name.string(), keyLayoutName.string());
+                        deviceIdenfifier.name.c_str(), keyLayoutName.string());
             }
         }
 
@@ -70,30 +70,30 @@
     }
 
     // Try searching by device identifier.
-    if (probeKeyMap(deviceIdenfifier, String8::empty())) {
+    if (probeKeyMap(deviceIdenfifier, "")) {
         return OK;
     }
 
     // Fall back on the Generic key map.
     // TODO Apply some additional heuristics here to figure out what kind of
     //      generic key map to use (US English, etc.) for typical external keyboards.
-    if (probeKeyMap(deviceIdenfifier, String8("Generic"))) {
+    if (probeKeyMap(deviceIdenfifier, "Generic")) {
         return OK;
     }
 
     // Try the Virtual key map as a last resort.
-    if (probeKeyMap(deviceIdenfifier, String8("Virtual"))) {
+    if (probeKeyMap(deviceIdenfifier, "Virtual")) {
         return OK;
     }
 
     // Give up!
     ALOGE("Could not determine key map for device '%s' and no default key maps were found!",
-            deviceIdenfifier.name.string());
+            deviceIdenfifier.name.c_str());
     return NAME_NOT_FOUND;
 }
 
 bool KeyMap::probeKeyMap(const InputDeviceIdentifier& deviceIdentifier,
-        const String8& keyMapName) {
+        const std::string& keyMapName) {
     if (!haveKeyLayout()) {
         loadKeyLayout(deviceIdentifier, keyMapName);
     }
@@ -104,10 +104,10 @@
 }
 
 status_t KeyMap::loadKeyLayout(const InputDeviceIdentifier& deviceIdentifier,
-        const String8& name) {
-    String8 path(getPath(deviceIdentifier, name,
+        const std::string& name) {
+    std::string path(getPath(deviceIdentifier, name,
             INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_LAYOUT));
-    if (path.isEmpty()) {
+    if (path.empty()) {
         return NAME_NOT_FOUND;
     }
 
@@ -116,15 +116,15 @@
         return status;
     }
 
-    keyLayoutFile.setTo(path);
+    keyLayoutFile = path;
     return OK;
 }
 
 status_t KeyMap::loadKeyCharacterMap(const InputDeviceIdentifier& deviceIdentifier,
-        const String8& name) {
-    String8 path(getPath(deviceIdentifier, name,
-            INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP));
-    if (path.isEmpty()) {
+        const std::string& name) {
+    std::string path = getPath(deviceIdentifier, name,
+            INPUT_DEVICE_CONFIGURATION_FILE_TYPE_KEY_CHARACTER_MAP);
+    if (path.empty()) {
         return NAME_NOT_FOUND;
     }
 
@@ -134,13 +134,13 @@
         return status;
     }
 
-    keyCharacterMapFile.setTo(path);
+    keyCharacterMapFile = path;
     return OK;
 }
 
-String8 KeyMap::getPath(const InputDeviceIdentifier& deviceIdentifier,
-        const String8& name, InputDeviceConfigurationFileType type) {
-    return name.isEmpty()
+std::string KeyMap::getPath(const InputDeviceIdentifier& deviceIdentifier,
+        const std::string& name, InputDeviceConfigurationFileType type) {
+    return name.empty()
             ? getInputDeviceConfigurationFilePathByDeviceIdentifier(deviceIdentifier, type)
             : getInputDeviceConfigurationFilePathByName(name, type);
 }
@@ -174,7 +174,7 @@
         }
     }
 
-    return strstr(deviceIdentifier.name.string(), "-keypad");
+    return strstr(deviceIdentifier.name.c_str(), "-keypad");
 }
 
 static int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaState) {
diff --git a/libs/input/VirtualKeyMap.cpp b/libs/input/VirtualKeyMap.cpp
index 9932973..3ec53bf 100644
--- a/libs/input/VirtualKeyMap.cpp
+++ b/libs/input/VirtualKeyMap.cpp
@@ -46,13 +46,13 @@
 VirtualKeyMap::~VirtualKeyMap() {
 }
 
-status_t VirtualKeyMap::load(const String8& filename, VirtualKeyMap** outMap) {
+status_t VirtualKeyMap::load(const std::string& filename, VirtualKeyMap** outMap) {
     *outMap = nullptr;
 
     Tokenizer* tokenizer;
-    status_t status = Tokenizer::open(filename, &tokenizer);
+    status_t status = Tokenizer::open(String8(filename.c_str()), &tokenizer);
     if (status) {
-        ALOGE("Error %d opening virtual key map file %s.", status, filename.string());
+        ALOGE("Error %d opening virtual key map file %s.", status, filename.c_str());
     } else {
         VirtualKeyMap* map = new VirtualKeyMap();
         if (!map) {
diff --git a/libs/ui/include/ui/DisplayInfo.h b/libs/ui/include/ui/DisplayInfo.h
index 94caf6b..8976d2d 100644
--- a/libs/ui/include/ui/DisplayInfo.h
+++ b/libs/ui/include/ui/DisplayInfo.h
@@ -35,6 +35,8 @@
     bool secure{false};
     nsecs_t appVsyncOffset{0};
     nsecs_t presentationDeadline{0};
+    uint32_t viewportW{0};
+    uint32_t viewportH{0};
 };
 
 /* Display orientations as defined in Surface.java and ISurfaceComposer.h. */
diff --git a/libs/ui/include/ui/Region.h b/libs/ui/include/ui/Region.h
index 7788452..68b60fc 100644
--- a/libs/ui/include/ui/Region.h
+++ b/libs/ui/include/ui/Region.h
@@ -25,6 +25,8 @@
 #include <ui/Rect.h>
 #include <utils/Flattenable.h>
 
+#include <android-base/macros.h>
+
 namespace android {
 // ---------------------------------------------------------------------------
 
@@ -93,11 +95,11 @@
             Region&     subtractSelf(const Region& rhs, int dx, int dy);
 
             // these translate rhs first
-    const   Region      translate(int dx, int dy) const;
-    const   Region      merge(const Region& rhs, int dx, int dy) const;
-    const   Region      mergeExclusive(const Region& rhs, int dx, int dy) const;
-    const   Region      intersect(const Region& rhs, int dx, int dy) const;
-    const   Region      subtract(const Region& rhs, int dx, int dy) const;
+    const   Region      translate(int dx, int dy) const WARN_UNUSED;
+    const   Region      merge(const Region& rhs, int dx, int dy) const WARN_UNUSED;
+    const   Region      mergeExclusive(const Region& rhs, int dx, int dy) const WARN_UNUSED;
+    const   Region      intersect(const Region& rhs, int dx, int dy) const WARN_UNUSED;
+    const   Region      subtract(const Region& rhs, int dx, int dy) const WARN_UNUSED;
 
     // convenience operators overloads
     inline  const Region      operator | (const Region& rhs) const;
diff --git a/opengl/libs/EGL/BlobCache.h b/opengl/libs/EGL/BlobCache.h
index 1f5d535..e5c5e5b 100644
--- a/opengl/libs/EGL/BlobCache.h
+++ b/opengl/libs/EGL/BlobCache.h
@@ -97,6 +97,10 @@
     //
     int unflatten(void const* buffer, size_t size);
 
+    // clear flushes out all contents of the cache then the BlobCache, leaving
+    // it in an empty state.
+    void clear() { mCacheEntries.clear(); }
+
 protected:
     // mMaxTotalSize is the maximum size that all cache entries can occupy. This
     // includes space for both keys and values. When a call to BlobCache::set
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index 77a474f..a964d29 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -76,16 +76,16 @@
     return value ? "true" : "false";
 }
 
-static String8 sha1(const String8& in) {
+static std::string sha1(const std::string& in) {
     SHA_CTX ctx;
     SHA1_Init(&ctx);
-    SHA1_Update(&ctx, reinterpret_cast<const u_char*>(in.string()), in.size());
+    SHA1_Update(&ctx, reinterpret_cast<const u_char*>(in.c_str()), in.size());
     u_char digest[SHA_DIGEST_LENGTH];
     SHA1_Final(digest, &ctx);
 
-    String8 out;
+    std::string out;
     for (size_t i = 0; i < SHA_DIGEST_LENGTH; i++) {
-        out.appendFormat("%02x", digest[i]);
+        out += StringPrintf("%02x", digest[i]);
     }
     return out;
 }
@@ -141,7 +141,7 @@
 
 // --- EventHub::Device ---
 
-EventHub::Device::Device(int fd, int32_t id, const String8& path,
+EventHub::Device::Device(int fd, int32_t id, const std::string& path,
         const InputDeviceIdentifier& identifier) :
         next(nullptr),
         fd(fd), id(id), path(path), identifier(identifier),
@@ -172,9 +172,9 @@
 }
 
 status_t EventHub::Device::enable() {
-    fd = open(path, O_RDWR | O_CLOEXEC | O_NONBLOCK);
+    fd = open(path.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
     if(fd < 0) {
-        ALOGE("could not open %s, %s\n", path.string(), strerror(errno));
+        ALOGE("could not open %s, %s\n", path.c_str(), strerror(errno));
         return -errno;
     }
     enabled = true;
@@ -307,7 +307,7 @@
             struct input_absinfo info;
             if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
                 ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
-                     axis, device->identifier.name.string(), device->fd, errno);
+                     axis, device->identifier.name.c_str(), device->fd, errno);
                 return -errno;
             }
 
@@ -416,7 +416,7 @@
             struct input_absinfo info;
             if(ioctl(device->fd, EVIOCGABS(axis), &info)) {
                 ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d",
-                     axis, device->identifier.name.string(), device->fd, errno);
+                     axis, device->identifier.name.c_str(), device->fd, errno);
                 return -errno;
             }
 
@@ -512,7 +512,7 @@
     return NAME_NOT_FOUND;
 }
 
-void EventHub::setExcludedDevices(const Vector<String8>& devices) {
+void EventHub::setExcludedDevices(const std::vector<std::string>& devices) {
     AutoMutex _l(mLock);
 
     mExcludedDevices = devices;
@@ -599,16 +599,16 @@
     return false;
 }
 
-static String8 generateDescriptor(InputDeviceIdentifier& identifier) {
-    String8 rawDescriptor;
-    rawDescriptor.appendFormat(":%04x:%04x:", identifier.vendor,
+static std::string generateDescriptor(InputDeviceIdentifier& identifier) {
+    std::string rawDescriptor;
+    rawDescriptor += StringPrintf(":%04x:%04x:", identifier.vendor,
             identifier.product);
     // TODO add handling for USB devices to not uniqueify kbs that show up twice
-    if (!identifier.uniqueId.isEmpty()) {
-        rawDescriptor.append("uniqueId:");
-        rawDescriptor.append(identifier.uniqueId);
+    if (!identifier.uniqueId.empty()) {
+        rawDescriptor += "uniqueId:";
+        rawDescriptor += identifier.uniqueId;
     } else if (identifier.nonce != 0) {
-        rawDescriptor.appendFormat("nonce:%04x", identifier.nonce);
+        rawDescriptor += StringPrintf("nonce:%04x", identifier.nonce);
     }
 
     if (identifier.vendor == 0 && identifier.product == 0) {
@@ -616,12 +616,12 @@
         // built-in so we need to rely on other information to uniquely identify
         // the input device.  Usually we try to avoid relying on the device name or
         // location but for built-in input device, they are unlikely to ever change.
-        if (!identifier.name.isEmpty()) {
-            rawDescriptor.append("name:");
-            rawDescriptor.append(identifier.name);
-        } else if (!identifier.location.isEmpty()) {
-            rawDescriptor.append("location:");
-            rawDescriptor.append(identifier.location);
+        if (!identifier.name.empty()) {
+            rawDescriptor += "name:";
+            rawDescriptor += identifier.name;
+        } else if (!identifier.location.empty()) {
+            rawDescriptor += "location:";
+            rawDescriptor += identifier.location;
         }
     }
     identifier.descriptor = sha1(rawDescriptor);
@@ -637,8 +637,8 @@
     // Ideally, we also want the descriptor to be short and relatively opaque.
 
     identifier.nonce = 0;
-    String8 rawDescriptor = generateDescriptor(identifier);
-    if (identifier.uniqueId.isEmpty()) {
+    std::string rawDescriptor = generateDescriptor(identifier);
+    if (identifier.uniqueId.empty()) {
         // If it didn't have a unique id check for conflicts and enforce
         // uniqueness if necessary.
         while(getDeviceByDescriptorLocked(identifier.descriptor) != nullptr) {
@@ -646,8 +646,8 @@
             rawDescriptor = generateDescriptor(identifier);
         }
     }
-    ALOGV("Created descriptor: raw=%s, cooked=%s", rawDescriptor.string(),
-            identifier.descriptor.string());
+    ALOGV("Created descriptor: raw=%s, cooked=%s", rawDescriptor.c_str(),
+            identifier.descriptor.c_str());
 }
 
 void EventHub::vibrate(int32_t deviceId, nsecs_t duration) {
@@ -664,7 +664,7 @@
         effect.replay.delay = 0;
         if (ioctl(device->fd, EVIOCSFF, &effect)) {
             ALOGW("Could not upload force feedback effect to device %s due to error %d.",
-                    device->identifier.name.string(), errno);
+                    device->identifier.name.c_str(), errno);
             return;
         }
         device->ffEffectId = effect.id;
@@ -677,7 +677,7 @@
         ev.value = 1;
         if (write(device->fd, &ev, sizeof(ev)) != sizeof(ev)) {
             ALOGW("Could not start force feedback effect on device %s due to error %d.",
-                    device->identifier.name.string(), errno);
+                    device->identifier.name.c_str(), errno);
             return;
         }
         device->ffEffectPlaying = true;
@@ -699,18 +699,18 @@
             ev.value = 0;
             if (write(device->fd, &ev, sizeof(ev)) != sizeof(ev)) {
                 ALOGW("Could not stop force feedback effect on device %s due to error %d.",
-                        device->identifier.name.string(), errno);
+                        device->identifier.name.c_str(), errno);
                 return;
             }
         }
     }
 }
 
-EventHub::Device* EventHub::getDeviceByDescriptorLocked(String8& descriptor) const {
+EventHub::Device* EventHub::getDeviceByDescriptorLocked(const std::string& descriptor) const {
     size_t size = mDevices.size();
     for (size_t i = 0; i < size; i++) {
         Device* device = mDevices.valueAt(i);
-        if (descriptor.compare(device->identifier.descriptor) == 0) {
+        if (descriptor == device->identifier.descriptor) {
             return device;
         }
     }
@@ -763,7 +763,7 @@
         while (mClosingDevices) {
             Device* device = mClosingDevices;
             ALOGV("Reporting device closed: id=%d, name=%s\n",
-                 device->id, device->path.string());
+                 device->id, device->path.c_str());
             mClosingDevices = device->next;
             event->when = now;
             event->deviceId = device->id == mBuiltInKeyboardId ? BUILT_IN_KEYBOARD_ID : device->id;
@@ -785,7 +785,7 @@
         while (mOpeningDevices != nullptr) {
             Device* device = mOpeningDevices;
             ALOGV("Reporting device opened: id=%d, name=%s\n",
-                 device->id, device->path.string());
+                 device->id, device->path.c_str());
             mOpeningDevices = device->next;
             event->when = now;
             event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
@@ -867,7 +867,7 @@
                     for (size_t i = 0; i < count; i++) {
                         struct input_event& iev = readBuffer[i];
                         ALOGV("%s got: time=%d.%06d, type=%d, code=%d, value=%d",
-                                device->path.string(),
+                                device->path.c_str(),
                                 (int) iev.time.tv_sec, (int) iev.time.tv_usec,
                                 iev.type, iev.code, iev.value);
 
@@ -936,7 +936,7 @@
                                         "event time %" PRId64 ", current time %" PRId64
                                         ", call time %" PRId64 ".  "
                                         "Using current time instead.",
-                                        device->path.string(), event->when, time, now);
+                                        device->path.c_str(), event->when, time, now);
                                 event->when = time;
                             } else {
                                 ALOGV("Event time is ok but failed the fast path and required "
@@ -962,12 +962,12 @@
                 }
             } else if (eventItem.events & EPOLLHUP) {
                 ALOGI("Removing device %s due to epoll hang-up event.",
-                        device->identifier.name.string());
+                        device->identifier.name.c_str());
                 deviceChanged = true;
                 closeDeviceLocked(device);
             } else {
                 ALOGW("Received unexpected epoll event 0x%08x for device %s.",
-                        eventItem.events, device->identifier.name.string());
+                        eventItem.events, device->identifier.name.c_str());
             }
         }
 
@@ -1125,14 +1125,14 @@
         //fprintf(stderr, "could not get device name for %s, %s\n", devicePath, strerror(errno));
     } else {
         buffer[sizeof(buffer) - 1] = '\0';
-        identifier.name.setTo(buffer);
+        identifier.name = buffer;
     }
 
     // Check to see if the device is on our excluded list
     for (size_t i = 0; i < mExcludedDevices.size(); i++) {
-        const String8& item = mExcludedDevices.itemAt(i);
+        const std::string& item = mExcludedDevices[i];
         if (identifier.name == item) {
-            ALOGI("ignoring event id %s driver %s\n", devicePath, item.string());
+            ALOGI("ignoring event id %s driver %s\n", devicePath, item.c_str());
             close(fd);
             return -1;
         }
@@ -1163,7 +1163,7 @@
         //fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
     } else {
         buffer[sizeof(buffer) - 1] = '\0';
-        identifier.location.setTo(buffer);
+        identifier.location = buffer;
     }
 
     // Get device unique id.
@@ -1171,7 +1171,7 @@
         //fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
     } else {
         buffer[sizeof(buffer) - 1] = '\0';
-        identifier.uniqueId.setTo(buffer);
+        identifier.uniqueId = buffer;
     }
 
     // Fill in the descriptor.
@@ -1179,7 +1179,7 @@
 
     // Allocate device.  (The device object takes ownership of the fd at this point.)
     int32_t deviceId = mNextDeviceId++;
-    Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
+    Device* device = new Device(fd, deviceId, devicePath, identifier);
 
     ALOGV("add device %d: %s\n", deviceId, devicePath);
     ALOGV("  bus:        %04x\n"
@@ -1187,10 +1187,10 @@
          "  product     %04x\n"
          "  version     %04x\n",
         identifier.bus, identifier.vendor, identifier.product, identifier.version);
-    ALOGV("  name:       \"%s\"\n", identifier.name.string());
-    ALOGV("  location:   \"%s\"\n", identifier.location.string());
-    ALOGV("  unique id:  \"%s\"\n", identifier.uniqueId.string());
-    ALOGV("  descriptor: \"%s\"\n", identifier.descriptor.string());
+    ALOGV("  name:       \"%s\"\n", identifier.name.c_str());
+    ALOGV("  location:   \"%s\"\n", identifier.location.c_str());
+    ALOGV("  unique id:  \"%s\"\n", identifier.uniqueId.c_str());
+    ALOGV("  descriptor: \"%s\"\n", identifier.descriptor.c_str());
     ALOGV("  driver:     v%d.%d.%d\n",
         driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
 
@@ -1343,7 +1343,7 @@
     // If the device isn't recognized as something we handle, don't monitor it.
     if (device->classes == 0) {
         ALOGV("Dropping device: id=%d, path='%s', name='%s'",
-                deviceId, devicePath, device->identifier.name.string());
+                deviceId, devicePath, device->identifier.name.c_str());
         delete device;
         return -1;
     }
@@ -1374,11 +1374,11 @@
 
     ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
             "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
-         deviceId, fd, devicePath, device->identifier.name.string(),
+         deviceId, fd, devicePath, device->identifier.name.c_str(),
          device->classes,
-         device->configurationFile.string(),
-         device->keyMap.keyLayoutFile.string(),
-         device->keyMap.keyCharacterMapFile.string(),
+         device->configurationFile.c_str(),
+         device->keyMap.keyLayoutFile.c_str(),
+         device->keyMap.keyCharacterMapFile.c_str(),
          toString(mBuiltInKeyboardId == deviceId));
 
     addDeviceLocked(device);
@@ -1392,11 +1392,11 @@
         unsigned int repeatRate[] = {0, 0};
         if (ioctl(device->fd, EVIOCSREP, repeatRate)) {
             ALOGW("Unable to disable kernel key repeat for %s: %s",
-                  device->path.string(), strerror(errno));
+                  device->path.c_str(), strerror(errno));
         }
     }
 
-    String8 wakeMechanism("EPOLLWAKEUP");
+    std::string wakeMechanism = "EPOLLWAKEUP";
     if (!mUsingEpollWakeup) {
 #ifndef EVIOCSSUSPENDBLOCK
         // uapi headers don't include EVIOCSSUSPENDBLOCK, and future kernels
@@ -1416,7 +1416,7 @@
     // clock.
     int clockId = CLOCK_MONOTONIC;
     bool usingClockIoctl = !ioctl(device->fd, EVIOCSCLOCKID, &clockId);
-    ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.string(),
+    ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.c_str(),
           toString(usingClockIoctl));
 }
 
@@ -1473,7 +1473,7 @@
     identifier.uniqueId = "<virtual>";
     assignDescriptorLocked(identifier);
 
-    Device* device = new Device(-1, VIRTUAL_KEYBOARD_ID, String8("<virtual>"), identifier);
+    Device* device = new Device(-1, VIRTUAL_KEYBOARD_ID, "<virtual>", identifier);
     device->classes = INPUT_DEVICE_CLASS_KEYBOARD
             | INPUT_DEVICE_CLASS_ALPHAKEY
             | INPUT_DEVICE_CLASS_DPAD
@@ -1491,26 +1491,26 @@
 void EventHub::loadConfigurationLocked(Device* device) {
     device->configurationFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
             device->identifier, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
-    if (device->configurationFile.isEmpty()) {
+    if (device->configurationFile.empty()) {
         ALOGD("No input device configuration file found for device '%s'.",
-                device->identifier.name.string());
+                device->identifier.name.c_str());
     } else {
-        status_t status = PropertyMap::load(device->configurationFile,
+        status_t status = PropertyMap::load(String8(device->configurationFile.c_str()),
                 &device->configuration);
         if (status) {
             ALOGE("Error loading input device configuration file for device '%s'.  "
                     "Using default configuration.",
-                    device->identifier.name.string());
+                    device->identifier.name.c_str());
         }
     }
 }
 
 status_t EventHub::loadVirtualKeyMapLocked(Device* device) {
     // The virtual key map is supplied by the kernel as a system board property file.
-    String8 path;
-    path.append("/sys/board_properties/virtualkeys.");
-    path.append(device->identifier.name);
-    if (access(path.string(), R_OK)) {
+    std::string path;
+    path += "/sys/board_properties/virtualkeys.";
+    path += device->identifier.name;
+    if (access(path.c_str(), R_OK)) {
         return NAME_NOT_FOUND;
     }
     return VirtualKeyMap::load(path, &device->virtualKeyMap);
@@ -1543,7 +1543,7 @@
 int32_t EventHub::getNextControllerNumberLocked(Device* device) {
     if (mControllerNumbers.isFull()) {
         ALOGI("Maximum number of controllers reached, assigning controller number 0 to device %s",
-                device->identifier.name.string());
+                device->identifier.name.c_str());
         return 0;
     }
     // Since the controller number 0 is reserved for non-controllers, translate all numbers up by
@@ -1617,12 +1617,12 @@
 
 void EventHub::closeDeviceLocked(Device* device) {
     ALOGI("Removed device: path=%s name=%s id=%d fd=%d classes=0x%x\n",
-         device->path.string(), device->identifier.name.string(), device->id,
+         device->path.c_str(), device->identifier.name.c_str(), device->id,
          device->fd, device->classes);
 
     if (device->id == mBuiltInKeyboardId) {
         ALOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
-                device->path.string(), mBuiltInKeyboardId);
+                device->path.c_str(), mBuiltInKeyboardId);
         mBuiltInKeyboardId = NO_BUILT_IN_KEYBOARD;
     }
 
@@ -1648,7 +1648,7 @@
         // Unlink the device from the opening devices list then delete it.
         // We don't need to tell the client that the device was closed because
         // it does not even know it was opened in the first place.
-        ALOGI("Device %s was immediately closed after opening.", device->path.string());
+        ALOGI("Device %s was immediately closed after opening.", device->path.c_str());
         if (pred) {
             pred->next = device->next;
         } else {
@@ -1750,28 +1750,28 @@
             const Device* device = mDevices.valueAt(i);
             if (mBuiltInKeyboardId == device->id) {
                 dump += StringPrintf(INDENT2 "%d: %s (aka device 0 - built-in keyboard)\n",
-                        device->id, device->identifier.name.string());
+                        device->id, device->identifier.name.c_str());
             } else {
                 dump += StringPrintf(INDENT2 "%d: %s\n", device->id,
-                        device->identifier.name.string());
+                        device->identifier.name.c_str());
             }
             dump += StringPrintf(INDENT3 "Classes: 0x%08x\n", device->classes);
-            dump += StringPrintf(INDENT3 "Path: %s\n", device->path.string());
+            dump += StringPrintf(INDENT3 "Path: %s\n", device->path.c_str());
             dump += StringPrintf(INDENT3 "Enabled: %s\n", toString(device->enabled));
-            dump += StringPrintf(INDENT3 "Descriptor: %s\n", device->identifier.descriptor.string());
-            dump += StringPrintf(INDENT3 "Location: %s\n", device->identifier.location.string());
+            dump += StringPrintf(INDENT3 "Descriptor: %s\n", device->identifier.descriptor.c_str());
+            dump += StringPrintf(INDENT3 "Location: %s\n", device->identifier.location.c_str());
             dump += StringPrintf(INDENT3 "ControllerNumber: %d\n", device->controllerNumber);
-            dump += StringPrintf(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.string());
+            dump += StringPrintf(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.c_str());
             dump += StringPrintf(INDENT3 "Identifier: bus=0x%04x, vendor=0x%04x, "
                     "product=0x%04x, version=0x%04x\n",
                     device->identifier.bus, device->identifier.vendor,
                     device->identifier.product, device->identifier.version);
             dump += StringPrintf(INDENT3 "KeyLayoutFile: %s\n",
-                    device->keyMap.keyLayoutFile.string());
+                    device->keyMap.keyLayoutFile.c_str());
             dump += StringPrintf(INDENT3 "KeyCharacterMapFile: %s\n",
-                    device->keyMap.keyCharacterMapFile.string());
+                    device->keyMap.keyCharacterMapFile.c_str());
             dump += StringPrintf(INDENT3 "ConfigurationFile: %s\n",
-                    device->configurationFile.string());
+                    device->configurationFile.c_str());
             dump += StringPrintf(INDENT3 "HaveKeyboardLayoutOverlay: %s\n",
                     toString(device->overlayKeyMap != nullptr));
         }
diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h
index dfe3def..ea663b7 100644
--- a/services/inputflinger/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -18,6 +18,8 @@
 #ifndef _RUNTIME_EVENT_HUB_H
 #define _RUNTIME_EVENT_HUB_H
 
+#include <vector>
+
 #include <input/Input.h>
 #include <input/InputDevice.h>
 #include <input/Keyboard.h>
@@ -29,7 +31,6 @@
 #include <utils/List.h>
 #include <utils/Errors.h>
 #include <utils/PropertyMap.h>
-#include <utils/Vector.h>
 #include <utils/KeyedVector.h>
 #include <utils/BitSet.h>
 
@@ -207,7 +208,7 @@
 
     // Sets devices that are excluded from opening.
     // This can be used to ignore input devices for sensors.
-    virtual void setExcludedDevices(const Vector<String8>& devices) = 0;
+    virtual void setExcludedDevices(const std::vector<std::string>& devices) = 0;
 
     /*
      * Wait for events to become available and returns them.
@@ -303,7 +304,7 @@
     virtual status_t mapAxis(int32_t deviceId, int32_t scanCode,
             AxisInfo* outAxisInfo) const;
 
-    virtual void setExcludedDevices(const Vector<String8>& devices);
+    virtual void setExcludedDevices(const std::vector<std::string>& devices);
 
     virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const;
     virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const;
@@ -344,7 +345,7 @@
 
         int fd; // may be -1 if device is closed
         const int32_t id;
-        const String8 path;
+        const std::string path;
         const InputDeviceIdentifier identifier;
 
         uint32_t classes;
@@ -357,7 +358,7 @@
         uint8_t ffBitmask[(FF_MAX + 1) / 8];
         uint8_t propBitmask[(INPUT_PROP_MAX + 1) / 8];
 
-        String8 configurationFile;
+        std::string configurationFile;
         PropertyMap* configuration;
         VirtualKeyMap* virtualKeyMap;
         KeyMap keyMap;
@@ -373,7 +374,8 @@
         int32_t timestampOverrideSec;
         int32_t timestampOverrideUsec;
 
-        Device(int fd, int32_t id, const String8& path, const InputDeviceIdentifier& identifier);
+        Device(int fd, int32_t id, const std::string& path,
+                const InputDeviceIdentifier& identifier);
         ~Device();
 
         void close();
@@ -413,7 +415,7 @@
     void scanDevicesLocked();
     status_t readNotifyLocked();
 
-    Device* getDeviceByDescriptorLocked(String8& descriptor) const;
+    Device* getDeviceByDescriptorLocked(const std::string& descriptor) const;
     Device* getDeviceLocked(int32_t deviceId) const;
     Device* getDeviceByPathLocked(const char* devicePath) const;
 
@@ -457,7 +459,7 @@
     bool mNeedToSendFinishedDeviceScan;
     bool mNeedToReopenDevices;
     bool mNeedToScanDevices;
-    Vector<String8> mExcludedDevices;
+    std::vector<std::string> mExcludedDevices;
 
     int mEpollFd;
     int mINotifyFd;
diff --git a/services/inputflinger/InputApplication.h b/services/inputflinger/InputApplication.h
index 724fc2c..9b365b9 100644
--- a/services/inputflinger/InputApplication.h
+++ b/services/inputflinger/InputApplication.h
@@ -17,6 +17,8 @@
 #ifndef _UI_INPUT_APPLICATION_H
 #define _UI_INPUT_APPLICATION_H
 
+#include <string>
+
 #include <input/Input.h>
 #include <utils/RefBase.h>
 #include <utils/Timers.h>
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index a213b2d..92e0af2 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -31,7 +31,6 @@
 #include <utils/Vector.h>
 #include <utils/Timers.h>
 #include <utils/RefBase.h>
-#include <utils/String8.h>
 
 namespace android {
 
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index a4f83b7..8f12129 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -257,11 +257,12 @@
 // --- InputReaderConfiguration ---
 
 bool InputReaderConfiguration::getDisplayViewport(ViewportType viewportType,
-        const String8* uniqueDisplayId, DisplayViewport* outViewport) const {
+        const std::string& uniqueDisplayId, DisplayViewport* outViewport) const {
     const DisplayViewport* viewport = nullptr;
-    if (viewportType == ViewportType::VIEWPORT_VIRTUAL && uniqueDisplayId != nullptr) {
+    if (viewportType == ViewportType::VIEWPORT_VIRTUAL && !uniqueDisplayId.empty()) {
+
         for (const DisplayViewport& currentViewport : mVirtualDisplays) {
-            if (currentViewport.uniqueId == *uniqueDisplayId) {
+            if (currentViewport.uniqueId == uniqueDisplayId) {
                 viewport = &currentViewport;
                 break;
             }
@@ -473,10 +474,10 @@
 
     if (device->isIgnored()) {
         ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
-                identifier.name.string());
+                identifier.name.c_str());
     } else {
         ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
-                identifier.name.string(), device->getSources());
+                identifier.name.c_str(), device->getSources());
     }
 
     mDevices.add(deviceId, device);
@@ -501,10 +502,10 @@
 
     if (device->isIgnored()) {
         ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
-                device->getId(), device->getName().string());
+                device->getId(), device->getName().c_str());
     } else {
         ALOGI("Device removed: id=%d, name='%s', sources=0x%08x",
-                device->getId(), device->getName().string(), device->getSources());
+                device->getId(), device->getName().c_str(), device->getSources());
     }
 
     if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
@@ -687,7 +688,7 @@
     if (now < mDisableVirtualKeysTimeout) {
         ALOGI("Dropping virtual key from device %s because virtual keys are "
                 "temporarily disabled for the next %0.3fms.  keyCode=%d, scanCode=%d",
-                device->getName().string(),
+                device->getName().c_str(),
                 (mDisableVirtualKeysTimeout - now) * 0.000001,
                 keyCode, scanCode);
         return true;
@@ -894,7 +895,7 @@
         if (i != 0) {
             dump += ", ";
         }
-        dump += mConfig.excludedDeviceNames.itemAt(i).string();
+        dump += mConfig.excludedDeviceNames[i];
     }
     dump += "]\n";
     dump += StringPrintf(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
@@ -1077,7 +1078,7 @@
     getDeviceInfo(& deviceInfo);
 
     dump += StringPrintf(INDENT "Device %d: %s\n", deviceInfo.getId(),
-            deviceInfo.getDisplayName().string());
+            deviceInfo.getDisplayName().c_str());
     dump += StringPrintf(INDENT2 "Generation: %d\n", mGeneration);
     dump += StringPrintf(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
     dump += StringPrintf(INDENT2 "HasMic:     %s\n", toString(mHasMic));
@@ -1135,7 +1136,7 @@
 
         if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_ALIAS)) {
             if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
-                String8 alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
+                std::string alias = mContext->getPolicy()->getDeviceAlias(mIdentifier);
                 if (mAlias != alias) {
                     mAlias = alias;
                     bumpGeneration();
@@ -1196,7 +1197,7 @@
 #endif
             }
         } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
-            ALOGI("Detected input event buffer overrun for device %s.", getName().string());
+            ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
             mDropUntilNextSync = true;
             reset(rawEvent->when);
         } else {
@@ -2294,7 +2295,7 @@
     if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
         if (mParameters.orientationAware) {
             DisplayViewport dvp;
-            config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, nullptr, &dvp);
+            config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, "", &dvp);
             mViewport = dvp;
         }
     }
@@ -2464,7 +2465,7 @@
             // key was not actually down
             ALOGI("Dropping key up from device %s because the key was not down.  "
                     "keyCode=%d, scanCode=%d",
-                    getDeviceName().string(), keyCode, scanCode);
+                    getDeviceName().c_str(), keyCode, scanCode);
             return;
         }
     }
@@ -2705,7 +2706,7 @@
         mOrientation = DISPLAY_ORIENTATION_0;
         if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
             DisplayViewport v;
-            if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, nullptr, &v)) {
+            if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, "", &v)) {
                 mOrientation = v.orientation;
             }
         }
@@ -3020,7 +3021,7 @@
     }
     if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
         DisplayViewport v;
-        if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, nullptr, &v)) {
+        if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, "", &v)) {
             mOrientation = v.orientation;
         } else {
             mOrientation = DISPLAY_ORIENTATION_0;
@@ -3394,8 +3395,10 @@
         mParameters.hasAssociatedDisplay = true;
         if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
             mParameters.associatedDisplayIsExternal = getDevice()->isExternal();
+            String8 uniqueDisplayId;
             getDevice()->getConfiguration().tryGetProperty(String8("touch.displayId"),
-                    mParameters.uniqueDisplayId);
+                    uniqueDisplayId);
+            mParameters.uniqueDisplayId = uniqueDisplayId.c_str();
         }
     }
 
@@ -3506,7 +3509,7 @@
     // Ensure we have valid X and Y axes.
     if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
         ALOGW(INDENT "Touch device '%s' did not report support for X or Y axis!  "
-                "The device will be inoperable.", getDeviceName().string());
+                "The device will be inoperable.", getDeviceName().c_str());
         mDeviceMode = DEVICE_MODE_DISABLED;
         return;
     }
@@ -3518,15 +3521,15 @@
     // Get associated display dimensions.
     DisplayViewport newViewport;
     if (mParameters.hasAssociatedDisplay) {
-        const String8* uniqueDisplayId = nullptr;
+        std::string uniqueDisplayId;
         ViewportType viewportTypeToUse;
 
         if (mParameters.associatedDisplayIsExternal) {
             viewportTypeToUse = ViewportType::VIEWPORT_EXTERNAL;
-        } else if (!mParameters.uniqueDisplayId.isEmpty()) {
+        } else if (!mParameters.uniqueDisplayId.empty()) {
             // If the IDC file specified a unique display Id, then it expects to be linked to a
             // virtual display with the same unique ID.
-            uniqueDisplayId = &mParameters.uniqueDisplayId;
+            uniqueDisplayId = mParameters.uniqueDisplayId;
             viewportTypeToUse = ViewportType::VIEWPORT_VIRTUAL;
         } else {
             viewportTypeToUse = ViewportType::VIEWPORT_INTERNAL;
@@ -3536,7 +3539,7 @@
             ALOGI(INDENT "Touch device '%s' could not query the properties of its associated "
                     "display.  The device will be inoperable until the display size "
                     "becomes available.",
-                    getDeviceName().string());
+                    getDeviceName().c_str());
             mDeviceMode = DEVICE_MODE_DISABLED;
             return;
         }
@@ -3642,7 +3645,7 @@
     if (viewportChanged || deviceModeChanged) {
         ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
                 "display id %d",
-                getDeviceId(), getDeviceName().string(), mSurfaceWidth, mSurfaceHeight,
+                getDeviceId(), getDeviceName().c_str(), mSurfaceWidth, mSurfaceHeight,
                 mSurfaceOrientation, mDeviceMode, mViewport.displayId);
 
         // Configure X and Y factors.
@@ -6925,7 +6928,7 @@
 #if DEBUG_POINTERS
             ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
                     "ignoring the rest.",
-                    getDeviceName().string(), MAX_POINTERS);
+                    getDeviceName().c_str(), MAX_POINTERS);
 #endif
             break; // too many fingers!
         }
@@ -7016,7 +7019,7 @@
         if (slotCount > MAX_SLOTS) {
             ALOGW("MultiTouch Device %s reported %zu slots but the framework "
                     "only supports a maximum of %zu slots at this time.",
-                    getDeviceName().string(), slotCount, MAX_SLOTS);
+                    getDeviceName().c_str(), slotCount, MAX_SLOTS);
             slotCount = MAX_SLOTS;
         }
         mMultiTouchMotionAccumulator.configure(getDevice(),
@@ -7259,7 +7262,7 @@
         // Prefer to keep explicitly mapped axes.
         if (mAxes.size() > PointerCoords::MAX_AXES) {
             ALOGI("Joystick '%s' has %zu axes but the framework only supports a maximum of %d.",
-                    getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
+                    getDeviceName().c_str(), mAxes.size(), PointerCoords::MAX_AXES);
             pruneAxes(true);
             pruneAxes(false);
         }
@@ -7281,7 +7284,7 @@
                 } else {
                     ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
                             "have already been assigned to other axes.",
-                            getDeviceName().string(), mAxes.keyAt(i));
+                            getDeviceName().c_str(), mAxes.keyAt(i));
                     mAxes.removeItemsAt(i--);
                     numAxes -= 1;
                 }
@@ -7310,7 +7313,7 @@
             continue;
         }
         ALOGI("Discarding joystick '%s' axis %d because there are too many axes.",
-                getDeviceName().string(), mAxes.keyAt(i));
+                getDeviceName().c_str(), mAxes.keyAt(i));
         mAxes.removeItemsAt(i);
     }
 }
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index af26b4f..c06168d 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -101,7 +101,7 @@
 
     // The excluded device names for the platform.
     // Devices with these names will be ignored.
-    Vector<String8> excludedDeviceNames;
+    std::vector<std::string> excludedDeviceNames;
 
     // Velocity control parameters for mouse pointer movements.
     VelocityControlParameters pointerVelocityControlParameters;
@@ -201,7 +201,7 @@
             pointerGestureZoomSpeedRatio(0.3f),
             showTouches(false) { }
 
-    bool getDisplayViewport(ViewportType viewportType, const String8* displayId,
+    bool getDisplayViewport(ViewportType viewportType, const std::string& uniqueDisplayId,
             DisplayViewport* outViewport) const;
     void setPhysicalDisplayViewport(ViewportType viewportType, const DisplayViewport& viewport);
     void setVirtualDisplayViewports(const Vector<DisplayViewport>& viewports);
@@ -274,11 +274,11 @@
             const InputDeviceIdentifier& identifier) = 0;
 
     /* Gets a user-supplied alias for a particular input device, or an empty string if none. */
-    virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier) = 0;
+    virtual std::string getDeviceAlias(const InputDeviceIdentifier& identifier) = 0;
 
     /* Gets the affine calibration associated with the specified device. */
     virtual TouchAffineTransformation getTouchAffineTransformation(
-            const String8& inputDeviceDescriptor, int32_t surfaceRotation) = 0;
+            const std::string& inputDeviceDescriptor, int32_t surfaceRotation) = 0;
 };
 
 
@@ -553,8 +553,8 @@
     inline int32_t getId() const { return mId; }
     inline int32_t getControllerNumber() const { return mControllerNumber; }
     inline int32_t getGeneration() const { return mGeneration; }
-    inline const String8& getName() const { return mIdentifier.name; }
-    inline const String8& getDescriptor() { return mIdentifier.descriptor; }
+    inline const std::string getName() const { return mIdentifier.name; }
+    inline const std::string getDescriptor() { return mIdentifier.descriptor; }
     inline uint32_t getClasses() const { return mClasses; }
     inline uint32_t getSources() const { return mSources; }
 
@@ -625,7 +625,7 @@
     int32_t mGeneration;
     int32_t mControllerNumber;
     InputDeviceIdentifier mIdentifier;
-    String8 mAlias;
+    std::string mAlias;
     uint32_t mClasses;
 
     Vector<InputMapper*> mMappers;
@@ -981,7 +981,7 @@
 
     inline InputDevice* getDevice() { return mDevice; }
     inline int32_t getDeviceId() { return mDevice->getId(); }
-    inline const String8 getDeviceName() { return mDevice->getName(); }
+    inline const std::string getDeviceName() { return mDevice->getName(); }
     inline InputReaderContext* getContext() { return mContext; }
     inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); }
     inline InputListenerInterface* getListener() { return mContext->getListener(); }
@@ -1309,7 +1309,7 @@
         bool associatedDisplayIsExternal;
         bool orientationAware;
         bool hasButtonUnderPad;
-        String8 uniqueDisplayId;
+        std::string uniqueDisplayId;
 
         enum GestureMode {
             GESTURE_MODE_SINGLE_TOUCH,
diff --git a/services/inputflinger/host/InputDriver.cpp b/services/inputflinger/host/InputDriver.cpp
index bd11d56..2f046c3 100644
--- a/services/inputflinger/host/InputDriver.cpp
+++ b/services/inputflinger/host/InputDriver.cpp
@@ -217,18 +217,18 @@
     idi.product = id->productId;
     idi.version = id->version;
 
-    String8 configFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
+    std::string configFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
             idi, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
-    if (configFile.isEmpty()) {
+    if (configFile.empty()) {
         ALOGD("No input device configuration file found for device '%s'.",
-                idi.name.string());
+                idi.name.c_str());
     } else {
         auto propMap = new input_property_map_t();
-        status_t status = PropertyMap::load(configFile, &propMap->propertyMap);
+        status_t status = PropertyMap::load(String8(configFile.c_str()), &propMap->propertyMap);
         if (status) {
             ALOGE("Error loading input device configuration file for device '%s'. "
                     "Using default configuration.",
-                    idi.name.string());
+                    idi.name.c_str());
             delete propMap;
             return nullptr;
         }
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 286cf88..9b985dc 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -142,7 +142,7 @@
     }
 
     void setDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
-            const String8& uniqueId) {
+            const std::string& uniqueId) {
         DisplayViewport v = createDisplayViewport(displayId, width, height, orientation, uniqueId);
         // Set the size of both the internal and external display at the same time.
         mConfig.setPhysicalDisplayViewport(ViewportType::VIEWPORT_INTERNAL, v);
@@ -150,14 +150,14 @@
     }
 
     void setVirtualDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
-            const String8& uniqueId) {
+            const std::string& uniqueId) {
         Vector<DisplayViewport> viewports;
         viewports.push_back(createDisplayViewport(displayId, width, height, orientation, uniqueId));
         mConfig.setVirtualDisplayViewports(viewports);
     }
 
-    void addExcludedDeviceName(const String8& deviceName) {
-        mConfig.excludedDeviceNames.push(deviceName);
+    void addExcludedDeviceName(const std::string& deviceName) {
+        mConfig.excludedDeviceNames.push_back(deviceName);
     }
 
     void addDisabledDevice(int32_t deviceId) {
@@ -188,7 +188,7 @@
         return mInputDevices;
     }
 
-    TouchAffineTransformation getTouchAffineTransformation(const String8& inputDeviceDescriptor,
+    TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
             int32_t surfaceRotation) {
         return transform;
     }
@@ -203,7 +203,7 @@
 
 private:
     DisplayViewport createDisplayViewport(int32_t displayId, int32_t width, int32_t height,
-            int32_t orientation, const String8& uniqueId) {
+            int32_t orientation, const std::string& uniqueId) {
         bool isRotated = (orientation == DISPLAY_ORIENTATION_90
                 || orientation == DISPLAY_ORIENTATION_270);
         DisplayViewport v;
@@ -239,8 +239,8 @@
         return nullptr;
     }
 
-    virtual String8 getDeviceAlias(const InputDeviceIdentifier&) {
-        return String8::empty();
+    virtual std::string getDeviceAlias(const InputDeviceIdentifier&) {
+        return "";
     }
 };
 
@@ -392,7 +392,7 @@
     };
 
     KeyedVector<int32_t, Device*> mDevices;
-    Vector<String8> mExcludedDevices;
+    std::vector<std::string> mExcludedDevices;
     List<RawEvent> mEvents;
 
 protected:
@@ -405,7 +405,7 @@
 public:
     FakeEventHub() { }
 
-    void addDevice(int32_t deviceId, const String8& name, uint32_t classes) {
+    void addDevice(int32_t deviceId, const std::string& name, uint32_t classes) {
         Device* device = new Device(classes);
         device->identifier.name = name;
         mDevices.add(deviceId, device);
@@ -534,7 +534,7 @@
         return device->leds.valueFor(led);
     }
 
-    Vector<String8>& getExcludedDevices() {
+    std::vector<std::string>& getExcludedDevices() {
         return mExcludedDevices;
     }
 
@@ -566,7 +566,7 @@
 private:
     Device* getDevice(int32_t deviceId) const {
         ssize_t index = mDevices.indexOfKey(deviceId);
-        return index >= 0 ? mDevices.valueAt(index) : NULL;
+        return index >= 0 ? mDevices.valueAt(index) : nullptr;
     }
 
     virtual uint32_t getDeviceClasses(int32_t deviceId) const {
@@ -658,7 +658,7 @@
         return NAME_NOT_FOUND;
     }
 
-    virtual void setExcludedDevices(const Vector<String8>& devices) {
+    virtual void setExcludedDevices(const std::vector<std::string>& devices) {
         mExcludedDevices = devices;
     }
 
@@ -1052,7 +1052,7 @@
         mNextDevice = device;
     }
 
-    InputDevice* newDevice(int32_t deviceId, int32_t controllerNumber, const String8& name,
+    InputDevice* newDevice(int32_t deviceId, int32_t controllerNumber, const std::string& name,
             uint32_t classes) {
         InputDeviceIdentifier identifier;
         identifier.name = name;
@@ -1101,7 +1101,7 @@
         mFakeEventHub.clear();
     }
 
-    void addDevice(int32_t deviceId, const String8& name, uint32_t classes,
+    void addDevice(int32_t deviceId, const std::string& name, uint32_t classes,
             const PropertyMap* configuration) {
         mFakeEventHub->addDevice(deviceId, name, classes);
 
@@ -1129,7 +1129,7 @@
     }
 
     FakeInputMapper* addDeviceWithFakeInputMapper(int32_t deviceId, int32_t controllerNumber,
-            const String8& name, uint32_t classes, uint32_t sources,
+            const std::string& name, uint32_t classes, uint32_t sources,
             const PropertyMap* configuration) {
         InputDevice* device = mReader->newDevice(deviceId, controllerNumber, name, classes);
         FakeInputMapper* mapper = new FakeInputMapper(device, sources);
@@ -1141,17 +1141,18 @@
 };
 
 TEST_F(InputReaderTest, GetInputDevices) {
-    ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"),
+    ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard",
             INPUT_DEVICE_CLASS_KEYBOARD, nullptr));
-    ASSERT_NO_FATAL_FAILURE(addDevice(2, String8("ignored"),
+    ASSERT_NO_FATAL_FAILURE(addDevice(2, "ignored",
             0, nullptr)); // no classes so device will be ignored
 
+
     Vector<InputDeviceInfo> inputDevices;
     mReader->getInputDevices(inputDevices);
 
     ASSERT_EQ(1U, inputDevices.size());
     ASSERT_EQ(1, inputDevices[0].getId());
-    ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.string());
+    ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.c_str());
     ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
     ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
     ASSERT_EQ(size_t(0), inputDevices[0].getMotionRanges().size());
@@ -1160,7 +1161,7 @@
     inputDevices = mFakePolicy->getInputDevices();
     ASSERT_EQ(1U, inputDevices.size());
     ASSERT_EQ(1, inputDevices[0].getId());
-    ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.string());
+    ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.c_str());
     ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
     ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
     ASSERT_EQ(size_t(0), inputDevices[0].getMotionRanges().size());
@@ -1169,12 +1170,12 @@
 TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) {
     constexpr int32_t deviceId = 1;
     constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
-    InputDevice* device = mReader->newDevice(deviceId, 0, String8("fake"), deviceClass);
+    InputDevice* device = mReader->newDevice(deviceId, 0, "fake", deviceClass);
     // Must add at least one mapper or the device will be ignored!
     FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_KEYBOARD);
     device->addMapper(mapper);
     mReader->setNextDevice(device);
-    addDevice(deviceId, String8("fake"), deviceClass, nullptr);
+    addDevice(deviceId, "fake", deviceClass, nullptr);
 
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr));
 
@@ -1208,7 +1209,7 @@
 
 TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
     FakeInputMapper* mapper = nullptr;
-    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
+    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, "fake",
             INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, nullptr));
     mapper->setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
 
@@ -1235,7 +1236,7 @@
 
 TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
     FakeInputMapper* mapper = nullptr;
-    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
+    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, "fake",
             INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, nullptr));
     mapper->setScanCodeState(KEY_A, AKEY_STATE_DOWN);
 
@@ -1262,7 +1263,7 @@
 
 TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
     FakeInputMapper* mapper = nullptr;
-    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
+    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, "fake",
             INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, nullptr));
     mapper->setSwitchState(SW_LID, AKEY_STATE_DOWN);
 
@@ -1289,8 +1290,9 @@
 
 TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
     FakeInputMapper* mapper = nullptr;
-    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
+    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, "fake",
             INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, nullptr));
+
     mapper->addSupportedKeyCode(AKEYCODE_A);
     mapper->addSupportedKeyCode(AKEYCODE_B);
 
@@ -1323,7 +1325,7 @@
 }
 
 TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) {
-    addDevice(1, String8("ignored"), INPUT_DEVICE_CLASS_KEYBOARD, nullptr);
+    addDevice(1, "ignored", INPUT_DEVICE_CLASS_KEYBOARD, nullptr);
 
     NotifyConfigurationChangedArgs args;
 
@@ -1333,7 +1335,7 @@
 
 TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
     FakeInputMapper* mapper = nullptr;
-    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, String8("fake"),
+    ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, 0, "fake",
             INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD, nullptr));
 
     mFakeEventHub->enqueueEvent(0, 1, EV_KEY, KEY_A, 1);
@@ -1373,7 +1375,7 @@
         mFakeListener = new FakeInputListener();
         mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
 
-        mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
+        mFakeEventHub->addDevice(DEVICE_ID, DEVICE_NAME, 0);
         InputDeviceIdentifier identifier;
         identifier.name = DEVICE_NAME;
         mDevice = new InputDevice(mFakeContext, DEVICE_ID, DEVICE_GENERATION,
@@ -1399,7 +1401,7 @@
 
 TEST_F(InputDeviceTest, ImmutableProperties) {
     ASSERT_EQ(DEVICE_ID, mDevice->getId());
-    ASSERT_STREQ(DEVICE_NAME, mDevice->getName());
+    ASSERT_STREQ(DEVICE_NAME, mDevice->getName().c_str());
     ASSERT_EQ(DEVICE_CLASSES, mDevice->getClasses());
 }
 
@@ -1427,7 +1429,7 @@
     InputDeviceInfo info;
     mDevice->getDeviceInfo(&info);
     ASSERT_EQ(DEVICE_ID, info.getId());
-    ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.string());
+    ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
     ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
     ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
 
@@ -1497,7 +1499,7 @@
     InputDeviceInfo info;
     mDevice->getDeviceInfo(&info);
     ASSERT_EQ(DEVICE_ID, info.getId());
-    ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.string());
+    ASSERT_STREQ(DEVICE_NAME, info.getIdentifier().name.c_str());
     ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
     ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
 
@@ -1570,7 +1572,7 @@
         mDevice = new InputDevice(mFakeContext, DEVICE_ID, DEVICE_GENERATION,
                 DEVICE_CONTROLLER_NUMBER, identifier, DEVICE_CLASSES);
 
-        mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
+        mFakeEventHub->addDevice(DEVICE_ID, DEVICE_NAME, 0);
     }
 
     virtual void TearDown() {
@@ -1597,12 +1599,12 @@
 
     void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
             int32_t orientation) {
-        mFakePolicy->setDisplayViewport(displayId, width, height, orientation, String8::empty());
+        mFakePolicy->setDisplayViewport(displayId, width, height, orientation, "");
         configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
     }
 
     void setVirtualDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
-            int32_t orientation, const String8& uniqueId) {
+            int32_t orientation, const std::string& uniqueId) {
         mFakePolicy->setVirtualDisplayViewport(displayId, width, height, orientation, uniqueId);
         configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
     }
@@ -3048,7 +3050,7 @@
 
 void TouchInputMapperTest::prepareVirtualDisplay(int32_t orientation) {
     setVirtualDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH,
-        VIRTUAL_DISPLAY_HEIGHT, orientation, String8(VIRTUAL_DISPLAY_UNIQUE_ID));
+        VIRTUAL_DISPLAY_HEIGHT, orientation, VIRTUAL_DISPLAY_UNIQUE_ID);
 }
 
 void TouchInputMapperTest::prepareVirtualKeys() {
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 05535a5..da57511 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -125,6 +125,7 @@
         "Scheduler/EventControlThread.cpp",
         "Scheduler/EventThread.cpp",
         "Scheduler/MessageQueue.cpp",
+        "Scheduler/Scheduler.cpp",
         "StartPropertySetThread.cpp",
         "SurfaceFlinger.cpp",
         "SurfaceInterceptor.cpp",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 1bb7a85..89394cd 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -58,7 +58,7 @@
         mRefreshPending(false) {
     ALOGV("Creating Layer %s", name.string());
 
-    mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);
+    mTexture.init(renderengine::Texture::TEXTURE_EXTERNAL, mTextureName);
 
     mPremultipliedAlpha = !(flags & ISurfaceComposerClient::eNonPremultiplied);
 
@@ -180,7 +180,7 @@
 
     if (!blackOutLayer) {
         // TODO: we could be more subtle with isFixedSize()
-        const bool useFiltering = getFiltering() || needsFiltering(renderArea) || isFixedSize();
+        const bool useFiltering = needsFiltering(renderArea) || isFixedSize();
 
         // Query the texture matrix given our current filtering mode.
         float textureMatrix[16];
@@ -589,17 +589,6 @@
 
     ui::Transform t = getTransform();
     Rect win = bounds;
-    Rect finalCrop = getFinalCrop(s);
-    if (!finalCrop.isEmpty()) {
-        win = t.transform(win);
-        if (!win.intersect(finalCrop, &win)) {
-            win.clear();
-        }
-        win = t.inverse().transform(win);
-        if (!win.intersect(bounds, &win)) {
-            win.clear();
-        }
-    }
 
     float left = float(win.left) / float(getActiveWidth(s));
     float top = float(win.top) / float(getActiveHeight(s));
@@ -608,7 +597,8 @@
 
     // TODO: we probably want to generate the texture coords with the mesh
     // here we assume that we only have 4 vertices
-    Mesh::VertexArray<vec2> texCoords(getBE().mMesh.getTexCoordArray<vec2>());
+    renderengine::Mesh::VertexArray<vec2> texCoords(getBE().mMesh.getTexCoordArray<vec2>());
+    // flip texcoords vertically because BufferLayerConsumer expects them to be in GL convention
     texCoords[0] = vec2(left, 1.0f - top);
     texCoords[1] = vec2(left, 1.0f - bottom);
     texCoords[2] = vec2(right, 1.0f - bottom);
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 3d06ded..45906ff 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -178,7 +178,7 @@
     bool mBufferLatched; // TODO: Use mActiveBuffer?
 
     // The texture used to draw the layer in GLES composition mode
-    mutable Texture mTexture;
+    mutable renderengine::Texture mTexture;
 
     bool mRefreshPending;
 };
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index aa8f4e1..fa181ad 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -54,7 +54,8 @@
 static const mat4 mtxIdentity;
 
 BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq,
-                                         RE::RenderEngine& engine, uint32_t tex, Layer* layer)
+                                         renderengine::RenderEngine& engine, uint32_t tex,
+                                         Layer* layer)
       : ConsumerBase(bq, false),
         mCurrentCrop(Rect::EMPTY_RECT),
         mCurrentTransform(0),
@@ -592,7 +593,8 @@
     ConsumerBase::dumpLocked(result, prefix);
 }
 
-BufferLayerConsumer::Image::Image(sp<GraphicBuffer> graphicBuffer, RE::RenderEngine& engine)
+BufferLayerConsumer::Image::Image(sp<GraphicBuffer> graphicBuffer,
+                                  renderengine::RenderEngine& engine)
       : mGraphicBuffer(graphicBuffer),
         mImage{engine.createImage()},
         mCreated(false),
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index 943b8a8..257a4e5 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -37,10 +37,10 @@
 class Layer;
 class String8;
 
-namespace RE {
+namespace renderengine {
 class RenderEngine;
 class Image;
-} // namespace RE
+} // namespace renderengine
 
 /*
  * BufferLayerConsumer consumes buffers of graphics data from a BufferQueue,
@@ -73,7 +73,7 @@
     // BufferLayerConsumer constructs a new BufferLayerConsumer object.  The
     // tex parameter indicates the name of the RenderEngine texture to which
     // images are to be streamed.
-    BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, RE::RenderEngine& engine,
+    BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, renderengine::RenderEngine& engine,
                         uint32_t tex, Layer* layer);
 
     // Sets the contents changed listener. This should be used instead of
@@ -216,19 +216,19 @@
     status_t bindTextureImageLocked();
 
 private:
-    // Image is a utility class for tracking and creating RE::Images. There
+    // Image is a utility class for tracking and creating renderengine::Images. There
     // is primarily just one image per slot, but there is also special cases:
     //  - After freeBuffer, we must still keep the current image/buffer
-    // Reference counting RE::Images lets us handle all these cases easily while
-    // also only creating new RE::Images from buffers when required.
+    // Reference counting renderengine::Images lets us handle all these cases easily while
+    // also only creating new renderengine::Images from buffers when required.
     class Image : public LightRefBase<Image> {
     public:
-        Image(sp<GraphicBuffer> graphicBuffer, RE::RenderEngine& engine);
+        Image(sp<GraphicBuffer> graphicBuffer, renderengine::RenderEngine& engine);
 
         Image(const Image& rhs) = delete;
         Image& operator=(const Image& rhs) = delete;
 
-        // createIfNeeded creates an RE::Image if we haven't created one yet.
+        // createIfNeeded creates an renderengine::Image if we haven't created one yet.
         status_t createIfNeeded();
 
         const sp<GraphicBuffer>& graphicBuffer() { return mGraphicBuffer; }
@@ -236,7 +236,7 @@
             return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle;
         }
 
-        const RE::Image& image() const { return *mImage; }
+        const renderengine::Image& image() const { return *mImage; }
 
     private:
         // Only allow instantiation using ref counting.
@@ -247,7 +247,7 @@
         sp<GraphicBuffer> mGraphicBuffer;
 
         // mImage is the image created from mGraphicBuffer.
-        std::unique_ptr<RE::Image> mImage;
+        std::unique_ptr<renderengine::Image> mImage;
         bool mCreated;
         int32_t mCropWidth;
         int32_t mCropHeight;
@@ -255,7 +255,7 @@
 
     // freeBufferLocked frees up the given buffer slot. If the slot has been
     // initialized this will release the reference to the GraphicBuffer in
-    // that slot and destroy the RE::Image in that slot.  Otherwise it has no
+    // that slot and destroy the renderengine::Image in that slot.  Otherwise it has no
     // effect.
     //
     // This method must be called with mMutex locked.
@@ -351,7 +351,7 @@
     // setFilteringEnabled().
     bool mFilteringEnabled;
 
-    RE::RenderEngine& mRE;
+    renderengine::RenderEngine& mRE;
 
     // mTexName is the name of the RenderEngine texture to which streamed
     // images will be bound when bindTexImage is called. It is set at
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 038eb01..ac3aad1 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -58,7 +58,6 @@
         return s.transparentRegionHint;
     }
     Rect getCrop(const Layer::State& s) const;
-    Rect getFinalCrop(const Layer::State& /*s*/) const { return Rect::EMPTY_RECT; }
 
     bool setTransform(uint32_t transform) override;
     bool setTransformToDisplayInverse(bool transformToDisplayInverse) override;
@@ -79,7 +78,6 @@
 
     // Override to ignore legacy layer state properties that are not used by BufferStateLayer
     bool setCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; };
-    bool setFinalCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; };
     void deferTransactionUntil_legacy(const sp<IBinder>& /*barrierHandle*/,
                                       uint64_t /*frameNumber*/) override {}
     void deferTransactionUntil_legacy(const sp<Layer>& /*barrierLayer*/,
@@ -127,7 +125,7 @@
 private:
     void onFirstRef() override;
 
-    std::unique_ptr<RE::Image> mTextureImage;
+    std::unique_ptr<renderengine::Image> mTextureImage;
 
     std::array<float, 16> mTransformMatrix;
 
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index acadfa0..9bf75e8 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -45,7 +45,7 @@
                         bool useIdentityTransform) {
     half4 color = getColor();
     if (color.a > 0) {
-        Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2);
+        renderengine::Mesh mesh(renderengine::Mesh::TRIANGLE_FAN, 4, 2);
         computeGeometry(renderArea, mesh, useIdentityTransform);
         auto& engine(mFlinger->getRenderEngine());
         engine.setupLayerBlending(getPremultipledAlpha(), false /* opaque */,
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index aab6c22..3eb0a92 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -215,9 +215,10 @@
         const wp<IBinder>& displayToken,
         const sp<ANativeWindow>& nativeWindow,
         const sp<DisplaySurface>& displaySurface,
-        std::unique_ptr<RE::Surface> renderSurface,
+        std::unique_ptr<renderengine::Surface> renderSurface,
         int displayWidth,
         int displayHeight,
+        int displayInstallOrientation,
         bool hasWideColorGamut,
         const HdrCapabilities& hdrCapabilities,
         const int32_t supportedPerFrameMetadata,
@@ -233,6 +234,7 @@
       mSurface{std::move(renderSurface)},
       mDisplayWidth(displayWidth),
       mDisplayHeight(displayHeight),
+      mDisplayInstallOrientation(displayInstallOrientation),
       mPageFlipCount(0),
       mIsSecure(isSecure),
       mLayerStack(NO_LAYER_STACK),
@@ -384,8 +386,7 @@
     size_t w = mDisplayWidth;
     size_t h = mDisplayHeight;
     Rect sourceCrop(0, 0, w, h);
-    mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, h,
-        false, ui::Transform::ROT_0);
+    mFlinger->getRenderEngine().setViewportAndProjection(w, h, sourceCrop, ui::Transform::ROT_0);
 }
 
 const sp<Fence>& DisplayDevice::getClientTargetAcquireFence() const {
@@ -604,9 +605,8 @@
     // need to take care of primary display rotation for mGlobalTransform
     // for case if the panel is not installed aligned with device orientation
     if (mType == DisplayType::DISPLAY_PRIMARY) {
-        int primaryDisplayOrientation = mFlinger->getPrimaryDisplayOrientation();
         DisplayDevice::orientationToTransfrom(
-                (orientation + primaryDisplayOrientation) % (DisplayState::eOrientation270 + 1),
+                (orientation + mDisplayInstallOrientation) % (DisplayState::eOrientation270 + 1),
                 w, h, &R);
     }
 
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index ddb09c5..ed73671 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -24,6 +24,7 @@
 #include <unordered_map>
 
 #include <binder/IBinder.h>
+#include <gui/LayerState.h>
 #include <hardware/hwcomposer_defs.h>
 #include <math/mat4.h>
 #include <renderengine/Surface.h>
@@ -84,9 +85,10 @@
             const wp<IBinder>& displayToken,
             const sp<ANativeWindow>& nativeWindow,
             const sp<DisplaySurface>& displaySurface,
-            std::unique_ptr<RE::Surface> renderSurface,
+            std::unique_ptr<renderengine::Surface> renderSurface,
             int displayWidth,
             int displayHeight,
+            int displayInstallOrientation,
             bool hasWideColorGamut,
             const HdrCapabilities& hdrCapabilities,
             const int32_t supportedPerFrameMetadata,
@@ -110,6 +112,7 @@
 
     int         getWidth() const;
     int         getHeight() const;
+    int         getInstallOrientation() const { return mDisplayInstallOrientation; }
 
     void                    setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers);
     const Vector< sp<Layer> >& getVisibleLayersSortedByZ() const;
@@ -231,9 +234,10 @@
     sp<ANativeWindow> mNativeWindow;
     sp<DisplaySurface> mDisplaySurface;
 
-    std::unique_ptr<RE::Surface> mSurface;
+    std::unique_ptr<renderengine::Surface> mSurface;
     int             mDisplayWidth;
     int             mDisplayHeight;
+    const int       mDisplayInstallOrientation;
     mutable uint32_t mPageFlipCount;
     std::string     mDisplayName;
     bool            mIsSecure;
@@ -339,18 +343,103 @@
                               rotation) {}
     DisplayRenderArea(const sp<const DisplayDevice> device, Rect sourceCrop, uint32_t reqWidth,
                       uint32_t reqHeight, ui::Transform::orientation_flags rotation)
-          : RenderArea(reqWidth, reqHeight, CaptureFill::OPAQUE, rotation), mDevice(device),
-                              mSourceCrop(sourceCrop) {}
+          : RenderArea(reqWidth, reqHeight, CaptureFill::OPAQUE,
+                       getDisplayRotation(rotation, device->getInstallOrientation())),
+            mDevice(device),
+            mSourceCrop(sourceCrop) {}
 
     const ui::Transform& getTransform() const override { return mDevice->getTransform(); }
     Rect getBounds() const override { return mDevice->getBounds(); }
     int getHeight() const override { return mDevice->getHeight(); }
     int getWidth() const override { return mDevice->getWidth(); }
     bool isSecure() const override { return mDevice->isSecure(); }
-    bool needsFiltering() const override { return mDevice->needsFiltering(); }
-    Rect getSourceCrop() const override { return mSourceCrop; }
+
+    bool needsFiltering() const override {
+        // check if the projection from the logical display to the physical
+        // display needs filtering
+        if (mDevice->needsFiltering()) {
+            return true;
+        }
+
+        // check if the projection from the logical render area (i.e., the
+        // physical display) to the physical render area requires filtering
+        const Rect sourceCrop = getSourceCrop();
+        int width = sourceCrop.width();
+        int height = sourceCrop.height();
+        if (getRotationFlags() & ui::Transform::ROT_90) {
+            std::swap(width, height);
+        }
+        return width != getReqWidth() || height != getReqHeight();
+    }
+
+    Rect getSourceCrop() const override {
+        // use the (projected) logical display viewport by default
+        if (mSourceCrop.isEmpty()) {
+            return mDevice->getScissor();
+        }
+
+        const int orientation = mDevice->getInstallOrientation();
+        if (orientation == DisplayState::eOrientationDefault) {
+            return mSourceCrop;
+        }
+
+        // Install orientation is transparent to the callers.  Apply it now.
+        uint32_t flags = 0x00;
+        switch (orientation) {
+            case DisplayState::eOrientation90:
+                flags = ui::Transform::ROT_90;
+                break;
+            case DisplayState::eOrientation180:
+                flags = ui::Transform::ROT_180;
+                break;
+            case DisplayState::eOrientation270:
+                flags = ui::Transform::ROT_270;
+                break;
+        }
+        ui::Transform tr;
+        tr.set(flags, getWidth(), getHeight());
+        return tr.transform(mSourceCrop);
+    }
 
 private:
+    // Install orientation is transparent to the callers.  We need to cancel
+    // it out by modifying rotation flags.
+    static ui::Transform::orientation_flags getDisplayRotation(
+            ui::Transform::orientation_flags rotation, int orientation) {
+        if (orientation == DisplayState::eOrientationDefault) {
+            return rotation;
+        }
+
+        // convert hw orientation into flag presentation
+        // here inverse transform needed
+        uint8_t hw_rot_90 = 0x00;
+        uint8_t hw_flip_hv = 0x00;
+        switch (orientation) {
+            case DisplayState::eOrientation90:
+                hw_rot_90 = ui::Transform::ROT_90;
+                hw_flip_hv = ui::Transform::ROT_180;
+                break;
+            case DisplayState::eOrientation180:
+                hw_flip_hv = ui::Transform::ROT_180;
+                break;
+            case DisplayState::eOrientation270:
+                hw_rot_90 = ui::Transform::ROT_90;
+                break;
+        }
+
+        // transform flags operation
+        // 1) flip H V if both have ROT_90 flag
+        // 2) XOR these flags
+        uint8_t rotation_rot_90 = rotation & ui::Transform::ROT_90;
+        uint8_t rotation_flip_hv = rotation & ui::Transform::ROT_180;
+        if (rotation_rot_90 & hw_rot_90) {
+            rotation_flip_hv = (~rotation_flip_hv) & ui::Transform::ROT_180;
+        }
+
+        return static_cast<ui::Transform::orientation_flags>(
+                (rotation_rot_90 ^ hw_rot_90) | (rotation_flip_hv ^ hw_flip_hv));
+    }
+
     const sp<const DisplayDevice> mDevice;
     const Rect mSourceCrop;
 };
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index c7d67e2..29de50c 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -78,7 +78,6 @@
         mOverrideScalingMode(-1),
         mCurrentFrameNumber(0),
         mFrameLatencyNeeded(false),
-        mFiltering(false),
         mNeedsFiltering(false),
         mProtectedByApp(false),
         mClientRef(client),
@@ -103,8 +102,6 @@
     mCurrentState.flags = layerFlags;
     mCurrentState.active_legacy.transform.set(0, 0);
     mCurrentState.crop_legacy.makeInvalid();
-    mCurrentState.finalCrop_legacy.makeInvalid();
-    mCurrentState.requestedFinalCrop_legacy = mCurrentState.finalCrop_legacy;
     mCurrentState.requestedCrop_legacy = mCurrentState.crop_legacy;
     mCurrentState.z = 0;
     mCurrentState.color.a = 1.0f;
@@ -298,11 +295,6 @@
     ui::Transform t = getTransform();
     win = t.transform(win);
 
-    Rect finalCrop = getFinalCrop(s);
-    if (!finalCrop.isEmpty()) {
-        win.intersect(finalCrop, &win);
-    }
-
     const sp<Layer>& p = mDrawingParent.promote();
     // Now we need to calculate the parent bounds, so we can clip ourselves to those.
     // When calculating the parent bounds for purposes of clipping,
@@ -351,13 +343,9 @@
 
     ui::Transform t = s.active_legacy.transform;
 
-    if (p != nullptr || !s.finalCrop_legacy.isEmpty()) {
+    if (p != nullptr) {
         floatWin = t.transform(floatWin);
         floatWin = floatWin.intersect(parentBounds);
-
-        if (!s.finalCrop_legacy.isEmpty()) {
-            floatWin = floatWin.intersect(s.finalCrop_legacy.toFloatRect());
-        }
         floatWin = t.inverse().transform(floatWin);
     }
 
@@ -388,12 +376,6 @@
     if (!activeCrop.intersect(display->getViewport(), &activeCrop)) {
         activeCrop.clear();
     }
-    Rect finalCrop = getFinalCrop(s);
-    if (!finalCrop.isEmpty()) {
-        if (!activeCrop.intersect(finalCrop, &activeCrop)) {
-            activeCrop.clear();
-        }
-    }
 
     const auto& p = mDrawingParent.promote();
     if (p != nullptr) {
@@ -554,12 +536,6 @@
     // computeBounds returns a FloatRect to provide more accuracy during the
     // transformation. We then round upon constructing 'frame'.
     Rect frame{t.transform(computeBounds(activeTransparentRegion))};
-    Rect finalCrop = getFinalCrop(s);
-    if (!finalCrop.isEmpty()) {
-        if (!frame.intersect(finalCrop, &frame)) {
-            frame.clear();
-        }
-    }
     if (!frame.intersect(display->getViewport(), &frame)) {
         frame.clear();
     }
@@ -671,10 +647,6 @@
     Rect bounds = reduce(win, getActiveTransparentRegion(s));
     Rect frame(getTransform().transform(bounds));
     frame.intersect(display->getViewport(), &frame);
-    Rect finalCrop = getFinalCrop(s);
-    if (!finalCrop.isEmpty()) {
-        frame.intersect(finalCrop, &frame);
-    }
     auto& displayTransform = display->getTransform();
     auto position = displayTransform.transform(frame);
 
@@ -700,10 +672,6 @@
     onDraw(renderArea, Region(renderArea.getBounds()), useIdentityTransform);
 }
 
-void Layer::draw(const RenderArea& renderArea) {
-    onDraw(renderArea, Region(renderArea.getBounds()), false);
-}
-
 void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue,
                             float alpha) const {
     auto& engine(mFlinger->getRenderEngine());
@@ -712,11 +680,6 @@
     engine.drawMesh(getBE().mMesh);
 }
 
-void Layer::clearWithOpenGL(const RenderArea& renderArea) const {
-    getBE().compositionInfo.firstClear = true;
-    computeGeometry(renderArea, getBE().mMesh, false);
-}
-
 void Layer::setCompositionType(int32_t displayId, HWC2::Composition type, bool /*callIntoHwc*/) {
     if (getBE().mHwcLayers.count(displayId) == 0) {
         ALOGE("setCompositionType called without a valid HWC layer");
@@ -768,38 +731,14 @@
     return true;
 }
 
-void Layer::setFiltering(bool filtering) {
-    mFiltering = filtering;
-}
-
-bool Layer::getFiltering() const {
-    return mFiltering;
-}
-
 // ----------------------------------------------------------------------------
 // local state
 // ----------------------------------------------------------------------------
 
-static void boundPoint(vec2* point, const Rect& crop) {
-    if (point->x < crop.left) {
-        point->x = crop.left;
-    }
-    if (point->x > crop.right) {
-        point->x = crop.right;
-    }
-    if (point->y < crop.top) {
-        point->y = crop.top;
-    }
-    if (point->y > crop.bottom) {
-        point->y = crop.bottom;
-    }
-}
-
-void Layer::computeGeometry(const RenderArea& renderArea, Mesh& mesh,
+void Layer::computeGeometry(const RenderArea& renderArea,
+                            renderengine::Mesh& mesh,
                             bool useIdentityTransform) const {
-    const Layer::State& s(getDrawingState());
     const ui::Transform renderAreaTransform(renderArea.getTransform());
-    const uint32_t height = renderArea.getHeight();
     FloatRect win = computeBounds();
 
     vec2 lt = vec2(win.left, win.top);
@@ -815,22 +754,11 @@
         rt = layerTransform.transform(rt);
     }
 
-    Rect finalCrop = getFinalCrop(s);
-    if (!finalCrop.isEmpty()) {
-        boundPoint(&lt, finalCrop);
-        boundPoint(&lb, finalCrop);
-        boundPoint(&rb, finalCrop);
-        boundPoint(&rt, finalCrop);
-    }
-
-    Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
+    renderengine::Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
     position[0] = renderAreaTransform.transform(lt);
     position[1] = renderAreaTransform.transform(lb);
     position[2] = renderAreaTransform.transform(rb);
     position[3] = renderAreaTransform.transform(rt);
-    for (size_t i = 0; i < 4; i++) {
-        position[i].y = height - position[i].y;
-    }
 }
 
 bool Layer::isSecure() const {
@@ -1291,20 +1219,6 @@
     return true;
 }
 
-bool Layer::setFinalCrop_legacy(const Rect& crop, bool immediate) {
-    if (mCurrentState.requestedFinalCrop_legacy == crop) return false;
-    mCurrentState.sequence++;
-    mCurrentState.requestedFinalCrop_legacy = crop;
-    if (immediate && !mFreezeGeometryUpdates) {
-        mCurrentState.finalCrop_legacy = crop;
-    }
-    mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate;
-
-    mCurrentState.modified = true;
-    setTransactionFlags(eTransactionNeeded);
-    return true;
-}
-
 bool Layer::setOverrideScalingMode(int32_t scalingMode) {
     if (scalingMode == mOverrideScalingMode) return false;
     mOverrideScalingMode = scalingMode;
@@ -1416,7 +1330,6 @@
     info.mWidth = ds.active_legacy.w;
     info.mHeight = ds.active_legacy.h;
     info.mCrop = ds.crop_legacy;
-    info.mFinalCrop = ds.finalCrop_legacy;
     info.mColor = ds.color;
     info.mFlags = ds.flags;
     info.mPixelFormat = getPixelFormat();
@@ -1954,7 +1867,6 @@
     size->set_h(state.active_legacy.h);
 
     LayerProtoHelper::writeToProto(state.crop_legacy, layerInfo->mutable_crop());
-    LayerProtoHelper::writeToProto(state.finalCrop_legacy, layerInfo->mutable_final_crop());
 
     layerInfo->set_is_opaque(isOpaque(state));
     layerInfo->set_invalidate(contentDirty);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 604ec65..9bd28b8 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -129,10 +129,6 @@
         Rect crop_legacy;
         Rect requestedCrop_legacy;
 
-        // finalCrop is expressed in display space coordinate.
-        Rect finalCrop_legacy;
-        Rect requestedFinalCrop_legacy;
-
         // If set, defers this state update until the identified Layer
         // receives a frame with the given frameNumber
         wp<Layer> barrierLayer_legacy;
@@ -225,8 +221,6 @@
     virtual bool setPosition(float x, float y, bool immediate);
     // Buffer space
     virtual bool setCrop_legacy(const Rect& crop, bool immediate);
-    // Parent buffer space/display space
-    virtual bool setFinalCrop_legacy(const Rect& crop, bool immediate);
 
     // TODO(b/38182121): Could we eliminate the various latching modes by
     // using the layer hierarchy?
@@ -284,7 +278,8 @@
         return getLayerStack() == layerStack && (!mPrimaryDisplayOnly || isPrimaryDisplay);
     }
 
-    void computeGeometry(const RenderArea& renderArea, Mesh& mesh, bool useIdentityTransform) const;
+    void computeGeometry(const RenderArea& renderArea, renderengine::Mesh& mesh,
+                         bool useIdentityTransform) const;
     FloatRect computeBounds(const Region& activeTransparentRegion) const;
     FloatRect computeBounds() const;
 
@@ -350,7 +345,6 @@
         return s.activeTransparentRegion_legacy;
     }
     virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; }
-    virtual Rect getFinalCrop(const Layer::State& s) const { return s.finalCrop_legacy; }
 
 protected:
     /*
@@ -413,7 +407,6 @@
      */
     void draw(const RenderArea& renderArea, const Region& clip);
     void draw(const RenderArea& renderArea, bool useIdentityTransform);
-    void draw(const RenderArea& renderArea);
 
     /*
      * doTransaction - process the transaction. This is a good place to figure
@@ -511,11 +504,6 @@
 
     // -----------------------------------------------------------------------
 
-    void clearWithOpenGL(const RenderArea& renderArea) const;
-    void setFiltering(bool filtering);
-    bool getFiltering() const;
-
-
     inline const State& getDrawingState() const { return mDrawingState; }
     inline const State& getCurrentState() const { return mCurrentState; }
     inline State& getCurrentState() { return mCurrentState; }
@@ -731,8 +719,6 @@
     int32_t mOverrideScalingMode;
     std::atomic<uint64_t> mCurrentFrameNumber;
     bool mFrameLatencyNeeded;
-    // Whether filtering is forced on or not
-    bool mFiltering;
     // Whether filtering is needed b/c of the drawingstate
     bool mNeedsFiltering;
 
diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp
index f389b57..da98bf5 100644
--- a/services/surfaceflinger/LayerBE.cpp
+++ b/services/surfaceflinger/LayerBE.cpp
@@ -30,14 +30,14 @@
 
 LayerBE::LayerBE(Layer* layer, std::string layerName)
       : mLayer(layer),
-        mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) {
+        mMesh(renderengine::Mesh::TRIANGLE_FAN, 4, 2, 2) {
     compositionInfo.layer = std::make_shared<LayerBE>(*this);
     compositionInfo.layerName = layerName;
 }
 
 LayerBE::LayerBE(const LayerBE& layer)
       : mLayer(layer.mLayer),
-        mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) {
+        mMesh(renderengine::Mesh::TRIANGLE_FAN, 4, 2, 2) {
     compositionInfo.layer = layer.compositionInfo.layer;
     compositionInfo.layerName = layer.mLayer->getName().string();
 }
@@ -48,7 +48,7 @@
     }
 }
 
-void LayerBE::clear(RE::RenderEngine& engine) {
+void LayerBE::clear(renderengine::RenderEngine& engine) {
     engine.setupFillWithColor(0, 0, 0, 0);
     engine.drawMesh(mMesh);
 }
diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h
index 531cdcd..f5150a7 100644
--- a/services/surfaceflinger/LayerBE.h
+++ b/services/surfaceflinger/LayerBE.h
@@ -91,13 +91,13 @@
     explicit LayerBE(const LayerBE& layer);
 
     void onLayerDisplayed(const sp<Fence>& releaseFence);
-    void clear(RE::RenderEngine& renderEngine);
-    Mesh& getMesh() { return mMesh; }
+    void clear(renderengine::RenderEngine& renderEngine);
+    renderengine::Mesh& getMesh() { return mMesh; }
 
 private:
     Layer*const mLayer;
     // The mesh used to draw the layer in GLES composition mode
-    Mesh mMesh;
+    renderengine::Mesh mMesh;
 
     // HWC items, accessed from the main thread
     struct HWCInfo {
diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp
index 136cdc0..72abea8 100644
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ b/services/surfaceflinger/LayerRejecter.cpp
@@ -90,11 +90,6 @@
                 mCurrent.crop_legacy = mFront.requestedCrop_legacy;
                 mRecomputeVisibleRegions = true;
             }
-            if (mFront.finalCrop_legacy != mFront.requestedFinalCrop_legacy) {
-                mFront.finalCrop_legacy = mFront.requestedFinalCrop_legacy;
-                mCurrent.finalCrop_legacy = mFront.requestedFinalCrop_legacy;
-                mRecomputeVisibleRegions = true;
-            }
         }
 
         ALOGD_IF(DEBUG_RESIZE,
diff --git a/services/surfaceflinger/RenderEngine/Android.bp b/services/surfaceflinger/RenderEngine/Android.bp
index 13752f2..064eb17 100644
--- a/services/surfaceflinger/RenderEngine/Android.bp
+++ b/services/surfaceflinger/RenderEngine/Android.bp
@@ -41,18 +41,25 @@
     name: "librenderengine_sources",
     srcs: [
         "Description.cpp",
-        "GLES20RenderEngine.cpp",
-        "GLExtensions.cpp",
-        "Image.cpp",
         "Mesh.cpp",
-        "Program.cpp",
-        "ProgramCache.cpp",
         "RenderEngine.cpp",
-        "Surface.cpp",
         "Texture.cpp",
     ],
 }
 
+filegroup {
+    name: "librenderengine_gl_sources",
+    srcs: [
+        "gl/GLES20RenderEngine.cpp",
+        "gl/GLExtensions.cpp",
+        "gl/GLFramebuffer.cpp",
+        "gl/GLImage.cpp",
+        "gl/GLSurface.cpp",
+        "gl/Program.cpp",
+        "gl/ProgramCache.cpp",
+    ],
+}
+
 cc_library_static {
     name: "librenderengine",
     defaults: ["librenderengine_defaults"],
@@ -68,6 +75,7 @@
     ],
     srcs: [
         ":librenderengine_sources",
+        ":librenderengine_gl_sources",
     ],
     lto: {
         thin: true,
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index d5f2103..b7522da 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-#include <renderengine/Description.h>
+#include <renderengine/private/Description.h>
 
 #include <stdint.h>
-#include <string.h>
 
 #include <utils/TypeHelpers.h>
 
 namespace android {
+namespace renderengine {
 
 void Description::setPremultipliedAlpha(bool premultipliedAlpha) {
     mPremultipliedAlpha = premultipliedAlpha;
@@ -95,4 +95,5 @@
     mDisplayMaxLuminance = maxLuminance;
 }
 
-} /* namespace android */
+}  // namespace renderengine
+}  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Mesh.cpp b/services/surfaceflinger/RenderEngine/Mesh.cpp
index 43852eb..5a3c2c8 100644
--- a/services/surfaceflinger/RenderEngine/Mesh.cpp
+++ b/services/surfaceflinger/RenderEngine/Mesh.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 namespace android {
+namespace renderengine {
 
 Mesh::Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordSize)
       : mVertexCount(vertexCount),
@@ -94,4 +95,5 @@
     return mStride;
 }
 
-} /* namespace android */
+}  // namespace renderengine
+}  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 594b1ed..e94200e 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -16,29 +16,30 @@
 
 #include <renderengine/RenderEngine.h>
 
+#include <vector>
+
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <configstore/Utils.h>
 #include <log/log.h>
 #include <private/gui/SyncFeatures.h>
-#include <renderengine/GLES20RenderEngine.h>
-#include <renderengine/GLExtensions.h>
 #include <renderengine/Image.h>
 #include <renderengine/Mesh.h>
 #include <renderengine/Surface.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
-
-#include <vector>
+#include <utils/KeyedVector.h>
+#include "gl/GLES20RenderEngine.h"
+#include "gl/GLExtensions.h"
+#include "gl/ProgramCache.h"
 
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
+using namespace android::renderengine::gl;
 
 extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 
-// ---------------------------------------------------------------------------
 namespace android {
-namespace RE {
-// ---------------------------------------------------------------------------
+namespace renderengine {
 
 RenderEngine::~RenderEngine() = default;
 
@@ -183,133 +184,6 @@
     return SyncFeatures::getInstance().useWaitSync();
 }
 
-bool RenderEngine::isCurrent() const {
-    return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext();
-}
-
-std::unique_ptr<RE::Surface> RenderEngine::createSurface() {
-    return std::make_unique<Surface>(*this);
-}
-
-std::unique_ptr<RE::Image> RenderEngine::createImage() {
-    return std::make_unique<Image>(*this);
-}
-
-bool RenderEngine::setCurrentSurface(const android::RE::Surface& surface) {
-    // Note: RE::Surface is an abstract interface. This implementation only ever
-    // creates RE::impl::Surface's, so it is safe to just cast to the actual
-    // type.
-    return setCurrentSurface(static_cast<const android::RE::impl::Surface&>(surface));
-}
-
-bool RenderEngine::setCurrentSurface(const android::RE::impl::Surface& surface) {
-    bool success = true;
-    EGLSurface eglSurface = surface.getEGLSurface();
-    if (eglSurface != eglGetCurrentSurface(EGL_DRAW)) {
-        success = eglMakeCurrent(mEGLDisplay, eglSurface, eglSurface, mEGLContext) == EGL_TRUE;
-        if (success && surface.getAsync()) {
-            eglSwapInterval(mEGLDisplay, 0);
-        }
-    }
-
-    return success;
-}
-
-void RenderEngine::resetCurrentSurface() {
-    eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-}
-
-base::unique_fd RenderEngine::flush() {
-    if (!GLExtensions::getInstance().hasNativeFenceSync()) {
-        return base::unique_fd();
-    }
-
-    EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
-    if (sync == EGL_NO_SYNC_KHR) {
-        ALOGW("failed to create EGL native fence sync: %#x", eglGetError());
-        return base::unique_fd();
-    }
-
-    // native fence fd will not be populated until flush() is done.
-    glFlush();
-
-    // get the fence fd
-    base::unique_fd fenceFd(eglDupNativeFenceFDANDROID(mEGLDisplay, sync));
-    eglDestroySyncKHR(mEGLDisplay, sync);
-    if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
-        ALOGW("failed to dup EGL native fence sync: %#x", eglGetError());
-    }
-
-    return fenceFd;
-}
-
-bool RenderEngine::finish() {
-    if (!GLExtensions::getInstance().hasFenceSync()) {
-        ALOGW("no synchronization support");
-        return false;
-    }
-
-    EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr);
-    if (sync == EGL_NO_SYNC_KHR) {
-        ALOGW("failed to create EGL fence sync: %#x", eglGetError());
-        return false;
-    }
-
-    EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
-                                         2000000000 /*2 sec*/);
-    EGLint error = eglGetError();
-    eglDestroySyncKHR(mEGLDisplay, sync);
-    if (result != EGL_CONDITION_SATISFIED_KHR) {
-        if (result == EGL_TIMEOUT_EXPIRED_KHR) {
-            ALOGW("fence wait timed out");
-        } else {
-            ALOGW("error waiting on EGL fence: %#x", error);
-        }
-        return false;
-    }
-
-    return true;
-}
-
-bool RenderEngine::waitFence(base::unique_fd fenceFd) {
-    if (!GLExtensions::getInstance().hasNativeFenceSync() ||
-        !GLExtensions::getInstance().hasWaitSync()) {
-        return false;
-    }
-
-    EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
-    EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
-    if (sync == EGL_NO_SYNC_KHR) {
-        ALOGE("failed to create EGL native fence sync: %#x", eglGetError());
-        return false;
-    }
-
-    // fenceFd is now owned by EGLSync
-    (void)fenceFd.release();
-
-    // XXX: The spec draft is inconsistent as to whether this should return an
-    // EGLint or void.  Ignore the return value for now, as it's not strictly
-    // needed.
-    eglWaitSyncKHR(mEGLDisplay, sync, 0);
-    EGLint error = eglGetError();
-    eglDestroySyncKHR(mEGLDisplay, sync);
-    if (error != EGL_SUCCESS) {
-        ALOGE("failed to wait for EGL native fence sync: %#x", error);
-        return false;
-    }
-
-    return true;
-}
-
-void RenderEngine::checkErrors() const {
-    do {
-        // there could be more than one error flag
-        GLenum error = glGetError();
-        if (error == GL_NO_ERROR) break;
-        ALOGE("GL error 0x%04x", int(error));
-    } while (true);
-}
-
 RenderEngine::GlesVersion RenderEngine::parseGlesVersion(const char* str) {
     int major, minor;
     if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
@@ -328,72 +202,6 @@
     return GLES_VERSION_1_0;
 }
 
-void RenderEngine::fillRegionWithColor(const Region& region, uint32_t height, float red,
-                                       float green, float blue, float alpha) {
-    size_t c;
-    Rect const* r = region.getArray(&c);
-    Mesh mesh(Mesh::TRIANGLES, c * 6, 2);
-    Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
-    for (size_t i = 0; i < c; i++, r++) {
-        position[i * 6 + 0].x = r->left;
-        position[i * 6 + 0].y = height - r->top;
-        position[i * 6 + 1].x = r->left;
-        position[i * 6 + 1].y = height - r->bottom;
-        position[i * 6 + 2].x = r->right;
-        position[i * 6 + 2].y = height - r->bottom;
-        position[i * 6 + 3].x = r->left;
-        position[i * 6 + 3].y = height - r->top;
-        position[i * 6 + 4].x = r->right;
-        position[i * 6 + 4].y = height - r->bottom;
-        position[i * 6 + 5].x = r->right;
-        position[i * 6 + 5].y = height - r->top;
-    }
-    setupFillWithColor(red, green, blue, alpha);
-    drawMesh(mesh);
-}
-
-void RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
-    glClearColor(red, green, blue, alpha);
-    glClear(GL_COLOR_BUFFER_BIT);
-}
-
-void RenderEngine::setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) {
-    glScissor(left, bottom, right, top);
-    glEnable(GL_SCISSOR_TEST);
-}
-
-void RenderEngine::disableScissor() {
-    glDisable(GL_SCISSOR_TEST);
-}
-
-void RenderEngine::genTextures(size_t count, uint32_t* names) {
-    glGenTextures(count, names);
-}
-
-void RenderEngine::deleteTextures(size_t count, uint32_t const* names) {
-    glDeleteTextures(count, names);
-}
-
-void RenderEngine::bindExternalTextureImage(uint32_t texName, const android::RE::Image& image) {
-    // Note: RE::Image is an abstract interface. This implementation only ever
-    // creates RE::impl::Image's, so it is safe to just cast to the actual type.
-    return bindExternalTextureImage(texName, static_cast<const android::RE::impl::Image&>(image));
-}
-
-void RenderEngine::bindExternalTextureImage(uint32_t texName,
-                                            const android::RE::impl::Image& image) {
-    const GLenum target = GL_TEXTURE_EXTERNAL_OES;
-
-    glBindTexture(target, texName);
-    if (image.getEGLImage() != EGL_NO_IMAGE_KHR) {
-        glEGLImageTargetTexture2DOES(target, static_cast<GLeglImageOES>(image.getEGLImage()));
-    }
-}
-
-void RenderEngine::readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) {
-    glReadPixels(l, b, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
-}
-
 void RenderEngine::dump(String8& result) {
     const GLExtensions& extensions = GLExtensions::getInstance();
 
@@ -405,45 +213,6 @@
     result.appendFormat("%s\n", extensions.getExtensions());
 }
 
-// ---------------------------------------------------------------------------
-
-void RenderEngine::bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer,
-                                                 RE::BindNativeBufferAsFramebuffer* bindHelper) {
-    bindHelper->mImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-                                           buffer, nullptr);
-    if (bindHelper->mImage == EGL_NO_IMAGE_KHR) {
-        bindHelper->mStatus = NO_MEMORY;
-        return;
-    }
-
-    uint32_t glStatus;
-    bindImageAsFramebuffer(bindHelper->mImage, &bindHelper->mTexName, &bindHelper->mFbName,
-                           &glStatus);
-
-    ALOGE_IF(glStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d",
-             glStatus);
-
-    bindHelper->mStatus = glStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
-}
-
-void RenderEngine::unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) {
-    if (bindHelper->mImage == EGL_NO_IMAGE_KHR) {
-        return;
-    }
-
-    // back to main framebuffer
-    unbindFramebuffer(bindHelper->mTexName, bindHelper->mFbName);
-    eglDestroyImageKHR(mEGLDisplay, bindHelper->mImage);
-
-    // Workaround for b/77935566 to force the EGL driver to release the
-    // screenshot buffer
-    setScissor(0, 0, 0, 0);
-    clearWithColor(0.0, 0.0, 0.0, 0.0);
-    disableScissor();
-}
-
-// ---------------------------------------------------------------------------
-
 static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
                                          EGLint wanted, EGLConfig* outConfig) {
     EGLint numConfigs = -1, n = 0;
@@ -594,12 +363,6 @@
     return config;
 }
 
-void RenderEngine::primeCache() const {
-    ProgramCache::getInstance().primeCache(mFeatureFlags & USE_COLOR_MANAGEMENT);
-}
-
-// ---------------------------------------------------------------------------
-
-} // namespace impl
-} // namespace RE
-} // namespace android
+}  // namespace impl
+}  // namespace renderengine
+}  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Texture.cpp b/services/surfaceflinger/RenderEngine/Texture.cpp
index c07ba08..5eabbcf 100644
--- a/services/surfaceflinger/RenderEngine/Texture.cpp
+++ b/services/surfaceflinger/RenderEngine/Texture.cpp
@@ -16,9 +16,8 @@
 
 #include <renderengine/Texture.h>
 
-#include <string.h>
-
 namespace android {
+namespace renderengine {
 
 Texture::Texture()
       : mTextureName(0), mTextureTarget(TEXTURE_2D), mWidth(0), mHeight(0), mFiltering(false) {}
@@ -74,4 +73,5 @@
     return mHeight;
 }
 
-} /* namespace android */
+}  // namespace renderengine
+}  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
similarity index 66%
rename from services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
rename to services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
index 617ba76..61df675 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
@@ -19,28 +19,31 @@
 #define LOG_TAG "RenderEngine"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include <renderengine/GLES20RenderEngine.h>
+#include "GLES20RenderEngine.h"
 
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <renderengine/Description.h>
-#include <renderengine/Mesh.h>
-#include <renderengine/Program.h>
-#include <renderengine/ProgramCache.h>
-#include <renderengine/Texture.h>
-#include <ui/ColorSpace.h>
-#include <ui/DebugUtils.h>
-#include <ui/Rect.h>
-#include <utils/String8.h>
-#include <utils/Trace.h>
-
-#include <cutils/compiler.h>
 #include <math.h>
-
 #include <fstream>
 #include <sstream>
 
-// ---------------------------------------------------------------------------
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <cutils/compiler.h>
+#include <renderengine/Mesh.h>
+#include <renderengine/Texture.h>
+#include <renderengine/private/Description.h>
+#include <ui/ColorSpace.h>
+#include <ui/DebugUtils.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+#include <utils/String8.h>
+#include <utils/Trace.h>
+#include "GLExtensions.h"
+#include "GLFramebuffer.h"
+#include "GLImage.h"
+#include "GLSurface.h"
+#include "Program.h"
+#include "ProgramCache.h"
+
 bool checkGlError(const char* op, int lineNumber) {
     bool errorFound = false;
     GLint error = glGetError();
@@ -100,11 +103,9 @@
     file.write(reinterpret_cast<char*>(outBuffer.data()), outBuffer.size());
 }
 
-// ---------------------------------------------------------------------------
 namespace android {
-namespace RE {
-namespace impl {
-// ---------------------------------------------------------------------------
+namespace renderengine {
+namespace gl {
 
 using ui::Dataspace;
 
@@ -155,30 +156,247 @@
 
 GLES20RenderEngine::~GLES20RenderEngine() {}
 
-size_t GLES20RenderEngine::getMaxTextureSize() const {
-    return mMaxTextureSize;
+std::unique_ptr<Framebuffer> GLES20RenderEngine::createFramebuffer() {
+    return std::make_unique<GLFramebuffer>(*this);
 }
 
-size_t GLES20RenderEngine::getMaxViewportDims() const {
-    return mMaxViewportDims[0] < mMaxViewportDims[1] ? mMaxViewportDims[0] : mMaxViewportDims[1];
+std::unique_ptr<Surface> GLES20RenderEngine::createSurface() {
+    return std::make_unique<GLSurface>(*this);
+}
+
+std::unique_ptr<Image> GLES20RenderEngine::createImage() {
+    return std::make_unique<GLImage>(*this);
+}
+
+void GLES20RenderEngine::primeCache() const {
+    ProgramCache::getInstance().primeCache(mFeatureFlags & USE_COLOR_MANAGEMENT);
+}
+
+bool GLES20RenderEngine::isCurrent() const {
+    return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext();
+}
+
+bool GLES20RenderEngine::setCurrentSurface(const Surface& surface) {
+    // Surface is an abstract interface. GLES20RenderEngine only ever
+    // creates GLSurface's, so it is safe to just cast to the actual
+    // type.
+    bool success = true;
+    const GLSurface& glSurface = static_cast<const GLSurface&>(surface);
+    EGLSurface eglSurface = glSurface.getEGLSurface();
+    if (eglSurface != eglGetCurrentSurface(EGL_DRAW)) {
+        success = eglMakeCurrent(mEGLDisplay, eglSurface, eglSurface, mEGLContext) == EGL_TRUE;
+        if (success && glSurface.getAsync()) {
+            eglSwapInterval(mEGLDisplay, 0);
+        }
+    }
+    return success;
+}
+
+void GLES20RenderEngine::resetCurrentSurface() {
+    eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+}
+
+base::unique_fd GLES20RenderEngine::flush() {
+    if (!GLExtensions::getInstance().hasNativeFenceSync()) {
+        return base::unique_fd();
+    }
+
+    EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
+    if (sync == EGL_NO_SYNC_KHR) {
+        ALOGW("failed to create EGL native fence sync: %#x", eglGetError());
+        return base::unique_fd();
+    }
+
+    // native fence fd will not be populated until flush() is done.
+    glFlush();
+
+    // get the fence fd
+    base::unique_fd fenceFd(eglDupNativeFenceFDANDROID(mEGLDisplay, sync));
+    eglDestroySyncKHR(mEGLDisplay, sync);
+    if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+        ALOGW("failed to dup EGL native fence sync: %#x", eglGetError());
+    }
+
+    return fenceFd;
+}
+
+bool GLES20RenderEngine::finish() {
+    if (!GLExtensions::getInstance().hasFenceSync()) {
+        ALOGW("no synchronization support");
+        return false;
+    }
+
+    EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr);
+    if (sync == EGL_NO_SYNC_KHR) {
+        ALOGW("failed to create EGL fence sync: %#x", eglGetError());
+        return false;
+    }
+
+    EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
+                                         2000000000 /*2 sec*/);
+    EGLint error = eglGetError();
+    eglDestroySyncKHR(mEGLDisplay, sync);
+    if (result != EGL_CONDITION_SATISFIED_KHR) {
+        if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+            ALOGW("fence wait timed out");
+        } else {
+            ALOGW("error waiting on EGL fence: %#x", error);
+        }
+        return false;
+    }
+
+    return true;
+}
+
+bool GLES20RenderEngine::waitFence(base::unique_fd fenceFd) {
+    if (!GLExtensions::getInstance().hasNativeFenceSync() ||
+        !GLExtensions::getInstance().hasWaitSync()) {
+        return false;
+    }
+
+    EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd, EGL_NONE};
+    EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
+    if (sync == EGL_NO_SYNC_KHR) {
+        ALOGE("failed to create EGL native fence sync: %#x", eglGetError());
+        return false;
+    }
+
+    // fenceFd is now owned by EGLSync
+    (void)fenceFd.release();
+
+    // XXX: The spec draft is inconsistent as to whether this should return an
+    // EGLint or void.  Ignore the return value for now, as it's not strictly
+    // needed.
+    eglWaitSyncKHR(mEGLDisplay, sync, 0);
+    EGLint error = eglGetError();
+    eglDestroySyncKHR(mEGLDisplay, sync);
+    if (error != EGL_SUCCESS) {
+        ALOGE("failed to wait for EGL native fence sync: %#x", error);
+        return false;
+    }
+
+    return true;
+}
+
+void GLES20RenderEngine::fillRegionWithColor(const Region& region, uint32_t height, float red,
+                                             float green, float blue, float alpha) {
+    size_t c;
+    Rect const* r = region.getArray(&c);
+    Mesh mesh(Mesh::TRIANGLES, c * 6, 2);
+    Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
+    for (size_t i = 0; i < c; i++, r++) {
+        position[i * 6 + 0].x = r->left;
+        position[i * 6 + 0].y = height - r->top;
+        position[i * 6 + 1].x = r->left;
+        position[i * 6 + 1].y = height - r->bottom;
+        position[i * 6 + 2].x = r->right;
+        position[i * 6 + 2].y = height - r->bottom;
+        position[i * 6 + 3].x = r->left;
+        position[i * 6 + 3].y = height - r->top;
+        position[i * 6 + 4].x = r->right;
+        position[i * 6 + 4].y = height - r->bottom;
+        position[i * 6 + 5].x = r->right;
+        position[i * 6 + 5].y = height - r->top;
+    }
+    setupFillWithColor(red, green, blue, alpha);
+    drawMesh(mesh);
+}
+
+void GLES20RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
+    glClearColor(red, green, blue, alpha);
+    glClear(GL_COLOR_BUFFER_BIT);
+}
+
+void GLES20RenderEngine::setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) {
+    glScissor(left, bottom, right, top);
+    glEnable(GL_SCISSOR_TEST);
+}
+
+void GLES20RenderEngine::disableScissor() {
+    glDisable(GL_SCISSOR_TEST);
+}
+
+void GLES20RenderEngine::genTextures(size_t count, uint32_t* names) {
+    glGenTextures(count, names);
+}
+
+void GLES20RenderEngine::deleteTextures(size_t count, uint32_t const* names) {
+    glDeleteTextures(count, names);
+}
+
+void GLES20RenderEngine::bindExternalTextureImage(uint32_t texName,
+                                                  const Image& image) {
+    const GLImage& glImage = static_cast<const GLImage&>(image);
+    const GLenum target = GL_TEXTURE_EXTERNAL_OES;
+
+    glBindTexture(target, texName);
+    if (glImage.getEGLImage() != EGL_NO_IMAGE_KHR) {
+        glEGLImageTargetTexture2DOES(target,
+                                     static_cast<GLeglImageOES>(glImage.getEGLImage()));
+    }
+}
+
+void GLES20RenderEngine::readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) {
+    glReadPixels(l, b, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+}
+
+status_t GLES20RenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {
+    GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(framebuffer);
+    EGLImageKHR eglImage = glFramebuffer->getEGLImage();
+    uint32_t textureName = glFramebuffer->getTextureName();
+    uint32_t framebufferName = glFramebuffer->getFramebufferName();
+
+    // Bind the texture and turn our EGLImage into a texture
+    glBindTexture(GL_TEXTURE_2D, textureName);
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglImage);
+
+    // Bind the Framebuffer to render into
+    glBindFramebuffer(GL_FRAMEBUFFER, framebufferName);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                           GL_TEXTURE_2D, textureName, 0);
+
+    mRenderToFbo = true;
+
+    uint32_t glStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+    ALOGE_IF(glStatus != GL_FRAMEBUFFER_COMPLETE_OES,
+             "glCheckFramebufferStatusOES error %d", glStatus);
+
+    return glStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
+}
+
+void GLES20RenderEngine::unbindFrameBuffer(Framebuffer* /* framebuffer */) {
+    mRenderToFbo = false;
+
+    // back to main framebuffer
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+    // Workaround for b/77935566 to force the EGL driver to release the
+    // screenshot buffer
+    setScissor(0, 0, 0, 0);
+    clearWithColor(0.0, 0.0, 0.0, 0.0);
+    disableScissor();
+}
+
+void GLES20RenderEngine::checkErrors() const {
+    do {
+        // there could be more than one error flag
+        GLenum error = glGetError();
+        if (error == GL_NO_ERROR) break;
+        ALOGE("GL error 0x%04x", int(error));
+    } while (true);
 }
 
 void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
-                                                  size_t hwh, bool yswap,
                                                   ui::Transform::orientation_flags rotation) {
     int32_t l = sourceCrop.left;
     int32_t r = sourceCrop.right;
-
-    // In GL, (0, 0) is the bottom-left corner, so flip y coordinates
-    int32_t t = hwh - sourceCrop.top;
-    int32_t b = hwh - sourceCrop.bottom;
-
-    mat4 m;
-    if (yswap) {
-        m = mat4::ortho(l, r, t, b, 0, 1);
-    } else {
-        m = mat4::ortho(l, r, b, t, 0, 1);
+    int32_t b = sourceCrop.bottom;
+    int32_t t = sourceCrop.top;
+    if (mRenderToFbo) {
+        std::swap(t, b);
     }
+    mat4 m = mat4::ortho(l, r, b, t, 0, 1);
 
     // Apply custom rotation to the projection.
     float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
@@ -272,30 +490,6 @@
     glDisable(GL_BLEND);
 }
 
-void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName,
-                                                uint32_t* fbName, uint32_t* status) {
-    GLuint tname, name;
-    // turn our EGLImage into a texture
-    glGenTextures(1, &tname);
-    glBindTexture(GL_TEXTURE_2D, tname);
-    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);
-
-    // create a Framebuffer Object to render into
-    glGenFramebuffers(1, &name);
-    glBindFramebuffer(GL_FRAMEBUFFER, name);
-    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0);
-
-    *status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-    *texName = tname;
-    *fbName = name;
-}
-
-void GLES20RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) {
-    glBindFramebuffer(GL_FRAMEBUFFER, 0);
-    glDeleteFramebuffers(1, &fbName);
-    glDeleteTextures(1, &texName);
-}
-
 void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) {
     mState.setPremultipliedAlpha(true);
     mState.setOpaque(false);
@@ -429,6 +623,14 @@
     }
 }
 
+size_t GLES20RenderEngine::getMaxTextureSize() const {
+    return mMaxTextureSize;
+}
+
+size_t GLES20RenderEngine::getMaxViewportDims() const {
+    return mMaxViewportDims[0] < mMaxViewportDims[1] ? mMaxViewportDims[0] : mMaxViewportDims[1];
+}
+
 void GLES20RenderEngine::dump(String8& result) {
     RenderEngine::dump(result);
     result.appendFormat("RenderEngine last dataspace conversion: (%s) to (%s)\n",
@@ -463,12 +665,6 @@
     return (isInputHdrDataSpace || isOutputHdrDataSpace) && inputTransfer != outputTransfer;
 }
 
-// ---------------------------------------------------------------------------
-} // namespace impl
-} // namespace RE
-} // namespace android
-// ---------------------------------------------------------------------------
-
-#if defined(__gl_h_)
-#error "don't include gl/gl.h in this file"
-#endif
+}  // namespace gl
+}  // namespace renderengine
+}  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
new file mode 100644
index 0000000..04dc1b1
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SF_GLES20RENDERENGINE_H_
+#define SF_GLES20RENDERENGINE_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <GLES2/gl2.h>
+#include <renderengine/RenderEngine.h>
+#include <renderengine/private/Description.h>
+
+namespace android {
+
+class String8;
+
+namespace renderengine {
+
+class Mesh;
+class Texture;
+
+namespace gl {
+
+class GLImage;
+class GLSurface;
+
+class GLES20RenderEngine : public impl::RenderEngine {
+public:
+    GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag
+    ~GLES20RenderEngine() override;
+
+    std::unique_ptr<Framebuffer> createFramebuffer() override;
+    std::unique_ptr<Surface> createSurface() override;
+    std::unique_ptr<Image> createImage() override;
+
+    void primeCache() const override;
+    bool isCurrent() const override;
+    bool setCurrentSurface(const Surface& surface) override;
+    void resetCurrentSurface() override;
+    base::unique_fd flush() override;
+    bool finish() override;
+    bool waitFence(base::unique_fd fenceFd) override;
+    void clearWithColor(float red, float green, float blue, float alpha) override;
+    void fillRegionWithColor(const Region& region, uint32_t height, float red, float green,
+                                     float blue, float alpha) override;
+    void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) override;
+    void disableScissor() override;
+    void genTextures(size_t count, uint32_t* names) override;
+    void deleteTextures(size_t count, uint32_t const* names) override;
+    void bindExternalTextureImage(uint32_t texName, const Image& image) override;
+    void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) override;
+    status_t bindFrameBuffer(Framebuffer* framebuffer) override;
+    void unbindFrameBuffer(Framebuffer* framebuffer) override;
+    void checkErrors() const override;
+
+protected:
+    void dump(String8& result) override;
+    void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
+                                  ui::Transform::orientation_flags rotation) override;
+    void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
+                            const half4& color) override;
+
+    // Color management related functions and state
+    void setSourceY410BT2020(bool enable) override;
+    void setSourceDataSpace(ui::Dataspace source) override;
+    void setOutputDataSpace(ui::Dataspace dataspace) override;
+    void setDisplayMaxLuminance(const float maxLuminance) override;
+
+    void setupLayerTexturing(const Texture& texture) override;
+    void setupLayerBlackedOut() override;
+    void setupFillWithColor(float r, float g, float b, float a) override;
+    void setupColorTransform(const mat4& colorTransform) override;
+    void disableTexturing() override;
+    void disableBlending() override;
+
+    void drawMesh(const Mesh& mesh) override;
+
+    size_t getMaxTextureSize() const override;
+    size_t getMaxViewportDims() const override;
+
+private:
+    // A data space is considered HDR data space if it has BT2020 color space
+    // with PQ or HLG transfer function.
+    bool isHdrDataSpace(const ui::Dataspace dataSpace) const;
+    bool needsXYZTransformMatrix() const;
+
+    GLuint mProtectedTexName;
+    GLint mMaxViewportDims[2];
+    GLint mMaxTextureSize;
+    GLuint mVpWidth;
+    GLuint mVpHeight;
+    Description mState;
+
+    mat4 mSrgbToDisplayP3;
+    mat4 mDisplayP3ToSrgb;
+    mat3 mSrgbToXyz;
+    mat3 mBt2020ToXyz;
+    mat3 mDisplayP3ToXyz;
+    mat4 mXyzToSrgb;
+    mat4 mXyzToDisplayP3;
+    mat4 mXyzToBt2020;
+
+    bool mRenderToFbo = false;
+
+    // Current dataspace of layer being rendered
+    ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN;
+
+    // Current output dataspace of the render engine
+    ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN;
+
+    // Whether device supports color management, currently color management
+    // supports sRGB, DisplayP3 color spaces.
+    const bool mUseColorManagement = false;
+};
+
+}  // namespace gl
+}  // namespace renderengine
+}  // namespace android
+
+#endif /* SF_GLES20RENDERENGINE_H_ */
diff --git a/services/surfaceflinger/RenderEngine/GLExtensions.cpp b/services/surfaceflinger/RenderEngine/gl/GLExtensions.cpp
similarity index 92%
rename from services/surfaceflinger/RenderEngine/GLExtensions.cpp
rename to services/surfaceflinger/RenderEngine/gl/GLExtensions.cpp
index b4fb2a1..6f50ea7 100644
--- a/services/surfaceflinger/RenderEngine/GLExtensions.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/GLExtensions.cpp
@@ -14,16 +14,17 @@
  * limitations under the License.
  */
 
-#include <renderengine/GLExtensions.h>
+#include "GLExtensions.h"
 
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 
-namespace android {
-// ---------------------------------------------------------------------------
+ANDROID_SINGLETON_STATIC_INSTANCE(android::renderengine::gl::GLExtensions)
 
-ANDROID_SINGLETON_STATIC_INSTANCE(GLExtensions)
+namespace android {
+namespace renderengine {
+namespace gl {
 
 SortedVector<String8> GLExtensions::parseExtensionString(char const* extensions) {
     SortedVector<String8> list;
@@ -120,5 +121,6 @@
     return mEGLExtensionList.indexOf(s) >= 0;
 }
 
-// ---------------------------------------------------------------------------
-}; // namespace android
+}  // namespace gl
+}  // namespace renderengine
+}  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/GLExtensions.h b/services/surfaceflinger/RenderEngine/gl/GLExtensions.h
similarity index 93%
rename from services/surfaceflinger/RenderEngine/include/renderengine/GLExtensions.h
rename to services/surfaceflinger/RenderEngine/gl/GLExtensions.h
index 1ff0d24..efdd8b7 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/GLExtensions.h
+++ b/services/surfaceflinger/RenderEngine/gl/GLExtensions.h
@@ -24,13 +24,13 @@
 #include <EGL/eglext.h>
 #include <GLES/gl.h>
 #include <GLES/glext.h>
-
 #include <utils/Singleton.h>
 #include <utils/SortedVector.h>
 #include <utils/String8.h>
 
 namespace android {
-// ---------------------------------------------------------------------------
+namespace renderengine {
+namespace gl {
 
 class GLExtensions : public Singleton<GLExtensions> {
     friend class Singleton<GLExtensions>;
@@ -82,7 +82,8 @@
     bool hasEGLExtension(char const* extension) const;
 };
 
-// ---------------------------------------------------------------------------
-}; // namespace android
+}  // namespace gl
+}  // namespace renderengine
+}  // namespace android
 
 #endif // ANDROID_SF_GLEXTENSION_H
diff --git a/services/surfaceflinger/RenderEngine/gl/GLFramebuffer.cpp b/services/surfaceflinger/RenderEngine/gl/GLFramebuffer.cpp
new file mode 100644
index 0000000..6aca1c8
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/gl/GLFramebuffer.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GLFramebuffer.h"
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include "GLES20RenderEngine.h"
+
+namespace android {
+namespace renderengine {
+namespace gl {
+
+GLFramebuffer::GLFramebuffer(const GLES20RenderEngine& engine)
+        : mEGLDisplay(engine.getEGLDisplay()),
+          mEGLImage(EGL_NO_IMAGE_KHR) {
+    glGenTextures(1, &mTextureName);
+    glGenFramebuffers(1, &mFramebufferName);
+}
+
+GLFramebuffer::~GLFramebuffer() {
+    glDeleteFramebuffers(1, &mFramebufferName);
+    glDeleteTextures(1, &mTextureName);
+    eglDestroyImageKHR(mEGLDisplay, mEGLImage);
+}
+
+bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer) {
+    if (mEGLImage != EGL_NO_IMAGE_KHR) {
+        eglDestroyImageKHR(mEGLDisplay, mEGLImage);
+        mEGLImage = EGL_NO_IMAGE_KHR;
+    }
+
+    if (nativeBuffer) {
+        mEGLImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
+                                      EGL_NATIVE_BUFFER_ANDROID,
+                                      nativeBuffer, nullptr);
+        if (mEGLImage == EGL_NO_IMAGE_KHR) {
+            return false;
+        }
+    }
+    return true;
+}
+
+}  // namespace gl
+}  // namespace renderengine
+}  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/gl/GLFramebuffer.h b/services/surfaceflinger/RenderEngine/gl/GLFramebuffer.h
new file mode 100644
index 0000000..90b2248
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/gl/GLFramebuffer.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <renderengine/Framebuffer.h>
+
+struct ANativeWindowBuffer;
+
+namespace android {
+namespace renderengine {
+namespace gl {
+
+class GLES20RenderEngine;
+
+class GLFramebuffer : public renderengine::Framebuffer {
+public:
+    explicit GLFramebuffer(const GLES20RenderEngine& engine);
+    ~GLFramebuffer() override;
+
+    bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer) override;
+    EGLImageKHR getEGLImage() const { return mEGLImage; }
+    uint32_t getTextureName() const { return mTextureName; }
+    uint32_t getFramebufferName() const { return mFramebufferName; }
+
+private:
+    EGLDisplay mEGLDisplay;
+    EGLImageKHR mEGLImage;
+    uint32_t mTextureName, mFramebufferName;
+};
+
+}  // namespace gl
+}  // namespace renderengine
+}  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Image.cpp b/services/surfaceflinger/RenderEngine/gl/GLImage.cpp
similarity index 78%
rename from services/surfaceflinger/RenderEngine/Image.cpp
rename to services/surfaceflinger/RenderEngine/gl/GLImage.cpp
index ee140eb..746f3e7 100644
--- a/services/surfaceflinger/RenderEngine/Image.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/GLImage.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,27 +14,17 @@
  * limitations under the License.
  */
 
-#include <renderengine/Image.h>
+#include "GLImage.h"
 
 #include <vector>
 
 #include <log/log.h>
-
-#include <renderengine/GLExtensions.h>
-#include <renderengine/RenderEngine.h>
+#include "GLExtensions.h"
+#include "GLES20RenderEngine.h"
 
 namespace android {
-namespace RE {
-
-Image::~Image() = default;
-
-namespace impl {
-
-Image::Image(const RenderEngine& engine) : mEGLDisplay(engine.getEGLDisplay()) {}
-
-Image::~Image() {
-    setNativeWindowBuffer(nullptr, false);
-}
+namespace renderengine {
+namespace gl {
 
 static std::vector<EGLint> buildAttributeList(bool isProtected) {
     std::vector<EGLint> attrs;
@@ -53,7 +43,13 @@
     return attrs;
 }
 
-bool Image::setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) {
+GLImage::GLImage(const GLES20RenderEngine& engine) : mEGLDisplay(engine.getEGLDisplay()) {}
+
+GLImage::~GLImage() {
+    setNativeWindowBuffer(nullptr, false);
+}
+
+bool GLImage::setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) {
     if (mEGLImage != EGL_NO_IMAGE_KHR) {
         if (!eglDestroyImageKHR(mEGLDisplay, mEGLImage)) {
             ALOGE("failed to destroy image: %#x", eglGetError());
@@ -74,6 +70,6 @@
     return true;
 }
 
-} // namespace impl
-} // namespace RE
-} // namespace android
+}  // namespace gl
+}  // namespace renderengine
+}  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/gl/GLImage.h b/services/surfaceflinger/RenderEngine/gl/GLImage.h
new file mode 100644
index 0000000..f670783
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/gl/GLImage.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <android-base/macros.h>
+#include <renderengine/Image.h>
+
+struct ANativeWindowBuffer;
+
+namespace android {
+namespace renderengine {
+namespace gl {
+
+class GLES20RenderEngine;
+
+class GLImage : public renderengine::Image {
+public:
+    explicit GLImage(const GLES20RenderEngine& engine);
+    ~GLImage() override;
+
+    bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) override;
+
+    EGLImageKHR getEGLImage() const { return mEGLImage; }
+
+private:
+    EGLDisplay mEGLDisplay;
+    EGLImageKHR mEGLImage = EGL_NO_IMAGE_KHR;
+
+    DISALLOW_COPY_AND_ASSIGN(GLImage);
+};
+
+}  // namespace gl
+}  // namespace renderengine
+}  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Surface.cpp b/services/surfaceflinger/RenderEngine/gl/GLSurface.cpp
similarity index 69%
rename from services/surfaceflinger/RenderEngine/Surface.cpp
rename to services/surfaceflinger/RenderEngine/gl/GLSurface.cpp
index 3e98ab4..ff9a252 100644
--- a/services/surfaceflinger/RenderEngine/Surface.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/GLSurface.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,32 +14,30 @@
  * limitations under the License.
  */
 
-#include <renderengine/Surface.h>
+#include "GLSurface.h"
 
 #include <log/log.h>
-#include <renderengine/RenderEngine.h>
 #include <ui/PixelFormat.h>
+#include "GLES20RenderEngine.h"
 
 namespace android {
-namespace RE {
+namespace renderengine {
+namespace gl {
 
-Surface::~Surface() = default;
-
-namespace impl {
-
-Surface::Surface(const RenderEngine& engine)
+GLSurface::GLSurface(const GLES20RenderEngine& engine)
       : mEGLDisplay(engine.getEGLDisplay()), mEGLConfig(engine.getEGLConfig()) {
     // RE does not assume any config when EGL_KHR_no_config_context is supported
     if (mEGLConfig == EGL_NO_CONFIG_KHR) {
-        mEGLConfig = RenderEngine::chooseEglConfig(mEGLDisplay, PIXEL_FORMAT_RGBA_8888, false);
+        mEGLConfig = GLES20RenderEngine::chooseEglConfig(mEGLDisplay,
+                                                         PIXEL_FORMAT_RGBA_8888, false);
     }
 }
 
-Surface::~Surface() {
+GLSurface::~GLSurface() {
     setNativeWindow(nullptr);
 }
 
-void Surface::setNativeWindow(ANativeWindow* window) {
+void GLSurface::setNativeWindow(ANativeWindow* window) {
     if (mEGLSurface != EGL_NO_SURFACE) {
         eglDestroySurface(mEGLDisplay, mEGLSurface);
         mEGLSurface = EGL_NO_SURFACE;
@@ -51,7 +49,7 @@
     }
 }
 
-void Surface::swapBuffers() const {
+void GLSurface::swapBuffers() const {
     if (!eglSwapBuffers(mEGLDisplay, mEGLSurface)) {
         EGLint error = eglGetError();
 
@@ -64,7 +62,7 @@
     }
 }
 
-EGLint Surface::queryConfig(EGLint attrib) const {
+EGLint GLSurface::queryConfig(EGLint attrib) const {
     EGLint value;
     if (!eglGetConfigAttrib(mEGLDisplay, mEGLConfig, attrib, &value)) {
         value = 0;
@@ -73,7 +71,7 @@
     return value;
 }
 
-EGLint Surface::querySurface(EGLint attrib) const {
+EGLint GLSurface::querySurface(EGLint attrib) const {
     EGLint value;
     if (!eglQuerySurface(mEGLDisplay, mEGLSurface, attrib, &value)) {
         value = 0;
@@ -82,30 +80,30 @@
     return value;
 }
 
-int32_t Surface::queryRedSize() const {
+int32_t GLSurface::queryRedSize() const {
     return queryConfig(EGL_RED_SIZE);
 }
 
-int32_t Surface::queryGreenSize() const {
+int32_t GLSurface::queryGreenSize() const {
     return queryConfig(EGL_GREEN_SIZE);
 }
 
-int32_t Surface::queryBlueSize() const {
+int32_t GLSurface::queryBlueSize() const {
     return queryConfig(EGL_BLUE_SIZE);
 }
 
-int32_t Surface::queryAlphaSize() const {
+int32_t GLSurface::queryAlphaSize() const {
     return queryConfig(EGL_ALPHA_SIZE);
 }
 
-int32_t Surface::queryWidth() const {
+int32_t GLSurface::queryWidth() const {
     return querySurface(EGL_WIDTH);
 }
 
-int32_t Surface::queryHeight() const {
+int32_t GLSurface::queryHeight() const {
     return querySurface(EGL_HEIGHT);
 }
 
-} // namespace impl
-} // namespace RE
-} // namespace android
+}  // namespace gl
+}  // namespace renderengine
+}  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/gl/GLSurface.h b/services/surfaceflinger/RenderEngine/gl/GLSurface.h
new file mode 100644
index 0000000..0b89c70
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/gl/GLSurface.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include <EGL/egl.h>
+#include <android-base/macros.h>
+#include <renderengine/Surface.h>
+
+struct ANativeWindow;
+
+namespace android {
+namespace renderengine {
+namespace gl {
+
+class GLES20RenderEngine;
+
+class GLSurface final : public renderengine::Surface {
+public:
+    GLSurface(const GLES20RenderEngine& engine);
+    ~GLSurface() override;
+
+    // renderengine::Surface implementation
+    void setCritical(bool enable) override { mCritical = enable; }
+    void setAsync(bool enable) override { mAsync = enable; }
+
+    void setNativeWindow(ANativeWindow* window) override;
+    void swapBuffers() const override;
+
+    int32_t queryRedSize() const override;
+    int32_t queryGreenSize() const override;
+    int32_t queryBlueSize() const override;
+    int32_t queryAlphaSize() const override;
+
+    int32_t queryWidth() const override;
+    int32_t queryHeight() const override;
+
+    bool getAsync() const { return mAsync; }
+    EGLSurface getEGLSurface() const { return mEGLSurface; }
+
+private:
+    EGLint queryConfig(EGLint attrib) const;
+    EGLint querySurface(EGLint attrib) const;
+
+    EGLDisplay mEGLDisplay;
+    EGLConfig mEGLConfig;
+
+    bool mCritical = false;
+    bool mAsync = false;
+
+    ANativeWindow* mWindow = nullptr;
+    EGLSurface mEGLSurface = EGL_NO_SURFACE;
+
+    DISALLOW_COPY_AND_ASSIGN(GLSurface);
+};
+
+}  // namespace gl
+}  // namespace renderengine
+}  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/gl/Program.cpp
similarity index 96%
rename from services/surfaceflinger/RenderEngine/Program.cpp
rename to services/surfaceflinger/RenderEngine/gl/Program.cpp
index 87371dc..c8d6cf9 100644
--- a/services/surfaceflinger/RenderEngine/Program.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/Program.cpp
@@ -14,17 +14,18 @@
  * limitations under the License.
  */
 
-#include <renderengine/Program.h>
+#include "Program.h"
 
 #include <stdint.h>
 
 #include <log/log.h>
 #include <math/mat4.h>
-#include <renderengine/Description.h>
-#include <renderengine/ProgramCache.h>
 #include <utils/String8.h>
+#include "ProgramCache.h"
 
 namespace android {
+namespace renderengine {
+namespace gl {
 
 Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const char* fragment)
       : mInitialized(false) {
@@ -152,4 +153,6 @@
     glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.mProjectionMatrix.asArray());
 }
 
-} /* namespace android */
+}  // namespace gl
+}  // namespace renderengine
+}  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Program.h b/services/surfaceflinger/RenderEngine/gl/Program.h
similarity index 92%
rename from services/surfaceflinger/RenderEngine/include/renderengine/Program.h
rename to services/surfaceflinger/RenderEngine/gl/Program.h
index 5e621cb..bb429ef 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/Program.h
+++ b/services/surfaceflinger/RenderEngine/gl/Program.h
@@ -20,13 +20,16 @@
 #include <stdint.h>
 
 #include <GLES2/gl2.h>
-#include <renderengine/Description.h>
-#include <renderengine/ProgramCache.h>
+#include <renderengine/private/Description.h>
+#include "ProgramCache.h"
 
 namespace android {
 
 class String8;
 
+namespace renderengine {
+namespace gl {
+
 /*
  * Abstracts a GLSL program comprising a vertex and fragment shader
  */
@@ -85,6 +88,8 @@
     GLint mOutputTransformMatrixLoc;
 };
 
-} /* namespace android */
+}  // namespace gl
+}  // namespace renderengine
+}  // namespace android
 
 #endif /* SF_RENDER_ENGINE_PROGRAM_H */
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp
similarity index 98%
rename from services/surfaceflinger/RenderEngine/ProgramCache.cpp
rename to services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp
index b7101e0..a19c1f1 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp
@@ -16,17 +16,20 @@
 
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include <renderengine/ProgramCache.h>
+#include "ProgramCache.h"
 
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
-#include <renderengine/Description.h>
-#include <renderengine/Program.h>
+#include <renderengine/private/Description.h>
 #include <utils/String8.h>
 #include <utils/Trace.h>
+#include "Program.h"
+
+ANDROID_SINGLETON_STATIC_INSTANCE(android::renderengine::gl::ProgramCache)
 
 namespace android {
-// -----------------------------------------------------------------------------------------------
+namespace renderengine {
+namespace gl {
 
 /*
  * A simple formatter class to automatically add the endl and
@@ -73,10 +76,6 @@
     return f;
 }
 
-// -----------------------------------------------------------------------------------------------
-
-ANDROID_SINGLETON_STATIC_INSTANCE(ProgramCache)
-
 ProgramCache::ProgramCache() {}
 
 ProgramCache::~ProgramCache() {}
@@ -685,4 +684,6 @@
     }
 }
 
-} /* namespace android */
+}  // namespace gl
+}  // namespace renderengine
+}  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/ProgramCache.h b/services/surfaceflinger/RenderEngine/gl/ProgramCache.h
similarity index 96%
rename from services/surfaceflinger/RenderEngine/include/renderengine/ProgramCache.h
rename to services/surfaceflinger/RenderEngine/gl/ProgramCache.h
index a5bee45..ea77a2d 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/ProgramCache.h
+++ b/services/surfaceflinger/RenderEngine/gl/ProgramCache.h
@@ -18,17 +18,23 @@
 #define SF_RENDER_ENGINE_PROGRAMCACHE_H
 
 #include <GLES2/gl2.h>
-#include <renderengine/Description.h>
+#include <renderengine/private/Description.h>
 #include <utils/KeyedVector.h>
 #include <utils/Singleton.h>
 #include <utils/TypeHelpers.h>
 
 namespace android {
 
+class String8;
+
+namespace renderengine {
+
 class Description;
+
+namespace gl {
+
 class Formatter;
 class Program;
-class String8;
 
 /*
  * This class generates GLSL programs suitable to handle a given
@@ -188,8 +194,11 @@
     DefaultKeyedVector<Key, Program*> mCache;
 };
 
-ANDROID_BASIC_TYPES_TRAITS(ProgramCache::Key)
+}  // namespace gl
+}  // namespace renderengine
 
-} /* namespace android */
+ANDROID_BASIC_TYPES_TRAITS(renderengine::gl::ProgramCache::Key)
+
+}  // namespace android
 
 #endif /* SF_RENDER_ENGINE_PROGRAMCACHE_H */
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Framebuffer.h b/services/surfaceflinger/RenderEngine/include/renderengine/Framebuffer.h
new file mode 100644
index 0000000..6595466
--- /dev/null
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/Framebuffer.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+struct ANativeWindowBuffer;
+
+namespace android {
+namespace renderengine {
+
+class Framebuffer {
+public:
+    virtual ~Framebuffer() = default;
+
+    virtual bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer) = 0;
+};
+
+}   // namespace renderengine
+}   // namespace android
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/include/renderengine/GLES20RenderEngine.h
deleted file mode 100644
index 0e9efdb..0000000
--- a/services/surfaceflinger/RenderEngine/include/renderengine/GLES20RenderEngine.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SF_GLES20RENDERENGINE_H_
-#define SF_GLES20RENDERENGINE_H_
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <GLES2/gl2.h>
-#include <renderengine/Description.h>
-#include <renderengine/ProgramCache.h>
-#include <renderengine/RenderEngine.h>
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class String8;
-class Mesh;
-class Texture;
-
-namespace RE {
-namespace impl {
-
-class GLES20RenderEngine : public RenderEngine {
-    GLuint mProtectedTexName;
-    GLint mMaxViewportDims[2];
-    GLint mMaxTextureSize;
-    GLuint mVpWidth;
-    GLuint mVpHeight;
-
-    struct Group {
-        GLuint texture;
-        GLuint fbo;
-        GLuint width;
-        GLuint height;
-        mat4 colorTransform;
-    };
-
-    Description mState;
-    Vector<Group> mGroupStack;
-
-    virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName,
-                                        uint32_t* status);
-    virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName);
-
-public:
-    GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag
-    virtual ~GLES20RenderEngine();
-
-protected:
-    virtual void dump(String8& result);
-    virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh,
-                                          bool yswap, ui::Transform::orientation_flags rotation);
-    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
-                                    const half4& color) override;
-
-    // Color management related functions and state
-    void setSourceY410BT2020(bool enable) override;
-    void setSourceDataSpace(ui::Dataspace source) override;
-    void setOutputDataSpace(ui::Dataspace dataspace) override;
-    void setDisplayMaxLuminance(const float maxLuminance) override;
-
-    virtual void setupLayerTexturing(const Texture& texture);
-    virtual void setupLayerBlackedOut();
-    virtual void setupFillWithColor(float r, float g, float b, float a);
-    virtual void setupColorTransform(const mat4& colorTransform);
-    virtual void disableTexturing();
-    virtual void disableBlending();
-
-    virtual void drawMesh(const Mesh& mesh);
-
-    virtual size_t getMaxTextureSize() const;
-    virtual size_t getMaxViewportDims() const;
-
-    // Current dataspace of layer being rendered
-    ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN;
-
-    // Current output dataspace of the render engine
-    ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN;
-
-    // Whether device supports color management, currently color management
-    // supports sRGB, DisplayP3 color spaces.
-    const bool mUseColorManagement = false;
-    mat4 mSrgbToDisplayP3;
-    mat4 mDisplayP3ToSrgb;
-    mat3 mSrgbToXyz;
-    mat3 mBt2020ToXyz;
-    mat3 mDisplayP3ToXyz;
-    mat4 mXyzToSrgb;
-    mat4 mXyzToDisplayP3;
-    mat4 mXyzToBt2020;
-
-private:
-    // A data space is considered HDR data space if it has BT2020 color space
-    // with PQ or HLG transfer function.
-    bool isHdrDataSpace(const ui::Dataspace dataSpace) const;
-    bool needsXYZTransformMatrix() const;
-};
-
-// ---------------------------------------------------------------------------
-} // namespace impl
-} // namespace RE
-} // namespace android
-// ---------------------------------------------------------------------------
-
-#endif /* SF_GLES20RENDERENGINE_H_ */
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Image.h b/services/surfaceflinger/RenderEngine/include/renderengine/Image.h
index c38fe0a..85ec91a 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/Image.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/Image.h
@@ -16,45 +16,17 @@
 
 #pragma once
 
-#include <cstdint>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
 struct ANativeWindowBuffer;
 
 namespace android {
-namespace RE {
+namespace renderengine {
 
 class Image {
 public:
-    virtual ~Image() = 0;
+    virtual ~Image() = default;
     virtual bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) = 0;
 };
 
-namespace impl {
+}  // namespace renderengine
+}  // namespace android
 
-class RenderEngine;
-
-class Image : public RE::Image {
-public:
-    explicit Image(const RenderEngine& engine);
-    ~Image() override;
-
-    Image(const Image&) = delete;
-    Image& operator=(const Image&) = delete;
-
-    bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) override;
-
-private:
-    // methods internal to RenderEngine
-    friend class RenderEngine;
-    EGLSurface getEGLImage() const { return mEGLImage; }
-
-    EGLDisplay mEGLDisplay;
-    EGLImageKHR mEGLImage = EGL_NO_IMAGE_KHR;
-};
-
-} // namespace impl
-} // namespace RE
-} // namespace android
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Mesh.h b/services/surfaceflinger/RenderEngine/include/renderengine/Mesh.h
index d0a9ac0..39ca2f7 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/Mesh.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/Mesh.h
@@ -20,6 +20,7 @@
 #include <stdint.h>
 
 namespace android {
+namespace renderengine {
 
 class Mesh {
 public:
@@ -97,5 +98,6 @@
     Primitive mPrimitive;
 };
 
-} /* namespace android */
+}  // namespace renderengine
+}  // namespace android
 #endif /* SF_RENDER_ENGINE_MESH_H */
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
index 6213784..86a1264 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
@@ -17,15 +17,16 @@
 #ifndef SF_RENDERENGINE_H_
 #define SF_RENDERENGINE_H_
 
-#include <memory>
-
 #include <stdint.h>
 #include <sys/types.h>
+#include <memory>
 
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <android-base/unique_fd.h>
 #include <math/mat4.h>
+#include <renderengine/Framebuffer.h>
+#include <renderengine/Image.h>
 #include <ui/GraphicTypes.h>
 #include <ui/Transform.h>
 
@@ -33,21 +34,19 @@
 
 struct ANativeWindowBuffer;
 
-// ---------------------------------------------------------------------------
 namespace android {
-// ---------------------------------------------------------------------------
 
 class String8;
 class Rect;
 class Region;
-class Mesh;
-class Texture;
 
-namespace RE {
+namespace renderengine {
 
-class Image;
-class Surface;
 class BindNativeBufferAsFramebuffer;
+class Image;
+class Mesh;
+class Surface;
+class Texture;
 
 namespace impl {
 class RenderEngine;
@@ -61,8 +60,9 @@
 
     virtual ~RenderEngine() = 0;
 
-    virtual std::unique_ptr<RE::Surface> createSurface() = 0;
-    virtual std::unique_ptr<RE::Image> createImage() = 0;
+    virtual std::unique_ptr<Framebuffer> createFramebuffer() = 0;
+    virtual std::unique_ptr<Surface> createSurface() = 0;
+    virtual std::unique_ptr<Image> createImage() = 0;
 
     virtual void primeCache() const = 0;
 
@@ -73,7 +73,7 @@
     virtual bool useWaitSync() const = 0;
 
     virtual bool isCurrent() const = 0;
-    virtual bool setCurrentSurface(const RE::Surface& surface) = 0;
+    virtual bool setCurrentSurface(const Surface& surface) = 0;
     virtual void resetCurrentSurface() = 0;
 
     // helpers
@@ -97,28 +97,27 @@
     virtual void disableScissor() = 0;
     virtual void genTextures(size_t count, uint32_t* names) = 0;
     virtual void deleteTextures(size_t count, uint32_t const* names) = 0;
-    virtual void bindExternalTextureImage(uint32_t texName, const RE::Image& image) = 0;
+    virtual void bindExternalTextureImage(uint32_t texName, const Image& image) = 0;
     virtual void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) = 0;
-    virtual void bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer,
-                                               RE::BindNativeBufferAsFramebuffer* bindHelper) = 0;
-    virtual void unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) = 0;
+    // When binding a native buffer, it must be done before setViewportAndProjection
+    // Returns NO_ERROR when binds successfully, NO_MEMORY when there's no memory for allocation.
+    virtual status_t bindFrameBuffer(Framebuffer* framebuffer) = 0;
+    virtual void unbindFrameBuffer(Framebuffer* framebuffer) = 0;
 
     // set-up
-    virtual void checkErrors() const;
-    virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, size_t hwh,
-                                          bool yswap, ui::Transform::orientation_flags rotation) = 0;
+    virtual void checkErrors() const = 0;
+    virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
+                                          ui::Transform::orientation_flags rotation) = 0;
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
                                     const half4& color) = 0;
     virtual void setupLayerTexturing(const Texture& texture) = 0;
     virtual void setupLayerBlackedOut() = 0;
     virtual void setupFillWithColor(float r, float g, float b, float a) = 0;
-
     virtual void setupColorTransform(const mat4& /* colorTransform */) = 0;
-
     virtual void disableTexturing() = 0;
     virtual void disableBlending() = 0;
 
-    // HDR and wide color gamut support
+    // HDR and color management support
     virtual void setSourceY410BT2020(bool enable) = 0;
     virtual void setSourceDataSpace(ui::Dataspace source) = 0;
     virtual void setOutputDataSpace(ui::Dataspace dataspace) = 0;
@@ -135,27 +134,28 @@
 class BindNativeBufferAsFramebuffer {
 public:
     BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer)
-          : mEngine(engine) {
-        mEngine.bindNativeBufferAsFrameBuffer(buffer, this);
+          : mEngine(engine),
+            mFramebuffer(mEngine.createFramebuffer()),
+            mStatus(NO_ERROR) {
+        mStatus = mFramebuffer->setNativeWindowBuffer(buffer) ?
+                  mEngine.bindFrameBuffer(mFramebuffer.get()) : NO_MEMORY;
     }
-    ~BindNativeBufferAsFramebuffer() { mEngine.unbindNativeBufferAsFrameBuffer(this); }
+    ~BindNativeBufferAsFramebuffer() {
+        mFramebuffer->setNativeWindowBuffer(nullptr);
+        mEngine.unbindFrameBuffer(mFramebuffer.get());
+    }
     status_t getStatus() const { return mStatus; }
 
-protected:
-    friend impl::RenderEngine;
-
+private:
     RenderEngine& mEngine;
-    EGLImageKHR mImage;
-    uint32_t mTexName, mFbName;
+    std::unique_ptr<Framebuffer> mFramebuffer;
     status_t mStatus;
 };
 
 namespace impl {
 
-class Image;
-class Surface;
-
-class RenderEngine : public RE::RenderEngine {
+class RenderEngine : public renderengine::RenderEngine {
+protected:
     enum GlesVersion {
         GLES_VERSION_1_0 = 0x10000,
         GLES_VERSION_1_1 = 0x10001,
@@ -171,7 +171,6 @@
 
     static bool overrideUseContextPriorityFromConfig(bool useContextPriority);
 
-protected:
     RenderEngine(uint32_t featureFlags);
 
     const uint32_t mFeatureFlags;
@@ -183,73 +182,21 @@
 
     static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
 
-    // RenderEngine interface implementation
-
-    std::unique_ptr<RE::Surface> createSurface() override;
-    std::unique_ptr<RE::Image> createImage() override;
-
-    void primeCache() const override;
-
     // dump the extension strings. always call the base class.
     void dump(String8& result) override;
 
     bool useNativeFenceSync() const override;
     bool useWaitSync() const override;
 
-    bool isCurrent() const;
-    bool setCurrentSurface(const RE::Surface& surface) override;
-    void resetCurrentSurface() override;
-
-    // synchronization
-
-    // flush submits RenderEngine command stream for execution and returns a
-    // native fence fd that is signaled when the execution has completed.  It
-    // returns -1 on errors.
-    base::unique_fd flush() override;
-    // finish waits until RenderEngine command stream has been executed.  It
-    // returns false on errors.
-    bool finish() override;
-    // waitFence inserts a wait on an external fence fd to RenderEngine
-    // command stream.  It returns false on errors.
-    bool waitFence(base::unique_fd fenceFd) override;
-
-    // helpers
-    void clearWithColor(float red, float green, float blue, float alpha) override;
-    void fillRegionWithColor(const Region& region, uint32_t height, float red, float green,
-                             float blue, float alpha) override;
-
-    // common to all GL versions
-    void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) override;
-    void disableScissor() override;
-    void genTextures(size_t count, uint32_t* names) override;
-    void deleteTextures(size_t count, uint32_t const* names) override;
-    void bindExternalTextureImage(uint32_t texName, const RE::Image& image) override;
-    void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels) override;
-
-    void checkErrors() const override;
-
     void setupColorTransform(const mat4& /* colorTransform */) override {}
 
     // internal to RenderEngine
     EGLDisplay getEGLDisplay() const;
     EGLConfig getEGLConfig() const;
-
-    // Common implementation
-    bool setCurrentSurface(const RE::impl::Surface& surface);
-    void bindExternalTextureImage(uint32_t texName, const RE::impl::Image& image);
-
-    void bindNativeBufferAsFrameBuffer(ANativeWindowBuffer* buffer,
-                                       RE::BindNativeBufferAsFramebuffer* bindHelper) override;
-    void unbindNativeBufferAsFrameBuffer(RE::BindNativeBufferAsFramebuffer* bindHelper) override;
-
-    // Overriden by each specialization
-    virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName,
-                                        uint32_t* status) = 0;
-    virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName) = 0;
 };
 
-} // namespace impl
-} // namespace RE
-} // namespace android
+}  // namespace impl
+}  // namespace renderengine
+}  // namespace android
 
 #endif /* SF_RENDERENGINE_H_ */
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Surface.h b/services/surfaceflinger/RenderEngine/include/renderengine/Surface.h
index d4d3d8c..3343e1f 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/Surface.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/Surface.h
@@ -18,16 +18,14 @@
 
 #include <cstdint>
 
-#include <EGL/egl.h>
-
 struct ANativeWindow;
 
 namespace android {
-namespace RE {
+namespace renderengine {
 
 class Surface {
 public:
-    virtual ~Surface() = 0;
+    virtual ~Surface() = default;
 
     virtual void setCritical(bool enable) = 0;
     virtual void setAsync(bool enable) = 0;
@@ -44,52 +42,5 @@
     virtual int32_t queryHeight() const = 0;
 };
 
-namespace impl {
-
-class RenderEngine;
-
-class Surface final : public RE::Surface {
-public:
-    Surface(const RenderEngine& engine);
-    ~Surface();
-
-    Surface(const Surface&) = delete;
-    Surface& operator=(const Surface&) = delete;
-
-    // RE::Surface implementation
-    void setCritical(bool enable) override { mCritical = enable; }
-    void setAsync(bool enable) override { mAsync = enable; }
-
-    void setNativeWindow(ANativeWindow* window) override;
-    void swapBuffers() const override;
-
-    int32_t queryRedSize() const override;
-    int32_t queryGreenSize() const override;
-    int32_t queryBlueSize() const override;
-    int32_t queryAlphaSize() const override;
-
-    int32_t queryWidth() const override;
-    int32_t queryHeight() const override;
-
-private:
-    EGLint queryConfig(EGLint attrib) const;
-    EGLint querySurface(EGLint attrib) const;
-
-    // methods internal to RenderEngine
-    friend class RenderEngine;
-    bool getAsync() const { return mAsync; }
-    EGLSurface getEGLSurface() const { return mEGLSurface; }
-
-    EGLDisplay mEGLDisplay;
-    EGLConfig mEGLConfig;
-
-    bool mCritical = false;
-    bool mAsync = false;
-
-    ANativeWindow* mWindow = nullptr;
-    EGLSurface mEGLSurface = EGL_NO_SURFACE;
-};
-
-} // namespace impl
-} // namespace RE
-} // namespace android
+}  // namespace renderengine
+}  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Texture.h b/services/surfaceflinger/RenderEngine/include/renderengine/Texture.h
index 56b6b31..fb3e0cc 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/Texture.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/Texture.h
@@ -14,22 +14,17 @@
  * limitations under the License.
  */
 
-#include <math/mat4.h>
-#include <stdint.h>
-
 #ifndef SF_RENDER_ENGINE_TEXTURE_H
 #define SF_RENDER_ENGINE_TEXTURE_H
 
+#include <stdint.h>
+
+#include <math/mat4.h>
+
 namespace android {
+namespace renderengine {
 
 class Texture {
-    uint32_t mTextureName;
-    uint32_t mTextureTarget;
-    size_t mWidth;
-    size_t mHeight;
-    bool mFiltering;
-    mat4 mTextureMatrix;
-
 public:
     enum Target { TEXTURE_2D = 0x0DE1, TEXTURE_EXTERNAL = 0x8D65 };
 
@@ -50,7 +45,16 @@
     bool getFiltering() const;
     size_t getWidth() const;
     size_t getHeight() const;
+
+private:
+    uint32_t mTextureName;
+    uint32_t mTextureTarget;
+    size_t mWidth;
+    size_t mHeight;
+    bool mFiltering;
+    mat4 mTextureMatrix;
 };
 
-} /* namespace android */
+}  // namespace renderengine
+}  // namespace android
 #endif /* SF_RENDER_ENGINE_TEXTURE_H */
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/Description.h b/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h
similarity index 93%
rename from services/surfaceflinger/RenderEngine/include/renderengine/Description.h
rename to services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h
index 9bc7e1c..a6301ae 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/Description.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h
@@ -14,15 +14,18 @@
  * limitations under the License.
  */
 
-#include <GLES2/gl2.h>
-#include <renderengine/Texture.h>
-
 #ifndef SF_RENDER_ENGINE_DESCRIPTION_H_
 #define SF_RENDER_ENGINE_DESCRIPTION_H_
 
-namespace android {
+#include <renderengine/Texture.h>
 
+namespace android {
+namespace renderengine {
+
+namespace gl {
 class Program;
+class ProgramCache;
+}
 
 /*
  * This holds the state of the rendering engine. This class is used
@@ -63,8 +66,8 @@
     void setDisplayMaxLuminance(const float maxLuminance);
 
 private:
-    friend class Program;
-    friend class ProgramCache;
+    friend class gl::Program;
+    friend class gl::ProgramCache;
 
     // whether textures are premultiplied
     bool mPremultipliedAlpha = false;
@@ -94,6 +97,7 @@
     mat4 mOutputTransformMatrix;
 };
 
-} /* namespace android */
+}  // namespace renderengine
+}  // namespace android
 
 #endif /* SF_RENDER_ENGINE_DESCRIPTION_H_ */
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index b84177c..fa2b0a6 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -45,11 +45,27 @@
 
 namespace impl {
 
+EventThread::EventThread(std::unique_ptr<VSyncSource> src,
+                         ResyncWithRateLimitCallback resyncWithRateLimitCallback,
+                         InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
+      : EventThread(nullptr, std::move(src), resyncWithRateLimitCallback, interceptVSyncsCallback,
+                    threadName) {}
+
 EventThread::EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback,
                          InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
+      : EventThread(src, nullptr, resyncWithRateLimitCallback, interceptVSyncsCallback,
+                    threadName) {}
+
+EventThread::EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc,
+                         ResyncWithRateLimitCallback resyncWithRateLimitCallback,
+                         InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
       : mVSyncSource(src),
+        mVSyncSourceUnique(std::move(uniqueSrc)),
         mResyncWithRateLimitCallback(resyncWithRateLimitCallback),
         mInterceptVSyncsCallback(interceptVSyncsCallback) {
+    if (src == nullptr) {
+        mVSyncSource = mVSyncSourceUnique.get();
+    }
     for (auto& event : mVSyncEvent) {
         event.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
         event.header.id = 0;
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index a0262b2..127891e 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -108,8 +108,12 @@
     using ResyncWithRateLimitCallback = std::function<void()>;
     using InterceptVSyncsCallback = std::function<void(nsecs_t)>;
 
+    // TODO(b/113612090): Once the Scheduler is complete this constructor will become obsolete.
     EventThread(VSyncSource* src, ResyncWithRateLimitCallback resyncWithRateLimitCallback,
                 InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName);
+    EventThread(std::unique_ptr<VSyncSource> src,
+                ResyncWithRateLimitCallback resyncWithRateLimitCallback,
+                InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName);
     ~EventThread();
 
     sp<BnDisplayEventConnection> createEventConnection() const override;
@@ -134,6 +138,11 @@
 private:
     friend EventThreadTest;
 
+    // TODO(b/113612090): Once the Scheduler is complete this constructor will become obsolete.
+    EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc,
+                ResyncWithRateLimitCallback resyncWithRateLimitCallback,
+                InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName);
+
     void threadMain();
     Vector<sp<EventThread::Connection>> waitForEventLocked(std::unique_lock<std::mutex>* lock,
                                                            DisplayEventReceiver::Event* event)
@@ -146,8 +155,10 @@
     // Implements VSyncSource::Callback
     void onVSyncEvent(nsecs_t timestamp) override;
 
+    // TODO(b/113612090): Once the Scheduler is complete this pointer will become obsolete.
+    VSyncSource* mVSyncSource GUARDED_BY(mMutex) = nullptr;
+    std::unique_ptr<VSyncSource> mVSyncSourceUnique GUARDED_BY(mMutex) = nullptr;
     // constants
-    VSyncSource* const mVSyncSource GUARDED_BY(mMutex) = nullptr;
     const ResyncWithRateLimitCallback mResyncWithRateLimitCallback;
     const InterceptVSyncsCallback mInterceptVSyncsCallback;
 
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index 056d381..58355ae 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -101,6 +101,17 @@
                    this);
 }
 
+void MessageQueue::setEventConnection(const sp<BnDisplayEventConnection>& connection) {
+    if (mEventTube.getFd() >= 0) {
+        mLooper->removeFd(mEventTube.getFd());
+    }
+
+    mEvents = connection;
+    mEvents->stealReceiveChannel(&mEventTube);
+    mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
+                   this);
+}
+
 void MessageQueue::waitMessage() {
     do {
         IPCThreadState::self()->flushCommands();
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h
index 90d1c72..2ec697e 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.h
+++ b/services/surfaceflinger/Scheduler/MessageQueue.h
@@ -85,7 +85,9 @@
     virtual ~MessageQueue();
 
     virtual void init(const sp<SurfaceFlinger>& flinger) = 0;
+    // TODO(akrulec): Remove this function once everything is migrated to Scheduler.
     virtual void setEventThread(EventThread* events) = 0;
+    virtual void setEventConnection(const sp<BnDisplayEventConnection>& connection) = 0;
     virtual void waitMessage() = 0;
     virtual status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime = 0) = 0;
     virtual void invalidate() = 0;
@@ -125,6 +127,7 @@
     ~MessageQueue() override = default;
     void init(const sp<SurfaceFlinger>& flinger) override;
     void setEventThread(android::EventThread* events) override;
+    void setEventConnection(const sp<BnDisplayEventConnection>& connection) override;
 
     void waitMessage() override;
     status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime = 0) override;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
new file mode 100644
index 0000000..bb85f4c
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Scheduler.h"
+
+#include <cinttypes>
+#include <cstdint>
+#include <memory>
+
+#include <gui/ISurfaceComposer.h>
+
+#include "DispSync.h"
+#include "DispSyncSource.h"
+#include "EventThread.h"
+#include "InjectVSyncSource.h"
+
+namespace android {
+
+#define RETURN_VALUE_IF_INVALID(value) \
+    if (handle == nullptr || mConnections.count(handle->id) == 0) return value
+#define RETURN_IF_INVALID() \
+    if (handle == nullptr || mConnections.count(handle->id) == 0) return
+
+std::atomic<int64_t> Scheduler::sNextId = 0;
+
+Scheduler::~Scheduler() = default;
+
+sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
+        const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+        impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
+        impl::EventThread::InterceptVSyncsCallback interceptCallback) {
+    const int64_t id = sNextId++;
+    ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
+
+    std::unique_ptr<EventThread> eventThread =
+            makeEventThread(connectionName, dispSync, phaseOffsetNs, resyncCallback,
+                            interceptCallback);
+    auto connection = std::make_unique<Connection>(new ConnectionHandle(id),
+                                                   eventThread->createEventConnection(),
+                                                   std::move(eventThread));
+    mConnections.insert(std::make_pair(id, std::move(connection)));
+    return mConnections[id]->handle;
+}
+
+std::unique_ptr<EventThread> Scheduler::makeEventThread(
+        const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+        impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
+        impl::EventThread::InterceptVSyncsCallback interceptCallback) {
+    std::unique_ptr<VSyncSource> eventThreadSource =
+            std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, connectionName);
+    return std::make_unique<impl::EventThread>(std::move(eventThreadSource), resyncCallback,
+                                               interceptCallback, connectionName);
+}
+
+sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
+        const sp<Scheduler::ConnectionHandle>& handle) {
+    RETURN_VALUE_IF_INVALID(nullptr);
+    return mConnections[handle->id]->thread->createEventConnection();
+}
+
+EventThread* Scheduler::getEventThread(const sp<Scheduler::ConnectionHandle>& handle) {
+    RETURN_VALUE_IF_INVALID(nullptr);
+    return mConnections[handle->id]->thread.get();
+}
+
+sp<BnDisplayEventConnection> Scheduler::getEventConnection(const sp<ConnectionHandle>& handle) {
+    RETURN_VALUE_IF_INVALID(nullptr);
+    return mConnections[handle->id]->eventConnection;
+}
+
+void Scheduler::hotplugReceived(const sp<Scheduler::ConnectionHandle>& handle,
+                                EventThread::DisplayType displayType, bool connected) {
+    RETURN_IF_INVALID();
+    mConnections[handle->id]->thread->onHotplugReceived(displayType, connected);
+}
+
+void Scheduler::onScreenAcquired(const sp<Scheduler::ConnectionHandle>& handle) {
+    RETURN_IF_INVALID();
+    mConnections[handle->id]->thread->onScreenAcquired();
+}
+
+void Scheduler::onScreenReleased(const sp<Scheduler::ConnectionHandle>& handle) {
+    RETURN_IF_INVALID();
+    mConnections[handle->id]->thread->onScreenReleased();
+}
+
+void Scheduler::dump(const sp<Scheduler::ConnectionHandle>& handle, String8& result) const {
+    RETURN_IF_INVALID();
+    mConnections.at(handle->id)->thread->dump(result);
+}
+
+void Scheduler::setPhaseOffset(const sp<Scheduler::ConnectionHandle>& handle, nsecs_t phaseOffset) {
+    RETURN_IF_INVALID();
+    mConnections[handle->id]->thread->setPhaseOffset(phaseOffset);
+}
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
new file mode 100644
index 0000000..8efbff4
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include <gui/ISurfaceComposer.h>
+
+#include "DispSync.h"
+#include "EventThread.h"
+#include "InjectVSyncSource.h"
+
+namespace android {
+
+class Scheduler {
+public:
+    /* The scheduler handle is a BBinder object passed to the client from which we can extract
+     * an ID for subsequent operations.
+     */
+    class ConnectionHandle : public BBinder {
+    public:
+        ConnectionHandle(int64_t id) : id(id) {}
+        ~ConnectionHandle() = default;
+        const int64_t id;
+    };
+
+    class Connection {
+    public:
+        Connection(sp<ConnectionHandle> handle, sp<BnDisplayEventConnection> eventConnection,
+                   std::unique_ptr<EventThread> eventThread)
+              : handle(handle), eventConnection(eventConnection), thread(std::move(eventThread)) {}
+        ~Connection() = default;
+
+        sp<ConnectionHandle> handle;
+        sp<BnDisplayEventConnection> eventConnection;
+        const std::unique_ptr<EventThread> thread;
+    };
+
+    Scheduler() = default;
+    virtual ~Scheduler();
+
+    /** Creates an EventThread connection. */
+    sp<ConnectionHandle> createConnection(
+            const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+            impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
+            impl::EventThread::InterceptVSyncsCallback interceptCallback);
+    sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle);
+
+    // Getter methods.
+    EventThread* getEventThread(const sp<ConnectionHandle>& handle);
+    sp<BnDisplayEventConnection> getEventConnection(const sp<ConnectionHandle>& handle);
+
+    // Should be called when receiving a hotplug event.
+    void hotplugReceived(const sp<ConnectionHandle>& handle, EventThread::DisplayType displayType,
+                         bool connected);
+    // Should be called after the screen is turned on.
+    void onScreenAcquired(const sp<ConnectionHandle>& handle);
+    // Should be called before the screen is turned off.
+    void onScreenReleased(const sp<ConnectionHandle>& handle);
+    // Should be called when dumpsys command is received.
+    void dump(const sp<ConnectionHandle>& handle, String8& result) const;
+    // Offers ability to modify phase offset in the event thread.
+    void setPhaseOffset(const sp<ConnectionHandle>& handle, nsecs_t phaseOffset);
+
+protected:
+    virtual std::unique_ptr<EventThread> makeEventThread(
+            const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+            impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
+            impl::EventThread::InterceptVSyncsCallback interceptCallback);
+
+private:
+    static std::atomic<int64_t> sNextId;
+    std::unordered_map<int64_t, std::unique_ptr<Connection>> mConnections;
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 888dd38..8c46e8a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -87,6 +87,7 @@
 #include "Scheduler/EventControlThread.h"
 #include "Scheduler/EventThread.h"
 #include "Scheduler/InjectVSyncSource.h"
+#include "Scheduler/Scheduler.h"
 
 #include <cutils/compiler.h>
 
@@ -193,9 +194,9 @@
 int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
 // TODO(courtneygo): Rename hasWideColorDisplay to clarify its actual meaning.
 bool SurfaceFlinger::hasWideColorDisplay;
+int SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientationDefault;
 bool SurfaceFlinger::useColorManagement;
 
-
 std::string getHwcServiceName() {
     char value[PROPERTY_VALUE_MAX] = {};
     property_get("debug.sf.hwc_service_name", value, "default");
@@ -329,19 +330,19 @@
 
     switch (primaryDisplayOrientation) {
         case V1_1::DisplayOrientation::ORIENTATION_90:
-            mPrimaryDisplayOrientation = DisplayState::eOrientation90;
+            SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientation90;
             break;
         case V1_1::DisplayOrientation::ORIENTATION_180:
-            mPrimaryDisplayOrientation = DisplayState::eOrientation180;
+            SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientation180;
             break;
         case V1_1::DisplayOrientation::ORIENTATION_270:
-            mPrimaryDisplayOrientation = DisplayState::eOrientation270;
+            SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientation270;
             break;
         default:
-            mPrimaryDisplayOrientation = DisplayState::eOrientationDefault;
+            SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientationDefault;
             break;
     }
-    ALOGV("Primary Display Orientation is set to %2d.", mPrimaryDisplayOrientation);
+    ALOGV("Primary Display Orientation is set to %2d.", SurfaceFlinger::primaryDisplayOrientation);
 
     // Note: We create a local temporary with the real DispSync implementation
     // type temporarily so we can initialize it with the configured values,
@@ -399,6 +400,9 @@
     property_get("debug.sf.early_gl_app_phase_offset_ns", value, "-1");
     const int earlyGlAppOffsetNs = atoi(value);
 
+    property_get("debug.sf.use_scheduler", value, "0");
+    mUseScheduler = atoi(value);
+
     const VSyncModulator::Offsets earlyOffsets =
             {earlySfOffsetNs != -1 ? earlySfOffsetNs : sfVsyncPhaseOffsetNs,
             earlyAppOffsetNs != -1 ? earlyAppOffsetNs : vsyncPhaseOffsetNs};
@@ -595,32 +599,54 @@
     Mutex::Autolock _l(mStateLock);
 
     // start the EventThread
-    mEventThreadSource =
-            std::make_unique<DispSyncSource>(mPrimaryDispSync.get(),
-                                             SurfaceFlinger::vsyncPhaseOffsetNs, true, "app");
-    mEventThread = std::make_unique<impl::EventThread>(mEventThreadSource.get(),
-                                                       [this] { resyncWithRateLimit(); },
-                                                       impl::EventThread::InterceptVSyncsCallback(),
-                                                       "appEventThread");
-    mSfEventThreadSource =
-            std::make_unique<DispSyncSource>(mPrimaryDispSync.get(),
-                                             SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
+    if (mUseScheduler) {
+        mScheduler = std::make_unique<Scheduler>();
+        mAppConnectionHandle =
+                mScheduler->createConnection("appConnection", mPrimaryDispSync.get(),
+                                             SurfaceFlinger::vsyncPhaseOffsetNs,
+                                             [this] { resyncWithRateLimit(); },
+                                             impl::EventThread::InterceptVSyncsCallback());
+        mSfConnectionHandle =
+                mScheduler->createConnection("sfConnection", mPrimaryDispSync.get(),
+                                             SurfaceFlinger::sfVsyncPhaseOffsetNs,
+                                             [this] { resyncWithRateLimit(); },
+                                             [this](nsecs_t timestamp) {
+                                                 mInterceptor->saveVSyncEvent(timestamp);
+                                             });
 
-    mSFEventThread =
-            std::make_unique<impl::EventThread>(mSfEventThreadSource.get(),
-                                                [this] { resyncWithRateLimit(); },
-                                                [this](nsecs_t timestamp) {
-                                                    mInterceptor->saveVSyncEvent(timestamp);
-                                                },
-                                                "sfEventThread");
-    mEventQueue->setEventThread(mSFEventThread.get());
-    mVsyncModulator.setEventThreads(mSFEventThread.get(), mEventThread.get());
+        mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
+        mVsyncModulator.setEventThreads(mScheduler->getEventThread(mSfConnectionHandle),
+                                        mScheduler->getEventThread(mAppConnectionHandle));
+    } else {
+        mEventThreadSource =
+                std::make_unique<DispSyncSource>(mPrimaryDispSync.get(),
+                                                 SurfaceFlinger::vsyncPhaseOffsetNs, true, "app");
+        mEventThread =
+                std::make_unique<impl::EventThread>(mEventThreadSource.get(),
+                                                    [this] { resyncWithRateLimit(); },
+                                                    impl::EventThread::InterceptVSyncsCallback(),
+                                                    "appEventThread");
+        mSfEventThreadSource =
+                std::make_unique<DispSyncSource>(mPrimaryDispSync.get(),
+                                                 SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
+
+        mSFEventThread =
+                std::make_unique<impl::EventThread>(mSfEventThreadSource.get(),
+                                                    [this] { resyncWithRateLimit(); },
+                                                    [this](nsecs_t timestamp) {
+                                                        mInterceptor->saveVSyncEvent(timestamp);
+                                                    },
+                                                    "sfEventThread");
+        mEventQueue->setEventThread(mSFEventThread.get());
+        mVsyncModulator.setEventThreads(mSFEventThread.get(), mEventThread.get());
+    }
 
     // Get a RenderEngine for the given display / config (can't fail)
     int32_t renderEngineFeature = 0;
-    renderEngineFeature |= (useColorManagement ? RE::RenderEngine::USE_COLOR_MANAGEMENT : 0);
-    getBE().mRenderEngine =
-            RE::impl::RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888, renderEngineFeature);
+    renderEngineFeature |= (useColorManagement ?
+                            renderengine::RenderEngine::USE_COLOR_MANAGEMENT : 0);
+    getBE().mRenderEngine = renderengine::impl::RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888,
+                                                                      renderEngineFeature);
     LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine");
 
     LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
@@ -819,6 +845,12 @@
         float xdpi = hwConfig->getDpiX();
         float ydpi = hwConfig->getDpiY();
 
+        info.w = hwConfig->getWidth();
+        info.h = hwConfig->getHeight();
+        // Default display viewport to display width and height
+        info.viewportW = info.w;
+        info.viewportH = info.h;
+
         if (type == DisplayDevice::DISPLAY_PRIMARY) {
             // The density of the device is provided by a build property
             float density = Density::getBuildDensity() / 160.0f;
@@ -838,6 +870,13 @@
             // TODO: this needs to go away (currently needed only by webkit)
             const auto display = getDefaultDisplayDeviceLocked();
             info.orientation = display ? display->getOrientation() : 0;
+
+            // This is for screenrecord
+            const Rect viewport = display->getViewport();
+            if (viewport.isValid()) {
+                info.viewportW = uint32_t(viewport.getWidth());
+                info.viewportH = uint32_t(viewport.getHeight());
+            }
         } else {
             // TODO: where should this value come from?
             static const int TV_DENSITY = 213;
@@ -845,8 +884,6 @@
             info.orientation = 0;
         }
 
-        info.w = hwConfig->getWidth();
-        info.h = hwConfig->getHeight();
         info.xdpi = xdpi;
         info.ydpi = ydpi;
         info.fps = 1e9 / hwConfig->getVsyncPeriod();
@@ -871,7 +908,7 @@
         info.secure = true;
 
         if (type == DisplayDevice::DISPLAY_PRIMARY &&
-            mPrimaryDisplayOrientation & DisplayState::eOrientationSwapMask) {
+            primaryDisplayOrientation & DisplayState::eOrientationSwapMask) {
             std::swap(info.w, info.h);
         }
 
@@ -893,21 +930,6 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) {
-    if (outViewport == nullptr || display.get() == nullptr) {
-        return BAD_VALUE;
-    }
-
-    sp<const DisplayDevice> device(getDisplayDevice(display));
-    if (device == nullptr) {
-        return BAD_VALUE;
-    }
-
-    *outViewport = device->getViewport();
-
-    return NO_ERROR;
-}
-
 int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) {
     const auto display = getDisplayDevice(displayToken);
     if (!display) {
@@ -1086,6 +1108,8 @@
             return;
         }
 
+        // TODO(akrulec): Part of the Injector should be refactored, so that it
+        // can be passed to Scheduler.
         if (enable) {
             ALOGV("VSync Injections enabled");
             if (mVSyncInjector.get() == nullptr) {
@@ -1144,10 +1168,18 @@
 
 sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
         ISurfaceComposer::VsyncSource vsyncSource) {
-    if (vsyncSource == eVsyncSourceSurfaceFlinger) {
-        return mSFEventThread->createEventConnection();
+    if (mUseScheduler) {
+        if (vsyncSource == eVsyncSourceSurfaceFlinger) {
+            return mScheduler->createDisplayEventConnection(mSfConnectionHandle);
+        } else {
+            return mScheduler->createDisplayEventConnection(mAppConnectionHandle);
+        }
     } else {
-        return mEventThread->createEventConnection();
+        if (vsyncSource == eVsyncSourceSurfaceFlinger) {
+            return mSFEventThread->createEventConnection();
+        } else {
+            return mEventThread->createEventConnection();
+        }
     }
 }
 
@@ -2181,7 +2213,16 @@
     switch (compositionInfo.compositionType)
     {
         case HWC2::Composition::Invalid:
+            break;
+
         case HWC2::Composition::Client:
+            if (compositionInfo.hwc.hwcLayer) {
+                auto error = (compositionInfo.hwc.hwcLayer)->
+                    setCompositionType(compositionInfo.compositionType);
+                ALOGE_IF(error != HWC2::Error::None,
+                        "[SF] Failed to set composition type: %s (%d)",
+                            to_string(error).c_str(), static_cast<int32_t>(error));
+            }
             break;
 
         case HWC2::Composition::Sideband:
@@ -2420,7 +2461,7 @@
     /*
      * Create our display's surface
      */
-    std::unique_ptr<RE::Surface> renderSurface = getRenderEngine().createSurface();
+    std::unique_ptr<renderengine::Surface> renderSurface = getRenderEngine().createSurface();
     renderSurface->setCritical(state.type == DisplayDevice::DISPLAY_PRIMARY);
     renderSurface->setAsync(state.isVirtual());
     renderSurface->setNativeWindow(nativeWindow.get());
@@ -2438,14 +2479,18 @@
         nativeWindow->setSwapInterval(nativeWindow.get(), 0);
     }
 
+    const int displayInstallOrientation = state.type == DisplayDevice::DISPLAY_PRIMARY ?
+        primaryDisplayOrientation : DisplayState::eOrientationDefault;
+
     // virtual displays are always considered enabled
     auto initialPowerMode = state.isVirtual() ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
 
     sp<DisplayDevice> display =
             new DisplayDevice(this, state.type, displayId, state.isSecure, displayToken,
                               nativeWindow, dispSurface, std::move(renderSurface), displayWidth,
-                              displayHeight, hasWideColorGamut, hdrCapabilities,
-                              supportedPerFrameMetadata, hwcColorModes, initialPowerMode);
+                              displayHeight, displayInstallOrientation, hasWideColorGamut,
+                              hdrCapabilities, supportedPerFrameMetadata, hwcColorModes,
+                              initialPowerMode);
 
     if (maxFrameBufferAcquiredBuffers >= 3) {
         nativeWindowSurface->preallocateBuffers();
@@ -2498,9 +2543,19 @@
                     display->disconnect(getHwComposer());
                 }
                 if (draw[i].type == DisplayDevice::DISPLAY_PRIMARY) {
-                    mEventThread->onHotplugReceived(EventThread::DisplayType::Primary, false);
+                    if (mUseScheduler) {
+                        mScheduler->hotplugReceived(mAppConnectionHandle,
+                                                    EventThread::DisplayType::Primary, false);
+                    } else {
+                        mEventThread->onHotplugReceived(EventThread::DisplayType::Primary, false);
+                    }
                 } else if (draw[i].type == DisplayDevice::DISPLAY_EXTERNAL) {
-                    mEventThread->onHotplugReceived(EventThread::DisplayType::External, false);
+                    if (mUseScheduler) {
+                        mScheduler->hotplugReceived(mAppConnectionHandle,
+                                                    EventThread::DisplayType::External, false);
+                    } else {
+                        mEventThread->onHotplugReceived(EventThread::DisplayType::External, false);
+                    }
                 }
                 mDisplays.erase(draw.keyAt(i));
             } else {
@@ -2603,11 +2658,23 @@
                                                                     dispSurface, producer));
                     if (!state.isVirtual()) {
                         if (state.type == DisplayDevice::DISPLAY_PRIMARY) {
-                            mEventThread->onHotplugReceived(EventThread::DisplayType::Primary,
+                            if (mUseScheduler) {
+                                mScheduler->hotplugReceived(mAppConnectionHandle,
+                                                            EventThread::DisplayType::Primary,
                                                             true);
+                            } else {
+                                mEventThread->onHotplugReceived(EventThread::DisplayType::Primary,
+                                                                true);
+                            }
                         } else if (state.type == DisplayDevice::DISPLAY_EXTERNAL) {
-                            mEventThread->onHotplugReceived(EventThread::DisplayType::External,
+                            if (mUseScheduler) {
+                                mScheduler->hotplugReceived(mAppConnectionHandle,
+                                                            EventThread::DisplayType::External,
                                                             true);
+                            } else {
+                                mEventThread->onHotplugReceived(EventThread::DisplayType::External,
+                                                                true);
+                            }
                         }
                     }
                 }
@@ -3569,10 +3636,6 @@
         if (layer->setCrop_legacy(s.crop_legacy, !geometryAppliesWithResize))
             flags |= eTraversalNeeded;
     }
-    if (what & layer_state_t::eFinalCropChanged_legacy) {
-        if (layer->setFinalCrop_legacy(s.finalCrop_legacy, !geometryAppliesWithResize))
-            flags |= eTraversalNeeded;
-    }
     if (what & layer_state_t::eLayerStackChanged) {
         ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
         // We only allow setting layer stacks for top level layers,
@@ -3717,6 +3780,11 @@
                     uniqueName, w, h, flags,
                     handle, &layer);
             break;
+        case ISurfaceComposerClient::eFXSurfaceContainer:
+            result = createContainerLayer(client,
+                    uniqueName, w, h, flags,
+                    handle, &layer);
+            break;
         default:
             result = BAD_VALUE;
             break;
@@ -3820,6 +3888,16 @@
     return NO_ERROR;
 }
 
+status_t SurfaceFlinger::createContainerLayer(const sp<Client>& client,
+        const String8& name, uint32_t w, uint32_t h, uint32_t flags,
+        sp<IBinder>* handle, sp<Layer>* outLayer)
+{
+    *outLayer = new ContainerLayer(this, client, name, w, h, flags);
+    *handle = (*outLayer)->getHandle();
+    return NO_ERROR;
+}
+
+
 status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
 {
     // called by a client when it wants to remove a Layer
@@ -3921,7 +3999,11 @@
         getHwComposer().setPowerMode(type, mode);
         if (display->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) {
             // FIXME: eventthread only knows about the main display right now
-            mEventThread->onScreenAcquired();
+            if (mUseScheduler) {
+                mScheduler->onScreenAcquired(mAppConnectionHandle);
+            } else {
+                mEventThread->onScreenAcquired();
+            }
             resyncToHardwareVsync(true);
         }
 
@@ -3945,7 +4027,11 @@
             disableHardwareVsync(true); // also cancels any in-progress resync
 
             // FIXME: eventthread only knows about the main display right now
-            mEventThread->onScreenReleased();
+            if (mUseScheduler) {
+                mScheduler->onScreenReleased(mAppConnectionHandle);
+            } else {
+                mEventThread->onScreenReleased();
+            }
         }
 
         getHwComposer().setPowerMode(type, mode);
@@ -3957,7 +4043,11 @@
         getHwComposer().setPowerMode(type, mode);
         if (display->isPrimary() && currentMode == HWC_POWER_MODE_DOZE_SUSPEND) {
             // FIXME: eventthread only knows about the main display right now
-            mEventThread->onScreenAcquired();
+            if (mUseScheduler) {
+                mScheduler->onScreenAcquired(mAppConnectionHandle);
+            } else {
+                mEventThread->onScreenAcquired();
+            }
             resyncToHardwareVsync(true);
         }
     } else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) {
@@ -3965,7 +4055,11 @@
         if (display->isPrimary()) {
             disableHardwareVsync(true); // also cancels any in-progress resync
             // FIXME: eventthread only knows about the main display right now
-            mEventThread->onScreenReleased();
+            if (mUseScheduler) {
+                mScheduler->onScreenReleased(mAppConnectionHandle);
+            } else {
+                mEventThread->onScreenReleased();
+            }
         }
         getHwComposer().setPowerMode(type, mode);
     } else {
@@ -4563,10 +4657,15 @@
     result.appendFormat("  transaction time: %f us\n",
             inTransactionDuration/1000.0);
 
+    result.appendFormat("  use Scheduler: %s\n", mUseScheduler ? "true" : "false");
     /*
      * VSYNC state
      */
-    mEventThread->dump(result);
+    if (mUseScheduler) {
+        mScheduler->dump(mAppConnectionHandle, result);
+    } else {
+        mEventThread->dump(result);
+    }
     result.append("\n");
 
     /*
@@ -4714,7 +4813,6 @@
         case GET_DISPLAY_COLOR_MODES:
         case GET_DISPLAY_CONFIGS:
         case GET_DISPLAY_STATS:
-        case GET_DISPLAY_VIEWPORT:
         case GET_SUPPORTED_FRAME_TIMESTAMPS:
         // Calling setTransactionState is safe, because you need to have been
         // granted a reference to Client* and Handle* to do anything with it.
@@ -4903,12 +5001,20 @@
             }
             case 1018: { // Modify Choreographer's phase offset
                 n = data.readInt32();
-                mEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
+                if (mUseScheduler) {
+                    mScheduler->setPhaseOffset(mAppConnectionHandle, static_cast<nsecs_t>(n));
+                } else {
+                    mEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
+                }
                 return NO_ERROR;
             }
             case 1019: { // Modify SurfaceFlinger's phase offset
                 n = data.readInt32();
-                mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
+                if (mUseScheduler) {
+                    mScheduler->setPhaseOffset(mSfConnectionHandle, static_cast<nsecs_t>(n));
+                } else {
+                    mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
+                }
                 return NO_ERROR;
             }
             case 1020: { // Layer updates interceptor
@@ -5082,37 +5188,15 @@
         display = getDisplayDeviceLocked(displayToken);
         if (!display) return BAD_VALUE;
 
-        const Rect& dispScissor = display->getScissor();
-        if (!dispScissor.isEmpty()) {
-            sourceCrop.set(dispScissor);
-            // adb shell screencap will default reqWidth and reqHeight to zeros.
-            if (reqWidth == 0 || reqHeight == 0) {
-                reqWidth = uint32_t(display->getViewport().width());
-                reqHeight = uint32_t(display->getViewport().height());
-            }
-        }
+        // ignore sourceCrop (i.e., use the projected logical display
+        // viewport) until the framework is fixed
+        sourceCrop.clear();
 
-        // get screen geometry
-        uint32_t width = display->getWidth();
-        uint32_t height = display->getHeight();
-
-        if (renderAreaRotation & ui::Transform::ROT_90) {
-            std::swap(width, height);
-        }
-
-        if (mPrimaryDisplayOrientation & DisplayState::eOrientationSwapMask) {
-            std::swap(width, height);
-        }
-
-        if ((reqWidth > width) || (reqHeight > height)) {
-            ALOGE("size mismatch (%d, %d) > (%d, %d)", reqWidth, reqHeight, width, height);
-        } else {
-            if (reqWidth == 0) {
-                reqWidth = width;
-            }
-            if (reqHeight == 0) {
-                reqHeight = height;
-            }
+        // set the requested width/height to the logical display viewport size
+        // by default
+        if (reqWidth == 0 || reqHeight == 0) {
+            reqWidth = uint32_t(display->getViewport().width());
+            reqHeight = uint32_t(display->getViewport().height());
         }
     }
 
@@ -5135,6 +5219,7 @@
               : RenderArea(reqWidth, reqHeight, CaptureFill::CLEAR),
                 mLayer(layer),
                 mCrop(crop),
+                mNeedsFiltering(false),
                 mFlinger(flinger),
                 mChildrenOnly(childrenOnly) {}
         const ui::Transform& getTransform() const override { return mTransform; }
@@ -5147,7 +5232,7 @@
         }
         int getWidth() const override { return mLayer->getActiveWidth(mLayer->getDrawingState()); }
         bool isSecure() const override { return false; }
-        bool needsFiltering() const override { return false; }
+        bool needsFiltering() const override { return mNeedsFiltering; }
         Rect getSourceCrop() const override {
             if (mCrop.isEmpty()) {
                 return getBounds();
@@ -5168,6 +5253,11 @@
         };
 
         void render(std::function<void()> drawLayers) override {
+            const Rect sourceCrop = getSourceCrop();
+            // no need to check rotation because there is none
+            mNeedsFiltering = sourceCrop.width() != getReqWidth() ||
+                sourceCrop.height() != getReqHeight();
+
             if (!mChildrenOnly) {
                 mTransform = mLayer->getTransform().inverse();
                 drawLayers();
@@ -5190,6 +5280,7 @@
         // layer which has no properties set and which does not draw.
         sp<ContainerLayer> screenshotParentLayer;
         ui::Transform mTransform;
+        bool mNeedsFiltering;
 
         SurfaceFlinger* mFlinger;
         const bool mChildrenOnly;
@@ -5321,64 +5412,16 @@
 }
 
 void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea,
-                                            TraverseLayersFunction traverseLayers, bool yswap,
+                                            TraverseLayersFunction traverseLayers,
                                             bool useIdentityTransform) {
     ATRACE_CALL();
 
     auto& engine(getRenderEngine());
 
-    // get screen geometry
-    const auto raWidth = renderArea.getWidth();
-    const auto raHeight = renderArea.getHeight();
-
     const auto reqWidth = renderArea.getReqWidth();
     const auto reqHeight = renderArea.getReqHeight();
-    Rect sourceCrop = renderArea.getSourceCrop();
-
-    bool filtering = false;
-    if (mPrimaryDisplayOrientation & DisplayState::eOrientationSwapMask) {
-        filtering = static_cast<int32_t>(reqWidth) != raHeight ||
-                static_cast<int32_t>(reqHeight) != raWidth;
-    } else {
-        filtering = static_cast<int32_t>(reqWidth) != raWidth ||
-                static_cast<int32_t>(reqHeight) != raHeight;
-    }
-
-    // if a default or invalid sourceCrop is passed in, set reasonable values
-    if (sourceCrop.width() == 0 || sourceCrop.height() == 0 || !sourceCrop.isValid()) {
-        sourceCrop.setLeftTop(Point(0, 0));
-        sourceCrop.setRightBottom(Point(raWidth, raHeight));
-    } else if (mPrimaryDisplayOrientation != DisplayState::eOrientationDefault) {
-        ui::Transform tr;
-        uint32_t flags = 0x00;
-        switch (mPrimaryDisplayOrientation) {
-            case DisplayState::eOrientation90:
-                flags = ui::Transform::ROT_90;
-                break;
-            case DisplayState::eOrientation180:
-                flags = ui::Transform::ROT_180;
-                break;
-            case DisplayState::eOrientation270:
-                flags = ui::Transform::ROT_270;
-                break;
-        }
-        tr.set(flags, raWidth, raHeight);
-        sourceCrop = tr.transform(sourceCrop);
-    }
-
-    // ensure that sourceCrop is inside screen
-    if (sourceCrop.left < 0) {
-        ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left);
-    }
-    if (sourceCrop.right > raWidth) {
-        ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, raWidth);
-    }
-    if (sourceCrop.top < 0) {
-        ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top);
-    }
-    if (sourceCrop.bottom > raHeight) {
-        ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, raHeight);
-    }
+    const auto sourceCrop = renderArea.getSourceCrop();
+    const auto rotation = renderArea.getRotationFlags();
 
     // assume ColorMode::SRGB / RenderIntent::COLORIMETRIC
     engine.setOutputDataSpace(Dataspace::SRGB);
@@ -5387,40 +5430,8 @@
     // make sure to clear all GL error flags
     engine.checkErrors();
 
-    ui::Transform::orientation_flags rotation = renderArea.getRotationFlags();
-    if (mPrimaryDisplayOrientation != DisplayState::eOrientationDefault) {
-        // convert hw orientation into flag presentation
-        // here inverse transform needed
-        uint8_t hw_rot_90  = 0x00;
-        uint8_t hw_flip_hv = 0x00;
-        switch (mPrimaryDisplayOrientation) {
-            case DisplayState::eOrientation90:
-                hw_rot_90 = ui::Transform::ROT_90;
-                hw_flip_hv = ui::Transform::ROT_180;
-                break;
-            case DisplayState::eOrientation180:
-                hw_flip_hv = ui::Transform::ROT_180;
-                break;
-            case DisplayState::eOrientation270:
-                hw_rot_90  = ui::Transform::ROT_90;
-                break;
-        }
-
-        // transform flags operation
-        // 1) flip H V if both have ROT_90 flag
-        // 2) XOR these flags
-        uint8_t rotation_rot_90  = rotation & ui::Transform::ROT_90;
-        uint8_t rotation_flip_hv = rotation & ui::Transform::ROT_180;
-        if (rotation_rot_90 & hw_rot_90) {
-            rotation_flip_hv = (~rotation_flip_hv) & ui::Transform::ROT_180;
-        }
-        rotation = static_cast<ui::Transform::orientation_flags>
-                   ((rotation_rot_90 ^ hw_rot_90) | (rotation_flip_hv ^ hw_flip_hv));
-    }
-
     // set-up our viewport
-    engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, raHeight, yswap,
-                                    rotation);
+    engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, rotation);
     engine.disableTexturing();
 
     const float alpha = RenderArea::getCaptureFillValue(renderArea.getCaptureFill());
@@ -5428,9 +5439,7 @@
     engine.clearWithColor(0, 0, 0, alpha);
 
     traverseLayers([&](Layer* layer) {
-        if (filtering) layer->setFiltering(true);
         layer->draw(renderArea, useIdentityTransform);
-        if (filtering) layer->setFiltering(false);
     });
 }
 
@@ -5458,7 +5467,7 @@
 
     // this binds the given EGLImage as a framebuffer for the
     // duration of this scope.
-    RE::BindNativeBufferAsFramebuffer bufferBond(getRenderEngine(), buffer);
+    renderengine::BindNativeBufferAsFramebuffer bufferBond(getRenderEngine(), buffer);
     if (bufferBond.getStatus() != NO_ERROR) {
         ALOGE("got ANWB binding error while taking screenshot");
         return INVALID_OPERATION;
@@ -5468,7 +5477,7 @@
     // via an FBO, which means we didn't have to create
     // an EGLSurface and therefore we're not
     // dependent on the context's EGLConfig.
-    renderScreenImplLocked(renderArea, traverseLayers, true, useIdentityTransform);
+    renderScreenImplLocked(renderArea, traverseLayers, useIdentityTransform);
 
     if (DEBUG_SCREENSHOTS) {
         getRenderEngine().finish();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3dbceae..3e76904 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -69,6 +69,7 @@
 #include "Scheduler/DispSync.h"
 #include "Scheduler/EventThread.h"
 #include "Scheduler/MessageQueue.h"
+#include "Scheduler/Scheduler.h"
 #include "Scheduler/VSyncModulator.h"
 #include "TimeStats/TimeStats.h"
 
@@ -106,7 +107,7 @@
 class EventThread;
 } // namespace impl
 
-namespace RE {
+namespace renderengine {
 class RenderEngine;
 }
 
@@ -175,7 +176,7 @@
     const std::string mHwcServiceName; // "default" for real use, something else for testing.
 
     // constant members (no synchronization needed for access)
-    std::unique_ptr<RE::RenderEngine> mRenderEngine;
+    std::unique_ptr<renderengine::RenderEngine> mRenderEngine;
     EGLContext mEGLContext;
     EGLDisplay mEGLDisplay;
 
@@ -288,6 +289,8 @@
     // found on devices with wide color gamut (e.g. Display-P3) display.
     static bool hasWideColorDisplay;
 
+    static int primaryDisplayOrientation;
+
     // Indicate if device wants color management on its display.
     static bool useColorManagement;
 
@@ -345,13 +348,11 @@
     // TODO: this should be made accessible only to HWComposer
     const Vector< sp<Layer> >& getLayerSortedByZForHwcDisplay(int id);
 
-    RE::RenderEngine& getRenderEngine() const { return *getBE().mRenderEngine; }
+    renderengine::RenderEngine& getRenderEngine() const { return *getBE().mRenderEngine; }
 
     bool authenticateSurfaceTextureLocked(
         const sp<IGraphicBufferProducer>& bufferProducer) const;
 
-    int getPrimaryDisplayOrientation() const { return mPrimaryDisplayOrientation; }
-
 private:
     friend class Client;
     friend class DisplayEventConnection;
@@ -435,7 +436,6 @@
     virtual status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
                                    const Rect& sourceCrop, float frameScale, bool childrenOnly);
     virtual status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats);
-    virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport);
     virtual status_t getDisplayConfigs(const sp<IBinder>& displayToken,
                                        Vector<DisplayInfo>* configs);
     virtual int getActiveConfig(const sp<IBinder>& displayToken);
@@ -548,6 +548,10 @@
             uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle,
             sp<Layer>* outLayer);
 
+    status_t createContainerLayer(const sp<Client>& client, const String8& name,
+            uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle,
+            sp<Layer>* outLayer);
+
     String8 getUniqueLayerName(const String8& name);
 
     // called in response to the window-manager calling
@@ -577,7 +581,7 @@
     void startBootAnim();
 
     void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
-                                bool yswap, bool useIdentityTransform);
+                                bool useIdentityTransform);
     status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers,
                                  sp<GraphicBuffer>* outBuffer,
                                  bool useIdentityTransform);
@@ -877,7 +881,6 @@
     mutable std::unique_ptr<MessageQueue> mEventQueue{std::make_unique<impl::MessageQueue>()};
     FrameTracker mAnimFrameTracker;
     std::unique_ptr<DispSync> mPrimaryDispSync;
-    int mPrimaryDisplayOrientation = DisplayState::eOrientationDefault;
 
     // protected by mDestroyedLayerLock;
     mutable Mutex mDestroyedLayerLock;
@@ -933,6 +936,11 @@
     CreateNativeWindowSurfaceFunction mCreateNativeWindowSurface;
 
     SurfaceFlingerBE mBE;
+
+    bool mUseScheduler = false;
+    std::unique_ptr<Scheduler> mScheduler;
+    sp<Scheduler::ConnectionHandle> mAppConnectionHandle;
+    sp<Scheduler::ConnectionHandle> mSfConnectionHandle;
 };
 }; // namespace android
 
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index f504c13..0b4c6fc 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -113,7 +113,6 @@
                                   layer->mCurrentState.barrierLayer_legacy.promote(),
                                   layer->mCurrentState.frameNumber_legacy);
     }
-    addFinalCropLocked(transaction, layerId, layer->mCurrentState.finalCrop_legacy);
     addOverrideScalingModeLocked(transaction, layerId, layer->getEffectiveScalingMode());
     addFlagsLocked(transaction, layerId, layer->mCurrentState.flags);
 }
@@ -289,15 +288,6 @@
     setProtoRectLocked(protoRect, rect);
 }
 
-void SurfaceInterceptor::addFinalCropLocked(Transaction* transaction, int32_t layerId,
-        const Rect& rect)
-{
-    SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
-    FinalCropChange* finalCropChange(change->mutable_final_crop());
-    Rectangle* protoRect(finalCropChange->mutable_rectangle());
-    setProtoRectLocked(protoRect, rect);
-}
-
 void SurfaceInterceptor::addDeferTransactionLocked(Transaction* transaction, int32_t layerId,
         const sp<const Layer>& layer, uint64_t frameNumber)
 {
@@ -374,9 +364,6 @@
         }
         addDeferTransactionLocked(transaction, layerId, otherLayer, state.frameNumber_legacy);
     }
-    if (state.what & layer_state_t::eFinalCropChanged_legacy) {
-        addFinalCropLocked(transaction, layerId, state.finalCrop_legacy);
-    }
     if (state.what & layer_state_t::eOverrideScalingModeChanged) {
         addOverrideScalingModeLocked(transaction, layerId, state.overrideScalingMode);
     }
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 218a1d2..394b99b 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -146,7 +146,6 @@
     void addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect);
     void addDeferTransactionLocked(Transaction* transaction, int32_t layerId,
             const sp<const Layer>& layer, uint64_t frameNumber);
-    void addFinalCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect);
     void addOverrideScalingModeLocked(Transaction* transaction, int32_t layerId,
             int32_t overrideScalingMode);
     void addSurfaceChangesLocked(Transaction* transaction, const layer_state_t& state);
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
index e1c0fd3..a5bf9c1 100644
--- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -101,7 +101,6 @@
                                 layerProto.requested_position().y()};
     layer->size = {layerProto.size().w(), layerProto.size().h()};
     layer->crop = generateRect(layerProto.crop());
-    layer->finalCrop = generateRect(layerProto.final_crop());
     layer->isOpaque = layerProto.is_opaque();
     layer->invalidate = layerProto.invalidate();
     layer->dataspace = layerProto.dataspace();
@@ -299,8 +298,7 @@
                   z, static_cast<double>(position.x), static_cast<double>(position.y), size.x,
                   size.y);
 
-    StringAppendF(&result, "crop=%s, finalCrop=%s, ", crop.to_string().c_str(),
-                  finalCrop.to_string().c_str());
+    StringAppendF(&result, "crop=%s, ", crop.to_string().c_str());
     StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate);
     StringAppendF(&result, "dataspace=%s, ", dataspace.c_str());
     StringAppendF(&result, "defaultPixelFormat=%s, ", pixelFormat.c_str());
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
index 360e599..b1610cf 100644
--- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -92,7 +92,6 @@
         float2 requestedPosition;
         int2 size;
         LayerProtoParser::Rect crop;
-        LayerProtoParser::Rect finalCrop;
         bool isOpaque;
         bool invalidate;
         std::string dataspace;
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index 7f882da..2a09634 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -41,7 +41,7 @@
   // The layer's crop in it's own bounds.
   optional RectProto crop = 14;
   // The layer's crop in it's parent's bounds.
-  optional RectProto final_crop = 15;
+  optional RectProto final_crop = 15 [deprecated=true];
   optional bool is_opaque = 16;
   optional bool invalidate = 17;
   optional string dataspace = 18;
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index 1319e12..34d0fd7 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
 {
         "presubmit": {
-            "filter": "CredentialsTest.*:LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*:SurfaceInterceptorTest.*:-CropLatchingTest.FinalCropLatchingBufferOldSize"
+            "filter": "CredentialsTest.*:LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*:SurfaceInterceptorTest.*"
         }
 }
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index 8ac2c87..740d2fa 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -167,7 +167,6 @@
     bool alphaUpdateFound(const SurfaceChange& change, bool foundAlpha);
     bool layerUpdateFound(const SurfaceChange& change, bool foundLayer);
     bool cropUpdateFound(const SurfaceChange& change, bool foundCrop);
-    bool finalCropUpdateFound(const SurfaceChange& change, bool foundFinalCrop);
     bool matrixUpdateFound(const SurfaceChange& change, bool foundMatrix);
     bool scalingModeUpdateFound(const SurfaceChange& change, bool foundScalingMode);
     bool transparentRegionHintUpdateFound(const SurfaceChange& change, bool foundTransparentRegion);
@@ -199,7 +198,6 @@
     void alphaUpdate(Transaction&);
     void layerUpdate(Transaction&);
     void cropUpdate(Transaction&);
-    void finalCropUpdate(Transaction&);
     void matrixUpdate(Transaction&);
     void overrideScalingModeUpdate(Transaction&);
     void transparentRegionHintUpdate(Transaction&);
@@ -323,10 +321,6 @@
     t.setCrop_legacy(mBGSurfaceControl, CROP_UPDATE);
 }
 
-void SurfaceInterceptorTest::finalCropUpdate(Transaction& t) {
-    t.setFinalCrop_legacy(mBGSurfaceControl, CROP_UPDATE);
-}
-
 void SurfaceInterceptorTest::matrixUpdate(Transaction& t) {
     t.setMatrix(mBGSurfaceControl, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2);
 }
@@ -377,7 +371,6 @@
     runInTransaction(&SurfaceInterceptorTest::alphaUpdate);
     runInTransaction(&SurfaceInterceptorTest::layerUpdate);
     runInTransaction(&SurfaceInterceptorTest::cropUpdate);
-    runInTransaction(&SurfaceInterceptorTest::finalCropUpdate);
     runInTransaction(&SurfaceInterceptorTest::matrixUpdate);
     runInTransaction(&SurfaceInterceptorTest::overrideScalingModeUpdate);
     runInTransaction(&SurfaceInterceptorTest::transparentRegionHintUpdate);
@@ -460,20 +453,6 @@
     return foundCrop;
 }
 
-bool SurfaceInterceptorTest::finalCropUpdateFound(const SurfaceChange& change,
-        bool foundFinalCrop) {
-    bool hasLeft(change.final_crop().rectangle().left() == CROP_UPDATE.left);
-    bool hasTop(change.final_crop().rectangle().top() == CROP_UPDATE.top);
-    bool hasRight(change.final_crop().rectangle().right() == CROP_UPDATE.right);
-    bool hasBottom(change.final_crop().rectangle().bottom() == CROP_UPDATE.bottom);
-    if (hasLeft && hasRight && hasTop && hasBottom && !foundFinalCrop) {
-        foundFinalCrop = true;
-    } else if (hasLeft && hasRight && hasTop && hasBottom && foundFinalCrop) {
-        [] () { FAIL(); }();
-    }
-    return foundFinalCrop;
-}
-
 bool SurfaceInterceptorTest::matrixUpdateFound(const SurfaceChange& change, bool foundMatrix) {
     bool hasSx((float)change.matrix().dsdx() == (float)M_SQRT1_2);
     bool hasTx((float)change.matrix().dtdx() == (float)M_SQRT1_2);
@@ -593,9 +572,6 @@
                         case SurfaceChange::SurfaceChangeCase::kCrop:
                             foundUpdate = cropUpdateFound(change, foundUpdate);
                             break;
-                        case SurfaceChange::SurfaceChangeCase::kFinalCrop:
-                            foundUpdate = finalCropUpdateFound(change, foundUpdate);
-                            break;
                         case SurfaceChange::SurfaceChangeCase::kMatrix:
                             foundUpdate = matrixUpdateFound(change, foundUpdate);
                             break;
@@ -636,7 +612,6 @@
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kAlpha));
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kLayer));
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kCrop));
-    ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kFinalCrop));
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kMatrix));
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kOverrideScalingMode));
     ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kTransparentRegionHint));
@@ -755,11 +730,6 @@
     captureTest(&SurfaceInterceptorTest::cropUpdate, SurfaceChange::SurfaceChangeCase::kCrop);
 }
 
-TEST_F(SurfaceInterceptorTest, InterceptFinalCropUpdateWorks) {
-    captureTest(&SurfaceInterceptorTest::finalCropUpdate,
-            SurfaceChange::SurfaceChangeCase::kFinalCrop);
-}
-
 TEST_F(SurfaceInterceptorTest, InterceptMatrixUpdateWorks) {
     captureTest(&SurfaceInterceptorTest::matrixUpdate, SurfaceChange::SurfaceChangeCase::kMatrix);
 }
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 4ab4fec..ed1529b 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -1759,168 +1759,6 @@
     }
 }
 
-TEST_F(LayerTransactionTest, SetFinalCropBasic_BufferQueue) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-    const Rect crop(8, 8, 24, 24);
-
-    // same as in SetCropBasic
-    Transaction().setFinalCrop_legacy(layer, crop).apply();
-    auto shot = screenshot();
-    shot->expectColor(crop, Color::RED);
-    shot->expectBorder(crop, Color::BLACK);
-}
-
-TEST_F(LayerTransactionTest, SetFinalCropEmpty_BufferQueue) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
-    // same as in SetCropEmpty
-    {
-        SCOPED_TRACE("empty rect");
-        Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 8, 8)).apply();
-        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-    }
-
-    {
-        SCOPED_TRACE("negative rect");
-        Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 0, 0)).apply();
-        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-    }
-}
-
-TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds_BufferQueue) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
-    // same as in SetCropOutOfBounds
-    Transaction().setFinalCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply();
-    auto shot = screenshot();
-    shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
-    shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
-}
-
-TEST_F(LayerTransactionTest, SetFinalCropWithTranslation_BufferQueue) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
-    // final crop is applied post-translation
-    Transaction().setPosition(layer, 16, 16).setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).apply();
-    auto shot = screenshot();
-    shot->expectColor(Rect(16, 16, 24, 24), Color::RED);
-    shot->expectBorder(Rect(16, 16, 24, 24), Color::BLACK);
-}
-
-TEST_F(LayerTransactionTest, SetFinalCropWithScale_BufferQueue) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
-    // final crop is not affected by matrix
-    Transaction()
-            .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f)
-            .setFinalCrop_legacy(layer, Rect(8, 8, 24, 24))
-            .apply();
-    auto shot = screenshot();
-    shot->expectColor(Rect(8, 8, 24, 24), Color::RED);
-    shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK);
-}
-
-TEST_F(LayerTransactionTest, SetFinalCropWithResize_BufferQueue) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
-    // same as in SetCropWithResize
-    Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply();
-    {
-        SCOPED_TRACE("resize pending");
-        auto shot = screenshot();
-        shot->expectColor(Rect(8, 8, 24, 24), Color::RED);
-        shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK);
-    }
-
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16));
-    {
-        SCOPED_TRACE("resize applied");
-        auto shot = screenshot();
-        shot->expectColor(Rect(8, 8, 16, 16), Color::RED);
-        shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK);
-    }
-}
-
-TEST_F(LayerTransactionTest, SetFinalCropWithNextResize_BufferQueue) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
-    // same as in SetCropWithNextResize
-    Transaction()
-            .setFinalCrop_legacy(layer, Rect(8, 8, 24, 24))
-            .setGeometryAppliesWithResize(layer)
-            .apply();
-    {
-        SCOPED_TRACE("waiting for next resize");
-        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-    }
-
-    Transaction().setFinalCrop_legacy(layer, Rect(4, 4, 12, 12)).apply();
-    {
-        SCOPED_TRACE("pending final crop modified");
-        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-    }
-
-    Transaction().setSize(layer, 16, 16).apply();
-    {
-        SCOPED_TRACE("resize pending");
-        screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
-    }
-
-    // finally resize
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16));
-    {
-        SCOPED_TRACE("new final crop applied");
-        auto shot = screenshot();
-        shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
-        shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
-    }
-}
-
-TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow_BufferQueue) {
-    sp<SurfaceControl> layer;
-    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
-
-    // same as in SetCropWithNextResizeScaleToWindow
-    Transaction()
-            .setFinalCrop_legacy(layer, Rect(4, 4, 12, 12))
-            .setSize(layer, 16, 16)
-            .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
-            .setGeometryAppliesWithResize(layer)
-            .apply();
-    {
-        SCOPED_TRACE("new final crop pending");
-        auto shot = screenshot();
-        shot->expectColor(Rect(0, 0, 16, 16), Color::RED);
-        shot->expectBorder(Rect(0, 0, 16, 16), Color::BLACK);
-    }
-
-    // XXX final crop is never latched without other geometry change (b/69315677)
-    Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply();
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16));
-    Transaction().setPosition(layer, 0, 0).apply();
-    {
-        SCOPED_TRACE("new final crop applied");
-        auto shot = screenshot();
-        shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
-        shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
-    }
-}
-
 TEST_F(LayerTransactionTest, SetBufferBasic_BufferState) {
     sp<SurfaceControl> layer;
     ASSERT_NO_FATAL_FAILURE(
@@ -2346,7 +2184,6 @@
             t.setSize(mFGSurfaceControl, 64, 64);
             t.setPosition(mFGSurfaceControl, 64, 64);
             t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 64, 64));
-            t.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1));
         });
 
         EXPECT_INITIAL_STATE("After restoring initial state");
@@ -2375,43 +2212,6 @@
     }
 };
 
-// In this test we ensure that setGeometryAppliesWithResize actually demands
-// a buffer of the new size, and not just any size.
-TEST_F(CropLatchingTest, FinalCropLatchingBufferOldSize) {
-    EXPECT_INITIAL_STATE("before anything");
-    // Normally the crop applies immediately even while a resize is pending.
-    asTransaction([&](Transaction& t) {
-        t.setSize(mFGSurfaceControl, 128, 128);
-        t.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127));
-    });
-
-    EXPECT_CROPPED_STATE("after setting crop (without geometryAppliesWithResize)");
-
-    restoreInitialState();
-
-    // In order to prepare to submit a buffer at the wrong size, we acquire it prior to
-    // initiating the resize.
-    lockAndFillFGBuffer();
-
-    asTransaction([&](Transaction& t) {
-        t.setSize(mFGSurfaceControl, 128, 128);
-        t.setGeometryAppliesWithResize(mFGSurfaceControl);
-        t.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127));
-    });
-
-    EXPECT_INITIAL_STATE("after setting crop (with geometryAppliesWithResize)");
-
-    // We now submit our old buffer, at the old size, and ensure it doesn't
-    // trigger geometry latching.
-    unlockFGBuffer();
-
-    EXPECT_INITIAL_STATE("after unlocking FG buffer (with geometryAppliesWithResize)");
-
-    completeFGResize();
-
-    EXPECT_CROPPED_STATE("after the resize finishes");
-}
-
 TEST_F(LayerUpdateTest, DeferredTransactionTest) {
     sp<ScreenCapture> sc;
     {
@@ -2588,22 +2388,6 @@
     }
 }
 
-TEST_F(ChildLayerTest, ChildLayerFinalCropping) {
-    asTransaction([&](Transaction& t) {
-        t.show(mChild);
-        t.setPosition(mChild, 0, 0);
-        t.setPosition(mFGSurfaceControl, 0, 0);
-        t.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5));
-    });
-
-    {
-        ScreenCapture::captureScreen(&mCapture);
-        mCapture->expectChildColor(0, 0);
-        mCapture->expectChildColor(4, 4);
-        mCapture->expectBGColor(5, 5);
-    }
-}
-
 TEST_F(ChildLayerTest, ChildLayerConstraints) {
     asTransaction([&](Transaction& t) {
         t.show(mChild);
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index 7fafab9..356a880 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -634,40 +634,6 @@
     EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
 }
 
-TEST_F(TransactionTest, LayerFinalCrop) {
-    // TODO: Add scaling to confirm that crop happens in display space?
-    {
-        TransactionScope ts(*sFakeComposer);
-        Rect cropRect(32, 32, 32 + 64, 32 + 64);
-        ts.setFinalCrop_legacy(mFGSurfaceControl, cropRect);
-    }
-    ASSERT_EQ(2, sFakeComposer->getFrameCount());
-
-    // In display space we are cropping with [32, 32, 96, 96] against display rect
-    // [64, 64, 128, 128]. Should yield display rect [64, 64, 96, 96]
-    auto referenceFrame = mBaseFrame;
-    referenceFrame[FG_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 32.f, 32.f};
-    referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 32, 64 + 32};
-
-    EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
-}
-
-TEST_F(TransactionTest, LayerFinalCropEmpty) {
-    // TODO: Add scaling to confirm that crop happens in display space?
-    {
-        TransactionScope ts(*sFakeComposer);
-        Rect cropRect(16, 16, 32, 32);
-        ts.setFinalCrop_legacy(mFGSurfaceControl, cropRect);
-    }
-    ASSERT_EQ(2, sFakeComposer->getFrameCount());
-
-    // In display space we are cropping with [16, 16, 32, 32] against display rect
-    // [64, 64, 128, 128]. The intersection is empty and only the background layer is composited.
-    std::vector<RenderState> referenceFrame(1);
-    referenceFrame[BG_LAYER] = mBaseFrame[BG_LAYER];
-    EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
-}
-
 TEST_F(TransactionTest, LayerSetLayer) {
     {
         TransactionScope ts(*sFakeComposer);
@@ -992,22 +958,6 @@
     EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
 }
 
-TEST_F(ChildLayerTest, FinalCropping) {
-    {
-        TransactionScope ts(*sFakeComposer);
-        ts.show(mChild);
-        ts.setPosition(mChild, 0, 0);
-        ts.setPosition(mFGSurfaceControl, 0, 0);
-        ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5));
-    }
-    auto referenceFrame = mBaseFrame;
-    referenceFrame[FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 0 + 5, 0 + 5};
-    referenceFrame[FG_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 5.f, 5.f};
-    referenceFrame[CHILD_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 0 + 5, 0 + 5};
-    referenceFrame[CHILD_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 5.f, 5.f};
-    EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
-}
-
 TEST_F(ChildLayerTest, Constraints) {
     {
         TransactionScope ts(*sFakeComposer);
@@ -1354,7 +1304,6 @@
         ts.setSize(mFGSurfaceControl, 64, 64);
         ts.setPosition(mFGSurfaceControl, 64, 64);
         ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 64, 64));
-        ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1));
     }
 };
 
@@ -1425,111 +1374,6 @@
     EXPECT_TRUE(framesAreSame(referenceFrame2, sFakeComposer->getLatestFrame()));
 }
 
-TEST_F(LatchingTest, FinalCropLatching) {
-    // Normally the crop applies immediately even while a resize is pending.
-    {
-        TransactionScope ts(*sFakeComposer);
-        ts.setSize(mFGSurfaceControl, 128, 128);
-        ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127));
-    }
-
-    auto referenceFrame1 = mBaseFrame;
-    referenceFrame1[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 127, 127};
-    referenceFrame1[FG_LAYER].mSourceCrop =
-            hwc_frect_t{0.f, 0.f, static_cast<float>(127 - 64), static_cast<float>(127 - 64)};
-    EXPECT_TRUE(framesAreSame(referenceFrame1, sFakeComposer->getLatestFrame()));
-
-    restoreInitialState();
-
-    {
-        TransactionScope ts(*sFakeComposer);
-        ts.setSize(mFGSurfaceControl, 128, 128);
-        ts.setGeometryAppliesWithResize(mFGSurfaceControl);
-        ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127));
-    }
-    EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame()));
-
-    completeFGResize();
-
-    auto referenceFrame2 = mBaseFrame;
-    referenceFrame2[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 127, 127};
-    referenceFrame2[FG_LAYER].mSourceCrop =
-            hwc_frect_t{0.f, 0.f, static_cast<float>(127 - 64), static_cast<float>(127 - 64)};
-    referenceFrame2[FG_LAYER].mSwapCount++;
-    EXPECT_TRUE(framesAreSame(referenceFrame2, sFakeComposer->getLatestFrame()));
-}
-
-// In this test we ensure that setGeometryAppliesWithResize actually demands
-// a buffer of the new size, and not just any size.
-TEST_F(LatchingTest, FinalCropLatchingBufferOldSize) {
-    // Normally the crop applies immediately even while a resize is pending.
-    {
-        TransactionScope ts(*sFakeComposer);
-        ts.setSize(mFGSurfaceControl, 128, 128);
-        ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127));
-    }
-
-    auto referenceFrame1 = mBaseFrame;
-    referenceFrame1[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 127, 127};
-    referenceFrame1[FG_LAYER].mSourceCrop =
-            hwc_frect_t{0.f, 0.f, static_cast<float>(127 - 64), static_cast<float>(127 - 64)};
-    EXPECT_TRUE(framesAreSame(referenceFrame1, sFakeComposer->getLatestFrame()));
-
-    restoreInitialState();
-
-    // In order to prepare to submit a buffer at the wrong size, we acquire it prior to
-    // initiating the resize.
-    lockAndFillFGBuffer();
-
-    {
-        TransactionScope ts(*sFakeComposer);
-        ts.setSize(mFGSurfaceControl, 128, 128);
-        ts.setGeometryAppliesWithResize(mFGSurfaceControl);
-        ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127));
-    }
-    EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame()));
-
-    // We now submit our old buffer, at the old size, and ensure it doesn't
-    // trigger geometry latching.
-    unlockFGBuffer();
-
-    auto referenceFrame2 = mBaseFrame;
-    referenceFrame2[FG_LAYER].mSwapCount++;
-    EXPECT_TRUE(framesAreSame(referenceFrame2, sFakeComposer->getLatestFrame()));
-
-    completeFGResize();
-    auto referenceFrame3 = referenceFrame2;
-    referenceFrame3[FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 127, 127};
-    referenceFrame3[FG_LAYER].mSourceCrop =
-            hwc_frect_t{0.f, 0.f, static_cast<float>(127 - 64), static_cast<float>(127 - 64)};
-    referenceFrame3[FG_LAYER].mSwapCount++;
-    EXPECT_TRUE(framesAreSame(referenceFrame3, sFakeComposer->getLatestFrame()));
-}
-
-TEST_F(LatchingTest, FinalCropLatchingRegressionForb37531386) {
-    // In this scenario, we attempt to set the final crop a second time while the resize
-    // is still pending, and ensure we are successful. Success meaning the second crop
-    // is the one which eventually latches and not the first.
-    {
-        TransactionScope ts(*sFakeComposer);
-        ts.setSize(mFGSurfaceControl, 128, 128);
-        ts.setGeometryAppliesWithResize(mFGSurfaceControl);
-        ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(64, 64, 127, 127));
-    }
-
-    {
-        TransactionScope ts(*sFakeComposer);
-        ts.setFinalCrop_legacy(mFGSurfaceControl, Rect(0, 0, -1, -1));
-    }
-    EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame()));
-
-    completeFGResize();
-
-    auto referenceFrame = mBaseFrame;
-    referenceFrame[FG_LAYER].mSwapCount++;
-    EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame()));
-}
-
 } // namespace
 
 int main(int argc, char** argv) {
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 8f1f5e5..f1f0fbf 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -22,6 +22,7 @@
         "DisplayTransactionTest.cpp",
         "EventControlThreadTest.cpp",
         "EventThreadTest.cpp",
+        "SchedulerTest.cpp",
         "mock/DisplayHardware/MockComposer.cpp",
         "mock/DisplayHardware/MockDisplaySurface.cpp",
         "mock/DisplayHardware/MockPowerAdvisor.cpp",
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 1f57b8e..32712c7 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -116,7 +116,7 @@
     // These mocks are created by the test, but are destroyed by SurfaceFlinger
     // by virtue of being stored into a std::unique_ptr. However we still need
     // to keep a reference to them for use in setting up call expectations.
-    RE::mock::RenderEngine* mRenderEngine = new RE::mock::RenderEngine();
+    renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
     Hwc2::mock::Composer* mComposer = nullptr;
     mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
     mock::SurfaceInterceptor* mSurfaceInterceptor = new mock::SurfaceInterceptor();
@@ -127,7 +127,7 @@
     sp<mock::GraphicBufferProducer> mProducer;
     mock::NativeWindowSurface* mNativeWindowSurface = nullptr;
     sp<mock::NativeWindow> mNativeWindow;
-    RE::mock::Surface* mRenderSurface = nullptr;
+    renderengine::mock::Surface* mRenderSurface = nullptr;
 };
 
 DisplayTransactionTest::DisplayTransactionTest() {
@@ -155,7 +155,7 @@
     mFlinger.mutableEventControlThread().reset(mEventControlThread);
     mFlinger.mutableEventThread().reset(mEventThread);
     mFlinger.mutableEventQueue().reset(mMessageQueue);
-    mFlinger.setupRenderEngine(std::unique_ptr<RE::RenderEngine>(mRenderEngine));
+    mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
     mFlinger.mutableInterceptor().reset(mSurfaceInterceptor);
     mFlinger.mutablePrimaryDispSync().reset(mPrimaryDispSync);
 
@@ -277,9 +277,10 @@
         // For simplicity, we only expect to create a single render surface for
         // each test.
         ASSERT_TRUE(test->mRenderSurface == nullptr);
-        test->mRenderSurface = new RE::mock::Surface();
+        test->mRenderSurface = new renderengine::mock::Surface();
         EXPECT_CALL(*test->mRenderEngine, createSurface())
-                .WillOnce(Return(ByMove(std::unique_ptr<RE::Surface>(test->mRenderSurface))));
+                .WillOnce(Return(ByMove(
+                        std::unique_ptr<renderengine::Surface>(test->mRenderSurface))));
         EXPECT_CALL(*test->mRenderSurface, setAsync(static_cast<bool>(ASYNC))).Times(1);
         EXPECT_CALL(*test->mRenderSurface, setCritical(static_cast<bool>(CRITICAL))).Times(1);
         EXPECT_CALL(*test->mRenderSurface, setNativeWindow(test->mNativeWindow.get())).Times(1);
@@ -1735,11 +1736,11 @@
     // A display is set up
     auto nativeWindow = new mock::NativeWindow();
     auto displaySurface = new mock::DisplaySurface();
-    auto renderSurface = new RE::mock::Surface();
+    auto renderSurface = new renderengine::mock::Surface();
     auto display = Case::Display::makeFakeExistingDisplayInjector(this);
     display.setNativeWindow(nativeWindow);
     display.setDisplaySurface(displaySurface);
-    display.setRenderSurface(std::unique_ptr<RE::Surface>(renderSurface));
+    display.setRenderSurface(std::unique_ptr<renderengine::Surface>(renderSurface));
     display.inject();
 
     // There is a change to the viewport state
@@ -1776,11 +1777,11 @@
     // A display is set up
     auto nativeWindow = new mock::NativeWindow();
     auto displaySurface = new mock::DisplaySurface();
-    auto renderSurface = new RE::mock::Surface();
+    auto renderSurface = new renderengine::mock::Surface();
     auto display = Case::Display::makeFakeExistingDisplayInjector(this);
     display.setNativeWindow(nativeWindow);
     display.setDisplaySurface(displaySurface);
-    display.setRenderSurface(std::unique_ptr<RE::Surface>(renderSurface));
+    display.setRenderSurface(std::unique_ptr<renderengine::Surface>(renderSurface));
     display.inject();
 
     // There is a change to the viewport state
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
new file mode 100644
index 0000000..c809e82
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -0,0 +1,186 @@
+#undef LOG_TAG
+#define LOG_TAG "SchedulerUnittests"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <log/log.h>
+
+#include "AsyncCallRecorder.h"
+#include "Scheduler/DispSync.h"
+#include "Scheduler/EventThread.h"
+#include "Scheduler/Scheduler.h"
+#include "mock/MockDispSync.h"
+#include "mock/MockEventThread.h"
+
+using testing::_;
+using testing::Return;
+
+namespace android {
+
+class SchedulerTest : public testing::Test {
+protected:
+    class MockEventThreadConnection : public BnDisplayEventConnection {
+    public:
+        MockEventThreadConnection() = default;
+        ~MockEventThreadConnection() = default;
+
+        MOCK_METHOD1(stealReceiveChannel, status_t(gui::BitTube* outChannel));
+        MOCK_METHOD1(setVsyncRate, status_t(uint32_t count));
+        MOCK_METHOD0(requestNextVsync, void());
+    };
+
+    /**
+     * This mock Scheduler class uses implementation of mock::EventThread but keeps everything else
+     * the same.
+     */
+    class MockScheduler : public android::Scheduler {
+    public:
+        MockScheduler(std::unique_ptr<EventThread> eventThread)
+              : mEventThread(std::move(eventThread)) {}
+
+        std::unique_ptr<EventThread> makeEventThread(
+                const char* /* connectionName */, DispSync* /* dispSync */,
+                nsecs_t /* phaseOffsetNs */,
+                impl::EventThread::ResyncWithRateLimitCallback /* resyncCallback */,
+                impl::EventThread::InterceptVSyncsCallback /* interceptCallback */) override {
+            return std::move(mEventThread);
+        }
+
+        MockScheduler() = default;
+        ~MockScheduler() override = default;
+
+        std::unique_ptr<EventThread> mEventThread;
+    };
+
+    SchedulerTest();
+    ~SchedulerTest() override;
+
+    sp<Scheduler::ConnectionHandle> mConnectionHandle;
+    mock::DispSync* mPrimaryDispSync = new mock::DispSync();
+    mock::EventThread* mEventThread;
+    std::unique_ptr<MockScheduler> mScheduler;
+    sp<MockEventThreadConnection> mEventThreadConnection;
+
+    AsyncCallRecorder<void (*)()> mResyncCallRecorder;
+    AsyncCallRecorder<void (*)(nsecs_t)> mInterceptVSyncCallRecorder;
+};
+
+SchedulerTest::SchedulerTest() {
+    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());
+
+    std::unique_ptr<mock::EventThread> eventThread = std::make_unique<mock::EventThread>();
+    mEventThread = eventThread.get();
+    mScheduler = std::make_unique<MockScheduler>(std::move(eventThread));
+    mEventThreadConnection = new MockEventThreadConnection();
+
+    // createConnection call to scheduler makes a createEventConnection call to EventThread. Make
+    // sure that call gets executed and returns an EventThread::Connection object.
+    EXPECT_CALL(*mEventThread, createEventConnection())
+            .WillRepeatedly(Return(mEventThreadConnection));
+
+    mConnectionHandle = mScheduler->createConnection("appConnection", mPrimaryDispSync, 16,
+                                                     mResyncCallRecorder.getInvocable(),
+                                                     mInterceptVSyncCallRecorder.getInvocable());
+}
+
+SchedulerTest::~SchedulerTest() {
+    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());
+}
+
+namespace {
+/* ------------------------------------------------------------------------
+ * Test cases
+ */
+TEST_F(SchedulerTest, canCreateAndDestroyTest) {
+    EXPECT_FALSE(mResyncCallRecorder.waitForCall().has_value());
+    EXPECT_FALSE(mInterceptVSyncCallRecorder.waitForCall().has_value());
+    EXPECT_EQ(0, mConnectionHandle->id);
+}
+
+TEST_F(SchedulerTest, testNullPtr) {
+    // Passing a null pointer for ConnectionHandle is a valid argument. The code doesn't throw any
+    // exceptions, just gracefully continues.
+    sp<IDisplayEventConnection> returnedValue;
+    ASSERT_NO_FATAL_FAILURE(returnedValue = mScheduler->createDisplayEventConnection(nullptr));
+    EXPECT_TRUE(returnedValue == nullptr);
+    EXPECT_TRUE(mScheduler->getEventThread(nullptr) == nullptr);
+    EXPECT_TRUE(mScheduler->getEventConnection(nullptr) == nullptr);
+    ASSERT_NO_FATAL_FAILURE(
+            mScheduler->hotplugReceived(nullptr, EventThread::DisplayType::Primary, false));
+    ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenAcquired(nullptr));
+    ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenReleased(nullptr));
+    String8 testString;
+    ASSERT_NO_FATAL_FAILURE(mScheduler->dump(nullptr, testString));
+    EXPECT_TRUE(testString == "");
+    ASSERT_NO_FATAL_FAILURE(mScheduler->setPhaseOffset(nullptr, 10));
+}
+
+TEST_F(SchedulerTest, invalidConnectionHandle) {
+    // Passing an invalid ConnectionHandle is a valid argument. The code doesn't throw any
+    // exceptions, just gracefully continues.
+    sp<Scheduler::ConnectionHandle> connectionHandle = new Scheduler::ConnectionHandle(20);
+
+    sp<IDisplayEventConnection> returnedValue;
+    ASSERT_NO_FATAL_FAILURE(returnedValue =
+                                    mScheduler->createDisplayEventConnection(connectionHandle));
+    EXPECT_TRUE(returnedValue == nullptr);
+    EXPECT_TRUE(mScheduler->getEventThread(connectionHandle) == nullptr);
+    EXPECT_TRUE(mScheduler->getEventConnection(connectionHandle) == nullptr);
+
+    // The EXPECT_CALLS make sure we don't call the functions on the subsequent event threads.
+    EXPECT_CALL(*mEventThread, onHotplugReceived(_, _)).Times(0);
+    ASSERT_NO_FATAL_FAILURE(mScheduler->hotplugReceived(connectionHandle,
+                                                        EventThread::DisplayType::Primary, false));
+
+    EXPECT_CALL(*mEventThread, onScreenAcquired()).Times(0);
+    ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenAcquired(connectionHandle));
+
+    EXPECT_CALL(*mEventThread, onScreenReleased()).Times(0);
+    ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenReleased(connectionHandle));
+
+    String8 testString;
+    EXPECT_CALL(*mEventThread, dump(_)).Times(0);
+    ASSERT_NO_FATAL_FAILURE(mScheduler->dump(connectionHandle, testString));
+    EXPECT_TRUE(testString == "");
+
+    EXPECT_CALL(*mEventThread, setPhaseOffset(_)).Times(0);
+    ASSERT_NO_FATAL_FAILURE(mScheduler->setPhaseOffset(connectionHandle, 10));
+}
+
+TEST_F(SchedulerTest, validConnectionHandle) {
+    sp<IDisplayEventConnection> returnedValue;
+    ASSERT_NO_FATAL_FAILURE(returnedValue =
+                                    mScheduler->createDisplayEventConnection(mConnectionHandle));
+    EXPECT_TRUE(returnedValue != nullptr);
+    ASSERT_EQ(returnedValue, mEventThreadConnection);
+
+    EXPECT_TRUE(mScheduler->getEventThread(mConnectionHandle) != nullptr);
+    EXPECT_TRUE(mScheduler->getEventConnection(mConnectionHandle) != nullptr);
+
+    EXPECT_CALL(*mEventThread, onHotplugReceived(EventThread::DisplayType::Primary, false))
+            .Times(1);
+    ASSERT_NO_FATAL_FAILURE(mScheduler->hotplugReceived(mConnectionHandle,
+                                                        EventThread::DisplayType::Primary, false));
+
+    EXPECT_CALL(*mEventThread, onScreenAcquired()).Times(1);
+    ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenAcquired(mConnectionHandle));
+
+    EXPECT_CALL(*mEventThread, onScreenReleased()).Times(1);
+    ASSERT_NO_FATAL_FAILURE(mScheduler->onScreenReleased(mConnectionHandle));
+
+    String8 testString("dump");
+    EXPECT_CALL(*mEventThread, dump(testString)).Times(1);
+    ASSERT_NO_FATAL_FAILURE(mScheduler->dump(mConnectionHandle, testString));
+    EXPECT_TRUE(testString != "");
+
+    EXPECT_CALL(*mEventThread, setPhaseOffset(10)).Times(1);
+    ASSERT_NO_FATAL_FAILURE(mScheduler->setPhaseOffset(mConnectionHandle, 10));
+}
+
+} // namespace
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index d8e7581..1bba480 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -23,7 +23,7 @@
 
 class EventThread;
 
-namespace RE {
+namespace renderengine {
 class RenderEngine;
 }
 
@@ -36,7 +36,7 @@
     // Extend this as needed for accessing SurfaceFlinger private (and public)
     // functions.
 
-    void setupRenderEngine(std::unique_ptr<RE::RenderEngine> renderEngine) {
+    void setupRenderEngine(std::unique_ptr<renderengine::RenderEngine> renderEngine) {
         mFlinger->getBE().mRenderEngine = std::move(renderEngine);
     }
 
@@ -113,6 +113,7 @@
      */
 
     auto& mutableHasWideColorDisplay() { return SurfaceFlinger::hasWideColorDisplay; }
+    auto& mutablePrimaryDisplayOrientation() { return SurfaceFlinger::primaryDisplayOrientation; }
     auto& mutableUseColorManagement() { return SurfaceFlinger::useColorManagement; }
 
     auto& mutableDisplayTokens() { return mFlinger->mDisplayTokens; }
@@ -313,7 +314,7 @@
             return *this;
         }
 
-        auto& setRenderSurface(std::unique_ptr<RE::Surface> renderSurface) {
+        auto& setRenderSurface(std::unique_ptr<renderengine::Surface> renderSurface) {
             mRenderSurface = std::move(renderSurface);
             return *this;
         }
@@ -328,8 +329,9 @@
             sp<DisplayDevice> device =
                     new DisplayDevice(mFlinger.mFlinger.get(), mType, mDisplayId, mSecure,
                                       mDisplayToken, mNativeWindow, mDisplaySurface,
-                                      std::move(mRenderSurface), 0, 0, false, HdrCapabilities(), 0,
-                                      hdrAndRenderIntents, HWC_POWER_MODE_NORMAL);
+                                      std::move(mRenderSurface), 0, 0,
+                                      DisplayState::eOrientationDefault, false, HdrCapabilities(),
+                                      0, hdrAndRenderIntents, HWC_POWER_MODE_NORMAL);
             mFlinger.mutableDisplays().emplace(mDisplayToken, device);
 
             DisplayDeviceState state;
@@ -352,7 +354,7 @@
         const int32_t mDisplayId;
         sp<ANativeWindow> mNativeWindow;
         sp<DisplaySurface> mDisplaySurface;
-        std::unique_ptr<RE::Surface> mRenderSurface;
+        std::unique_ptr<renderengine::Surface> mRenderSurface;
         bool mSecure = false;
     };
 
diff --git a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
index 8d503f4..f2f3675 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h
@@ -30,6 +30,7 @@
 
     MOCK_METHOD1(init, void(const sp<SurfaceFlinger>&));
     MOCK_METHOD1(setEventThread, void(android::EventThread*));
+    MOCK_METHOD1(setEventConnection, void(const sp<BnDisplayEventConnection>& connection));
     MOCK_METHOD0(waitMessage, void());
     MOCK_METHOD2(postMessage, status_t(const sp<MessageBase>&, nsecs_t));
     MOCK_METHOD0(invalidate, void());
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
index 200f214..06ef0b2 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
@@ -19,7 +19,7 @@
 #include <ui/Region.h>
 
 namespace android {
-namespace RE {
+namespace renderengine {
 namespace mock {
 
 // Explicit default instantiation is recommended.
@@ -33,5 +33,5 @@
 Image::~Image() = default;
 
 } // namespace mock
-} // namespace RE
+} // namespace renderengine
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
index b907c49..1c5135b 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
@@ -25,22 +25,23 @@
 #include <renderengine/Texture.h>
 
 namespace android {
-namespace RE {
+namespace renderengine {
 namespace mock {
 
-class RenderEngine : public RE::RenderEngine {
+class RenderEngine : public renderengine::RenderEngine {
 public:
     RenderEngine();
     ~RenderEngine() override;
 
-    MOCK_METHOD0(createSurface, std::unique_ptr<RE::Surface>());
-    MOCK_METHOD0(createImage, std::unique_ptr<RE::Image>());
+    MOCK_METHOD0(createFramebuffer, std::unique_ptr<Framebuffer>());
+    MOCK_METHOD0(createSurface, std::unique_ptr<renderengine::Surface>());
+    MOCK_METHOD0(createImage, std::unique_ptr<renderengine::Image>());
     MOCK_CONST_METHOD0(primeCache, void());
     MOCK_METHOD1(dump, void(String8&));
     MOCK_CONST_METHOD0(useNativeFenceSync, bool());
     MOCK_CONST_METHOD0(useWaitSync, bool());
     MOCK_CONST_METHOD0(isCurrent, bool());
-    MOCK_METHOD1(setCurrentSurface, bool(const RE::Surface&));
+    MOCK_METHOD1(setCurrentSurface, bool(const renderengine::Surface&));
     MOCK_METHOD0(resetCurrentSurface, void());
     MOCK_METHOD0(flush, base::unique_fd());
     MOCK_METHOD0(finish, bool());
@@ -52,11 +53,11 @@
     MOCK_METHOD0(disableScissor, void());
     MOCK_METHOD2(genTextures, void(size_t, uint32_t*));
     MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*));
-    MOCK_METHOD2(bindExternalTextureImage, void(uint32_t, const RE::Image&));
+    MOCK_METHOD2(bindExternalTextureImage, void(uint32_t, const renderengine::Image&));
     MOCK_METHOD5(readPixels, void(size_t, size_t, size_t, size_t, uint32_t*));
     MOCK_CONST_METHOD0(checkErrors, void());
-    MOCK_METHOD6(setViewportAndProjection,
-                 void(size_t, size_t, Rect, size_t, bool, ui::Transform::orientation_flags));
+    MOCK_METHOD4(setViewportAndProjection,
+                 void(size_t, size_t, Rect, ui::Transform::orientation_flags));
     MOCK_METHOD4(setupLayerBlending, void(bool, bool, bool, const half4&));
     MOCK_METHOD1(setupLayerTexturing, void(const Texture&));
     MOCK_METHOD0(setupLayerBlackedOut, void());
@@ -69,15 +70,14 @@
     MOCK_METHOD1(setSourceDataSpace, void(ui::Dataspace));
     MOCK_METHOD1(setOutputDataSpace, void(ui::Dataspace));
     MOCK_METHOD1(setDisplayMaxLuminance, void(const float));
-    MOCK_METHOD2(bindNativeBufferAsFrameBuffer,
-                 void(ANativeWindowBuffer*, RE::BindNativeBufferAsFramebuffer*));
-    MOCK_METHOD1(unbindNativeBufferAsFrameBuffer, void(RE::BindNativeBufferAsFramebuffer*));
+    MOCK_METHOD1(bindFrameBuffer, status_t(Framebuffer*));
+    MOCK_METHOD1(unbindFrameBuffer, void(Framebuffer*));
     MOCK_METHOD1(drawMesh, void(const Mesh&));
     MOCK_CONST_METHOD0(getMaxTextureSize, size_t());
     MOCK_CONST_METHOD0(getMaxViewportDims, size_t());
 };
 
-class Surface : public RE::Surface {
+class Surface : public renderengine::Surface {
 public:
     Surface();
     ~Surface() override;
@@ -94,7 +94,7 @@
     MOCK_CONST_METHOD0(queryHeight, int32_t());
 };
 
-class Image : public RE::Image {
+class Image : public renderengine::Image {
 public:
     Image();
     ~Image() override;
@@ -104,5 +104,5 @@
 };
 
 } // namespace mock
-} // namespace RE
+} // namespace renderengine
 } // namespace android
diff --git a/services/vr/performanced/cpu_set.cpp b/services/vr/performanced/cpu_set.cpp
index 1a7264c..d940b79 100644
--- a/services/vr/performanced/cpu_set.cpp
+++ b/services/vr/performanced/cpu_set.cpp
@@ -106,7 +106,7 @@
   return sets;
 }
 
-std::string CpuSetManager::DumpState() const {
+void CpuSetManager::DumpState(std::ostringstream& stream) const {
   size_t max_path = 0;
   std::vector<CpuSet*> sets;
 
@@ -119,8 +119,6 @@
     return a->path() < b->path();
   });
 
-  std::ostringstream stream;
-
   stream << std::left;
   stream << std::setw(max_path) << "Path";
   stream << " ";
@@ -146,8 +144,6 @@
     stream << std::setw(6) << set->GetTasks().size();
     stream << std::endl;
   }
-
-  return stream.str();
 }
 
 void CpuSetManager::MoveUnboundTasks(const std::string& target_set) {
diff --git a/services/vr/performanced/cpu_set.h b/services/vr/performanced/cpu_set.h
index 6879272..4c25e9e 100644
--- a/services/vr/performanced/cpu_set.h
+++ b/services/vr/performanced/cpu_set.h
@@ -5,6 +5,7 @@
 
 #include <memory>
 #include <mutex>
+#include <sstream>
 #include <string>
 #include <unordered_map>
 #include <vector>
@@ -83,7 +84,7 @@
   // to shield the system from interference from unbound kernel threads.
   void MoveUnboundTasks(const std::string& target_set);
 
-  std::string DumpState() const;
+  void DumpState(std::ostringstream& stream) const;
 
   operator bool() const { return root_set_ != nullptr; }
 
diff --git a/services/vr/performanced/performance_service.cpp b/services/vr/performanced/performance_service.cpp
index d304bac..73dcf76 100644
--- a/services/vr/performanced/performance_service.cpp
+++ b/services/vr/performanced/performance_service.cpp
@@ -1,5 +1,7 @@
 #include "performance_service.h"
 
+#include <sstream>
+
 #include <sched.h>
 #include <sys/prctl.h>
 #include <unistd.h>
@@ -31,6 +33,10 @@
 
 const char kRootCpuSet[] = "/";
 
+const char kVrAppRenderPolicy[] = "vr:app:render";
+
+const bool kAllowAppsToRequestVrAppRenderPolicy = false;
+
 constexpr unsigned long kTimerSlackForegroundNs = 50000;
 constexpr unsigned long kTimerSlackBackgroundNs = 40000000;
 
@@ -133,6 +139,17 @@
   using AllowRootSystemTrusted =
       CheckOr<Trusted, UserId<AID_ROOT, AID_SYSTEM>, GroupId<AID_SYSTEM>>;
 
+  auto vr_app_render_permission_check = [](
+      const pdx::Message& sender, const Task& task) {
+          // For vr:app:render, in addition to system/root apps and VrCore, we
+          // also allow apps to request vr:app:render if
+          // kAllowAppsToRequestVrAppRenderPolicy == true, but not for other
+          // apps, only for themselves.
+          return (task && task.thread_group_id() == sender.GetProcessId() &&
+                  kAllowAppsToRequestVrAppRenderPolicy)
+              || AllowRootSystemTrusted::Check(sender, task);
+      };
+
   partition_permission_check_ = AllowRootSystemTrusted::Check;
 
   // Setup the scheduler classes.
@@ -184,11 +201,11 @@
         .priority = fifo_medium + 2,
         .permission_check = AllowRootSystemTrusted::Check,
         "/system/performance"}},
-      {"vr:app:render",
+      {kVrAppRenderPolicy,
        {.timer_slack = kTimerSlackForegroundNs,
         .scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK,
         .priority = fifo_medium + 1,
-        .permission_check = AllowRootSystemTrusted::Check,
+        .permission_check = vr_app_render_permission_check,
         "/application/performance"}},
       {"normal",
        {.timer_slack = kTimerSlackForegroundNs,
@@ -215,7 +232,10 @@
 }
 
 std::string PerformanceService::DumpState(size_t /*max_length*/) {
-  return cpuset_.DumpState();
+  std::ostringstream stream;
+  stream << "vr_app_render_thread: " << vr_app_render_thread_ << std::endl;
+  cpuset_.DumpState(stream);
+  return stream.str();
 }
 
 Status<void> PerformanceService::OnSetSchedulerPolicy(
@@ -241,7 +261,12 @@
     // Make sure the sending process is allowed to make the requested change to
     // this task.
     if (!config.IsAllowed(message, task))
-      return ErrorStatus(EINVAL);
+      return ErrorStatus(EPERM);
+
+    if (scheduler_policy == kVrAppRenderPolicy) {
+      // We only allow one vr:app:render thread at a time
+      SetVrAppRenderThread(task_id);
+    }
 
     // Get the thread group's cpu set. Policies that do not specify a cpuset
     // should default to this cpuset.
@@ -299,14 +324,16 @@
 Status<void> PerformanceService::OnSetCpuPartition(
     Message& message, pid_t task_id, const std::string& partition) {
   Task task(task_id);
-  if (!task || task.thread_group_id() != message.GetProcessId())
+  if (!task)
     return ErrorStatus(EINVAL);
+  if (task.thread_group_id() != message.GetProcessId())
+    return ErrorStatus(EPERM);
 
   // Temporary permission check.
   // TODO(eieio): Replace this with a configuration file.
   if (partition_permission_check_ &&
       !partition_permission_check_(message, task)) {
-    return ErrorStatus(EINVAL);
+    return ErrorStatus(EPERM);
   }
 
   auto target_set = cpuset_.Lookup(partition);
@@ -333,7 +360,12 @@
     // Make sure the sending process is allowed to make the requested change to
     // this task.
     if (!config.IsAllowed(message, task))
-      return ErrorStatus(EINVAL);
+      return ErrorStatus(EPERM);
+
+    if (scheduler_class == kVrAppRenderPolicy) {
+      // We only allow one vr:app:render thread at a time
+      SetVrAppRenderThread(task_id);
+    }
 
     struct sched_param param;
     param.sched_priority = config.priority;
@@ -356,8 +388,10 @@
                                                           pid_t task_id) {
   // Make sure the task id is valid and belongs to the sending process.
   Task task(task_id);
-  if (!task || task.thread_group_id() != message.GetProcessId())
+  if (!task)
     return ErrorStatus(EINVAL);
+  if (task.thread_group_id() != message.GetProcessId())
+    return ErrorStatus(EPERM);
 
   return task.GetCpuSetPath();
 }
@@ -390,5 +424,38 @@
   }
 }
 
+void PerformanceService::SetVrAppRenderThread(pid_t new_vr_app_render_thread) {
+  ALOGI("SetVrAppRenderThread old=%d new=%d",
+      vr_app_render_thread_, new_vr_app_render_thread);
+
+  if (vr_app_render_thread_ >= 0 &&
+      vr_app_render_thread_ != new_vr_app_render_thread) {
+    // Restore the default scheduler policy and priority on the previous
+    // vr:app:render thread.
+    struct sched_param param;
+    param.sched_priority = 0;
+    if (sched_setscheduler(vr_app_render_thread_, SCHED_NORMAL, &param) < 0) {
+      if (errno == ESRCH) {
+        ALOGI("Failed to revert %s scheduler policy. Couldn't find thread %d."
+            " Was the app killed?", kVrAppRenderPolicy, vr_app_render_thread_);
+      } else {
+        ALOGE("Failed to revert %s scheduler policy: %s",
+            kVrAppRenderPolicy, strerror(errno));
+      }
+    }
+
+    // Restore the default timer slack on the previous vr:app:render thread.
+    prctl(PR_SET_TIMERSLACK_PID, kTimerSlackForegroundNs,
+        vr_app_render_thread_);
+  }
+
+  // We could also reset the thread's cpuset here, but the cpuset is already
+  // managed by Android. Better to let Android adjust the cpuset as the app
+  // moves to the background, rather than adjust it ourselves here, and risk
+  // stomping on the value set by Android.
+
+  vr_app_render_thread_ = new_vr_app_render_thread;
+}
+
 }  // namespace dvr
 }  // namespace android
diff --git a/services/vr/performanced/performance_service.h b/services/vr/performanced/performance_service.h
index 6b519ab..fe63756 100644
--- a/services/vr/performanced/performance_service.h
+++ b/services/vr/performanced/performance_service.h
@@ -39,6 +39,14 @@
   pdx::Status<std::string> OnGetCpuPartition(pdx::Message& message,
                                              pid_t task_id);
 
+  // Set which thread gets the vr:app:render policy. Only one thread at a time
+  // is allowed to have vr:app:render. If multiple threads are allowed
+  // vr:app:render, and those threads busy loop, the system can freeze. When
+  // SetVrAppRenderThread() is called, the thread which we had previously
+  // assigned vr:app:render will have its scheduling policy reset to default
+  // values.
+  void SetVrAppRenderThread(pid_t new_vr_app_render_thread);
+
   CpuSetManager cpuset_;
 
   int sched_fifo_min_priority_;
@@ -70,6 +78,8 @@
   std::function<bool(const pdx::Message& message, const Task& task)>
       partition_permission_check_;
 
+  pid_t vr_app_render_thread_ = -1;
+
   PerformanceService(const PerformanceService&) = delete;
   void operator=(const PerformanceService&) = delete;
 };