Merge "[SurfaceFlinger] Add composition unit tests"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..f8f0265
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,3 @@
+[Hook Scripts]
+owners_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "OWNERS$"
+installd_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "^cmds/installd/"
diff --git a/cmds/installd/OWNERS b/cmds/installd/OWNERS
new file mode 100644
index 0000000..50440f1
--- /dev/null
+++ b/cmds/installd/OWNERS
@@ -0,0 +1,7 @@
+set noparent
+
+calin@google.com
+agampe@google.com
+jsharkey@android.com
+toddke@google.com
+ngeoffray@google.com
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 6b340a8..d776682 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -403,7 +403,11 @@
 
     cb.func_audit = audit_callback;
     selinux_set_callback(SELINUX_CB_AUDIT, cb);
+#ifdef VENDORSERVICEMANAGER
+    cb.func_log = selinux_vendor_log_callback;
+#else
     cb.func_log = selinux_log_callback;
+#endif
     selinux_set_callback(SELINUX_CB_LOG, cb);
 
 #ifdef VENDORSERVICEMANAGER
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 76d5a73..e5c68b5 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -24,10 +24,10 @@
     ],
 
     srcs: [
-        "ABinderProcess.cpp",
-        "AIBinder.cpp",
-        "AParcel.cpp",
-        "AServiceManager.cpp",
+        "ibinder.cpp",
+        "parcel.cpp",
+        "process.cpp",
+        "service_manager.cpp",
     ],
 
     shared_libs: [
diff --git a/libs/binder/ndk/AIBinder.cpp b/libs/binder/ndk/ibinder.cpp
similarity index 64%
rename from libs/binder/ndk/AIBinder.cpp
rename to libs/binder/ndk/ibinder.cpp
index 83972f7..8a1ec05 100644
--- a/libs/binder/ndk/AIBinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -15,13 +15,15 @@
  */
 
 #include <android/binder_ibinder.h>
-#include "AIBinder_internal.h"
+#include "ibinder_internal.h"
 
 #include <android/binder_status.h>
-#include "AParcel_internal.h"
+#include "parcel_internal.h"
 
 #include <android-base/logging.h>
 
+using DeathRecipient = ::android::IBinder::DeathRecipient;
+
 using ::android::IBinder;
 using ::android::Parcel;
 using ::android::sp;
@@ -32,10 +34,10 @@
 
 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 */};
+void clean(const void* /*id*/, void* /*obj*/, void* /*cookie*/){/* do nothing */};
 
 static void attach(const sp<IBinder>& binder) {
-    binder->attachObject(kId, kValue, nullptr /*cookie*/, cleanId);
+    binder->attachObject(kId, kValue, nullptr /*cookie*/, clean);
 }
 static bool has(const sp<IBinder>& binder) {
     return binder != nullptr && binder->findObject(kId) == kValue;
@@ -43,6 +45,21 @@
 
 } // namespace ABBinderTag
 
+namespace ABpBinderTag {
+
+static std::mutex gLock;
+static const void* kId = "ABpBinder";
+struct Value {
+    wp<ABpBinder> binder;
+};
+void clean(const void* id, void* obj, void* cookie) {
+    CHECK(id == kId) << id << " " << obj << " " << cookie;
+
+    delete static_cast<Value*>(obj);
+};
+
+} // namespace ABpBinderTag
+
 AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {}
 AIBinder::~AIBinder() {}
 
@@ -121,14 +138,51 @@
 }
 ABpBinder::~ABpBinder() {}
 
-sp<AIBinder> ABpBinder::fromBinder(const ::android::sp<::android::IBinder>& binder) {
+void ABpBinder::onLastStrongRef(const void* id) {
+    {
+        std::lock_guard<std::mutex> lock(ABpBinderTag::gLock);
+        // Since ABpBinder is OBJECT_LIFETIME_WEAK, we must remove this weak reference in order for
+        // the ABpBinder to be deleted. Since a strong reference to this ABpBinder object should no
+        // longer be able to exist at the time of this method call, there is no longer a need to
+        // recover it.
+
+        ABpBinderTag::Value* value =
+                static_cast<ABpBinderTag::Value*>(remote()->findObject(ABpBinderTag::kId));
+        if (value != nullptr) {
+            value->binder = nullptr;
+        }
+    }
+
+    BpRefBase::onLastStrongRef(id);
+}
+
+sp<AIBinder> ABpBinder::lookupOrCreateFromBinder(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);
+
+    // The following code ensures that for a given binder object (remote or local), if it is not an
+    // ABBinder then at most one ABpBinder object exists in a given process representing it.
+    std::lock_guard<std::mutex> lock(ABpBinderTag::gLock);
+
+    ABpBinderTag::Value* value =
+            static_cast<ABpBinderTag::Value*>(binder->findObject(ABpBinderTag::kId));
+    if (value == nullptr) {
+        value = new ABpBinderTag::Value;
+        binder->attachObject(ABpBinderTag::kId, static_cast<void*>(value), nullptr /*cookie*/,
+                             ABpBinderTag::clean);
+    }
+
+    sp<ABpBinder> ret = value->binder.promote();
+    if (ret == nullptr) {
+        ret = new ABpBinder(binder);
+        value->binder = ret;
+    }
+
+    return ret;
 }
 
 struct AIBinder_Weak {
@@ -179,6 +233,63 @@
     return new AIBinder_Class(interfaceDescriptor, onCreate, onDestroy, onTransact);
 }
 
+void AIBinder_DeathRecipient::TransferDeathRecipient::binderDied(const wp<IBinder>& who) {
+    CHECK(who == mWho);
+
+    mOnDied(mCookie);
+    mWho = nullptr;
+}
+
+AIBinder_DeathRecipient::AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied)
+      : mOnDied(onDied) {
+    CHECK(onDied != nullptr);
+}
+
+binder_status_t AIBinder_DeathRecipient::linkToDeath(AIBinder* binder, void* cookie) {
+    CHECK(binder != nullptr);
+
+    std::lock_guard<std::mutex> l(mDeathRecipientsMutex);
+
+    sp<TransferDeathRecipient> recipient =
+            new TransferDeathRecipient(binder->getBinder(), cookie, mOnDied);
+
+    binder_status_t status = binder->getBinder()->linkToDeath(recipient, cookie, 0 /*flags*/);
+    if (status != EX_NONE) {
+        return status;
+    }
+
+    mDeathRecipients.push_back(recipient);
+    return EX_NONE;
+}
+
+binder_status_t AIBinder_DeathRecipient::unlinkToDeath(AIBinder* binder, void* cookie) {
+    CHECK(binder != nullptr);
+
+    std::lock_guard<std::mutex> l(mDeathRecipientsMutex);
+
+    for (auto it = mDeathRecipients.rbegin(); it != mDeathRecipients.rend(); ++it) {
+        sp<TransferDeathRecipient> recipient = *it;
+
+        if (recipient->getCookie() == cookie &&
+
+            recipient->getWho() == binder->getBinder()) {
+            mDeathRecipients.erase(it.base() - 1);
+
+            binder_status_t status =
+                    binder->getBinder()->unlinkToDeath(recipient, cookie, 0 /*flags*/);
+            if (status != EX_NONE) {
+                LOG(ERROR) << __func__
+                           << ": removed reference to death recipient but unlink failed.";
+            }
+            return status;
+        }
+    }
+
+    return -ENOENT;
+}
+
+// start of C-API methods
+
 AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args) {
     if (clazz == nullptr) {
         LOG(ERROR) << __func__ << ": Must provide class to construct local binder.";
@@ -218,6 +329,26 @@
     return binder->getBinder()->pingBinder();
 }
 
+binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
+                                     void* cookie) {
+    if (binder == nullptr || recipient == nullptr) {
+        LOG(ERROR) << __func__ << ": Must provide binder and recipient.";
+        return EX_NULL_POINTER;
+    }
+
+    return recipient->linkToDeath(binder, cookie);
+}
+
+binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
+                                       void* cookie) {
+    if (binder == nullptr || recipient == nullptr) {
+        LOG(ERROR) << __func__ << ": Must provide binder and recipient.";
+        return EX_NULL_POINTER;
+    }
+
+    return recipient->unlinkToDeath(binder, cookie);
+}
+
 void AIBinder_incStrong(AIBinder* binder) {
     if (binder == nullptr) {
         LOG(ERROR) << __func__ << ": on null binder";
@@ -285,6 +416,13 @@
         return EX_ILLEGAL_STATE;
     }
 
+    if (!binder->isRemote()) {
+        LOG(WARNING) << "A binder object at " << binder
+                     << " is being transacted on, however, this object is in the same process as "
+                        "its proxy. Transacting with this binder is expensive compared to just "
+                        "calling the corresponding functionality in the same process.";
+    }
+
     *in = new AParcel(binder);
     binder_status_t status = (**in)->writeInterfaceToken(clazz->getInterfaceDescriptor());
     if (status != EX_NONE) {
@@ -340,3 +478,21 @@
 
     return parcelStatus;
 }
+
+AIBinder_DeathRecipient* AIBinder_DeathRecipient_new(
+        AIBinder_DeathRecipient_onBinderDied onBinderDied) {
+    if (onBinderDied == nullptr) {
+        LOG(ERROR) << __func__ << ": requires non-null onBinderDied parameter.";
+        return nullptr;
+    }
+    return new AIBinder_DeathRecipient(onBinderDied);
+}
+
+void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient** recipient) {
+    if (recipient == nullptr) {
+        return;
+    }
+
+    delete *recipient;
+    *recipient = nullptr;
+}
diff --git a/libs/binder/ndk/AIBinder_internal.h b/libs/binder/ndk/ibinder_internal.h
similarity index 65%
rename from libs/binder/ndk/AIBinder_internal.h
rename to libs/binder/ndk/ibinder_internal.h
index 23949bb..fcf1b0b 100644
--- a/libs/binder/ndk/AIBinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -17,9 +17,11 @@
 #pragma once
 
 #include <android/binder_ibinder.h>
-#include "AIBinder_internal.h"
+#include "ibinder_internal.h"
 
 #include <atomic>
+#include <mutex>
+#include <vector>
 
 #include <binder/Binder.h>
 #include <binder/IBinder.h>
@@ -79,13 +81,18 @@
     void* mUserData;
 };
 
-// This binder object may be remote or local (even though it is 'Bp'). It is not yet associated with
-// a class.
+// This binder object may be remote or local (even though it is 'Bp'). The implication if it is
+// local is that it is an IBinder object created outside of the domain of libbinder_ndk.
 struct ABpBinder : public AIBinder, public ::android::BpRefBase {
-    static ::android::sp<AIBinder> fromBinder(const ::android::sp<::android::IBinder>& binder);
+    // Looks up to see if this object has or is an existing ABBinder or ABpBinder object, otherwise
+    // it creates an ABpBinder object.
+    static ::android::sp<AIBinder> lookupOrCreateFromBinder(
+            const ::android::sp<::android::IBinder>& binder);
 
     virtual ~ABpBinder();
 
+    void onLastStrongRef(const void* id) override;
+
     ::android::sp<::android::IBinder> getBinder() override { return remote(); }
     ABpBinder* asABpBinder() override { return this; }
 
@@ -108,3 +115,38 @@
     // one.
     const ::android::String16 mInterfaceDescriptor;
 };
+
+// Ownership is like this (when linked to death):
+//
+//   AIBinder_DeathRecipient -sp-> TransferDeathRecipient <-wp-> IBinder
+//
+// When the AIBinder_DeathRecipient is dropped, so are the actual underlying death recipients. When
+// the IBinder dies, only a wp to it is kept.
+struct AIBinder_DeathRecipient {
+    // One of these is created for every linkToDeath. This is to be able to recover data when a
+    // binderDied receipt only gives us information about the IBinder.
+    struct TransferDeathRecipient : ::android::IBinder::DeathRecipient {
+        TransferDeathRecipient(const ::android::wp<::android::IBinder>& who, void* cookie,
+                               const AIBinder_DeathRecipient_onBinderDied& onDied)
+              : mWho(who), mCookie(cookie), mOnDied(onDied) {}
+
+        void binderDied(const ::android::wp<::android::IBinder>& who) override;
+
+        const ::android::wp<::android::IBinder>& getWho() { return mWho; }
+        void* getCookie() { return mCookie; }
+
+    private:
+        ::android::wp<::android::IBinder> mWho;
+        void* mCookie;
+        const AIBinder_DeathRecipient_onBinderDied& mOnDied;
+    };
+
+    AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied);
+    binder_status_t linkToDeath(AIBinder* binder, void* cookie);
+    binder_status_t unlinkToDeath(AIBinder* binder, void* cookie);
+
+private:
+    std::mutex mDeathRecipientsMutex;
+    std::vector<::android::sp<TransferDeathRecipient>> mDeathRecipients;
+    AIBinder_DeathRecipient_onBinderDied mOnDied;
+};
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index aa29437..7dca5a4 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -14,6 +14,16 @@
  * limitations under the License.
  */
 
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_ibinder.h
+ * @brief Object which can receive transactions and be sent across processes.
+ */
+
 #pragma once
 
 #include <stdint.h>
@@ -84,6 +94,16 @@
  * 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.
+ *
+ * If the process containing an AIBinder dies, it is possible to be holding a strong reference to
+ * an object which does not exist. In this case, transactions to this binder will return
+ * EX_DEAD_OBJECT. See also AIBinder_linkToDeath, AIBinder_unlinkToDeath, and AIBinder_isAlive.
+ *
+ * Once an AIBinder is created, anywhere it is passed (remotely or locally), there is a 1-1
+ * correspondence between the address of an AIBinder and the object it represents. This means that
+ * when two AIBinder pointers point to the same address, they represent the same object (whether
+ * that object is local or remote). This correspondance can be broken accidentally if AIBinder_new
+ * is erronesouly called to create the same object multiple times.
  */
 struct AIBinder;
 typedef struct AIBinder AIBinder;
@@ -97,6 +117,12 @@
 typedef struct AIBinder_Weak AIBinder_Weak;
 
 /**
+ * Represents a handle on a death notification. See AIBinder_linkToDeath/AIBinder_unlinkToDeath.
+ */
+struct AIBinder_DeathRecipient;
+typedef struct AIBinder_DeathRecipient AIBinder_DeathRecipient;
+
+/**
  * 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
@@ -138,6 +164,14 @@
  *
  * When this is called, the refcount is implicitly 1. So, calling decStrong exactly one time is
  * required to delete this object.
+ *
+ * Once an AIBinder object is created using this API, re-creating that AIBinder for the same
+ * instance of the same class will break pointer equality for that specific AIBinder object. For
+ * instance, if someone erroneously created two AIBinder instances representing the same callback
+ * object and passed one to a hypothetical addCallback function and then later another one to a
+ * hypothetical removeCallback function, the remote process would have no way to determine that
+ * these two objects are actually equal using the AIBinder pointer alone (which they should be able
+ * to do). Also see the suggested memory ownership model suggested above.
  */
 __attribute__((warn_unused_result)) AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args);
 
@@ -163,6 +197,26 @@
 binder_status_t AIBinder_ping(AIBinder* binder);
 
 /**
+ * Registers for notifications that the associated binder is dead. The same death recipient may be
+ * associated with multiple different binders. If the binder is local, then no death recipient will
+ * be given (since if the local process dies, then no recipient will exist to recieve a
+ * transaction). The cookie is passed to recipient in the case that this binder dies and can be
+ * null. The exact cookie must also be used to unlink this transaction (see AIBinder_linkToDeath).
+ * This function may return a binder transaction failure. The cookie can be used both for
+ * identification and holding user data.
+ */
+binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
+                                     void* cookie);
+
+/**
+ * Stops registration for the associated binder dying. Does not delete the recipient. This function
+ * may return a binder transaction failure and in case the death recipient cannot be found, it
+ * returns -ENOENT.
+ */
+binder_status_t AIBinder_unlinkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
+                                       void* cookie);
+
+/**
  * This can only be called if a strong reference to this object already exists in process.
  */
 void AIBinder_incStrong(AIBinder* binder);
@@ -254,4 +308,23 @@
  */
 __attribute__((warn_unused_result)) AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder);
 
+/**
+ * This function is executed on death receipt. See AIBinder_linkToDeath/AIBinder_unlinkToDeath.
+ */
+typedef void (*AIBinder_DeathRecipient_onBinderDied)(void* cookie);
+
+/**
+ * Creates a new binder death recipient. This can be attached to multiple different binder objects.
+ */
+__attribute__((warn_unused_result)) AIBinder_DeathRecipient* AIBinder_DeathRecipient_new(
+        AIBinder_DeathRecipient_onBinderDied onBinderDied);
+
+/**
+ * Deletes a binder death recipient. It is not necessary to call AIBinder_unlinkToDeath before
+ * calling this as these will all be automatically unlinked.
+ */
+void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient** recipient);
+
 __END_DECLS
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index 19925f7..e871ed1 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -14,6 +14,16 @@
  * limitations under the License.
  */
 
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_parcel.h
+ * @brief A collection of data that can be sent as a single packet.
+ */
+
 #pragma once
 
 #include <sys/cdefs.h>
@@ -150,3 +160,5 @@
 // @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
index d414c99..e97e181 100644
--- a/libs/binder/ndk/include_ndk/android/binder_status.h
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -14,6 +14,15 @@
  * limitations under the License.
  */
 
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_status.h
+ */
+
 #pragma once
 
 #include <stdint.h>
@@ -54,3 +63,5 @@
 typedef int32_t binder_status_t;
 
 __END_DECLS
+
+/** @} */
diff --git a/libs/binder/ndk/AParcel.cpp b/libs/binder/ndk/parcel.cpp
similarity index 91%
rename from libs/binder/ndk/AParcel.cpp
rename to libs/binder/ndk/parcel.cpp
index 93384d6..ccdfc7b 100644
--- a/libs/binder/ndk/AParcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -15,9 +15,9 @@
  */
 
 #include <android/binder_parcel.h>
-#include "AParcel_internal.h"
+#include "parcel_internal.h"
 
-#include "AIBinder_internal.h"
+#include "ibinder_internal.h"
 
 #include <binder/Parcel.h>
 
@@ -35,7 +35,8 @@
 }
 
 binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) {
-    return (*parcel)->writeStrongBinder(binder->getBinder());
+    sp<IBinder> writeBinder = binder != nullptr ? binder->getBinder() : nullptr;
+    return (*parcel)->writeStrongBinder(writeBinder);
 }
 binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder) {
     sp<IBinder> readBinder = nullptr;
@@ -43,7 +44,7 @@
     if (status != EX_NONE) {
         return status;
     }
-    sp<AIBinder> ret = ABpBinder::fromBinder(readBinder);
+    sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(readBinder);
     AIBinder_incStrong(ret.get());
     *binder = ret.get();
     return status;
@@ -54,7 +55,7 @@
     if (status != EX_NONE) {
         return status;
     }
-    sp<AIBinder> ret = ABpBinder::fromBinder(readBinder);
+    sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(readBinder);
     AIBinder_incStrong(ret.get());
     *binder = ret.get();
     return status;
diff --git a/libs/binder/ndk/AParcel_internal.h b/libs/binder/ndk/parcel_internal.h
similarity index 98%
rename from libs/binder/ndk/AParcel_internal.h
rename to libs/binder/ndk/parcel_internal.h
index 9f30a2f..b6a9110 100644
--- a/libs/binder/ndk/AParcel_internal.h
+++ b/libs/binder/ndk/parcel_internal.h
@@ -21,7 +21,7 @@
 #include <sys/cdefs.h>
 
 #include <binder/Parcel.h>
-#include "AIBinder_internal.h"
+#include "ibinder_internal.h"
 
 struct AParcel {
     const ::android::Parcel* operator->() const { return mParcel; }
diff --git a/libs/binder/ndk/ABinderProcess.cpp b/libs/binder/ndk/process.cpp
similarity index 100%
rename from libs/binder/ndk/ABinderProcess.cpp
rename to libs/binder/ndk/process.cpp
diff --git a/libs/binder/ndk/scripts/gen_parcel_helper.py b/libs/binder/ndk/scripts/gen_parcel_helper.py
index 5c0b936..794afe2 100755
--- a/libs/binder/ndk/scripts/gen_parcel_helper.py
+++ b/libs/binder/ndk/scripts/gen_parcel_helper.py
@@ -81,7 +81,7 @@
         source += "}\n\n"
 
     replaceFileTags(ROOT + "include_ndk/android/binder_parcel.h", header)
-    replaceFileTags(ROOT + "AParcel.cpp", source)
+    replaceFileTags(ROOT + "parcel.cpp", source)
 
     print("Updating DONE.")
 
diff --git a/libs/binder/ndk/AServiceManager.cpp b/libs/binder/ndk/service_manager.cpp
similarity index 93%
rename from libs/binder/ndk/AServiceManager.cpp
rename to libs/binder/ndk/service_manager.cpp
index 3979945..5bc69b0 100644
--- a/libs/binder/ndk/AServiceManager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -15,7 +15,7 @@
  */
 
 #include <android/binder_manager.h>
-#include "AIBinder_internal.h"
+#include "ibinder_internal.h"
 
 #include <binder/IServiceManager.h>
 
@@ -41,7 +41,7 @@
     sp<IServiceManager> sm = defaultServiceManager();
     sp<IBinder> binder = sm->getService(String16(instance));
 
-    sp<AIBinder> ret = ABpBinder::fromBinder(binder);
+    sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(binder);
     AIBinder_incStrong(ret.get());
     return ret.get();
 }
diff --git a/libs/binder/ndk/test/main_client.cpp b/libs/binder/ndk/test/main_client.cpp
index 967789f..b8518d7 100644
--- a/libs/binder/ndk/test/main_client.cpp
+++ b/libs/binder/ndk/test/main_client.cpp
@@ -16,6 +16,7 @@
 
 #include <android-base/logging.h>
 #include <android/binder_manager.h>
+#include <android/binder_process.h>
 #include <gtest/gtest.h>
 #include <iface/iface.h>
 
@@ -45,6 +46,28 @@
     AIBinder_decStrong(binder);
 }
 
+void OnBinderDeath(void* cookie) {
+    LOG(ERROR) << "BINDER DIED. COOKIE: " << cookie;
+}
+
+TEST(NdkBinder, LinkToDeath) {
+    ABinderProcess_setThreadPoolMaxThreadCount(1); // to recieve death notifications
+    ABinderProcess_startThreadPool();
+
+    AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
+    ASSERT_NE(nullptr, binder);
+
+    AIBinder_DeathRecipient* recipient = AIBinder_DeathRecipient_new(OnBinderDeath);
+    ASSERT_NE(nullptr, recipient);
+
+    EXPECT_EQ(EX_NONE, AIBinder_linkToDeath(binder, recipient, nullptr));
+    EXPECT_EQ(EX_NONE, AIBinder_unlinkToDeath(binder, recipient, nullptr));
+    EXPECT_EQ(-ENOENT, AIBinder_unlinkToDeath(binder, recipient, nullptr));
+
+    AIBinder_DeathRecipient_delete(&recipient);
+    AIBinder_decStrong(binder);
+}
+
 class MyTestFoo : public IFoo {
     int32_t doubleNumber(int32_t in) override {
         LOG(INFO) << "doubleNumber " << in;
@@ -64,6 +87,34 @@
     EXPECT_EQ(2, getFoo->doubleNumber(1));
 }
 
+TEST(NdkBinder, EqualityOfRemoteBinderPointer) {
+    AIBinder* binderA = AServiceManager_getService(kExistingNonNdkService);
+    ASSERT_NE(nullptr, binderA);
+
+    AIBinder* binderB = AServiceManager_getService(kExistingNonNdkService);
+    ASSERT_NE(nullptr, binderB);
+
+    EXPECT_EQ(binderA, binderB);
+
+    AIBinder_decStrong(binderA);
+    AIBinder_decStrong(binderB);
+}
+
+TEST(NdkBinder, ABpBinderRefCount) {
+    AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
+    AIBinder_Weak* wBinder = AIBinder_Weak_new(binder);
+
+    ASSERT_NE(nullptr, binder);
+    EXPECT_EQ(1, AIBinder_debugGetRefCount(binder));
+
+    AIBinder_decStrong(binder);
+
+    // assert because would need to decStrong if non-null and we shouldn't need to add a no-op here
+    ASSERT_NE(nullptr, AIBinder_Weak_promote(wBinder));
+
+    AIBinder_Weak_delete(&wBinder);
+}
+
 TEST(NdkBinder, AddServiceMultipleTimes) {
     static const char* kInstanceName1 = "test-multi-1";
     static const char* kInstanceName2 = "test-multi-2";
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index ef3e592..98264ac 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -31,6 +31,7 @@
         "-Werror",
     ],
     cppflags: [
+        "-std=c++1z",
         "-Weverything",
 
         // The static constructors and destructors in this library have not been noted to
@@ -58,7 +59,7 @@
         "-Wno-weak-vtables",
 
         // Allow four-character integer literals
-	"-Wno-four-char-constants",
+        "-Wno-four-char-constants",
 
         // Allow documentation warnings
         "-Wno-documentation",
@@ -116,7 +117,7 @@
         "SyncFeatures.cpp",
         "view/Surface.cpp",
         "bufferqueue/1.0/B2HProducerListener.cpp",
-        "bufferqueue/1.0/H2BGraphicBufferProducer.cpp"
+        "bufferqueue/1.0/H2BGraphicBufferProducer.cpp",
     ],
 
     shared_libs: [
@@ -124,7 +125,7 @@
         "libsync",
         "libbinder",
         "libbufferhub",
-        "libbufferhubqueue",  // TODO(b/70046255): Remove this once BufferHub is integrated into libgui.
+        "libbufferhubqueue", // TODO(b/70046255): Remove this once BufferHub is integrated into libgui.
         "libpdx_default_transport",
         "libcutils",
         "libEGL",
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index deb8ea8..5a8d8db 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "LayerState"
+
 #include <utils/Errors.h>
 #include <binder/Parcel.h>
 #include <gui/ISurfaceComposerClient.h>
@@ -313,8 +315,10 @@
         sidebandStream = other.sidebandStream;
     }
 
-    if (other.what != what) {
-        ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating?");
+    if ((other.what & what) != other.what) {
+        ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
+              "other.what=0x%X what=0x%X",
+              other.what, what);
     }
 }
 
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index e3ef2a9..1605050 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -26,6 +26,7 @@
         "-Werror",
     ],
     cppflags: [
+        "-std=c++1z",
         "-Weverything",
 
         // The static constructors and destructors in this library have not been noted to
diff --git a/libs/ui/FenceTime.cpp b/libs/ui/FenceTime.cpp
index 1414766..340231d 100644
--- a/libs/ui/FenceTime.cpp
+++ b/libs/ui/FenceTime.cpp
@@ -33,18 +33,6 @@
 
 const auto FenceTime::NO_FENCE = std::make_shared<FenceTime>(Fence::NO_FENCE);
 
-void* FenceTime::operator new(size_t byteCount) noexcept {
-    void *p = nullptr;
-    if (posix_memalign(&p, alignof(FenceTime), byteCount)) {
-        return nullptr;
-    }
-    return p;
-}
-
-void FenceTime::operator delete(void *p) {
-    free(p);
-}
-
 FenceTime::FenceTime(const sp<Fence>& fence)
   : mState(((fence.get() != nullptr) && fence->isValid()) ?
             State::VALID : State::INVALID),
diff --git a/libs/ui/include/ui/FenceTime.h b/libs/ui/include/ui/FenceTime.h
index 871fcf2..a5a1fcb 100644
--- a/libs/ui/include/ui/FenceTime.h
+++ b/libs/ui/include/ui/FenceTime.h
@@ -113,11 +113,6 @@
 
     void signalForTest(nsecs_t signalTime);
 
-    // Override new and delete since this needs 8-byte alignment, which
-    // is not guaranteed on x86.
-    static void* operator new(size_t nbytes) noexcept;
-    static void operator delete(void *p);
-
 private:
     // For tests only. If forceValidForTest is true, then getSignalTime will
     // never return SIGNAL_TIME_INVALID and isValid will always return true.
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 1f2c517..a296d20 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -440,6 +440,9 @@
 Status<std::vector<size_t>> ProducerQueue::AllocateBuffers(
     uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
     uint64_t usage, size_t buffer_count) {
+  if (buffer_count == 0) {
+    return {};
+  }
   if (capacity() + buffer_count > kMaxQueueCapacity) {
     ALOGE(
         "ProducerQueue::AllocateBuffers: queue is at capacity: %zu, cannot "
@@ -481,10 +484,13 @@
     }
   }
 
-  if (buffer_slots.size() == 0) {
-    // Error out if no buffer is allocated and improted.
-    ALOGE_IF(TRACE, "ProducerQueue::AllocateBuffers: no buffer allocated.");
-    ErrorStatus(ENOMEM);
+  if (buffer_slots.size() != buffer_count) {
+    // Error out if the count of allocated/imported buffer(s) is not correct.
+    ALOGE(
+        "ProducerQueue::AllocateBuffers: requested to import %zu "
+        "buffers, but actually imported %zu buffers.",
+        buffer_count, buffer_slots.size());
+    return ErrorStatus(ENOMEM);
   }
 
   return {std::move(buffer_slots)};
@@ -502,12 +508,6 @@
           status.GetErrorMessage().c_str());
     return status.error_status();
   }
-
-  if (status.get().size() == 0) {
-    ALOGE_IF(TRACE, "ProducerQueue::AllocateBuffer: no buffer allocated.");
-    ErrorStatus(ENOMEM);
-  }
-
   return {status.get()[0]};
 }
 
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index 2975f56..c1f322c 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -562,6 +562,28 @@
   ASSERT_EQ(cs2, ps2);
 }
 
+TEST_F(BufferHubQueueTest, TestAllocateTwoBuffers) {
+  ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
+  ASSERT_EQ(producer_queue_->capacity(), 0);
+
+  auto status = producer_queue_->AllocateBuffers(
+      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+      kBufferUsage, 2);
+  ASSERT_TRUE(status.ok());
+  ASSERT_EQ(producer_queue_->capacity(), 2);
+}
+
+TEST_F(BufferHubQueueTest, TestAllocateZeroBuffers) {
+  ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
+  ASSERT_EQ(producer_queue_->capacity(), 0);
+
+  auto status = producer_queue_->AllocateBuffers(
+      kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
+      kBufferUsage, 0);
+  ASSERT_TRUE(status.ok());
+  ASSERT_EQ(producer_queue_->capacity(), 0);
+}
+
 TEST_F(BufferHubQueueTest, TestUsageSetMask) {
   const uint32_t set_mask = GRALLOC_USAGE_SW_WRITE_OFTEN;
   ASSERT_TRUE(
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 10974b4..4839bfb 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -433,6 +433,10 @@
     if (mFlinger->isLayerTripleBufferingDisabled()) {
         mProducer->setMaxDequeuedBufferCount(2);
     }
+
+    if (const auto display = mFlinger->getDefaultDisplayDevice()) {
+        updateTransformHint(display);
+    }
 }
 
 status_t BufferQueueLayer::setDefaultBufferProperties(uint32_t w, uint32_t h, PixelFormat format) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 2c94a0e..d963ab6 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -160,11 +160,13 @@
 
     std::optional<DisplayId> displayId;
 
-    uint8_t port;
-    DisplayIdentificationData data;
-    if (getDisplayIdentificationData(hwcDisplayId, &port, &data)) {
-        displayId = generateDisplayId(port, data);
-        ALOGE_IF(!displayId, "Failed to generate stable ID for display %" PRIu64, hwcDisplayId);
+    if (connection == HWC2::Connection::Connected) {
+        uint8_t port;
+        DisplayIdentificationData data;
+        if (getDisplayIdentificationData(hwcDisplayId, &port, &data)) {
+            displayId = generateDisplayId(port, data);
+            ALOGE_IF(!displayId, "Failed to generate stable ID for display %" PRIu64, hwcDisplayId);
+        }
     }
 
     // Disconnect is handled through HWComposer::disconnectDisplay via
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 29de50c..a1e45b0 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -284,7 +284,7 @@
 }
 
 Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const {
-    const Layer::State& s(getDrawingState());
+    const State& s(getDrawingState());
     Rect win(getActiveWidth(s), getActiveHeight(s));
 
     Rect crop = getCrop(s);
@@ -319,12 +319,12 @@
 }
 
 FloatRect Layer::computeBounds() const {
-    const Layer::State& s(getDrawingState());
+    const State& s(getDrawingState());
     return computeBounds(getActiveTransparentRegion(s));
 }
 
 FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const {
-    const Layer::State& s(getDrawingState());
+    const State& s(getDrawingState());
     Rect win(getActiveWidth(s), getActiveHeight(s));
 
     Rect crop = getCrop(s);
@@ -762,7 +762,7 @@
 }
 
 bool Layer::isSecure() const {
-    const Layer::State& s(mDrawingState);
+    const State& s(mDrawingState);
     return (s.flags & layer_state_t::eLayerSecure);
 }
 
@@ -885,7 +885,7 @@
 }
 
 uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) {
-    const Layer::State& s(getDrawingState());
+    const State& s(getDrawingState());
 
     const bool sizeChanged = (stateToCommit->requested_legacy.w != s.requested_legacy.w) ||
             (stateToCommit->requested_legacy.h != s.requested_legacy.h);
@@ -941,7 +941,7 @@
     // latching configuration. See Layer.h for a detailed discussion of
     // how geometry latching is controlled.
     if (!(flags & eDontUpdateGeometryState)) {
-        Layer::State& editCurrentState(getCurrentState());
+        State& editCurrentState(getCurrentState());
 
         // If mFreezeGeometryUpdates is true we are in the setGeometryAppliesWithResize
         // mode, which causes attributes which normally latch regardless of scaling mode,
@@ -974,14 +974,14 @@
     ATRACE_CALL();
 
     pushPendingState();
-    Layer::State c = getCurrentState();
+    State c = getCurrentState();
     if (!applyPendingStates(&c)) {
         return 0;
     }
 
     flags = doTransactionResize(flags, &c);
 
-    const Layer::State& s(getDrawingState());
+    const State& s(getDrawingState());
 
     if (getActiveGeometry(c) != getActiveGeometry(s)) {
         // invalidate and recompute the visible regions if needed
@@ -1272,7 +1272,7 @@
 // ----------------------------------------------------------------------------
 
 bool Layer::isHiddenByPolicy() const {
-    const Layer::State& s(mDrawingState);
+    const State& s(mDrawingState);
     const auto& parent = mDrawingParent.promote();
     if (parent != nullptr && parent->isHiddenByPolicy()) {
         return true;
@@ -1315,7 +1315,7 @@
 // TODO(marissaw): add new layer state info to layer debugging
 LayerDebugInfo Layer::getLayerDebugInfo() const {
     LayerDebugInfo info;
-    const Layer::State& ds = getDrawingState();
+    const State& ds = getDrawingState();
     info.mName = getName();
     sp<Layer> parent = getParent();
     info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string());
@@ -1392,7 +1392,7 @@
 
     result.appendFormat(" %s\n", name.string());
 
-    const Layer::State& layerState(getDrawingState());
+    const State& layerState(getDrawingState());
     const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(displayId);
     if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) {
         result.appendFormat("  rel %6d | ", layerState.z);
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index f00367f..3b54873 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -16,152 +16,33 @@
 
 #include <renderengine/RenderEngine.h>
 
-#include <vector>
-
+#include <cutils/properties.h>
 #include <log/log.h>
 #include <private/gui/SyncFeatures.h>
-#include <renderengine/Image.h>
-#include <renderengine/Mesh.h>
-#include <renderengine/Surface.h>
-#include <ui/Rect.h>
-#include <ui/Region.h>
-#include <utils/KeyedVector.h>
 #include "gl/GLES20RenderEngine.h"
-#include "gl/GLExtensions.h"
-#include "gl/ProgramCache.h"
-
-using namespace android::renderengine::gl;
-
-extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 
 namespace android {
 namespace renderengine {
 
+std::unique_ptr<impl::RenderEngine> RenderEngine::create(int hwcFormat, uint32_t featureFlags) {
+    char prop[PROPERTY_VALUE_MAX];
+    property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, "gles");
+    if (strcmp(prop, "gles") == 0) {
+        ALOGD("RenderEngine GLES Backend");
+        return renderengine::gl::GLES20RenderEngine::create(hwcFormat, featureFlags);
+    }
+    ALOGE("UNKNOWN BackendType: %s, create GLES RenderEngine.", prop);
+    return renderengine::gl::GLES20RenderEngine::create(hwcFormat, featureFlags);
+}
+
 RenderEngine::~RenderEngine() = default;
 
 namespace impl {
 
-std::unique_ptr<RenderEngine> RenderEngine::create(int hwcFormat, uint32_t featureFlags) {
-    // initialize EGL for the default display
-    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    if (!eglInitialize(display, nullptr, nullptr)) {
-        LOG_ALWAYS_FATAL("failed to initialize EGL");
-    }
-
-    GLExtensions& extensions = GLExtensions::getInstance();
-    extensions.initWithEGLStrings(eglQueryStringImplementationANDROID(display, EGL_VERSION),
-                                  eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS));
-
-    // The code assumes that ES2 or later is available if this extension is
-    // supported.
-    EGLConfig config = EGL_NO_CONFIG;
-    if (!extensions.hasNoConfigContext()) {
-        config = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
-    }
-
-    EGLint renderableType = 0;
-    if (config == EGL_NO_CONFIG) {
-        renderableType = EGL_OPENGL_ES2_BIT;
-    } else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
-        LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
-    }
-    EGLint contextClientVersion = 0;
-    if (renderableType & EGL_OPENGL_ES2_BIT) {
-        contextClientVersion = 2;
-    } else if (renderableType & EGL_OPENGL_ES_BIT) {
-        contextClientVersion = 1;
-    } else {
-        LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs");
-    }
-
-    std::vector<EGLint> contextAttributes;
-    contextAttributes.reserve(6);
-    contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
-    contextAttributes.push_back(contextClientVersion);
-    bool useContextPriority = extensions.hasContextPriority() &&
-                              (featureFlags & RenderEngine::USE_HIGH_PRIORITY_CONTEXT);
-    if (useContextPriority) {
-        contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
-        contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
-    }
-    contextAttributes.push_back(EGL_NONE);
-
-    EGLContext ctxt = eglCreateContext(display, config, nullptr, contextAttributes.data());
-
-    // if can't create a GL context, we can only abort.
-    LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");
-
-    // now figure out what version of GL did we actually get
-    // NOTE: a dummy surface is not needed if KHR_create_context is supported
-
-    EGLConfig dummyConfig = config;
-    if (dummyConfig == EGL_NO_CONFIG) {
-        dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
-    }
-    EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
-    EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs);
-    LOG_ALWAYS_FATAL_IF(dummy == EGL_NO_SURFACE, "can't create dummy pbuffer");
-    EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
-    LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");
-
-    extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
-                                 glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));
-
-    GlesVersion version = parseGlesVersion(extensions.getVersion());
-
-    // initialize the renderer while GL is current
-
-    std::unique_ptr<RenderEngine> engine;
-    switch (version) {
-        case GLES_VERSION_1_0:
-        case GLES_VERSION_1_1:
-            LOG_ALWAYS_FATAL("SurfaceFlinger requires OpenGL ES 2.0 minimum to run.");
-            break;
-        case GLES_VERSION_2_0:
-        case GLES_VERSION_3_0:
-            engine = std::make_unique<GLES20RenderEngine>(featureFlags);
-            break;
-    }
-    engine->setEGLHandles(display, config, ctxt);
-
-    ALOGI("OpenGL ES informations:");
-    ALOGI("vendor    : %s", extensions.getVendor());
-    ALOGI("renderer  : %s", extensions.getRenderer());
-    ALOGI("version   : %s", extensions.getVersion());
-    ALOGI("extensions: %s", extensions.getExtensions());
-    ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize());
-    ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims());
-
-    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    eglDestroySurface(display, dummy);
-
-    return engine;
-}
-
 RenderEngine::RenderEngine(uint32_t featureFlags)
-      : mEGLDisplay(EGL_NO_DISPLAY),
-        mEGLConfig(nullptr),
-        mEGLContext(EGL_NO_CONTEXT),
-        mFeatureFlags(featureFlags) {}
+      : mFeatureFlags(featureFlags) {}
 
-RenderEngine::~RenderEngine() {
-    eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    eglTerminate(mEGLDisplay);
-}
-
-void RenderEngine::setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt) {
-    mEGLDisplay = display;
-    mEGLConfig = config;
-    mEGLContext = ctxt;
-}
-
-EGLDisplay RenderEngine::getEGLDisplay() const {
-    return mEGLDisplay;
-}
-
-EGLConfig RenderEngine::getEGLConfig() const {
-    return mEGLConfig;
-}
+RenderEngine::~RenderEngine() = default;
 
 bool RenderEngine::useNativeFenceSync() const {
     return SyncFeatures::getInstance().useNativeFenceSync();
@@ -171,185 +52,6 @@
     return SyncFeatures::getInstance().useWaitSync();
 }
 
-RenderEngine::GlesVersion RenderEngine::parseGlesVersion(const char* str) {
-    int major, minor;
-    if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
-        if (sscanf(str, "OpenGL ES %d.%d", &major, &minor) != 2) {
-            ALOGW("Unable to parse GL_VERSION string: \"%s\"", str);
-            return GLES_VERSION_1_0;
-        }
-    }
-
-    if (major == 1 && minor == 0) return GLES_VERSION_1_0;
-    if (major == 1 && minor >= 1) return GLES_VERSION_1_1;
-    if (major == 2 && minor >= 0) return GLES_VERSION_2_0;
-    if (major == 3 && minor >= 0) return GLES_VERSION_3_0;
-
-    ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor);
-    return GLES_VERSION_1_0;
-}
-
-void RenderEngine::dump(String8& result) {
-    const GLExtensions& extensions = GLExtensions::getInstance();
-
-    result.appendFormat("EGL implementation : %s\n", extensions.getEGLVersion());
-    result.appendFormat("%s\n", extensions.getEGLExtensions());
-
-    result.appendFormat("GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
-                        extensions.getVersion());
-    result.appendFormat("%s\n", extensions.getExtensions());
-}
-
-static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
-                                         EGLint wanted, EGLConfig* outConfig) {
-    EGLint numConfigs = -1, n = 0;
-    eglGetConfigs(dpy, nullptr, 0, &numConfigs);
-    EGLConfig* const configs = new EGLConfig[numConfigs];
-    eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
-
-    if (n) {
-        if (attribute != EGL_NONE) {
-            for (int i = 0; i < n; i++) {
-                EGLint value = 0;
-                eglGetConfigAttrib(dpy, configs[i], attribute, &value);
-                if (wanted == value) {
-                    *outConfig = configs[i];
-                    delete[] configs;
-                    return NO_ERROR;
-                }
-            }
-        } else {
-            // just pick the first one
-            *outConfig = configs[0];
-            delete[] configs;
-            return NO_ERROR;
-        }
-    }
-    delete[] configs;
-    return NAME_NOT_FOUND;
-}
-
-class EGLAttributeVector {
-    struct Attribute;
-    class Adder;
-    friend class Adder;
-    KeyedVector<Attribute, EGLint> mList;
-    struct Attribute {
-        Attribute() : v(0){};
-        explicit Attribute(EGLint v) : v(v) {}
-        EGLint v;
-        bool operator<(const Attribute& other) const {
-            // this places EGL_NONE at the end
-            EGLint lhs(v);
-            EGLint rhs(other.v);
-            if (lhs == EGL_NONE) lhs = 0x7FFFFFFF;
-            if (rhs == EGL_NONE) rhs = 0x7FFFFFFF;
-            return lhs < rhs;
-        }
-    };
-    class Adder {
-        friend class EGLAttributeVector;
-        EGLAttributeVector& v;
-        EGLint attribute;
-        Adder(EGLAttributeVector& v, EGLint attribute) : v(v), attribute(attribute) {}
-
-    public:
-        void operator=(EGLint value) {
-            if (attribute != EGL_NONE) {
-                v.mList.add(Attribute(attribute), value);
-            }
-        }
-        operator EGLint() const { return v.mList[attribute]; }
-    };
-
-public:
-    EGLAttributeVector() { mList.add(Attribute(EGL_NONE), EGL_NONE); }
-    void remove(EGLint attribute) {
-        if (attribute != EGL_NONE) {
-            mList.removeItem(Attribute(attribute));
-        }
-    }
-    Adder operator[](EGLint attribute) { return Adder(*this, attribute); }
-    EGLint operator[](EGLint attribute) const { return mList[attribute]; }
-    // cast-operator to (EGLint const*)
-    operator EGLint const*() const { return &mList.keyAt(0).v; }
-};
-
-static status_t selectEGLConfig(EGLDisplay display, EGLint format, EGLint renderableType,
-                                EGLConfig* config) {
-    // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
-    // it is to be used with WIFI displays
-    status_t err;
-    EGLint wantedAttribute;
-    EGLint wantedAttributeValue;
-
-    EGLAttributeVector attribs;
-    if (renderableType) {
-        attribs[EGL_RENDERABLE_TYPE] = renderableType;
-        attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE;
-        attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
-        attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE;
-        attribs[EGL_RED_SIZE] = 8;
-        attribs[EGL_GREEN_SIZE] = 8;
-        attribs[EGL_BLUE_SIZE] = 8;
-        attribs[EGL_ALPHA_SIZE] = 8;
-        wantedAttribute = EGL_NONE;
-        wantedAttributeValue = EGL_NONE;
-    } else {
-        // if no renderable type specified, fallback to a simplified query
-        wantedAttribute = EGL_NATIVE_VISUAL_ID;
-        wantedAttributeValue = format;
-    }
-
-    err = selectConfigForAttribute(display, attribs, wantedAttribute, wantedAttributeValue, config);
-    if (err == NO_ERROR) {
-        EGLint caveat;
-        if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
-            ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
-    }
-
-    return err;
-}
-
-EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
-    status_t err;
-    EGLConfig config;
-
-    // First try to get an ES2 config
-    err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
-    if (err != NO_ERROR) {
-        // If ES2 fails, try ES1
-        err = selectEGLConfig(display, format, EGL_OPENGL_ES_BIT, &config);
-        if (err != NO_ERROR) {
-            // still didn't work, probably because we're on the emulator...
-            // try a simplified query
-            ALOGW("no suitable EGLConfig found, trying a simpler query");
-            err = selectEGLConfig(display, format, 0, &config);
-            if (err != NO_ERROR) {
-                // this EGL is too lame for android
-                LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
-            }
-        }
-    }
-
-    if (logConfig) {
-        // print some debugging info
-        EGLint r, g, b, a;
-        eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
-        eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
-        eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
-        eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
-        ALOGI("EGL information:");
-        ALOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
-        ALOGI("version   : %s", eglQueryString(display, EGL_VERSION));
-        ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
-        ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS) ?: "Not Supported");
-        ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
-    }
-
-    return config;
-}
-
 }  // namespace impl
 }  // namespace renderengine
 }  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
index 61df675..0f0ff62 100644
--- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
@@ -44,6 +44,8 @@
 #include "Program.h"
 #include "ProgramCache.h"
 
+extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
+
 bool checkGlError(const char* op, int lineNumber) {
     bool errorFound = false;
     GLint error = glGetError();
@@ -109,8 +111,259 @@
 
 using ui::Dataspace;
 
+static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
+                                         EGLint wanted, EGLConfig* outConfig) {
+    EGLint numConfigs = -1, n = 0;
+    eglGetConfigs(dpy, nullptr, 0, &numConfigs);
+    EGLConfig* const configs = new EGLConfig[numConfigs];
+    eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
+
+    if (n) {
+        if (attribute != EGL_NONE) {
+            for (int i = 0; i < n; i++) {
+                EGLint value = 0;
+                eglGetConfigAttrib(dpy, configs[i], attribute, &value);
+                if (wanted == value) {
+                    *outConfig = configs[i];
+                    delete[] configs;
+                    return NO_ERROR;
+                }
+            }
+        } else {
+            // just pick the first one
+            *outConfig = configs[0];
+            delete[] configs;
+            return NO_ERROR;
+        }
+    }
+    delete[] configs;
+    return NAME_NOT_FOUND;
+}
+
+class EGLAttributeVector {
+    struct Attribute;
+    class Adder;
+    friend class Adder;
+    KeyedVector<Attribute, EGLint> mList;
+    struct Attribute {
+        Attribute() : v(0){};
+        explicit Attribute(EGLint v) : v(v) {}
+        EGLint v;
+        bool operator<(const Attribute& other) const {
+            // this places EGL_NONE at the end
+            EGLint lhs(v);
+            EGLint rhs(other.v);
+            if (lhs == EGL_NONE) lhs = 0x7FFFFFFF;
+            if (rhs == EGL_NONE) rhs = 0x7FFFFFFF;
+            return lhs < rhs;
+        }
+    };
+    class Adder {
+        friend class EGLAttributeVector;
+        EGLAttributeVector& v;
+        EGLint attribute;
+        Adder(EGLAttributeVector& v, EGLint attribute) : v(v), attribute(attribute) {}
+
+    public:
+        void operator=(EGLint value) {
+            if (attribute != EGL_NONE) {
+                v.mList.add(Attribute(attribute), value);
+            }
+        }
+        operator EGLint() const { return v.mList[attribute]; }
+    };
+
+public:
+    EGLAttributeVector() { mList.add(Attribute(EGL_NONE), EGL_NONE); }
+    void remove(EGLint attribute) {
+        if (attribute != EGL_NONE) {
+            mList.removeItem(Attribute(attribute));
+        }
+    }
+    Adder operator[](EGLint attribute) { return Adder(*this, attribute); }
+    EGLint operator[](EGLint attribute) const { return mList[attribute]; }
+    // cast-operator to (EGLint const*)
+    operator EGLint const*() const { return &mList.keyAt(0).v; }
+};
+
+static status_t selectEGLConfig(EGLDisplay display, EGLint format, EGLint renderableType,
+                                EGLConfig* config) {
+    // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
+    // it is to be used with WIFI displays
+    status_t err;
+    EGLint wantedAttribute;
+    EGLint wantedAttributeValue;
+
+    EGLAttributeVector attribs;
+    if (renderableType) {
+        attribs[EGL_RENDERABLE_TYPE] = renderableType;
+        attribs[EGL_RECORDABLE_ANDROID] = EGL_TRUE;
+        attribs[EGL_SURFACE_TYPE] = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
+        attribs[EGL_FRAMEBUFFER_TARGET_ANDROID] = EGL_TRUE;
+        attribs[EGL_RED_SIZE] = 8;
+        attribs[EGL_GREEN_SIZE] = 8;
+        attribs[EGL_BLUE_SIZE] = 8;
+        attribs[EGL_ALPHA_SIZE] = 8;
+        wantedAttribute = EGL_NONE;
+        wantedAttributeValue = EGL_NONE;
+    } else {
+        // if no renderable type specified, fallback to a simplified query
+        wantedAttribute = EGL_NATIVE_VISUAL_ID;
+        wantedAttributeValue = format;
+    }
+
+    err = selectConfigForAttribute(display, attribs, wantedAttribute, wantedAttributeValue, config);
+    if (err == NO_ERROR) {
+        EGLint caveat;
+        if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
+            ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
+    }
+
+    return err;
+}
+
+std::unique_ptr<GLES20RenderEngine> GLES20RenderEngine::create(int hwcFormat,
+                                                               uint32_t featureFlags) {
+    // initialize EGL for the default display
+    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    if (!eglInitialize(display, nullptr, nullptr)) {
+        LOG_ALWAYS_FATAL("failed to initialize EGL");
+    }
+
+    GLExtensions& extensions = GLExtensions::getInstance();
+    extensions.initWithEGLStrings(eglQueryStringImplementationANDROID(display, EGL_VERSION),
+                                  eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS));
+
+    // The code assumes that ES2 or later is available if this extension is
+    // supported.
+    EGLConfig config = EGL_NO_CONFIG;
+    if (!extensions.hasNoConfigContext()) {
+        config = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
+    }
+
+    EGLint renderableType = 0;
+    if (config == EGL_NO_CONFIG) {
+        renderableType = EGL_OPENGL_ES2_BIT;
+    } else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
+        LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
+    }
+    EGLint contextClientVersion = 0;
+    if (renderableType & EGL_OPENGL_ES2_BIT) {
+        contextClientVersion = 2;
+    } else if (renderableType & EGL_OPENGL_ES_BIT) {
+        contextClientVersion = 1;
+    } else {
+        LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs");
+    }
+
+    std::vector<EGLint> contextAttributes;
+    contextAttributes.reserve(6);
+    contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
+    contextAttributes.push_back(contextClientVersion);
+    bool useContextPriority = extensions.hasContextPriority() &&
+                              (featureFlags & RenderEngine::USE_HIGH_PRIORITY_CONTEXT);
+    if (useContextPriority) {
+        contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
+        contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
+    }
+    contextAttributes.push_back(EGL_NONE);
+
+    EGLContext ctxt = eglCreateContext(display, config, nullptr, contextAttributes.data());
+
+    // if can't create a GL context, we can only abort.
+    LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");
+
+    // now figure out what version of GL did we actually get
+    // NOTE: a dummy surface is not needed if KHR_create_context is supported
+
+    EGLConfig dummyConfig = config;
+    if (dummyConfig == EGL_NO_CONFIG) {
+        dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
+    }
+    EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
+    EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs);
+    LOG_ALWAYS_FATAL_IF(dummy == EGL_NO_SURFACE, "can't create dummy pbuffer");
+    EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
+    LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");
+
+    extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
+                                 glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));
+
+    GlesVersion version = parseGlesVersion(extensions.getVersion());
+
+    // initialize the renderer while GL is current
+
+    std::unique_ptr<GLES20RenderEngine> engine;
+    switch (version) {
+        case GLES_VERSION_1_0:
+        case GLES_VERSION_1_1:
+            LOG_ALWAYS_FATAL("SurfaceFlinger requires OpenGL ES 2.0 minimum to run.");
+            break;
+        case GLES_VERSION_2_0:
+        case GLES_VERSION_3_0:
+            engine = std::make_unique<GLES20RenderEngine>(featureFlags);
+            break;
+    }
+    engine->setEGLHandles(display, config, ctxt);
+
+    ALOGI("OpenGL ES informations:");
+    ALOGI("vendor    : %s", extensions.getVendor());
+    ALOGI("renderer  : %s", extensions.getRenderer());
+    ALOGI("version   : %s", extensions.getVersion());
+    ALOGI("extensions: %s", extensions.getExtensions());
+    ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize());
+    ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims());
+
+    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglDestroySurface(display, dummy);
+
+    return engine;
+}
+
+EGLConfig GLES20RenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
+    status_t err;
+    EGLConfig config;
+
+    // First try to get an ES2 config
+    err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
+    if (err != NO_ERROR) {
+        // If ES2 fails, try ES1
+        err = selectEGLConfig(display, format, EGL_OPENGL_ES_BIT, &config);
+        if (err != NO_ERROR) {
+            // still didn't work, probably because we're on the emulator...
+            // try a simplified query
+            ALOGW("no suitable EGLConfig found, trying a simpler query");
+            err = selectEGLConfig(display, format, 0, &config);
+            if (err != NO_ERROR) {
+                // this EGL is too lame for android
+                LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
+            }
+        }
+    }
+
+    if (logConfig) {
+        // print some debugging info
+        EGLint r, g, b, a;
+        eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
+        eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
+        eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
+        eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
+        ALOGI("EGL information:");
+        ALOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
+        ALOGI("version   : %s", eglQueryString(display, EGL_VERSION));
+        ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
+        ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS) ?: "Not Supported");
+        ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
+    }
+
+    return config;
+}
+
 GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags)
-      : RenderEngine(featureFlags),
+      : renderengine::impl::RenderEngine(featureFlags),
+        mEGLDisplay(EGL_NO_DISPLAY),
+        mEGLConfig(nullptr),
+        mEGLContext(EGL_NO_CONTEXT),
         mVpWidth(0),
         mVpHeight(0),
         mUseColorManagement(featureFlags & USE_COLOR_MANAGEMENT) {
@@ -154,7 +407,10 @@
     }
 }
 
-GLES20RenderEngine::~GLES20RenderEngine() {}
+GLES20RenderEngine::~GLES20RenderEngine() {
+    eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglTerminate(mEGLDisplay);
+}
 
 std::unique_ptr<Framebuffer> GLES20RenderEngine::createFramebuffer() {
     return std::make_unique<GLFramebuffer>(*this);
@@ -278,35 +534,35 @@
     return true;
 }
 
-void GLES20RenderEngine::fillRegionWithColor(const Region& region, uint32_t height, float red,
-                                             float green, float blue, float alpha) {
+void GLES20RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
+    glClearColor(red, green, blue, alpha);
+    glClear(GL_COLOR_BUFFER_BIT);
+}
+
+void GLES20RenderEngine::fillRegionWithColor(const Region& region, 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 + 0].y = r->top;
         position[i * 6 + 1].x = r->left;
-        position[i * 6 + 1].y = height - r->bottom;
+        position[i * 6 + 1].y = r->bottom;
         position[i * 6 + 2].x = r->right;
-        position[i * 6 + 2].y = height - r->bottom;
+        position[i * 6 + 2].y = r->bottom;
         position[i * 6 + 3].x = r->left;
-        position[i * 6 + 3].y = height - r->top;
+        position[i * 6 + 3].y = r->top;
         position[i * 6 + 4].x = r->right;
-        position[i * 6 + 4].y = height - r->bottom;
+        position[i * 6 + 4].y = r->bottom;
         position[i * 6 + 5].x = r->right;
-        position[i * 6 + 5].y = height - r->top;
+        position[i * 6 + 5].y = 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);
@@ -632,12 +888,37 @@
 }
 
 void GLES20RenderEngine::dump(String8& result) {
-    RenderEngine::dump(result);
+    const GLExtensions& extensions = GLExtensions::getInstance();
+
+    result.appendFormat("EGL implementation : %s\n", extensions.getEGLVersion());
+    result.appendFormat("%s\n", extensions.getEGLExtensions());
+
+    result.appendFormat("GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
+                        extensions.getVersion());
+    result.appendFormat("%s\n", extensions.getExtensions());
     result.appendFormat("RenderEngine last dataspace conversion: (%s) to (%s)\n",
                         dataspaceDetails(static_cast<android_dataspace>(mDataSpace)).c_str(),
                         dataspaceDetails(static_cast<android_dataspace>(mOutputDataSpace)).c_str());
 }
 
+GLES20RenderEngine::GlesVersion GLES20RenderEngine::parseGlesVersion(const char* str) {
+    int major, minor;
+    if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
+        if (sscanf(str, "OpenGL ES %d.%d", &major, &minor) != 2) {
+            ALOGW("Unable to parse GL_VERSION string: \"%s\"", str);
+            return GLES_VERSION_1_0;
+        }
+    }
+
+    if (major == 1 && minor == 0) return GLES_VERSION_1_0;
+    if (major == 1 && minor >= 1) return GLES_VERSION_1_1;
+    if (major == 2 && minor >= 0) return GLES_VERSION_2_0;
+    if (major == 3 && minor >= 0) return GLES_VERSION_3_0;
+
+    ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor);
+    return GLES_VERSION_1_0;
+}
+
 bool GLES20RenderEngine::isHdrDataSpace(const Dataspace dataSpace) const {
     const Dataspace standard = static_cast<Dataspace>(dataSpace & Dataspace::STANDARD_MASK);
     const Dataspace transfer = static_cast<Dataspace>(dataSpace & Dataspace::TRANSFER_MASK);
@@ -665,6 +946,12 @@
     return (isInputHdrDataSpace || isOutputHdrDataSpace) && inputTransfer != outputTransfer;
 }
 
+void GLES20RenderEngine::setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt) {
+    mEGLDisplay = display;
+    mEGLConfig = config;
+    mEGLContext = ctxt;
+}
+
 }  // namespace gl
 }  // namespace renderengine
 }  // namespace android
diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
index 04dc1b1..1abc5ba 100644
--- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
@@ -20,10 +20,14 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
 #include <GLES2/gl2.h>
 #include <renderengine/RenderEngine.h>
 #include <renderengine/private/Description.h>
 
+#define EGL_NO_CONFIG ((EGLConfig)0)
+
 namespace android {
 
 class String8;
@@ -40,6 +44,9 @@
 
 class GLES20RenderEngine : public impl::RenderEngine {
 public:
+    static std::unique_ptr<GLES20RenderEngine> create(int hwcFormat, uint32_t featureFlags);
+    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
+
     GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag
     ~GLES20RenderEngine() override;
 
@@ -55,8 +62,8 @@
     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 fillRegionWithColor(const Region& region, 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;
@@ -67,19 +74,16 @@
     void unbindFrameBuffer(Framebuffer* framebuffer) override;
     void checkErrors() const override;
 
+    // internal to RenderEngine
+    EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
+    EGLConfig getEGLConfig() const { return mEGLConfig; }
+
 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;
@@ -87,17 +91,37 @@
     void disableTexturing() override;
     void disableBlending() override;
 
+    // HDR and 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;
+
+    // drawing
     void drawMesh(const Mesh& mesh) override;
 
     size_t getMaxTextureSize() const override;
     size_t getMaxViewportDims() const override;
 
 private:
+    enum GlesVersion {
+        GLES_VERSION_1_0 = 0x10000,
+        GLES_VERSION_1_1 = 0x10001,
+        GLES_VERSION_2_0 = 0x20000,
+        GLES_VERSION_3_0 = 0x30000,
+    };
+
+    static GlesVersion parseGlesVersion(const char* str);
+
     // 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;
+    void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt);
 
+    EGLDisplay mEGLDisplay;
+    EGLConfig mEGLConfig;
+    EGLContext mEGLContext;
     GLuint mProtectedTexName;
     GLint mMaxViewportDims[2];
     GLint mMaxTextureSize;
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
index 2e2ba1c..17d8782 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
@@ -21,8 +21,6 @@
 #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>
@@ -30,7 +28,10 @@
 #include <ui/GraphicTypes.h>
 #include <ui/Transform.h>
 
-#define EGL_NO_CONFIG ((EGLConfig)0)
+/**
+ * Allows to set RenderEngine backend to GLES (default) or Vulkan (NOT yet supported).
+ */
+#define PROPERTY_DEBUG_RENDERENGINE_BACKEND "debug.renderengine.backend"
 
 struct ANativeWindowBuffer;
 
@@ -59,6 +60,8 @@
         USE_HIGH_PRIORITY_CONTEXT = 1 << 1, // Use high priority context
     };
 
+    static std::unique_ptr<impl::RenderEngine> create(int hwcFormat, uint32_t featureFlags);
+
     virtual ~RenderEngine() = 0;
 
     virtual std::unique_ptr<Framebuffer> createFramebuffer() = 0;
@@ -90,10 +93,9 @@
     virtual bool waitFence(base::unique_fd fenceFd) = 0;
 
     virtual void clearWithColor(float red, float green, float blue, float alpha) = 0;
-    virtual void fillRegionWithColor(const Region& region, uint32_t height, float red, float green,
+    virtual void fillRegionWithColor(const Region& region, float red, float green,
                                      float blue, float alpha) = 0;
 
-    // common to all GL versions
     virtual void setScissor(uint32_t left, uint32_t bottom, uint32_t right, uint32_t top) = 0;
     virtual void disableScissor() = 0;
     virtual void genTextures(size_t count, uint32_t* names) = 0;
@@ -155,43 +157,18 @@
 
 namespace impl {
 
+// impl::RenderEngine contains common implementation that is graphics back-end agnostic.
 class RenderEngine : public renderengine::RenderEngine {
-protected:
-    enum GlesVersion {
-        GLES_VERSION_1_0 = 0x10000,
-        GLES_VERSION_1_1 = 0x10001,
-        GLES_VERSION_2_0 = 0x20000,
-        GLES_VERSION_3_0 = 0x30000,
-    };
-    static GlesVersion parseGlesVersion(const char* str);
-
-    EGLDisplay mEGLDisplay;
-    EGLConfig mEGLConfig;
-    EGLContext mEGLContext;
-    void setEGLHandles(EGLDisplay display, EGLConfig config, EGLContext ctxt);
-
-    RenderEngine(uint32_t featureFlags);
-
-    const uint32_t mFeatureFlags;
-
 public:
     virtual ~RenderEngine() = 0;
 
-    static std::unique_ptr<RenderEngine> create(int hwcFormat, uint32_t featureFlags);
-
-    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
-
-    // dump the extension strings. always call the base class.
-    void dump(String8& result) override;
-
     bool useNativeFenceSync() const override;
     bool useWaitSync() const override;
-
     void setupColorTransform(const mat4& /* colorTransform */) override {}
 
-    // internal to RenderEngine
-    EGLDisplay getEGLDisplay() const;
-    EGLConfig getEGLConfig() const;
+protected:
+    RenderEngine(uint32_t featureFlags);
+    const uint32_t mFeatureFlags;
 };
 
 }  // namespace impl
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index bb85f4c..54e19c7 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -39,7 +39,7 @@
 Scheduler::~Scheduler() = default;
 
 sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
-        const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+        const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
         impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
         impl::EventThread::InterceptVSyncsCallback interceptCallback) {
     const int64_t id = sNextId++;
@@ -56,13 +56,15 @@
 }
 
 std::unique_ptr<EventThread> Scheduler::makeEventThread(
-        const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+        const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
         impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
         impl::EventThread::InterceptVSyncsCallback interceptCallback) {
+    const std::string sourceName = connectionName + "Source";
     std::unique_ptr<VSyncSource> eventThreadSource =
-            std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, connectionName);
+            std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, sourceName.c_str());
+    const std::string threadName = connectionName + "Thread";
     return std::make_unique<impl::EventThread>(std::move(eventThreadSource), resyncCallback,
-                                               interceptCallback, connectionName);
+                                               interceptCallback, threadName.c_str());
 }
 
 sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 8efbff4..fcb46e6 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -56,7 +56,7 @@
 
     /** Creates an EventThread connection. */
     sp<ConnectionHandle> createConnection(
-            const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+            const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
             impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
             impl::EventThread::InterceptVSyncsCallback interceptCallback);
     sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle);
@@ -79,7 +79,7 @@
 
 protected:
     virtual std::unique_ptr<EventThread> makeEventThread(
-            const char* connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
+            const std::string& connectionName, DispSync* dispSync, int64_t phaseOffsetNs,
             impl::EventThread::ResyncWithRateLimitCallback resyncCallback,
             impl::EventThread::InterceptVSyncsCallback interceptCallback);
 
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index 7dfad43..ea8ca4c 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -67,6 +67,14 @@
         mAppEventThread = appEventThread;
     }
 
+    void setSchedulerAndHandles(Scheduler* scheduler,
+                                Scheduler::ConnectionHandle* appConnectionHandle,
+                                Scheduler::ConnectionHandle* sfConnectionHandle) {
+        mScheduler = scheduler;
+        mAppConnectionHandle = appConnectionHandle;
+        mSfConnectionHandle = sfConnectionHandle;
+    }
+
     void setTransactionStart(TransactionStart transactionStart) {
         if (transactionStart == TransactionStart::EARLY) {
             mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT;
@@ -108,11 +116,19 @@
 
         bool changed = false;
         if (desired.sf != current.sf) {
-            mSfEventThread->setPhaseOffset(desired.sf);
+            if (mSfConnectionHandle != nullptr) {
+                mScheduler->setPhaseOffset(mSfConnectionHandle, desired.sf);
+            } else {
+                mSfEventThread->setPhaseOffset(desired.sf);
+            }
             changed = true;
         }
         if (desired.app != current.app) {
-            mAppEventThread->setPhaseOffset(desired.app);
+            if (mSfConnectionHandle != nullptr) {
+                mScheduler->setPhaseOffset(mAppConnectionHandle, desired.app);
+            } else {
+                mAppEventThread->setPhaseOffset(desired.app);
+            }
             changed = true;
         }
 
@@ -138,6 +154,10 @@
     EventThread* mSfEventThread = nullptr;
     EventThread* mAppEventThread = nullptr;
 
+    Scheduler* mScheduler = nullptr;
+    Scheduler::ConnectionHandle* mAppConnectionHandle = nullptr;
+    Scheduler::ConnectionHandle* mSfConnectionHandle = nullptr;
+
     std::atomic<Offsets> mOffsets;
 
     std::atomic<TransactionStart> mTransactionStart = TransactionStart::NORMAL;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a5bd73a..9537ccc 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -632,8 +632,8 @@
                                              });
 
         mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
-        mVsyncModulator.setEventThreads(mScheduler->getEventThread(mSfConnectionHandle),
-                                        mScheduler->getEventThread(mAppConnectionHandle));
+        mVsyncModulator.setSchedulerAndHandles(mScheduler.get(), mAppConnectionHandle.get(),
+                                               mSfConnectionHandle.get());
     } else {
         mEventThreadSource =
                 std::make_unique<DispSyncSource>(mPrimaryDispSync.get(),
@@ -667,8 +667,8 @@
 
     // TODO(b/77156734): We need to stop casting and use HAL types when possible.
     getBE().mRenderEngine =
-        renderengine::impl::RenderEngine::create(static_cast<int32_t>(compositionPixelFormat),
-                                                 renderEngineFeature);
+        renderengine::RenderEngine::create(static_cast<int32_t>(compositionPixelFormat),
+                                           renderEngineFeature);
     LOG_ALWAYS_FATAL_IF(getBE().mRenderEngine == nullptr, "couldn't create RenderEngine");
 
     LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
@@ -1688,9 +1688,8 @@
             doComposeSurfaces(display);
 
             // and draw the dirty region
-            const int32_t height = display->getHeight();
             auto& engine(getRenderEngine());
-            engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1);
+            engine.fillRegionWithColor(dirtyRegion, 1, 0, 1, 1);
 
             display->swapBuffers(getHwComposer());
         }
@@ -3194,7 +3193,7 @@
             // screen is already cleared here
             if (!region.isEmpty()) {
                 // can happen with SurfaceView
-                drawWormhole(display, region);
+                drawWormhole(region);
             }
         }
 
@@ -3231,9 +3230,10 @@
                 case HWC2::Composition::Sideband:
                 case HWC2::Composition::SolidColor: {
                     const Layer::State& state(compositionInfo.layer->mLayer->getDrawingState());
-                    const bool opaque = compositionInfo.layer->mLayer->isOpaque(state);
-                    if (compositionInfo.hwc.clearClientTarget && !firstLayer &&
-                            opaque && (state.color.a == 1.0f) && hasClientComposition) {
+                    const bool opaque = compositionInfo.layer->mLayer->isOpaque(state) &&
+                                        compositionInfo.layer->mLayer->getAlpha() == 1.0f;
+                    if (compositionInfo.hwc.clearClientTarget && !firstLayer && opaque &&
+                            hasClientComposition) {
                         // never clear the very first layer since we're
                         // guaranteed the FB is already cleared
                         compositionInfo.layer->clear(getRenderEngine());
@@ -3262,11 +3262,9 @@
     return true;
 }
 
-void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& display,
-                                  const Region& region) const {
-    const int32_t height = display->getHeight();
+void SurfaceFlinger::drawWormhole(const Region& region) const {
     auto& engine(getRenderEngine());
-    engine.fillRegionWithColor(region, height, 0, 0, 0, 0);
+    engine.fillRegionWithColor(region, 0, 0, 0, 0);
 }
 
 status_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 72ede93..00ee2c4 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -710,7 +710,7 @@
 
     void postFramebuffer(const sp<DisplayDevice>& display);
     void postFrame();
-    void drawWormhole(const sp<const DisplayDevice>& display, const Region& region) const;
+    void drawWormhole(const Region& region) const;
 
     /* ------------------------------------------------------------------------
      * Display management
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index a8b7770..6fe52d3 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -1,4 +1,4 @@
-// Copyright (C) 2018 The Android Open Source Project
+// Copyright 2018 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -16,6 +16,12 @@
     name: "libsurfaceflinger_unittest",
     defaults: ["libsurfaceflinger_defaults"],
     test_suites: ["device-tests"],
+    sanitize: {
+        // Using the address sanitizer not only helps uncover issues in the code
+        // covered by the tests, but also covers some of the tricky injection of
+        // fakes the unit tests currently do.
+        address: true,
+    },
     srcs: [
         ":libsurfaceflinger_sources",
         "CompositionTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
index 9113171..4f1c99e 100644
--- a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
@@ -77,20 +77,23 @@
 }
 
 TEST(DisplayIdentificationTest, parseEdid) {
-    auto edid = parseEdid(asDisplayIdentificationData(kInternalEdid));
+    auto data = asDisplayIdentificationData(kInternalEdid);
+    auto edid = parseEdid(data);
     ASSERT_TRUE(edid);
     EXPECT_EQ(0x4ca3u, edid->manufacturerId);
     EXPECT_STREQ("SEC", edid->pnpId.data());
     // ASCII text should be used as fallback if display name and serial number are missing.
     EXPECT_EQ("121AT11-801", edid->displayName);
 
-    edid = parseEdid(asDisplayIdentificationData(kExternalEdid));
+    data = asDisplayIdentificationData(kExternalEdid);
+    edid = parseEdid(data);
     ASSERT_TRUE(edid);
     EXPECT_EQ(0x22f0u, edid->manufacturerId);
     EXPECT_STREQ("HWP", edid->pnpId.data());
     EXPECT_EQ("HP ZR30w", edid->displayName);
 
-    edid = parseEdid(asDisplayIdentificationData(kExternalEedid));
+    data = asDisplayIdentificationData(kExternalEedid);
+    edid = parseEdid(data);
     ASSERT_TRUE(edid);
     EXPECT_EQ(0x4c2du, edid->manufacturerId);
     EXPECT_STREQ("SAM", edid->pnpId.data());
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 32712c7..aa377af 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -662,7 +662,7 @@
 using SimpleHwcVirtualDisplayVariant = HwcVirtualDisplayVariant<1024, 768, Secure::TRUE>;
 using HwcVirtualDisplayCase =
         Case<SimpleHwcVirtualDisplayVariant, WideColorSupportNotConfiguredVariant,
-             HdrNotSupportedVariant<SimpleHwcVirtualDisplayVariant>, 
+             HdrNotSupportedVariant<SimpleHwcVirtualDisplayVariant>,
              NoPerFrameMetadataSupportVariant<SimpleHwcVirtualDisplayVariant>>;
 using WideColorP3ColorimetricDisplayCase =
         Case<PrimaryDisplayVariant, WideColorP3ColorimetricSupportedVariant<PrimaryDisplayVariant>,
@@ -1304,6 +1304,8 @@
     // Call Expectations
 
     EXPECT_CALL(*mComposer, isUsingVrComposer()).WillRepeatedly(Return(false));
+    EXPECT_CALL(*mComposer, getDisplayIdentificationData(Case::Display::HWC_DISPLAY_ID, _, _))
+            .Times(0);
 
     setupCommonCallExpectationsForDisconnectProcessing<Case>();
 
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index c809e82..df0d982 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -40,7 +40,7 @@
               : mEventThread(std::move(eventThread)) {}
 
         std::unique_ptr<EventThread> makeEventThread(
-                const char* /* connectionName */, DispSync* /* dispSync */,
+                const std::string& /* connectionName */, DispSync* /* dispSync */,
                 nsecs_t /* phaseOffsetNs */,
                 impl::EventThread::ResyncWithRateLimitCallback /* resyncCallback */,
                 impl::EventThread::InterceptVSyncsCallback /* interceptCallback */) override {
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
index 8d3be7f..39ed622 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
@@ -49,7 +49,7 @@
     MOCK_METHOD1(waitFence, bool(base::unique_fd*));
     bool waitFence(base::unique_fd fd) override { return waitFence(&fd); };
     MOCK_METHOD4(clearWithColor, void(float, float, float, float));
-    MOCK_METHOD6(fillRegionWithColor, void(const Region&, uint32_t, float, float, float, float));
+    MOCK_METHOD5(fillRegionWithColor, void(const Region&, float, float, float, float));
     MOCK_METHOD4(setScissor, void(uint32_t, uint32_t, uint32_t, uint32_t));
     MOCK_METHOD0(disableScissor, void());
     MOCK_METHOD2(genTextures, void(size_t, uint32_t*));
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index 76eca35..8817e8d 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -28,7 +28,7 @@
 // API version (major.minor.patch)
 define VERSION_MAJOR 1
 define VERSION_MINOR 1
-define VERSION_PATCH 82
+define VERSION_PATCH 84
 
 // API limits
 define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -221,6 +221,10 @@
 @extension("VK_EXT_shader_subgroup_vote") define VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION 1
 @extension("VK_EXT_shader_subgroup_vote") define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote"
 
+// 68
+@extension("VK_EXT_astc_decode_mode") define VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION 1
+@extension("VK_EXT_astc_decode_mode") define VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME "VK_EXT_astc_decode_mode"
+
 // 70
 @extension("VK_KHR_maintenance1") define VK_KHR_MAINTENANCE1_SPEC_VERSION 2
 @extension("VK_KHR_maintenance1") define VK_KHR_MAINTENANCE1_EXTENSION_NAME "VK_KHR_maintenance1"
@@ -437,6 +441,10 @@
 @extension("VK_AMD_shader_fragment_mask") define VK_AMD_SHADER_FRAGMENT_MASK_SPEC_VERSION 1
 @extension("VK_AMD_shader_fragment_mask") define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask"
 
+// 139
+@extension("VK_EXT_inline_uniform_block") define VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION 1
+@extension("VK_EXT_inline_uniform_block") define VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME "VK_EXT_inline_uniform_block"
+
 // 141
 @extension("VK_EXT_shader_stencil_export") define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1
 @extension("VK_EXT_shader_stencil_export") define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export"
@@ -526,8 +534,8 @@
 @extension("VK_AMD_shader_core_properties") define VK_AMD_SHADER_CORE_PROPERTIES_EXTENSION_NAME "VK_AMD_shader_core_properties"
 
 // 191
-@extension("VK_EXT_vertex_attribute_divisor") define VK_AMD_SHADER_CORE_PROPERTIES_SPEC_VERSION 1
-@extension("VK_EXT_vertex_attribute_divisor") define VK_AMD_BUFFER_MARKER_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor"
+@extension("VK_EXT_vertex_attribute_divisor") define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 2
+@extension("VK_EXT_vertex_attribute_divisor") define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor"
 
 // 199
 @extension("VK_NV_shader_subgroup_partitioned") define VK_NV_SHADER_SUBGROUP_PARTITIONED_SPEC_VERSION 1
@@ -537,6 +545,10 @@
 @extension("VK_NV_device_diagnostic_checkpoints") define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_SPEC_VERSION 2
 @extension("VK_NV_device_diagnostic_checkpoints") define VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME "VK_NV_device_diagnostic_checkpoints"
 
+// 212
+@extension("VK_KHR_vulkan_memory_model") define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 2
+@extension("VK_KHR_vulkan_memory_model") define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model"
+
 /////////////
 //  Types  //
 /////////////
@@ -697,6 +709,9 @@
     VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC               = 0x00000008,
     VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC               = 0x00000009,
     VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT                     = 0x0000000a,
+
+    //@extension("VK_EXT_inline_uniform_block") // 139
+    VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT             = 1000138000,
 }
 
 enum VkQueryType {
@@ -1416,6 +1431,10 @@
     //@extension("VK_NN_vi_surface") // 63
     VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN                 = 1000062000,
 
+    //@extension("VK_EXT_astc_decode_mode") // 68
+    VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT           = 1000067000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT  = 1000067001,
+
     //@extension("VK_KHR_device_group_creation") // 71
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR      = 1000070000,
     VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR       = 1000070001,
@@ -1595,6 +1614,12 @@
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000,
     VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001,
 
+    //@extension("VK_EXT_inline_uniform_block") // 139
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT     = 1000138000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT   = 1000138001,
+    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT         = 1000138002,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT  = 1000138003,
+
     //@extension("VK_EXT_sample_locations") // 144
     VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT                         = 1000143000,
     VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT       = 1000143001,
@@ -1667,10 +1692,14 @@
     //@extension("VK_EXT_vertex_attribute_divisor") // 191
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT   = 1000190000,
     VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT       = 1000190001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT     = 1000190002,
 
     //@extension("VK_NV_device_diagnostic_checkpoints") // 207
     VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV                        = 1000206000,
     VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV     = 1000206001,
+
+    //@extension("VK_KHR_vulkan_memory_model") // 212
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = 1000211000,
 }
 
 enum VkSubpassContents {
@@ -5354,6 +5383,20 @@
     void*                                       window
 }
 
+@extension("VK_EXT_astc_decode_mode") // 68
+class VkImageViewASTCDecodeModeEXT {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkFormat                                    decodeMode
+}
+
+@extension("VK_EXT_astc_decode_mode") // 68
+class VkPhysicalDeviceASTCDecodeFeaturesEXT {
+    VkStructureType                             sType
+    void*                                       pNext
+    VkBool32                                    decodeModeSharedExponent
+}
+
 @extension("VK_KHR_device_group_creation") // 71
 class VkPhysicalDeviceGroupPropertiesKHR {
     VkStructureType                                 sType
@@ -6386,6 +6429,40 @@
     VkBool32                                        filterMinmaxImageComponentMapping
 }
 
+@extension("VK_EXT_inline_uniform_block") // 139
+class VkPhysicalDeviceInlineUniformBlockFeaturesEXT {
+    VkStructureType                                 sType
+    void*                                           pNext
+    VkBool32                                        inlineUniformBlock
+    VkBool32                                        descriptorBindingInlineUniformBlockUpdateAfterBind
+}
+
+@extension("VK_EXT_inline_uniform_block") // 139
+class VkPhysicalDeviceInlineUniformBlockPropertiesEXT {
+    VkStructureType                                 sType
+    void*                                           pNext
+    u32                                             maxInlineUniformBlockSize
+    u32                                             maxPerStageDescriptorInlineUniformBlocks
+    u32                                             maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks
+    u32                                             maxDescriptorSetInlineUniformBlocks
+    u32                                             maxDescriptorSetUpdateAfterBindInlineUniformBlocks
+}
+
+@extension("VK_EXT_inline_uniform_block") // 139
+class VkWriteDescriptorSetInlineUniformBlockEXT {
+    VkStructureType                                 sType
+    const void*                                     pNext
+    u32                                             dataSize
+    const void*                                     pData
+}
+
+@extension("VK_EXT_inline_uniform_block") // 139
+class VkDescriptorPoolInlineUniformBlockCreateInfoEXT {
+    VkStructureType                                 sType
+    const void*                                     pNext
+    u32                                             maxInlineUniformBlockBindings
+}
+
 @extension("VK_EXT_sample_locations") // 144
 class VkSampleLocationEXT {
     f32                                             x
@@ -6796,6 +6873,14 @@
     const VkVertexInputBindingDivisorDescriptionEXT*    pVertexBindingDivisors
 }
 
+@extension("VK_EXT_vertex_attribute_divisor") // 191
+class VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT {
+    VkStructureType                                 sType
+    void*                                           pNext
+    VkBool32                                        vertexAttributeInstanceRateDivisor
+    VkBool32                                        vertexAttributeInstanceRateZeroDivisor
+}
+
 @extension("VK_NV_device_diagnostic_checkpoints") // 207
 class VkQueueFamilyCheckpointPropertiesNV {
     VkStructureType                                 sType
@@ -6811,6 +6896,14 @@
     void*                                           pCheckpointMarker
 }
 
+@extension("VK_KHR_vulkan_memory_model") // 212
+class VkPhysicalDeviceVulkanMemoryModelFeaturesKHR {
+    VkStructureType                                 sType
+    void*                                           pNext
+    VkBool32                                        vulkanMemoryModel
+    VkBool32                                        vulkanMemoryModelDeviceScope
+}
+
 
 ////////////////
 //  Commands  //
diff --git a/vulkan/include/vulkan/vulkan_core.h b/vulkan/include/vulkan/vulkan_core.h
index d511015..fe45014 100644
--- a/vulkan/include/vulkan/vulkan_core.h
+++ b/vulkan/include/vulkan/vulkan_core.h
@@ -43,7 +43,7 @@
 #define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
 #define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
 // Version of this file
-#define VK_HEADER_VERSION 82
+#define VK_HEADER_VERSION 84
 
 
 #define VK_NULL_HANDLE 0
@@ -305,6 +305,8 @@
     VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000,
     VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000,
     VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN = 1000062000,
+    VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT = 1000067000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT = 1000067001,
     VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073000,
     VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR = 1000073001,
     VK_STRUCTURE_TYPE_MEMORY_WIN32_HANDLE_PROPERTIES_KHR = 1000073002,
@@ -380,6 +382,10 @@
     VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID = 1000129005,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT = 1000130000,
     VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT = 1000130001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT = 1000138000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT = 1000138001,
+    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT = 1000138002,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO_EXT = 1000138003,
     VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT = 1000143000,
     VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT = 1000143001,
     VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT = 1000143002,
@@ -406,8 +412,11 @@
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_AMD = 1000185000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT = 1000190000,
     VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT = 1000190001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT = 1000190002,
     VK_STRUCTURE_TYPE_CHECKPOINT_DATA_NV = 1000206000,
     VK_STRUCTURE_TYPE_QUEUE_FAMILY_CHECKPOINT_PROPERTIES_NV = 1000206001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR = 1000211000,
+    VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
     VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES,
@@ -442,6 +451,7 @@
     VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES,
     VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO,
+    VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO_KHR = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
     VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES_KHR = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
     VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO_KHR = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
@@ -1120,6 +1130,7 @@
     VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8,
     VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9,
     VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10,
+    VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT = 1000138000,
     VK_DESCRIPTOR_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_TYPE_SAMPLER,
     VK_DESCRIPTOR_TYPE_END_RANGE = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
     VK_DESCRIPTOR_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT - VK_DESCRIPTOR_TYPE_SAMPLER + 1),
@@ -4575,7 +4586,6 @@
 
 #define VK_KHR_SURFACE_SPEC_VERSION       25
 #define VK_KHR_SURFACE_EXTENSION_NAME     "VK_KHR_surface"
-#define VK_COLORSPACE_SRGB_NONLINEAR_KHR  VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
 
 
 typedef enum VkColorSpaceKHR {
@@ -4594,6 +4604,7 @@
     VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT = 1000104012,
     VK_COLOR_SPACE_PASS_THROUGH_EXT = 1000104013,
     VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT = 1000104014,
+    VK_COLORSPACE_SRGB_NONLINEAR_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
     VK_COLOR_SPACE_BEGIN_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
     VK_COLOR_SPACE_END_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
     VK_COLOR_SPACE_RANGE_SIZE_KHR = (VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR + 1),
@@ -5981,13 +5992,24 @@
 
 
 
+#define VK_KHR_vulkan_memory_model 1
+#define VK_KHR_VULKAN_MEMORY_MODEL_SPEC_VERSION 2
+#define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME "VK_KHR_vulkan_memory_model"
+
+typedef struct VkPhysicalDeviceVulkanMemoryModelFeaturesKHR {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           vulkanMemoryModel;
+    VkBool32           vulkanMemoryModelDeviceScope;
+} VkPhysicalDeviceVulkanMemoryModelFeaturesKHR;
+
+
+
 #define VK_EXT_debug_report 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
 
 #define VK_EXT_DEBUG_REPORT_SPEC_VERSION  9
 #define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
-#define VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
-#define VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT
 
 
 typedef enum VkDebugReportObjectTypeEXT {
@@ -6027,6 +6049,8 @@
     VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT = 33,
     VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT = 1000156000,
     VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT,
+    VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT,
     VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_EXT,
     VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_KHR_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION_EXT,
     VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
@@ -6431,6 +6455,24 @@
 #define VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME "VK_EXT_shader_subgroup_vote"
 
 
+#define VK_EXT_astc_decode_mode 1
+#define VK_EXT_ASTC_DECODE_MODE_SPEC_VERSION 1
+#define VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME "VK_EXT_astc_decode_mode"
+
+typedef struct VkImageViewASTCDecodeModeEXT {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkFormat           decodeMode;
+} VkImageViewASTCDecodeModeEXT;
+
+typedef struct VkPhysicalDeviceASTCDecodeFeaturesEXT {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           decodeModeSharedExponent;
+} VkPhysicalDeviceASTCDecodeFeaturesEXT;
+
+
+
 #define VK_EXT_conditional_rendering 1
 #define VK_EXT_CONDITIONAL_RENDERING_SPEC_VERSION 1
 #define VK_EXT_CONDITIONAL_RENDERING_EXTENSION_NAME "VK_EXT_conditional_rendering"
@@ -6746,7 +6788,6 @@
 #define VK_EXT_display_surface_counter 1
 #define VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION 1
 #define VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME "VK_EXT_display_surface_counter"
-#define VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT
 
 
 typedef enum VkSurfaceCounterFlagBitsEXT {
@@ -7300,6 +7341,42 @@
 #define VK_AMD_SHADER_FRAGMENT_MASK_EXTENSION_NAME "VK_AMD_shader_fragment_mask"
 
 
+#define VK_EXT_inline_uniform_block 1
+#define VK_EXT_INLINE_UNIFORM_BLOCK_SPEC_VERSION 1
+#define VK_EXT_INLINE_UNIFORM_BLOCK_EXTENSION_NAME "VK_EXT_inline_uniform_block"
+
+typedef struct VkPhysicalDeviceInlineUniformBlockFeaturesEXT {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           inlineUniformBlock;
+    VkBool32           descriptorBindingInlineUniformBlockUpdateAfterBind;
+} VkPhysicalDeviceInlineUniformBlockFeaturesEXT;
+
+typedef struct VkPhysicalDeviceInlineUniformBlockPropertiesEXT {
+    VkStructureType    sType;
+    void*              pNext;
+    uint32_t           maxInlineUniformBlockSize;
+    uint32_t           maxPerStageDescriptorInlineUniformBlocks;
+    uint32_t           maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks;
+    uint32_t           maxDescriptorSetInlineUniformBlocks;
+    uint32_t           maxDescriptorSetUpdateAfterBindInlineUniformBlocks;
+} VkPhysicalDeviceInlineUniformBlockPropertiesEXT;
+
+typedef struct VkWriteDescriptorSetInlineUniformBlockEXT {
+    VkStructureType    sType;
+    const void*        pNext;
+    uint32_t           dataSize;
+    const void*        pData;
+} VkWriteDescriptorSetInlineUniformBlockEXT;
+
+typedef struct VkDescriptorPoolInlineUniformBlockCreateInfoEXT {
+    VkStructureType    sType;
+    const void*        pNext;
+    uint32_t           maxInlineUniformBlockBindings;
+} VkDescriptorPoolInlineUniformBlockCreateInfoEXT;
+
+
+
 #define VK_EXT_shader_stencil_export 1
 #define VK_EXT_SHADER_STENCIL_EXPORT_SPEC_VERSION 1
 #define VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME "VK_EXT_shader_stencil_export"
@@ -7483,7 +7560,6 @@
 
 #define VK_EXT_VALIDATION_CACHE_SPEC_VERSION 1
 #define VK_EXT_VALIDATION_CACHE_EXTENSION_NAME "VK_EXT_validation_cache"
-#define VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT
 
 
 typedef enum VkValidationCacheHeaderVersionEXT {
@@ -7734,7 +7810,7 @@
 
 
 #define VK_EXT_vertex_attribute_divisor 1
-#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 2
+#define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_SPEC_VERSION 3
 #define VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME "VK_EXT_vertex_attribute_divisor"
 
 typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT {
@@ -7755,6 +7831,13 @@
     const VkVertexInputBindingDivisorDescriptionEXT*    pVertexBindingDivisors;
 } VkPipelineVertexInputDivisorStateCreateInfoEXT;
 
+typedef struct VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT {
+    VkStructureType    sType;
+    void*              pNext;
+    VkBool32           vertexAttributeInstanceRateDivisor;
+    VkBool32           vertexAttributeInstanceRateZeroDivisor;
+} VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT;
+
 
 
 #define VK_NV_shader_subgroup_partitioned 1
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index 96c5563..b32977a 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -165,8 +165,13 @@
     std::lock_guard<std::mutex> lock(mutex_);
     if (--refcount_ == 0) {
         ALOGV("closing layer library '%s'", path_.c_str());
-        dlclose(dlhandle_);
-        dlhandle_ = nullptr;
+        std::string error_msg;
+        if (!android::CloseNativeLibrary(dlhandle_, native_bridge_, &error_msg)) {
+            ALOGE("failed to unload library '%s': %s", path_.c_str(), error_msg.c_str());
+            refcount_++;
+        } else {
+           dlhandle_ = nullptr;
+        }
     }
 }