Merge "SF: Scheduler add strong typing helpers."
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 657dfb6..b87582e 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2526,6 +2526,8 @@
         return RunStatus::OK;
     }
 
+    MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
+            calling_uid, calling_package.c_str());
     if (options_->bugreport_fd.get() != -1) {
         // If the output needs to be copied over to the caller's fd, get user consent.
         android::String16 package(calling_package.c_str());
@@ -2703,10 +2705,10 @@
         FinalizeFile();
     }
 
-    // Share the final file with the caller if the user has consented.
+    // Share the final file with the caller if the user has consented or Shell is the caller.
     Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
     if (options_->bugreport_fd.get() != -1) {
-        status = CopyBugreportIfUserConsented();
+        status = CopyBugreportIfUserConsented(calling_uid);
         if (status != Dumpstate::RunStatus::OK &&
             status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
             // Do an early return if there were errors. We make an exception for consent
@@ -2776,6 +2778,9 @@
 }
 
 void Dumpstate::CheckUserConsent(int32_t calling_uid, const android::String16& calling_package) {
+    if (calling_uid == AID_SHELL) {
+        return;
+    }
     consent_callback_ = new ConsentCallback();
     const String16 incidentcompanion("incidentcompanion");
     sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
@@ -2810,10 +2815,15 @@
     return USER_CONSENT_DENIED;
 }
 
-Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented() {
+Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
     // If the caller has asked to copy the bugreport over to their directory, we need explicit
-    // user consent.
-    UserConsentResult consent_result = consent_callback_->getResult();
+    // user consent (unless the caller is Shell).
+    UserConsentResult consent_result;
+    if (calling_uid == AID_SHELL) {
+        consent_result = UserConsentResult::APPROVED;
+    } else {
+        consent_result = consent_callback_->getResult();
+    }
     if (consent_result == UserConsentResult::UNAVAILABLE) {
         // User has not responded yet.
         uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 5ba84ca..430936e 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -498,8 +498,9 @@
 
     RunStatus HandleUserConsentDenied();
 
-    // Copies bugreport artifacts over to the caller's directories provided there is user consent.
-    RunStatus CopyBugreportIfUserConsented();
+    // Copies bugreport artifacts over to the caller's directories provided there is user consent or
+    // called by Shell.
+    RunStatus CopyBugreportIfUserConsented(int32_t calling_uid);
 
     // Used by GetInstance() only.
     explicit Dumpstate(const std::string& version = VERSION_CURRENT);
diff --git a/headers/media_plugin/media/openmax/OMX_VideoExt.h b/headers/media_plugin/media/openmax/OMX_VideoExt.h
index 435fcc8..dc37bbd 100644
--- a/headers/media_plugin/media/openmax/OMX_VideoExt.h
+++ b/headers/media_plugin/media/openmax/OMX_VideoExt.h
@@ -291,18 +291,19 @@
 
 /** Dolby Vision Profile enum type */
 typedef enum OMX_VIDEO_DOLBYVISIONPROFILETYPE {
-    OMX_VIDEO_DolbyVisionProfileUnknown = 0x0,
-    OMX_VIDEO_DolbyVisionProfileDvavPer = 0x1,
-    OMX_VIDEO_DolbyVisionProfileDvavPen = 0x2,
-    OMX_VIDEO_DolbyVisionProfileDvheDer = 0x4,
-    OMX_VIDEO_DolbyVisionProfileDvheDen = 0x8,
-    OMX_VIDEO_DolbyVisionProfileDvheDtr = 0x10,
-    OMX_VIDEO_DolbyVisionProfileDvheStn = 0x20,
-    OMX_VIDEO_DolbyVisionProfileDvheDth = 0x40,
-    OMX_VIDEO_DolbyVisionProfileDvheDtb = 0x80,
-    OMX_VIDEO_DolbyVisionProfileDvheSt  = 0x100,
-    OMX_VIDEO_DolbyVisionProfileDvavSe  = 0x200,
-    OMX_VIDEO_DolbyVisionProfileMax     = 0x7FFFFFFF
+    OMX_VIDEO_DolbyVisionProfileUnknown  = 0x0,
+    OMX_VIDEO_DolbyVisionProfileDvavPer  = 0x1,
+    OMX_VIDEO_DolbyVisionProfileDvavPen  = 0x2,
+    OMX_VIDEO_DolbyVisionProfileDvheDer  = 0x4,
+    OMX_VIDEO_DolbyVisionProfileDvheDen  = 0x8,
+    OMX_VIDEO_DolbyVisionProfileDvheDtr  = 0x10,
+    OMX_VIDEO_DolbyVisionProfileDvheStn  = 0x20,
+    OMX_VIDEO_DolbyVisionProfileDvheDth  = 0x40,
+    OMX_VIDEO_DolbyVisionProfileDvheDtb  = 0x80,
+    OMX_VIDEO_DolbyVisionProfileDvheSt   = 0x100,
+    OMX_VIDEO_DolbyVisionProfileDvavSe   = 0x200,
+    OMX_VIDEO_DolbyVisionProfileDvav110  = 0x400,
+    OMX_VIDEO_DolbyVisionProfileMax      = 0x7FFFFFFF
 } OMX_VIDEO_DOLBYVISIONPROFILETYPE;
 
 /** Dolby Vision Level enum type */
diff --git a/libs/android_runtime_lazy/Android.bp b/libs/android_runtime_lazy/Android.bp
index 2d6292c..09a5f39 100644
--- a/libs/android_runtime_lazy/Android.bp
+++ b/libs/android_runtime_lazy/Android.bp
@@ -52,10 +52,6 @@
         "libutils",
     ],
 
-    required: [
-        "libandroid_runtime",
-    ],
-
     export_include_dirs: [
         "include",
     ],
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index 9da9c13..60f047f 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -115,18 +115,23 @@
 }
 
 int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) {
-    return noteOp(op, uid, callingPackage, String16("noteOp from native code"));
+    return noteOp(op, uid, callingPackage, String16(), String16());
 }
 
 int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage,
-        const String16& message) {
+        const String16& featureId, const String16& message) {
     sp<IAppOpsService> service = getService();
     int32_t mode = service != nullptr
             ? service->noteOperation(op, uid, callingPackage)
             : APP_OPS_MANAGER_UNAVAILABLE_MODE;
 
     if (mode == AppOpsManager::MODE_ALLOWED) {
-        markAppOpNoted(uid, callingPackage, op, message);
+        if (message.size() == 0) {
+            markAppOpNoted(uid, callingPackage, op, featureId,
+                    String16("noteOp from native code"));
+        } else {
+            markAppOpNoted(uid, callingPackage, op, featureId, message);
+        }
     }
 
     return mode;
@@ -134,19 +139,23 @@
 
 int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
         bool startIfModeDefault) {
-    return startOpNoThrow(op, uid, callingPackage, startIfModeDefault,
-            String16("startOpNoThrow from native code"));
+    return startOpNoThrow(op, uid, callingPackage, startIfModeDefault, String16(), String16());
 }
 
 int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
-        bool startIfModeDefault, const String16& message) {
+        bool startIfModeDefault, const String16& featureId, const String16& message) {
     sp<IAppOpsService> service = getService();
     int32_t mode = service != nullptr
             ? service->startOperation(getToken(service), op, uid, callingPackage,
                     startIfModeDefault) : APP_OPS_MANAGER_UNAVAILABLE_MODE;
 
     if (mode == AppOpsManager::MODE_ALLOWED) {
-        markAppOpNoted(uid, callingPackage, op, message);
+        if (message.size() == 0) {
+            markAppOpNoted(uid, callingPackage, op, featureId,
+                    String16("startOp from native code"));
+        } else {
+            markAppOpNoted(uid, callingPackage, op, featureId, message);
+        }
     }
 
     return mode;
@@ -198,7 +207,7 @@
 }
 
 void AppOpsManager::markAppOpNoted(int32_t uid, const String16& packageName, int32_t opCode,
-         const String16& message) {
+         const String16& featureId, const String16& message) {
     // check it the appops needs to be collected and cache result
     if (appOpsToNote[opCode] == 0) {
         if (shouldCollectNotes(opCode)) {
@@ -212,14 +221,16 @@
         return;
     }
 
-    noteAsyncOp(String16(), uid, packageName, opCode, message);
+    noteAsyncOp(String16(), uid, packageName, opCode, featureId, message);
 }
 
 void AppOpsManager::noteAsyncOp(const String16& callingPackageName, int32_t uid,
-         const String16& packageName, int32_t opCode, const String16& message) {
+         const String16& packageName, int32_t opCode, const String16& featureId,
+         const String16& message) {
     sp<IAppOpsService> service = getService();
     if (service != nullptr) {
-        return service->noteAsyncOp(callingPackageName, uid, packageName, opCode, message);
+        return service->noteAsyncOp(callingPackageName, uid, packageName, opCode, featureId,
+                message);
     }
 }
 
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 50c7053..238c9dc 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -214,16 +214,21 @@
 {
     // Once a binder has died, it will never come back to life.
     if (mAlive) {
+        bool privateVendor = flags & FLAG_PRIVATE_VENDOR;
+        // don't send userspace flags to the kernel
+        flags = flags & ~FLAG_PRIVATE_VENDOR;
+
         // user transactions require a given stability level
         if (code >= FIRST_CALL_TRANSACTION && code <= LAST_CALL_TRANSACTION) {
             using android::internal::Stability;
 
             auto stability = Stability::get(this);
+            auto required = privateVendor ? Stability::VENDOR : Stability::kLocalStability;
 
-            if (CC_UNLIKELY(!Stability::check(stability, Stability::kLocalStability))) {
+            if (CC_UNLIKELY(!Stability::check(stability, required))) {
                 ALOGE("Cannot do a user transaction on a %s binder in a %s context.",
                     Stability::stabilityString(stability).c_str(),
-                    Stability::stabilityString(Stability::kLocalStability).c_str());
+                    Stability::stabilityString(required).c_str());
                 return BAD_TYPE;
             }
         }
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
index 6c16c2d..9760e13 100644
--- a/libs/binder/IAppOpsService.cpp
+++ b/libs/binder/IAppOpsService.cpp
@@ -145,7 +145,8 @@
     }
 
     virtual void noteAsyncOp(const String16& callingPackageName, int32_t uid,
-            const String16& packageName, int32_t opCode, const String16& message) {
+            const String16& packageName, int32_t opCode, const String16& featureId,
+            const String16& message) {
         Parcel data, reply;
         data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
 
@@ -166,6 +167,14 @@
         }
 
         data.writeInt32(opCode);
+
+        // Convert empty featureId into null string
+        if (featureId.size() != 0) {
+            data.writeString16(featureId);
+        } else {
+            data.writeString16(nullptr, 0);
+        }
+
         data.writeString16(message);
         remote()->transact(NOTE_ASYNC_OP_TRANSACTION, data, &reply);
     }
@@ -291,8 +300,9 @@
             int32_t uid = data.readInt32();
             String16 packageName = data.readString16();
             int32_t opCode = data.readInt32();
+            String16 featureId = data.readString16();
             String16 message = data.readString16();
-            noteAsyncOp(callingPackageName, uid, packageName, opCode, message);
+            noteAsyncOp(callingPackageName, uid, packageName, opCode, featureId, message);
             reply->writeNoException();
             return NO_ERROR;
         } break;
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 573a038..323e079 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -50,10 +50,6 @@
 #include <private/binder/binder_module.h>
 #include "Static.h"
 
-#ifndef INT32_MAX
-#define INT32_MAX ((int32_t)(2147483647))
-#endif
-
 #define LOG_REFS(...)
 //#define LOG_REFS(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
 #define LOG_ALLOC(...)
@@ -750,61 +746,37 @@
   return writeUtf8AsUtf16(*str);
 }
 
-namespace {
-
-template<typename T>
-status_t writeByteVectorInternal(Parcel* parcel, const std::vector<T>& val)
-{
-    status_t status;
-    if (val.size() > std::numeric_limits<int32_t>::max()) {
-        status = BAD_VALUE;
-        return status;
+status_t Parcel::writeByteVectorInternal(const int8_t* data, size_t size) {
+    if (size > std::numeric_limits<int32_t>::max()) {
+        return BAD_VALUE;
     }
 
-    status = parcel->writeInt32(val.size());
+    status_t status = writeInt32(size);
     if (status != OK) {
         return status;
     }
 
-    void* data = parcel->writeInplace(val.size());
-    if (!data) {
-        status = BAD_VALUE;
-        return status;
-    }
-
-    memcpy(data, val.data(), val.size());
-    return status;
+    return write(data, size);
 }
 
-template<typename T>
-status_t writeByteVectorInternalPtr(Parcel* parcel,
-                                    const std::unique_ptr<std::vector<T>>& val)
-{
-    if (!val) {
-        return parcel->writeInt32(-1);
-    }
-
-    return writeByteVectorInternal(parcel, *val);
-}
-
-}  // namespace
-
 status_t Parcel::writeByteVector(const std::vector<int8_t>& val) {
-    return writeByteVectorInternal(this, val);
+    return writeByteVectorInternal(val.data(), val.size());
 }
 
 status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val)
 {
-    return writeByteVectorInternalPtr(this, val);
+    if (!val) return writeInt32(-1);
+    return writeByteVectorInternal(val->data(), val->size());
 }
 
 status_t Parcel::writeByteVector(const std::vector<uint8_t>& val) {
-    return writeByteVectorInternal(this, val);
+    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());
 }
 
 status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val)
 {
-    return writeByteVectorInternalPtr(this, val);
+    if (!val) return writeInt32(-1);
+    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
 }
 
 status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val)
@@ -1477,81 +1449,41 @@
     return err;
 }
 
-namespace {
-
-template<typename T>
-status_t readByteVectorInternal(const Parcel* parcel,
-                                std::vector<T>* val) {
-    val->clear();
-
-    int32_t size;
-    status_t status = parcel->readInt32(&size);
-
-    if (status != OK) {
-        return status;
+status_t Parcel::readByteVectorInternal(int8_t* data, size_t size) const {
+    if (size_t(size) > dataAvail()) {
+      return BAD_VALUE;
     }
-
-    if (size < 0) {
-        status = UNEXPECTED_NULL;
-        return status;
-    }
-    if (size_t(size) > parcel->dataAvail()) {
-        status = BAD_VALUE;
-        return status;
-    }
-
-    T* data = const_cast<T*>(reinterpret_cast<const T*>(parcel->readInplace(size)));
-    if (!data) {
-        status = BAD_VALUE;
-        return status;
-    }
-    val->reserve(size);
-    val->insert(val->end(), data, data + size);
-
-    return status;
+    return read(data, size);
 }
 
-template<typename T>
-status_t readByteVectorInternalPtr(
-        const Parcel* parcel,
-        std::unique_ptr<std::vector<T>>* val) {
-    const int32_t start = parcel->dataPosition();
-    int32_t size;
-    status_t status = parcel->readInt32(&size);
-    val->reset();
-
-    if (status != OK || size < 0) {
-        return status;
-    }
-
-    parcel->setDataPosition(start);
-    val->reset(new (std::nothrow) std::vector<T>());
-
-    status = readByteVectorInternal(parcel, val->get());
-
-    if (status != OK) {
-        val->reset();
-    }
-
-    return status;
-}
-
-}  // namespace
-
 status_t Parcel::readByteVector(std::vector<int8_t>* val) const {
-    return readByteVectorInternal(this, val);
+    if (status_t status = resizeOutVector(val); status != OK) return status;
+    return readByteVectorInternal(val->data(), val->size());
 }
 
 status_t Parcel::readByteVector(std::vector<uint8_t>* val) const {
-    return readByteVectorInternal(this, val);
+    if (status_t status = resizeOutVector(val); status != OK) return status;
+    return readByteVectorInternal(reinterpret_cast<int8_t*>(val->data()), val->size());
 }
 
 status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const {
-    return readByteVectorInternalPtr(this, val);
+    if (status_t status = resizeOutVector(val); status != OK) return status;
+    if (val->get() == nullptr) {
+        // resizeOutVector does not create the out vector if size is < 0.
+        // This occurs when writing a null byte vector.
+        return OK;
+    }
+    return readByteVectorInternal((*val)->data(), (*val)->size());
 }
 
 status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const {
-    return readByteVectorInternalPtr(this, val);
+    if (status_t status = resizeOutVector(val); status != OK) return status;
+    if (val->get() == nullptr) {
+        // resizeOutVector does not create the out vector if size is < 0.
+        // This occurs when writing a null byte vector.
+        return OK;
+    }
+    return readByteVectorInternal(reinterpret_cast<int8_t*>((*val)->data()), (*val)->size());
 }
 
 status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const {
@@ -2630,11 +2562,13 @@
             if (objectsSize == 0) {
                 free(mObjects);
                 mObjects = nullptr;
+                mObjectsCapacity = 0;
             } else {
                 binder_size_t* objects =
                     (binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t));
                 if (objects) {
                     mObjects = objects;
+                    mObjectsCapacity = objectsSize;
                 }
             }
             mObjectsSize = objectsSize;
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 136bdb0..b3afd81 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -4,6 +4,9 @@
       "name": "binderSafeInterfaceTest"
     },
     {
+      "name": "binderVendorDoubleLoadTest"
+    },
+    {
       "name": "binderDriverInterfaceTest"
     },
     {
@@ -14,6 +17,9 @@
     },
     {
       "name": "binderStabilityTest"
+    },
+    {
+      "name": "CtsNdkBinderTestCases"
     }
   ]
 }
diff --git a/libs/binder/fuzzer/Android.bp b/libs/binder/fuzzer/Android.bp
index 5a6955f..a9d2b75 100644
--- a/libs/binder/fuzzer/Android.bp
+++ b/libs/binder/fuzzer/Android.bp
@@ -1,5 +1,5 @@
-cc_defaults {
-    name: "binder_parcel_fuzzer_defaults",
+cc_fuzz {
+    name: "binder_parcel_fuzzer",
     defaults: ["libbinder_ndk_host_user"],
     host_supported: true,
     srcs: [
@@ -36,16 +36,8 @@
             ],
         },
     },
-    defaults_visibility: [":__subpackages__"],
-}
-
-cc_fuzz {
-    name: "binder_parcel_fuzzer",
-    defaults: ["binder_parcel_fuzzer_defaults"],
-}
-
-cc_fuzz {
-    name: "binder_parcel_fuzzer_logs",
-    defaults: ["binder_parcel_fuzzer_defaults"],
-    cflags: ["-DENABLE_LOG_FUZZ"],
+    // This flag enables verbose output in the fuzz target, and is very useful
+    // for debugging a failure. If you are trying to diagnose how a crash was
+    // produced, you may find uncommenting the below line very useful.
+    // cflags: ["-DENABLE_LOG_FUZZ"],
 }
diff --git a/libs/binder/fuzzer/binder.cpp b/libs/binder/fuzzer/binder.cpp
index 04fe0e7..52c730c 100644
--- a/libs/binder/fuzzer/binder.cpp
+++ b/libs/binder/fuzzer/binder.cpp
@@ -22,6 +22,10 @@
 
 using ::android::status_t;
 
+enum ByteEnum : int8_t {};
+enum IntEnum : int32_t {};
+enum LongEnum : int64_t {};
+
 class ExampleParcelable : public android::Parcelable {
 public:
     status_t writeToParcel(android::Parcel* /*parcel*/) const override {
@@ -80,6 +84,7 @@
     PARCEL_READ_WITH_STATUS(T, FUN), \
     PARCEL_READ_NO_STATUS(T, FUN)
 
+// clang-format off
 std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS {
     PARCEL_READ_NO_STATUS(size_t, dataSize),
     PARCEL_READ_NO_STATUS(size_t, dataAvail),
@@ -148,6 +153,14 @@
     PARCEL_READ_WITH_STATUS(android::sp<android::IBinder>, readStrongBinder),
     PARCEL_READ_WITH_STATUS(android::sp<android::IBinder>, readNullableStrongBinder),
 
+    // TODO(b/131868573): can force read of arbitrarily sized vector
+    // PARCEL_READ_WITH_STATUS(std::vector<ByteEnum>, readEnumVector),
+    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<ByteEnum>>, readEnumVector),
+    // PARCEL_READ_WITH_STATUS(std::vector<IntEnum>, readEnumVector),
+    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<IntEnum>>, readEnumVector),
+    // PARCEL_READ_WITH_STATUS(std::vector<LongEnum>, readEnumVector),
+    // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<LongEnum>>, readEnumVector),
+
     // only reading one parcelable type for now
     // TODO(b/131868573): can force read of arbitrarily sized vector
     // PARCEL_READ_WITH_STATUS(std::unique_ptr<std::vector<std::unique_ptr<ExampleParcelable>>>, readParcelableVector),
@@ -239,3 +252,4 @@
     PARCEL_READ_NO_STATUS(size_t, getBlobAshmemSize),
     PARCEL_READ_NO_STATUS(size_t, getOpenAshmemSize),
 };
+// clang-format on
diff --git a/libs/binder/fuzzer/hwbinder.cpp b/libs/binder/fuzzer/hwbinder.cpp
index b8cce72..0fec393 100644
--- a/libs/binder/fuzzer/hwbinder.cpp
+++ b/libs/binder/fuzzer/hwbinder.cpp
@@ -30,6 +30,9 @@
     return os;
 }
 
+#define PARCEL_READ_OPT_STATUS(T, FUN) \
+    PARCEL_READ_NO_STATUS(T, FUN), PARCEL_READ_WITH_STATUS(T, FUN)
+
 #define PARCEL_READ_NO_STATUS(T, FUN) \
     [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {\
         FUZZ_LOG() << "about to read " #T " using " #FUN " with no status";\
@@ -45,6 +48,7 @@
         FUZZ_LOG() << #T " status: " << status << " value: " << t;\
     }
 
+// clang-format off
 std::vector<ParcelRead<::android::hardware::Parcel>> HWBINDER_PARCEL_READ_FUNCTIONS {
     PARCEL_READ_NO_STATUS(size_t, dataSize),
     PARCEL_READ_NO_STATUS(size_t, dataAvail),
@@ -62,30 +66,44 @@
         FUZZ_LOG() << "enforceInterface status: " << okay;
     },
     PARCEL_READ_NO_STATUS(size_t, objectsCount),
+    [] (const ::android::hardware::Parcel& p, uint8_t length) {
+        FUZZ_LOG() << "about to read";
+        std::vector<uint8_t> data (length);
+        status_t status = p.read(data.data(), length);
+        FUZZ_LOG() << "read status: " << status << " data: " << hexString(data.data(), data.size());
+    },
+    [] (const ::android::hardware::Parcel& p, uint8_t length) {
+        FUZZ_LOG() << "about to read";
+        std::vector<uint8_t> data (length);
+        const void* inplace = p.readInplace(length);
+        FUZZ_LOG() << "read status: " << hexString(inplace, length);
+    },
     PARCEL_READ_WITH_STATUS(int8_t, readInt8),
     PARCEL_READ_WITH_STATUS(uint8_t, readUint8),
     PARCEL_READ_WITH_STATUS(int16_t, readInt16),
     PARCEL_READ_WITH_STATUS(uint16_t, readUint16),
-    PARCEL_READ_WITH_STATUS(int32_t, readInt32),
-    PARCEL_READ_WITH_STATUS(uint32_t, readUint32),
-    PARCEL_READ_WITH_STATUS(int64_t, readInt64),
-    PARCEL_READ_WITH_STATUS(uint64_t, readUint64),
-    PARCEL_READ_WITH_STATUS(float, readFloat),
-    PARCEL_READ_WITH_STATUS(double, readDouble),
-    PARCEL_READ_WITH_STATUS(bool, readBool),
-    PARCEL_READ_WITH_STATUS(::android::String16, readString16),
-    PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readStrongBinder),
-    PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readNullableStrongBinder),
-    [] (const ::android::hardware::Parcel& p, uint8_t amount) {
-        FUZZ_LOG() << "about to readInPlace " << amount;
-        const uint8_t* data = (const uint8_t*)p.readInplace(amount);
-        if (data) {
-            std::vector<uint8_t> vdata(data, data + amount);
-            FUZZ_LOG() << "readInPlace " << amount << " data: " << hexString(vdata);
-        } else {
-            FUZZ_LOG() << "readInPlace " << amount << " no data";
-        }
+    PARCEL_READ_OPT_STATUS(int32_t, readInt32),
+    PARCEL_READ_OPT_STATUS(uint32_t, readUint32),
+    PARCEL_READ_OPT_STATUS(int64_t, readInt64),
+    PARCEL_READ_OPT_STATUS(uint64_t, readUint64),
+    PARCEL_READ_OPT_STATUS(float, readFloat),
+    PARCEL_READ_OPT_STATUS(double, readDouble),
+    PARCEL_READ_OPT_STATUS(bool, readBool),
+    [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {
+        FUZZ_LOG() << "about to readCString";
+        const char* str = p.readCString();
+        FUZZ_LOG() << "readCString " << (str ? str : "<null>");
     },
+    PARCEL_READ_OPT_STATUS(::android::String16, readString16),
+    PARCEL_READ_WITH_STATUS(std::unique_ptr<::android::String16>, readString16),
+    [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {
+        FUZZ_LOG() << "about to readString16Inplace";
+        size_t outSize = 0;
+        const char16_t* str = p.readString16Inplace(&outSize);
+        FUZZ_LOG() << "readString16Inplace: " << hexString(str, sizeof(char16_t) * outSize);
+    },
+    PARCEL_READ_OPT_STATUS(::android::sp<::android::hardware::IBinder>, readStrongBinder),
+    PARCEL_READ_WITH_STATUS(::android::sp<::android::hardware::IBinder>, readNullableStrongBinder),
     [] (const ::android::hardware::Parcel& p, uint8_t size) {
         FUZZ_LOG() << "about to readBuffer";
         size_t handle = 0;
@@ -130,6 +148,28 @@
         // should be null since we don't create any IPC objects
         CHECK(data == nullptr) << data;
     },
+    [] (const ::android::hardware::Parcel& p, uint8_t size) {
+        FUZZ_LOG() << "about to readEmbeddedNativeHandle";
+        size_t parent_buffer_handle = size & 0xf;
+        size_t parent_offset = size >> 4;
+        const native_handle_t* handle = nullptr;
+        status_t status = p.readEmbeddedNativeHandle(parent_buffer_handle, parent_offset, &handle);
+        FUZZ_LOG() << "readEmbeddedNativeHandle status: " << status << " handle: " << handle << " handle: " << handle;
+
+        // should be null since we don't create any IPC objects
+        CHECK(handle == nullptr) << handle;
+    },
+    [] (const ::android::hardware::Parcel& p, uint8_t size) {
+        FUZZ_LOG() << "about to readNullableEmbeddedNativeHandle";
+        size_t parent_buffer_handle = size & 0xf;
+        size_t parent_offset = size >> 4;
+        const native_handle_t* handle = nullptr;
+        status_t status = p.readNullableEmbeddedNativeHandle(parent_buffer_handle, parent_offset, &handle);
+        FUZZ_LOG() << "readNullableEmbeddedNativeHandle status: " << status << " handle: " << handle << " handle: " << handle;
+
+        // should be null since we don't create any IPC objects
+        CHECK(handle == nullptr) << handle;
+    },
     [] (const ::android::hardware::Parcel& p, uint8_t /*data*/) {
         FUZZ_LOG() << "about to readNativeHandleNoDup";
         const native_handle_t* handle = nullptr;
@@ -150,3 +190,4 @@
         CHECK(handle == nullptr) << handle;
     },
 };
+// clang-format on
diff --git a/libs/binder/fuzzer/main.cpp b/libs/binder/fuzzer/main.cpp
index 929e2c3..6657edb 100644
--- a/libs/binder/fuzzer/main.cpp
+++ b/libs/binder/fuzzer/main.cpp
@@ -34,6 +34,9 @@
     P p;
     p.setData(input.data(), input.size());
 
+    // since we are only using a byte to index
+    CHECK(reads.size() <= 255) << reads.size();
+
     for (size_t i = 0; i < instructions.size() - 1; i += 2) {
         uint8_t a = instructions[i];
         uint8_t readIdx = a % reads.size();
@@ -74,6 +77,10 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
     if (size <= 1) return 0;  // no use
+
+    // avoid timeouts, see b/142617274, b/142473153
+    if (size > 50000) return 0;
+
     uint8_t options = *data;
     data++;
     size--;
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index 0ab40b8..2744ce1 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -130,16 +130,17 @@
     int32_t checkOp(int32_t op, int32_t uid, const String16& callingPackage);
     int32_t checkAudioOpNoThrow(int32_t op, int32_t usage, int32_t uid,
             const String16& callingPackage);
-    // @Deprecated, use noteOp(int32_t, int32_t uid, const String16&, const String16&) instead
+    // @Deprecated, use noteOp(int32_t, int32_t uid, const String16&, const String16&,
+    //              const String16&) instead
     int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage);
     int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage,
-            const String16& message);
-    // @Deprecated, use startOpNoThrow(int32_t, int32_t, const String16&, bool, const String16&)
-    // instead
+            const String16& featureId, const String16& message);
+    // @Deprecated, use startOpNoThrow(int32_t, int32_t, const String16&, bool, const String16&,
+    //              const String16&) instead
     int32_t startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
             bool startIfModeDefault);
     int32_t startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
-            bool startIfModeDefault, const String16& message);
+            bool startIfModeDefault, const String16& featureId, const String16& message);
     void finishOp(int32_t op, int32_t uid, const String16& callingPackage);
     void startWatchingMode(int32_t op, const String16& packageName,
             const sp<IAppOpsCallback>& callback);
@@ -147,7 +148,7 @@
     int32_t permissionToOpCode(const String16& permission);
     void setCameraAudioRestriction(int32_t mode);
     void noteAsyncOp(const String16& callingPackageName, int32_t uid, const String16& packageName,
-            int32_t opCode, const String16& message);
+            int32_t opCode, const String16& featureId, const String16& message);
 
 private:
     Mutex mLock;
@@ -155,7 +156,7 @@
 
     sp<IAppOpsService> getService();
     void markAppOpNoted(int32_t uid, const String16& packageName, int32_t opCode,
-            const String16& message);
+            const String16& featureId, const String16& message);
     bool shouldCollectNotes(int32_t opCode);
 };
 
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h
index 8b8a3c2..ad34bc5 100644
--- a/libs/binder/include/binder/IAppOpsService.h
+++ b/libs/binder/include/binder/IAppOpsService.h
@@ -49,7 +49,8 @@
             const String16& packageName) = 0;
     virtual void setCameraAudioRestriction(int32_t mode) = 0;
     virtual void noteAsyncOp(const String16& callingPackageName, int32_t uid,
-            const String16& packageName, int32_t opCode, const String16& message) = 0;
+            const String16& packageName, int32_t opCode, const String16& featureId,
+            const String16& message) = 0;
     virtual bool shouldCollectNotes(int32_t opCode) = 0;
 
     enum {
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index 64f3052..64604b7 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -62,7 +62,11 @@
         DEBUG_PID_TRANSACTION   = B_PACK_CHARS('_', 'P', 'I', 'D'),
 
         // Corresponds to TF_ONE_WAY -- an asynchronous call.
-        FLAG_ONEWAY             = 0x00000001
+        FLAG_ONEWAY             = 0x00000001,
+
+        // Private userspace flag for transaction which is being requested from
+        // a vendor context.
+        FLAG_PRIVATE_VENDOR     = 0x10000000,
     };
 
                           IBinder();
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 8726681..0f8abab 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -19,6 +19,7 @@
 
 #include <map> // for legacy reasons
 #include <string>
+#include <type_traits>
 #include <vector>
 
 #include <android-base/unique_fd.h>
@@ -157,6 +158,18 @@
     status_t            writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val);
     status_t            writeStrongBinderVector(const std::vector<sp<IBinder>>& val);
 
+    // Write an Enum vector with underlying type int8_t.
+    // Does not use padding; each byte is contiguous.
+    template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+    status_t            writeEnumVector(const std::vector<T>& val);
+    template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+    status_t            writeEnumVector(const std::unique_ptr<std::vector<T>>& val);
+    // Write an Enum vector with underlying type != int8_t.
+    template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+    status_t            writeEnumVector(const std::vector<T>& val);
+    template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+    status_t            writeEnumVector(const std::unique_ptr<std::vector<T>>& val);
+
     template<typename T>
     status_t            writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val);
     template<typename T>
@@ -275,6 +288,19 @@
     status_t            readStrongBinder(sp<IBinder>* val) const;
     status_t            readNullableStrongBinder(sp<IBinder>* val) const;
 
+
+    // Read an Enum vector with underlying type int8_t.
+    // Does not use padding; each byte is contiguous.
+    template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+    status_t            readEnumVector(std::vector<T>* val) const;
+    template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+    status_t            readEnumVector(std::unique_ptr<std::vector<T>>* val) const;
+    // Read an Enum vector with underlying type != int8_t.
+    template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+    status_t            readEnumVector(std::vector<T>* val) const;
+    template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
+    status_t            readEnumVector(std::unique_ptr<std::vector<T>>* val) const;
+
     template<typename T>
     status_t            readParcelableVector(
                             std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const;
@@ -438,6 +464,19 @@
     status_t            writeRawNullableParcelable(const Parcelable*
                                                    parcelable);
 
+    template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0>
+    status_t            writeEnum(const T& val);
+    template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0>
+    status_t            writeEnum(const T& val);
+
+    template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool> = 0>
+    status_t            readEnum(T* pArg) const;
+    template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool> = 0>
+    status_t            readEnum(T* pArg) const;
+
+    status_t writeByteVectorInternal(const int8_t* data, size_t size);
+    status_t readByteVectorInternal(int8_t* data, size_t size) const;
+
     template<typename T, typename U>
     status_t            unsafeReadTypedVector(std::vector<T>* val,
                                               status_t(Parcel::*read_func)(U*) const) const;
@@ -913,6 +952,66 @@
     return unsafeWriteTypedVector(*val, &Parcel::writeNullableParcelable<T>);
 }
 
+template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
+status_t Parcel::writeEnum(const T& val) {
+    return writeInt32(static_cast<int32_t>(val));
+}
+template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>>
+status_t Parcel::writeEnum(const T& val) {
+    return writeInt64(static_cast<int64_t>(val));
+}
+
+template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::writeEnumVector(const std::vector<T>& val) {
+    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size());
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) {
+    if (!val) return writeInt32(-1);
+    return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size());
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::writeEnumVector(const std::vector<T>& val) {
+    return writeTypedVector(val, &Parcel::writeEnum);
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::writeEnumVector(const std::unique_ptr<std::vector<T>>& val) {
+    return writeNullableTypedVector(val, &Parcel::writeEnum);
+}
+
+template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
+status_t Parcel::readEnum(T* pArg) const {
+    return readInt32(reinterpret_cast<int32_t *>(pArg));
+}
+template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int64_t>, bool>>
+status_t Parcel::readEnum(T* pArg) const {
+    return readInt64(reinterpret_cast<int64_t *>(pArg));
+}
+
+template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::readEnumVector(std::vector<T>* val) const {
+    if (status_t status = resizeOutVector(val); status != OK) return status;
+    return readByteVectorInternal(reinterpret_cast<int8_t*>(val->data()), val->size());
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
+    if (status_t status = resizeOutVector(val); status != OK) return status;
+    if (val->get() == nullptr) {
+        // resizeOutVector does not create the out vector if size is < 0.
+        // This occurs when writing a null Enum vector.
+        return OK;
+    }
+    return readByteVectorInternal(reinterpret_cast<int8_t*>((*val)->data()), (*val)->size());
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::readEnumVector(std::vector<T>* val) const {
+    return readTypedVector(val, &Parcel::readEnum);
+}
+template<typename T, std::enable_if_t<std::is_enum_v<T> && !std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool>>
+status_t Parcel::readEnumVector(std::unique_ptr<std::vector<T>>* val) const {
+    return readNullableTypedVector(val, &Parcel::readEnum);
+}
+
 // ---------------------------------------------------------------------------
 
 inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index b06ca86..e752c45 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -17,6 +17,7 @@
 #include <android/binder_ibinder.h>
 #include "ibinder_internal.h"
 
+#include <android/binder_stability.h>
 #include <android/binder_status.h>
 #include "parcel_internal.h"
 #include "status_internal.h"
@@ -542,7 +543,8 @@
         return STATUS_UNKNOWN_TRANSACTION;
     }
 
-    if ((flags & ~FLAG_ONEWAY) != 0) {
+    constexpr binder_flags_t kAllFlags = FLAG_PRIVATE_VENDOR | FLAG_ONEWAY;
+    if ((flags & ~kAllFlags) != 0) {
         LOG(ERROR) << __func__ << ": Unrecognized flags sent: " << flags;
         return STATUS_BAD_VALUE;
     }
diff --git a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
index c6868b0..dc3c8d2 100644
--- a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -201,7 +201,22 @@
     /**
      * See AStatus_isOk.
      */
-    bool isOk() { return get() != nullptr && AStatus_isOk(get()); }
+    bool isOk() const { return get() != nullptr && AStatus_isOk(get()); }
+
+    /**
+     * See AStatus_getExceptionCode
+     */
+    binder_exception_t getExceptionCode() const { return AStatus_getExceptionCode(get()); }
+
+    /**
+     * See AStatus_getServiceSpecificError
+     */
+    int32_t getServiceSpecificError() const { return AStatus_getServiceSpecificError(get()); }
+
+    /**
+     * See AStatus_getStatus
+     */
+    binder_status_t getStatus() const { return AStatus_getStatus(get()); }
 
     /**
      * Convenience method for okay status.
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
index b03fce1..e1a8cfd 100644
--- a/libs/binder/ndk/include_platform/android/binder_stability.h
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -20,7 +20,21 @@
 
 __BEGIN_DECLS
 
-#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+/**
+ * Private addition to binder_flag_t.
+ */
+enum {
+    /**
+     * Indicates that this transaction is coupled w/ vendor.img
+     */
+    FLAG_PRIVATE_VENDOR = 0x10000000,
+};
+
+#if (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
+
+enum {
+    FLAG_PRIVATE_LOCAL = FLAG_PRIVATE_VENDOR,
+};
 
 /**
  * This interface has the stability of the vendor image.
@@ -33,6 +47,10 @@
 
 #else  // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
 
+enum {
+    FLAG_PRIVATE_LOCAL = 0,
+};
+
 /**
  * This interface has the stability of the system image.
  */
diff --git a/libs/binder/ndk/test/Android.bp b/libs/binder/ndk/test/Android.bp
index bb1fe2f..1c5dba3 100644
--- a/libs/binder/ndk/test/Android.bp
+++ b/libs/binder/ndk/test/Android.bp
@@ -67,3 +67,31 @@
     srcs: ["main_server.cpp"],
     gtest: false,
 }
+
+cc_test {
+    name: "binderVendorDoubleLoadTest",
+    vendor: true,
+    srcs: [
+        "binderVendorDoubleLoadTest.cpp",
+    ],
+    static_libs: [
+        "IBinderVendorDoubleLoadTest-cpp",
+        "IBinderVendorDoubleLoadTest-ndk_platform",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libbinder_ndk",
+        "libutils",
+    ],
+    test_suites: ["device-tests"],
+}
+
+aidl_interface {
+    name: "IBinderVendorDoubleLoadTest",
+    // TODO(b/119771576): only vendor is needed
+    vendor_available: true,
+    srcs: [
+        "IBinderVendorDoubleLoadTest.aidl",
+    ],
+}
diff --git a/libs/binder/ndk/test/AndroidTest.xml b/libs/binder/ndk/test/AndroidTest.xml
new file mode 100644
index 0000000..89646f7
--- /dev/null
+++ b/libs/binder/ndk/test/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs binderVendorDoubleLoadTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="binderVendorDoubleLoadTest->/data/nativetest/vendor/binderVendorDoubleLoadTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/nativetest/vendor" />
+        <option name="module-name" value="binderVendorDoubleLoadTest" />
+    </test>
+</configuration>
+
diff --git a/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl b/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl
new file mode 100644
index 0000000..3a5bd9c
--- /dev/null
+++ b/libs/binder/ndk/test/IBinderVendorDoubleLoadTest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+interface IBinderVendorDoubleLoadTest {
+    @utf8InCpp String RepeatString(@utf8InCpp String toRepeat);
+}
diff --git a/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp b/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp
new file mode 100644
index 0000000..f72dc36
--- /dev/null
+++ b/libs/binder/ndk/test/binderVendorDoubleLoadTest.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <BnBinderVendorDoubleLoadTest.h>
+#include <aidl/BnBinderVendorDoubleLoadTest.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/binder_stability.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <binder/Stability.h>
+#include <binder/Status.h>
+#include <gtest/gtest.h>
+
+#include <sys/prctl.h>
+
+using namespace android;
+using ::android::base::EndsWith;
+using ::android::base::GetProperty;
+using ::android::base::Split;
+using ::android::binder::Status;
+using ::android::internal::Stability;
+using ::ndk::ScopedAStatus;
+using ::ndk::SharedRefBase;
+using ::ndk::SpAIBinder;
+
+static const std::string kLocalNdkServerName = "NdkServer-local-IBinderVendorDoubleLoadTest";
+static const std::string kRemoteNdkServerName = "NdkServer-remote-IBinderVendorDoubleLoadTest";
+
+class NdkServer : public aidl::BnBinderVendorDoubleLoadTest {
+    ScopedAStatus RepeatString(const std::string& in, std::string* out) override {
+        *out = in;
+        return ScopedAStatus::ok();
+    }
+};
+class CppServer : public BnBinderVendorDoubleLoadTest {
+    Status RepeatString(const std::string& in, std::string* out) override {
+        *out = in;
+        return Status::ok();
+    }
+};
+
+TEST(DoubleBinder, VendorCppCantCallIntoSystem) {
+    Vector<String16> services = defaultServiceManager()->listServices();
+    EXPECT_TRUE(services.empty());
+}
+
+TEST(DoubleBinder, VendorCppCantRegisterService) {
+    sp<CppServer> cppServer = new CppServer;
+    status_t status = defaultServiceManager()->addService(String16("anything"), cppServer);
+    EXPECT_EQ(EX_TRANSACTION_FAILED, status);
+}
+
+TEST(DoubleBinder, CppVendorCantManuallyMarkVintfStability) {
+    // this test also implies that stability logic is turned on in vendor
+    ASSERT_DEATH(
+            {
+                sp<IBinder> binder = new CppServer();
+                Stability::markVintf(binder.get());
+            },
+            "Should only mark known object.");
+}
+
+TEST(DoubleBinder, NdkVendorCantManuallyMarkVintfStability) {
+    // this test also implies that stability logic is turned on in vendor
+    ASSERT_DEATH(
+            {
+                std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
+                AIBinder_markVintfStability(ndkServer->asBinder().get());
+            },
+            "Should only mark known object.");
+}
+
+TEST(DoubleBinder, CallIntoNdk) {
+    for (const std::string& serviceName : {kLocalNdkServerName, kRemoteNdkServerName}) {
+        SpAIBinder binder = SpAIBinder(AServiceManager_checkService(serviceName.c_str()));
+        ASSERT_NE(nullptr, binder.get()) << serviceName;
+        EXPECT_EQ(STATUS_OK, AIBinder_ping(binder.get())) << serviceName;
+
+        std::shared_ptr<aidl::IBinderVendorDoubleLoadTest> server =
+                aidl::IBinderVendorDoubleLoadTest::fromBinder(binder);
+
+        ASSERT_NE(nullptr, server.get()) << serviceName;
+
+        EXPECT_EQ(STATUS_OK, AIBinder_ping(server->asBinder().get()));
+
+        std::string outString;
+        ScopedAStatus status = server->RepeatString("foo", &outString);
+        EXPECT_EQ(STATUS_OK, AStatus_getExceptionCode(status.get())) << serviceName;
+        EXPECT_EQ("foo", outString) << serviceName;
+    }
+}
+
+void initDrivers() {
+    // Explicitly instantiated with the same driver that system would use.
+    // __ANDROID_VNDK__ right now uses /dev/vndbinder by default.
+    ProcessState::initWithDriver("/dev/binder");
+    ProcessState::self()->startThreadPool();
+    ABinderProcess_startThreadPool();
+}
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+
+    if (fork() == 0) {
+        // child process
+
+        prctl(PR_SET_PDEATHSIG, SIGHUP);
+
+        initDrivers();
+
+        // REMOTE SERVERS
+        std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
+        CHECK(STATUS_OK == AServiceManager_addService(ndkServer->asBinder().get(),
+                                                      kRemoteNdkServerName.c_str()));
+
+        // OR sleep forever or whatever, it doesn't matter
+        IPCThreadState::self()->joinThreadPool(true);
+        exit(1);  // should not reach
+    }
+
+    sleep(1);
+
+    initDrivers();
+
+    // LOCAL SERVERS
+    std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
+    AServiceManager_addService(ndkServer->asBinder().get(), kLocalNdkServerName.c_str());
+
+    return RUN_ALL_TESTS();
+}
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 3a369cd..9a50175 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -64,7 +64,7 @@
                                                    : Fence::NO_FENCE);
         mNextCallbackBufferItem = BufferItem();
     }
-    mDequeueWaitCV.notify_one();
+    mDequeueWaitCV.notify_all();
     decStrong((void*)transactionCallbackThunk);
 }
 
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index a5f115e..db1ac24 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -18,8 +18,14 @@
 
 #include <gui/BLASTBufferQueue.h>
 
+#include <android/hardware/graphics/common/1.2/types.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/IProducerListener.h>
 #include <gui/SurfaceComposerClient.h>
+#include <private/gui/ComposerService.h>
+#include <ui/DisplayInfo.h>
 #include <ui/GraphicBuffer.h>
+#include <ui/GraphicTypes.h>
 
 #include <gtest/gtest.h>
 
@@ -27,10 +33,8 @@
 
 namespace android {
 
-const int DEFAULT_WIDTH = 100;
-const int DEFAULT_HEIGHT = 100;
-
 using Transaction = SurfaceComposerClient::Transaction;
+using android::hardware::graphics::common::V1_2::BufferUsage;
 
 class BLASTBufferQueueHelper {
 public:
@@ -47,12 +51,24 @@
     }
 
     int getWidth() { return mBlastBufferQueueAdapter->mWidth; }
+
     int getHeight() { return mBlastBufferQueueAdapter->mHeight; }
+
     Transaction* getNextTransaction() { return mBlastBufferQueueAdapter->mNextTransaction; }
+
+    sp<IGraphicBufferProducer> getIGraphicBufferProducer() {
+        return mBlastBufferQueueAdapter->getIGraphicBufferProducer();
+    }
+
     const sp<SurfaceControl> getSurfaceControl() {
         return mBlastBufferQueueAdapter->mSurfaceControl;
     }
 
+    void waitForCallback() {
+        std::unique_lock lock{mBlastBufferQueueAdapter->mMutex};
+        mBlastBufferQueueAdapter->mDequeueWaitCV.wait_for(lock, 1s);
+    }
+
 private:
     sp<BLASTBufferQueue> mBlastBufferQueueAdapter;
 };
@@ -73,39 +89,149 @@
     }
 
     void SetUp() {
+        mComposer = ComposerService::getComposerService();
         mClient = new SurfaceComposerClient();
-        mSurfaceControl = mClient->createSurface(String8("TestSurface"), DEFAULT_WIDTH,
-                                                 DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_8888);
+        mDisplayToken = mClient->getInternalDisplayToken();
+        ASSERT_NE(nullptr, mDisplayToken.get());
+        Transaction t;
+        t.setDisplayLayerStack(mDisplayToken, 0);
+        t.apply();
+        t.clear();
+
+        DisplayInfo info;
+        ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mDisplayToken, &info));
+        mDisplayWidth = info.w;
+        mDisplayHeight = info.h;
+
+        mSurfaceControl = mClient->createSurface(String8("TestSurface"), mDisplayWidth,
+                                                 mDisplayHeight, PIXEL_FORMAT_RGBA_8888,
+                                                 ISurfaceComposerClient::eFXSurfaceBufferState,
+                                                 /*parent*/ nullptr);
+        t.setLayerStack(mSurfaceControl, 0)
+                .setLayer(mSurfaceControl, std::numeric_limits<int32_t>::max())
+                .setFrame(mSurfaceControl, Rect(0, 0, mDisplayWidth, mDisplayHeight))
+                .show(mSurfaceControl)
+                .setDataspace(mSurfaceControl, ui::Dataspace::V0_SRGB)
+                .apply();
+    }
+
+    void fillBuffer(uint32_t* bufData, uint32_t width, uint32_t height, uint32_t stride, uint8_t r,
+                    uint8_t g, uint8_t b) {
+        for (uint32_t row = 0; row < height; row++) {
+            for (uint32_t col = 0; col < width; col++) {
+                uint8_t* pixel = (uint8_t*)(bufData + (row * stride) + col);
+                *pixel = r;
+                *(pixel + 1) = g;
+                *(pixel + 2) = b;
+                *(pixel + 3) = 255;
+            }
+        }
+    }
+
+    void checkScreenCapture(uint8_t r, uint8_t g, uint8_t b) {
+        const auto width = mScreenCaptureBuf->getWidth();
+        const auto height = mScreenCaptureBuf->getHeight();
+        const auto stride = mScreenCaptureBuf->getStride();
+
+        uint32_t* bufData;
+        mScreenCaptureBuf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_READ_OFTEN),
+                                reinterpret_cast<void**>(&bufData));
+
+        for (uint32_t row = 0; row < height; row++) {
+            for (uint32_t col = 0; col < width; col++) {
+                uint8_t* pixel = (uint8_t*)(bufData + (row * stride) + col);
+                EXPECT_EQ(r, *(pixel));
+                EXPECT_EQ(g, *(pixel + 1));
+                EXPECT_EQ(b, *(pixel + 2));
+            }
+        }
+        mScreenCaptureBuf->unlock();
+        ASSERT_EQ(false, ::testing::Test::HasFailure());
     }
 
     sp<SurfaceComposerClient> mClient;
+    sp<ISurfaceComposer> mComposer;
+
+    sp<IBinder> mDisplayToken;
+
     sp<SurfaceControl> mSurfaceControl;
+    sp<GraphicBuffer> mScreenCaptureBuf;
+
+    uint32_t mDisplayWidth;
+    uint32_t mDisplayHeight;
 };
 
 TEST_F(BLASTBufferQueueTest, CreateBLASTBufferQueue) {
     // create BLASTBufferQueue adapter associated with this surface
-    BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
     ASSERT_EQ(mSurfaceControl, adapter.getSurfaceControl());
-    ASSERT_EQ(DEFAULT_WIDTH, adapter.getWidth());
-    ASSERT_EQ(DEFAULT_HEIGHT, adapter.getHeight());
+    ASSERT_EQ(mDisplayWidth, adapter.getWidth());
+    ASSERT_EQ(mDisplayHeight, adapter.getHeight());
     ASSERT_EQ(nullptr, adapter.getNextTransaction());
 }
 
 TEST_F(BLASTBufferQueueTest, Update) {
-    BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
     sp<SurfaceControl> updateSurface =
-            mClient->createSurface(String8("UpdateTest"), DEFAULT_WIDTH / 2, DEFAULT_HEIGHT / 2,
-                                   PIXEL_FORMAT_RGB_888);
-    adapter.update(updateSurface, DEFAULT_WIDTH / 2, DEFAULT_HEIGHT / 2);
+            mClient->createSurface(String8("UpdateTest"), mDisplayWidth / 2, mDisplayHeight / 2,
+                                   PIXEL_FORMAT_RGBA_8888);
+    adapter.update(updateSurface, mDisplayWidth / 2, mDisplayHeight / 2);
     ASSERT_EQ(updateSurface, adapter.getSurfaceControl());
-    ASSERT_EQ(DEFAULT_WIDTH / 2, adapter.getWidth());
-    ASSERT_EQ(DEFAULT_HEIGHT / 2, adapter.getHeight());
+    ASSERT_EQ(mDisplayWidth / 2, adapter.getWidth());
+    ASSERT_EQ(mDisplayHeight / 2, adapter.getHeight());
 }
 
 TEST_F(BLASTBufferQueueTest, SetNextTransaction) {
-    BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
     Transaction next;
     adapter.setNextTransaction(&next);
     ASSERT_EQ(&next, adapter.getNextTransaction());
 }
+
+TEST_F(BLASTBufferQueueTest, onFrameAvailable_Apply) {
+    uint8_t r = 255;
+    uint8_t g = 0;
+    uint8_t b = 0;
+
+    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
+    auto igbProducer = adapter.getIGraphicBufferProducer();
+    ASSERT_NE(nullptr, igbProducer.get());
+    IGraphicBufferProducer::QueueBufferOutput qbOutput;
+    ASSERT_EQ(NO_ERROR,
+              igbProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
+                                   &qbOutput));
+    ASSERT_EQ(NO_ERROR, igbProducer->setMaxDequeuedBufferCount(3));
+
+    int slot;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buf;
+    auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight,
+                                          PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                          nullptr, nullptr);
+    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
+    ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
+
+    uint32_t* bufData;
+    buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
+              reinterpret_cast<void**>(&bufData));
+    fillBuffer(bufData, buf->getWidth(), buf->getHeight(), buf->getStride(), r, g, b);
+    buf->unlock();
+
+    IGraphicBufferProducer::QueueBufferInput input(systemTime(), false, HAL_DATASPACE_UNKNOWN,
+                                                   Rect(mDisplayWidth, mDisplayHeight),
+                                                   NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
+                                                   Fence::NO_FENCE);
+    igbProducer->queueBuffer(slot, input, &qbOutput);
+
+    adapter.waitForCallback();
+
+    // capture screen and verify that it is red
+    bool capturedSecureLayers;
+    ASSERT_EQ(NO_ERROR,
+              mComposer->captureScreen(mDisplayToken, &mScreenCaptureBuf, capturedSecureLayers,
+                                       ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(),
+                                       mDisplayWidth, mDisplayHeight,
+                                       /*useIdentityTransform*/ false));
+    ASSERT_NO_FATAL_FAILURE(checkScreenCapture(r, g, b));
+}
 } // namespace android
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 09eeaea..03b9cd7 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -405,12 +405,11 @@
     surface->expectTap(1, 1);
 }
 
-/**
- * TODO(b/139494112) fix tests once we define expected behavior
- *
-// Ensure we send the input to the right surface when the surface visibility changes due to the
-// first buffer being submitted. ref: b/120839715
-TEST_F(InputSurfacesTest, input_respects_buffer_layer_buffer) {
+// TODO(b/139494112) update tests once we define expected behavior
+// Ensure we still send input to the surface regardless of surface visibility changes due to the
+// first buffer being submitted or alpha changes.
+// Original bug ref: b/120839715
+TEST_F(InputSurfacesTest, input_ignores_buffer_layer_buffer) {
     std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
     std::unique_ptr<InputSurface> bufferSurface =
             InputSurface::makeBufferInputSurface(mComposerClient, 100, 100);
@@ -419,14 +418,14 @@
     bufferSurface->showAt(10, 10);
 
     injectTap(11, 11);
-    bgSurface->expectTap(1, 1);
+    bufferSurface->expectTap(1, 1);
 
     postBuffer(bufferSurface->mSurfaceControl);
     injectTap(11, 11);
     bufferSurface->expectTap(1, 1);
 }
 
-TEST_F(InputSurfacesTest, input_respects_buffer_layer_alpha) {
+TEST_F(InputSurfacesTest, input_ignores_buffer_layer_alpha) {
     std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
     std::unique_ptr<InputSurface> bufferSurface =
             InputSurface::makeBufferInputSurface(mComposerClient, 100, 100);
@@ -441,10 +440,10 @@
     bufferSurface->doTransaction([](auto &t, auto &sc) { t.setAlpha(sc, 0.0); });
 
     injectTap(11, 11);
-    bgSurface->expectTap(1, 1);
+    bufferSurface->expectTap(1, 1);
 }
 
-TEST_F(InputSurfacesTest, input_respects_color_layer_alpha) {
+TEST_F(InputSurfacesTest, input_ignores_color_layer_alpha) {
     std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
     std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100);
 
@@ -457,9 +456,8 @@
     fgSurface->doTransaction([](auto &t, auto &sc) { t.setAlpha(sc, 0.0); });
 
     injectTap(11, 11);
-    bgSurface->expectTap(1, 1);
+    fgSurface->expectTap(1, 1);
 }
-*/
 
 TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) {
     std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100);
diff --git a/libs/math/include/math/quat.h b/libs/math/include/math/quat.h
index 1936a2b..07573c5 100644
--- a/libs/math/include/math/quat.h
+++ b/libs/math/include/math/quat.h
@@ -109,7 +109,7 @@
 
     // initialize from 4 values to w + xi + yj + zk
     template<typename A, typename B, typename C, typename D>
-    constexpr TQuaternion(A w, B x, C y, D z) : x(x), y(y), z(z), w(w) { }
+    constexpr TQuaternion(A w, B x, C y, D z) : x(static_cast<T>(x)), y(static_cast<T>(y)), z(static_cast<T>(z)), w(static_cast<T>(w)) { }
 
     // initialize from a vec3 + a value to : v.xi + v.yj + v.zk + w
     template<typename A, typename B>
diff --git a/libs/math/include/math/vec2.h b/libs/math/include/math/vec2.h
index a347633..e0adb7f 100644
--- a/libs/math/include/math/vec2.h
+++ b/libs/math/include/math/vec2.h
@@ -89,7 +89,7 @@
     constexpr TVec2(A v) : x(v), y(v) { }
 
     template<typename A, typename B>
-    constexpr TVec2(A x, B y) : x(x), y(y) { }
+    constexpr TVec2(A x, B y) : x(static_cast<T>(x)), y(static_cast<T>(y)) { }
 
     template<typename A>
     explicit
diff --git a/libs/math/include/math/vec3.h b/libs/math/include/math/vec3.h
index 009fd84..21fb684 100644
--- a/libs/math/include/math/vec3.h
+++ b/libs/math/include/math/vec3.h
@@ -86,13 +86,13 @@
 
     // handles implicit conversion to a tvec4. must not be explicit.
     template<typename A, typename = typename std::enable_if<std::is_arithmetic<A>::value >::type>
-    constexpr TVec3(A v) : x(v), y(v), z(v) { }
+    constexpr TVec3(A v) : x(static_cast<T>(v)), y(static_cast<T>(v)), z(static_cast<T>(v)) { }
 
     template<typename A, typename B, typename C>
-    constexpr TVec3(A x, B y, C z) : x(x), y(y), z(z) { }
+    constexpr TVec3(A x, B y, C z) : x(static_cast<T>(x)), y(static_cast<T>(y)), z(static_cast<T>(z)) { }
 
     template<typename A, typename B>
-    constexpr TVec3(const TVec2<A>& v, B z) : x(v.x), y(v.y), z(z) { }
+    constexpr TVec3(const TVec2<A>& v, B z) : x(v.x), y(v.y), z(static_cast<T>(z)) { }
 
     template<typename A>
     explicit
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index 9bd3095..1ec73ce 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -266,10 +266,10 @@
 
     char buf[CMSG_SPACE(kFdBufferSize)];
     struct msghdr msg = {
-            .msg_control = buf,
-            .msg_controllen = sizeof(buf),
             .msg_iov = &iov[0],
             .msg_iovlen = 1,
+            .msg_control = buf,
+            .msg_controllen = sizeof(buf),
     };
 
     struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
@@ -306,10 +306,10 @@
     iov[0].iov_len = kMessageBufferSize;
 
     struct msghdr msg = {
-            .msg_control = fdBuf,
-            .msg_controllen = sizeof(fdBuf),
             .msg_iov = &iov[0],
             .msg_iovlen = 1,
+            .msg_control = fdBuf,
+            .msg_controllen = sizeof(fdBuf),
     };
 
     int result;
diff --git a/libs/ui/ColorSpace.cpp b/libs/ui/ColorSpace.cpp
index 7a14af1..df390e2 100644
--- a/libs/ui/ColorSpace.cpp
+++ b/libs/ui/ColorSpace.cpp
@@ -364,7 +364,11 @@
     for (uint32_t z = 0; z < size; z++) {
         for (int32_t y = int32_t(size - 1); y >= 0; y--) {
             for (uint32_t x = 0; x < size; x++) {
-                *data++ = connector.transform({x * m, y * m, z * m});
+                *data++ = connector.transform({
+                    static_cast<float>(x) * m,
+                    static_cast<float>(y) * m,
+                    static_cast<float>(z) * m,
+                });
             }
         }
     }
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index eb787a2..cc9ccbc 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -89,7 +89,7 @@
         if (rec.size) {
             StringAppendF(&result,
                           "%10p: %7.2f KiB | %4u (%4u) x %4u | %4u | %8X | 0x%" PRIx64 " | %s\n",
-                          list.keyAt(i), rec.size / 1024.0, rec.width, rec.stride, rec.height,
+                          list.keyAt(i), static_cast<double>(rec.size) / 1024.0, rec.width, rec.stride, rec.height,
                           rec.layerCount, rec.format, rec.usage, rec.requestorName.c_str());
         } else {
             StringAppendF(&result,
@@ -99,7 +99,7 @@
         }
         total += rec.size;
     }
-    StringAppendF(&result, "Total allocated (estimate): %.2f KB\n", total / 1024.0);
+    StringAppendF(&result, "Total allocated (estimate): %.2f KB\n", static_cast<double>(total) / 1024.0);
 
     result.append(mAllocator->dumpDebugInfo());
 }
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 55e3b99..1222cd6 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -339,10 +339,10 @@
     size_t count = mStorage.size();
     Rect* rects = mStorage.editArray();
     while (count) {
-        rects->left = static_cast<int32_t>(rects->left * sx + 0.5f);
-        rects->right = static_cast<int32_t>(rects->right * sx + 0.5f);
-        rects->top = static_cast<int32_t>(rects->top * sy + 0.5f);
-        rects->bottom = static_cast<int32_t>(rects->bottom * sy + 0.5f);
+        rects->left = static_cast<int32_t>(static_cast<float>(rects->left) * sx + 0.5f);
+        rects->right = static_cast<int32_t>(static_cast<float>(rects->right) * sx + 0.5f);
+        rects->top = static_cast<int32_t>(static_cast<float>(rects->top) * sy + 0.5f);
+        rects->bottom = static_cast<int32_t>(static_cast<float>(rects->bottom) * sy + 0.5f);
         rects++;
         count--;
     }
diff --git a/libs/ui/include/ui/Size.h b/libs/ui/include/ui/Size.h
index c39d8af..d9b713d 100644
--- a/libs/ui/include/ui/Size.h
+++ b/libs/ui/include/ui/Size.h
@@ -132,7 +132,7 @@
         // Otherwise we leverage implicit conversion to safely compare values of
         // different types, to ensure we return a value clamped to the range of
         // ToType.
-        return v < toLowest ? toLowest : (v > toHighest ? toHighest : static_cast<ToType>(v));
+        return v < toLowest ? toLowest : (static_cast<ToType>(v) > toHighest ? toHighest : static_cast<ToType>(v));
     }
 };
 
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
index 640a69a..930c7c7 100644
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ b/services/inputflinger/dispatcher/Entry.cpp
@@ -18,10 +18,12 @@
 
 #include "Connection.h"
 
+#include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <cutils/atomic.h>
 #include <inttypes.h>
 
+using android::base::GetBoolProperty;
 using android::base::StringPrintf;
 
 namespace android::inputdispatcher {
@@ -133,7 +135,11 @@
 KeyEntry::~KeyEntry() {}
 
 void KeyEntry::appendDescription(std::string& msg) const {
-    msg += StringPrintf("KeyEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32 ", action=%s, "
+    msg += StringPrintf("KeyEvent");
+    if (!GetBoolProperty("ro.debuggable", false)) {
+        return;
+    }
+    msg += StringPrintf("(deviceId=%d, source=0x%08x, displayId=%" PRId32 ", action=%s, "
                         "flags=0x%08x, keyCode=%d, scanCode=%d, metaState=0x%08x, "
                         "repeatCount=%d), policyFlags=0x%08x",
                         deviceId, source, displayId, keyActionToString(action).c_str(), flags,
@@ -189,7 +195,11 @@
 MotionEntry::~MotionEntry() {}
 
 void MotionEntry::appendDescription(std::string& msg) const {
-    msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32
+    msg += StringPrintf("MotionEvent");
+    if (!GetBoolProperty("ro.debuggable", false)) {
+        return;
+    }
+    msg += StringPrintf("(deviceId=%d, source=0x%08x, displayId=%" PRId32
                         ", action=%s, actionButton=0x%08x, flags=0x%08x, metaState=0x%08x, "
                         "buttonState=0x%08x, "
                         "classification=%s, edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, "
diff --git a/services/inputflinger/host/InputDriver.cpp b/services/inputflinger/host/InputDriver.cpp
index 2f046c3..683c05d 100644
--- a/services/inputflinger/host/InputDriver.cpp
+++ b/services/inputflinger/host/InputDriver.cpp
@@ -127,10 +127,10 @@
             input_bus_t bus, const char* uniqueId) {
     auto identifier = new ::input_device_identifier {
         .name = name,
-        .productId = productId,
-        .vendorId = vendorId,
-        .bus = bus,
         .uniqueId = uniqueId,
+        .bus = bus,
+        .vendorId = vendorId,
+        .productId = productId,
     };
     // TODO: store this identifier somewhere
     return identifier;
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index b500ad3..603a9f7 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -61,7 +61,7 @@
         mTextureName(args.textureName),
         mCompositionLayer{mFlinger->getCompositionEngine().createLayer(
                 compositionengine::LayerCreationArgs{this})} {
-    ALOGV("Creating Layer %s", args.name.string());
+    ALOGV("Creating Layer %s", getDebugName());
 
     mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied);
 
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index d80a70e..a4f7797 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -62,7 +62,7 @@
     std::vector<OccupancyTracker::Segment> history;
     status_t result = mConsumer->getOccupancyHistory(forceFlush, &history);
     if (result != NO_ERROR) {
-        ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), result);
+        ALOGW("[%s] Failed to obtain occupancy history (%d)", getDebugName(), result);
         return {};
     }
     return history;
@@ -110,7 +110,7 @@
     ALOGW_IF(!isPlausible,
              "[%s] Timestamp %" PRId64 " seems implausible "
              "relative to expectedPresent %" PRId64,
-             mName.string(), addedTime, expectedPresentTime);
+             getDebugName(), addedTime, expectedPresentTime);
 
     const bool isDue = addedTime < expectedPresentTime;
     return isDue || !isPlausible;
@@ -225,7 +225,7 @@
     bool queuedBuffer = false;
     const int32_t layerID = getSequence();
     LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
-                    getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
+                    getProducerStickyTransform() != 0, mName, mOverrideScalingMode,
                     getTransformToDisplayInverse());
 
     if (isRemovedFromCurrentState()) {
@@ -398,7 +398,7 @@
         while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
             status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
             if (result != NO_ERROR) {
-                ALOGE("[%s] Timed out waiting on callback", mName.string());
+                ALOGE("[%s] Timed out waiting on callback", getDebugName());
             }
         }
 
@@ -426,7 +426,7 @@
         while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
             status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
             if (result != NO_ERROR) {
-                ALOGE("[%s] Timed out waiting on callback", mName.string());
+                ALOGE("[%s] Timed out waiting on callback", getDebugName());
             }
         }
 
@@ -459,12 +459,14 @@
     // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
     sp<IGraphicBufferProducer> producer;
     sp<IGraphicBufferConsumer> consumer;
-    BufferQueue::createBufferQueue(&producer, &consumer, true);
-    mProducer = new MonitoredProducer(producer, mFlinger, this);
-    mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);
+    mFlinger->getFactory().createBufferQueue(&producer, &consumer, true);
+    mProducer = mFlinger->getFactory().createMonitoredProducer(producer, mFlinger, this);
+    mConsumer =
+            mFlinger->getFactory().createBufferLayerConsumer(consumer, mFlinger->getRenderEngine(),
+                                                             mTextureName, this);
     mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
     mConsumer->setContentsChangedListener(this);
-    mConsumer->setName(mName);
+    mConsumer->setName(String8(mName.data(), mName.size()));
 
     // BufferQueueCore::mMaxDequeuedBufferCount is default to 1
     if (!mFlinger->isLayerTripleBufferingDisabled()) {
@@ -527,9 +529,7 @@
 }
 
 sp<Layer> BufferQueueLayer::createClone() {
-    const String8 name = mName + " (Mirror)";
-    LayerCreationArgs args =
-            LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata());
+    LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, LayerMetadata());
     args.textureName = mTextureName;
     sp<BufferQueueLayer> layer = mFlinger->getFactory().createBufferQueueLayer(args);
     layer->setInitialValuesForClone(this);
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 75fc0e9..6fe89c4 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -136,7 +136,7 @@
         return;
     }
     mPendingStates.push_back(mCurrentState);
-    ATRACE_INT(mTransactionName.string(), mPendingStates.size());
+    ATRACE_INT(mTransactionName.c_str(), mPendingStates.size());
 }
 
 bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) {
@@ -479,7 +479,7 @@
         (s.active.w != bufferWidth || s.active.h != bufferHeight)) {
         ALOGE("[%s] rejecting buffer: "
               "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}",
-              mName.string(), bufferWidth, bufferHeight, s.active.w, s.active.h);
+              getDebugName(), bufferWidth, bufferHeight, s.active.w, s.active.h);
         mFlinger->mTimeStats->removeTimeRecord(layerID, mFrameNumber);
         return BAD_VALUE;
     }
@@ -669,9 +669,7 @@
 }
 
 sp<Layer> BufferStateLayer::createClone() {
-    const String8 name = mName + " (Mirror)";
-    LayerCreationArgs args =
-            LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata());
+    LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, LayerMetadata());
     args.textureName = mTextureName;
     sp<BufferStateLayer> layer = mFlinger->getFactory().createBufferStateLayer(args);
     layer->mHwcSlotGenerator = mHwcSlotGenerator;
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index 172d445..8bfa569 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -108,13 +108,11 @@
 }
 
 sp<Layer> ColorLayer::createClone() {
-    String8 name = mName + " (Mirror)";
     sp<ColorLayer> layer = mFlinger->getFactory().createColorLayer(
-            LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()));
+            LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0,
+                              LayerMetadata()));
     layer->setInitialValuesForClone(this);
     return layer;
 }
 
-// ---------------------------------------------------------------------------
-
-}; // namespace android
+} // namespace android
diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp
index e58e6f4..ab664be 100644
--- a/services/surfaceflinger/ContainerLayer.cpp
+++ b/services/surfaceflinger/ContainerLayer.cpp
@@ -31,10 +31,11 @@
 }
 
 sp<Layer> ContainerLayer::createClone() {
-    String8 name = mName + " (Mirror)";
     sp<ContainerLayer> layer = mFlinger->getFactory().createContainerLayer(
-            LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()));
+            LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0,
+                              LayerMetadata()));
     layer->setInitialValuesForClone(this);
     return layer;
 }
+
 } // namespace android
diff --git a/services/surfaceflinger/EventLog/EventLog.cpp b/services/surfaceflinger/EventLog/EventLog.cpp
index 365a0bd..a532fc1 100644
--- a/services/surfaceflinger/EventLog/EventLog.cpp
+++ b/services/surfaceflinger/EventLog/EventLog.cpp
@@ -17,13 +17,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <log/log.h>
-#include <utils/String8.h>
 
 #include "EventLog.h"
 
-// ---------------------------------------------------------------------------
 namespace android {
-// ---------------------------------------------------------------------------
 
 ANDROID_SINGLETON_STATIC_INSTANCE(EventLog)
 
@@ -31,11 +28,11 @@
 EventLog::EventLog() {
 }
 
-void EventLog::doLogFrameDurations(const String8& window,
-        const int32_t* durations, size_t numDurations) {
+void EventLog::doLogFrameDurations(const std::string_view& name, const int32_t* durations,
+                                   size_t numDurations) {
     EventLog::TagBuffer buffer(LOGTAG_SF_FRAME_DUR);
     buffer.startList(1 + numDurations);
-    buffer.writeString8(window);
+    buffer.writeString(name);
     for (size_t i = 0; i < numDurations; i++) {
         buffer.writeInt32(durations[i]);
     }
@@ -43,10 +40,9 @@
     buffer.log();
 }
 
-void EventLog::logFrameDurations(const String8& window,
-        const int32_t* durations, size_t numDurations) {
-    EventLog::getInstance().doLogFrameDurations(window, durations,
-            numDurations);
+void EventLog::logFrameDurations(const std::string_view& name, const int32_t* durations,
+                                 size_t numDurations) {
+    EventLog::getInstance().doLogFrameDurations(name, durations, numDurations);
 }
 
 // ---------------------------------------------------------------------------
@@ -113,9 +109,9 @@
     mPos += needed;
 }
 
-void EventLog::TagBuffer::writeString8(const String8& value) {
+void EventLog::TagBuffer::writeString(const std::string_view& value) {
     if (mOverflow) return;
-    const int32_t stringLen = value.length();
+    const size_t stringLen = value.length();
     const size_t needed = 1 + sizeof(int32_t) + stringLen;
     if (mPos + needed > STORAGE_MAX_SIZE) {
         mOverflow = true;
@@ -123,11 +119,8 @@
     }
     mStorage[mPos + 0] = EVENT_TYPE_STRING;
     memcpy(&mStorage[mPos + 1], &stringLen, sizeof(int32_t));
-    memcpy(&mStorage[mPos + 5], value.string(), stringLen);
+    memcpy(&mStorage[mPos + 5], value.data(), stringLen);
     mPos += needed;
 }
 
-// ---------------------------------------------------------------------------
-}// namespace android
-
-// ---------------------------------------------------------------------------
+} // namespace android
diff --git a/services/surfaceflinger/EventLog/EventLog.h b/services/surfaceflinger/EventLog/EventLog.h
index efc5d70..ee3587e 100644
--- a/services/surfaceflinger/EventLog/EventLog.h
+++ b/services/surfaceflinger/EventLog/EventLog.h
@@ -14,24 +14,21 @@
  * limitations under the License.
  */
 
-#include <stdint.h>
+#pragma once
+
 #include <utils/Errors.h>
 #include <utils/Singleton.h>
 
-#ifndef ANDROID_SF_EVENTLOG_H
-#define ANDROID_SF_EVENTLOG_H
+#include <cstdint>
+#include <string_view>
 
-// ---------------------------------------------------------------------------
 namespace android {
-// ---------------------------------------------------------------------------
-
-class String8;
 
 class EventLog : public Singleton<EventLog> {
 
 public:
-    static void logFrameDurations(const String8& window,
-            const int32_t* durations, size_t numDurations);
+    static void logFrameDurations(const std::string_view& name, const int32_t* durations,
+                                  size_t numDurations);
 
 protected:
     EventLog();
@@ -54,18 +51,13 @@
     public:
         explicit TagBuffer(int32_t tag);
 
-        // starts list of items
         void startList(int8_t count);
-        // terminates the list
         void endList();
-        // write a 32-bit integer
-        void writeInt32(int32_t value);
-        // write a 64-bit integer
-        void writeInt64(int64_t value);
-        // write a C string
-        void writeString8(const String8& value);
 
-        // outputs the the buffer to the log
+        void writeInt32(int32_t);
+        void writeInt64(int64_t);
+        void writeString(const std::string_view&);
+
         void log();
     };
 
@@ -74,12 +66,8 @@
     EventLog& operator =(const EventLog&);
 
     enum { LOGTAG_SF_FRAME_DUR = 60100 };
-    void doLogFrameDurations(const String8& window, const int32_t* durations,
-            size_t numDurations);
+    void doLogFrameDurations(const std::string_view& name, const int32_t* durations,
+                             size_t numDurations);
 };
 
-// ---------------------------------------------------------------------------
-}// namespace android
-// ---------------------------------------------------------------------------
-
-#endif /* ANDROID_SF_EVENTLOG_H */
+} // namespace android
diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp
index f4cc49b..a6e511e 100644
--- a/services/surfaceflinger/FrameTracker.cpp
+++ b/services/surfaceflinger/FrameTracker.cpp
@@ -21,7 +21,6 @@
 
 #include <android-base/stringprintf.h>
 #include <android/log.h>
-#include <utils/String8.h>
 
 #include <ui/FrameStats.h>
 
@@ -139,7 +138,7 @@
     }
 }
 
-void FrameTracker::logAndResetStats(const String8& name) {
+void FrameTracker::logAndResetStats(const std::string_view& name) {
     Mutex::Autolock lock(mMutex);
     logStatsLocked(name);
     resetFrameCountersLocked();
@@ -217,7 +216,7 @@
     }
 }
 
-void FrameTracker::logStatsLocked(const String8& name) const {
+void FrameTracker::logStatsLocked(const std::string_view& name) const {
     for (int i = 0; i < NUM_FRAME_BUCKETS; i++) {
         if (mNumFrames[i] > 0) {
             EventLog::logFrameDurations(name, mNumFrames, NUM_FRAME_BUCKETS);
diff --git a/services/surfaceflinger/FrameTracker.h b/services/surfaceflinger/FrameTracker.h
index 555dcc1..35382be 100644
--- a/services/surfaceflinger/FrameTracker.h
+++ b/services/surfaceflinger/FrameTracker.h
@@ -14,21 +14,18 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_FRAMETRACKER_H
-#define ANDROID_FRAMETRACKER_H
+#pragma once
 
 #include <ui/FenceTime.h>
-
-#include <stddef.h>
-
 #include <utils/Mutex.h>
-#include <utils/Timers.h>
 #include <utils/RefBase.h>
+#include <utils/Timers.h>
+
+#include <cstddef>
+#include <string_view>
 
 namespace android {
 
-class String8;
-
 // FrameTracker tracks information about the most recently rendered frames. It
 // uses a circular buffer of frame records, and is *NOT* thread-safe -
 // mutexing must be done at a higher level if multi-threaded access is
@@ -87,7 +84,7 @@
 
     // logAndResetStats dumps the current statistics to the binary event log
     // and then resets the accumulated statistics to their initial values.
-    void logAndResetStats(const String8& name);
+    void logAndResetStats(const std::string_view& name);
 
     // dumpStats dump appends the current frame display time history to the result string.
     void dumpStats(std::string& result) const;
@@ -123,7 +120,7 @@
     void resetFrameCountersLocked();
 
     // logStatsLocked dumps the current statistics to the binary event log.
-    void logStatsLocked(const String8& name) const;
+    void logStatsLocked(const std::string_view& name) const;
 
     // isFrameValidLocked returns true if the data for the given frame index is
     // valid and has all arrived (i.e. there are no oustanding fences).
@@ -160,6 +157,4 @@
     mutable Mutex mMutex;
 };
 
-}
-
-#endif // ANDROID_FRAMETRACKER_H
+} // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6a45625..37caab2 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -83,8 +83,6 @@
     if (args.flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque;
     if (args.flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure;
 
-    mTransactionName = String8("TX - ") + mName;
-
     mCurrentState.active_legacy.w = args.w;
     mCurrentState.active_legacy.h = args.h;
     mCurrentState.flags = layerFlags;
@@ -137,11 +135,11 @@
 }
 
 LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, const sp<Client>& client,
-                                     const String8& name, uint32_t w, uint32_t h, uint32_t flags,
+                                     std::string name, uint32_t w, uint32_t h, uint32_t flags,
                                      LayerMetadata metadata)
       : flinger(flinger),
         client(client),
-        name(name),
+        name(std::move(name)),
         w(w),
         h(h),
         flags(flags),
@@ -235,10 +233,6 @@
 // set-up
 // ---------------------------------------------------------------------------
 
-const String8& Layer::getName() const {
-    return mName;
-}
-
 bool Layer::getPremultipledAlpha() const {
     return mPremultipliedAlpha;
 }
@@ -523,7 +517,7 @@
 }
 
 const char* Layer::getDebugName() const {
-    return mName.string();
+    return mName.c_str();
 }
 
 // ---------------------------------------------------------------------------
@@ -614,7 +608,7 @@
     if (mCurrentState.barrierLayer_legacy != nullptr && !isRemovedFromCurrentState()) {
         sp<Layer> barrierLayer = mCurrentState.barrierLayer_legacy.promote();
         if (barrierLayer == nullptr) {
-            ALOGE("[%s] Unable to promote barrier Layer.", mName.string());
+            ALOGE("[%s] Unable to promote barrier Layer.", getDebugName());
             // If we can't promote the layer we are intended to wait on,
             // then it is expired or otherwise invalid. Allow this transaction
             // to be applied as per normal (no synchronization).
@@ -638,7 +632,7 @@
         mFlinger->setTransactionFlags(eTraversalNeeded);
     }
     mPendingStates.push_back(mCurrentState);
-    ATRACE_INT(mTransactionName.string(), mPendingStates.size());
+    ATRACE_INT(mTransactionName.c_str(), mPendingStates.size());
 }
 
 void Layer::popPendingState(State* stateToCommit) {
@@ -646,7 +640,7 @@
     *stateToCommit = mPendingStates[0];
 
     mPendingStates.removeAt(0);
-    ATRACE_INT(mTransactionName.string(), mPendingStates.size());
+    ATRACE_INT(mTransactionName.c_str(), mPendingStates.size());
 }
 
 bool Layer::applyPendingStates(State* stateToCommit) {
@@ -657,7 +651,7 @@
                 // If we don't have a sync point for this, apply it anyway. It
                 // will be visually wrong, but it should keep us from getting
                 // into too much trouble.
-                ALOGE("[%s] No local sync point found", mName.string());
+                ALOGE("[%s] No local sync point found", getDebugName());
                 popPendingState(stateToCommit);
                 stateUpdateAvailable = true;
                 continue;
@@ -665,7 +659,7 @@
 
             if (mRemoteSyncPoints.front()->getFrameNumber() !=
                 mPendingStates[0].frameNumber_legacy) {
-                ALOGE("[%s] Unexpected sync point frame number found", mName.string());
+                ALOGE("[%s] Unexpected sync point frame number found", getDebugName());
 
                 // Signal our end of the sync point and then dispose of it
                 mRemoteSyncPoints.front()->setTransactionApplied();
@@ -717,7 +711,7 @@
                  "            requested={ wh={%4u,%4u} }}\n"
                  "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
                  "            requested={ wh={%4u,%4u} }}\n",
-                 this, getName().string(), getBufferTransform(), getEffectiveScalingMode(),
+                 this, getName().c_str(), getBufferTransform(), getEffectiveScalingMode(),
                  stateToCommit->active_legacy.w, stateToCommit->active_legacy.h,
                  stateToCommit->crop_legacy.left, stateToCommit->crop_legacy.top,
                  stateToCommit->crop_legacy.right, stateToCommit->crop_legacy.bottom,
@@ -908,7 +902,6 @@
         }
         setZOrderRelativeOf(nullptr);
     }
-    mCurrentState.isRelativeOf = false;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -931,6 +924,8 @@
     mCurrentState.zOrderRelativeOf = relativeOf;
     mCurrentState.sequence++;
     mCurrentState.modified = true;
+    mCurrentState.isRelativeOf = relativeOf != nullptr;
+
     setTransactionFlags(eTransactionNeeded);
 }
 
@@ -952,7 +947,6 @@
     mCurrentState.sequence++;
     mCurrentState.modified = true;
     mCurrentState.z = relativeZ;
-    mCurrentState.isRelativeOf = true;
 
     auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote();
     if (oldZOrderRelativeOf != nullptr) {
@@ -999,9 +993,10 @@
     if (!mCurrentState.bgColorLayer && alpha != 0) {
         // create background color layer if one does not yet exist
         uint32_t flags = ISurfaceComposerClient::eFXSurfaceColor;
-        const String8& name = mName + "BackgroundColorLayer";
+        std::string name = mName + "BackgroundColorLayer";
         mCurrentState.bgColorLayer = mFlinger->getFactory().createColorLayer(
-                LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, flags, LayerMetadata()));
+                LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), 0, 0, flags,
+                                  LayerMetadata()));
 
         // add to child list
         addChild(mCurrentState.bgColorLayer);
@@ -1196,11 +1191,13 @@
 
 // TODO(marissaw): add new layer state info to layer debugging
 LayerDebugInfo Layer::getLayerDebugInfo() const {
+    using namespace std::string_literals;
+
     LayerDebugInfo info;
     const State& ds = getDrawingState();
     info.mName = getName();
     sp<Layer> parent = getParent();
-    info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string());
+    info.mParentName = parent ? parent->getName() : "none"s;
     info.mType = getType();
     info.mTransparentRegion = ds.activeTransparentRegion_legacy;
 
@@ -1267,12 +1264,12 @@
     std::string name;
     if (mName.length() > 77) {
         std::string shortened;
-        shortened.append(mName.string(), 36);
+        shortened.append(mName, 0, 36);
         shortened.append("[...]");
-        shortened.append(mName.string() + (mName.length() - 36), 36);
-        name = shortened;
+        shortened.append(mName, mName.length() - 36);
+        name = std::move(shortened);
     } else {
-        name = std::string(mName.string(), mName.size());
+        name = mName;
     }
 
     StringAppendF(&result, " %s\n", name.c_str());
@@ -1319,14 +1316,14 @@
 }
 
 void Layer::dumpFrameEvents(std::string& result) {
-    StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().string(), getType(), this);
+    StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().c_str(), getType(), this);
     Mutex::Autolock lock(mFrameEventHistoryMutex);
     mFrameEventHistory.checkFencesForCompletion();
     mFrameEventHistory.dump(result);
 }
 
 void Layer::dumpCallingUidPid(std::string& result) const {
-    StringAppendF(&result, "Layer %s (%s) pid:%d uid:%d\n", getName().string(), getType(),
+    StringAppendF(&result, "Layer %s (%s) pid:%d uid:%d\n", getName().c_str(), getType(),
                   mCallingPid, mCallingUid);
 }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3023cf5..ad81920 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -34,7 +34,6 @@
 #include <ui/Region.h>
 #include <ui/Transform.h>
 #include <utils/RefBase.h>
-#include <utils/String8.h>
 #include <utils/Timers.h>
 
 #include <cstdint>
@@ -79,12 +78,12 @@
 // ---------------------------------------------------------------------------
 
 struct LayerCreationArgs {
-    LayerCreationArgs(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name,
+    LayerCreationArgs(SurfaceFlinger* flinger, const sp<Client>& client, std::string name,
                       uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata);
 
     SurfaceFlinger* flinger;
     const sp<Client>& client;
-    const String8& name;
+    std::string name;
     uint32_t w;
     uint32_t h;
     uint32_t flags;
@@ -804,7 +803,7 @@
     // Creates a new handle each time, so we only expect
     // this to be called once.
     sp<IBinder> getHandle();
-    const String8& getName() const;
+    const std::string& getName() const { return mName; }
     virtual void notifyAvailableFrames(nsecs_t /*expectedPresentTime*/) {}
     virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; }
     bool getPremultipledAlpha() const;
@@ -820,8 +819,8 @@
     bool usingRelativeZ(LayerVector::StateSet stateSet) const;
 
     bool mPremultipliedAlpha{true};
-    String8 mName;
-    String8 mTransactionName; // A cached version of "TX - " + mName for systraces
+    const std::string mName;
+    const std::string mTransactionName{"TX - " + mName};
 
     bool mPrimaryDisplayOnly = false;
 
diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp
index 8a22183..1a60f1e 100644
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ b/services/surfaceflinger/LayerRejecter.cpp
@@ -24,7 +24,7 @@
 namespace android {
 
 LayerRejecter::LayerRejecter(Layer::State& front, Layer::State& current,
-                             bool& recomputeVisibleRegions, bool stickySet, const char* name,
+                             bool& recomputeVisibleRegions, bool stickySet, const std::string& name,
                              int32_t overrideScalingMode, bool transformToDisplayInverse)
       : mFront(front),
         mCurrent(current),
@@ -90,7 +90,7 @@
                  "(%4d,%4d) "
                  "}\n"
                  "            requested_legacy={ wh={%4u,%4u} }}\n",
-                 mName, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
+                 mName.c_str(), bufWidth, bufHeight, item.mTransform, item.mScalingMode,
                  mFront.active_legacy.w, mFront.active_legacy.h, mFront.crop_legacy.left,
                  mFront.crop_legacy.top, mFront.crop_legacy.right, mFront.crop_legacy.bottom,
                  mFront.crop_legacy.getWidth(), mFront.crop_legacy.getHeight(),
@@ -102,7 +102,8 @@
             // reject this buffer
             ALOGE("[%s] rejecting buffer: "
                   "bufWidth=%d, bufHeight=%d, front.active_legacy.{w=%d, h=%d}",
-                  mName, bufWidth, bufHeight, mFront.active_legacy.w, mFront.active_legacy.h);
+                  mName.c_str(), bufWidth, bufHeight, mFront.active_legacy.w,
+                  mFront.active_legacy.h);
             return true;
         }
     }
diff --git a/services/surfaceflinger/LayerRejecter.h b/services/surfaceflinger/LayerRejecter.h
index 1bd0c26..fb5c750 100644
--- a/services/surfaceflinger/LayerRejecter.h
+++ b/services/surfaceflinger/LayerRejecter.h
@@ -14,30 +14,29 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_LAYER_REJECTER_H
-#define ANDROID_LAYER_REJECTER_H
+#pragma once
 
 #include "Layer.h"
 #include "BufferLayerConsumer.h"
 
 namespace android {
-    class LayerRejecter : public BufferLayerConsumer::BufferRejecter {
-    public:
-        LayerRejecter(Layer::State &front, Layer::State &current, bool &recomputeVisibleRegions,
-                      bool stickySet, const char *name, int32_t overrideScalingMode,
-                      bool transformToDisplayInverse);
 
-        virtual bool reject(const sp<GraphicBuffer> &buf, const BufferItem &item);
+class LayerRejecter : public BufferLayerConsumer::BufferRejecter {
+public:
+    LayerRejecter(Layer::State& front, Layer::State& current, bool& recomputeVisibleRegions,
+                  bool stickySet, const std::string& name, int32_t overrideScalingMode,
+                  bool transformToDisplayInverse);
 
-    private:
-        Layer::State &mFront;
-        Layer::State &mCurrent;
-        bool &mRecomputeVisibleRegions;
-        bool mStickyTransformSet;
-        const char *mName;
-        int32_t mOverrideScalingMode;
-        bool mTransformToDisplayInverse;
-    };
-}  // namespace android
+    virtual bool reject(const sp<GraphicBuffer>&, const BufferItem&);
 
-#endif  // ANDROID_LAYER_REJECTER_H
+private:
+    Layer::State& mFront;
+    Layer::State& mCurrent;
+    bool& mRecomputeVisibleRegions;
+    const bool mStickyTransformSet;
+    const std::string& mName;
+    const int32_t mOverrideScalingMode;
+    const bool mTransformToDisplayInverse;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 1c1367c..30027de 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -436,7 +436,7 @@
             }
             if (!intersectsAnyArea) return;
 
-            ALOGV("Traversing [%s] [%d, %d, %d, %d]", layer->getName().string(), bounds.left,
+            ALOGV("Traversing [%s] [%d, %d, %d, %d]", layer->getDebugName(), bounds.left,
                   bounds.top, bounds.right, bounds.bottom);
             visitor(layer);
         };
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index f80c233..5473db6 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -40,7 +40,7 @@
 LayerHistory::LayerHistory() {
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.sf.layer_history_trace", value, "0");
-    mTraceEnabled = bool(atoi(value));
+    mTraceEnabled = static_cast<bool>(atoi(value));
 }
 
 LayerHistory::~LayerHistory() = default;
@@ -128,19 +128,23 @@
 
     // Iterate through all layers that have been recently updated, and find the max refresh rate.
     for (const auto& [layerId, layerInfo] : mActiveLayerInfos) {
-        const float layerRefreshRate = layerInfo->getDesiredRefreshRate();
-        if (mTraceEnabled) {
-            // Store the refresh rate in traces for easy debugging.
-            std::string layerName = "LFPS " + layerInfo->getName();
-            ATRACE_INT(layerName.c_str(), std::round(layerRefreshRate));
-            ALOGD("%s: %f", layerName.c_str(), std::round(layerRefreshRate));
-        }
-        if (layerInfo->isRecentlyActive() && layerRefreshRate > newRefreshRate) {
-            newRefreshRate = layerRefreshRate;
+        const bool recent = layerInfo->isRecentlyActive();
+        if (recent || CC_UNLIKELY(mTraceEnabled)) {
+            const float refreshRate = layerInfo->getDesiredRefreshRate();
+            if (recent && refreshRate > newRefreshRate) {
+                newRefreshRate = refreshRate;
+            }
+
+            if (CC_UNLIKELY(mTraceEnabled)) {
+                std::string name = "LFPS " + layerInfo->getName();
+                const float rate = std::round(refreshRate);
+                ATRACE_INT(name.c_str(), rate);
+                ALOGD("%s: %f", name.c_str(), rate);
+            }
         }
         isHDR |= layerInfo->getHDRContent();
     }
-    if (mTraceEnabled) {
+    if (CC_UNLIKELY(mTraceEnabled)) {
         ALOGD("LayerHistory DesiredRefreshRate: %.2f", newRefreshRate);
     }
 
@@ -158,7 +162,7 @@
             (!it->second->getHDRContent() && it->second->getLastUpdatedTime() < obsoleteEpsilon)) {
             // erase() function returns the iterator of the next
             // to last deleted element.
-            if (mTraceEnabled) {
+            if (CC_UNLIKELY(mTraceEnabled)) {
                 ALOGD("Layer %s obsolete", it->second->getName().c_str());
                 // Make sure to update systrace to indicate that the layer was erased.
                 std::string layerName = "LFPS " + it->second->getName();
@@ -189,4 +193,4 @@
 }
 
 } // namespace scheduler
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 54e2065..0e33f10 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -122,6 +122,8 @@
 
 namespace android {
 
+using namespace std::string_literals;
+
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
 using namespace android::sysprop;
@@ -1911,8 +1913,7 @@
                 layer->onPostComposition(displayDevice->getId(), glCompositionDoneFenceTime,
                                          presentFenceTime, compositorTiming);
         if (frameLatched) {
-            recordBufferingStats(layer->getName().string(),
-                    layer->getOccupancyHistory(false));
+            recordBufferingStats(layer->getName(), layer->getOccupancyHistory(false));
         }
     });
 
@@ -2574,7 +2575,7 @@
     if (!mLayersPendingRemoval.isEmpty()) {
         // Notify removed layers now that they can't be drawn from
         for (const auto& l : mLayersPendingRemoval) {
-            recordBufferingStats(l->getName().string(), l->getOccupancyHistory(true));
+            recordBufferingStats(l->getName(), l->getOccupancyHistory(true));
 
             // Ensure any buffers set to display on any children are released.
             if (l->isRemovedFromCurrentState()) {
@@ -3244,11 +3245,12 @@
         // everything else inherits layer stack from its parent.
         if (layer->hasParent()) {
             ALOGE("Attempt to set layer stack on layer with parent (%s) is invalid",
-                    layer->getName().string());
+                  layer->getDebugName());
         } else if (idx < 0) {
             ALOGE("Attempt to set layer stack on layer without parent (%s) that "
-                    "that also does not appear in the top level layer list. Something"
-                    " has gone wrong.", layer->getName().string());
+                  "that also does not appear in the top level layer list. Something"
+                  " has gone wrong.",
+                  layer->getDebugName());
         } else if (layer->setLayerStack(s.layerStack)) {
             mCurrentState.layersSortedByZ.removeAt(idx);
             mCurrentState.layersSortedByZ.add(layer);
@@ -3406,7 +3408,7 @@
 
     sp<Layer> mirrorLayer;
     sp<Layer> mirrorFrom;
-    String8 uniqueName = getUniqueLayerName(String8("MirrorRoot"));
+    std::string uniqueName = getUniqueLayerName("MirrorRoot");
 
     {
         Mutex::Autolock _l(mStateLock);
@@ -3415,8 +3417,8 @@
             return NAME_NOT_FOUND;
         }
 
-        status_t result = createContainerLayer(client, uniqueName, -1, -1, 0, LayerMetadata(),
-                                               outHandle, &mirrorLayer);
+        status_t result = createContainerLayer(client, std::move(uniqueName), -1, -1, 0,
+                                               LayerMetadata(), outHandle, &mirrorLayer);
         if (result != NO_ERROR) {
             return result;
         }
@@ -3447,7 +3449,7 @@
 
     sp<Layer> layer;
 
-    String8 uniqueName = getUniqueLayerName(name);
+    std::string uniqueName = getUniqueLayerName(name.string());
 
     bool primaryDisplayOnly = false;
 
@@ -3463,13 +3465,13 @@
 
     switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
         case ISurfaceComposerClient::eFXSurfaceBufferQueue:
-            result = createBufferQueueLayer(client, uniqueName, w, h, flags, std::move(metadata),
-                                            format, handle, gbp, &layer);
+            result = createBufferQueueLayer(client, std::move(uniqueName), w, h, flags,
+                                            std::move(metadata), format, handle, gbp, &layer);
 
             break;
         case ISurfaceComposerClient::eFXSurfaceBufferState:
-            result = createBufferStateLayer(client, uniqueName, w, h, flags, std::move(metadata),
-                                            handle, &layer);
+            result = createBufferStateLayer(client, std::move(uniqueName), w, h, flags,
+                                            std::move(metadata), handle, &layer);
             break;
         case ISurfaceComposerClient::eFXSurfaceColor:
             // check if buffer size is set for color layer.
@@ -3479,8 +3481,8 @@
                 return BAD_VALUE;
             }
 
-            result = createColorLayer(client, uniqueName, w, h, flags, std::move(metadata), handle,
-                                      &layer);
+            result = createColorLayer(client, std::move(uniqueName), w, h, flags,
+                                      std::move(metadata), handle, &layer);
             break;
         case ISurfaceComposerClient::eFXSurfaceContainer:
             // check if buffer size is set for container layer.
@@ -3489,8 +3491,8 @@
                       int(w), int(h));
                 return BAD_VALUE;
             }
-            result = createContainerLayer(client, uniqueName, w, h, flags, std::move(metadata),
-                                          handle, &layer);
+            result = createContainerLayer(client, std::move(uniqueName), w, h, flags,
+                                          std::move(metadata), handle, &layer);
             break;
         default:
             result = BAD_VALUE;
@@ -3517,35 +3519,32 @@
     return result;
 }
 
-String8 SurfaceFlinger::getUniqueLayerName(const String8& name)
-{
-    bool matchFound = true;
-    uint32_t dupeCounter = 0;
+std::string SurfaceFlinger::getUniqueLayerName(const char* name) {
+    unsigned dupeCounter = 0;
 
     // Tack on our counter whether there is a hit or not, so everyone gets a tag
-    String8 uniqueName = name + "#" + String8(std::to_string(dupeCounter).c_str());
+    std::string uniqueName = base::StringPrintf("%s#%u", name, dupeCounter);
 
     // Grab the state lock since we're accessing mCurrentState
     Mutex::Autolock lock(mStateLock);
 
     // Loop over layers until we're sure there is no matching name
+    bool matchFound = true;
     while (matchFound) {
         matchFound = false;
         mCurrentState.traverseInZOrder([&](Layer* layer) {
             if (layer->getName() == uniqueName) {
                 matchFound = true;
-                uniqueName = name + "#" + String8(std::to_string(++dupeCounter).c_str());
+                uniqueName = base::StringPrintf("%s#%u", name, ++dupeCounter);
             }
         });
     }
 
-    ALOGV_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name.c_str(),
-             uniqueName.c_str());
-
+    ALOGV_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name, uniqueName.c_str());
     return uniqueName;
 }
 
-status_t SurfaceFlinger::createBufferQueueLayer(const sp<Client>& client, const String8& name,
+status_t SurfaceFlinger::createBufferQueueLayer(const sp<Client>& client, std::string name,
                                                 uint32_t w, uint32_t h, uint32_t flags,
                                                 LayerMetadata metadata, PixelFormat& format,
                                                 sp<IBinder>* handle,
@@ -3563,8 +3562,7 @@
     }
 
     sp<BufferQueueLayer> layer;
-    LayerCreationArgs args =
-            LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata));
+    LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata));
     args.textureName = getNewTexture();
     {
         // Grab the SF state lock during this since it's the only safe way to access
@@ -3585,12 +3583,11 @@
     return err;
 }
 
-status_t SurfaceFlinger::createBufferStateLayer(const sp<Client>& client, const String8& name,
+status_t SurfaceFlinger::createBufferStateLayer(const sp<Client>& client, std::string name,
                                                 uint32_t w, uint32_t h, uint32_t flags,
                                                 LayerMetadata metadata, sp<IBinder>* handle,
                                                 sp<Layer>* outLayer) {
-    LayerCreationArgs args =
-            LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata));
+    LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata));
     args.displayDevice = getDefaultDisplayDevice();
     args.textureName = getNewTexture();
     sp<BufferStateLayer> layer = getFactory().createBufferStateLayer(args);
@@ -3600,26 +3597,25 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::createColorLayer(const sp<Client>& client, const String8& name, uint32_t w,
+status_t SurfaceFlinger::createColorLayer(const sp<Client>& client, std::string name, uint32_t w,
                                           uint32_t h, uint32_t flags, LayerMetadata metadata,
                                           sp<IBinder>* handle, sp<Layer>* outLayer) {
     *outLayer = getFactory().createColorLayer(
-            LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)));
+            {this, client, std::move(name), w, h, flags, std::move(metadata)});
     *handle = (*outLayer)->getHandle();
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::createContainerLayer(const sp<Client>& client, const String8& name,
+status_t SurfaceFlinger::createContainerLayer(const sp<Client>& client, std::string name,
                                               uint32_t w, uint32_t h, uint32_t flags,
                                               LayerMetadata metadata, sp<IBinder>* handle,
                                               sp<Layer>* outLayer) {
     *outLayer = getFactory().createContainerLayer(
-            LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)));
+            {this, client, std::move(name), w, h, flags, std::move(metadata)});
     *handle = (*outLayer)->getHandle();
     return NO_ERROR;
 }
 
-
 void SurfaceFlinger::markLayerPendingRemovalLocked(const sp<Layer>& layer) {
     mLayersPendingRemoval.add(layer);
     mLayersRemoved = true;
@@ -3828,8 +3824,6 @@
                           strerror(-err), err);
         }
 
-        using namespace std::string_literals;
-
         static const std::unordered_map<std::string, Dumper> dumpers = {
                 {"--display-id"s, dumper(&SurfaceFlinger::dumpDisplayIdentificationData)},
                 {"--dispsync"s,
@@ -3885,7 +3879,7 @@
 
 void SurfaceFlinger::listLayersLocked(std::string& result) const {
     mCurrentState.traverseInZOrder(
-            [&](Layer* layer) { StringAppendF(&result, "%s\n", layer->getName().string()); });
+            [&](Layer* layer) { StringAppendF(&result, "%s\n", layer->getDebugName()); });
 }
 
 void SurfaceFlinger::dumpStatsLocked(const DumpArgs& args, std::string& result) const {
@@ -3894,7 +3888,7 @@
     if (args.size() > 1) {
         const auto name = String8(args[1]);
         mCurrentState.traverseInZOrder([&](Layer* layer) {
-            if (name == layer->getName()) {
+            if (layer->getName() == name.string()) {
                 layer->dumpFrameStats(result);
             }
         });
@@ -3904,8 +3898,11 @@
 }
 
 void SurfaceFlinger::clearStatsLocked(const DumpArgs& args, std::string&) {
+    const bool clearAll = args.size() < 2;
+    const auto name = clearAll ? String8() : String8(args[1]);
+
     mCurrentState.traverseInZOrder([&](Layer* layer) {
-        if (args.size() < 2 || String8(args[1]) == layer->getName()) {
+        if (clearAll || layer->getName() == name.string()) {
             layer->clearFrameStats();
         }
     });
@@ -3924,7 +3921,7 @@
         layer->logFrameStats();
     });
 
-    mAnimFrameTracker.logAndResetStats(String8("<win-anim>"));
+    mAnimFrameTracker.logAndResetStats("<win-anim>");
 }
 
 void SurfaceFlinger::appendSfConfigString(std::string& result) const {
@@ -3982,8 +3979,8 @@
                   bucketTimeSec, percent);
 }
 
-void SurfaceFlinger::recordBufferingStats(const char* layerName,
-        std::vector<OccupancyTracker::Segment>&& history) {
+void SurfaceFlinger::recordBufferingStats(const std::string& layerName,
+                                          std::vector<OccupancyTracker::Segment>&& history) {
     Mutex::Autolock lock(getBE().mBufferingStatsMutex);
     auto& stats = getBE().mBufferingStats[layerName];
     for (const auto& segment : history) {
@@ -5031,13 +5028,14 @@
                 drawLayers();
             } else {
                 Rect bounds = getBounds();
+                uint32_t w = static_cast<uint32_t>(bounds.getWidth());
+                uint32_t h = static_cast<uint32_t>(bounds.getHeight());
                 // In the "childrenOnly" case we reparent the children to a screenshot
                 // layer which has no properties set and which does not draw.
                 sp<ContainerLayer> screenshotParentLayer =
-                        mFlinger->getFactory().createContainerLayer(
-                                LayerCreationArgs(mFlinger, nullptr, String8("Screenshot Parent"),
-                                                  bounds.getWidth(), bounds.getHeight(), 0,
-                                                  LayerMetadata()));
+                        mFlinger->getFactory().createContainerLayer({mFlinger, nullptr,
+                                                                     "Screenshot Parent"s, w, h, 0,
+                                                                     LayerMetadata()});
 
                 ReparentForDrawing reparent(mLayer, screenshotParentLayer, sourceCrop);
                 drawLayers();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 9f3a914..b719245 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -607,27 +607,27 @@
                          sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp,
                          const sp<IBinder>& parentHandle, const sp<Layer>& parentLayer = nullptr);
 
-    status_t createBufferQueueLayer(const sp<Client>& client, const String8& name, uint32_t w,
+    status_t createBufferQueueLayer(const sp<Client>& client, std::string name, uint32_t w,
                                     uint32_t h, uint32_t flags, LayerMetadata metadata,
                                     PixelFormat& format, sp<IBinder>* outHandle,
                                     sp<IGraphicBufferProducer>* outGbp, sp<Layer>* outLayer);
 
-    status_t createBufferStateLayer(const sp<Client>& client, const String8& name, uint32_t w,
+    status_t createBufferStateLayer(const sp<Client>& client, std::string name, uint32_t w,
                                     uint32_t h, uint32_t flags, LayerMetadata metadata,
                                     sp<IBinder>* outHandle, sp<Layer>* outLayer);
 
-    status_t createColorLayer(const sp<Client>& client, const String8& name, uint32_t w, uint32_t h,
+    status_t createColorLayer(const sp<Client>& client, std::string name, uint32_t w, uint32_t h,
                               uint32_t flags, LayerMetadata metadata, sp<IBinder>* outHandle,
                               sp<Layer>* outLayer);
 
-    status_t createContainerLayer(const sp<Client>& client, const String8& name, uint32_t w,
+    status_t createContainerLayer(const sp<Client>& client, std::string name, uint32_t w,
                                   uint32_t h, uint32_t flags, LayerMetadata metadata,
                                   sp<IBinder>* outHandle, sp<Layer>* outLayer);
 
     status_t mirrorLayer(const sp<Client>& client, const sp<IBinder>& mirrorFromHandle,
                          sp<IBinder>* outHandle);
 
-    String8 getUniqueLayerName(const String8& name);
+    std::string getUniqueLayerName(const char* name);
 
     // called when all clients have released all their references to
     // this layer meaning it is entirely safe to destroy all
@@ -866,8 +866,8 @@
     // Not const because each Layer needs to query Fences and cache timestamps.
     void dumpFrameEventsLocked(std::string& result);
 
-    void recordBufferingStats(const char* layerName,
-            std::vector<OccupancyTracker::Segment>&& history);
+    void recordBufferingStats(const std::string& layerName,
+                              std::vector<OccupancyTracker::Segment>&& history);
     void dumpBufferingStats(std::string& result) const;
     void dumpDisplayIdentificationData(std::string& result) const;
     void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const;
diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
index f0457e3..4f439da 100644
--- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
+++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
@@ -17,12 +17,14 @@
 #include <compositionengine/impl/CompositionEngine.h>
 #include <ui/GraphicBuffer.h>
 
+#include "BufferLayerConsumer.h"
 #include "BufferQueueLayer.h"
 #include "BufferStateLayer.h"
 #include "ColorLayer.h"
 #include "ContainerLayer.h"
 #include "DisplayDevice.h"
 #include "Layer.h"
+#include "MonitoredProducer.h"
 #include "NativeWindowSurface.h"
 #include "StartPropertySetThread.h"
 #include "SurfaceFlingerDefaultFactory.h"
@@ -92,6 +94,18 @@
     BufferQueue::createBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger);
 }
 
+sp<IGraphicBufferProducer> DefaultFactory::createMonitoredProducer(
+        const sp<IGraphicBufferProducer>& producer, const sp<SurfaceFlinger>& flinger,
+        const wp<Layer>& layer) {
+    return new MonitoredProducer(producer, flinger, layer);
+}
+
+sp<BufferLayerConsumer> DefaultFactory::createBufferLayerConsumer(
+        const sp<IGraphicBufferConsumer>& consumer, renderengine::RenderEngine& renderEngine,
+        uint32_t textureName, Layer* layer) {
+    return new BufferLayerConsumer(consumer, renderEngine, textureName, layer);
+}
+
 std::unique_ptr<surfaceflinger::NativeWindowSurface> DefaultFactory::createNativeWindowSurface(
         const sp<IGraphicBufferProducer>& producer) {
     return surfaceflinger::impl::createNativeWindowSurface(producer);
diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
index 89e0679..42bb177 100644
--- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
@@ -42,6 +42,12 @@
     void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
                            sp<IGraphicBufferConsumer>* outConsumer,
                            bool consumerIsSurfaceFlinger) override;
+    sp<IGraphicBufferProducer> createMonitoredProducer(const sp<IGraphicBufferProducer>&,
+                                                       const sp<SurfaceFlinger>&,
+                                                       const wp<Layer>&) override;
+    sp<BufferLayerConsumer> createBufferLayerConsumer(const sp<IGraphicBufferConsumer>&,
+                                                      renderengine::RenderEngine&, uint32_t tex,
+                                                      Layer*) override;
     std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
             const sp<IGraphicBufferProducer>&) override;
     std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() override;
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h
index 3fd4de8..20784d2 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerFactory.h
@@ -30,6 +30,7 @@
 
 class BufferQueueLayer;
 class BufferStateLayer;
+class BufferLayerConsumer;
 class ColorLayer;
 class ContainerLayer;
 class DisplayDevice;
@@ -39,6 +40,7 @@
 class HWComposer;
 class IGraphicBufferConsumer;
 class IGraphicBufferProducer;
+class Layer;
 class MessageQueue;
 class Scheduler;
 class StartPropertySetThread;
@@ -85,6 +87,13 @@
     virtual void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
                                    sp<IGraphicBufferConsumer>* outConsumer,
                                    bool consumerIsSurfaceFlinger) = 0;
+    virtual sp<IGraphicBufferProducer> createMonitoredProducer(const sp<IGraphicBufferProducer>&,
+                                                               const sp<SurfaceFlinger>&,
+                                                               const wp<Layer>&) = 0;
+    virtual sp<BufferLayerConsumer> createBufferLayerConsumer(const sp<IGraphicBufferConsumer>&,
+                                                              renderengine::RenderEngine&,
+                                                              uint32_t tex, Layer*) = 0;
+
     virtual std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
             const sp<IGraphicBufferProducer>&) = 0;
 
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index a02d14c..7e6c472 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -165,10 +165,6 @@
     return layer;
 }
 
-const std::string SurfaceInterceptor::getLayerName(const sp<const Layer>& layer) const {
-    return layer->getName().string();
-}
-
 int32_t SurfaceInterceptor::getLayerId(const sp<const Layer>& layer) const {
     return layer->sequence;
 }
@@ -490,7 +486,7 @@
 {
     SurfaceCreation* creation(increment->mutable_surface_creation());
     creation->set_id(getLayerId(layer));
-    creation->set_name(getLayerName(layer));
+    creation->set_name(layer->getName());
     creation->set_w(layer->mCurrentState.active_legacy.w);
     creation->set_h(layer->mCurrentState.active_legacy.h);
 }
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 6858c4d..72b734b 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -123,7 +123,6 @@
 
     status_t writeProtoFileLocked();
     const sp<const Layer> getLayer(const wp<const IBinder>& weakHandle) const;
-    const std::string getLayerName(const sp<const Layer>& layer) const;
     int32_t getLayerId(const sp<const Layer>& layer) const;
     int32_t getLayerIdFromWeakRef(const wp<const Layer>& layer) const;
     int32_t getLayerIdFromHandle(const sp<const IBinder>& weakHandle) const;
diff --git a/services/surfaceflinger/tests/RelativeZ_test.cpp b/services/surfaceflinger/tests/RelativeZ_test.cpp
index 8549db2..8c56d27 100644
--- a/services/surfaceflinger/tests/RelativeZ_test.cpp
+++ b/services/surfaceflinger/tests/RelativeZ_test.cpp
@@ -144,4 +144,63 @@
         sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
     }
 }
+
+TEST_F(RelativeZTest, LayerAndRelativeRemoved) {
+    std::unique_ptr<ScreenCapture> sc;
+
+    // Background layer (RED)
+    // Foregroud layer (GREEN)
+    //   Child layer (BLUE) (relative to relativeToLayer layer)
+    //   Relative layer (WHITE)
+    sp<SurfaceControl> childLayer =
+            createColorLayer("Child layer", Color::BLUE, mForegroundLayer.get());
+    sp<SurfaceControl> relativeToLayer =
+            createColorLayer("Relative layer", Color::WHITE, mForegroundLayer.get());
+
+    Transaction{}
+            .setRelativeLayer(childLayer, relativeToLayer->getHandle(), 1)
+            .show(childLayer)
+            .show(relativeToLayer)
+            .apply();
+
+    {
+        // The childLayer should be in front of relativeToLayer.
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b);
+    }
+
+    // Remove layer that childLayer is relative to
+    // Background layer (RED)
+    // Foregroud layer (GREEN)
+    //   Child layer (BLUE) (relative to relativeToLayer layer)
+    Transaction{}.reparent(relativeToLayer, nullptr).apply();
+    relativeToLayer = 0;
+
+    {
+        // The child layer is relative to an deleted layer so it won't be drawn.
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+    }
+
+    // Background layer (RED)
+    // Foregroud layer (GREEN)
+    Transaction{}.reparent(childLayer, nullptr).apply();
+
+    {
+        // The child layer is offscreen, so it won't be drawn.
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+    }
+
+    // Background layer (RED)
+    // Foregroud layer (GREEN)
+    //   Child layer (BLUE)
+    Transaction{}.reparent(childLayer, mForegroundLayer->getHandle()).apply();
+
+    {
+        // The relative z info for child layer should be reset, leaving the child layer on top.
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b);
+    }
+}
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 8aff096..60da70f 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -839,7 +839,7 @@
     static FlingerLayerType createLayer(CompositionTest* test) {
         FlingerLayerType layer = Base::template createLayerWithFactory<ColorLayer>(test, [test]() {
             return new ColorLayer(LayerCreationArgs(test->mFlinger.mFlinger.get(), sp<Client>(),
-                                                    String8("test-layer"), LayerProperties::WIDTH,
+                                                    "test-layer", LayerProperties::WIDTH,
                                                     LayerProperties::HEIGHT,
                                                     LayerProperties::LAYER_FLAGS, LayerMetadata()));
         });
@@ -879,11 +879,9 @@
         FlingerLayerType layer =
                 Base::template createLayerWithFactory<BufferQueueLayer>(test, [test]() {
                     sp<Client> client;
-                    String8 name("test-layer");
-                    LayerCreationArgs args =
-                            LayerCreationArgs(test->mFlinger.mFlinger.get(), client, name,
-                                              LayerProperties::WIDTH, LayerProperties::HEIGHT,
-                                              LayerProperties::LAYER_FLAGS, LayerMetadata());
+                    LayerCreationArgs args(test->mFlinger.mFlinger.get(), client, "test-layer",
+                                           LayerProperties::WIDTH, LayerProperties::HEIGHT,
+                                           LayerProperties::LAYER_FLAGS, LayerMetadata());
                     args.textureName = test->mFlinger.mutableTexturePool().back();
                     return new BufferQueueLayer(args);
                 });
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index b85c1b6..c7664fb 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -62,23 +62,19 @@
     ~Factory() = default;
 
     std::unique_ptr<DispSync> createDispSync(const char*, bool) override {
-        // TODO: Use test-fixture controlled factory
         return nullptr;
     }
 
     std::unique_ptr<EventControlThread> createEventControlThread(
             std::function<void(bool)>) override {
-        // TODO: Use test-fixture controlled factory
         return nullptr;
     }
 
     std::unique_ptr<HWComposer> createHWComposer(const std::string&) override {
-        // TODO: Use test-fixture controlled factory
         return nullptr;
     }
 
     std::unique_ptr<MessageQueue> createMessageQueue() override {
-        // TODO: Use test-fixture controlled factory
         return std::make_unique<android::impl::MessageQueue>();
     }
 
@@ -88,39 +84,49 @@
 
     std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)>,
                                                const scheduler::RefreshRateConfigs&) override {
-        // TODO: Use test-fixture controlled factory
         return nullptr;
     }
 
     std::unique_ptr<SurfaceInterceptor> createSurfaceInterceptor(SurfaceFlinger* flinger) override {
-        // TODO: Use test-fixture controlled factory
         return std::make_unique<android::impl::SurfaceInterceptor>(flinger);
     }
 
     sp<StartPropertySetThread> createStartPropertySetThread(bool timestampPropertyValue) override {
-        // TODO: Use test-fixture controlled factory
         return new StartPropertySetThread(timestampPropertyValue);
     }
 
     sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs&& creationArgs) override {
-        // TODO: Use test-fixture controlled factory
         return new DisplayDevice(std::move(creationArgs));
     }
 
     sp<GraphicBuffer> createGraphicBuffer(uint32_t width, uint32_t height, PixelFormat format,
                                           uint32_t layerCount, uint64_t usage,
                                           std::string requestorName) override {
-        // TODO: Use test-fixture controlled factory
         return new GraphicBuffer(width, height, format, layerCount, usage, requestorName);
     }
 
     void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
                            sp<IGraphicBufferConsumer>* outConsumer,
                            bool consumerIsSurfaceFlinger) override {
-        if (!mCreateBufferQueue) return;
+        if (!mCreateBufferQueue) {
+            BufferQueue::createBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger);
+            return;
+        }
         mCreateBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger);
     }
 
+    sp<IGraphicBufferProducer> createMonitoredProducer(const sp<IGraphicBufferProducer>& producer,
+                                                       const sp<SurfaceFlinger>& flinger,
+                                                       const wp<Layer>& layer) override {
+        return new MonitoredProducer(producer, flinger, layer);
+    }
+
+    sp<BufferLayerConsumer> createBufferLayerConsumer(const sp<IGraphicBufferConsumer>& consumer,
+                                                      renderengine::RenderEngine& renderEngine,
+                                                      uint32_t textureName, Layer* layer) override {
+        return new BufferLayerConsumer(consumer, renderEngine, textureName, layer);
+    }
+
     std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
             const sp<IGraphicBufferProducer>& producer) override {
         if (!mCreateNativeWindowSurface) return nullptr;
@@ -132,22 +138,18 @@
     }
 
     sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs&) override {
-        // TODO: Use test-fixture controlled factory
         return nullptr;
     }
 
     sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs&) override {
-        // TODO: Use test-fixture controlled factory
         return nullptr;
     }
 
     sp<ColorLayer> createColorLayer(const LayerCreationArgs&) override {
-        // TODO: Use test-fixture controlled factory
         return nullptr;
     }
 
     sp<ContainerLayer> createContainerLayer(const LayerCreationArgs&) override {
-        // TODO: Use test-fixture controlled factory
         return nullptr;
     }
 
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 48f26e7..1578d9f 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -519,7 +519,11 @@
       get_device_proc_addr_(nullptr),
       driver_extensions_(nullptr),
       driver_extension_count_(0) {
-    enabled_extensions_.set(driver::ProcHook::EXTENSION_CORE);
+    // advertise the loader supported core Vulkan API version at vulkan::api
+    for (uint32_t i = driver::ProcHook::EXTENSION_CORE_1_0;
+         i != driver::ProcHook::EXTENSION_COUNT; ++i) {
+        enabled_extensions_.set(i);
+    }
 }
 
 LayerChain::~LayerChain() {
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index b413ac9..c3c19ec 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -99,6 +99,7 @@
 
     VkResult Validate();
     void DowngradeApiVersion();
+    void UpgradeDeviceCoreApiVersion(uint32_t api_version);
 
     const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
     const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
@@ -328,8 +329,12 @@
       physical_dev_(VK_NULL_HANDLE),
       instance_info_(create_info),
       extension_filter_() {
-    hook_extensions_.set(ProcHook::EXTENSION_CORE);
-    hal_extensions_.set(ProcHook::EXTENSION_CORE);
+    // instance core versions need to match the loader api version
+    for (uint32_t i = ProcHook::EXTENSION_CORE_1_0;
+         i != ProcHook::EXTENSION_COUNT; ++i) {
+        hook_extensions_.set(i);
+        hal_extensions_.set(i);
+    }
 }
 
 CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
@@ -340,8 +345,9 @@
       physical_dev_(physical_dev),
       dev_info_(create_info),
       extension_filter_() {
-    hook_extensions_.set(ProcHook::EXTENSION_CORE);
-    hal_extensions_.set(ProcHook::EXTENSION_CORE);
+    // initialize with baseline core API version
+    hook_extensions_.set(ProcHook::EXTENSION_CORE_1_0);
+    hal_extensions_.set(ProcHook::EXTENSION_CORE_1_0);
 }
 
 CreateInfoWrapper::~CreateInfoWrapper() {
@@ -540,7 +546,8 @@
             case ProcHook::ANDROID_external_memory_android_hardware_buffer:
             case ProcHook::ANDROID_native_buffer:
             case ProcHook::GOOGLE_display_timing:
-            case ProcHook::EXTENSION_CORE:
+            case ProcHook::EXTENSION_CORE_1_0:
+            case ProcHook::EXTENSION_CORE_1_1:
             case ProcHook::EXTENSION_COUNT:
                 // Device and meta extensions. If we ever get here it's a bug in
                 // our code. But enumerating them lets us avoid having a default
@@ -588,7 +595,8 @@
             case ProcHook::EXT_debug_report:
             case ProcHook::EXT_swapchain_colorspace:
             case ProcHook::ANDROID_native_buffer:
-            case ProcHook::EXTENSION_CORE:
+            case ProcHook::EXTENSION_CORE_1_0:
+            case ProcHook::EXTENSION_CORE_1_1:
             case ProcHook::EXTENSION_COUNT:
                 // Instance and meta extensions. If we ever get here it's a bug
                 // in our code. But enumerating them lets us avoid having a
@@ -636,6 +644,31 @@
     }
 }
 
+void CreateInfoWrapper::UpgradeDeviceCoreApiVersion(uint32_t api_version) {
+    ALOG_ASSERT(!is_instance_, "Device only API called by instance wrapper.");
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wold-style-cast"
+    api_version ^= VK_VERSION_PATCH(api_version);
+#pragma clang diagnostic pop
+
+    // cap the API version to the loader supported highest version
+    if (api_version > VK_API_VERSION_1_1)
+        api_version = VK_API_VERSION_1_1;
+
+    switch (api_version) {
+        case VK_API_VERSION_1_1:
+            hook_extensions_.set(ProcHook::EXTENSION_CORE_1_1);
+            hal_extensions_.set(ProcHook::EXTENSION_CORE_1_1);
+            [[clang::fallthrough]];
+        case VK_API_VERSION_1_0:
+            break;
+        default:
+            ALOGD("Unknown upgrade API version[%u]", api_version);
+            break;
+    }
+}
+
 VKAPI_ATTR void* DefaultAllocate(void*,
                                  size_t size,
                                  size_t alignment,
@@ -771,7 +804,7 @@
                        : nullptr;
             break;
         case ProcHook::DEVICE:
-            proc = (hook->extension == ProcHook::EXTENSION_CORE)
+            proc = (hook->extension == ProcHook::EXTENSION_CORE_1_0)
                        ? hook->proc
                        : hook->checked_proc;
             break;
@@ -1117,6 +1150,13 @@
     if (!data)
         return VK_ERROR_OUT_OF_HOST_MEMORY;
 
+    VkPhysicalDeviceProperties properties;
+    ATRACE_BEGIN("driver.GetPhysicalDeviceProperties");
+    instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
+                                                     &properties);
+    ATRACE_END();
+
+    wrapper.UpgradeDeviceCoreApiVersion(properties.apiVersion);
     data->hook_extensions |= wrapper.GetHookExtensions();
 
     // call into the driver
@@ -1161,12 +1201,6 @@
         return VK_ERROR_INCOMPATIBLE_DRIVER;
     }
 
-    VkPhysicalDeviceProperties properties;
-    ATRACE_BEGIN("driver.GetPhysicalDeviceProperties");
-    instance_data.driver.GetPhysicalDeviceProperties(physicalDevice,
-                                                     &properties);
-    ATRACE_END();
-
     if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) {
         // Log that the app is hitting software Vulkan implementation
         android::GraphicsEnv::getInstance().setTargetStats(
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
index f058c47..61e1818 100644
--- a/vulkan/libvulkan/driver.h
+++ b/vulkan/libvulkan/driver.h
@@ -67,9 +67,7 @@
         : opaque_api_data(),
           allocator(alloc),
           driver(),
-          get_device_proc_addr(nullptr) {
-        hook_extensions.set(ProcHook::EXTENSION_CORE);
-    }
+          get_device_proc_addr(nullptr) {}
 
     api::InstanceData opaque_api_data;
 
@@ -89,9 +87,7 @@
         : opaque_api_data(),
           allocator(alloc),
           debug_report_callbacks(debug_report_callbacks_),
-          driver() {
-        hook_extensions.set(ProcHook::EXTENSION_CORE);
-    }
+          driver() {}
 
     api::DeviceData opaque_api_data;
 
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index 272f2d1..52205e9 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -74,6 +74,15 @@
     }
 }
 
+VKAPI_ATTR VkResult checkedBindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
+    if (GetData(device).hook_extensions[ProcHook::EXTENSION_CORE_1_1]) {
+        return BindImageMemory2(device, bindInfoCount, pBindInfos);
+    } else {
+        Logger(device).Err(device, "VK_VERSION_1_1 not enabled. vkBindImageMemory2 not executed.");
+        return VK_SUCCESS;
+    }
+}
+
 VKAPI_ATTR VkResult checkedBindImageMemory2KHR(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos) {
     if (GetData(device).hook_extensions[ProcHook::KHR_bind_memory2]) {
         return BindImageMemory2KHR(device, bindInfoCount, pBindInfos);
@@ -145,6 +154,14 @@
     }
 }
 
+VKAPI_ATTR void checkedGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) {
+    if (GetData(device).hook_extensions[ProcHook::EXTENSION_CORE_1_1]) {
+        GetDeviceQueue2(device, pQueueInfo, pQueue);
+    } else {
+        Logger(device).Err(device, "VK_VERSION_1_1 not enabled. vkGetDeviceQueue2 not executed.");
+    }
+}
+
 // clang-format on
 
 const ProcHook g_proc_hooks[] = {
@@ -173,16 +190,16 @@
     {
         "vkAllocateCommandBuffers",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers),
         nullptr,
     },
     {
         "vkBindImageMemory2",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_1,
         reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory2),
-        nullptr,
+        reinterpret_cast<PFN_vkVoidFunction>(checkedBindImageMemory2),
     },
     {
         "vkBindImageMemory2KHR",
@@ -208,14 +225,14 @@
     {
         "vkCreateDevice",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(CreateDevice),
         nullptr,
     },
     {
         "vkCreateInstance",
         ProcHook::GLOBAL,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(CreateInstance),
         nullptr,
     },
@@ -243,14 +260,14 @@
     {
         "vkDestroyDevice",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice),
         nullptr,
     },
     {
         "vkDestroyInstance",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance),
         nullptr,
     },
@@ -271,28 +288,28 @@
     {
         "vkEnumerateDeviceExtensionProperties",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties),
         nullptr,
     },
     {
         "vkEnumerateInstanceExtensionProperties",
         ProcHook::GLOBAL,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties),
         nullptr,
     },
     {
         "vkEnumeratePhysicalDeviceGroups",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_1,
         reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDeviceGroups),
         nullptr,
     },
     {
         "vkEnumeratePhysicalDevices",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices),
         nullptr,
     },
@@ -313,28 +330,28 @@
     {
         "vkGetDeviceProcAddr",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr),
         nullptr,
     },
     {
         "vkGetDeviceQueue",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue),
         nullptr,
     },
     {
         "vkGetDeviceQueue2",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_1,
         reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue2),
-        nullptr,
+        reinterpret_cast<PFN_vkVoidFunction>(checkedGetDeviceQueue2),
     },
     {
         "vkGetInstanceProcAddr",
         ProcHook::INSTANCE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr),
         nullptr,
     },
@@ -446,7 +463,7 @@
     {
         "vkQueueSubmit",
         ProcHook::DEVICE,
-        ProcHook::EXTENSION_CORE,
+        ProcHook::EXTENSION_CORE_1_0,
         reinterpret_cast<PFN_vkVoidFunction>(QueueSubmit),
         nullptr,
     },
@@ -562,5 +579,3 @@
 
 }  // namespace driver
 }  // namespace vulkan
-
-// clang-format on
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index cd7d8f8..43c4d14 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -49,7 +49,8 @@
         KHR_bind_memory2,
         KHR_get_physical_device_properties2,
 
-        EXTENSION_CORE,  // valid bit
+        EXTENSION_CORE_1_0,
+        EXTENSION_CORE_1_1,
         EXTENSION_COUNT,
         EXTENSION_UNKNOWN,
     };
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index d60eaa7..bbf50a1 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1291,6 +1291,7 @@
     VkImageCreateInfo image_create = {
         .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
         .pNext = &image_native_buffer,
+        .flags = createProtectedSwapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
         .imageType = VK_IMAGE_TYPE_2D,
         .format = create_info->imageFormat,
         .extent = {0, 0, 1},
@@ -1299,7 +1300,6 @@
         .samples = VK_SAMPLE_COUNT_1_BIT,
         .tiling = VK_IMAGE_TILING_OPTIMAL,
         .usage = create_info->imageUsage,
-        .flags = createProtectedSwapchain ? VK_IMAGE_CREATE_PROTECTED_BIT : 0u,
         .sharingMode = create_info->imageSharingMode,
         .queueFamilyIndexCount = create_info->queueFamilyIndexCount,
         .pQueueFamilyIndices = create_info->pQueueFamilyIndices,
diff --git a/vulkan/scripts/api_generator.py b/vulkan/scripts/api_generator.py
index a0c648c..7c39075 100644
--- a/vulkan/scripts/api_generator.py
+++ b/vulkan/scripts/api_generator.py
@@ -13,28 +13,46 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
-# This script provides the functions required for generating the
-# vulkan api framework directly from the vulkan registry (vk.xml)
+
+"""Generates the api_gen.h and api_gen.cpp.
+"""
 
 import os
 import generator_common as gencom
 
-def isInstanceDispatchTableEntry(functionName):
-  if functionName == 'vkEnumerateDeviceLayerProperties': # deprecated, unused internally - @dbd33bc
-    return False
-  if gencom.gencom.isFunctionExported(functionName) and gencom.isInstanceDispatched(functionName):
-    return True
-  return False
+# Functions intercepted at vulkan::api level.
+_INTERCEPTED_COMMANDS = [
+    'vkCreateDevice',
+    'vkDestroyDevice',
+    'vkDestroyInstance',
+    'vkEnumerateDeviceExtensionProperties',
+    'vkEnumerateDeviceLayerProperties',
+]
 
-def isDeviceDispatchTableEntry(functionName):
-  if gencom.gencom.isFunctionExported(functionName) and gencom.gencom.isDeviceDispatched(functionName):
-    return True
-  return False
 
-def api_genh():
+def gen_h():
+  """Generates the api_gen.h file.
+  """
+  genfile = os.path.join(os.path.dirname(__file__),
+                         '..', 'libvulkan', 'api_gen.h')
 
-  header = """#ifndef LIBVULKAN_API_GEN_H
+  with open(genfile, 'w') as f:
+    instance_dispatch_table_entries = []
+    device_dispatch_table_entries = []
+
+    for cmd in gencom.command_list:
+      if cmd not in gencom.alias_dict:
+        if gencom.is_instance_dispatch_table_entry(cmd):
+          instance_dispatch_table_entries.append(
+              'PFN_' + cmd + ' ' + gencom.base_name(cmd) + ';')
+        elif gencom.is_device_dispatch_table_entry(cmd):
+          device_dispatch_table_entries.append(
+              'PFN_' + cmd + ' ' + gencom.base_name(cmd) + ';')
+
+    f.write(gencom.copyright_and_warning(2016))
+
+    f.write("""\
+#ifndef LIBVULKAN_API_GEN_H
 #define LIBVULKAN_API_GEN_H
 
 #include <vulkan/vulkan.h>
@@ -46,9 +64,26 @@
 namespace vulkan {
 namespace api {
 
-"""
+struct InstanceDispatchTable {
+    // clang-format off\n""")
 
-  tail = """
+    for entry in instance_dispatch_table_entries:
+      f.write(gencom.indent(1) + entry + '\n')
+
+    f.write("""\
+    // clang-format on
+};
+
+struct DeviceDispatchTable {
+    // clang-format off\n""")
+
+    for entry in device_dispatch_table_entries:
+      f.write(gencom.indent(1) + entry + '\n')
+
+    f.write("""\
+    // clang-format on
+};
+
 bool InitDispatchTable(
     VkInstance instance,
     PFN_vkGetInstanceProcAddr get_proc,
@@ -61,105 +96,70 @@
 }  // namespace api
 }  // namespace vulkan
 
-#endif  // LIBVULKAN_API_GEN_H
-"""
-  genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','api_gen.h')
-  with open(genfile, 'w') as f:
-    instanceDispatchTableEntries = []
-    deviceDispatchTableEntries = []
-    for commands in gencom.allCommandsList:
-      if commands not in gencom.aliasDict:
-        if gencom.isInstanceDispatchTableEntry(commands):
-          instanceDispatchTableEntries.append('PFN_'+commands+' '+commands[2:]+';')
-        elif gencom.isDeviceDispatchTableEntry(commands):
-          deviceDispatchTableEntries.append('PFN_'+commands+' '+commands[2:]+';')
+#endif  // LIBVULKAN_API_GEN_H\n""")
 
-    f.write (gencom.copyright)
-    f.write (gencom.warning)
-    f.write (header)
-    f.write ('struct InstanceDispatchTable {\n')
-    gencom.clang_off(f,1)
-    for functions in instanceDispatchTableEntries:
-      f.write(gencom.clang_off_spaces + functions + '\n')
-    gencom.clang_on(f,1)
-    f.write ('};\n\n')
-
-    f.write ('struct DeviceDispatchTable {\n')
-    gencom.clang_off(f,1)
-    for functions in deviceDispatchTableEntries:
-      f.write(gencom.clang_off_spaces + functions + '\n')
-    gencom.clang_on(f,1)
-    f.write ('};\n')
-
-    f.write (tail)
     f.close()
-  gencom.runClangFormat(genfile)
+  gencom.run_clang_format(genfile)
 
-def defineInitProc(name, f):
-  f.write ('#define UNLIKELY(expr) __builtin_expect((expr), 0)\n')
-  f.write ('\n')
-  f.write ("""#define INIT_PROC(required, obj, proc)                                 \\
-    do {                                                               \\
-        data.""" + name + """.proc =                                           \\
-            reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
-        if (UNLIKELY(required && !data.""" + name + """.proc)) {               \\
-            ALOGE("missing " #obj " proc: vk" #proc);                  \\
-            success = false;                                           \\
-        }                                                              \\
-    } while (0)\n\n""")
 
-def defineInitProcExt(f):
-  f.write ('// Exported extension functions may be invoked even when their extensions\n')
-  f.write ('// are disabled.  Dispatch to stubs when that happens.\n')
-  f.write ("""#define INIT_PROC_EXT(ext, required, obj, proc)  \\
-    do {                                         \\
-        if (extensions[driver::ProcHook::ext])   \\
-            INIT_PROC(required, obj, proc);      \\
-        else                                     \\
-            data.dispatch.proc = disabled##proc; \\
-    } while (0)\n\n""")
+def _define_extension_stub(cmd, f):
+  """Emits a stub for an exported extension function.
 
-def defineExtensionStub(functionName, f):
-  if functionName in gencom.extensionsDict and gencom.isFunctionExported(functionName):
-    extname = gencom.extensionsDict[functionName]
-    base_name = functionName[2:]
-    pList = gencom.paramDict[functionName]
-    firstParam = pList[0][0] + pList[0][1]
-    tailParams = [x[0][:-1] for x in pList[1:]]
-    tailP = ', '.join(tailParams)
-    f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[functionName] + ' disabled' + base_name + '(' + firstParam + ', ' + tailP + ') {\n')
-    f.write (gencom.clang_off_spaces)
-    f.write ('driver::Logger(' + pList[0][1] + ').Err(' + pList[0][1] + ', \"' + extname + ' not enabled. Exported ' + functionName + ' not executed.\");\n')
-    if gencom.returnTypeDict[functionName] != 'void':
-      f.write(gencom.clang_off_spaces + 'return VK_SUCCESS;\n')
-    f.write ('}\n\n')
+  Args:
+    cmd: Vulkan function name.
+    f: Output file handle.
+  """
+  if (cmd in gencom.extension_dict and gencom.is_function_exported(cmd)):
+    ext_name = gencom.extension_dict[cmd]
+    ret = gencom.return_type_dict[cmd]
+    params = gencom.param_dict[cmd]
+    first_param = params[0][0] + params[0][1]
+    tail_params = ', '.join([i[0][:-1] for i in params[1:]])
 
-def isIntercepted(functionName):
-  if gencom.isFunctionSupported(functionName):
-    if gencom.isGloballyDispatched(functionName):
-      return True
-    elif functionName == 'vkCreateDevice':
-      return True
-    elif functionName == 'vkEnumerateDeviceLayerProperties':
-      return True
-    elif functionName == 'vkEnumerateDeviceExtensionProperties':
-      return True
-    elif functionName == 'vkDestroyInstance':
-      return True
-    elif functionName == 'vkDestroyDevice':
+    f.write('VKAPI_ATTR ' + ret + ' disabled' + gencom.base_name(cmd) +
+            '(' + first_param + ', ' + tail_params + ') {\n')
+
+    f.write(gencom.indent(1) + 'driver::Logger(' + params[0][1] +
+            ').Err(' + params[0][1] + ', \"' + ext_name +
+            ' not enabled. Exported ' + cmd + ' not executed.\");\n')
+
+    if gencom.return_type_dict[cmd] != 'void':
+      f.write(gencom.indent(1) + 'return VK_SUCCESS;\n')
+
+    f.write('}\n\n')
+
+
+def _is_intercepted(cmd):
+  """Returns true if a function is intercepted by vulkan::api.
+
+  Args:
+    cmd: Vulkan function name.
+  """
+  if gencom.is_function_supported(cmd):
+    if gencom.is_globally_dispatched(cmd) or cmd in _INTERCEPTED_COMMANDS:
       return True
   return False
 
-def interceptInstanceProcAddr(functionName, f):
-  indent = 1
-  f.write (gencom.clang_off_spaces*indent + '// global functions\n' + gencom.clang_off_spaces*indent+ 'if (instance == VK_NULL_HANDLE) {\n')
-  indent = indent + 1
-  for cmds in gencom.allCommandsList:
-    if gencom.isGloballyDispatched(cmds):
-      f.write(gencom.clang_off_spaces*indent + 'if (strcmp(pName, \"' + cmds + '\") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ');\n')
 
-  f.write ('\n')
-  f.write ("""        ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \\\"%s\\\") call", pName);
+def _intercept_instance_proc_addr(f):
+  """Emits code for vkGetInstanceProcAddr for function interception.
+
+  Args:
+    f: Output file handle.
+  """
+  f.write("""\
+    // global functions
+    if (instance == VK_NULL_HANDLE) {\n""")
+
+  for cmd in gencom.command_list:
+    if gencom.is_globally_dispatched(cmd):
+      f.write(gencom.indent(2) +
+              'if (strcmp(pName, \"' + cmd +
+              '\") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' +
+              gencom.base_name(cmd) + ');\n')
+
+  f.write("""
+        ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \\\"%s\\\") call", pName);
         return nullptr;
     }
 
@@ -167,14 +167,21 @@
         const char* name;
         PFN_vkVoidFunction proc;
     } hooks[] = {\n""")
-  sortedCommandsList = sorted(gencom.allCommandsList)
-  for cmds in sortedCommandsList:
-    if gencom.isFunctionExported(cmds):
-      if gencom.isGloballyDispatched(cmds):
-        f.write (gencom.clang_off_spaces*2 + '{ \"' + cmds + '\", nullptr },\n')
-      elif isIntercepted(cmds) or cmds == 'vkGetInstanceProcAddr' or gencom.isDeviceDispatched(cmds):
-        f.write (gencom.clang_off_spaces*2 + '{ \"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ') },\n')
-  f.write (gencom.clang_off_spaces + """};
+
+  sorted_command_list = sorted(gencom.command_list)
+  for cmd in sorted_command_list:
+    if gencom.is_function_exported(cmd):
+      if gencom.is_globally_dispatched(cmd):
+        f.write(gencom.indent(2) + '{ \"' + cmd + '\", nullptr },\n')
+      elif (_is_intercepted(cmd) or
+            cmd == 'vkGetInstanceProcAddr' or
+            gencom.is_device_dispatched(cmd)):
+        f.write(gencom.indent(2) + '{ \"' + cmd +
+                '\", reinterpret_cast<PFN_vkVoidFunction>(' +
+                gencom.base_name(cmd) + ') },\n')
+
+  f.write("""\
+    };
     // clang-format on
     constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
     auto hook = std::lower_bound(
@@ -190,19 +197,30 @@
     }
     // clang-format off\n\n""")
 
-def interceptDeviceProcAddr(functionName, f):
-  f.write (gencom.clang_off_spaces + """if (device == VK_NULL_HANDLE) {
+
+def _intercept_device_proc_addr(f):
+  """Emits code for vkGetDeviceProcAddr for function interception.
+
+  Args:
+    f: Output file handle.
+  """
+  f.write("""\
+    if (device == VK_NULL_HANDLE) {
         ALOGE("invalid vkGetDeviceProcAddr(VK_NULL_HANDLE, ...) call");
         return nullptr;
-    }\n\n""")
-  f.write (gencom.clang_off_spaces + 'static const char* const known_non_device_names[] = {\n')
-  sortedCommandsList = sorted(gencom.allCommandsList)
-  for cmds in sortedCommandsList:
-    if gencom.isFunctionSupported(cmds):
-      if not gencom.isDeviceDispatched(cmds):
-        f.write(gencom.clang_off_spaces*2 + '\"' + cmds + '\",\n')
-  f.write(gencom.clang_off_spaces + '};\n')
-  f.write(gencom.clang_off_spaces + """// clang-format on
+    }
+
+    static const char* const known_non_device_names[] = {\n""")
+
+  sorted_command_list = sorted(gencom.command_list)
+  for cmd in sorted_command_list:
+    if gencom.is_function_supported(cmd):
+      if not gencom.is_device_dispatched(cmd):
+        f.write(gencom.indent(2) + '\"' + cmd + '\",\n')
+
+  f.write("""\
+    };
+    // clang-format on
     constexpr size_t count =
         sizeof(known_non_device_names) / sizeof(known_non_device_names[0]);
     if (!pName ||
@@ -215,27 +233,46 @@
         return nullptr;
     }
     // clang-format off\n\n""")
-  for cmds in gencom.allCommandsList:
-    if gencom.isDeviceDispatched(cmds):
-      if isIntercepted(cmds) or cmds == 'vkGetDeviceProcAddr':
-        f.write (gencom.clang_off_spaces + 'if (strcmp(pName, "' + cmds + '") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' + cmds[2:] + ');\n')
-  f.write ('\n')
 
-def apiDispatch(functionName, f):
-  assert not isIntercepted(functionName)
-
-  f.write (gencom.clang_off_spaces)
-  if gencom.returnTypeDict[functionName] != 'void':
-    f.write ('return ')
-
-  paramList = gencom.paramDict[functionName]
-  p0 = paramList[0][1]
-  f.write('GetData(' + p0 + ').dispatch.' + functionName[2:] + '(' + ', '.join(i[1] for i in paramList) + ');\n')
+  for cmd in gencom.command_list:
+    if gencom.is_device_dispatched(cmd):
+      if _is_intercepted(cmd) or cmd == 'vkGetDeviceProcAddr':
+        f.write(gencom.indent(1) + 'if (strcmp(pName, "' + cmd +
+                '") == 0) return reinterpret_cast<PFN_vkVoidFunction>(' +
+                gencom.base_name(cmd) + ');\n')
+  f.write('\n')
 
 
-def api_gencpp():
-  genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','api_gen.cpp')
-  header = """#include <log/log.h>
+def _api_dispatch(cmd, f):
+  """Emits code to dispatch a function.
+
+  Args:
+    cmd: Vulkan function name.
+    f: Output file handle.
+  """
+  assert not _is_intercepted(cmd)
+
+  f.write(gencom.indent(1))
+  if gencom.return_type_dict[cmd] != 'void':
+    f.write('return ')
+
+  param_list = gencom.param_dict[cmd]
+  handle = param_list[0][1]
+  f.write('GetData(' + handle + ').dispatch.' + gencom.base_name(cmd) +
+          '(' + ', '.join(i[1] for i in param_list) + ');\n')
+
+
+def gen_cpp():
+  """Generates the api_gen.cpp file.
+  """
+  genfile = os.path.join(os.path.dirname(__file__),
+                         '..', 'libvulkan', 'api_gen.cpp')
+
+  with open(genfile, 'w') as f:
+    f.write(gencom.copyright_and_warning(2016))
+
+    f.write("""\
+#include <log/log.h>
 #include <string.h>
 
 #include <algorithm>
@@ -247,80 +284,106 @@
 namespace vulkan {
 namespace api {
 
-"""
-  with open(genfile, 'w') as f:
-    f.write (gencom.copyright)
-    f.write (gencom.warning)
-    f.write ("""#include <log/log.h>
-#include <string.h>
+#define UNLIKELY(expr) __builtin_expect((expr), 0)
 
-#include <algorithm>
+#define INIT_PROC(required, obj, proc)                                 \\
+    do {                                                               \\
+        data.dispatch.proc =                                           \\
+            reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
+        if (UNLIKELY(required && !data.dispatch.proc)) {               \\
+            ALOGE("missing " #obj " proc: vk" #proc);                  \\
+            success = false;                                           \\
+        }                                                              \\
+    } while (0)
 
-// to catch mismatches between vulkan.h and this file
-#undef VK_NO_PROTOTYPES
-#include "api.h"
+// Exported extension functions may be invoked even when their extensions
+// are disabled.  Dispatch to stubs when that happens.
+#define INIT_PROC_EXT(ext, required, obj, proc)  \\
+    do {                                         \\
+        if (extensions[driver::ProcHook::ext])   \\
+            INIT_PROC(required, obj, proc);      \\
+        else                                     \\
+            data.dispatch.proc = disabled##proc; \\
+    } while (0)
 
-namespace vulkan {
-namespace api {\n\n""")
-    defineInitProc('dispatch',f)
-    defineInitProcExt(f)
-    f.write ('namespace {\n\n')
-    gencom.clang_off(f,0)
-    f.write ('\n')
-    for cmds in gencom.allCommandsList:
-      defineExtensionStub(cmds,f)
-    gencom.clang_on(f,0)
-    f.write ('\n}  // namespace\n\n')
-    f.write ("""bool InitDispatchTable(
+namespace {
+
+// clang-format off\n\n""")
+
+    for cmd in gencom.command_list:
+      _define_extension_stub(cmd, f)
+
+    f.write("""\
+// clang-format on
+
+}  // namespace
+
+bool InitDispatchTable(
     VkInstance instance,
     PFN_vkGetInstanceProcAddr get_proc,
     const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
     auto& data = GetData(instance);
-    bool success = true;\n\n""")
-    gencom.clang_off(f,1)
-    for cmds in gencom.allCommandsList:
-      if gencom.isInstanceDispatchTableEntry(cmds):
-        gencom.initProc(cmds, f)
-    gencom.clang_on(f,1)
-    f.write ('\n')
-    f.write ('    return success;\n}\n\n')
-    f.write ("""bool InitDispatchTable(
+    bool success = true;
+
+    // clang-format off\n""")
+
+    for cmd in gencom.command_list:
+      if gencom.is_instance_dispatch_table_entry(cmd):
+        gencom.init_proc(cmd, f)
+
+    f.write("""\
+    // clang-format on
+
+    return success;
+}
+
+bool InitDispatchTable(
     VkDevice dev,
     PFN_vkGetDeviceProcAddr get_proc,
     const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
     auto& data = GetData(dev);
-    bool success = true;\n\n""")
+    bool success = true;
 
-    gencom.clang_off(f,1)
-    for cmds in gencom.allCommandsList:
-      if gencom.isDeviceDispatchTableEntry(cmds):
-        gencom.initProc(cmds, f)
-    gencom.clang_on(f,1)
-    f.write ('\n')
-    f.write ('    return success;\n}\n\n')
+    // clang-format off\n""")
 
-    gencom.clang_off(f,0)
+    for cmd in gencom.command_list:
+      if gencom.is_device_dispatch_table_entry(cmd):
+        gencom.init_proc(cmd, f)
 
-    f.write ('\nnamespace {\n\n')
-    f.write('// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr\n')
-    for cmds in gencom.allCommandsList:
-      if gencom.isFunctionExported(cmds) and not isIntercepted(cmds):
-        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
-        f.write ('VKAPI_ATTR '+gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' + ', '.join(paramList) + ');\n')
+    f.write("""\
+    // clang-format on
 
-    f.write ('\n')
+    return success;
+}
 
-    for cmds in gencom.allCommandsList:
-      if gencom.isFunctionExported(cmds) and not isIntercepted(cmds):
-        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
-        f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' + ', '.join(paramList) + ') {\n')
-        if cmds == 'vkGetInstanceProcAddr':
-          interceptInstanceProcAddr(cmds, f)
-        elif cmds == 'vkGetDeviceProcAddr':
-          interceptDeviceProcAddr(cmds, f)
-        apiDispatch(cmds, f)
+// clang-format off
+
+namespace {
+
+// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr
+""")
+
+    for cmd in gencom.command_list:
+      if gencom.is_function_exported(cmd) and not _is_intercepted(cmd):
+        param_list = [''.join(i) for i in gencom.param_dict[cmd]]
+        f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' +
+                gencom.base_name(cmd) + '(' + ', '.join(param_list) + ');\n')
+
+    f.write('\n')
+    for cmd in gencom.command_list:
+      if gencom.is_function_exported(cmd) and not _is_intercepted(cmd):
+        param_list = [''.join(i) for i in gencom.param_dict[cmd]]
+        f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' +
+                gencom.base_name(cmd) + '(' + ', '.join(param_list) + ') {\n')
+        if cmd == 'vkGetInstanceProcAddr':
+          _intercept_instance_proc_addr(f)
+        elif cmd == 'vkGetDeviceProcAddr':
+          _intercept_device_proc_addr(f)
+        _api_dispatch(cmd, f)
         f.write('}\n\n')
-    f.write ("""\n}  // anonymous namespace
+
+    f.write("""
+}  // anonymous namespace
 
 // clang-format on
 
@@ -329,18 +392,19 @@
 
 // clang-format off\n\n""")
 
-    for cmds in gencom.allCommandsList:
-      if gencom.isFunctionExported(cmds):
-        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
-        f.write ('__attribute__((visibility("default")))\n')
-        f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds + '(' + ', '.join(paramList) + ') {\n')
-        f.write (gencom.clang_off_spaces)
-        if gencom.returnTypeDict[cmds] != 'void':
-          f.write ('return ')
-        paramList = gencom.paramDict[cmds]
-        f.write ('vulkan::api::' + cmds[2:] + '(' + ', '.join(i[1] for i in paramList) + ');\n')
-        f.write ('}\n\n')
+    for cmd in gencom.command_list:
+      if gencom.is_function_exported(cmd):
+        param_list = [''.join(i) for i in gencom.param_dict[cmd]]
+        f.write('__attribute__((visibility("default")))\n')
+        f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' +
+                cmd + '(' + ', '.join(param_list) + ') {\n')
+        f.write(gencom.indent(1))
+        if gencom.return_type_dict[cmd] != 'void':
+          f.write('return ')
+        param_list = gencom.param_dict[cmd]
+        f.write('vulkan::api::' + gencom.base_name(cmd) +
+                '(' + ', '.join(i[1] for i in param_list) + ');\n}\n\n')
 
-    gencom.clang_on(f, 0)
+    f.write('// clang-format on\n')
     f.close()
-  gencom.runClangFormat(genfile)
+  gencom.run_clang_format(genfile)
diff --git a/vulkan/scripts/code_generator.py b/vulkan/scripts/code_generator.py
index 39fedf4..2a017d2 100755
--- a/vulkan/scripts/code_generator.py
+++ b/vulkan/scripts/code_generator.py
@@ -13,20 +13,20 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
-# This script provides the main function for generating
-# vulkan framework directly from the vulkan registry (vk.xml).
 
-import generator_common as gencom
-import api_generator as apigen
-import driver_generator as drivergen
-import null_generator as nullgen
+"""Generates vulkan framework directly from the vulkan registry (vk.xml).
+"""
+
+import api_generator
+import driver_generator
+import generator_common
+import null_generator
 
 if __name__ == '__main__':
-  gencom.parseVulkanRegistry()
-  apigen.api_genh()
-  apigen.api_gencpp()
-  drivergen.driver_genh()
-  drivergen.driver_gencpp()
-  nullgen.null_driver_genh()
-  nullgen.null_driver_gencpp()
+  generator_common.parse_vulkan_registry()
+  api_generator.gen_h()
+  api_generator.gen_cpp()
+  driver_generator.gen_h()
+  driver_generator.gen_cpp()
+  null_generator.gen_h()
+  null_generator.gen_cpp()
diff --git a/vulkan/scripts/driver_generator.py b/vulkan/scripts/driver_generator.py
index 4868ac0..a64a702 100644
--- a/vulkan/scripts/driver_generator.py
+++ b/vulkan/scripts/driver_generator.py
@@ -13,45 +13,176 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
-# This script provides the functions for generating the
-# vulkan driver framework directly from the vulkan registry (vk.xml).
 
-import generator_common as gencom
+"""Generates the driver_gen.h and driver_gen.cpp.
+"""
+
 import os
+import generator_common as gencom
 
-interceptedExtensions = [
-  'VK_ANDROID_native_buffer',
-  'VK_EXT_debug_report',
-  'VK_EXT_hdr_metadata',
-  'VK_EXT_swapchain_colorspace',
-  'VK_GOOGLE_display_timing',
-  'VK_KHR_android_surface',
-  'VK_KHR_get_surface_capabilities2',
-  'VK_KHR_incremental_present',
-  'VK_KHR_shared_presentable_image',
-  'VK_KHR_surface',
-  'VK_KHR_swapchain',
+# Extensions intercepted at vulkan::driver level.
+_INTERCEPTED_EXTENSIONS = [
+    'VK_ANDROID_native_buffer',
+    'VK_EXT_debug_report',
+    'VK_EXT_hdr_metadata',
+    'VK_EXT_swapchain_colorspace',
+    'VK_GOOGLE_display_timing',
+    'VK_KHR_android_surface',
+    'VK_KHR_get_surface_capabilities2',
+    'VK_KHR_incremental_present',
+    'VK_KHR_shared_presentable_image',
+    'VK_KHR_surface',
+    'VK_KHR_swapchain',
 ]
 
-knownExtensions = interceptedExtensions + [
-  'VK_ANDROID_external_memory_android_hardware_buffer',
-  'VK_KHR_bind_memory2',
-  'VK_KHR_get_physical_device_properties2',
+# Extensions known to vulkan::driver level.
+_KNOWN_EXTENSIONS = _INTERCEPTED_EXTENSIONS + [
+    'VK_ANDROID_external_memory_android_hardware_buffer',
+    'VK_KHR_bind_memory2',
+    'VK_KHR_get_physical_device_properties2',
 ]
 
-def defineProcHookType(f):
-  f.write ("""struct ProcHook {
+# Functions needed at vulkan::driver level.
+_NEEDED_COMMANDS = [
+    # Create functions of dispatchable objects
+    'vkCreateDevice',
+    'vkGetDeviceQueue',
+    'vkGetDeviceQueue2',
+    'vkAllocateCommandBuffers',
+
+    # Destroy functions of dispatchable objects
+    'vkDestroyInstance',
+    'vkDestroyDevice',
+
+    # Enumeration of extensions
+    'vkEnumerateDeviceExtensionProperties',
+
+    # We cache physical devices in loader.cpp
+    'vkEnumeratePhysicalDevices',
+    'vkEnumeratePhysicalDeviceGroups',
+
+    'vkGetInstanceProcAddr',
+    'vkGetDeviceProcAddr',
+
+    'vkQueueSubmit',
+
+    # VK_KHR_swapchain->VK_ANDROID_native_buffer translation
+    'vkCreateImage',
+    'vkDestroyImage',
+
+    'vkGetPhysicalDeviceProperties',
+    'vkGetPhysicalDeviceProperties2',
+    'vkGetPhysicalDeviceProperties2KHR',
+
+    # VK_KHR_swapchain v69 requirement
+    'vkBindImageMemory2',
+    'vkBindImageMemory2KHR',
+]
+
+# Functions intercepted at vulkan::driver level.
+_INTERCEPTED_COMMANDS = [
+    # Create functions of dispatchable objects
+    'vkCreateInstance',
+    'vkCreateDevice',
+    'vkEnumeratePhysicalDevices',
+    'vkEnumeratePhysicalDeviceGroups',
+    'vkGetDeviceQueue',
+    'vkGetDeviceQueue2',
+    'vkAllocateCommandBuffers',
+
+    # Destroy functions of dispatchable objects
+    'vkDestroyInstance',
+    'vkDestroyDevice',
+
+    # Enumeration of extensions
+    'vkEnumerateInstanceExtensionProperties',
+    'vkEnumerateDeviceExtensionProperties',
+
+    'vkGetInstanceProcAddr',
+    'vkGetDeviceProcAddr',
+
+    'vkQueueSubmit',
+
+    # VK_KHR_swapchain v69 requirement
+    'vkBindImageMemory2',
+    'vkBindImageMemory2KHR',
+]
+
+
+def _is_driver_table_entry(cmd):
+  """Returns true if a function is needed by vulkan::driver.
+
+  Args:
+    cmd: Vulkan function name.
+  """
+  if gencom.is_function_supported(cmd):
+    if cmd in _NEEDED_COMMANDS:
+      return True
+    if cmd in gencom.extension_dict:
+      if (gencom.extension_dict[cmd] == 'VK_ANDROID_native_buffer' or
+          gencom.extension_dict[cmd] == 'VK_EXT_debug_report'):
+        return True
+  return False
+
+
+def _is_instance_driver_table_entry(cmd):
+  """Returns true if a instance-dispatched function is needed by vulkan::driver.
+
+  Args:
+    cmd: Vulkan function name.
+  """
+  return (_is_driver_table_entry(cmd) and
+          gencom.is_instance_dispatched(cmd))
+
+
+def _is_device_driver_table_entry(cmd):
+  """Returns true if a device-dispatched function is needed by vulkan::driver.
+
+  Args:
+    cmd: Vulkan function name.
+  """
+  return (_is_driver_table_entry(cmd) and
+          gencom.is_device_dispatched(cmd))
+
+
+def gen_h():
+  """Generates the driver_gen.h file.
+  """
+  genfile = os.path.join(os.path.dirname(__file__),
+                         '..', 'libvulkan', 'driver_gen.h')
+
+  with open(genfile, 'w') as f:
+    f.write(gencom.copyright_and_warning(2016))
+
+    f.write("""\
+#ifndef LIBVULKAN_DRIVER_GEN_H
+#define LIBVULKAN_DRIVER_GEN_H
+
+#include <vulkan/vk_android_native_buffer.h>
+#include <vulkan/vulkan.h>
+
+#include <bitset>
+
+namespace vulkan {
+namespace driver {
+
+struct ProcHook {
     enum Type {
         GLOBAL,
         INSTANCE,
         DEVICE,
     };
     enum Extension {\n""")
-  for exts in knownExtensions:
-    f.write (gencom.clang_off_spaces*2 + exts[3:] + ',\n')
-  f.write ('\n')
-  f.write (gencom.clang_off_spaces*2 + """EXTENSION_CORE,  // valid bit
+
+    for ext in _KNOWN_EXTENSIONS:
+      f.write(gencom.indent(2) + gencom.base_ext_name(ext) + ',\n')
+
+    f.write('\n')
+    for version in gencom.version_code_list:
+      f.write(gencom.indent(2) + 'EXTENSION_CORE_' + version + ',\n')
+
+    # EXTENSION_COUNT must be the next enum after the highest API version.
+    f.write("""\
         EXTENSION_COUNT,
         EXTENSION_UNKNOWN,
     };
@@ -62,99 +193,33 @@
 
     PFN_vkVoidFunction proc;
     PFN_vkVoidFunction checked_proc;  // always nullptr for non-device hooks
-};\n\n""")
+};
 
-def isExtensionIntercepted(extensionName):
-  if extensionName in interceptedExtensions:
-    return True
-  return False
+struct InstanceDriverTable {
+    // clang-format off\n""")
 
-def isDriverTableEntry(functionName):
-  switchCase = {
-    # Create functions of dispatchable objects
-    'vkCreateDevice' : True,
-    'vkGetDeviceQueue' : True,
-    'vkGetDeviceQueue2' : True,
-    'vkAllocateCommandBuffers' : True,
+    for cmd in gencom.command_list:
+      if _is_instance_driver_table_entry(cmd):
+        f.write(gencom.indent(1) + 'PFN_' + cmd + ' ' +
+                gencom.base_name(cmd) + ';\n')
 
-    # Destroy functions of dispatchable objects
-    'vkDestroyInstance' : True,
-    'vkDestroyDevice' : True,
+    f.write("""\
+    // clang-format on
+};
 
-    # Enumeration of extensions
-    'vkEnumerateDeviceExtensionProperties' : True,
+struct DeviceDriverTable {
+    // clang-format off\n""")
 
-    # We cache physical devices in loader.cpp
-    'vkEnumeratePhysicalDevices' : True,
-    'vkEnumeratePhysicalDeviceGroups' : True,
+    for cmd in gencom.command_list:
+      if _is_device_driver_table_entry(cmd):
+        f.write(gencom.indent(1) + 'PFN_' + cmd + ' ' +
+                gencom.base_name(cmd) + ';\n')
 
-    'vkGetInstanceProcAddr' : True,
-    'vkGetDeviceProcAddr' : True,
+    f.write("""\
+    // clang-format on
+};
 
-    'vkQueueSubmit' : True,
-
-    # VK_KHR_swapchain->VK_ANDROID_native_buffer translation
-    'vkCreateImage' : True,
-    'vkDestroyImage' : True,
-
-    'vkGetPhysicalDeviceProperties' : True,
-    'vkGetPhysicalDeviceProperties2' : True,
-    'vkGetPhysicalDeviceProperties2KHR' : True,
-
-    # VK_KHR_swapchain v69 requirement
-    'vkBindImageMemory2' : True,
-    'vkBindImageMemory2KHR' : True
-  }
-  if gencom.isFunctionSupported(functionName):
-    if functionName in switchCase:
-      return True
-    if functionName in gencom.extensionsDict:
-      if gencom.extensionsDict[functionName] == 'VK_ANDROID_native_buffer' or gencom.extensionsDict[functionName] == 'VK_EXT_debug_report':
-        return True
-  return False
-
-def isInstanceDriverTableEntry(functionName):
-  if isDriverTableEntry(functionName) and gencom.isInstanceDispatched(functionName):
-    return True
-  return False
-
-def isDeviceDriverTableEntry(functionName):
-  if isDriverTableEntry(functionName) and gencom.isDeviceDispatched(functionName):
-    return True
-  return False
-
-def driver_genh():
-  header = """#ifndef LIBVULKAN_DRIVER_GEN_H
-#define LIBVULKAN_DRIVER_GEN_H
-
-#include <vulkan/vk_android_native_buffer.h>
-#include <vulkan/vulkan.h>
-
-#include <bitset>
-
-namespace vulkan {
-namespace driver {\n\n"""
-  genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','driver_gen.h')
-  with open(genfile, 'w') as f:
-    f.write (gencom.copyright)
-    f.write (gencom.warning)
-    f.write (header)
-    defineProcHookType(f)
-    f.write ('struct InstanceDriverTable {\n')
-    gencom.clang_off(f, 1)
-    for cmds in gencom.allCommandsList:
-      if isInstanceDriverTableEntry(cmds):
-        f.write (gencom.clang_off_spaces + 'PFN_' + cmds + ' ' + cmds[2:] + ';\n')
-    gencom.clang_on(f, 1)
-    f.write ('};\n\n')
-    f.write ('struct DeviceDriverTable {\n')
-    gencom.clang_off(f,1)
-    for cmds in gencom.allCommandsList:
-      if isDeviceDriverTableEntry(cmds):
-        f.write (gencom.clang_off_spaces + 'PFN_' + cmds + ' ' + cmds[2:] + ';\n')
-    gencom.clang_on(f,1)
-    f.write ('};\n\n')
-    f.write ("""const ProcHook* GetProcHook(const char* name);
+const ProcHook* GetProcHook(const char* name);
 ProcHook::Extension GetProcHookExtension(const char* name);
 
 bool InitDriverTable(VkInstance instance,
@@ -168,148 +233,198 @@
 }  // namespace vulkan
 
 #endif  // LIBVULKAN_DRIVER_TABLE_H\n""")
+
     f.close()
-  gencom.runClangFormat(genfile)
+  gencom.run_clang_format(genfile)
 
-def isIntercepted(functionName):
-  switchCase = {
-    # Create functions of dispatchable objects
-    'vkCreateInstance' : True,
-    'vkCreateDevice' : True,
-    'vkEnumeratePhysicalDevices' : True,
-    'vkEnumeratePhysicalDeviceGroups' : True,
-    'vkGetDeviceQueue' : True,
-    'vkGetDeviceQueue2' : True,
-    'vkAllocateCommandBuffers' : True,
 
-    # Destroy functions of dispatchable objects
-    'vkDestroyInstance' : True,
-    'vkDestroyDevice' : True,
+def _is_intercepted(cmd):
+  """Returns true if a function is intercepted by vulkan::driver.
 
-    # Enumeration of extensions
-    'vkEnumerateInstanceExtensionProperties' : True,
-    'vkEnumerateDeviceExtensionProperties' : True,
+  Args:
+    cmd: Vulkan function name.
+  """
+  if gencom.is_function_supported(cmd):
+    if cmd in _INTERCEPTED_COMMANDS:
+      return True
 
-    'vkGetInstanceProcAddr' : True,
-    'vkGetDeviceProcAddr' : True,
-
-    'vkQueueSubmit' : True,
-
-    # VK_KHR_swapchain v69 requirement
-    'vkBindImageMemory2' : True,
-    'vkBindImageMemory2KHR' : True
-  }
-  if gencom.isFunctionSupported(functionName):
-    if functionName in switchCase:
-      return switchCase[functionName]
-
-    if functionName in gencom.extensionsDict:
-      return isExtensionIntercepted(gencom.extensionsDict[functionName])
+    if cmd in gencom.extension_dict:
+      return gencom.extension_dict[cmd] in _INTERCEPTED_EXTENSIONS
   return False
 
-def needProcHookStub(functionName):
-  if isIntercepted(functionName) and gencom.isDeviceDispatched(functionName):
-    if functionName in gencom.extensionsDict:
-      if not gencom.isExtensionInternal(gencom.extensionsDict[functionName]):
+
+def _get_proc_hook_enum(cmd):
+  """Returns the ProcHook enumeration for the corresponding core function.
+
+  Args:
+    cmd: Vulkan function name.
+  """
+  assert cmd in gencom.version_dict
+  for version in gencom.version_code_list:
+    if gencom.version_dict[cmd] == 'VK_VERSION_' + version:
+      return 'ProcHook::EXTENSION_CORE_' + version
+
+
+def _need_proc_hook_stub(cmd):
+  """Returns true if a function needs a ProcHook stub.
+
+  Args:
+    cmd: Vulkan function name.
+  """
+  if _is_intercepted(cmd) and gencom.is_device_dispatched(cmd):
+    if cmd in gencom.extension_dict:
+      if not gencom.is_extension_internal(gencom.extension_dict[cmd]):
         return True
+    elif gencom.version_dict[cmd] != 'VK_VERSION_1_0':
+      return True
   return False
 
-def defineInitProc(name, f):
-  f.write ('#define UNLIKELY(expr) __builtin_expect((expr), 0)\n')
-  f.write ('\n')
-  f.write ("""#define INIT_PROC(required, obj, proc)                                 \\
-    do {                                                               \\
-        data.""" + name + """.proc =                                             \\
-            reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
-        if (UNLIKELY(required && !data.""" + name + """.proc)) {                 \\
-            ALOGE("missing " #obj " proc: vk" #proc);                  \\
-            success = false;                                           \\
-        }                                                              \\
-    } while (0)\n\n""")
 
-def defineInitProcExt(f):
-  f.write ("""#define INIT_PROC_EXT(ext, required, obj, proc) \\
-    do {                                        \\
-        if (extensions[ProcHook::ext])          \\
-            INIT_PROC(required, obj, proc);     \\
-    } while (0)\n\n""")
+def _define_proc_hook_stub(cmd, f):
+  """Emits a stub for ProcHook::checked_proc.
 
-def defineProcHookStub(functionName, f):
-  if needProcHookStub(functionName):
-    ext_name = gencom.extensionsDict[functionName]
-    base_name = functionName[2:]
-    paramList = [''.join(i) for i in gencom.paramDict[functionName]]
-    p0 = gencom.paramDict[functionName][0][1]
-    f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[functionName] + ' checked' + base_name + '(' + ', '.join(paramList) + ') {\n')
-    ext_hook = 'ProcHook::' + ext_name[3:]
+  Args:
+    cmd: Vulkan function name.
+    f: Output file handle.
+  """
+  if _need_proc_hook_stub(cmd):
+    return_type = gencom.return_type_dict[cmd]
 
-    f.write (gencom.clang_off_spaces + 'if (GetData(' + p0 + ').hook_extensions[' + ext_hook + ']) {\n')
-    f.write (gencom.clang_off_spaces *2)
-    if gencom.returnTypeDict[functionName] != 'void':
-      f.write ('return ')
-    paramNames = [''.join(i[1]) for i in gencom.paramDict[functionName]]
-    f.write (base_name + '(' + ', '.join(paramNames) + ');\n')
-    f.write (gencom.clang_off_spaces + '} else {\n')
-    f.write (gencom.clang_off_spaces*2 + 'Logger(' + p0 + ').Err(' + p0 + ', \"' + ext_name + ' not enabled. ' + functionName + ' not executed.\");\n')
-    if gencom.returnTypeDict[functionName] != 'void':
-      f.write (gencom.clang_off_spaces*2 + 'return VK_SUCCESS;\n')
-    f.write (gencom.clang_off_spaces + '}\n')
-    f.write ('}\n\n')
+    ext_name = ''
+    ext_hook = ''
+    if cmd in gencom.extension_dict:
+      ext_name = gencom.extension_dict[cmd]
+      ext_hook = 'ProcHook::' + gencom.base_ext_name(ext_name)
+    else:
+      ext_name = gencom.version_dict[cmd]
+      ext_hook = _get_proc_hook_enum(cmd)
 
-def defineGlobalProcHook(functionName, f):
-  base_name = functionName[2:]
-  assert (functionName not in gencom.extensionsDict)
-  f.write (gencom.clang_off_spaces + '{\n' + gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n' + gencom.clang_off_spaces*2)
-  f.write ("""ProcHook::GLOBAL,
-        ProcHook::EXTENSION_CORE,
-        reinterpret_cast<PFN_vkVoidFunction>(""" + base_name  + """),
+    handle = gencom.param_dict[cmd][0][1]
+    param_types = ', '.join([''.join(i) for i in gencom.param_dict[cmd]])
+    param_names = ', '.join([''.join(i[1]) for i in gencom.param_dict[cmd]])
+
+    f.write('VKAPI_ATTR ' + return_type + ' checked' + gencom.base_name(cmd) +
+            '(' + param_types + ') {\n')
+    f.write(gencom.indent(1) + 'if (GetData(' + handle + ').hook_extensions[' +
+            ext_hook + ']) {\n')
+
+    f.write(gencom.indent(2))
+    if gencom.return_type_dict[cmd] != 'void':
+      f.write('return ')
+    f.write(gencom.base_name(cmd) + '(' + param_names + ');\n')
+
+    f.write(gencom.indent(1) + '} else {\n')
+    f.write(gencom.indent(2) + 'Logger(' + handle + ').Err(' + handle + ', \"' +
+            ext_name + ' not enabled. ' + cmd + ' not executed.\");\n')
+    if gencom.return_type_dict[cmd] != 'void':
+      f.write(gencom.indent(2) + 'return VK_SUCCESS;\n')
+    f.write(gencom.indent(1) + '}\n}\n\n')
+
+
+def _define_global_proc_hook(cmd, f):
+  """Emits definition of a global ProcHook.
+
+  Args:
+    cmd: Vulkan function name.
+    f: Output file handle.
+  """
+  assert cmd not in gencom.extension_dict
+
+  f.write(gencom.indent(1) + '{\n')
+  f.write(gencom.indent(2) + '\"' + cmd + '\",\n')
+  f.write(gencom.indent(2) + 'ProcHook::GLOBAL,\n')
+  f.write(gencom.indent(2) + _get_proc_hook_enum(cmd) + ',\n')
+  f.write(gencom.indent(2) + 'reinterpret_cast<PFN_vkVoidFunction>(' +
+          gencom.base_name(cmd) + '),\n')
+  f.write(gencom.indent(2) + 'nullptr,\n')
+  f.write(gencom.indent(1) + '},\n')
+
+
+def _define_instance_proc_hook(cmd, f):
+  """Emits definition of a instance ProcHook.
+
+  Args:
+    cmd: Vulkan function name.
+    f: Output file handle.
+  """
+  f.write(gencom.indent(1) + '{\n')
+  f.write(gencom.indent(2) + '\"' + cmd + '\",\n')
+  f.write(gencom.indent(2) + 'ProcHook::INSTANCE,\n')
+
+  if cmd in gencom.extension_dict:
+    ext_name = gencom.extension_dict[cmd]
+    f.write(gencom.indent(2) + 'ProcHook::' +
+            gencom.base_ext_name(ext_name) + ',\n')
+
+    if gencom.is_extension_internal(ext_name):
+      f.write("""\
         nullptr,
-    },\n""")
-
-def defineInstanceProcHook(functionName, f):
-  base_name = functionName[2:]
-  f.write (gencom.clang_off_spaces + '{\n')
-  f.write (gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n')
-  f.write (gencom.clang_off_spaces*2 + 'ProcHook::INSTANCE,\n')
-
-  if functionName in gencom.extensionsDict:
-    ext_name = gencom.extensionsDict[functionName]
-    f.write (gencom.clang_off_spaces*2 + 'ProcHook::' + ext_name[3:] + ',\n')
-    if gencom.isExtensionInternal(ext_name):
-      f.write (gencom.clang_off_spaces*2 + 'nullptr,\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
+        nullptr,\n""")
     else:
-      f.write (gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(' + base_name + '),\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
-
+      f.write("""\
+        reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
+        nullptr,\n""")
   else:
-    f.write (gencom.clang_off_spaces*2 + """ProcHook::EXTENSION_CORE,
-        reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """),
+    f.write(gencom.indent(2) + _get_proc_hook_enum(cmd) + ',\n')
+    f.write("""\
+        reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
         nullptr,\n""")
 
-  f.write (gencom.clang_off_spaces + '},\n')
+  f.write(gencom.indent(1) + '},\n')
 
-def defineDeviceProcHook(functionName, f):
-  base_name = functionName[2:]
-  f.write (gencom.clang_off_spaces + '{\n')
-  f.write (gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n')
-  f.write (gencom.clang_off_spaces*2 + 'ProcHook::DEVICE,\n')
 
-  if functionName in gencom.extensionsDict:
-    ext_name = gencom.extensionsDict[functionName]
-    f.write (gencom.clang_off_spaces*2 + 'ProcHook::' + ext_name[3:] + ',\n')
-    if gencom.isExtensionInternal(ext_name):
-      f.write (gencom.clang_off_spaces*2 + 'nullptr,\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
+def _define_device_proc_hook(cmd, f):
+  """Emits definition of a device ProcHook.
+
+  Args:
+    cmd: Vulkan function name.
+    f: Output file handle.
+  """
+  f.write(gencom.indent(1) + '{\n')
+  f.write(gencom.indent(2) + '\"' + cmd + '\",\n')
+  f.write(gencom.indent(2) + 'ProcHook::DEVICE,\n')
+
+  if (cmd in gencom.extension_dict or
+      gencom.version_dict[cmd] != 'VK_VERSION_1_0'):
+    ext_name = ''
+    ext_hook = ''
+    if cmd in gencom.extension_dict:
+      ext_name = gencom.extension_dict[cmd]
+      ext_hook = 'ProcHook::' + gencom.base_ext_name(ext_name)
     else:
-      f.write (gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(' + base_name + '),\n' + gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(checked' + base_name + '),\n')
+      ext_name = gencom.version_dict[cmd]
+      ext_hook = _get_proc_hook_enum(cmd)
+    f.write(gencom.indent(2) + ext_hook + ',\n')
+
+    if gencom.is_extension_internal(ext_name):
+      f.write("""\
+        nullptr,
+        nullptr,\n""")
+    else:
+      f.write("""\
+        reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
+        reinterpret_cast<PFN_vkVoidFunction>(checked""" +
+              gencom.base_name(cmd) + '),\n')
 
   else:
-    f.write (gencom.clang_off_spaces*2 + """ProcHook::EXTENSION_CORE,
-        reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """),
+    f.write(gencom.indent(2) + _get_proc_hook_enum(cmd) + ',\n')
+    f.write("""\
+        reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
         nullptr,\n""")
 
-  f.write (gencom.clang_off_spaces + '},\n')
+  f.write(gencom.indent(1) + '},\n')
 
-def driver_gencpp():
-  header = """#include <log/log.h>
+
+def gen_cpp():
+  """Generates the driver_gen.cpp file.
+  """
+  genfile = os.path.join(os.path.dirname(__file__),
+                         '..', 'libvulkan', 'driver_gen.cpp')
+
+  with open(genfile, 'w') as f:
+    f.write(gencom.copyright_and_warning(2016))
+    f.write("""\
+#include <log/log.h>
 #include <string.h>
 
 #include <algorithm>
@@ -321,35 +436,34 @@
 
 namespace {
 
-// clang-format off\n\n"""
+// clang-format off\n\n""")
 
-  genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','driver_gen.cpp')
+    for cmd in gencom.command_list:
+      _define_proc_hook_stub(cmd, f)
 
-  with open(genfile, 'w') as f:
-    f.write (gencom.copyright)
-    f.write (gencom.warning)
-    f.write (header)
+    f.write("""\
+// clang-format on
 
-    for cmds in gencom.allCommandsList:
-      defineProcHookStub(cmds, f)
-    gencom.clang_on(f, 0)
-    f.write ('\n')
+const ProcHook g_proc_hooks[] = {
+    // clang-format off\n""")
 
-    f.write ('const ProcHook g_proc_hooks[] = {\n')
-    gencom.clang_off(f, 1)
-    sortedCommandsList = sorted(gencom.allCommandsList)
-    for cmds in sortedCommandsList:
-      if isIntercepted(cmds):
-        if gencom.isGloballyDispatched(cmds):
-          defineGlobalProcHook(cmds, f)
-        elif gencom.isInstanceDispatched(cmds):
-          defineInstanceProcHook(cmds, f)
-        elif gencom.isDeviceDispatched(cmds):
-          defineDeviceProcHook(cmds, f)
-    gencom.clang_on(f, 1)
-    f.write ('};\n\n}  // namespace\n\n')
+    sorted_command_list = sorted(gencom.command_list)
+    for cmd in sorted_command_list:
+      if _is_intercepted(cmd):
+        if gencom.is_globally_dispatched(cmd):
+          _define_global_proc_hook(cmd, f)
+        elif gencom.is_instance_dispatched(cmd):
+          _define_instance_proc_hook(cmd, f)
+        elif gencom.is_device_dispatched(cmd):
+          _define_device_proc_hook(cmd, f)
 
-    f.write ("""const ProcHook* GetProcHook(const char* name) {
+    f.write("""\
+    // clang-format on
+};
+
+}  // namespace
+
+const ProcHook* GetProcHook(const char* name) {
     const auto& begin = g_proc_hooks;
     const auto& end =
         g_proc_hooks + sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
@@ -357,44 +471,76 @@
         begin, end, name,
         [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
     return (hook < end && strcmp(hook->name, name) == 0) ? hook : nullptr;
-}\n\n""")
+}
 
-    f.write ('ProcHook::Extension GetProcHookExtension(const char* name) {\n')
-    gencom.clang_off(f, 1)
-    for exts in knownExtensions:
-      f.write (gencom.clang_off_spaces + 'if (strcmp(name, \"' + exts + '\") == 0) return ProcHook::' + exts[3:] + ';\n')
-    gencom.clang_on(f, 1)
-    f.write (gencom.clang_off_spaces + 'return ProcHook::EXTENSION_UNKNOWN;\n')
-    f.write ('}\n\n')
+ProcHook::Extension GetProcHookExtension(const char* name) {
+    // clang-format off\n""")
 
-    defineInitProc('driver', f)
-    defineInitProcExt(f)
+    for ext in _KNOWN_EXTENSIONS:
+      f.write(gencom.indent(1) + 'if (strcmp(name, \"' + ext +
+              '\") == 0) return ProcHook::' + gencom.base_ext_name(ext) + ';\n')
 
-    f.write ("""bool InitDriverTable(VkInstance instance,
+    f.write("""\
+    // clang-format on
+    return ProcHook::EXTENSION_UNKNOWN;
+}
+
+#define UNLIKELY(expr) __builtin_expect((expr), 0)
+
+#define INIT_PROC(required, obj, proc)                                 \\
+    do {                                                               \\
+        data.driver.proc =                                             \\
+            reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
+        if (UNLIKELY(required && !data.driver.proc)) {                 \\
+            ALOGE("missing " #obj " proc: vk" #proc);                  \\
+            success = false;                                           \\
+        }                                                              \\
+    } while (0)
+
+#define INIT_PROC_EXT(ext, required, obj, proc) \\
+    do {                                        \\
+        if (extensions[ProcHook::ext])          \\
+            INIT_PROC(required, obj, proc);     \\
+    } while (0)
+
+bool InitDriverTable(VkInstance instance,
                      PFN_vkGetInstanceProcAddr get_proc,
                      const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
     auto& data = GetData(instance);
-    bool success = true;\n\n""")
-    gencom.clang_off(f, 1)
-    for cmds in gencom.allCommandsList:
-      if isInstanceDriverTableEntry(cmds):
-        gencom.initProc(cmds, f)
-    gencom.clang_on(f, 1)
-    f.write ('\n' + gencom.clang_off_spaces + 'return success;\n')
-    f.write ('}\n\n')
+    bool success = true;
 
-    f.write ("""bool InitDriverTable(VkDevice dev,
+    // clang-format off\n""")
+
+    for cmd in gencom.command_list:
+      if _is_instance_driver_table_entry(cmd):
+        gencom.init_proc(cmd, f)
+
+    f.write("""\
+    // clang-format on
+
+    return success;
+}
+
+bool InitDriverTable(VkDevice dev,
                      PFN_vkGetDeviceProcAddr get_proc,
                      const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
     auto& data = GetData(dev);
-    bool success = true;\n\n""")
-    gencom.clang_off(f, 1)
-    for cmds in gencom.allCommandsList:
-      if isDeviceDriverTableEntry(cmds):
-        gencom.initProc(cmds, f)
-    gencom.clang_on(f, 1)
-    f.write ('\n' + gencom.clang_off_spaces + 'return success;\n')
-    f.write ('}\n\n}  // namespace driver\n}  // namespace vulkan\n\n')
-    gencom.clang_on(f, 0)
+    bool success = true;
+
+    // clang-format off\n""")
+
+    for cmd in gencom.command_list:
+      if _is_device_driver_table_entry(cmd):
+        gencom.init_proc(cmd, f)
+
+    f.write("""\
+    // clang-format on
+
+    return success;
+}
+
+}  // namespace driver
+}  // namespace vulkan\n""")
+
     f.close()
-  gencom.runClangFormat(genfile)
+  gencom.run_clang_format(genfile)
diff --git a/vulkan/scripts/generator_common.py b/vulkan/scripts/generator_common.py
index f1f09d5..cf370fa 100644
--- a/vulkan/scripts/generator_common.py
+++ b/vulkan/scripts/generator_common.py
@@ -13,33 +13,16 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
-# This script provides the common functions for generating the
-# vulkan framework directly from the vulkan registry (vk.xml).
 
-from subprocess import check_call
-
-copyright = """/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
+"""Provide the utilities for framework generation.
 """
 
-warning = '// WARNING: This file is generated. See ../README.md for instructions.\n\n'
+import os
+import subprocess
+import xml.etree.ElementTree as element_tree
 
-blacklistedExtensions = [
+# Extensions unsupported on Android.
+_BLACKLISTED_EXTENSIONS = [
     'VK_EXT_acquire_xlib_display',
     'VK_EXT_direct_mode_display',
     'VK_EXT_display_control',
@@ -70,191 +53,354 @@
     'VK_NVX_image_view_handle',
 ]
 
-exportedExtensions = [
+# Extensions having functions exported by the loader.
+_EXPORTED_EXTENSIONS = [
     'VK_ANDROID_external_memory_android_hardware_buffer',
     'VK_KHR_android_surface',
     'VK_KHR_surface',
     'VK_KHR_swapchain',
 ]
 
-optionalCommands = [
+# Functions optional on Android even if extension is advertised.
+_OPTIONAL_COMMANDS = [
     'vkGetSwapchainGrallocUsageANDROID',
     'vkGetSwapchainGrallocUsage2ANDROID',
 ]
 
-def runClangFormat(args):
-  clang_call = ["clang-format", "--style", "file", "-i", args]
-  check_call (clang_call)
+# Dict for mapping dispatch table to a type.
+_DISPATCH_TYPE_DICT = {
+    'VkInstance ': 'Instance',
+    'VkPhysicalDevice ': 'Instance',
+    'VkDevice ': 'Device',
+    'VkQueue ': 'Device',
+    'VkCommandBuffer ': 'Device'
+}
 
-def isExtensionInternal(extensionName):
-  if extensionName == 'VK_ANDROID_native_buffer':
-    return True
-  return False
+# Dict for mapping a function to its alias.
+alias_dict = {}
 
-def isFunctionSupported(functionName):
-  if functionName not in extensionsDict:
+# List of all the Vulkan functions.
+command_list = []
+
+# Dict for mapping a function to an extension.
+extension_dict = {}
+
+# Dict for mapping a function to all its parameters.
+param_dict = {}
+
+# Dict for mapping a function to its return type.
+return_type_dict = {}
+
+# List of the sorted Vulkan version codes. e.g. '1_0', '1_1'.
+version_code_list = []
+
+# Dict for mapping a function to the core Vulkan API version.
+version_dict = {}
+
+
+def indent(num):
+  """Returns the requested indents.
+
+  Args:
+    num: Number of the 4-space indents.
+  """
+  return '    ' * num
+
+
+def copyright_and_warning(year):
+  """Returns the standard copyright and warning codes.
+
+  Args:
+    year: An integer year for the copyright.
+  """
+  return """\
+/*
+ * Copyright """ + str(year) + """ The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// WARNING: This file is generated. See ../README.md for instructions.
+
+"""
+
+
+def run_clang_format(args):
+  """Run clang format on the file.
+
+  Args:
+    args: The file to be formatted.
+  """
+  clang_call = ['clang-format', '--style', 'file', '-i', args]
+  subprocess.check_call(clang_call)
+
+
+def is_extension_internal(ext):
+  """Returns true if an extension is internal to the loader and drivers.
+
+  The loader should not enumerate this extension.
+
+  Args:
+    ext: Vulkan extension name.
+  """
+  return ext == 'VK_ANDROID_native_buffer'
+
+
+def base_name(cmd):
+  """Returns a function name without the 'vk' prefix.
+
+  Args:
+    cmd: Vulkan function name.
+  """
+  return cmd[2:]
+
+
+def base_ext_name(ext):
+  """Returns an extension name without the 'VK_' prefix.
+
+  Args:
+    ext: Vulkan extension name.
+  """
+  return ext[3:]
+
+
+def version_code(version):
+  """Returns the version code from a version string.
+
+  Args:
+    version: Vulkan version string.
+  """
+  return version[11:]
+
+
+def is_function_supported(cmd):
+  """Returns true if a function is core or from a supportable extension.
+
+  Args:
+    cmd: Vulkan function name.
+  """
+  if cmd not in extension_dict:
     return True
   else:
-    if extensionsDict[functionName] not in blacklistedExtensions:
+    if extension_dict[cmd] not in _BLACKLISTED_EXTENSIONS:
       return True
   return False
 
-def isInstanceDispatched(functionName):
-  return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Instance'
 
-def isDeviceDispatched(functionName):
-  return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Device'
+def get_dispatch_table_type(cmd):
+  """Returns the dispatch table type for a function.
 
-def isGloballyDispatched(functionName):
-  return isFunctionSupported(functionName) and getDispatchTableType(functionName) == 'Global'
-
-def isExtensionExported(extensionName):
-  if extensionName in exportedExtensions:
-    return True
-  return False
-
-def isFunctionExported(functionName):
-  if isFunctionSupported(functionName):
-    if functionName in extensionsDict:
-      return isExtensionExported(extensionsDict[functionName])
-    return True
-  return False
-
-def getDispatchTableType(functionName):
-  if functionName not in paramDict:
+  Args:
+    cmd: Vulkan function name.
+  """
+  if cmd not in param_dict:
     return None
 
-  switchCase = {
-      'VkInstance ' : 'Instance',
-      'VkPhysicalDevice ' : 'Instance',
-      'VkDevice ' : 'Device',
-      'VkQueue ' : 'Device',
-      'VkCommandBuffer ' : 'Device'
-  }
-
-  if len(paramDict[functionName]) > 0:
-    return switchCase.get(paramDict[functionName][0][0], 'Global')
+  if param_dict[cmd]:
+    return _DISPATCH_TYPE_DICT.get(param_dict[cmd][0][0], 'Global')
   return 'Global'
 
-def isInstanceDispatchTableEntry(functionName):
-  if functionName == 'vkEnumerateDeviceLayerProperties': # deprecated, unused internally - @dbd33bc
+
+def is_globally_dispatched(cmd):
+  """Returns true if the function is global, which is not dispatched.
+
+  Only global functions and functions handled in the loader top without calling
+  into lower layers are not dispatched.
+
+  Args:
+    cmd: Vulkan function name.
+  """
+  return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Global'
+
+
+def is_instance_dispatched(cmd):
+  """Returns true for functions that can have instance-specific dispatch.
+
+  Args:
+    cmd: Vulkan function name.
+  """
+  return (is_function_supported(cmd) and
+          get_dispatch_table_type(cmd) == 'Instance')
+
+
+def is_device_dispatched(cmd):
+  """Returns true for functions that can have device-specific dispatch.
+
+  Args:
+    cmd: Vulkan function name.
+  """
+  return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Device'
+
+
+def is_extension_exported(ext):
+  """Returns true if an extension has functions exported by the loader.
+
+  E.g. applications can directly link to an extension function.
+
+  Args:
+    ext: Vulkan extension name.
+  """
+  return ext in _EXPORTED_EXTENSIONS
+
+
+def is_function_exported(cmd):
+  """Returns true if a function is exported from the Android Vulkan library.
+
+  Functions in the core API and in loader extensions are exported.
+
+  Args:
+    cmd: Vulkan function name.
+  """
+  if is_function_supported(cmd):
+    if cmd in extension_dict:
+      return is_extension_exported(extension_dict[cmd])
+    return True
+  return False
+
+
+def is_instance_dispatch_table_entry(cmd):
+  """Returns true if a function is exported and instance-dispatched.
+
+  Args:
+    cmd: Vulkan function name.
+  """
+  if cmd == 'vkEnumerateDeviceLayerProperties':
+    # deprecated, unused internally - @dbd33bc
     return False
-  if isFunctionExported(functionName) and isInstanceDispatched(functionName):
-    return True
-  return False
-
-def isDeviceDispatchTableEntry(functionName):
-  if isFunctionExported(functionName) and isDeviceDispatched(functionName):
-    return True
-  return False
+  return is_function_exported(cmd) and is_instance_dispatched(cmd)
 
 
-def clang_on(f, indent):
-  f.write (clang_off_spaces * indent + '// clang-format on\n')
+def is_device_dispatch_table_entry(cmd):
+  """Returns true if a function is exported and device-dispatched.
 
-def clang_off(f, indent):
-  f.write (clang_off_spaces * indent + '// clang-format off\n')
+  Args:
+    cmd: Vulkan function name.
+  """
+  return is_function_exported(cmd) and is_device_dispatched(cmd)
 
-clang_off_spaces = ' ' * 4
 
-parametersList = []
-paramDict = {}
-allCommandsList = []
-extensionsDict = {}
-returnTypeDict = {}
-versionDict = {}
-aliasDict = {}
+def init_proc(name, f):
+  """Emits code to invoke INIT_PROC or INIT_PROC_EXT.
 
-def parseVulkanRegistry():
-  import xml.etree.ElementTree as ET
-  import os
-  vulkan_registry = os.path.join(os.path.dirname(__file__),'..','..','..','..','external','vulkan-headers','registry','vk.xml')
-  tree = ET.parse(vulkan_registry)
+  Args:
+    name: Vulkan function name.
+    f: Output file handle.
+  """
+  f.write(indent(1))
+  if name in extension_dict:
+    f.write('INIT_PROC_EXT(' + base_ext_name(extension_dict[name]) + ', ')
+  else:
+    f.write('INIT_PROC(')
+
+  if name in version_dict and version_dict[name] == 'VK_VERSION_1_1':
+    f.write('false, ')
+  elif name in _OPTIONAL_COMMANDS:
+    f.write('false, ')
+  else:
+    f.write('true, ')
+
+  if is_instance_dispatched(name):
+    f.write('instance, ')
+  else:
+    f.write('dev, ')
+
+  f.write(base_name(name) + ');\n')
+
+
+def parse_vulkan_registry():
+  """Parses Vulkan registry into the below global variables.
+
+  alias_dict
+  command_list
+  extension_dict
+  param_dict
+  return_type_dict
+  version_code_list
+  version_dict
+  """
+  registry = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..',
+                          'external', 'vulkan-headers', 'registry', 'vk.xml')
+  tree = element_tree.parse(registry)
   root = tree.getroot()
   for commands in root.iter('commands'):
     for command in commands:
       if command.tag == 'command':
-        parametersList.clear()
+        parameter_list = []
         protoset = False
-        fnName = ""
-        fnType = ""
-        if command.get('alias') != None:
+        cmd_name = ''
+        cmd_type = ''
+        if command.get('alias') is not None:
           alias = command.get('alias')
-          fnName = command.get('name')
-          aliasDict[fnName] = alias
-          allCommandsList.append(fnName)
-          paramDict[fnName] = paramDict[alias].copy()
-          returnTypeDict[fnName] = returnTypeDict[alias]
+          cmd_name = command.get('name')
+          alias_dict[cmd_name] = alias
+          command_list.append(cmd_name)
+          param_dict[cmd_name] = param_dict[alias].copy()
+          return_type_dict[cmd_name] = return_type_dict[alias]
         for params in command:
           if params.tag == 'param':
-            paramtype = ""
-            if params.text != None and params.text.strip() != '':
-              paramtype = params.text.strip() + ' '
-            typeval = params.find('type')
-            paramtype = paramtype + typeval.text
-            if typeval.tail != None:
-              paramtype += typeval.tail.strip() + ' '
+            param_type = ''
+            if params.text is not None and params.text.strip():
+              param_type = params.text.strip() + ' '
+            type_val = params.find('type')
+            param_type = param_type + type_val.text
+            if type_val.tail is not None:
+              param_type += type_val.tail.strip() + ' '
             pname = params.find('name')
-            paramname = pname.text
-            if pname.tail != None and pname.tail.strip() != '':
-              parametersList.append((paramtype, paramname, pname.tail.strip()))
+            param_name = pname.text
+            if pname.tail is not None and pname.tail.strip():
+              parameter_list.append(
+                  (param_type, param_name, pname.tail.strip()))
             else:
-              parametersList.append((paramtype, paramname))
+              parameter_list.append((param_type, param_name))
           if params.tag == 'proto':
             for c in params:
               if c.tag == 'type':
-                fnType = c.text
+                cmd_type = c.text
               if c.tag == 'name':
-                fnName = c.text
+                cmd_name = c.text
                 protoset = True
-                allCommandsList.append(fnName)
-                returnTypeDict[fnName] = fnType
-        if protoset == True:
-          paramDict[fnName] = parametersList.copy()
+                command_list.append(cmd_name)
+                return_type_dict[cmd_name] = cmd_type
+        if protoset:
+          param_dict[cmd_name] = parameter_list.copy()
 
   for exts in root.iter('extensions'):
     for extension in exts:
-      apiversion = ""
+      apiversion = ''
       if extension.tag == 'extension':
         extname = extension.get('name')
         for req in extension:
-          if req.get('feature') != None:
+          if req.get('feature') is not None:
             apiversion = req.get('feature')
           for commands in req:
             if commands.tag == 'command':
-              commandname = commands.get('name')
-              if commandname not in extensionsDict:
-                extensionsDict[commandname] = extname
-                if apiversion != "":
-                  versionDict[commandname] = apiversion
+              cmd_name = commands.get('name')
+              if cmd_name not in extension_dict:
+                extension_dict[cmd_name] = extname
+                if apiversion:
+                  version_dict[cmd_name] = apiversion
 
   for feature in root.iter('feature'):
     apiversion = feature.get('name')
     for req in feature:
       for command in req:
         if command.tag == 'command':
-          cmdName = command.get('name')
-          if cmdName in allCommandsList:
-            versionDict[cmdName] = apiversion
+          cmd_name = command.get('name')
+          if cmd_name in command_list:
+            version_dict[cmd_name] = apiversion
 
-
-def initProc(name, f):
-  if name in extensionsDict:
-    f.write ('    INIT_PROC_EXT(' + extensionsDict[name][3:] + ', ')
-  else:
-    f.write ('    INIT_PROC(')
-
-  if name in versionDict and versionDict[name] == 'VK_VERSION_1_1':
-    f.write('false, ')
-  elif name in optionalCommands:
-    f.write('false, ')
-  else:
-    f.write('true, ')
-
-  if isInstanceDispatched(name):
-    f.write('instance, ')
-  else:
-    f.write('dev, ')
-
-  f.write(name[2:] + ');\n')
-
+  version_code_set = set()
+  for version in version_dict.values():
+    version_code_set.add(version_code(version))
+  for code in sorted(version_code_set):
+    version_code_list.append(code)
diff --git a/vulkan/scripts/null_generator.py b/vulkan/scripts/null_generator.py
index 3a761ce..e9faef6 100644
--- a/vulkan/scripts/null_generator.py
+++ b/vulkan/scripts/null_generator.py
@@ -13,49 +13,43 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
-# This script provides the functions for generating the null driver
-# framework directly from the vulkan registry (vk.xml).
 
-import generator_common as gencom
-import os
-
-copyright = """/*
- * Copyright 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
+"""Generates the null_driver_gen.h and null_driver_gen.cpp.
 """
 
-def isDriverExtension(extensionName):
-  switchCase = {
-    'VK_ANDROID_native_buffer' : True,
-    'VK_EXT_debug_report' : True,
-    'VK_KHR_get_physical_device_properties2' : True
-  }
+import os
+import generator_common as gencom
 
-  if extensionName in switchCase:
-    return switchCase[extensionName]
-  return False
+# Extensions implemented by the driver.
+_DRIVER_EXTENSION_DICT = {
+    'VK_ANDROID_native_buffer',
+    'VK_EXT_debug_report',
+    'VK_KHR_get_physical_device_properties2'
+}
 
-def isDriverFunction(functionName):
-  if functionName in gencom.extensionsDict:
-    return isDriverExtension(gencom.extensionsDict[functionName])
+
+def _is_driver_function(cmd):
+  """Returns true if the function is implemented by the driver.
+
+  Args:
+    cmd: Vulkan function name.
+  """
+  if cmd in gencom.extension_dict:
+    return gencom.extension_dict[cmd] in _DRIVER_EXTENSION_DICT
   return True
 
-def null_driver_genh():
-  header = """#ifndef NULLDRV_NULL_DRIVER_H
+
+def gen_h():
+  """Generates the null_driver_gen.h file.
+  """
+  genfile = os.path.join(os.path.dirname(__file__),
+                         '..', 'nulldrv', 'null_driver_gen.h')
+
+  with open(genfile, 'w') as f:
+    f.write(gencom.copyright_and_warning(2015))
+
+    f.write("""\
+#ifndef NULLDRV_NULL_DRIVER_H
 #define NULLDRV_NULL_DRIVER_H 1
 
 #include <vulkan/vk_android_native_buffer.h>
@@ -66,27 +60,36 @@
 PFN_vkVoidFunction GetGlobalProcAddr(const char* name);
 PFN_vkVoidFunction GetInstanceProcAddr(const char* name);
 
-"""
-  genfile = os.path.join(os.path.dirname(__file__),'..','nulldrv','null_driver_gen.h')
-  with open(genfile, 'w') as f:
-    f.write (copyright)
-    f.write (gencom.warning)
-    f.write (header)
-    gencom.clang_off(f,0)
+// clang-format off\n""")
 
-    for cmds in gencom.allCommandsList:
-      if isDriverFunction(cmds):
-        paramList = [''.join(i) for i in gencom.paramDict[cmds]]
-        f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[cmds] + ' ' + cmds[2:] + '(' +', '.join(paramList) + ');\n')
-    gencom.clang_on(f,0)
+    for cmd in gencom.command_list:
+      if _is_driver_function(cmd):
+        param_list = [''.join(i) for i in gencom.param_dict[cmd]]
+        f.write('VKAPI_ATTR ' + gencom.return_type_dict[cmd] + ' ' +
+                gencom.base_name(cmd) + '(' + ', '.join(param_list) + ');\n')
 
-    f.write ('\n}  // namespace null_driver\n')
-    f.write ('\n#endif  // NULLDRV_NULL_DRIVER_H\n')
+    f.write("""\
+// clang-format on
+
+}  // namespace null_driver
+
+#endif  // NULLDRV_NULL_DRIVER_H\n""")
+
     f.close()
-  gencom.runClangFormat(genfile)
+  gencom.run_clang_format(genfile)
 
-def null_driver_gencpp():
-  header = """#include <algorithm>
+
+def gen_cpp():
+  """Generates the null_driver_gen.cpp file.
+  """
+  genfile = os.path.join(os.path.dirname(__file__),
+                         '..', 'nulldrv', 'null_driver_gen.cpp')
+
+  with open(genfile, 'w') as f:
+    f.write(gencom.copyright_and_warning(2015))
+
+    f.write("""\
+#include <algorithm>
 
 #include "null_driver_gen.h"
 
@@ -116,30 +119,36 @@
 }
 
 const NameProc kGlobalProcs[] = {
-"""
-  genfile = os.path.join(os.path.dirname(__file__),'..','nulldrv','null_driver_gen.cpp')
-  with open(genfile, 'w') as f:
-    f.write (copyright)
-    f.write (gencom.warning)
-    f.write (header)
-    gencom.clang_off(f,1)
+    // clang-format off\n""")
 
-    sortedCommandsList = sorted(gencom.allCommandsList)
-    for cmds in sortedCommandsList:
-      if isDriverFunction(cmds) and gencom.getDispatchTableType(cmds) == 'Global':
-        f.write (gencom.clang_off_spaces + '{\"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' + cmds + '>(' + cmds[2:] + '))},\n')
-    gencom.clang_on(f,1)
-    f.write ('};\n\n')
+    sorted_command_list = sorted(gencom.command_list)
+    for cmd in sorted_command_list:
+      if (_is_driver_function(cmd) and
+          gencom.get_dispatch_table_type(cmd) == 'Global'):
+        f.write(gencom.indent(1) + '{\"' + cmd +
+                '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' +
+                cmd + '>(' + gencom.base_name(cmd) + '))},\n')
 
-    f.write ('const NameProc kInstanceProcs[] = {\n')
-    gencom.clang_off(f,1)
-    for cmds in sortedCommandsList:
-      if isDriverFunction(cmds):
-        f.write (gencom.clang_off_spaces + '{\"' + cmds + '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' + cmds + '>(' + cmds[2:] + '))},\n')
-    gencom.clang_on(f,1)
-    f.write ('};\n\n}  // namespace\n\n')
+    f.write("""\
+    // clang-format on
+};
 
-    f.write ("""namespace null_driver {
+const NameProc kInstanceProcs[] = {
+    // clang-format off\n""")
+
+    for cmd in sorted_command_list:
+      if _is_driver_function(cmd):
+        f.write(gencom.indent(1) + '{\"' + cmd +
+                '\", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_' +
+                cmd + '>(' + gencom.base_name(cmd) + '))},\n')
+
+    f.write("""\
+    // clang-format on
+};
+
+}  // namespace
+
+namespace null_driver {
 
 PFN_vkVoidFunction GetGlobalProcAddr(const char* name) {
     return Lookup(name, kGlobalProcs);
@@ -150,6 +159,6 @@
 }
 
 }  // namespace null_driver\n""")
-    f.close()
-  gencom.runClangFormat(genfile)
 
+    f.close()
+  gencom.run_clang_format(genfile)