Merge "Set isRelativeOf flag when calling setZOrderRelativeOf"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 369c3de..657dfb6 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -253,7 +253,7 @@
         MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
         return 0L;
     }
-    MYLOGD("Module metadata package name: %s", package_name.c_str());
+    MYLOGD("Module metadata package name: %s\n", package_name.c_str());
     int64_t version_code;
     status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
                                                        &version_code);
@@ -876,6 +876,17 @@
         CommandOptions::WithTimeoutInMs(timeout_ms).Build());
 }
 
+static void DoSystemLogcat(time_t since) {
+    char since_str[80];
+    strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
+
+    unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
+    RunCommand("SYSTEM LOG",
+               {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
+                since_str},
+               CommandOptions::WithTimeoutInMs(timeout_ms).Build());
+}
+
 static void DoLogcat() {
     unsigned long timeout_ms;
     // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
@@ -1071,7 +1082,7 @@
         std::string path(title);
         path.append(" - ").append(String8(service).c_str());
         size_t bytes_written = 0;
-        status_t status = dumpsys.startDumpThread(service, args);
+        status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
         if (status == OK) {
             dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
             std::chrono::duration<double> elapsed_seconds;
@@ -1143,7 +1154,7 @@
             path.append("_HIGH");
         }
         path.append(kProtoExt);
-        status_t status = dumpsys.startDumpThread(service, args);
+        status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
         if (status == OK) {
             status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
             bool dumpTerminated = (status == OK);
@@ -1365,8 +1376,6 @@
         ds.TakeScreenshot();
     }
 
-    DoLogcat();
-
     AddAnrTraceFiles();
 
     // NOTE: tombstones are always added as separate entries in the zip archive
@@ -1523,6 +1532,12 @@
     // keep the system stats as close to its initial state as possible.
     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysCritical);
 
+    // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
+    // buffer.
+    DoLogcat();
+    // Capture timestamp after first logcat to use in next logcat
+    time_t logcat_ts = time(nullptr);
+
     /* collect stack traces from Dalvik and native processes (needs root) */
     RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpTraces, &dump_traces_path);
 
@@ -1569,7 +1584,10 @@
     }
 
     RETURN_IF_USER_DENIED_CONSENT();
-    return dumpstate();
+    Dumpstate::RunStatus status = dumpstate();
+    // Capture logcat since the last time we did it.
+    DoSystemLogcat(logcat_ts);
+    return status;
 }
 
 // This method collects common dumpsys for telephony and wifi
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 9f65425..abdf168 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -59,12 +59,13 @@
             "usage: dumpsys\n"
             "         To dump all services.\n"
             "or:\n"
-            "       dumpsys [-t TIMEOUT] [--priority LEVEL] [--help | -l | --skip SERVICES | "
-            "SERVICE [ARGS]]\n"
+            "       dumpsys [-t TIMEOUT] [--priority LEVEL] [--pid] [--help | -l | --skip SERVICES "
+            "| SERVICE [ARGS]]\n"
             "         --help: shows this help\n"
             "         -l: only list services, do not dump them\n"
             "         -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n"
             "         -T TIMEOUT_MS: TIMEOUT to use in milliseconds instead of default 10 seconds\n"
+            "         --pid: dump PID instead of usual dump\n"
             "         --proto: filter services that support dumping data in proto format. Dumps\n"
             "               will be in proto format.\n"
             "         --priority LEVEL: filter services based on specified priority\n"
@@ -120,9 +121,11 @@
     bool showListOnly = false;
     bool skipServices = false;
     bool asProto = false;
+    Type type = Type::DUMP;
     int timeoutArgMs = 10000;
     int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL;
-    static struct option longOptions[] = {{"priority", required_argument, 0, 0},
+    static struct option longOptions[] = {{"pid", no_argument, 0, 0},
+                                          {"priority", required_argument, 0, 0},
                                           {"proto", no_argument, 0, 0},
                                           {"skip", no_argument, 0, 0},
                                           {"help", no_argument, 0, 0},
@@ -157,6 +160,8 @@
                     usage();
                     return -1;
                 }
+            } else if (!strcmp(longOptions[optionIndex].name, "pid")) {
+                type = Type::PID;
             }
             break;
 
@@ -246,7 +251,7 @@
         const String16& serviceName = services[i];
         if (IsSkipped(skippedServices, serviceName)) continue;
 
-        if (startDumpThread(serviceName, args) == OK) {
+        if (startDumpThread(type, serviceName, args) == OK) {
             bool addSeparator = (N > 1);
             if (addSeparator) {
                 writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags);
@@ -313,7 +318,18 @@
     }
 }
 
-status_t Dumpsys::startDumpThread(const String16& serviceName, const Vector<String16>& args) {
+static status_t dumpPidToFd(const sp<IBinder>& service, const unique_fd& fd) {
+     pid_t pid;
+     status_t status = service->getDebugPid(&pid);
+     if (status != OK) {
+         return status;
+     }
+     WriteStringToFd(std::to_string(pid) + "\n", fd.get());
+     return OK;
+}
+
+status_t Dumpsys::startDumpThread(Type type, const String16& serviceName,
+                                  const Vector<String16>& args) {
     sp<IBinder> service = sm_->checkService(serviceName);
     if (service == nullptr) {
         aerr << "Can't find service: " << serviceName << endl;
@@ -333,16 +349,22 @@
 
     // dump blocks until completion, so spawn a thread..
     activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable {
-        int err = service->dump(remote_end.get(), args);
+        status_t err = 0;
 
-        // It'd be nice to be able to close the remote end of the socketpair before the dump
-        // call returns, to terminate our reads if the other end closes their copy of the
-        // file descriptor, but then hangs for some reason. There doesn't seem to be a good
-        // way to do this, though.
-        remote_end.reset();
+        switch (type) {
+        case Type::DUMP:
+            err = service->dump(remote_end.get(), args);
+            break;
+        case Type::PID:
+            err = dumpPidToFd(service, remote_end);
+            break;
+        default:
+            aerr << "Unknown dump type" << static_cast<int>(type) << endl;
+            return;
+        }
 
-        if (err != 0) {
-            aerr << "Error dumping service info: (" << strerror(err) << ") "
+        if (err != OK) {
+            aerr << "Error dumping service info status_t: (" << err << ") "
                  << serviceName << endl;
         }
     });
diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h
index c48a1e9..929c55c 100644
--- a/cmds/dumpsys/dumpsys.h
+++ b/cmds/dumpsys/dumpsys.h
@@ -51,6 +51,11 @@
      */
     static void setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags);
 
+    enum class Type {
+        DUMP,  // dump using `dump` function
+        PID,   // dump pid of server only
+    };
+
     /**
      * Starts a thread to connect to a service and get its dump output. The thread redirects
      * the output to a pipe. Thread must be stopped by a subsequent callto {@code
@@ -61,7 +66,8 @@
      *         {@code NAME_NOT_FOUND} service could not be found.
      *         {@code != OK} error
      */
-    status_t startDumpThread(const String16& serviceName, const Vector<String16>& args);
+    status_t startDumpThread(Type type, const String16& serviceName,
+                             const Vector<String16>& args);
 
     /**
      * Writes a section header to a file descriptor.
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index cbac839..cf4e0b5 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -194,7 +194,7 @@
         CaptureStdout();
         CaptureStderr();
         dump_.setServiceArgs(args, supportsProto, priorityFlags);
-        status_t status = dump_.startDumpThread(serviceName, args);
+        status_t status = dump_.startDumpThread(Dumpsys::Type::DUMP, serviceName, args);
         EXPECT_THAT(status, Eq(0));
         status = dump_.writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(500), false,
                                  elapsedDuration, bytesWritten);
@@ -539,6 +539,27 @@
     AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH);
 }
 
+// Tests 'dumpsys --pid'
+TEST_F(DumpsysTest, ListAllServicesWithPid) {
+    ExpectListServices({"Locksmith", "Valet"});
+    ExpectCheckService("Locksmith");
+    ExpectCheckService("Valet");
+
+    CallMain({"--pid"});
+
+    AssertRunningServices({"Locksmith", "Valet"});
+    AssertOutputContains(std::to_string(getpid()));
+}
+
+// Tests 'dumpsys --pid service_name'
+TEST_F(DumpsysTest, ListServiceWithPid) {
+    ExpectCheckService("Locksmith");
+
+    CallMain({"--pid", "Locksmith"});
+
+    AssertOutput(std::to_string(getpid()) + "\n");
+}
+
 TEST_F(DumpsysTest, GetBytesWritten) {
     const char* serviceName = "service2";
     const char* dumpContents = "dump1";
@@ -563,4 +584,4 @@
         dump_.writeDump(STDOUT_FILENO, String16("service"), std::chrono::milliseconds(500),
                         /* as_proto = */ false, elapsedDuration, bytesWritten);
     EXPECT_THAT(status, Eq(INVALID_OPERATION));
-}
\ No newline at end of file
+}
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/binder/Android.bp b/libs/binder/Android.bp
index 643a956..e5646ef 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -73,6 +73,7 @@
     // or dessert updates. Instead, apex users should use libbinder_ndk.
     apex_available: [
         "//apex_available:platform",
+        "com.android.vndk.current",
         // TODO(b/139016109) remove these three
         "com.android.media.swcodec",
         "test_com.android.media.swcodec",
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 573a038..7d9846a 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(...)
@@ -509,7 +505,7 @@
     }
 }
 
-#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
 constexpr int32_t kHeader = B_PACK_CHARS('V', 'N', 'D', 'R');
 #else
 constexpr int32_t kHeader = B_PACK_CHARS('S', 'Y', 'S', 'T');
@@ -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 {
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 0336d3e..6971c72 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -373,7 +373,9 @@
         }
     }
 
+#ifdef __ANDROID__
     LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver '%s' could not be opened.  Terminating.", driver);
+#endif
 }
 
 ProcessState::~ProcessState()
diff --git a/libs/binder/fuzzer/Android.bp b/libs/binder/fuzzer/Android.bp
index d2f0d37..a9d2b75 100644
--- a/libs/binder/fuzzer/Android.bp
+++ b/libs/binder/fuzzer/Android.bp
@@ -36,4 +36,8 @@
             ],
         },
     },
+    // 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 86264db..04fe0e7 100644
--- a/libs/binder/fuzzer/binder.cpp
+++ b/libs/binder/fuzzer/binder.cpp
@@ -93,26 +93,16 @@
     PARCEL_READ_NO_STATUS(size_t, allowFds),
     PARCEL_READ_NO_STATUS(size_t, hasFileDescriptors),
     [] (const ::android::Parcel& p, uint8_t len) {
-#ifdef __ANDROID__
         std::string interface(len, 'a');
         FUZZ_LOG() << "about to enforceInterface: " << interface;
         bool b = p.enforceInterface(::android::String16(interface.c_str()));
         FUZZ_LOG() << "enforced interface: " << b;
-#else
-        FUZZ_LOG() << "skipping enforceInterface";
-        (void)p;
-        (void)len;
-#endif // __ANDROID__
     },
     [] (const ::android::Parcel& p, uint8_t /*len*/) {
-#ifdef __ANDROID__
         FUZZ_LOG() << "about to checkInterface";
-        bool b = p.checkInterface(new android::BBinder());
+        android::sp<android::IBinder> aBinder = new android::BBinder();
+        bool b = p.checkInterface(aBinder.get());
         FUZZ_LOG() << "checked interface: " << b;
-#else
-        FUZZ_LOG() << "skipping checkInterface";
-        (void)p;
-#endif // __ANDROID__
     },
     PARCEL_READ_NO_STATUS(size_t, objectsCount),
     PARCEL_READ_NO_STATUS(status_t, errorCheck),
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 369aa34..3b7caea 100644
--- a/libs/binder/fuzzer/main.cpp
+++ b/libs/binder/fuzzer/main.cpp
@@ -34,24 +34,45 @@
     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();
+
         uint8_t b = instructions[i + 1];
 
-        FUZZ_LOG() << "size: " << p.dataSize() << " avail: " << p.dataAvail()
-                   << " pos: " << p.dataPosition() << " cap: " << p.dataCapacity();
+        FUZZ_LOG() << "Instruction: " << (i / 2) + 1 << "/" << instructions.size() / 2
+                   << " cmd: " << static_cast<size_t>(a) << " (" << static_cast<size_t>(readIdx)
+                   << ") arg: " << static_cast<size_t>(b) << " size: " << p.dataSize()
+                   << " avail: " << p.dataAvail() << " pos: " << p.dataPosition()
+                   << " cap: " << p.dataCapacity();
 
-        reads[a % reads.size()](p, b);
+        reads[readIdx](p, b);
     }
 }
 
 void fuzz(uint8_t options, const std::vector<uint8_t>& input, const std::vector<uint8_t>& instructions) {
-    (void) options;
+    uint8_t parcelType = options & 0x3;
 
-    // although they will do completely different things, might as well fuzz both
-    doFuzz<::android::hardware::Parcel>(HWBINDER_PARCEL_READ_FUNCTIONS, input, instructions);
-    doFuzz<::android::Parcel>(BINDER_PARCEL_READ_FUNCTIONS, input, instructions);
-    doFuzz<NdkParcelAdapter>(BINDER_NDK_PARCEL_READ_FUNCTIONS, input, instructions);
+    switch (parcelType) {
+        case 0x0:
+            doFuzz<::android::hardware::Parcel>(HWBINDER_PARCEL_READ_FUNCTIONS, input,
+                                                instructions);
+            break;
+        case 0x1:
+            doFuzz<::android::Parcel>(BINDER_PARCEL_READ_FUNCTIONS, input, instructions);
+            break;
+        case 0x2:
+            doFuzz<NdkParcelAdapter>(BINDER_NDK_PARCEL_READ_FUNCTIONS, input, instructions);
+            break;
+        case 0x3:
+            /*reserved for future use*/
+            break;
+        default:
+            LOG_ALWAYS_FATAL("unknown parcel type %d", static_cast<int>(parcelType));
+    }
 }
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
diff --git a/libs/binder/fuzzer/util.cpp b/libs/binder/fuzzer/util.cpp
index b1213e9..479f406 100644
--- a/libs/binder/fuzzer/util.cpp
+++ b/libs/binder/fuzzer/util.cpp
@@ -24,13 +24,17 @@
 std::string hexString(const void* bytes, size_t len) {
     if (bytes == nullptr) return "<null>";
 
-    std::ostringstream s;
-    s << std::hex << std::setfill('0');
+    const uint8_t* bytes8 = static_cast<const uint8_t*>(bytes);
+    char chars[] = "0123456789abcdef";
+    std::string result;
+    result.resize(len * 2);
+
     for (size_t i = 0; i < len; i++) {
-        s << std::setw(2) << static_cast<int>(
-            static_cast<const uint8_t*>(bytes)[i]);
+        result[2 * i] = chars[bytes8[i] >> 4];
+        result[2 * i + 1] = chars[bytes8[i] & 0xf];
     }
-    return s.str();
+
+    return result;
 }
 std::string hexString(const std::vector<uint8_t>& bytes) {
     return hexString(bytes.data(), bytes.size());
diff --git a/libs/binder/fuzzer/util.h b/libs/binder/fuzzer/util.h
index 416c3a7..aa504d2 100644
--- a/libs/binder/fuzzer/util.h
+++ b/libs/binder/fuzzer/util.h
@@ -23,27 +23,31 @@
 #error "Must define FUZZ_LOG_TAG"
 #endif
 
-#define ENABLE_LOG_FUZZ 1
-#define FUZZ_LOG() FuzzLog(FUZZ_LOG_TAG, ENABLE_LOG_FUZZ).log()
+#define FUZZ_LOG() FuzzLog(FUZZ_LOG_TAG).log()
 
+#ifdef ENABLE_LOG_FUZZ
 class FuzzLog {
 public:
-    FuzzLog(const std::string& tag, bool log) : mTag(tag), mLog(log) {}
-    ~FuzzLog() {
-        if (mLog) {
-            std::cout << mTag << ": " << mOs.str() << std::endl;
-        }
-    }
+    FuzzLog(const char* tag) : mTag(tag) {}
+    ~FuzzLog() { std::cout << mTag << ": " << mOs.str() << std::endl; }
 
-    std::stringstream& log() {
-        return mOs;
-    }
+    std::stringstream& log() { return mOs; }
 
 private:
-    std::string mTag;
-    bool mLog;
+    const char* mTag = nullptr;
     std::stringstream mOs;
 };
+#else
+class FuzzLog {
+public:
+    FuzzLog(const char* /*tag*/) {}
+    template <typename T>
+    FuzzLog& operator<<(const T& /*t*/) {
+        return *this;
+    }
+    FuzzLog& log() { return *this; }
+};
+#endif
 
 std::string hexString(const void* bytes, size_t len);
 std::string hexString(const std::vector<uint8_t>& bytes);
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/include/binder/Stability.h b/libs/binder/include/binder/Stability.h
index 2894482..b2f51d3 100644
--- a/libs/binder/include/binder/Stability.h
+++ b/libs/binder/include/binder/Stability.h
@@ -81,7 +81,7 @@
         VINTF = 0b111111,
     };
 
-#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
     static constexpr Level kLocalStability = Level::VENDOR;
 #else
     static constexpr Level kLocalStability = Level::SYSTEM;
diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h
index b03fce1..924812e 100644
--- a/libs/binder/ndk/include_platform/android/binder_stability.h
+++ b/libs/binder/ndk/include_platform/android/binder_stability.h
@@ -20,7 +20,8 @@
 
 __BEGIN_DECLS
 
-#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#if defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || \
+        (defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__))
 
 /**
  * This interface has the stability of the vendor image.
@@ -31,7 +32,8 @@
     AIBinder_markVendorStability(binder);
 }
 
-#else  // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#else  // defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) &&
+       // !defined(__ANDROID_APEX__))
 
 /**
  * This interface has the stability of the system image.
@@ -42,7 +44,8 @@
     AIBinder_markSystemStability(binder);
 }
 
-#endif  // defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__)
+#endif  // defined(__ANDROID_APEX_COM_ANDROID_VNDK_CURRENT__) || (defined(__ANDROID_VNDK__) &&
+        // !defined(__ANDROID_APEX__))
 
 /**
  * This interface has system<->vendor stability
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 30f5f73..2859111 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -307,6 +307,13 @@
     }
 }
 
+bool GraphicsEnv::setInjectLayersPrSetDumpable() {
+    if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
+        return false;
+    }
+    return true;
+}
+
 void* GraphicsEnv::loadLibrary(std::string name) {
     const android_dlextinfo dlextinfo = {
             .flags = ANDROID_DLEXT_USE_NAMESPACE,
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index a47f468..83448d4 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -68,6 +68,14 @@
     void setDriverLoaded(GpuStatsInfo::Api api, bool isDriverLoaded, int64_t driverLoadingTime);
 
     /*
+     * Api for Vk/GL layer injection.  Presently, drivers enable certain
+     * profiling features when prctl(PR_GET_DUMPABLE) returns true.
+     * Calling this when layer injection metadata is present allows the driver
+     * to enable profiling even when in a non-debuggable app
+     */
+    bool setInjectLayersPrSetDumpable();
+
+    /*
      * Apis for ANGLE
      */
     // Check if the requested app should use ANGLE.
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index da51675..e6d442d 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -35,6 +35,7 @@
         ":libgui_bufferqueue_sources",
 
         "BitTube.cpp",
+        "BLASTBufferQueue.cpp",
         "BufferHubConsumer.cpp",
         "BufferHubProducer.cpp",
         "BufferItemConsumer.cpp",
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
new file mode 100644
index 0000000..3a369cd
--- /dev/null
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -0,0 +1,126 @@
+/*
+ * 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 <gui/BLASTBufferQueue.h>
+#include <gui/BufferItemConsumer.h>
+
+#include <chrono>
+
+using namespace std::chrono_literals;
+
+namespace android {
+
+BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height)
+      : mSurfaceControl(surface), mWidth(width), mHeight(height) {
+    BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+    mBufferItemConsumer =
+            new BufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true);
+    mBufferItemConsumer->setName(String8("BLAST Consumer"));
+    mBufferItemConsumer->setFrameAvailableListener(this);
+    mBufferItemConsumer->setBufferFreedListener(this);
+    mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
+    mBufferItemConsumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888);
+}
+
+void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, int width, int height) {
+    std::unique_lock _lock{mMutex};
+    mSurfaceControl = surface;
+    mWidth = width;
+    mHeight = height;
+    mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
+}
+
+static void transactionCallbackThunk(void* context, nsecs_t latchTime,
+                                     const sp<Fence>& presentFence,
+                                     const std::vector<SurfaceControlStats>& stats) {
+    if (context == nullptr) {
+        return;
+    }
+    BLASTBufferQueue* bq = static_cast<BLASTBufferQueue*>(context);
+    bq->transactionCallback(latchTime, presentFence, stats);
+}
+
+void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/,
+                                           const std::vector<SurfaceControlStats>& stats) {
+    std::unique_lock _lock{mMutex};
+
+    if (stats.size() > 0 && mNextCallbackBufferItem.mGraphicBuffer != nullptr) {
+        mBufferItemConsumer->releaseBuffer(mNextCallbackBufferItem,
+                                           stats[0].previousReleaseFence
+                                                   ? stats[0].previousReleaseFence
+                                                   : Fence::NO_FENCE);
+        mNextCallbackBufferItem = BufferItem();
+    }
+    mDequeueWaitCV.notify_one();
+    decStrong((void*)transactionCallbackThunk);
+}
+
+void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
+    std::unique_lock _lock{mMutex};
+
+    SurfaceComposerClient::Transaction localTransaction;
+    bool applyTransaction = true;
+    SurfaceComposerClient::Transaction* t = &localTransaction;
+    if (mNextTransaction != nullptr) {
+        t = mNextTransaction;
+        mNextTransaction = nullptr;
+        applyTransaction = false;
+    }
+
+    int status = OK;
+    mNextCallbackBufferItem = mLastSubmittedBufferItem;
+
+    mLastSubmittedBufferItem = BufferItem();
+    status = mBufferItemConsumer->acquireBuffer(&mLastSubmittedBufferItem, -1, false);
+    if (status != OK) {
+        ALOGE("Failed to acquire?");
+    }
+
+    auto buffer = mLastSubmittedBufferItem.mGraphicBuffer;
+
+    if (buffer == nullptr) {
+        ALOGE("Null buffer");
+        return;
+    }
+
+
+    // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
+    incStrong((void*)transactionCallbackThunk);
+
+    t->setBuffer(mSurfaceControl, buffer);
+    t->setAcquireFence(mSurfaceControl,
+                       item.mFence ? new Fence(item.mFence->dup()) : Fence::NO_FENCE);
+    t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));
+
+    t->setFrame(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()});
+    t->setCrop(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()});
+
+    if (applyTransaction) {
+        ALOGE("Apply transaction");
+        t->apply();
+
+        if (mNextCallbackBufferItem.mGraphicBuffer != nullptr) {
+            mDequeueWaitCV.wait_for(_lock, 5000ms);
+        }
+    }
+}
+
+void BLASTBufferQueue::setNextTransaction(SurfaceComposerClient::Transaction* t) {
+    std::unique_lock _lock{mMutex};
+    mNextTransaction = t;
+}
+
+} // namespace android
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
new file mode 100644
index 0000000..6320556
--- /dev/null
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GUI_BLAST_BUFFER_QUEUE_H
+#define ANDROID_GUI_BLAST_BUFFER_QUEUE_H
+
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/BufferItemConsumer.h>
+#include <gui/BufferItem.h>
+#include <gui/SurfaceComposerClient.h>
+
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+
+#include <system/window.h>
+
+namespace android {
+
+class BufferItemConsumer;
+
+class BLASTBufferQueue
+    : public ConsumerBase::FrameAvailableListener, public BufferItemConsumer::BufferFreedListener
+{
+public:
+    BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height);
+    sp<IGraphicBufferProducer> getIGraphicBufferProducer() const {
+        return mProducer;
+    }
+
+    void onBufferFreed(const wp<GraphicBuffer>&/* graphicBuffer*/) override { /* TODO */ }
+    void onFrameReplaced(const BufferItem& item) override {onFrameAvailable(item);}
+    void onFrameAvailable(const BufferItem& item) override;
+
+    void transactionCallback(nsecs_t latchTime, const sp<Fence>& presentFence,
+            const std::vector<SurfaceControlStats>& stats);
+    void setNextTransaction(SurfaceComposerClient::Transaction *t);
+
+    void update(const sp<SurfaceControl>& surface, int width, int height);
+    
+
+    virtual ~BLASTBufferQueue() = default;
+
+private:
+    friend class BLASTBufferQueueHelper;
+
+    // can't be copied
+    BLASTBufferQueue& operator = (const BLASTBufferQueue& rhs);
+    BLASTBufferQueue(const BLASTBufferQueue& rhs);
+
+    sp<SurfaceControl> mSurfaceControl;
+    
+    mutable std::mutex mMutex;
+
+    static const int MAX_BUFFERS = 2;
+    struct BufferInfo {
+        sp<GraphicBuffer> buffer;
+        int fence;
+    };
+    
+    int mDequeuedBuffers = 0;
+
+    int mWidth;
+    int mHeight;
+
+    BufferItem mLastSubmittedBufferItem;
+    BufferItem mNextCallbackBufferItem;
+    sp<Fence> mLastFence;
+
+    std::condition_variable mDequeueWaitCV;
+
+    sp<IGraphicBufferConsumer> mConsumer;
+    sp<IGraphicBufferProducer> mProducer;
+    sp<BufferItemConsumer> mBufferItemConsumer;
+
+    SurfaceComposerClient::Transaction* mNextTransaction = nullptr;
+};
+
+} // namespace android
+
+#endif  // ANDROID_GUI_SURFACE_H
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index cbda6b2..7f960ab 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -13,7 +13,8 @@
     ],
 
     srcs: [
-        "BufferItemConsumer_test.cpp",
+        "BLASTBufferQueue_test.cpp",
+	"BufferItemConsumer_test.cpp",
         "BufferQueue_test.cpp",
         "CpuConsumer_test.cpp",
         "EndToEndNativeInputTest.cpp",
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
new file mode 100644
index 0000000..a5f115e
--- /dev/null
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "BLASTBufferQueue_test"
+
+#include <gui/BLASTBufferQueue.h>
+
+#include <gui/SurfaceComposerClient.h>
+#include <ui/GraphicBuffer.h>
+
+#include <gtest/gtest.h>
+
+using namespace std::chrono_literals;
+
+namespace android {
+
+const int DEFAULT_WIDTH = 100;
+const int DEFAULT_HEIGHT = 100;
+
+using Transaction = SurfaceComposerClient::Transaction;
+
+class BLASTBufferQueueHelper {
+public:
+    BLASTBufferQueueHelper(const sp<SurfaceControl>& sc, int width, int height) {
+        mBlastBufferQueueAdapter = new BLASTBufferQueue(sc, width, height);
+    }
+
+    void update(const sp<SurfaceControl>& sc, int width, int height) {
+        mBlastBufferQueueAdapter->update(sc, width, height);
+    }
+
+    void setNextTransaction(Transaction* next) {
+        mBlastBufferQueueAdapter->setNextTransaction(next);
+    }
+
+    int getWidth() { return mBlastBufferQueueAdapter->mWidth; }
+    int getHeight() { return mBlastBufferQueueAdapter->mHeight; }
+    Transaction* getNextTransaction() { return mBlastBufferQueueAdapter->mNextTransaction; }
+    const sp<SurfaceControl> getSurfaceControl() {
+        return mBlastBufferQueueAdapter->mSurfaceControl;
+    }
+
+private:
+    sp<BLASTBufferQueue> mBlastBufferQueueAdapter;
+};
+
+class BLASTBufferQueueTest : public ::testing::Test {
+public:
+protected:
+    BLASTBufferQueueTest() {
+        const ::testing::TestInfo* const testInfo =
+                ::testing::UnitTest::GetInstance()->current_test_info();
+        ALOGV("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name());
+    }
+
+    ~BLASTBufferQueueTest() {
+        const ::testing::TestInfo* const testInfo =
+                ::testing::UnitTest::GetInstance()->current_test_info();
+        ALOGV("End test:   %s.%s", testInfo->test_case_name(), testInfo->name());
+    }
+
+    void SetUp() {
+        mClient = new SurfaceComposerClient();
+        mSurfaceControl = mClient->createSurface(String8("TestSurface"), DEFAULT_WIDTH,
+                                                 DEFAULT_HEIGHT, PIXEL_FORMAT_RGBA_8888);
+    }
+
+    sp<SurfaceComposerClient> mClient;
+    sp<SurfaceControl> mSurfaceControl;
+};
+
+TEST_F(BLASTBufferQueueTest, CreateBLASTBufferQueue) {
+    // create BLASTBufferQueue adapter associated with this surface
+    BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+    ASSERT_EQ(mSurfaceControl, adapter.getSurfaceControl());
+    ASSERT_EQ(DEFAULT_WIDTH, adapter.getWidth());
+    ASSERT_EQ(DEFAULT_HEIGHT, adapter.getHeight());
+    ASSERT_EQ(nullptr, adapter.getNextTransaction());
+}
+
+TEST_F(BLASTBufferQueueTest, Update) {
+    BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+    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);
+    ASSERT_EQ(updateSurface, adapter.getSurfaceControl());
+    ASSERT_EQ(DEFAULT_WIDTH / 2, adapter.getWidth());
+    ASSERT_EQ(DEFAULT_HEIGHT / 2, adapter.getHeight());
+}
+
+TEST_F(BLASTBufferQueueTest, SetNextTransaction) {
+    BLASTBufferQueueHelper adapter(mSurfaceControl, DEFAULT_WIDTH, DEFAULT_HEIGHT);
+    Transaction next;
+    adapter.setNextTransaction(&next);
+    ASSERT_EQ(&next, adapter.getNextTransaction());
+}
+} // namespace android
diff --git a/opengl/tests/gl_perf/fill_common.cpp b/opengl/tests/gl_perf/fill_common.cpp
index fefedc0..613f1c6 100644
--- a/opengl/tests/gl_perf/fill_common.cpp
+++ b/opengl/tests/gl_perf/fill_common.cpp
@@ -191,10 +191,10 @@
 static void randUniform(int pgm, const char *var) {
     GLint loc = glGetUniformLocation(pgm, var);
     if (loc >= 0) {
-        float x = ((float)rand()) / RAND_MAX;
-        float y = ((float)rand()) / RAND_MAX;
-        float z = ((float)rand()) / RAND_MAX;
-        float w = ((float)rand()) / RAND_MAX;
+        float x = ((float)rand()) / (float)RAND_MAX;
+        float y = ((float)rand()) / (float)RAND_MAX;
+        float z = ((float)rand()) / (float)RAND_MAX;
+        float w = ((float)rand()) / (float)RAND_MAX;
         glUniform4f(loc, x, y, z, w);
     }
 }
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 7d30672..e7640dd 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -128,7 +128,7 @@
                 "from non shell/root entity (PID: %d)", ipc->getCallingPid());
         return;
     }
-    mDispatcher->registerInputChannel(channel, false);
+    mDispatcher->registerInputChannel(channel);
 }
 
 void InputManager::unregisterInputChannel(const sp<InputChannel>& channel) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 4db9ae2..ee8c344 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -3865,11 +3865,9 @@
     }
 }
 
-status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
-                                               int32_t displayId) {
+status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {
 #if DEBUG_REGISTRATION
-    ALOGD("channel '%s' ~ registerInputChannel - displayId=%" PRId32,
-          inputChannel->getName().c_str(), displayId);
+    ALOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().c_str());
 #endif
 
     { // acquire lock
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 0d9d6b0..1f906e4 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -106,8 +106,7 @@
     virtual bool transferTouchFocus(const sp<IBinder>& fromToken,
                                     const sp<IBinder>& toToken) override;
 
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
-                                          int32_t displayId) override;
+    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) override;
     virtual status_t registerInputMonitor(const sp<InputChannel>& inputChannel, int32_t displayId,
                                           bool isGestureMonitor) override;
     virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) override;
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
index 18848a0..2baceba 100644
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ b/services/inputflinger/dispatcher/TouchState.cpp
@@ -93,15 +93,6 @@
                            std::end(newMonitors));
 }
 
-void TouchState::removeWindow(const sp<InputWindowHandle>& windowHandle) {
-    for (size_t i = 0; i < windows.size(); i++) {
-        if (windows[i].windowHandle == windowHandle) {
-            windows.erase(windows.begin() + i);
-            return;
-        }
-    }
-}
-
 void TouchState::removeWindowByToken(const sp<IBinder>& token) {
     for (size_t i = 0; i < windows.size(); i++) {
         if (windows[i].windowHandle->getToken() == token) {
diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h
index 3e0e0eb..623c6a8 100644
--- a/services/inputflinger/dispatcher/TouchState.h
+++ b/services/inputflinger/dispatcher/TouchState.h
@@ -49,7 +49,6 @@
                            BitSet32 pointerIds);
     void addPortalWindow(const sp<android::InputWindowHandle>& windowHandle);
     void addGestureMonitors(const std::vector<TouchedMonitor>& monitors);
-    void removeWindow(const sp<android::InputWindowHandle>& windowHandle);
     void removeWindowByToken(const sp<IBinder>& token);
     void filterNonAsIsTouchWindows();
     void filterNonMonitors();
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 9329ca6..ce7366f 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -126,8 +126,7 @@
      *
      * This method may be called on any thread (usually by the input manager).
      */
-    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel,
-                                          int32_t displayId) = 0;
+    virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel) = 0;
 
     /* Registers input channels to be used to monitor input events.
      *
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index aa98ef7..7d69854 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -471,7 +471,7 @@
             FakeInputReceiver(dispatcher, name, displayId),
             mFocused(false), mFrame(Rect(0, 0, WIDTH, HEIGHT)), mLayoutParamFlags(0) {
             mServerChannel->setToken(new BBinder());
-            mDispatcher->registerInputChannel(mServerChannel, displayId);
+            mDispatcher->registerInputChannel(mServerChannel);
 
             inputApplicationHandle->updateInfo();
             mInfo.applicationInfo = *inputApplicationHandle->getInfo();
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index 3df8360..3e47ec6 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -28,7 +28,6 @@
 #include <utils/Trace.h>
 
 #include <algorithm>
-#include <regex>
 
 namespace android {
 
@@ -156,22 +155,6 @@
     return static_cast<int32_t>(delta);
 }
 
-// This regular expression captures the following for instance:
-// StatusBar in StatusBar#0
-// com.appname in com.appname/com.appname.activity#0
-// com.appname in SurfaceView - com.appname/com.appname.activity#0
-static const std::regex packageNameRegex("(?:SurfaceView[-\\s\\t]+)?([^/]+).*#\\d+");
-
-static std::string getPackageName(const std::string& layerName) {
-    std::smatch match;
-    if (std::regex_match(layerName.begin(), layerName.end(), match, packageNameRegex)) {
-        // There must be a match for group 1 otherwise the whole string is not
-        // matched and the above will return false
-        return match[1];
-    }
-    return "";
-}
-
 void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerID) {
     ATRACE_CALL();
 
@@ -187,7 +170,6 @@
             const std::string& layerName = layerRecord.layerName;
             if (!mTimeStats.stats.count(layerName)) {
                 mTimeStats.stats[layerName].layerName = layerName;
-                mTimeStats.stats[layerName].packageName = getPackageName(layerName);
             }
             TimeStatsHelper::TimeStatsLayer& timeStatsLayer = mTimeStats.stats[layerName];
             timeStatsLayer.totalFrames++;
@@ -236,19 +218,13 @@
     }
 }
 
-// This regular expression captures the following layer names for instance:
-// 1) StatusBat#0
-// 2) NavigationBar#1
-// 3) co(m).*#0
-// 4) SurfaceView - co(m).*#0
-// Using [-\\s\t]+ for the conjunction part between SurfaceView and co(m).*
-// is a bit more robust in case there's a slight change.
-// The layer name would only consist of . / $ _ 0-9 a-z A-Z in most cases.
-static const std::regex layerNameRegex(
-        "(((SurfaceView[-\\s\\t]+)?com?\\.[./$\\w]+)|((Status|Navigation)Bar))#\\d+");
+static constexpr const char* kPopupWindowPrefix = "PopupWindow";
+static const size_t kMinLenLayerName = std::strlen(kPopupWindowPrefix);
 
+// Avoid tracking the "PopupWindow:<random hash>#<number>" layers
 static bool layerNameIsValid(const std::string& layerName) {
-    return std::regex_match(layerName.begin(), layerName.end(), layerNameRegex);
+    return layerName.length() >= kMinLenLayerName &&
+            layerName.compare(0, kMinLenLayerName, kPopupWindowPrefix) != 0;
 }
 
 void TimeStats::setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName,
diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
index dee2cae..4eb9ec3 100644
--- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
@@ -171,7 +171,7 @@
 }
 
 static std::string genLayerName(int32_t layerID) {
-    return (layerID < 0 ? "invalid.dummy" : "com.dummy#") + std::to_string(layerID);
+    return (layerID < 0 ? "PopupWindow:b54fcd1#0" : "com.dummy#") + std::to_string(layerID);
 }
 
 void TimeStatsTest::setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts) {
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index d829e41..f676573 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -480,14 +480,14 @@
     if (strcmp(name, "VK_EXT_swapchain_colorspace") == 0) return ProcHook::EXT_swapchain_colorspace;
     if (strcmp(name, "VK_GOOGLE_display_timing") == 0) return ProcHook::GOOGLE_display_timing;
     if (strcmp(name, "VK_KHR_android_surface") == 0) return ProcHook::KHR_android_surface;
+    if (strcmp(name, "VK_KHR_get_surface_capabilities2") == 0) return ProcHook::KHR_get_surface_capabilities2;
     if (strcmp(name, "VK_KHR_incremental_present") == 0) return ProcHook::KHR_incremental_present;
     if (strcmp(name, "VK_KHR_shared_presentable_image") == 0) return ProcHook::KHR_shared_presentable_image;
     if (strcmp(name, "VK_KHR_surface") == 0) return ProcHook::KHR_surface;
     if (strcmp(name, "VK_KHR_swapchain") == 0) return ProcHook::KHR_swapchain;
-    if (strcmp(name, "VK_KHR_get_surface_capabilities2") == 0) return ProcHook::KHR_get_surface_capabilities2;
-    if (strcmp(name, "VK_KHR_get_physical_device_properties2") == 0) return ProcHook::KHR_get_physical_device_properties2;
     if (strcmp(name, "VK_ANDROID_external_memory_android_hardware_buffer") == 0) return ProcHook::ANDROID_external_memory_android_hardware_buffer;
     if (strcmp(name, "VK_KHR_bind_memory2") == 0) return ProcHook::KHR_bind_memory2;
+    if (strcmp(name, "VK_KHR_get_physical_device_properties2") == 0) return ProcHook::KHR_get_physical_device_properties2;
     // clang-format on
     return ProcHook::EXTENSION_UNKNOWN;
 }
@@ -562,5 +562,3 @@
 
 }  // namespace driver
 }  // namespace vulkan
-
-// clang-format on
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index fb2f257..cd7d8f8 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -40,14 +40,14 @@
         EXT_swapchain_colorspace,
         GOOGLE_display_timing,
         KHR_android_surface,
+        KHR_get_surface_capabilities2,
         KHR_incremental_present,
         KHR_shared_presentable_image,
         KHR_surface,
         KHR_swapchain,
-        KHR_get_surface_capabilities2,
-        KHR_get_physical_device_properties2,
         ANDROID_external_memory_android_hardware_buffer,
         KHR_bind_memory2,
+        KHR_get_physical_device_properties2,
 
         EXTENSION_CORE,  // valid bit
         EXTENSION_COUNT,
diff --git a/vulkan/nulldrv/null_driver_gen.h b/vulkan/nulldrv/null_driver_gen.h
index 668dc7d..0d3f688 100644
--- a/vulkan/nulldrv/null_driver_gen.h
+++ b/vulkan/nulldrv/null_driver_gen.h
@@ -207,9 +207,6 @@
 VKAPI_ATTR VkResult GetSwapchainGrallocUsage2ANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, uint64_t* grallocConsumerUsage, uint64_t* grallocProducerUsage);
 VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
 VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
-VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
-VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
-VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
 // clang-format on
 
 }  // namespace null_driver
diff --git a/vulkan/scripts/api_generator.py b/vulkan/scripts/api_generator.py
index a0c648c..d1fff42 100644
--- a/vulkan/scripts/api_generator.py
+++ b/vulkan/scripts/api_generator.py
@@ -20,21 +20,36 @@
 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
+_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():
+  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 +61,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 +93,54 @@
 }  // 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):
+  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 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')
+    f.write('VKAPI_ATTR ' + ret + ' disabled' + gencom.base_name(cmd) +
+            '(' + first_param + ', ' + tail_params + ') {\n')
 
-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(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):
+  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):
+  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 +148,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 +178,25 @@
     }
     // 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):
+  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 +209,38 @@
         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):
+  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():
+  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 +252,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 +360,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..378a9c0 100755
--- a/vulkan/scripts/code_generator.py
+++ b/vulkan/scripts/code_generator.py
@@ -17,16 +17,16 @@
 # 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
+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 ef36f8c..5fff83e 100644
--- a/vulkan/scripts/driver_generator.py
+++ b/vulkan/scripts/driver_generator.py
@@ -17,41 +17,147 @@
 # This script provides the functions for generating the
 # vulkan driver framework directly from the vulkan registry (vk.xml).
 
-import generator_common as gencom
 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_incremental_present',
-  'VK_KHR_shared_presentable_image',
-  'VK_KHR_surface',
-  'VK_KHR_swapchain',
-  'VK_KHR_get_surface_capabilities2'
+_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_KHR_get_physical_device_properties2',
-  'VK_ANDROID_external_memory_android_hardware_buffer',
-  'VK_KHR_bind_memory2'
+_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 {
+_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',
+]
+
+_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):
+  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):
+  return (_is_driver_table_entry(cmd) and
+          gencom.is_instance_dispatched(cmd))
+
+
+def _is_device_driver_table_entry(cmd):
+  return (_is_driver_table_entry(cmd) and
+          gencom.is_device_dispatched(cmd))
+
+
+def gen_h():
+  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 exts in _KNOWN_EXTENSIONS:
+      f.write(gencom.indent(2) + exts[3:] + ',\n')
+
+    f.write("""
+        EXTENSION_CORE,  // valid bit
         EXTENSION_COUNT,
         EXTENSION_UNKNOWN,
     };
@@ -62,99 +168,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 +208,131 @@
 }  // 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):
+  if gencom.is_function_supported(cmd):
+    if cmd in _INTERCEPTED_COMMANDS:
+      return True
 
-    # Enumeration of extensions
-    'vkEnumerateInstanceExtensionProperties' : True,
-    'vkEnumerateDeviceExtensionProperties' : 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 _need_proc_hook_stub(cmd):
+  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
   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 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')
+def _define_proc_hook_stub(cmd, f):
+  if _need_proc_hook_stub(cmd):
+    return_type = gencom.return_type_dict[cmd]
+    ext_name = gencom.extension_dict[cmd]
     ext_hook = 'ProcHook::' + ext_name[3:]
+    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 (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')
+    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')
 
-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,
+    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):
+  assert cmd not in gencom.extension_dict
+
+  f.write(gencom.indent(1) + '{\n')
+  f.write(gencom.indent(2) + '\"' + cmd + '\",\n')
+  f.write("""\
+        ProcHook::GLOBAL,
         ProcHook::EXTENSION_CORE,
-        reinterpret_cast<PFN_vkVoidFunction>(""" + base_name  + """),
+        reinterpret_cast<PFN_vkVoidFunction>(""" + gencom.base_name(cmd) + """),
         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')
+def _define_instance_proc_hook(cmd, f):
+  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::' + ext_name[3:] + ',\n')
+
+    if gencom.is_extension_internal(ext_name):
+      f.write("""\
+        nullptr,
+        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("""\
+        ProcHook::EXTENSION_CORE,
+        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):
+  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:
+    ext_name = gencom.extension_dict[cmd]
+    f.write(gencom.indent(2) + 'ProcHook::' + ext_name[3:] + ',\n')
+
+    if gencom.is_extension_internal(ext_name):
+      f.write("""\
+        nullptr,
+        nullptr,\n""")
     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')
+      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("""\
+        ProcHook::EXTENSION_CORE,
+        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():
+  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 +344,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 +379,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 exts in _KNOWN_EXTENSIONS:
+      f.write(gencom.indent(1) + 'if (strcmp(name, \"' + exts +
+              '\") == 0) return ProcHook::' + exts[3:] + ';\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 fe9dab4..03993e2 100644
--- a/vulkan/scripts/generator_common.py
+++ b/vulkan/scripts/generator_common.py
@@ -17,10 +17,77 @@
 # This script provides the common functions for generating the
 # vulkan framework directly from the vulkan registry (vk.xml).
 
-from subprocess import check_call
+import os
+import subprocess
+import xml.etree.ElementTree as element_tree
 
-copyright = """/*
- * Copyright 2016 The Android Open Source Project
+_BLACKLISTED_EXTENSIONS = [
+    'VK_EXT_acquire_xlib_display',
+    'VK_EXT_direct_mode_display',
+    'VK_EXT_display_control',
+    'VK_EXT_display_surface_counter',
+    'VK_EXT_full_screen_exclusive',
+    'VK_EXT_headless_surface',
+    'VK_EXT_metal_surface',
+    'VK_FUCHSIA_imagepipe_surface',
+    'VK_GGP_stream_descriptor_surface',
+    'VK_KHR_display',
+    'VK_KHR_display_swapchain',
+    'VK_KHR_external_fence_win32',
+    'VK_KHR_external_memory_win32',
+    'VK_KHR_external_semaphore_win32',
+    'VK_KHR_mir_surface',
+    'VK_KHR_wayland_surface',
+    'VK_KHR_win32_keyed_mutex',
+    'VK_KHR_win32_surface',
+    'VK_KHR_xcb_surface',
+    'VK_KHR_xlib_surface',
+    'VK_MVK_ios_surface',
+    'VK_MVK_macos_surface',
+    'VK_NN_vi_surface',
+    'VK_NV_cooperative_matrix',
+    'VK_NV_coverage_reduction_mode',
+    'VK_NV_external_memory_win32',
+    'VK_NV_win32_keyed_mutex',
+    'VK_NVX_image_view_handle',
+]
+
+_EXPORTED_EXTENSIONS = [
+    'VK_ANDROID_external_memory_android_hardware_buffer',
+    'VK_KHR_android_surface',
+    'VK_KHR_surface',
+    'VK_KHR_swapchain',
+]
+
+_OPTIONAL_COMMANDS = [
+    'vkGetSwapchainGrallocUsageANDROID',
+    'vkGetSwapchainGrallocUsage2ANDROID',
+]
+
+_DISPATCH_TYPE_DICT = {
+    'VkInstance ': 'Instance',
+    'VkPhysicalDevice ': 'Instance',
+    'VkDevice ': 'Device',
+    'VkQueue ': 'Device',
+    'VkCommandBuffer ': 'Device'
+}
+
+alias_dict = {}
+command_list = []
+extension_dict = {}
+param_dict = {}
+return_type_dict = {}
+version_dict = {}
+
+
+def indent(num):
+  return '    ' * num
+
+
+def copyright_and_warning(year):
+  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.
@@ -35,221 +102,168 @@
  * limitations under the License.
  */
 
+// WARNING: This file is generated. See ../README.md for instructions.
+
 """
 
-warning = '// WARNING: This file is generated. See ../README.md for instructions.\n\n'
 
-blacklistedExtensions = [
-    'VK_KHR_display',
-    'VK_KHR_display_swapchain',
-    'VK_KHR_mir_surface',
-    'VK_KHR_xcb_surface',
-    'VK_KHR_xlib_surface',
-    'VK_KHR_wayland_surface',
-    'VK_KHR_win32_surface',
-    'VK_KHR_external_memory_win32',
-    'VK_KHR_win32_keyed_mutex',
-    'VK_KHR_external_semaphore_win32',
-    'VK_KHR_external_fence_win32',
-    'VK_EXT_acquire_xlib_display',
-    'VK_EXT_direct_mode_display',
-    'VK_EXT_display_surface_counter',
-    'VK_EXT_display_control',
-    'VK_FUCHSIA_imagepipe_surface',
-    'VK_MVK_ios_surface',
-    'VK_MVK_macos_surface',
-    'VK_NN_vi_surface',
-    'VK_NV_external_memory_win32',
-    'VK_NV_win32_keyed_mutex',
-    'VK_EXT_metal_surface', #not present in vulkan.api
-    'VK_NVX_image_view_handle', #not present in vulkan.api
-    'VK_NV_cooperative_matrix', #not present in vulkan.api
-    'VK_EXT_headless_surface', #not present in vulkan.api
-    'VK_GGP_stream_descriptor_surface', #not present in vulkan.api
-    'VK_NV_coverage_reduction_mode', #not present in vulkan.api
-    'VK_EXT_full_screen_exclusive' #not present in vulkan.api
-]
+def run_clang_format(args):
+  clang_call = ['clang-format', '--style', 'file', '-i', args]
+  subprocess.check_call(clang_call)
 
-exportedExtensions = [
-    'VK_KHR_surface',
-    'VK_KHR_swapchain',
-    'VK_KHR_android_surface',
-    'VK_ANDROID_external_memory_android_hardware_buffer'
-]
 
-def runClangFormat(args):
-  clang_call = ["clang-format", "--style", "file", "-i", args]
-  check_call (clang_call)
+def is_extension_internal(extension_name):
+  return extension_name == 'VK_ANDROID_native_buffer'
 
-def isExtensionInternal(extensionName):
-  if extensionName == 'VK_ANDROID_native_buffer':
-    return True
-  return False
 
-def isFunctionSupported(functionName):
-  if functionName not in extensionsDict:
+def base_name(cmd):
+  return cmd[2:]
+
+
+def is_function_supported(cmd):
+  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 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:
+def get_dispatch_table_type(cmd):
+  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):
+  return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Global'
+
+
+def is_instance_dispatched(cmd):
+  return (is_function_supported(cmd) and
+          get_dispatch_table_type(cmd) == 'Instance')
+
+
+def is_device_dispatched(cmd):
+  return is_function_supported(cmd) and get_dispatch_table_type(cmd) == 'Device'
+
+
+def is_extension_exported(extension_name):
+  return extension_name in _EXPORTED_EXTENSIONS
+
+
+def is_function_exported(cmd):
+  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):
+  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):
+  return is_function_exported(cmd) and is_device_dispatched(cmd)
 
-def clang_off(f, indent):
-  f.write (clang_off_spaces * indent + '// clang-format off\n')
 
-clang_off_spaces = ' ' * 4
+def init_proc(name, f):
+  f.write(indent(1))
+  if name in extension_dict:
+    f.write('INIT_PROC_EXT(' + extension_dict[name][3:] + ', ')
+  else:
+    f.write('INIT_PROC(')
 
-parametersList = []
-paramDict = {}
-allCommandsList = []
-extensionsDict = {}
-returnTypeDict = {}
-versionDict = {}
-aliasDict = {}
+  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, ')
 
-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)
+  if is_instance_dispatched(name):
+    f.write('instance, ')
+  else:
+    f.write('dev, ')
+
+  f.write(base_name(name) + ');\n')
+
+
+def parse_vulkan_registry():
+  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
-
-
-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 == 'vkGetSwapchainGrallocUsageANDROID' or name == 'vkGetSwapchainGrallocUsage2ANDROID': # optional in vulkan.api
-    f.write('false, ')
-  else:
-    f.write('true, ')
-
-  if isInstanceDispatched(name):
-    f.write('instance, ')
-  else:
-    f.write('dev, ')
-
-  f.write(name[2:] + ');\n')
-
+          cmd_name = command.get('name')
+          if cmd_name in command_list:
+            version_dict[cmd_name] = apiversion
diff --git a/vulkan/scripts/null_generator.py b/vulkan/scripts/null_generator.py
index ee8762e..2a99a1d 100644
--- a/vulkan/scripts/null_generator.py
+++ b/vulkan/scripts/null_generator.py
@@ -17,45 +17,31 @@
 # 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
+import generator_common as gencom
 
-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.
- */
+_DRIVER_EXTENSION_DICT = {
+    'VK_ANDROID_native_buffer',
+    'VK_EXT_debug_report',
+    'VK_KHR_get_physical_device_properties2'
+}
 
-"""
 
-def isDriverExtension(extensionName):
-  switchCase = {
-    'VK_ANDROID_native_buffer' : True,
-    'VK_EXT_debug_report' : True,
-    'VK_KHR_get_physical_device_properties2' : True
-  }
-
-  if extensionName in switchCase:
-    return switchCase[extensionName]
-  return False
-
-def isDriverFunction(functionName):
-  if functionName in gencom.extensionsDict:
-    return isDriverExtension(gencom.extensionsDict[functionName])
+def _is_driver_function(cmd):
+  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():
+  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,30 +52,34 @@
 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')
-    f.write ("""VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
-VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
-VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);\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():
+  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"
 
@@ -119,30 +109,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);
@@ -153,6 +149,6 @@
 }
 
 }  // namespace null_driver\n""")
-    f.close()
-  gencom.runClangFormat(genfile)
 
+    f.close()
+  gencom.run_clang_format(genfile)