Merge "Fix InputReader_test"
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 2ee6a07..b1338f8 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -525,8 +525,10 @@
 // their system properties.
 static void pokeHalServices()
 {
+    using ::android::hidl::base::V1_0::IBase;
     using ::android::hidl::manager::V1_0::IServiceManager;
     using ::android::hardware::hidl_string;
+    using ::android::hardware::Return;
 
     sp<IServiceManager> sm = ::android::hardware::defaultServiceManager();
 
@@ -543,23 +545,24 @@
                 continue;
             hidl_string fqInterfaceName = fqInstanceName.substr(0, n);
             hidl_string instanceName = fqInstanceName.substr(n+1, std::string::npos);
-            auto getRet = sm->get(fqInterfaceName, instanceName, [&](const auto &interface) {
-                auto notifyRet = interface->notifySyspropsChanged();
-                if (!notifyRet.isOk()) {
-                    fprintf(stderr, "failed to notifySyspropsChanged on service %s: %s\n",
-                            fqInstanceName.c_str(),
-                            notifyRet.getStatus().toString8().string());
-                }
-            });
-            if (!getRet.isOk()) {
+            Return<sp<IBase>> interfaceRet = sm->get(fqInterfaceName, instanceName);
+            if (!interfaceRet.isOk()) {
                 fprintf(stderr, "failed to get service %s: %s\n",
                         fqInstanceName.c_str(),
-                        getRet.getStatus().toString8().string());
+                        interfaceRet.description().c_str());
+                continue;
+            }
+            sp<IBase> interface = interfaceRet;
+            auto notifyRet = interface->notifySyspropsChanged();
+            if (!notifyRet.isOk()) {
+                fprintf(stderr, "failed to notifySyspropsChanged on service %s: %s\n",
+                        fqInstanceName.c_str(),
+                        notifyRet.description().c_str());
             }
         }
     });
     if (!listRet.isOk()) {
-        fprintf(stderr, "failed to list services: %s\n", listRet.getStatus().toString8().string());
+        fprintf(stderr, "failed to list services: %s\n", listRet.description().c_str());
     }
 }
 
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index 897cfb1..af87ffa 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -16,6 +16,7 @@
         utils.cpp
 COMMON_SHARED_LIBRARIES := \
         android.hardware.dumpstate@1.0 \
+        libhidlbase \
         libbase \
         libbinder \
         libcutils \
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 1e33439..ccc8378 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1074,6 +1074,8 @@
     RunCommand("VOLD DUMP", {"vdc", "dump"});
     RunCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
 
+    RunCommand("STORAGED TASKIOINFO", {"storaged", "-d"}, CommandOptions::WithTimeout(10).Build());
+
     RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
 
     RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index ee88705..0f50fc9 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -23,9 +23,25 @@
 #include <libgen.h>
 #include <math.h>
 #include <poll.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/capability.h>
 #include <sys/inotify.h>
 #include <sys/klog.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <time.h>
+#include <unistd.h>
 
+#include <string>
+#include <vector>
+
+#include <android/log.h>
 #include <android-base/file.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 8a9d6a6..ee4d541 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -18,12 +18,17 @@
 
 #include <errno.h>
 #include <inttypes.h>
+#include <fstream>
+#include <fts.h>
 #include <regex>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/capability.h>
 #include <sys/file.h>
 #include <sys/resource.h>
+#include <sys/quota.h>
 #include <sys/stat.h>
+#include <sys/statvfs.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/xattr.h>
@@ -37,7 +42,6 @@
 #include <cutils/log.h>               // TODO: Move everything to base/logging.
 #include <cutils/properties.h>
 #include <cutils/sched_policy.h>
-#include <diskusage/dirsize.h>
 #include <logwrap/logwrap.h>
 #include <private/android_filesystem_config.h>
 #include <selinux/android.h>
@@ -49,6 +53,8 @@
 #include "otapreopt_utils.h"
 #include "utils.h"
 
+#include "MatchExtensionGen.h"
+
 #ifndef LOG_TAG
 #define LOG_TAG "installd"
 #endif
@@ -77,7 +83,7 @@
 // NOTE: keep in sync with Installer
 static constexpr int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
 static constexpr int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9;
-
+static constexpr int FLAG_USE_QUOTA = 1 << 12;
 
 namespace {
 
@@ -87,10 +93,6 @@
     return binder::Status::ok();
 }
 
-static binder::Status exception(uint32_t code) {
-    return binder::Status::fromExceptionCode(code);
-}
-
 static binder::Status exception(uint32_t code, const std::string& msg) {
     return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
 }
@@ -204,7 +206,8 @@
  * if the label of that top-level file actually changed.  This can save us
  * significant time by avoiding no-op traversals of large filesystem trees.
  */
-static int restorecon_app_data_lazy(const std::string& path, const std::string& seInfo, uid_t uid) {
+static int restorecon_app_data_lazy(const std::string& path, const std::string& seInfo, uid_t uid,
+        bool existing) {
     int res = 0;
     char* before = nullptr;
     char* after = nullptr;
@@ -228,8 +231,10 @@
     // If the initial top-level restorecon above changed the label, then go
     // back and restorecon everything recursively
     if (strcmp(before, after)) {
-        LOG(DEBUG) << "Detected label change from " << before << " to " << after << " at " << path
-                << "; running recursive restorecon";
+        if (existing) {
+            LOG(DEBUG) << "Detected label change from " << before << " to " << after << " at "
+                    << path << "; running recursive restorecon";
+        }
         if (selinux_android_restorecon_pkgdir(path.c_str(), seInfo.c_str(), uid,
                 SELINUX_ANDROID_RESTORECON_RECURSE) < 0) {
             PLOG(ERROR) << "Failed recursive restorecon for " << path;
@@ -247,8 +252,9 @@
 }
 
 static int restorecon_app_data_lazy(const std::string& parent, const char* name,
-        const std::string& seInfo, uid_t uid) {
-    return restorecon_app_data_lazy(StringPrintf("%s/%s", parent.c_str(), name), seInfo, uid);
+        const std::string& seInfo, uid_t uid, bool existing) {
+    return restorecon_app_data_lazy(StringPrintf("%s/%s", parent.c_str(), name), seInfo, uid,
+            existing);
 }
 
 static int prepare_app_dir(const std::string& path, mode_t target_mode, uid_t uid) {
@@ -259,14 +265,75 @@
     return 0;
 }
 
-static int prepare_app_dir(const std::string& parent, const char* name, mode_t target_mode,
-        uid_t uid) {
-    return prepare_app_dir(StringPrintf("%s/%s", parent.c_str(), name), target_mode, uid);
+/**
+ * Prepare an app cache directory, which offers to fix-up the GID and
+ * directory mode flags during a platform upgrade.
+ */
+static int prepare_app_cache_dir(const std::string& parent, const char* name, mode_t target_mode,
+        uid_t uid, gid_t gid) {
+    auto path = StringPrintf("%s/%s", parent.c_str(), name);
+    struct stat st;
+    if (stat(path.c_str(), &st) != 0) {
+        if (errno == ENOENT) {
+            // This is fine, just create it
+            if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, gid) != 0) {
+                PLOG(ERROR) << "Failed to prepare " << path;
+                return -1;
+            } else {
+                return 0;
+            }
+        } else {
+            PLOG(ERROR) << "Failed to stat " << path;
+            return -1;
+        }
+    }
+
+    if (st.st_uid != uid) {
+        // Mismatched UID is real trouble; we can't recover
+        LOG(ERROR) << "Mismatched UID at " << path << ": found " << st.st_uid
+                << " but expected " << uid;
+        return -1;
+    } else if (st.st_gid == gid && st.st_mode == target_mode) {
+        // Everything looks good!
+        return 0;
+    }
+
+    // Directory is owned correctly, but GID or mode mismatch means it's
+    // probably a platform upgrade so we need to fix them
+    FTS *fts;
+    FTSENT *p;
+    char *argv[] = { (char*) path.c_str(), nullptr };
+    if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) {
+        PLOG(ERROR) << "Failed to fts_open " << path;
+        return -1;
+    }
+    while ((p = fts_read(fts)) != NULL) {
+        switch (p->fts_info) {
+        case FTS_DP:
+            if (chmod(p->fts_accpath, target_mode) != 0) {
+                PLOG(WARNING) << "Failed to chmod " << p->fts_path;
+            }
+            // Intentional fall through to also set GID
+        case FTS_F:
+            if (chown(p->fts_accpath, -1, gid) != 0) {
+                PLOG(WARNING) << "Failed to chown " << p->fts_path;
+            }
+            break;
+        case FTS_SL:
+        case FTS_SLNONE:
+            if (lchown(p->fts_accpath, -1, gid) != 0) {
+                PLOG(WARNING) << "Failed to chown " << p->fts_path;
+            }
+            break;
+        }
+    }
+    fts_close(fts);
+    return 0;
 }
 
 binder::Status InstalldNativeService::createAppData(const std::unique_ptr<std::string>& uuid,
         const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
-        const std::string& seInfo, int32_t targetSdkVersion) {
+        const std::string& seInfo, int32_t targetSdkVersion, int64_t* _aidl_return) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
@@ -274,20 +341,27 @@
     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
     const char* pkgname = packageName.c_str();
 
+    // Assume invalid inode unless filled in below
+    if (_aidl_return != nullptr) *_aidl_return = -1;
+
     uid_t uid = multiuser_get_uid(userId, appId);
-    mode_t target_mode = targetSdkVersion >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
+    gid_t cacheGid = multiuser_get_cache_gid(userId, appId);
+    mode_t targetMode = targetSdkVersion >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
+
     if (flags & FLAG_STORAGE_CE) {
         auto path = create_data_user_ce_package_path(uuid_, userId, pkgname);
-        if (prepare_app_dir(path, target_mode, uid) ||
-                prepare_app_dir(path, "cache", 0771, uid) ||
-                prepare_app_dir(path, "code_cache", 0771, uid)) {
+        bool existing = (access(path.c_str(), F_OK) == 0);
+
+        if (prepare_app_dir(path, targetMode, uid) ||
+                prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) ||
+                prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) {
             return error("Failed to prepare " + path);
         }
 
         // Consider restorecon over contents if label changed
-        if (restorecon_app_data_lazy(path, seInfo, uid) ||
-                restorecon_app_data_lazy(path, "cache", seInfo, uid) ||
-                restorecon_app_data_lazy(path, "code_cache", seInfo, uid)) {
+        if (restorecon_app_data_lazy(path, seInfo, uid, existing) ||
+                restorecon_app_data_lazy(path, "cache", seInfo, uid, existing) ||
+                restorecon_app_data_lazy(path, "code_cache", seInfo, uid, existing)) {
             return error("Failed to restorecon " + path);
         }
 
@@ -297,15 +371,26 @@
                 write_path_inode(path, "code_cache", kXattrInodeCodeCache)) {
             return error("Failed to write_path_inode for " + path);
         }
+
+        // And return the CE inode of the top-level data directory so we can
+        // clear contents while CE storage is locked
+        if ((_aidl_return != nullptr)
+                && get_path_inode(path, reinterpret_cast<ino_t*>(_aidl_return)) != 0) {
+            return error("Failed to get_path_inode for " + path);
+        }
     }
     if (flags & FLAG_STORAGE_DE) {
         auto path = create_data_user_de_package_path(uuid_, userId, pkgname);
-        if (prepare_app_dir(path, target_mode, uid)) {
+        bool existing = (access(path.c_str(), F_OK) == 0);
+
+        if (prepare_app_dir(path, targetMode, uid) ||
+                prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) ||
+                prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) {
             return error("Failed to prepare " + path);
         }
 
         // Consider restorecon over contents if label changed
-        if (restorecon_app_data_lazy(path, seInfo, uid)) {
+        if (restorecon_app_data_lazy(path, seInfo, uid, existing)) {
             return error("Failed to restorecon " + path);
         }
 
@@ -323,8 +408,8 @@
             const std::string ref_profile_path = create_data_ref_profile_package_path(pkgname);
             // dex2oat/profman runs under the shared app gid and it needs to read/write reference
             // profiles.
-            appid_t shared_app_gid = multiuser_get_shared_app_gid(uid);
-            if (fs_prepare_dir_strict(
+            int shared_app_gid = multiuser_get_shared_gid(0, appId);
+            if ((shared_app_gid != -1) && fs_prepare_dir_strict(
                     ref_profile_path.c_str(), 0700, shared_app_gid, shared_app_gid) != 0) {
                 return error("Failed to prepare " + ref_profile_path);
             }
@@ -559,7 +644,7 @@
         }
 
         if (!createAppData(toUuid, packageName, user, FLAG_STORAGE_CE | FLAG_STORAGE_DE, appId,
-                seInfo, targetSdkVersion).isOk()) {
+                seInfo, targetSdkVersion, nullptr).isOk()) {
             res = error("Failed to create package target");
             goto fail;
         }
@@ -672,7 +757,7 @@
             if (delete_dir_contents_and_dir(path, true) != 0) {
                 res = error("Failed to delete " + path);
             }
-            path = create_data_user_profiles_path(userId);
+            path = create_data_user_profile_path(userId);
             if (delete_dir_contents_and_dir(path, true) != 0) {
                 res = error("Failed to delete " + path);
             }
@@ -765,8 +850,109 @@
     }
 }
 
-static void add_app_data_size(std::string& path, int64_t *codesize, int64_t *datasize,
-        int64_t *cachesize) {
+struct stats {
+    int64_t codeSize;
+    int64_t dataSize;
+    int64_t cacheSize;
+};
+
+#if MEASURE_DEBUG
+static std::string toString(std::vector<int64_t> values) {
+    std::stringstream res;
+    res << "[";
+    for (size_t i = 0; i < values.size(); i++) {
+        res << values[i];
+        if (i < values.size() - 1) {
+            res << ",";
+        }
+    }
+    res << "]";
+    return res.str();
+}
+#endif
+
+static std::string findDeviceForUuid(const std::unique_ptr<std::string>& uuid) {
+    auto path = create_data_path(uuid ? uuid->c_str() : nullptr);
+    std::ifstream in("/proc/mounts");
+    if (!in.is_open()) {
+        PLOG(ERROR) << "Failed to read mounts";
+        return "";
+    }
+    std::string source;
+    std::string target;
+    while (!in.eof()) {
+        std::getline(in, source, ' ');
+        std::getline(in, target, ' ');
+        if (target == path) {
+            return source;
+        }
+        // Skip to next line
+        std::getline(in, source);
+    }
+    PLOG(ERROR) << "Failed to resolve block device for " << path;
+    return "";
+}
+
+static void collectQuotaStats(const std::string& device, int32_t userId,
+        int32_t appId, struct stats* stats, struct stats* extStats ATTRIBUTE_UNUSED) {
+    if (device.empty()) return;
+
+    struct dqblk dq;
+
+    uid_t uid = multiuser_get_uid(userId, appId);
+    if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
+            reinterpret_cast<char*>(&dq)) != 0) {
+        if (errno != ESRCH) {
+            PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
+        }
+    } else {
+#if MEASURE_DEBUG
+        LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
+#endif
+        stats->dataSize += dq.dqb_curspace;
+    }
+
+    int cacheGid = multiuser_get_cache_gid(userId, appId);
+    if (cacheGid != -1) {
+        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), cacheGid,
+                reinterpret_cast<char*>(&dq)) != 0) {
+            if (errno != ESRCH) {
+                PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << cacheGid;
+            }
+        } else {
+#if MEASURE_DEBUG
+        LOG(DEBUG) << "quotactl() for GID " << cacheGid << " " << dq.dqb_curspace;
+#endif
+            stats->cacheSize += dq.dqb_curspace;
+        }
+    }
+
+    int sharedGid = multiuser_get_shared_app_gid(uid);
+    if (sharedGid != -1) {
+        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), sharedGid,
+                reinterpret_cast<char*>(&dq)) != 0) {
+            if (errno != ESRCH) {
+                PLOG(ERROR) << "Failed to quotactl " << device << " for GID " << sharedGid;
+            }
+        } else {
+#if MEASURE_DEBUG
+        LOG(DEBUG) << "quotactl() for GID " << sharedGid << " " << dq.dqb_curspace;
+#endif
+            stats->codeSize += dq.dqb_curspace;
+        }
+    }
+
+#if MEASURE_EXTERNAL
+    // TODO: measure using external GIDs
+#endif
+}
+
+static void collectQuotaStats(const std::unique_ptr<std::string>& uuid, int32_t userId,
+        int32_t appId, struct stats* stats, struct stats* extStats) {
+    collectQuotaStats(findDeviceForUuid(uuid), userId, appId, stats, extStats);
+}
+
+static void collectManualStats(const std::string& path, struct stats* stats) {
     DIR *d;
     int dfd;
     struct dirent *de;
@@ -774,108 +960,387 @@
 
     d = opendir(path.c_str());
     if (d == nullptr) {
-        PLOG(WARNING) << "Failed to open " << path;
+        if (errno != ENOENT) {
+            PLOG(WARNING) << "Failed to open " << path;
+        }
         return;
     }
     dfd = dirfd(d);
     while ((de = readdir(d))) {
         const char *name = de->d_name;
 
-        int64_t statsize = 0;
+        int64_t size = 0;
         if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
-            statsize = stat_size(&s);
+            size = s.st_blocks * 512;
         }
 
         if (de->d_type == DT_DIR) {
-            int subfd;
-            int64_t dirsize = 0;
-            /* always skip "." and ".." */
-            if (name[0] == '.') {
-                if (name[1] == 0) continue;
-                if ((name[1] == '.') && (name[2] == 0)) continue;
-            }
-            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
-            if (subfd >= 0) {
-                dirsize = calculate_dir_size(subfd);
-                close(subfd);
-            }
-            // TODO: check xattrs!
-            if (!strcmp(name, "cache") || !strcmp(name, "code_cache")) {
-                *datasize += statsize;
-                *cachesize += dirsize;
+            if (!strcmp(name, ".")) {
+                // Don't recurse, but still count node size
+            } else if (!strcmp(name, "..")) {
+                // Don't recurse or count node size
+                continue;
             } else {
-                *datasize += dirsize + statsize;
+                // Measure all children nodes
+                size = 0;
+                calculate_tree_size(StringPrintf("%s/%s", path.c_str(), name), &size);
             }
-        } else if (de->d_type == DT_LNK && !strcmp(name, "lib")) {
-            *codesize += statsize;
-        } else {
-            *datasize += statsize;
+
+            if (!strcmp(name, "cache") || !strcmp(name, "code_cache")) {
+                stats->cacheSize += size;
+            }
+        }
+
+        // Legacy symlink isn't owned by app
+        if (de->d_type == DT_LNK && !strcmp(name, "lib")) {
+            continue;
+        }
+
+        // Everything found inside is considered data
+        stats->dataSize += size;
+    }
+    closedir(d);
+}
+
+static void collectManualStatsForUser(const std::string& path, struct stats* stats,
+        bool exclude_apps = false) {
+    DIR *d;
+    int dfd;
+    struct dirent *de;
+    struct stat s;
+
+    d = opendir(path.c_str());
+    if (d == nullptr) {
+        if (errno != ENOENT) {
+            PLOG(WARNING) << "Failed to open " << path;
+        }
+        return;
+    }
+    dfd = dirfd(d);
+    while ((de = readdir(d))) {
+        if (de->d_type == DT_DIR) {
+            const char *name = de->d_name;
+            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) != 0) {
+                continue;
+            }
+            if (!strcmp(name, ".") || !strcmp(name, "..")) {
+                continue;
+            } else if (exclude_apps && (s.st_uid >= AID_APP_START && s.st_uid <= AID_APP_END)) {
+                continue;
+            } else {
+                collectManualStats(StringPrintf("%s/%s", path.c_str(), name), stats);
+            }
         }
     }
     closedir(d);
 }
 
 binder::Status InstalldNativeService::getAppSize(const std::unique_ptr<std::string>& uuid,
-        const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode,
-        const std::string& codePath, std::vector<int64_t>* _aidl_return) {
+        const std::vector<std::string>& packageNames, int32_t userId, int32_t flags,
+        int32_t appId, const std::vector<int64_t>& ceDataInodes,
+        const std::vector<std::string>& codePaths, std::vector<int64_t>* _aidl_return) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
-    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+    for (auto packageName : packageNames) {
+        CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+    }
+
+    // When modifying this logic, always verify using tests:
+    // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetAppSize
+
+#if MEASURE_DEBUG
+    LOG(INFO) << "Measuring user " << userId << " app " << appId;
+#endif
+
+    // Here's a summary of the common storage locations across the platform,
+    // and how they're each tagged:
+    //
+    // /data/app/com.example                           UID system
+    // /data/app/com.example/oat                       UID system
+    // /data/user/0/com.example                        UID u0_a10      GID u0_a10
+    // /data/user/0/com.example/cache                  UID u0_a10      GID u0_a10_cache
+    // /data/media/0/foo.txt                           UID u0_media_rw
+    // /data/media/0/bar.jpg                           UID u0_media_rw GID u0_media_image
+    // /data/media/0/Android/data/com.example          UID u0_media_rw GID u0_a10_ext
+    // /data/media/0/Android/data/com.example/cache    UID u0_media_rw GID u0_a10_ext_cache
+    // /data/media/obb/com.example                     UID system
+
+    struct stats stats;
+    struct stats extStats;
+    memset(&stats, 0, sizeof(stats));
+    memset(&extStats, 0, sizeof(extStats));
 
     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
-    const char* pkgname = packageName.c_str();
-    const char* code_path = codePath.c_str();
 
-    DIR *d;
-    int dfd;
-    int64_t codesize = 0;
-    int64_t datasize = 0;
-    int64_t cachesize = 0;
-    int64_t asecsize = 0;
-
-    d = opendir(code_path);
-    if (d != nullptr) {
-        dfd = dirfd(d);
-        codesize += calculate_dir_size(dfd);
-        closedir(d);
+    for (auto packageName : packageNames) {
+        auto obbCodePath = create_data_media_obb_path(uuid_, packageName.c_str());
+        calculate_tree_size(obbCodePath, &extStats.codeSize);
     }
 
-    if (flags & FLAG_STORAGE_CE) {
-        auto path = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInode);
-        add_app_data_size(path, &codesize, &datasize, &cachesize);
-    }
-    if (flags & FLAG_STORAGE_DE) {
-        auto path = create_data_user_de_package_path(uuid_, userId, pkgname);
-        add_app_data_size(path, &codesize, &datasize, &cachesize);
+    if (flags & FLAG_USE_QUOTA && appId >= AID_APP_START) {
+        for (auto codePath : codePaths) {
+            calculate_tree_size(codePath, &stats.codeSize, -1,
+                    multiuser_get_shared_gid(userId, appId));
+        }
+
+        collectQuotaStats(uuid, userId, appId, &stats, &extStats);
+
+    } else {
+        for (auto codePath : codePaths) {
+            calculate_tree_size(codePath, &stats.codeSize);
+        }
+
+        for (size_t i = 0; i < packageNames.size(); i++) {
+            const char* pkgname = packageNames[i].c_str();
+
+            auto cePath = create_data_user_ce_package_path(uuid_, userId, pkgname, ceDataInodes[i]);
+            collectManualStats(cePath, &stats);
+
+            auto dePath = create_data_user_de_package_path(uuid_, userId, pkgname);
+            collectManualStats(dePath, &stats);
+
+            auto userProfilePath = create_data_user_profile_package_path(userId, pkgname);
+            calculate_tree_size(userProfilePath, &stats.dataSize);
+
+            auto refProfilePath = create_data_ref_profile_package_path(pkgname);
+            calculate_tree_size(refProfilePath, &stats.codeSize);
+
+#if MEASURE_EXTERNAL
+            auto extPath = create_data_media_package_path(uuid_, userId, pkgname, "data");
+            collectManualStats(extPath, &extStats);
+
+            auto mediaPath = create_data_media_package_path(uuid_, userId, pkgname, "media");
+            calculate_tree_size(mediaPath, &extStats.dataSize);
+#endif
+        }
+
+        int32_t sharedGid = multiuser_get_shared_gid(userId, appId);
+        if (sharedGid != -1) {
+            calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
+                    sharedGid, -1);
+        }
+
+        calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize,
+                multiuser_get_uid(userId, appId), -1);
     }
 
-    std::vector<int64_t> res;
-    res.push_back(codesize);
-    res.push_back(datasize);
-    res.push_back(cachesize);
-    res.push_back(asecsize);
-    *_aidl_return = res;
+    std::vector<int64_t> ret;
+    ret.push_back(stats.codeSize);
+    ret.push_back(stats.dataSize);
+    ret.push_back(stats.cacheSize);
+    ret.push_back(extStats.codeSize);
+    ret.push_back(extStats.dataSize);
+    ret.push_back(extStats.cacheSize);
+#if MEASURE_DEBUG
+    LOG(DEBUG) << "Final result " << toString(ret);
+#endif
+    *_aidl_return = ret;
     return ok();
 }
 
-binder::Status InstalldNativeService::getAppDataInode(const std::unique_ptr<std::string>& uuid,
-        const std::string& packageName, int32_t userId, int32_t flags, int64_t* _aidl_return) {
+binder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::string>& uuid,
+        int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
+        std::vector<int64_t>* _aidl_return) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
-    CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+
+    // When modifying this logic, always verify using tests:
+    // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetUserSize
+
+#if MEASURE_DEBUG
+    LOG(INFO) << "Measuring user " << userId;
+#endif
+
+    struct stats stats;
+    struct stats extStats;
+    memset(&stats, 0, sizeof(stats));
+    memset(&extStats, 0, sizeof(extStats));
 
     const char* uuid_ = uuid ? uuid->c_str() : nullptr;
-    const char* pkgname = packageName.c_str();
 
-    if (flags & FLAG_STORAGE_CE) {
-        auto path = create_data_user_ce_package_path(uuid_, userId, pkgname);
-        if (get_path_inode(path, reinterpret_cast<ino_t*>(_aidl_return)) == 0) {
-            return ok();
-        } else {
-            return error("Failed to get_path_inode for " + path);
+    auto obbPath = create_data_path(uuid_) + "/media/obb";
+    calculate_tree_size(obbPath, &extStats.codeSize);
+
+    if (flags & FLAG_USE_QUOTA) {
+        calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize, -1, -1, true);
+
+        auto cePath = create_data_user_ce_path(uuid_, userId);
+        collectManualStatsForUser(cePath, &stats, true);
+
+        auto dePath = create_data_user_de_path(uuid_, userId);
+        collectManualStatsForUser(dePath, &stats, true);
+
+        auto userProfilePath = create_data_user_profile_path(userId);
+        calculate_tree_size(userProfilePath, &stats.dataSize, -1, -1, true);
+
+        auto refProfilePath = create_data_ref_profile_path();
+        calculate_tree_size(refProfilePath, &stats.codeSize, -1, -1, true);
+
+#if MEASURE_EXTERNAL
+        // TODO: measure external storage paths
+#endif
+
+        calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize,
+                -1, -1, true);
+
+        calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize,
+                -1, -1, true);
+
+        auto device = findDeviceForUuid(uuid);
+        for (auto appId : appIds) {
+            if (appId >= AID_APP_START) {
+                collectQuotaStats(device, userId, appId, &stats, &extStats);
+#if MEASURE_DEBUG
+                // Sleep to make sure we don't lose logs
+                usleep(1);
+#endif
+            }
         }
+    } else {
+        calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize);
+
+        auto cePath = create_data_user_ce_path(uuid_, userId);
+        collectManualStatsForUser(cePath, &stats);
+
+        auto dePath = create_data_user_de_path(uuid_, userId);
+        collectManualStatsForUser(dePath, &stats);
+
+        auto userProfilePath = create_data_user_profile_path(userId);
+        calculate_tree_size(userProfilePath, &stats.dataSize);
+
+        auto refProfilePath = create_data_ref_profile_path();
+        calculate_tree_size(refProfilePath, &stats.codeSize);
+
+#if MEASURE_EXTERNAL
+        // TODO: measure external storage paths
+#endif
+
+        calculate_tree_size(create_data_dalvik_cache_path(), &stats.codeSize);
+
+        calculate_tree_size(create_data_misc_foreign_dex_path(userId), &stats.dataSize);
     }
-    return exception(binder::Status::EX_UNSUPPORTED_OPERATION);
+
+    std::vector<int64_t> ret;
+    ret.push_back(stats.codeSize);
+    ret.push_back(stats.dataSize);
+    ret.push_back(stats.cacheSize);
+    ret.push_back(extStats.codeSize);
+    ret.push_back(extStats.dataSize);
+    ret.push_back(extStats.cacheSize);
+#if MEASURE_DEBUG
+    LOG(DEBUG) << "Final result " << toString(ret);
+#endif
+    *_aidl_return = ret;
+    return ok();
+}
+
+binder::Status InstalldNativeService::getExternalSize(const std::unique_ptr<std::string>& uuid,
+        int32_t userId, int32_t flags, std::vector<int64_t>* _aidl_return) {
+    ENFORCE_UID(AID_SYSTEM);
+    CHECK_ARGUMENT_UUID(uuid);
+
+    // When modifying this logic, always verify using tests:
+    // runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/pm/InstallerTest.java -m testGetExternalSize
+
+#if MEASURE_DEBUG
+    LOG(INFO) << "Measuring external " << userId;
+#endif
+
+    const char* uuid_ = uuid ? uuid->c_str() : nullptr;
+
+    int64_t totalSize = 0;
+    int64_t audioSize = 0;
+    int64_t videoSize = 0;
+    int64_t imageSize = 0;
+
+    if (flags & FLAG_USE_QUOTA) {
+        struct dqblk dq;
+
+        auto device = findDeviceForUuid(uuid);
+
+        uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
+        if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid,
+                reinterpret_cast<char*>(&dq)) != 0) {
+            if (errno != ESRCH) {
+                PLOG(ERROR) << "Failed to quotactl " << device << " for UID " << uid;
+            }
+        } else {
+#if MEASURE_DEBUG
+        LOG(DEBUG) << "quotactl() for UID " << uid << " " << dq.dqb_curspace;
+#endif
+            totalSize = dq.dqb_curspace;
+        }
+
+        gid_t audioGid = multiuser_get_uid(userId, AID_MEDIA_AUDIO);
+        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), audioGid,
+                reinterpret_cast<char*>(&dq)) == 0) {
+#if MEASURE_DEBUG
+        LOG(DEBUG) << "quotactl() for GID " << audioGid << " " << dq.dqb_curspace;
+#endif
+            audioSize = dq.dqb_curspace;
+        }
+        gid_t videoGid = multiuser_get_uid(userId, AID_MEDIA_VIDEO);
+        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), videoGid,
+                reinterpret_cast<char*>(&dq)) == 0) {
+#if MEASURE_DEBUG
+        LOG(DEBUG) << "quotactl() for GID " << videoGid << " " << dq.dqb_curspace;
+#endif
+            videoSize = dq.dqb_curspace;
+        }
+        gid_t imageGid = multiuser_get_uid(userId, AID_MEDIA_IMAGE);
+        if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), device.c_str(), imageGid,
+                reinterpret_cast<char*>(&dq)) == 0) {
+#if MEASURE_DEBUG
+        LOG(DEBUG) << "quotactl() for GID " << imageGid << " " << dq.dqb_curspace;
+#endif
+            imageSize = dq.dqb_curspace;
+        }
+    } else {
+        FTS *fts;
+        FTSENT *p;
+        auto path = create_data_media_path(uuid_, userId);
+        char *argv[] = { (char*) path.c_str(), nullptr };
+        if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) {
+            return error("Failed to fts_open " + path);
+        }
+        while ((p = fts_read(fts)) != NULL) {
+            char* ext;
+            int64_t size = (p->fts_statp->st_blocks * 512);
+            switch (p->fts_info) {
+            case FTS_F:
+                // Only categorize files not belonging to apps
+                if (p->fts_statp->st_gid < AID_APP_START) {
+                    ext = strrchr(p->fts_name, '.');
+                    if (ext != nullptr) {
+                        switch (MatchExtension(++ext)) {
+                        case AID_MEDIA_AUDIO: audioSize += size; break;
+                        case AID_MEDIA_VIDEO: videoSize += size; break;
+                        case AID_MEDIA_IMAGE: imageSize += size; break;
+                        }
+                    }
+                }
+                // Fall through to always count against total
+            case FTS_D:
+            case FTS_DEFAULT:
+            case FTS_SL:
+            case FTS_SLNONE:
+                totalSize += size;
+                break;
+            }
+        }
+        fts_close(fts);
+    }
+
+    std::vector<int64_t> ret;
+    ret.push_back(totalSize);
+    ret.push_back(audioSize);
+    ret.push_back(videoSize);
+    ret.push_back(imageSize);
+#if MEASURE_DEBUG
+    LOG(DEBUG) << "Final result " << toString(ret);
+#endif
+    *_aidl_return = ret;
+    return ok();
 }
 
 // Dumps the contents of a profile file, using pkgname's dex files for pretty
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 749a218..5397a74 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -45,7 +45,7 @@
 
     binder::Status createAppData(const std::unique_ptr<std::string>& uuid,
             const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
-            const std::string& seInfo, int32_t targetSdkVersion);
+            const std::string& seInfo, int32_t targetSdkVersion, int64_t* _aidl_return);
     binder::Status restoreconAppData(const std::unique_ptr<std::string>& uuid,
             const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
             const std::string& seInfo);
@@ -55,11 +55,16 @@
             const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode);
     binder::Status destroyAppData(const std::unique_ptr<std::string>& uuid,
             const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode);
-    binder::Status getAppDataInode(const std::unique_ptr<std::string>& uuid,
-            const std::string& packageName, int32_t userId, int32_t flags, int64_t* _aidl_return);
+
     binder::Status getAppSize(const std::unique_ptr<std::string>& uuid,
-            const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode,
-            const std::string& codePath, std::vector<int64_t>* _aidl_return);
+            const std::vector<std::string>& packageNames, int32_t userId, int32_t flags,
+            int32_t appId, const std::vector<int64_t>& ceDataInodes,
+            const std::vector<std::string>& codePaths, std::vector<int64_t>* _aidl_return);
+    binder::Status getUserSize(const std::unique_ptr<std::string>& uuid,
+            int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
+            std::vector<int64_t>* _aidl_return);
+    binder::Status getExternalSize(const std::unique_ptr<std::string>& uuid,
+            int32_t userId, int32_t flags, std::vector<int64_t>* _aidl_return);
 
     binder::Status moveCompleteApp(const std::unique_ptr<std::string>& fromUuid,
             const std::unique_ptr<std::string>& toUuid, const std::string& packageName,
diff --git a/cmds/installd/MatchExtensionGen.h b/cmds/installd/MatchExtensionGen.h
new file mode 100644
index 0000000..fded6b7
--- /dev/null
+++ b/cmds/installd/MatchExtensionGen.h
@@ -0,0 +1,628 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/******************************************************************
+ * THIS CODE WAS GENERATED BY matchgen.py, DO NOT MODIFY DIRECTLY *
+ ******************************************************************/
+
+#include <private/android_filesystem_config.h>
+
+int MatchExtension(const char* ext) {
+
+    switch (ext[0]) {
+    case '3':
+        switch (ext[1]) {
+        case 'g': case 'G':
+            switch (ext[2]) {
+            case '2':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            case 'p': case 'P':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                case 'p': case 'P':
+                    switch (ext[4]) {
+                    case '\0': return AID_MEDIA_VIDEO;
+                    case '2':
+                        switch (ext[5]) {
+                        case '\0': return AID_MEDIA_VIDEO;
+                        }
+                    }
+                }
+            }
+        }
+    case 'a': case 'A':
+        switch (ext[1]) {
+        case 'a': case 'A':
+            switch (ext[2]) {
+            case 'c': case 'C':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            }
+        case 'i': case 'I':
+            switch (ext[2]) {
+            case 'f': case 'F':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                case 'c': case 'C':
+                    switch (ext[4]) {
+                    case '\0': return AID_MEDIA_AUDIO;
+                    }
+                case 'f': case 'F':
+                    switch (ext[4]) {
+                    case '\0': return AID_MEDIA_AUDIO;
+                    }
+                }
+            }
+        case 'm': case 'M':
+            switch (ext[2]) {
+            case 'r': case 'R':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            }
+        case 'r': case 'R':
+            switch (ext[2]) {
+            case 't': case 'T':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            case 'w': case 'W':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        case 's': case 'S':
+            switch (ext[2]) {
+            case 'f': case 'F':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            case 'x': case 'X':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            }
+        case 'v': case 'V':
+            switch (ext[2]) {
+            case 'i': case 'I':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            }
+        case 'w': case 'W':
+            switch (ext[2]) {
+            case 'b': case 'B':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            }
+        }
+    case 'b': case 'B':
+        switch (ext[1]) {
+        case 'm': case 'M':
+            switch (ext[2]) {
+            case 'p': case 'P':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        }
+    case 'c': case 'C':
+        switch (ext[1]) {
+        case 'r': case 'R':
+            switch (ext[2]) {
+            case '2':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        }
+    case 'd': case 'D':
+        switch (ext[1]) {
+        case 'i': case 'I':
+            switch (ext[2]) {
+            case 'f': case 'F':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            }
+        case 'l': case 'L':
+            switch (ext[2]) {
+            case '\0': return AID_MEDIA_VIDEO;
+            }
+        case 'n': case 'N':
+            switch (ext[2]) {
+            case 'g': case 'G':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        case 'v': case 'V':
+            switch (ext[2]) {
+            case '\0': return AID_MEDIA_VIDEO;
+            }
+        }
+    case 'f': case 'F':
+        switch (ext[1]) {
+        case 'l': case 'L':
+            switch (ext[2]) {
+            case 'a': case 'A':
+                switch (ext[3]) {
+                case 'c': case 'C':
+                    switch (ext[4]) {
+                    case '\0': return AID_MEDIA_AUDIO;
+                    }
+                }
+            case 'i': case 'I':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            }
+        }
+    case 'g': case 'G':
+        switch (ext[1]) {
+        case 'i': case 'I':
+            switch (ext[2]) {
+            case 'f': case 'F':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        case 's': case 'S':
+            switch (ext[2]) {
+            case 'm': case 'M':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            }
+        }
+    case 'j': case 'J':
+        switch (ext[1]) {
+        case 'n': case 'N':
+            switch (ext[2]) {
+            case 'g': case 'G':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        case 'p': case 'P':
+            switch (ext[2]) {
+            case 'e': case 'E':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                case 'g': case 'G':
+                    switch (ext[4]) {
+                    case '\0': return AID_MEDIA_IMAGE;
+                    }
+                }
+            case 'g': case 'G':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        }
+    case 'l': case 'L':
+        switch (ext[1]) {
+        case 's': case 'S':
+            switch (ext[2]) {
+            case 'f': case 'F':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            case 'x': case 'X':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            }
+        }
+    case 'm': case 'M':
+        switch (ext[1]) {
+        case '3':
+            switch (ext[2]) {
+            case 'u': case 'U':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            }
+        case '4':
+            switch (ext[2]) {
+            case 'a': case 'A':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            case 'v': case 'V':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            }
+        case 'k': case 'K':
+            switch (ext[2]) {
+            case 'a': case 'A':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            case 'v': case 'V':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            }
+        case 'n': case 'N':
+            switch (ext[2]) {
+            case 'g': case 'G':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            }
+        case 'o': case 'O':
+            switch (ext[2]) {
+            case 'v': case 'V':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                case 'i': case 'I':
+                    switch (ext[4]) {
+                    case 'e': case 'E':
+                        switch (ext[5]) {
+                        case '\0': return AID_MEDIA_VIDEO;
+                        }
+                    }
+                }
+            }
+        case 'p': case 'P':
+            switch (ext[2]) {
+            case '2':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            case '3':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            case '4':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            case 'e': case 'E':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                case 'g': case 'G':
+                    switch (ext[4]) {
+                    case '\0': return AID_MEDIA_VIDEO;
+                    case 'a': case 'A':
+                        switch (ext[5]) {
+                        case '\0': return AID_MEDIA_AUDIO;
+                        }
+                    }
+                }
+            case 'g': case 'G':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                case 'a': case 'A':
+                    switch (ext[4]) {
+                    case '\0': return AID_MEDIA_AUDIO;
+                    }
+                }
+            }
+        case 'x': case 'X':
+            switch (ext[2]) {
+            case 'u': case 'U':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            }
+        }
+    case 'n': case 'N':
+        switch (ext[1]) {
+        case 'e': case 'E':
+            switch (ext[2]) {
+            case 'f': case 'F':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        case 'r': case 'R':
+            switch (ext[2]) {
+            case 'w': case 'W':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        }
+    case 'o': case 'O':
+        switch (ext[1]) {
+        case 'g': case 'G':
+            switch (ext[2]) {
+            case 'a': case 'A':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            case 'g': case 'G':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            }
+        case 'r': case 'R':
+            switch (ext[2]) {
+            case 'f': case 'F':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        }
+    case 'p': case 'P':
+        switch (ext[1]) {
+        case 'b': case 'B':
+            switch (ext[2]) {
+            case 'm': case 'M':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        case 'c': case 'C':
+            switch (ext[2]) {
+            case 'x': case 'X':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        case 'e': case 'E':
+            switch (ext[2]) {
+            case 'f': case 'F':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        case 'g': case 'G':
+            switch (ext[2]) {
+            case 'm': case 'M':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        case 'l': case 'L':
+            switch (ext[2]) {
+            case 's': case 'S':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            }
+        case 'n': case 'N':
+            switch (ext[2]) {
+            case 'g': case 'G':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            case 'm': case 'M':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        case 'p': case 'P':
+            switch (ext[2]) {
+            case 'm': case 'M':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        case 's': case 'S':
+            switch (ext[2]) {
+            case 'd': case 'D':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        }
+    case 'q': case 'Q':
+        switch (ext[1]) {
+        case 't': case 'T':
+            switch (ext[2]) {
+            case '\0': return AID_MEDIA_VIDEO;
+            }
+        }
+    case 'r': case 'R':
+        switch (ext[1]) {
+        case 'a': case 'A':
+            switch (ext[2]) {
+            case '\0': return AID_MEDIA_AUDIO;
+            case 'm': case 'M':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            case 's': case 'S':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        case 'g': case 'G':
+            switch (ext[2]) {
+            case 'b': case 'B':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        case 'm': case 'M':
+            switch (ext[2]) {
+            case '\0': return AID_MEDIA_AUDIO;
+            }
+        case 'w': case 'W':
+            switch (ext[2]) {
+            case '2':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        }
+    case 's': case 'S':
+        switch (ext[1]) {
+        case 'd': case 'D':
+            switch (ext[2]) {
+            case '2':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            }
+        case 'n': case 'N':
+            switch (ext[2]) {
+            case 'd': case 'D':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            }
+        case 'r': case 'R':
+            switch (ext[2]) {
+            case 'w': case 'W':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        case 'v': case 'V':
+            switch (ext[2]) {
+            case 'g': case 'G':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                case 'z': case 'Z':
+                    switch (ext[4]) {
+                    case '\0': return AID_MEDIA_IMAGE;
+                    }
+                }
+            }
+        }
+    case 't': case 'T':
+        switch (ext[1]) {
+        case 'i': case 'I':
+            switch (ext[2]) {
+            case 'f': case 'F':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                case 'f': case 'F':
+                    switch (ext[4]) {
+                    case '\0': return AID_MEDIA_IMAGE;
+                    }
+                }
+            }
+        case 's': case 'S':
+            switch (ext[2]) {
+            case '\0': return AID_MEDIA_VIDEO;
+            }
+        }
+    case 'v': case 'V':
+        switch (ext[1]) {
+        case 'o': case 'O':
+            switch (ext[2]) {
+            case 'b': case 'B':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            }
+        }
+    case 'w': case 'W':
+        switch (ext[1]) {
+        case 'a': case 'A':
+            switch (ext[2]) {
+            case 'v': case 'V':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            case 'x': case 'X':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            }
+        case 'b': case 'B':
+            switch (ext[2]) {
+            case 'm': case 'M':
+                switch (ext[3]) {
+                case 'p': case 'P':
+                    switch (ext[4]) {
+                    case '\0': return AID_MEDIA_IMAGE;
+                    }
+                }
+            }
+        case 'e': case 'E':
+            switch (ext[2]) {
+            case 'b': case 'B':
+                switch (ext[3]) {
+                case 'm': case 'M':
+                    switch (ext[4]) {
+                    case '\0': return AID_MEDIA_VIDEO;
+                    }
+                case 'p': case 'P':
+                    switch (ext[4]) {
+                    case '\0': return AID_MEDIA_IMAGE;
+                    }
+                }
+            }
+        case 'm': case 'M':
+            switch (ext[2]) {
+            case '\0': return AID_MEDIA_VIDEO;
+            case 'a': case 'A':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_AUDIO;
+                }
+            case 'v': case 'V':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            case 'x': case 'X':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            }
+        case 'r': case 'R':
+            switch (ext[2]) {
+            case 'f': case 'F':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            }
+        case 'v': case 'V':
+            switch (ext[2]) {
+            case 'x': case 'X':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_VIDEO;
+                }
+            }
+        }
+    case 'x': case 'X':
+        switch (ext[1]) {
+        case 'b': case 'B':
+            switch (ext[2]) {
+            case 'm': case 'M':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        case 'p': case 'P':
+            switch (ext[2]) {
+            case 'm': case 'M':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        case 'w': case 'W':
+            switch (ext[2]) {
+            case 'd': case 'D':
+                switch (ext[3]) {
+                case '\0': return AID_MEDIA_IMAGE;
+                }
+            }
+        }
+    }
+
+    return 0;
+}
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index bcfaca8..6e4d7fa 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -21,7 +21,7 @@
     void createUserData(@nullable @utf8InCpp String uuid, int userId, int userSerial, int flags);
     void destroyUserData(@nullable @utf8InCpp String uuid, int userId, int flags);
 
-    void createAppData(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName,
+    long createAppData(@nullable @utf8InCpp String uuid, in @utf8InCpp String packageName,
             int userId, int flags, int appId, in @utf8InCpp String seInfo, int targetSdkVersion);
     void restoreconAppData(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
             int userId, int flags, int appId, @utf8InCpp String seInfo);
@@ -31,10 +31,12 @@
             int userId, int flags, long ceDataInode);
     void destroyAppData(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
             int userId, int flags, long ceDataInode);
-    long getAppDataInode(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
-            int userId, int flags);
-    long[] getAppSize(@nullable @utf8InCpp String uuid, @utf8InCpp String packageName,
-            int userId, int flags, long ceDataInode, @utf8InCpp String codePath);
+
+    long[] getAppSize(@nullable @utf8InCpp String uuid, in @utf8InCpp String[] packageNames,
+            int userId, int flags, int appId, in long[] ceDataInodes,
+            in @utf8InCpp String[] codePaths);
+    long[] getUserSize(@nullable @utf8InCpp String uuid, int userId, int flags, in int[] appIds);
+    long[] getExternalSize(@nullable @utf8InCpp String uuid, int userId, int flags);
 
     void moveCompleteApp(@nullable @utf8InCpp String fromUuid, @nullable @utf8InCpp String toUuid,
             @utf8InCpp String packageName, @utf8InCpp String dataAppName, int appId,
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 37f3290..5025fde 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "installed"
 
 #include <fcntl.h>
 #include <stdlib.h>
@@ -26,11 +27,11 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include <android/log.h>               // TODO: Move everything to base/logging.
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
-#include <cutils/log.h>               // TODO: Move everything to base/logging.
 #include <cutils/properties.h>
 #include <cutils/sched_policy.h>
 #include <private/android_filesystem_config.h>
@@ -1149,7 +1150,13 @@
             ALOGE("installd cannot compute input vdex location for '%s'\n", path);
             return -1;
         }
-        in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
+        if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE) {
+            // When we dex2oat because iof boot image change, we are going to update
+            // in-place the vdex file.
+            in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDWR, 0));
+        } else {
+            in_vdex_fd.reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
+        }
     }
 
     // Infer the name of the output VDEX and create it.
@@ -1157,14 +1164,26 @@
     if (out_vdex_path_str.empty()) {
         return -1;
     }
-    Dex2oatFileWrapper<std::function<void ()>> out_vdex_fd(
-            open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
-            [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
-    if (out_vdex_fd.get() < 0) {
-        ALOGE("installd cannot open '%s' for output during dexopt\n", out_vdex_path_str.c_str());
-        return -1;
+    Dex2oatFileWrapper<std::function<void ()>> out_vdex_wrapper_fd;
+    int out_vdex_fd = -1;
+
+    // If we are compiling because the boot image is out of date, we do not
+    // need to recreate a vdex, and can use the same existing one.
+    if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE &&
+            in_vdex_fd != -1 &&
+            in_vdex_path_str == out_vdex_path_str) {
+        out_vdex_fd = in_vdex_fd;
+    } else {
+        out_vdex_wrapper_fd.reset(
+              open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
+              [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
+        out_vdex_fd = out_vdex_wrapper_fd.get();
+        if (out_vdex_fd < 0) {
+            ALOGE("installd cannot open '%s' for output during dexopt\n", out_vdex_path_str.c_str());
+            return -1;
+        }
     }
-    if (!set_permissions_and_ownership(out_vdex_fd.get(), is_public,
+    if (!set_permissions_and_ownership(out_vdex_fd, is_public,
                 uid, out_vdex_path_str.c_str())) {
         return -1;
     }
@@ -1247,7 +1266,7 @@
             run_patchoat(input_fd.get(),
                          in_vdex_fd.get(),
                          out_oat_fd.get(),
-                         out_vdex_fd.get(),
+                         out_vdex_fd,
                          input_file,
                          in_vdex_path_str.c_str(),
                          out_oat_path,
@@ -1260,7 +1279,7 @@
             run_dex2oat(input_fd.get(),
                         out_oat_fd.get(),
                         in_vdex_fd.get(),
-                        out_vdex_fd.get(),
+                        out_vdex_fd,
                         image_fd.get(),
                         input_file_name,
                         out_oat_path,
@@ -1291,7 +1310,7 @@
 
     // We've been successful, don't delete output.
     out_oat_fd.SetCleanup(false);
-    out_vdex_fd.SetCleanup(false);
+    out_vdex_wrapper_fd.SetCleanup(false);
     image_fd.SetCleanup(false);
     reference_profile_fd.SetCleanup(false);
 
diff --git a/cmds/installd/globals.cpp b/cmds/installd/globals.cpp
index 93e1ce5..c0ea79c 100644
--- a/cmds/installd/globals.cpp
+++ b/cmds/installd/globals.cpp
@@ -14,19 +14,17 @@
 ** limitations under the License.
 */
 
+#define LOG_TAG "installd"
+
 #include <stdlib.h>
 #include <string.h>
 
-#include <cutils/log.h>               // TODO: Move everything to base::logging.
+#include <android/log.h>              // TODO: Move everything to base::logging.
 
 #include <globals.h>
 #include <installd_constants.h>
 #include <utils.h>
 
-#ifndef LOG_TAG
-#define LOG_TAG "installd"
-#endif
-
 namespace android {
 namespace installd {
 
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index 6c49aa3..35936a2 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -13,6 +13,7 @@
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
+#define LOG_TAG "installd"
 
 #include <fcntl.h>
 #include <selinux/android.h>
@@ -24,8 +25,8 @@
 
 #include <android-base/logging.h>
 #include <cutils/fs.h>
-#include <cutils/log.h>               // TODO: Move everything to base::logging.
 #include <cutils/properties.h>
+#include <log/log.h>              // TODO: Move everything to base::logging.
 #include <private/android_filesystem_config.h>
 
 #include "InstalldNativeService.h"
@@ -34,10 +35,6 @@
 #include "installd_deps.h"  // Need to fill in requirements of commands.
 #include "utils.h"
 
-#ifndef LOG_TAG
-#define LOG_TAG "installd"
-#endif
-
 namespace android {
 namespace installd {
 
@@ -63,12 +60,12 @@
 
     file_name_start = strrchr(apk_path, '/');
     if (file_name_start == NULL) {
-        ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
+        SLOGE("apk_path '%s' has no '/'s in it\n", apk_path);
         return false;
     }
     file_name_end = strrchr(apk_path, '.');
     if (file_name_end < file_name_start) {
-        ALOGE("apk_path '%s' has no extension\n", apk_path);
+        SLOGE("apk_path '%s' has no extension\n", apk_path);
         return false;
     }
 
@@ -94,14 +91,14 @@
                               const char *instruction_set) {
     if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set)
             + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) {
-        ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path);
+        SLOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path);
         return false;
     }
 
     strcpy(path, apk_path);
     char *end = strrchr(path, '/');
     if (end == NULL) {
-        ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
+        SLOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
         return false;
     }
     const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/');
@@ -111,7 +108,7 @@
     strcat(path, apk_end);         // path = /system/framework/oat/<isa>/whatever.jar\0
     end = strrchr(path, '.');
     if (end == NULL) {
-        ALOGE("apk_path '%s' has no extension.\n", apk_path);
+        SLOGE("apk_path '%s' has no extension.\n", apk_path);
         return false;
     }
     strcpy(end + 1, "odex");
@@ -170,12 +167,12 @@
 static bool initialize_globals() {
     const char* data_path = getenv("ANDROID_DATA");
     if (data_path == nullptr) {
-        ALOGE("Could not find ANDROID_DATA");
+        SLOGE("Could not find ANDROID_DATA");
         return false;
     }
     const char* root_path = getenv("ANDROID_ROOT");
     if (root_path == nullptr) {
-        ALOGE("Could not find ANDROID_ROOT");
+        SLOGE("Could not find ANDROID_ROOT");
         return false;
     }
 
@@ -201,12 +198,12 @@
     }
 
     if (ensure_config_user_dirs(0) == -1) {
-        ALOGE("Failed to setup misc for user 0");
+        SLOGE("Failed to setup misc for user 0");
         goto fail;
     }
 
     if (version == 2) {
-        ALOGD("Upgrading to /data/misc/user directories");
+        SLOGD("Upgrading to /data/misc/user directories");
 
         char misc_dir[PATH_MAX];
         snprintf(misc_dir, PATH_MAX, "%smisc", android_data_dir.path);
@@ -247,12 +244,12 @@
                 gid_t gid = uid;
                 if (access(keychain_added_dir, F_OK) == 0) {
                     if (copy_dir_files(keychain_added_dir, misc_added_dir, uid, gid) != 0) {
-                        ALOGE("Some files failed to copy");
+                        SLOGE("Some files failed to copy");
                     }
                 }
                 if (access(keychain_removed_dir, F_OK) == 0) {
                     if (copy_dir_files(keychain_removed_dir, misc_removed_dir, uid, gid) != 0) {
-                        ALOGE("Some files failed to copy");
+                        SLOGE("Some files failed to copy");
                     }
                 }
             }
@@ -272,7 +269,7 @@
     // Persist layout version if changed
     if (version != oldVersion) {
         if (fs_write_atomic_int(version_path, version) == -1) {
-            ALOGE("Failed to save version to %s: %s", version_path, strerror(errno));
+            SLOGE("Failed to save version to %s: %s", version_path, strerror(errno));
             goto fail;
         }
     }
@@ -312,29 +309,29 @@
     setenv("ANDROID_LOG_TAGS", "*:v", 1);
     android::base::InitLogging(argv);
 
-    LOG(INFO) << "installd firing up";
+    SLOGI("installd firing up");
 
     union selinux_callback cb;
     cb.func_log = log_callback;
     selinux_set_callback(SELINUX_CB_LOG, cb);
 
     if (!initialize_globals()) {
-        ALOGE("Could not initialize globals; exiting.\n");
+        SLOGE("Could not initialize globals; exiting.\n");
         exit(1);
     }
 
     if (initialize_directories() < 0) {
-        ALOGE("Could not create directories; exiting.\n");
+        SLOGE("Could not create directories; exiting.\n");
         exit(1);
     }
 
     if (selinux_enabled && selinux_status_open(true) < 0) {
-        ALOGE("Could not open selinux status; exiting.\n");
+        SLOGE("Could not open selinux status; exiting.\n");
         exit(1);
     }
 
     if ((ret = InstalldNativeService::start()) != android::OK) {
-        ALOGE("Unable to start InstalldNativeService: %d", ret);
+        SLOGE("Unable to start InstalldNativeService: %d", ret);
         exit(1);
     }
 
diff --git a/cmds/installd/matchgen.py b/cmds/installd/matchgen.py
new file mode 100644
index 0000000..b37352b
--- /dev/null
+++ b/cmds/installd/matchgen.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the 'License');
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an 'AS IS' BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import collections
+
+TYPES = {
+    "AID_MEDIA_AUDIO": ["aac","aac","amr","awb","snd","flac","flac","mp3","mpga","mpega","mp2","m4a","aif","aiff","aifc","gsm","mka","m3u","wma","wax","ra","rm","ram","ra","pls","sd2","wav","ogg","oga"],
+    "AID_MEDIA_VIDEO": ["3gpp","3gp","3gpp2","3g2","avi","dl","dif","dv","fli","m4v","ts","mpeg","mpg","mpe","mp4","vob","qt","mov","mxu","webm","lsf","lsx","mkv","mng","asf","asx","wm","wmv","wmx","wvx","movie","wrf"],
+    "AID_MEDIA_IMAGE": ["bmp","gif","jpg","jpeg","jpe","pcx","png","svg","svgz","tiff","tif","wbmp","webp","dng","cr2","ras","art","jng","nef","nrw","orf","rw2","pef","psd","pnm","pbm","pgm","ppm","srw","arw","rgb","xbm","xpm","xwd"]
+}
+
+print """/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/******************************************************************
+ * THIS CODE WAS GENERATED BY matchgen.py, DO NOT MODIFY DIRECTLY *
+ ******************************************************************/
+
+#include <private/android_filesystem_config.h>
+
+int MatchExtension(const char* ext) {
+"""
+
+trie = collections.defaultdict(lambda: collections.defaultdict(lambda: collections.defaultdict(lambda: collections.defaultdict(lambda: collections.defaultdict(lambda: collections.defaultdict(lambda: ""))))))
+
+for t in TYPES:
+    for v in TYPES[t]:
+        v = v.lower()
+        target = trie
+        for c in v:
+            target = target[c]
+        target["\0"] = t
+
+def dump(target, index):
+    prefix = "    " * (index + 1)
+    print "%sswitch (ext[%d]) {" % (prefix, index)
+    for k in sorted(target.keys()):
+        if k == "\0":
+            print "%scase '\\0': return %s;" % (prefix, target[k])
+        else:
+            upper = k.upper()
+            if k != upper:
+                print "%scase '%s': case '%s':" % (prefix, k, upper)
+            else:
+                print "%scase '%s':" % (prefix, k)
+            dump(target[k], index + 1)
+    print "%s}" % (prefix)
+
+dump(trie, 0)
+
+print """
+    return 0;
+}
+"""
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index d53018f..7aba5d0 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -27,12 +27,12 @@
 #include <sys/stat.h>
 #include <sys/wait.h>
 
+#include <android/log.h>
 #include <android-base/logging.h>
 #include <android-base/macros.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <cutils/fs.h>
-#include <cutils/log.h>
 #include <cutils/properties.h>
 #include <private/android_filesystem_config.h>
 
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 4bd98e4..9849a0f 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -18,6 +18,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <fts.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
@@ -29,10 +30,10 @@
 #include <sys/statfs.h>
 #endif
 
+#include <android/log.h>
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 #include <cutils/fs.h>
-#include <cutils/log.h>
 #include <private/android_filesystem_config.h>
 
 #include "globals.h"  // extern variables.
@@ -198,17 +199,31 @@
     return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid);
 }
 
+std::string create_data_media_obb_path(const char* volume_uuid, const char* package_name) {
+    return StringPrintf("%s/media/obb/%s", create_data_path(volume_uuid).c_str(), package_name);
+}
+
+std::string create_data_media_package_path(const char* volume_uuid, userid_t userid,
+        const char* data_type, const char* package_name) {
+    return StringPrintf("%s/Android/%s/%s", create_data_media_path(volume_uuid, userid).c_str(),
+            data_type, package_name);
+}
+
 std::string create_data_misc_legacy_path(userid_t userid) {
     return StringPrintf("%s/misc/user/%u", create_data_path(nullptr).c_str(), userid);
 }
 
-std::string create_data_user_profiles_path(userid_t userid) {
+std::string create_data_user_profile_path(userid_t userid) {
     return StringPrintf("%s/cur/%u", android_profiles_dir.path, userid);
 }
 
 std::string create_data_user_profile_package_path(userid_t user, const char* package_name) {
     check_package_name(package_name);
-    return StringPrintf("%s/%s",create_data_user_profiles_path(user).c_str(), package_name);
+    return StringPrintf("%s/%s",create_data_user_profile_path(user).c_str(), package_name);
+}
+
+std::string create_data_ref_profile_path() {
+    return StringPrintf("%s/ref", android_profiles_dir.path);
 }
 
 std::string create_data_ref_profile_package_path(const char* package_name) {
@@ -216,6 +231,14 @@
     return StringPrintf("%s/ref/%s", android_profiles_dir.path, package_name);
 }
 
+std::string create_data_dalvik_cache_path() {
+    return "/data/dalvik-cache";
+}
+
+std::string create_data_misc_foreign_dex_path(userid_t userid) {
+    return StringPrintf("/data/misc/profiles/cur/%d/foreign-dex", userid);
+}
+
 // Keep profile paths in sync with ActivityThread.
 constexpr const char* PRIMARY_PROFILE_NAME = "primary.prof";
 
@@ -255,6 +278,59 @@
     return users;
 }
 
+int calculate_tree_size(const std::string& path, int64_t* size,
+        int32_t include_gid, int32_t exclude_gid, bool exclude_apps) {
+    FTS *fts;
+    FTSENT *p;
+    int64_t matchedSize = 0;
+    char *argv[] = { (char*) path.c_str(), nullptr };
+    if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_XDEV, NULL))) {
+        if (errno != ENOENT) {
+            PLOG(ERROR) << "Failed to fts_open " << path;
+        }
+        return -1;
+    }
+    while ((p = fts_read(fts)) != NULL) {
+        switch (p->fts_info) {
+        case FTS_D:
+        case FTS_DEFAULT:
+        case FTS_F:
+        case FTS_SL:
+        case FTS_SLNONE:
+            int32_t uid = p->fts_statp->st_uid;
+            int32_t gid = p->fts_statp->st_gid;
+            int32_t user_uid = multiuser_get_app_id(uid);
+            int32_t user_gid = multiuser_get_app_id(gid);
+            if (exclude_apps && ((user_uid >= AID_APP_START && user_uid <= AID_APP_END)
+                    || (user_gid >= AID_CACHE_GID_START && user_gid <= AID_CACHE_GID_END)
+                    || (user_gid >= AID_SHARED_GID_START && user_gid <= AID_SHARED_GID_END))) {
+                // Don't traverse inside or measure
+                fts_set(fts, p, FTS_SKIP);
+                break;
+            }
+            if (include_gid != -1 && gid != include_gid) {
+                break;
+            }
+            if (exclude_gid != -1 && gid == exclude_gid) {
+                break;
+            }
+            matchedSize += (p->fts_statp->st_blocks * 512);
+            break;
+        }
+    }
+    fts_close(fts);
+#if MEASURE_DEBUG
+    if ((include_gid == -1) && (exclude_gid == -1)) {
+        LOG(DEBUG) << "Measured " << path << " size " << matchedSize;
+    } else {
+        LOG(DEBUG) << "Measured " << path << " size " << matchedSize << "; include " << include_gid
+                << " exclude " << exclude_gid;
+    }
+#endif
+    *size += matchedSize;
+    return 0;
+}
+
 int create_move_path(char path[PKG_PATH_MAX],
     const char* pkgname,
     const char* leaf,
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 4c299fd..f2f0cbb 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -30,6 +30,9 @@
 
 #include <installd_constants.h>
 
+#define MEASURE_DEBUG 0
+#define MEASURE_EXTERNAL 0
+
 namespace android {
 namespace installd {
 
@@ -86,17 +89,28 @@
         userid_t user, const char* package_name);
 
 std::string create_data_media_path(const char* volume_uuid, userid_t userid);
+std::string create_data_media_obb_path(const char* volume_uuid, const char* package_name);
+std::string create_data_media_package_path(const char* volume_uuid, userid_t userid,
+        const char* data_type, const char* package_name);
 
 std::string create_data_misc_legacy_path(userid_t userid);
 
-std::string create_data_user_profiles_path(userid_t userid);
+std::string create_data_user_profile_path(userid_t userid);
 std::string create_data_user_profile_package_path(userid_t user, const char* package_name);
+
+std::string create_data_ref_profile_path();
 std::string create_data_ref_profile_package_path(const char* package_name);
 
+std::string create_data_dalvik_cache_path();
+std::string create_data_misc_foreign_dex_path(userid_t userid);
+
 std::string create_primary_profile(const std::string& profile_dir);
 
 std::vector<userid_t> get_known_users(const char* volume_uuid);
 
+int calculate_tree_size(const std::string& path, int64_t* size,
+        int32_t include_gid = -1, int32_t exclude_gid = -1, bool exclude_apps = false);
+
 int create_user_config_path(char path[PKG_PATH_MAX], userid_t userid);
 
 int create_move_path(char path[PKG_PATH_MAX],
diff --git a/cmds/ip-up-vpn/ip-up-vpn.c b/cmds/ip-up-vpn/ip-up-vpn.c
index 75b907c..5c566fc 100644
--- a/cmds/ip-up-vpn/ip-up-vpn.c
+++ b/cmds/ip-up-vpn/ip-up-vpn.c
@@ -14,22 +14,22 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "ip-up-vpn"
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <linux/if.h>
+#include <linux/route.h>
+#include <netinet/in.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
-
-#include <arpa/inet.h>
-#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <linux/if.h>
-#include <linux/route.h>
 
-#define LOG_TAG "ip-up-vpn"
-#include <cutils/log.h>
+#include <android/log.h>
 
 #define DIR "/data/misc/vpn/"
 
diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c
index 27c461a..cb557aa 100644
--- a/cmds/servicemanager/binder.c
+++ b/cmds/servicemanager/binder.c
@@ -1,14 +1,18 @@
 /* Copyright 2008 The Android Open Source Project
  */
 
+#define LOG_TAG "Binder"
+
+#include <errno.h>
+#include <fcntl.h>
 #include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
 #include <sys/mman.h>
+#include <unistd.h>
+
+#include <android/log.h>
 
 #include "binder.h"
 
@@ -16,9 +20,6 @@
 
 #define TRACE 0
 
-#define LOG_TAG "Binder"
-#include <cutils/log.h>
-
 void bio_init_from_txn(struct binder_io *io, struct binder_transaction_data *txn);
 
 #if TRACE
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index ea41558..8f4e01b 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -22,7 +22,7 @@
 #define ALOGE(x...) fprintf(stderr, "svcmgr: " x)
 #else
 #define LOG_TAG "ServiceManager"
-#include <cutils/log.h>
+#include <android/log.h>
 #endif
 
 struct audit_data {
diff --git a/include/android/native_window.h b/include/android/native_window.h
index b60b9f1..021dc42 100644
--- a/include/android/native_window.h
+++ b/include/android/native_window.h
@@ -38,12 +38,16 @@
  * Pixel formats that a window can use.
  */
 enum {
+    // NOTE: these values must match the values from graphics/common/x.x/types.hal
+
     /** Red: 8 bits, Green: 8 bits, Blue: 8 bits, Alpha: 8 bits. **/
     WINDOW_FORMAT_RGBA_8888          = 1,
     /** Red: 8 bits, Green: 8 bits, Blue: 8 bits, Unused: 8 bits. **/
     WINDOW_FORMAT_RGBX_8888          = 2,
     /** Red: 5 bits, Green: 6 bits, Blue: 5 bits. **/
     WINDOW_FORMAT_RGB_565            = 4,
+    /** Red: 16 bits, Green: 16 bits, Blue: 16 bits, Alpha: 16 bits. **/
+    WINDOW_FORMAT_RGBA_FP16          = 0x16,
 };
 
 struct ANativeWindow;
diff --git a/include/android/sensor.h b/include/android/sensor.h
index b6a42ae..4a00818 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -397,6 +397,7 @@
 /**
  * Enable the selected sensor with a specified sampling period and max batch report latency.
  * Returns a negative error code on failure.
+ * Note: To disable the selected sensor, use ASensorEventQueue_disableSensor() same as before.
  */
 int ASensorEventQueue_registerSensor(ASensorEventQueue* queue, ASensor const* sensor,
         int32_t samplingPeriodUs, int maxBatchReportLatencyUs);
diff --git a/include/audiomanager/AudioManager.h b/include/audiomanager/AudioManager.h
new file mode 100644
index 0000000..d561594
--- /dev/null
+++ b/include/audiomanager/AudioManager.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIOMANAGER_H
+#define ANDROID_AUDIOMANAGER_H
+
+namespace android {
+
+// must be kept in sync with definitions in AudioPlaybackConfiguration.java
+
+#define PLAYER_PIID_INVALID -1
+
+enum {
+    PLAYER_TYPE_SLES_AUDIOPLAYER_BUFFERQUEUE = 11,
+    PLAYER_TYPE_SLES_AUDIOPLAYER_URI_FD = 12,
+};
+
+enum {
+    PLAYER_STATE_UNKNOWN  = -1,
+    PLAYER_STATE_RELEASED = 0,
+    PLAYER_STATE_IDLE     = 1,
+    PLAYER_STATE_STARTED  = 2,
+    PLAYER_STATE_PAUSED   = 3,
+    PLAYER_STATE_STOPPED  = 4,
+};
+
+}; // namespace android
+
+#endif // ANDROID_AUDIOMANAGER_H
diff --git a/include/audiomanager/IAudioManager.h b/include/audiomanager/IAudioManager.h
new file mode 100644
index 0000000..f5ea259
--- /dev/null
+++ b/include/audiomanager/IAudioManager.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IAUDIOMANAGER_H
+#define ANDROID_IAUDIOMANAGER_H
+
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+#include <hardware/power.h>
+#include <system/audio.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class IAudioManager : public IInterface
+{
+public:
+    // These transaction IDs must be kept in sync with the method order from
+    // IAudioService.aidl.
+    enum {
+        // transaction IDs for the unsupported methods are commented out
+        /*
+        ADJUSTSUGGESTEDSTREAMVOLUME           = IBinder::FIRST_CALL_TRANSACTION,
+        ADJUSTSTREAMVOLUME                    = IBinder::FIRST_CALL_TRANSACTION + 1,
+        SETSTREAMVOLUME                       = IBinder::FIRST_CALL_TRANSACTION + 2,
+        ISSTREAMMUTE                          = IBinder::FIRST_CALL_TRANSACTION + 3,
+        FORCEREMOTESUBMIXFULLVOLUME           = IBinder::FIRST_CALL_TRANSACTION + 4,
+        ISMASTERMUTE                          = IBinder::FIRST_CALL_TRANSACTION + 5,
+        SETMASTERMUTE                         = IBinder::FIRST_CALL_TRANSACTION + 6,
+        GETSTREAMVOLUME                       = IBinder::FIRST_CALL_TRANSACTION + 7,
+        GETSTREAMMINVOLUME                    = IBinder::FIRST_CALL_TRANSACTION + 8,
+        GETSTREAMMAXVOLUME                    = IBinder::FIRST_CALL_TRANSACTION + 9,
+        GETLASTAUDIBLESTREAMVOLUME            = IBinder::FIRST_CALL_TRANSACTION + 10,
+        SETMICROPHONEMUTE                     = IBinder::FIRST_CALL_TRANSACTION + 11,
+        SETRINGERMODEEXTERNAL                 = IBinder::FIRST_CALL_TRANSACTION + 12,
+        SETRINGERMODEINTERNAL                 = IBinder::FIRST_CALL_TRANSACTION + 13,
+        GETRINGERMODEEXTERNAL                 = IBinder::FIRST_CALL_TRANSACTION + 14,
+        GETRINGERMODEINTERNAL                 = IBinder::FIRST_CALL_TRANSACTION + 15,
+        ISVALIDRINGERMODE                     = IBinder::FIRST_CALL_TRANSACTION + 16,
+        SETVIBRATESETTING                     = IBinder::FIRST_CALL_TRANSACTION + 17,
+        GETVIBRATESETTING                     = IBinder::FIRST_CALL_TRANSACTION + 18,
+        SHOULDVIBRATE                         = IBinder::FIRST_CALL_TRANSACTION + 19,
+        SETMODE                               = IBinder::FIRST_CALL_TRANSACTION + 20,
+        GETMODE                               = IBinder::FIRST_CALL_TRANSACTION + 21,
+        PLAYSOUNDEFFECT                       = IBinder::FIRST_CALL_TRANSACTION + 22,
+        PLAYSOUNDEFFECTVOLUME                 = IBinder::FIRST_CALL_TRANSACTION + 23,
+        LOADSOUNDEFFECTS                      = IBinder::FIRST_CALL_TRANSACTION + 24,
+        UNLOADSOUNDEFFECTS                    = IBinder::FIRST_CALL_TRANSACTION + 25,
+        RELOADAUDIOSETTINGS                   = IBinder::FIRST_CALL_TRANSACTION + 26,
+        AVRCPSUPPORTSABSOLUTEVOLUME           = IBinder::FIRST_CALL_TRANSACTION + 27,
+        SETSPEAKERPHONEON                     = IBinder::FIRST_CALL_TRANSACTION + 28,
+        ISSPEAKERPHONEON                      = IBinder::FIRST_CALL_TRANSACTION + 29,
+        SETBLUETOOTHSCOON                     = IBinder::FIRST_CALL_TRANSACTION + 30,
+        ISBLUETOOTHSCOON                      = IBinder::FIRST_CALL_TRANSACTION + 31,
+        SETBLUETOOTHA2DPON                    = IBinder::FIRST_CALL_TRANSACTION + 32,
+        ISBLUETOOTHA2DPON                     = IBinder::FIRST_CALL_TRANSACTION + 33,
+        REQUESTAUDIOFOCUS                     = IBinder::FIRST_CALL_TRANSACTION + 34,
+        ABANDONAUDIOFOCUS                     = IBinder::FIRST_CALL_TRANSACTION + 35,
+        UNREGISTERAUDIOFOCUSCLIENT            = IBinder::FIRST_CALL_TRANSACTION + 36,
+        GETCURRENTAUDIOFOCUS                  = IBinder::FIRST_CALL_TRANSACTION + 37,
+        STARTBLUETOOTHSCO                     = IBinder::FIRST_CALL_TRANSACTION + 38,
+        STARTBLUETOOTHSCOVIRTUALCALL          = IBinder::FIRST_CALL_TRANSACTION + 39,
+        STOPBLUETOOTHSCO                      = IBinder::FIRST_CALL_TRANSACTION + 40,
+        FORCEVOLUMECONTROLSTREAM              = IBinder::FIRST_CALL_TRANSACTION + 41,
+        SETRINGTONEPLAYER                     = IBinder::FIRST_CALL_TRANSACTION + 42,
+        GETRINGTONEPLAYER                     = IBinder::FIRST_CALL_TRANSACTION + 43,
+        GETUISOUNDSSTREAMTYPE                 = IBinder::FIRST_CALL_TRANSACTION + 44,
+        SETWIREDDEVICECONNECTIONSTATE         = IBinder::FIRST_CALL_TRANSACTION + 45,
+        SETBLUETOOTHA2DPDEVICECONNECTIONSTATE = IBinder::FIRST_CALL_TRANSACTION + 46,
+        HANDLEBLUETOOTHA2DPDEVICECONFIGCHANGE = IBinder::FIRST_CALL_TRANSACTION + 47,
+        STARTWATCHINGROUTES                   = IBinder::FIRST_CALL_TRANSACTION + 48,
+        ISCAMERASOUNDFORCED                   = IBinder::FIRST_CALL_TRANSACTION + 49,
+        SETVOLUMECONTROLLER                   = IBinder::FIRST_CALL_TRANSACTION + 50,
+        NOTIFYVOLUMECONTROLLERVISIBLE         = IBinder::FIRST_CALL_TRANSACTION + 51,
+        ISSTREAMAFFECTEDBYRINGERMODE          = IBinder::FIRST_CALL_TRANSACTION + 52,
+        ISSTREAMAFFECTEDBYMUTE                = IBinder::FIRST_CALL_TRANSACTION + 53,
+        DISABLESAFEMEDIAVOLUME                = IBinder::FIRST_CALL_TRANSACTION + 54,
+        SETHDMISYSTEMAUDIOSUPPORTED           = IBinder::FIRST_CALL_TRANSACTION + 55,
+        ISHDMISYSTEMAUDIOSUPPORTED            = IBinder::FIRST_CALL_TRANSACTION + 56,
+        REGISTERAUDIOPOLICY                   = IBinder::FIRST_CALL_TRANSACTION + 57,
+        UNREGISTERAUDIOPOLICYASYNC            = IBinder::FIRST_CALL_TRANSACTION + 58,
+        SETFOCUSPROPERTIESFORPOLICY           = IBinder::FIRST_CALL_TRANSACTION + 59,
+        SETVOLUMEPOLICY                       = IBinder::FIRST_CALL_TRANSACTION + 60,
+        REGISTERRECORDINGCALLBACK             = IBinder::FIRST_CALL_TRANSACTION + 61,
+        UNREGISTERRECORDINGCALLBACK           = IBinder::FIRST_CALL_TRANSACTION + 62,
+        GETACTIVERECORDINGCONFIGURATIONS      = IBinder::FIRST_CALL_TRANSACTION + 63,
+        REGISTERPLAYBACKCALLBACK              = IBinder::FIRST_CALL_TRANSACTION + 64,
+        UNREGISTERPLAYBACKCALLBACK            = IBinder::FIRST_CALL_TRANSACTION + 65,
+        GETACTIVEPLAYBACKCONFIGURATIONS       = IBinder::FIRST_CALL_TRANSACTION + 66,
+        */
+
+        TRACK_PLAYER                          = IBinder::FIRST_CALL_TRANSACTION + 67,
+        PLAYER_ATTRIBUTES                     = IBinder::FIRST_CALL_TRANSACTION + 68,
+        PLAYER_EVENT                          = IBinder::FIRST_CALL_TRANSACTION + 69,
+        RELEASE_PLAYER                        = IBinder::FIRST_CALL_TRANSACTION + 70,
+
+    };
+
+    DECLARE_META_INTERFACE(AudioManager)
+
+    // The parcels created by these methods must be kept in sync with the
+    // corresponding methods from IAudioService.aidl and objects it imports.
+    virtual audio_unique_id_t trackPlayer(int playerType, int usage, int content) = 0;
+    /*oneway*/ virtual status_t playerAttributes(audio_unique_id_t piid, int usage, int content)= 0;
+    /*oneway*/ virtual status_t playerEvent(int piid, int event) = 0;
+    /*oneway*/ virtual status_t releasePlayer(int piid) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAUDIOMANAGER_H
diff --git a/include/gfx/.clang-format b/include/gfx/.clang-format
new file mode 100644
index 0000000..86763a0
--- /dev/null
+++ b/include/gfx/.clang-format
@@ -0,0 +1,11 @@
+BasedOnStyle: Google
+
+AccessModifierOffset: -2
+AllowShortFunctionsOnASingleLine: Inline
+BinPackParameters: false
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+ConstructorInitializerIndentWidth: 2
+ContinuationIndentWidth: 8
+IndentWidth: 4
diff --git a/include/gfx/FloatRect.h b/include/gfx/FloatRect.h
new file mode 100644
index 0000000..6be5e22
--- /dev/null
+++ b/include/gfx/FloatRect.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+namespace android {
+namespace gfx {
+
+class FloatRect {
+  public:
+    FloatRect() = default;
+    constexpr FloatRect(float _left, float _top, float _right, float _bottom)
+      : left(_left), top(_top), right(_right), bottom(_bottom) {}
+
+    float getWidth() const { return right - left; }
+    float getHeight() const { return bottom - top; }
+
+    float left = 0.0f;
+    float top = 0.0f;
+    float right = 0.0f;
+    float bottom = 0.0f;
+};
+
+inline bool operator==(const FloatRect& a, const FloatRect& b) {
+    return a.left == b.left && a.top == b.top && a.right == b.right && a.bottom == b.bottom;
+}
+
+}  // namespace gfx
+}  // namespace android
diff --git a/include/gui/BitTube.h b/include/gui/BitTube.h
index 3ecac52..9d65fad 100644
--- a/include/gui/BitTube.h
+++ b/include/gui/BitTube.h
@@ -20,10 +20,9 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#include <android/log.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
-#include <cutils/log.h>
-
 
 namespace android {
 // ----------------------------------------------------------------------------
diff --git a/include/gui/BufferItem.h b/include/gui/BufferItem.h
index 5232d0f..ab676cc 100644
--- a/include/gui/BufferItem.h
+++ b/include/gui/BufferItem.h
@@ -20,6 +20,7 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
+#include <ui/FenceTime.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
 
@@ -59,6 +60,9 @@
     // mFence is a fence that will signal when the buffer is idle.
     sp<Fence> mFence;
 
+    // The std::shared_ptr<FenceTime> wrapper around mFence.
+    std::shared_ptr<FenceTime> mFenceTime{FenceTime::NO_FENCE};
+
     // mCrop is the current crop rectangle for this buffer slot.
     Rect mCrop;
 
diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h
index 0e95ec3..8a3fa39 100644
--- a/include/gui/FrameTimestamps.h
+++ b/include/gui/FrameTimestamps.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_GUI_FRAMETIMESTAMPS_H
 #define ANDROID_GUI_FRAMETIMESTAMPS_H
 
-#include <ui/Fence.h>
+#include <ui/FenceTime.h>
 #include <utils/Flattenable.h>
 #include <utils/StrongPointer.h>
 #include <utils/Timers.h>
@@ -28,12 +28,12 @@
 
 namespace android {
 
-
 struct FrameEvents;
 class FrameEventHistoryDelta;
 class String8;
 
 
+// Identifiers for all the events that may be recorded or reported.
 enum class FrameEvent {
     POSTED,
     REQUESTED_PRESENT,
@@ -79,23 +79,17 @@
     bool addRetireCalled{false};
     bool addReleaseCalled{false};
 
-    nsecs_t postedTime{0};
-    nsecs_t requestedPresentTime{0};
-    nsecs_t latchTime{0};
-    nsecs_t firstRefreshStartTime{0};
-    nsecs_t lastRefreshStartTime{0};
+    nsecs_t postedTime{-1};
+    nsecs_t requestedPresentTime{-1};
+    nsecs_t latchTime{-1};
+    nsecs_t firstRefreshStartTime{-1};
+    nsecs_t lastRefreshStartTime{-1};
 
-    nsecs_t acquireTime{0};
-    nsecs_t gpuCompositionDoneTime{0};
-    nsecs_t displayPresentTime{0};
-    nsecs_t displayRetireTime{0};
-    nsecs_t releaseTime{0};
-
-    sp<Fence> acquireFence{Fence::NO_FENCE};
-    sp<Fence> gpuCompositionDoneFence{Fence::NO_FENCE};
-    sp<Fence> displayPresentFence{Fence::NO_FENCE};
-    sp<Fence> displayRetireFence{Fence::NO_FENCE};
-    sp<Fence> releaseFence{Fence::NO_FENCE};
+    std::shared_ptr<FenceTime> acquireFence{FenceTime::NO_FENCE};
+    std::shared_ptr<FenceTime> gpuCompositionDoneFence{FenceTime::NO_FENCE};
+    std::shared_ptr<FenceTime> displayPresentFence{FenceTime::NO_FENCE};
+    std::shared_ptr<FenceTime> displayRetireFence{FenceTime::NO_FENCE};
+    std::shared_ptr<FenceTime> releaseFence{FenceTime::NO_FENCE};
 };
 
 
@@ -122,11 +116,23 @@
 public:
     ~ProducerFrameEventHistory() override;
 
-    void updateAcquireFence(uint64_t frameNumber, sp<Fence> acquire);
+    void updateAcquireFence(
+            uint64_t frameNumber, std::shared_ptr<FenceTime>&& acquire);
     void applyDelta(const FrameEventHistoryDelta& delta);
 
+    void updateSignalTimes();
+
 private:
     size_t mAcquireOffset{0};
+
+    // The consumer updates it's timelines in Layer and SurfaceFlinger since
+    // they can coordinate shared timelines better. The producer doesn't have
+    // shared timelines though, so just let it own and update all of them.
+    FenceTimeline mAcquireTimeline;
+    FenceTimeline mGpuCompositionDoneTimeline;
+    FenceTimeline mPresentTimeline;
+    FenceTimeline mRetireTimeline;
+    FenceTimeline mReleaseTimeline;
 };
 
 
@@ -136,7 +142,7 @@
     uint64_t frameNumber{0};
     nsecs_t postedTime{0};
     nsecs_t requestedPresentTime{0};
-    sp<Fence> acquireFence{Fence::NO_FENCE};
+    std::shared_ptr<FenceTime> acquireFence{FenceTime::NO_FENCE};
 };
 
 
@@ -175,18 +181,26 @@
     void addLatch(uint64_t frameNumber, nsecs_t latchTime);
     void addPreComposition(uint64_t frameNumber, nsecs_t refreshStartTime);
     void addPostComposition(uint64_t frameNumber,
-            sp<Fence> gpuCompositionDone, sp<Fence> displayPresent);
-    void addRetire(uint64_t frameNumber, sp<Fence> displayRetire);
-    void addRelease(uint64_t frameNumber, sp<Fence> release);
+            const std::shared_ptr<FenceTime>& gpuCompositionDone,
+            const std::shared_ptr<FenceTime>& displayPresent);
+    void addRetire(uint64_t frameNumber,
+            const std::shared_ptr<FenceTime>& displayRetire);
+    void addRelease(uint64_t frameNumber,
+            std::shared_ptr<FenceTime>&& release);
 
     void getAndResetDelta(FrameEventHistoryDelta* delta);
 
 private:
+    void getFrameDelta(FrameEventHistoryDelta* delta,
+            const std::array<FrameEvents, MAX_FRAME_HISTORY>::iterator& frame);
+
     std::array<FrameEventDirtyFields, MAX_FRAME_HISTORY> mFramesDirty;
     size_t mQueueOffset{0};
     size_t mCompositionOffset{0};
     size_t mRetireOffset{0};
     size_t mReleaseOffset{0};
+
+    bool mProducerWantsEvents{false};
 };
 
 
@@ -202,6 +216,13 @@
             const FrameEvents& frameTimestamps,
             const FrameEventDirtyFields& dirtyFields);
 
+    // Movable.
+    FrameEventsDelta(FrameEventsDelta&& src) = default;
+    FrameEventsDelta& operator=(FrameEventsDelta&& src) = default;
+    // Not copyable.
+    FrameEventsDelta(const FrameEventsDelta& src) = delete;
+    FrameEventsDelta& operator=(const FrameEventsDelta& src) = delete;
+
     // Flattenable implementation
     size_t getFlattenedSize() const;
     size_t getFdCount() const;
@@ -226,10 +247,10 @@
     nsecs_t mFirstRefreshStartTime{0};
     nsecs_t mLastRefreshStartTime{0};
 
-    sp<Fence> mGpuCompositionDoneFence{Fence::NO_FENCE};
-    sp<Fence> mDisplayPresentFence{Fence::NO_FENCE};
-    sp<Fence> mDisplayRetireFence{Fence::NO_FENCE};
-    sp<Fence> mReleaseFence{Fence::NO_FENCE};
+    FenceTime::Snapshot mGpuCompositionDoneFence;
+    FenceTime::Snapshot mDisplayPresentFence;
+    FenceTime::Snapshot mDisplayRetireFence;
+    FenceTime::Snapshot mReleaseFence;
 
     // This is a static method with an auto return value so we can call
     // it without needing const and non-const versions.
@@ -253,6 +274,16 @@
 friend class ProducerFrameEventHistory;
 
 public:
+    FrameEventHistoryDelta() = default;
+
+    // Movable.
+    FrameEventHistoryDelta(FrameEventHistoryDelta&& src) = default;
+    FrameEventHistoryDelta& operator=(FrameEventHistoryDelta&& src);
+    // Not copyable.
+    FrameEventHistoryDelta(const FrameEventHistoryDelta& src) = delete;
+    FrameEventHistoryDelta& operator=(
+            const FrameEventHistoryDelta& src) = delete;
+
     // Flattenable implementation.
     size_t getFlattenedSize() const;
     size_t getFdCount() const;
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index 6ff1303..493ecde 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -187,6 +187,10 @@
     // ready to be read from.
     sp<Fence> getCurrentFence() const;
 
+    // getCurrentFence returns the FenceTime indicating when the current
+    // buffer is ready to be read from.
+    std::shared_ptr<FenceTime> getCurrentFenceTime() const;
+
     // doGLFenceWait inserts a wait command into the OpenGL ES command stream
     // to ensure that it is safe for future OpenGL ES commands to access the
     // current texture buffer.
@@ -398,6 +402,9 @@
     // mCurrentFence is the fence received from BufferQueue in updateTexImage.
     sp<Fence> mCurrentFence;
 
+    // The FenceTime wrapper around mCurrentFence.
+    std::shared_ptr<FenceTime> mCurrentFenceTime{FenceTime::NO_FENCE};
+
     // mCurrentTransformMatrix is the transform matrix for the current texture.
     // It gets computed by computeTransformMatrix each time updateTexImage is
     // called.
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 492db35..304a0c0 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -363,6 +363,15 @@
     };
 
     struct QueueBufferOutput : public Flattenable<QueueBufferOutput> {
+        QueueBufferOutput() = default;
+
+        // Moveable.
+        QueueBufferOutput(QueueBufferOutput&& src) = default;
+        QueueBufferOutput& operator=(QueueBufferOutput&& src) = default;
+        // Not copyable.
+        QueueBufferOutput(const QueueBufferOutput& src) = delete;
+        QueueBufferOutput& operator=(const QueueBufferOutput& src) = delete;
+
         // Flattenable protocol
         static constexpr size_t minFlattenedSize();
         size_t getFlattenedSize() const;
diff --git a/include/media/hardware/HDCPAPI.h b/include/media/hardware/HDCPAPI.h
index 3a53e9f..30cd5fd 100644
--- a/include/media/hardware/HDCPAPI.h
+++ b/include/media/hardware/HDCPAPI.h
@@ -73,7 +73,7 @@
     // Module can call the notification function to signal completion/failure
     // of asynchronous operations (such as initialization) or out of band
     // events.
-    HDCPModule(void *cookie, ObserverFunc observerNotify) {};
+    HDCPModule(void * /*cookie*/, ObserverFunc /*observerNotify*/) {};
 
     virtual ~HDCPModule() {};
 
@@ -104,8 +104,8 @@
     // 1 for the second and so on)
     // inputCTR _will_be_maintained_by_the_callee_ for each PES stream.
     virtual status_t encrypt(
-            const void *inData, size_t size, uint32_t streamCTR,
-            uint64_t *outInputCTR, void *outData) {
+            const void * /*inData*/, size_t /*size*/, uint32_t /*streamCTR*/,
+            uint64_t * /*outInputCTR*/, void * /*outData*/) {
         return INVALID_OPERATION;
     }
 
@@ -119,8 +119,8 @@
     // 1 for the second and so on)
     // inputCTR _will_be_maintained_by_the_callee_ for each PES stream.
     virtual status_t encryptNative(
-            buffer_handle_t buffer, size_t offset, size_t size,
-            uint32_t streamCTR, uint64_t *outInputCTR, void *outData) {
+            buffer_handle_t /*buffer*/, size_t /*offset*/, size_t /*size*/,
+            uint32_t /*streamCTR*/, uint64_t * /*outInputCTR*/, void * /*outData*/) {
         return INVALID_OPERATION;
     }
     // DECRYPTION only:
@@ -133,9 +133,9 @@
     // until outData contains size bytes of decrypted data.
     // Both streamCTR and inputCTR will be provided by the caller.
     virtual status_t decrypt(
-            const void *inData, size_t size,
-            uint32_t streamCTR, uint64_t inputCTR,
-            void *outData) {
+            const void * /*inData*/, size_t /*size*/,
+            uint32_t /*streamCTR*/, uint64_t /*inputCTR*/,
+            void * /*outData*/) {
         return INVALID_OPERATION;
     }
 
diff --git a/include/ui/GrallocAllocator.h b/include/ui/GrallocAllocator.h
index 5645bed..dd0f9e0 100644
--- a/include/ui/GrallocAllocator.h
+++ b/include/ui/GrallocAllocator.h
@@ -47,14 +47,14 @@
 
     Error createBufferDescriptor(
             const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
-            BufferDescriptor& descriptor) const;
+            BufferDescriptor* outDescriptor) const;
     void destroyBufferDescriptor(BufferDescriptor descriptor) const;
 
-    Error allocate(BufferDescriptor descriptor, Buffer& buffer) const;
+    Error allocate(BufferDescriptor descriptor, Buffer* outBuffer) const;
     void free(Buffer buffer) const;
 
     Error exportHandle(BufferDescriptor descriptor, Buffer buffer,
-            native_handle_t*& bufferHandle) const;
+            native_handle_t** outBufferHandle) const;
 
 private:
     sp<IAllocator> mAllocator;
diff --git a/include/ui/GrallocMapper.h b/include/ui/GrallocMapper.h
index 99d2837..f533dfb 100644
--- a/include/ui/GrallocMapper.h
+++ b/include/ui/GrallocMapper.h
@@ -32,97 +32,35 @@
 using hardware::graphics::common::V1_0::PixelFormat;
 using hardware::graphics::mapper::V2_0::FlexLayout;
 using hardware::graphics::mapper::V2_0::BackingStore;
-using hardware::graphics::mapper::V2_0::Device;
 using hardware::graphics::mapper::V2_0::IMapper;
 
 // Mapper is a wrapper to IMapper, a client-side graphics buffer mapper.
 class Mapper {
 public:
     Mapper();
-    ~Mapper();
 
     // this will be removed and Mapper will be always valid
     bool valid() const { return (mMapper != nullptr); }
 
-    Error retain(buffer_handle_t handle) const
-    {
-        return mMapper->retain(mDevice, handle);
-    }
-
+    Error retain(buffer_handle_t handle) const;
     void release(buffer_handle_t handle) const;
 
-    Error getDimensions(buffer_handle_t handle,
-            uint32_t& width, uint32_t& height) const
-    {
-        return mMapper->getDimensions(mDevice, handle, &width, &height);
-    }
-
-    Error getFormat(buffer_handle_t handle,
-            PixelFormat& format) const
-    {
-        return mMapper->getFormat(mDevice, handle, &format);
-    }
-
-    Error getLayerCount(buffer_handle_t handle, uint32_t& layerCount) const
-    {
-        return mMapper->getLayerCount(mDevice, handle, &layerCount);
-    }
-
-    Error getProducerUsageMask(buffer_handle_t handle,
-            uint64_t& usageMask) const
-    {
-        return mMapper->getProducerUsageMask(mDevice, handle, &usageMask);
-    }
-
-    Error getConsumerUsageMask(buffer_handle_t handle,
-            uint64_t& usageMask) const
-    {
-        return mMapper->getConsumerUsageMask(mDevice, handle, &usageMask);
-    }
-
-    Error getBackingStore(buffer_handle_t handle,
-            BackingStore& store) const
-    {
-        return mMapper->getBackingStore(mDevice, handle, &store);
-    }
-
-    Error getStride(buffer_handle_t handle, uint32_t& stride) const
-    {
-        return mMapper->getStride(mDevice, handle, &stride);
-    }
-
-    Error getNumFlexPlanes(buffer_handle_t handle, uint32_t& numPlanes) const
-    {
-        return mMapper->getNumFlexPlanes(mDevice, handle, &numPlanes);
-    }
+    Error getStride(buffer_handle_t handle, uint32_t* outStride) const;
 
     Error lock(buffer_handle_t handle,
             uint64_t producerUsageMask,
             uint64_t consumerUsageMask,
-            const Device::Rect& accessRegion,
-            int acquireFence, void*& data) const
-    {
-        return mMapper->lock(mDevice, handle,
-                producerUsageMask, consumerUsageMask,
-                &accessRegion, acquireFence, &data);
-    }
-
+            const IMapper::Rect& accessRegion,
+            int acquireFence, void** outData) const;
     Error lock(buffer_handle_t handle,
             uint64_t producerUsageMask,
             uint64_t consumerUsageMask,
-            const Device::Rect& accessRegion,
-            int acquireFence, FlexLayout& flexLayout) const
-    {
-        return mMapper->lockFlex(mDevice, handle,
-                producerUsageMask, consumerUsageMask,
-                &accessRegion, acquireFence, &flexLayout);
-    }
-
+            const IMapper::Rect& accessRegion,
+            int acquireFence, FlexLayout* outLayout) const;
     int unlock(buffer_handle_t handle) const;
 
 private:
-    const IMapper* mMapper;
-    Device* mDevice;
+    sp<IMapper> mMapper;
 };
 
 } // namespace Gralloc2
diff --git a/include/ui/PixelFormat.h b/include/ui/PixelFormat.h
index f26fecb..ab7a9a3 100644
--- a/include/ui/PixelFormat.h
+++ b/include/ui/PixelFormat.h
@@ -60,6 +60,7 @@
     PIXEL_FORMAT_BGRA_8888   = HAL_PIXEL_FORMAT_BGRA_8888,   // 4x8-bit BGRA
     PIXEL_FORMAT_RGBA_5551   = 6,                            // 16-bit ARGB
     PIXEL_FORMAT_RGBA_4444   = 7,                            // 16-bit ARGB
+    PIXEL_FORMAT_RGBA_FP16   = HAL_PIXEL_FORMAT_RGBA_FP16,   // 64-bit RGBA
 };
 
 typedef int32_t PixelFormat;
diff --git a/include/ui/Rect.h b/include/ui/Rect.h
index a8513a9..8aadd58 100644
--- a/include/ui/Rect.h
+++ b/include/ui/Rect.h
@@ -17,11 +17,13 @@
 #ifndef ANDROID_UI_RECT
 #define ANDROID_UI_RECT
 
+#include <gfx/FloatRect.h>
 #include <utils/Flattenable.h>
 #include <utils/Log.h>
 #include <utils/TypeHelpers.h>
 #include <ui/Point.h>
 
+#include <android/log.h>
 #include <android/rect.h>
 
 namespace android {
@@ -177,11 +179,15 @@
     // this calculates (Region(*this) - exclude).bounds() efficiently
     Rect reduce(const Rect& exclude) const;
 
-
     // for backward compatibility
     inline int32_t width() const { return getWidth(); }
     inline int32_t height() const { return getHeight(); }
     inline void set(const Rect& rhs) { operator = (rhs); }
+
+    gfx::FloatRect toFloatRect() const {
+        return {static_cast<float>(left), static_cast<float>(top),
+                static_cast<float>(right), static_cast<float>(bottom)};
+    }
 };
 
 ANDROID_BASIC_TYPES_TRAITS(Rect)
diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp
index 898ee52..87b295a 100644
--- a/libs/binder/IActivityManager.cpp
+++ b/libs/binder/IActivityManager.cpp
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+#include <unistd.h>
+#include <fcntl.h>
+
 #include <binder/IActivityManager.h>
 
 #include <binder/Parcel.h>
@@ -42,7 +45,7 @@
                 // Success is indicated here by a nonzero int followed by the fd;
                 // failure by a zero int with no data following.
                 if (reply.readInt32() != 0) {
-                    fd = dup(reply.readParcelFileDescriptor());
+                    fd = fcntl(reply.readParcelFileDescriptor(), F_DUPFD_CLOEXEC, 0);
                 }
             } else {
                 // An exception was thrown back; fall through to return failure
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index 790fa8c..45633f3 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -17,21 +17,20 @@
 #define LOG_TAG "IMemory"
 
 #include <atomic>
+#include <fcntl.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-
 #include <sys/types.h>
 #include <sys/mman.h>
+#include <unistd.h>
 
+#include <android/log.h>
 #include <binder/IMemory.h>
-#include <cutils/log.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
 #include <binder/Parcel.h>
 #include <utils/CallStack.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
 
 #define VERBOSE   0
 
@@ -288,7 +287,7 @@
                 mBase   = heap->mBase;
                 mSize   = heap->mSize;
                 mOffset = heap->mOffset;
-                int fd = dup(heap->mHeapId.load(memory_order_relaxed));
+                int fd = fcntl(heap->mHeapId.load(memory_order_relaxed), F_DUPFD_CLOEXEC, 0);
                 ALOGE_IF(fd==-1, "cannot dup fd=%d",
                         heap->mHeapId.load(memory_order_relaxed));
                 mHeapId.store(fd, memory_order_release);
@@ -323,7 +322,7 @@
 
         Mutex::Autolock _l(mLock);
         if (mHeapId.load(memory_order_relaxed) == -1) {
-            int fd = dup( parcel_fd );
+            int fd = fcntl(parcel_fd, F_DUPFD_CLOEXEC, 0);
             ALOGE_IF(fd==-1, "cannot dup fd=%d, size=%zd, err=%d (%s)",
                     parcel_fd, size, err, strerror(errno));
 
diff --git a/libs/binder/IShellCallback.cpp b/libs/binder/IShellCallback.cpp
index 8b97301..c793df3 100644
--- a/libs/binder/IShellCallback.cpp
+++ b/libs/binder/IShellCallback.cpp
@@ -16,6 +16,9 @@
 
 #define LOG_TAG "ShellCallback"
 
+#include <unistd.h>
+#include <fcntl.h>
+
 #include <binder/IShellCallback.h>
 
 #include <utils/Log.h>
@@ -44,7 +47,7 @@
         remote()->transact(OP_OPEN_OUTPUT_FILE, data, &reply, 0);
         reply.readExceptionCode();
         int fd = reply.readParcelFileDescriptor();
-        return fd >= 0 ? dup(fd) : fd;
+        return fd >= 0 ? fcntl(fd, F_DUPFD_CLOEXEC, 0) : fd;
 
     }
 };
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index 43a01e4..415c252 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -16,16 +16,16 @@
 
 #define LOG_TAG "MemoryHeapBase"
 
-#include <stdlib.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <fcntl.h>
 #include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdlib.h>
 #include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
 
-#include <cutils/log.h>
+#include <android/log.h>
 #include <cutils/ashmem.h>
 #include <cutils/atomic.h>
 
@@ -83,7 +83,7 @@
 {
     const size_t pagesize = getpagesize();
     size = ((size + pagesize-1) & ~(pagesize-1));
-    mapfd(dup(fd), size, offset);
+    mapfd(fcntl(fd, F_DUPFD_CLOEXEC, 0), size, offset);
 }
 
 status_t MemoryHeapBase::init(int fd, void *base, int size, int flags, const char* device)
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 15c441e..a6ccb53 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -539,7 +539,7 @@
                 // If this is a file descriptor, we need to dup it so the
                 // new Parcel now owns its own fd, and can declare that we
                 // officially know we have fds.
-                flat->handle = dup(flat->handle);
+                flat->handle = fcntl(flat->handle, F_DUPFD_CLOEXEC, 0);
                 flat->cookie = 1;
                 mHasFds = mFdsKnown = true;
                 if (!mAllowFds) {
@@ -1142,7 +1142,7 @@
 
 status_t Parcel::writeDupFileDescriptor(int fd)
 {
-    int dupFd = dup(fd);
+    int dupFd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
     if (dupFd < 0) {
         return -errno;
     }
@@ -1972,7 +1972,7 @@
     }
 
     for (int i=0 ; err==NO_ERROR && i<numFds ; i++) {
-        h->data[i] = dup(readFileDescriptor());
+        h->data[i] = fcntl(readFileDescriptor(), F_DUPFD_CLOEXEC, 0);
         if (h->data[i] < 0) {
             for (int j = 0; j < i; j++) {
                 close(h->data[j]);
@@ -2020,7 +2020,7 @@
         return BAD_TYPE;
     }
 
-    val->reset(dup(got));
+    val->reset(fcntl(got, F_DUPFD_CLOEXEC, 0));
 
     if (val->get() < 0) {
         return BAD_VALUE;
@@ -2095,9 +2095,9 @@
     status_t err = NO_ERROR;
     for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {
         int fd = this->readFileDescriptor();
-        if (fd < 0 || ((fds[i] = dup(fd)) < 0)) {
+        if (fd < 0 || ((fds[i] = fcntl(fd, F_DUPFD_CLOEXEC, 0)) < 0)) {
             err = BAD_VALUE;
-            ALOGE("dup() failed in Parcel::read, i is %zu, fds[i] is %d, fd_count is %zu, error: %s",
+            ALOGE("fcntl(F_DUPFD_CLOEXEC) failed in Parcel::read, i is %zu, fds[i] is %d, fd_count is %zu, error: %s",
                   i, fds[i], fd_count, strerror(fd < 0 ? -fd : errno));
             // Close all the file descriptors that were dup-ed.
             for (size_t j=0; j<i ;j++) {
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index e7078ba..70d425e 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -20,9 +20,9 @@
 
 #include <limits>
 
+#include <android/log.h>
 #include <binder/IBinder.h>
 #include <binder/Parcel.h>
-#include <log/log.h>
 #include <utils/Errors.h>
 
 using android::BAD_TYPE;
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index bf758ce..cb17da4 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -42,6 +42,9 @@
         "-Wno-nested-anon-types",
         "-Wno-gnu-anonymous-struct",
 
+        // We are aware of the risks inherent in comparing floats for equality
+        "-Wno-float-equal",
+
         "-DDEBUG_ONLY_CODE=0",
     ],
 
@@ -96,6 +99,7 @@
     ],
 
     shared_libs: [
+        "libsync",
         "libbinder",
         "libcutils",
         "libEGL",
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index 669124e..69b5962 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -91,11 +91,11 @@
     size_t size = sizeof(uint32_t); // Flags
     if (mGraphicBuffer != 0) {
         size += mGraphicBuffer->getFlattenedSize();
-        FlattenableUtils::align<4>(size);
+        size = FlattenableUtils::align<4>(size);
     }
     if (mFence != 0) {
         size += mFence->getFlattenedSize();
-        FlattenableUtils::align<4>(size);
+        size = FlattenableUtils::align<4>(size);
     }
     size += mSurfaceDamage.getFlattenedSize();
     size = FlattenableUtils::align<8>(size);
@@ -204,6 +204,8 @@
         status_t err = mFence->unflatten(buffer, size, fds, count);
         if (err) return err;
         size -= FlattenableUtils::align<4>(buffer);
+
+        mFenceTime = std::make_shared<FenceTime>(mFence);
     }
 
     status_t err = mSurfaceDamage.unflatten(buffer, size);
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index ee4c58c..d66aa1a 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -205,6 +205,7 @@
             // was cached when it was last queued.
             outBuffer->mGraphicBuffer = mSlots[slot].mGraphicBuffer;
             outBuffer->mFence = Fence::NO_FENCE;
+            outBuffer->mFenceTime = FenceTime::NO_FENCE;
             outBuffer->mCrop = mCore->mSharedBufferCache.crop;
             outBuffer->mTransform = mCore->mSharedBufferCache.transform &
                     ~static_cast<uint32_t>(
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 75198d7..39b9a0b 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -762,6 +762,8 @@
         return BAD_VALUE;
     }
 
+    auto acquireFenceTime = std::make_shared<FenceTime>(acquireFence);
+
     switch (scalingMode) {
         case NATIVE_WINDOW_SCALING_MODE_FREEZE:
         case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
@@ -858,6 +860,7 @@
         item.mFrameNumber = currentFrameNumber;
         item.mSlot = slot;
         item.mFence = acquireFence;
+        item.mFenceTime = acquireFenceTime;
         item.mIsDroppable = mCore->mAsyncMode ||
                 mCore->mDequeueBufferCannotBlock ||
                 (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == slot);
@@ -969,7 +972,7 @@
         // small trade-off in favor of latency rather than throughput.
         mLastQueueBufferFence->waitForever("Throttling EGL Production");
     }
-    mLastQueueBufferFence = acquireFence;
+    mLastQueueBufferFence = std::move(acquireFence);
     mLastQueuedCrop = item.mCrop;
     mLastQueuedTransform = item.mTransform;
 
@@ -979,7 +982,7 @@
         currentFrameNumber,
         postedTime,
         requestedPresentTimestamp,
-        acquireFence
+        std::move(acquireFenceTime)
     };
     addAndGetFrameTimestamps(&newFrameEventsEntry,
             getFrameTimestamps ? &output->frameTimestamps : nullptr);
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index 8393160..a9bafef 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -64,6 +64,7 @@
     switch (static_cast<int>(format)) {
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_RGBA_FP16:
         case HAL_PIXEL_FORMAT_RGB_888:
         case HAL_PIXEL_FORMAT_RGB_565:
         case HAL_PIXEL_FORMAT_BGRA_8888:
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index 30ff65f..c9b8948 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -16,6 +16,7 @@
 
 #include <gui/FrameTimestamps.h>
 
+#include <cutils/compiler.h>  // For CC_[UN]LIKELY
 #include <inttypes.h>
 #include <utils/String8.h>
 
@@ -25,28 +26,25 @@
 
 namespace android {
 
-static inline bool isValidTimestamp(nsecs_t time) {
-    return time > 0 && time < INT64_MAX;
-}
 
 // ============================================================================
 // FrameEvents
 // ============================================================================
 
 bool FrameEvents::hasPostedInfo() const {
-    return isValidTimestamp(postedTime);
+    return Fence::isValidTimestamp(postedTime);
 }
 
 bool FrameEvents::hasRequestedPresentInfo() const {
-    return isValidTimestamp(requestedPresentTime);
+    return Fence::isValidTimestamp(requestedPresentTime);
 }
 
 bool FrameEvents::hasLatchInfo() const {
-    return isValidTimestamp(latchTime);
+    return Fence::isValidTimestamp(latchTime);
 }
 
 bool FrameEvents::hasFirstRefreshStartInfo() const {
-    return isValidTimestamp(firstRefreshStartTime);
+    return Fence::isValidTimestamp(firstRefreshStartTime);
 }
 
 bool FrameEvents::hasLastRefreshStartInfo() const {
@@ -57,7 +55,7 @@
 }
 
 bool FrameEvents::hasAcquireInfo() const {
-    return isValidTimestamp(acquireTime) || acquireFence->isValid();
+    return acquireFence->isValid();
 }
 
 bool FrameEvents::hasGpuCompositionDoneInfo() const {
@@ -80,22 +78,27 @@
     return addReleaseCalled;
 }
 
-static void checkFenceForCompletion(sp<Fence>* fence, nsecs_t* dstTime) {
-    if ((*fence)->isValid()) {
-        nsecs_t time = (*fence)->getSignalTime();
-        if (isValidTimestamp(time)) {
-            *dstTime = time;
-            *fence = Fence::NO_FENCE;
-        }
-    }
+void FrameEvents::checkFencesForCompletion() {
+    acquireFence->getSignalTime();
+    gpuCompositionDoneFence->getSignalTime();
+    displayPresentFence->getSignalTime();
+    displayRetireFence->getSignalTime();
+    releaseFence->getSignalTime();
 }
 
-void FrameEvents::checkFencesForCompletion() {
-    checkFenceForCompletion(&acquireFence, &acquireTime);
-    checkFenceForCompletion(&gpuCompositionDoneFence, &gpuCompositionDoneTime);
-    checkFenceForCompletion(&displayPresentFence, &displayPresentTime);
-    checkFenceForCompletion(&displayRetireFence, &displayRetireTime);
-    checkFenceForCompletion(&releaseFence, &releaseTime);
+static void dumpFenceTime(String8& outString, const char* name,
+        bool pending, const FenceTime& fenceTime) {
+    outString.appendFormat("--- %s", name);
+    nsecs_t signalTime = fenceTime.getCachedSignalTime();
+    if (Fence::isValidTimestamp(signalTime)) {
+        outString.appendFormat("%" PRId64 "\n", signalTime);
+    } else if (pending || signalTime == Fence::SIGNAL_TIME_PENDING) {
+        outString.appendFormat("Pending\n");
+    } else if (&fenceTime == FenceTime::NO_FENCE.get()){
+        outString.appendFormat("N/A\n");
+    } else {
+        outString.appendFormat("Error\n");
+    }
 }
 
 void FrameEvents::dump(String8& outString) const
@@ -109,66 +112,36 @@
     outString.appendFormat("--- Req. Present\t%" PRId64 "\n", requestedPresentTime);
 
     outString.appendFormat("--- Latched     \t");
-    if (isValidTimestamp(latchTime)) {
+    if (Fence::isValidTimestamp(latchTime)) {
         outString.appendFormat("%" PRId64 "\n", latchTime);
     } else {
         outString.appendFormat("Pending\n");
     }
 
     outString.appendFormat("--- Refresh (First)\t");
-    if (isValidTimestamp(firstRefreshStartTime)) {
+    if (Fence::isValidTimestamp(firstRefreshStartTime)) {
         outString.appendFormat("%" PRId64 "\n", firstRefreshStartTime);
     } else {
         outString.appendFormat("Pending\n");
     }
 
     outString.appendFormat("--- Refresh (Last)\t");
-    if (isValidTimestamp(lastRefreshStartTime)) {
+    if (Fence::isValidTimestamp(lastRefreshStartTime)) {
         outString.appendFormat("%" PRId64 "\n", lastRefreshStartTime);
     } else {
         outString.appendFormat("Pending\n");
     }
 
-    outString.appendFormat("--- Acquire     \t");
-    if (isValidTimestamp(acquireTime)) {
-        outString.appendFormat("%" PRId64 "\n", acquireTime);
-    } else {
-        outString.appendFormat("Pending\n");
-    }
-
-    outString.appendFormat("--- GPU Composite Done\t");
-    if (isValidTimestamp(gpuCompositionDoneTime)) {
-        outString.appendFormat("%" PRId64 "\n", gpuCompositionDoneTime);
-    } else if (!addPostCompositeCalled || gpuCompositionDoneFence->isValid()) {
-        outString.appendFormat("Pending\n");
-    } else {
-        outString.appendFormat("N/A\n");
-    }
-
-    outString.appendFormat("--- Display Present\t");
-    if (isValidTimestamp(displayPresentTime)) {
-        outString.appendFormat("%" PRId64 "\n", displayPresentTime);
-    } else if (!addPostCompositeCalled || displayPresentFence->isValid()) {
-        outString.appendFormat("Pending\n");
-    } else {
-        outString.appendFormat("N/A\n");
-    }
-
-    outString.appendFormat("--- Display Retire\t");
-    if (isValidTimestamp(displayRetireTime)) {
-        outString.appendFormat("%" PRId64 "\n", displayRetireTime);
-    } else if (!addRetireCalled || displayRetireFence->isValid()) {
-        outString.appendFormat("Pending\n");
-    } else {
-        outString.appendFormat("N/A\n");
-    }
-
-    outString.appendFormat("--- Release     \t");
-    if (isValidTimestamp(releaseTime)) {
-        outString.appendFormat("%" PRId64 "\n", releaseTime);
-    } else {
-        outString.appendFormat("Pending\n");
-    }
+    dumpFenceTime(outString, "Acquire           \t",
+            true, *acquireFence);
+    dumpFenceTime(outString, "GPU Composite Done\t",
+            !addPostCompositeCalled, *gpuCompositionDoneFence);
+    dumpFenceTime(outString, "Display Present   \t",
+            !addPostCompositeCalled, *displayPresentFence);
+    dumpFenceTime(outString, "Display Retire    \t",
+            !addRetireCalled, *displayRetireFence);
+    dumpFenceTime(outString, "Release           \t",
+            true, *releaseFence);
 }
 
 
@@ -250,7 +223,7 @@
 ProducerFrameEventHistory::~ProducerFrameEventHistory() = default;
 
 void ProducerFrameEventHistory::updateAcquireFence(
-        uint64_t frameNumber, sp<Fence> acquire) {
+        uint64_t frameNumber, std::shared_ptr<FenceTime>&& acquire) {
     FrameEvents* frame = getFrame(frameNumber, &mAcquireOffset);
     if (frame == nullptr) {
         ALOGE("ProducerFrameEventHistory::updateAcquireFence: "
@@ -259,20 +232,39 @@
     }
 
     if (acquire->isValid()) {
-        frame->acquireFence = acquire;
+        mAcquireTimeline.push(acquire);
+        frame->acquireFence = std::move(acquire);
     } else {
         // If there isn't an acquire fence, assume that buffer was
         // ready for the consumer when posted.
-        frame->acquireTime = frame->postedTime;
+        frame->acquireFence = std::make_shared<FenceTime>(frame->postedTime);
     }
 }
 
-static void applyFenceDelta(sp<Fence>* dst, const sp<Fence>& src) {
-    if (src->isValid()) {
-        if ((*dst)->isValid()) {
-            ALOGE("applyFenceDelta: Unexpected fence.");
-        }
-        *dst = src;
+static void applyFenceDelta(FenceTimeline* timeline,
+        std::shared_ptr<FenceTime>* dst, const FenceTime::Snapshot& src) {
+    if (CC_UNLIKELY(dst == nullptr)) {
+        ALOGE("applyFenceDelta: dst is null.");
+        return;
+    }
+
+    switch (src.state) {
+        case FenceTime::Snapshot::State::EMPTY:
+            return;
+        case FenceTime::Snapshot::State::FENCE:
+            if (CC_UNLIKELY((*dst)->isValid())) {
+                ALOGE("applyFenceDelta: Unexpected fence.");
+            }
+            *dst = std::make_shared<FenceTime>(src.fence);
+            timeline->push(*dst);
+            return;
+        case FenceTime::Snapshot::State::SIGNAL_TIME:
+            if ((*dst)->isValid()) {
+                (*dst)->applyTrustedSnapshot(src);
+            } else {
+                *dst = std::make_shared<FenceTime>(src.signalTime);
+            }
+            return;
     }
 }
 
@@ -297,40 +289,37 @@
         frame.firstRefreshStartTime = d.mFirstRefreshStartTime;
         frame.lastRefreshStartTime = d.mLastRefreshStartTime;
 
-        if (frame.frameNumber == d.mFrameNumber) {
-            // Existing frame. Merge.
-            // Consumer never sends timestamps of fences, only the fences
-            // themselves, so we never need to update the fence timestamps here.
-            applyFenceDelta(
-                    &frame.gpuCompositionDoneFence, d.mGpuCompositionDoneFence);
-            applyFenceDelta(&frame.displayPresentFence, d.mDisplayPresentFence);
-            applyFenceDelta(&frame.displayRetireFence, d.mDisplayRetireFence);
-            applyFenceDelta(&frame.releaseFence, d.mReleaseFence);
-        } else {
-            // New frame. Overwrite.
+        if (frame.frameNumber != d.mFrameNumber) {
+            // We got a new frame. Initialize some of the fields.
             frame.frameNumber = d.mFrameNumber;
-
-            frame.gpuCompositionDoneFence = d.mGpuCompositionDoneFence;
-            frame.displayPresentFence = d.mDisplayPresentFence;
-            frame.displayRetireFence = d.mDisplayRetireFence;
-            frame.releaseFence = d.mReleaseFence;
-
-            // Set aquire fence and time at this point.
-            frame.acquireTime = 0;
-            frame.acquireFence = Fence::NO_FENCE;
-
-            // Reset fence-related timestamps
-            frame.gpuCompositionDoneTime = 0;
-            frame.displayPresentTime = 0;
-            frame.displayRetireTime = 0;
-            frame.releaseTime = 0;
-
+            frame.acquireFence = FenceTime::NO_FENCE;
+            frame.gpuCompositionDoneFence = FenceTime::NO_FENCE;
+            frame.displayPresentFence = FenceTime::NO_FENCE;
+            frame.displayRetireFence = FenceTime::NO_FENCE;
+            frame.releaseFence = FenceTime::NO_FENCE;
             // The consumer only sends valid frames.
             frame.valid = true;
         }
+
+        applyFenceDelta(&mGpuCompositionDoneTimeline,
+                &frame.gpuCompositionDoneFence, d.mGpuCompositionDoneFence);
+        applyFenceDelta(&mPresentTimeline,
+                &frame.displayPresentFence, d.mDisplayPresentFence);
+        applyFenceDelta(&mRetireTimeline,
+                &frame.displayRetireFence, d.mDisplayRetireFence);
+        applyFenceDelta(&mReleaseTimeline,
+                &frame.releaseFence, d.mReleaseFence);
     }
 }
 
+void ProducerFrameEventHistory::updateSignalTimes() {
+    mAcquireTimeline.updateSignalTimes();
+    mGpuCompositionDoneTimeline.updateSignalTimes();
+    mPresentTimeline.updateSignalTimes();
+    mRetireTimeline.updateSignalTimes();
+    mReleaseTimeline.updateSignalTimes();
+}
+
 
 // ============================================================================
 // ConsumerFrameEventHistory
@@ -360,7 +349,7 @@
         uint64_t frameNumber, nsecs_t latchTime) {
     FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
     if (frame == nullptr) {
-        ALOGE("ConsumerFrameEventHistory::addLatch: Did not find frame.");
+        ALOGE_IF(mProducerWantsEvents, "addLatch: Did not find frame.");
         return;
     }
     frame->latchTime = latchTime;
@@ -371,24 +360,25 @@
         uint64_t frameNumber, nsecs_t refreshStartTime) {
     FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
     if (frame == nullptr) {
-        ALOGE("ConsumerFrameEventHistory::addPreComposition: "
-              "Did not find frame.");
+        ALOGE_IF(mProducerWantsEvents,
+                "addPreComposition: Did not find frame.");
         return;
     }
     frame->lastRefreshStartTime = refreshStartTime;
     mFramesDirty[mCompositionOffset].setDirty<FrameEvent::LAST_REFRESH_START>();
-    if (!isValidTimestamp(frame->firstRefreshStartTime)) {
+    if (!Fence::isValidTimestamp(frame->firstRefreshStartTime)) {
         frame->firstRefreshStartTime = refreshStartTime;
         mFramesDirty[mCompositionOffset].setDirty<FrameEvent::FIRST_REFRESH_START>();
     }
 }
 
 void ConsumerFrameEventHistory::addPostComposition(uint64_t frameNumber,
-        sp<Fence> gpuCompositionDone, sp<Fence> displayPresent) {
+        const std::shared_ptr<FenceTime>& gpuCompositionDone,
+        const std::shared_ptr<FenceTime>& displayPresent) {
     FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
     if (frame == nullptr) {
-        ALOGE("ConsumerFrameEventHistory::addPostComposition: "
-              "Did not find frame.");
+        ALOGE_IF(mProducerWantsEvents,
+                "addPostComposition: Did not find frame.");
         return;
     }
     // Only get GPU and present info for the first composite.
@@ -404,10 +394,10 @@
 }
 
 void ConsumerFrameEventHistory::addRetire(
-        uint64_t frameNumber, sp<Fence> displayRetire) {
+        uint64_t frameNumber, const std::shared_ptr<FenceTime>& displayRetire) {
     FrameEvents* frame = getFrame(frameNumber, &mRetireOffset);
     if (frame == nullptr) {
-        ALOGE("ConsumerFrameEventHistory::addRetire: Did not find frame.");
+        ALOGE_IF(mProducerWantsEvents, "addRetire: Did not find frame.");
         return;
     }
     frame->addRetireCalled = true;
@@ -416,26 +406,40 @@
 }
 
 void ConsumerFrameEventHistory::addRelease(
-        uint64_t frameNumber, sp<Fence> release) {
+        uint64_t frameNumber, std::shared_ptr<FenceTime>&& release) {
     FrameEvents* frame = getFrame(frameNumber, &mReleaseOffset);
     if (frame == nullptr) {
         ALOGE("ConsumerFrameEventHistory::addRelease: Did not find frame.");
         return;
     }
     frame->addReleaseCalled = true;
-    frame->releaseFence = release;
+    frame->releaseFence = std::move(release);
     mFramesDirty[mReleaseOffset].setDirty<FrameEvent::RELEASE>();
 }
 
+void ConsumerFrameEventHistory::getFrameDelta(
+        FrameEventHistoryDelta* delta,
+        const std::array<FrameEvents, MAX_FRAME_HISTORY>::iterator& frame) {
+    mProducerWantsEvents = true;
+    size_t i = static_cast<size_t>(std::distance(mFrames.begin(), frame));
+    if (mFramesDirty[i].anyDirty()) {
+        delta->mDeltas.emplace_back(i, *frame, mFramesDirty[i]);
+        mFramesDirty[i].reset();
+    }
+}
+
 void ConsumerFrameEventHistory::getAndResetDelta(
         FrameEventHistoryDelta* delta) {
+    // Write these in order of frame number so that it is easy to
+    // add them to a FenceTimeline in the proper order producer side.
     delta->mDeltas.reserve(mFramesDirty.size());
-    for (size_t i = 0; i < mFramesDirty.size(); i++) {
-        if (mFramesDirty[i].anyDirty()) {
-            delta->mDeltas.push_back(
-                    FrameEventsDelta(i, mFrames[i], mFramesDirty[i]));
-            mFramesDirty[i].reset();
-        }
+    auto earliestFrame = std::min_element(
+            mFrames.begin(), mFrames.end(), &FrameNumberLessThan);
+    for (auto frame = earliestFrame; frame != mFrames.end(); ++frame) {
+        getFrameDelta(delta, frame);
+    }
+    for (auto frame = mFrames.begin(); frame != earliestFrame; ++frame) {
+        getFrameDelta(delta, frame);
     }
 }
 
@@ -458,15 +462,20 @@
       mLatchTime(frameTimestamps.latchTime),
       mFirstRefreshStartTime(frameTimestamps.firstRefreshStartTime),
       mLastRefreshStartTime(frameTimestamps.lastRefreshStartTime) {
-    mGpuCompositionDoneFence =
-            dirtyFields.isDirty<FrameEvent::GL_COMPOSITION_DONE>() ?
-                    frameTimestamps.gpuCompositionDoneFence : Fence::NO_FENCE;
-    mDisplayPresentFence = dirtyFields.isDirty<FrameEvent::DISPLAY_PRESENT>() ?
-            frameTimestamps.displayPresentFence : Fence::NO_FENCE;
-    mDisplayRetireFence = dirtyFields.isDirty<FrameEvent::DISPLAY_RETIRE>() ?
-            frameTimestamps.displayRetireFence : Fence::NO_FENCE;
-    mReleaseFence = dirtyFields.isDirty<FrameEvent::RELEASE>() ?
-            frameTimestamps.releaseFence : Fence::NO_FENCE;
+    if (dirtyFields.isDirty<FrameEvent::GL_COMPOSITION_DONE>()) {
+        mGpuCompositionDoneFence =
+                frameTimestamps.gpuCompositionDoneFence->getSnapshot();
+    }
+    if (dirtyFields.isDirty<FrameEvent::DISPLAY_PRESENT>()) {
+        mDisplayPresentFence =
+                frameTimestamps.displayPresentFence->getSnapshot();
+    }
+    if (dirtyFields.isDirty<FrameEvent::DISPLAY_RETIRE>()) {
+        mDisplayRetireFence = frameTimestamps.displayRetireFence->getSnapshot();
+    }
+    if (dirtyFields.isDirty<FrameEvent::RELEASE>()) {
+        mReleaseFence = frameTimestamps.releaseFence->getSnapshot();
+    }
 }
 
 size_t FrameEventsDelta::minFlattenedSize() {
@@ -489,16 +498,16 @@
     auto fences = allFences(this);
     return minFlattenedSize() +
             std::accumulate(fences.begin(), fences.end(), size_t(0),
-                    [](size_t a, const sp<Fence>* fence) {
-                            return a + (*fence)->getFlattenedSize();
+                    [](size_t a, const FenceTime::Snapshot* fence) {
+                            return a + fence->getFlattenedSize();
                     });
 }
 
 size_t FrameEventsDelta::getFdCount() const {
     auto fences = allFences(this);
     return std::accumulate(fences.begin(), fences.end(), size_t(0),
-            [](size_t a, const sp<Fence>* fence) {
-                return a + (*fence)->getFdCount();
+            [](size_t a, const FenceTime::Snapshot* fence) {
+                return a + fence->getFdCount();
             });
 }
 
@@ -532,7 +541,7 @@
 
     // Fences
     for (auto fence : allFences(this)) {
-        status_t status = (*fence)->flatten(buffer, size, fds, count);
+        status_t status = fence->flatten(buffer, size, fds, count);
         if (status != NO_ERROR) {
             return status;
         }
@@ -570,8 +579,7 @@
 
     // Fences
     for (auto fence : allFences(this)) {
-        *fence = new Fence;
-        status_t status = (*fence)->unflatten(buffer, size, fds, count);
+        status_t status = fence->unflatten(buffer, size, fds, count);
         if (status != NO_ERROR) {
             return status;
         }
@@ -584,6 +592,16 @@
 // FrameEventHistoryDelta
 // ============================================================================
 
+FrameEventHistoryDelta& FrameEventHistoryDelta::operator=(
+        FrameEventHistoryDelta&& src) {
+    if (CC_UNLIKELY(!mDeltas.empty())) {
+        ALOGE("FrameEventHistoryDelta: Clobbering history.");
+    }
+    mDeltas = std::move(src.mDeltas);
+    ALOGE_IF(src.mDeltas.empty(), "Source mDeltas not empty.");
+    return *this;
+}
+
 size_t FrameEventHistoryDelta::minFlattenedSize() {
     return sizeof(uint32_t);
 }
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 10e999c..fea9df7 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -322,6 +322,7 @@
         mCurrentTransform = 0;
         mCurrentTimestamp = 0;
         mCurrentFence = Fence::NO_FENCE;
+        mCurrentFenceTime = FenceTime::NO_FENCE;
 
         if (mAttached) {
             // This binds a dummy buffer (mReleasedTexImage).
@@ -488,6 +489,7 @@
     mCurrentScalingMode = item.mScalingMode;
     mCurrentTimestamp = item.mTimestamp;
     mCurrentFence = item.mFence;
+    mCurrentFenceTime = item.mFenceTime;
     mCurrentFrameNumber = item.mFrameNumber;
 
     computeCurrentTransformMatrixLocked();
@@ -856,6 +858,7 @@
             switch (buf->getPixelFormat()) {
                 case PIXEL_FORMAT_RGBA_8888:
                 case PIXEL_FORMAT_RGBX_8888:
+                case PIXEL_FORMAT_RGBA_FP16:
                 case PIXEL_FORMAT_RGB_888:
                 case PIXEL_FORMAT_RGB_565:
                 case PIXEL_FORMAT_BGRA_8888:
@@ -981,6 +984,11 @@
     return mCurrentFence;
 }
 
+std::shared_ptr<FenceTime> GLConsumer::getCurrentFenceTime() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentFenceTime;
+}
+
 status_t GLConsumer::doGLFenceWait() const {
     Mutex::Autolock lock(mMutex);
     return doGLFenceWaitLocked();
diff --git a/libs/gui/GraphicBufferAlloc.cpp b/libs/gui/GraphicBufferAlloc.cpp
index 9d045dd..7d91d33 100644
--- a/libs/gui/GraphicBufferAlloc.cpp
+++ b/libs/gui/GraphicBufferAlloc.cpp
@@ -15,7 +15,7 @@
  ** limitations under the License.
  */
 
-#include <cutils/log.h>
+#include <android/log.h>
 
 #include <ui/GraphicBuffer.h>
 
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 053d153..dbf03a5 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -14,21 +14,20 @@
  * limitations under the License.
  */
 
+#include <inttypes.h>
+#include <stdint.h>
+#include <sys/limits.h>
+#include <sys/types.h>
 
+#include <android/log.h>
 #include <binder/AppOpsManager.h>
 #include <binder/IServiceManager.h>
 #include <gui/Sensor.h>
 #include <hardware/sensors.h>
-#include <log/log.h>
 #include <utils/Errors.h>
 #include <utils/String8.h>
 #include <utils/Flattenable.h>
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <sys/limits.h>
-
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 6a02a77..1e79e06 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -144,6 +144,19 @@
     mEnableFrameTimestamps = enable;
 }
 
+static void getFrameTimestamp(nsecs_t *dst, const nsecs_t& src) {
+    if (dst != nullptr) {
+        *dst = Fence::isValidTimestamp(src) ? src : 0;
+    }
+}
+
+static void getFrameTimestampFence(nsecs_t *dst, const std::shared_ptr<FenceTime>& src) {
+    if (dst != nullptr) {
+        nsecs_t signalTime = src->getSignalTime();
+        *dst = Fence::isValidTimestamp(signalTime) ? signalTime : 0;
+    }
+}
+
 status_t Surface::getFrameTimestamps(uint64_t frameNumber,
         nsecs_t* outRequestedPresentTime, nsecs_t* outAcquireTime,
         nsecs_t* outRefreshStartTime, nsecs_t* outGlCompositionDoneTime,
@@ -188,29 +201,16 @@
         return NAME_NOT_FOUND;
     }
 
-    events->checkFencesForCompletion();
+    getFrameTimestamp(outRequestedPresentTime, events->requestedPresentTime);
+    getFrameTimestamp(outRefreshStartTime, events->firstRefreshStartTime);
 
-    if (outRequestedPresentTime) {
-        *outRequestedPresentTime = events->requestedPresentTime;
-    }
-    if (outAcquireTime) {
-        *outAcquireTime = events->acquireTime;
-    }
-    if (outRefreshStartTime) {
-        *outRefreshStartTime = events->firstRefreshStartTime;
-    }
-    if (outGlCompositionDoneTime) {
-        *outGlCompositionDoneTime = events->gpuCompositionDoneTime;
-    }
-    if (outDisplayPresentTime) {
-        *outDisplayPresentTime = events->displayPresentTime;
-    }
-    if (outDisplayRetireTime) {
-        *outDisplayRetireTime = events->displayRetireTime;
-    }
-    if (outReleaseTime) {
-        *outReleaseTime = events->releaseTime;
-    }
+    getFrameTimestampFence(outAcquireTime, events->acquireFence);
+    getFrameTimestampFence(
+            outGlCompositionDoneTime, events->gpuCompositionDoneFence);
+    getFrameTimestampFence(
+            outDisplayPresentTime, events->displayPresentFence);
+    getFrameTimestampFence(outDisplayRetireTime, events->displayRetireFence);
+    getFrameTimestampFence(outReleaseTime, events->releaseFence);
 
     return NO_ERROR;
 }
@@ -571,7 +571,12 @@
         // Update timestamps with the local acquire fence.
         // The consumer doesn't send it back to prevent us from having two
         // file descriptors of the same fence.
-        mFrameEventHistory.updateAcquireFence(mNextFrameNumber, fence);
+        mFrameEventHistory.updateAcquireFence(mNextFrameNumber,
+                std::make_shared<FenceTime>(std::move(fence)));
+
+        // Cache timestamps of signaled fences so we can close their file
+        // descriptors.
+        mFrameEventHistory.updateSignalTimes();
     }
 
     mDefaultWidth = output.width;
@@ -1283,7 +1288,8 @@
 static status_t copyBlt(
         const sp<GraphicBuffer>& dst,
         const sp<GraphicBuffer>& src,
-        const Region& reg)
+        const Region& reg,
+        int *dstFenceFd)
 {
     // src and dst with, height and format must be identical. no verification
     // is done here.
@@ -1294,9 +1300,10 @@
     ALOGE_IF(err, "error locking src buffer %s", strerror(-err));
 
     uint8_t* dst_bits = NULL;
-    err = dst->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(),
-            reinterpret_cast<void**>(&dst_bits));
+    err = dst->lockAsync(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(),
+            reinterpret_cast<void**>(&dst_bits), *dstFenceFd);
     ALOGE_IF(err, "error locking dst buffer %s", strerror(-err));
+    *dstFenceFd = -1;
 
     Region::const_iterator head(reg.begin());
     Region::const_iterator tail(reg.end());
@@ -1330,7 +1337,7 @@
         src->unlock();
 
     if (dst_bits)
-        dst->unlock();
+        dst->unlockAsync(dstFenceFd);
 
     return err;
 }
@@ -1380,8 +1387,9 @@
         if (canCopyBack) {
             // copy the area that is invalid and not repainted this round
             const Region copyback(mDirtyRegion.subtract(newDirtyRegion));
-            if (!copyback.isEmpty())
-                copyBlt(backBuffer, frontBuffer, copyback);
+            if (!copyback.isEmpty()) {
+                copyBlt(backBuffer, frontBuffer, copyback, &fenceFd);
+            }
         } else {
             // if we can't copy-back anything, modify the user's dirty
             // region to make sure they redraw the whole buffer
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 1aa03a5..66e1bb6 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -29,8 +29,12 @@
 #include <private/gui/ComposerService.h>
 #include <binder/ProcessState.h>
 
+#include <thread>
+
 namespace android {
 
+using namespace std::chrono_literals;
+
 class SurfaceTest : public ::testing::Test {
 protected:
 
@@ -77,6 +81,8 @@
 
 TEST_F(SurfaceTest, QueuesToWindowComposerIsTrueWhenPurgatorized) {
     mSurfaceControl.clear();
+    // Wait for the async clean-up to complete.
+    std::this_thread::sleep_for(50ms);
 
     sp<ANativeWindow> anw(mSurface);
     int result = -123;
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 2dff4e0..136dd7f 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -19,20 +19,18 @@
 // Log debug messages about touch event resampling
 #define DEBUG_RESAMPLING 0
 
-
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
 #include <math.h>
-#include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/types.h>
 #include <unistd.h>
 
-#include <cutils/log.h>
+#include <android/log.h>
 #include <cutils/properties.h>
 #include <input/InputTransport.h>
 
-
 namespace android {
 
 // Socket buffer size.  The default is typically about 128KB, which is much larger than
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 3328a92..4cd0d3a 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -28,6 +28,9 @@
         // We only care about compiling as C++14
         "-Wno-c++98-compat-pedantic",
 
+        // We are aware of the risks inherent in comparing floats for equality
+        "-Wno-float-equal",
+
         // We use four-character constants for the GraphicBuffer header, and don't care
         // that they're non-portable as long as they're consistent within one execution
         "-Wno-four-char-constants",
@@ -59,12 +62,9 @@
         "UiConfig.cpp",
     ],
 
-    static_libs: [
-        "android.hardware.graphics.mapper@2.0",
-    ],
-
     shared_libs: [
         "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
         "libbinder",
         "libcutils",
         "libhardware",
diff --git a/libs/ui/Gralloc1On0Adapter.cpp b/libs/ui/Gralloc1On0Adapter.cpp
index 111879a..a0bbe63 100644
--- a/libs/ui/Gralloc1On0Adapter.cpp
+++ b/libs/ui/Gralloc1On0Adapter.cpp
@@ -294,6 +294,7 @@
 gralloc1_error_t Gralloc1On0Adapter::retain(
         const std::shared_ptr<Buffer>& buffer)
 {
+    std::lock_guard<std::mutex> lock(mBufferMutex);
     buffer->retain();
     return GRALLOC1_ERROR_NONE;
 }
@@ -301,6 +302,7 @@
 gralloc1_error_t Gralloc1On0Adapter::release(
         const std::shared_ptr<Buffer>& buffer)
 {
+    std::lock_guard<std::mutex> lock(mBufferMutex);
     if (!buffer->release()) {
         return GRALLOC1_ERROR_NONE;
     }
@@ -320,7 +322,6 @@
         }
     }
 
-    std::lock_guard<std::mutex> lock(mBufferMutex);
     mBuffers.erase(handle);
     return GRALLOC1_ERROR_NONE;
 }
diff --git a/libs/ui/GrallocAllocator.cpp b/libs/ui/GrallocAllocator.cpp
index 021122a..ca67990 100644
--- a/libs/ui/GrallocAllocator.cpp
+++ b/libs/ui/GrallocAllocator.cpp
@@ -55,7 +55,7 @@
 
 Error Allocator::createBufferDescriptor(
         const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
-        BufferDescriptor& descriptor) const
+        BufferDescriptor* outDescriptor) const
 {
     Error error = kDefaultError;
     mClient->createDescriptor(descriptorInfo,
@@ -65,7 +65,7 @@
                     return;
                 }
 
-                descriptor = tmpDescriptor;
+                *outDescriptor = tmpDescriptor;
             });
 
     return error;
@@ -76,7 +76,8 @@
     mClient->destroyDescriptor(descriptor);
 }
 
-Error Allocator::allocate(BufferDescriptor descriptor, Buffer& buffer) const
+Error Allocator::allocate(BufferDescriptor descriptor,
+        Buffer* outBuffer) const
 {
     hardware::hidl_vec<BufferDescriptor> descriptors;
     descriptors.setToExternal(&descriptor, 1);
@@ -89,7 +90,7 @@
                     return;
                 }
 
-                buffer = tmpBuffers[0];
+                *outBuffer = tmpBuffers[0];
             });
 
     return error;
@@ -101,7 +102,7 @@
 }
 
 Error Allocator::exportHandle(BufferDescriptor descriptor, Buffer buffer,
-        native_handle_t*& bufferHandle) const
+        native_handle_t** outBufferHandle) const
 {
     Error error = kDefaultError;
     auto status = mClient->exportHandle(descriptor, buffer,
@@ -111,8 +112,8 @@
                     return;
                 }
 
-                bufferHandle = native_handle_clone(tmpBufferHandle);
-                if (!bufferHandle) {
+                *outBufferHandle = native_handle_clone(tmpBufferHandle);
+                if (!*outBufferHandle) {
                     error = Error::NO_RESOURCES;
                 }
             });
diff --git a/libs/ui/GrallocMapper.cpp b/libs/ui/GrallocMapper.cpp
index d568b68..b444871 100644
--- a/libs/ui/GrallocMapper.cpp
+++ b/libs/ui/GrallocMapper.cpp
@@ -26,85 +26,144 @@
 
 namespace Gralloc2 {
 
-typedef const void*(*FetchInterface)(const char* name);
-
-static FetchInterface loadHalLib(const char* pkg_name)
-{
-    static const std::array<const char*, 3> sSearchDirs = {{
-        HAL_LIBRARY_PATH_ODM,
-        HAL_LIBRARY_PATH_VENDOR,
-        HAL_LIBRARY_PATH_SYSTEM,
-    }};
-    static const char sSymbolName[] = "HALLIB_FETCH_Interface";
-
-    void* handle = nullptr;
-    std::string path;
-    for (auto dir : sSearchDirs) {
-        path = dir;
-        path += pkg_name;
-        path += ".hallib.so";
-        handle = dlopen(path.c_str(), RTLD_LOCAL | RTLD_NOW);
-        if (handle) {
-            break;
-        }
-    }
-    if (!handle) {
-        return nullptr;
-    }
-
-    void* symbol = dlsym(handle, sSymbolName);
-    if (!symbol) {
-        ALOGE("%s is missing from %s", sSymbolName, path.c_str());
-        dlclose(handle);
-        return nullptr;
-    }
-
-    return reinterpret_cast<FetchInterface>(symbol);
-}
+static constexpr Error kDefaultError = Error::NO_RESOURCES;
 
 Mapper::Mapper()
-    : mMapper(nullptr), mDevice(nullptr)
 {
-    static const char sHalLibName[] = "android.hardware.graphics.mapper";
-    static const char sSupportedInterface[] =
-        "android.hardware.graphics.mapper@2.0::IMapper";
-
-    FetchInterface fetchInterface = loadHalLib(sHalLibName);
-    if (!fetchInterface) {
-        return;
-    }
-
-    mMapper = static_cast<const IMapper*>(
-            fetchInterface(sSupportedInterface));
-    if (!mMapper) {
-        ALOGE("%s is not supported", sSupportedInterface);
-        return;
-    }
-
-    if (mMapper->createDevice(&mDevice) != Error::NONE) {
-        ALOGE("failed to create mapper device");
-        mMapper = nullptr;
+    mMapper = IMapper::getService("gralloc-mapper");
+    if (mMapper != nullptr && mMapper->isRemote()) {
+        LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
     }
 }
 
-Mapper::~Mapper()
+Error Mapper::retain(buffer_handle_t handle) const
 {
-    if (mMapper) {
-        mMapper->destroyDevice(mDevice);
-    }
+    auto ret = mMapper->retain(handle);
+    return (ret.isOk()) ? static_cast<Error>(ret) : kDefaultError;
 }
 
 void Mapper::release(buffer_handle_t handle) const
 {
-    auto error = mMapper->release(mDevice, handle);
+    auto ret = mMapper->release(handle);
+
+    auto error = (ret.isOk()) ? static_cast<Error>(ret) : kDefaultError;
     ALOGE_IF(error != Error::NONE,
             "release(%p) failed with %d", handle, error);
 }
 
+Error Mapper::getStride(buffer_handle_t handle, uint32_t* outStride) const
+{
+    Error error = kDefaultError;
+    mMapper->getStride(handle,
+            [&](const auto& tmpError, const auto& tmpStride)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                *outStride = tmpStride;
+            });
+
+    return error;
+}
+
+Error Mapper::lock(buffer_handle_t handle,
+        uint64_t producerUsageMask,
+        uint64_t consumerUsageMask,
+        const IMapper::Rect& accessRegion,
+        int acquireFence, void** outData) const
+{
+    hardware::hidl_handle acquireFenceHandle;
+
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
+
+    Error error = kDefaultError;
+    mMapper->lock(handle, producerUsageMask, consumerUsageMask,
+            accessRegion, acquireFenceHandle,
+            [&](const auto& tmpError, const auto& tmpData)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                *outData = tmpData;
+            });
+
+    if (error == Error::NONE && acquireFence >= 0) {
+        close(acquireFence);
+    }
+
+    return error;
+}
+
+Error Mapper::lock(buffer_handle_t handle,
+        uint64_t producerUsageMask,
+        uint64_t consumerUsageMask,
+        const IMapper::Rect& accessRegion,
+        int acquireFence, FlexLayout* outLayout) const
+{
+    hardware::hidl_handle acquireFenceHandle;
+
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
+
+    Error error = kDefaultError;
+    mMapper->lockFlex(handle, producerUsageMask, consumerUsageMask,
+            accessRegion, acquireFenceHandle,
+            [&](const auto& tmpError, const auto& tmpLayout)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                *outLayout = tmpLayout;
+            });
+
+    if (error == Error::NONE && acquireFence >= 0) {
+        close(acquireFence);
+    }
+
+    return error;
+}
+
 int Mapper::unlock(buffer_handle_t handle) const
 {
     int releaseFence;
-    auto error = mMapper->unlock(mDevice, handle, &releaseFence);
+
+    Error error = kDefaultError;
+    mMapper->unlock(handle,
+            [&](const auto& tmpError, const auto& tmpReleaseFence)
+            {
+                error = tmpError;
+                if (error != Error::NONE) {
+                    return;
+                }
+
+                auto fenceHandle = tmpReleaseFence.getNativeHandle();
+                if (fenceHandle && fenceHandle->numFds == 1) {
+                    int fd = dup(fenceHandle->data[0]);
+                    if (fd >= 0) {
+                        releaseFence = fd;
+                    } else {
+                        error = Error::NO_RESOURCES;
+                    }
+                } else {
+                    releaseFence = -1;
+                }
+            });
+
     if (error != Error::NONE) {
         ALOGE("unlock(%p) failed with %d", handle, error);
         releaseFence = -1;
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index d258586..6f57d37 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -18,7 +18,7 @@
 #define LOG_TAG "GraphicBufferAllocator"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include <cutils/log.h>
+#include <android/log.h>
 
 #include <utils/Singleton.h>
 #include <utils/String8.h>
@@ -115,14 +115,14 @@
         info.consumerUsageMask = usage;
 
         Gralloc2::BufferDescriptor descriptor;
-        auto error = mAllocator->createBufferDescriptor(info, descriptor);
+        auto error = mAllocator->createBufferDescriptor(info, &descriptor);
         if (error != Gralloc2::Error::NONE) {
             ALOGE("Failed to create desc (%u x %u) layerCount %u format %d usage %u: %d",
                     width, height, layerCount, format, usage, error);
             return;
         }
 
-        error = mAllocator->allocate(descriptor, mBuffer);
+        error = mAllocator->allocate(descriptor, &mBuffer);
         if (error == Gralloc2::Error::NOT_SHARED) {
             error = Gralloc2::Error::NONE;
         }
@@ -134,7 +134,7 @@
             return;
         }
 
-        error = mAllocator->exportHandle(descriptor, mBuffer, mHandle);
+        error = mAllocator->exportHandle(descriptor, mBuffer, &mHandle);
         if (error != Gralloc2::Error::NONE) {
             ALOGE("Failed to export handle");
             mAllocator->free(mBuffer);
@@ -172,7 +172,7 @@
 
         *handle = mHandle;
 
-        auto error = mapper.getGrallocMapper().getStride(mHandle, *stride);
+        auto error = mapper.getGrallocMapper().getStride(mHandle, stride);
         if (error != Gralloc2::Error::NONE) {
             ALOGW("Failed to get stride from buffer: %d", error);
             *stride = 0;
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index fb55bf1..1ff934b 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -148,10 +148,10 @@
     gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
     gralloc1_error_t error;
     if (mMapper->valid()) {
-        const Gralloc2::Device::Rect& accessRect =
-            *reinterpret_cast<Gralloc2::Device::Rect*>(&accessRegion);
+        const Gralloc2::IMapper::Rect& accessRect =
+            *reinterpret_cast<Gralloc2::IMapper::Rect*>(&accessRegion);
         error = static_cast<gralloc1_error_t>(mMapper->lock(
-                    handle, usage, usage, accessRect, fenceFd, *vaddr));
+                    handle, usage, usage, accessRect, fenceFd, vaddr));
     } else {
         sp<Fence> fence = new Fence(fenceFd);
         error = mDevice->lock(handle,
@@ -196,10 +196,32 @@
 
     gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
 
-    if (!mMapper->valid()) {
+    std::vector<android_flex_plane_t> planes;
+    android_flex_layout_t flexLayout{};
+    gralloc1_error_t error;
+
+    if (mMapper->valid()) {
+        const Gralloc2::IMapper::Rect& accessRect =
+            *reinterpret_cast<Gralloc2::IMapper::Rect*>(&accessRegion);
+        Gralloc2::FlexLayout layout{};
+        error = static_cast<gralloc1_error_t>(mMapper->lock(
+                    handle, usage, usage, accessRect, fenceFd, &layout));
+
+        if (error == GRALLOC1_ERROR_NONE) {
+            planes.resize(layout.planes.size());
+            memcpy(planes.data(), layout.planes.data(),
+                    sizeof(planes[0]) * planes.size());
+
+            flexLayout.format = static_cast<android_flex_format_t>(
+                    layout.format);
+            flexLayout.num_planes = static_cast<uint32_t>(planes.size());
+            flexLayout.planes = planes.data();
+        }
+    } else {
+        sp<Fence> fence = new Fence(fenceFd);
+
         if (mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
-            sp<Fence> fence = new Fence(fenceFd);
-            gralloc1_error_t error = mDevice->lockYCbCr(handle,
+            error = mDevice->lockYCbCr(handle,
                     static_cast<gralloc1_producer_usage_t>(usage),
                     static_cast<gralloc1_consumer_usage_t>(usage),
                     &accessRegion, ycbcr, fence);
@@ -207,40 +229,23 @@
                     "lockYCbCr(%p, ...) failed: %d", handle, error);
             return error;
         }
-    }
 
-    uint32_t numPlanes = 0;
-    gralloc1_error_t error;
-    if (mMapper->valid()) {
-        error = static_cast<gralloc1_error_t>(
-                mMapper->getNumFlexPlanes(handle, numPlanes));
-    } else {
+        uint32_t numPlanes = 0;
         error = mDevice->getNumFlexPlanes(handle, &numPlanes);
-    }
 
-    if (error != GRALLOC1_ERROR_NONE) {
-        ALOGV("Failed to retrieve number of flex planes: %d", error);
-        return error;
-    }
-    if (numPlanes < 3) {
-        ALOGV("Not enough planes for YCbCr (%u found)", numPlanes);
-        return GRALLOC1_ERROR_UNSUPPORTED;
-    }
+        if (error != GRALLOC1_ERROR_NONE) {
+            ALOGV("Failed to retrieve number of flex planes: %d", error);
+            return error;
+        }
+        if (numPlanes < 3) {
+            ALOGV("Not enough planes for YCbCr (%u found)", numPlanes);
+            return GRALLOC1_ERROR_UNSUPPORTED;
+        }
 
-    std::vector<android_flex_plane_t> planes(numPlanes);
-    android_flex_layout_t flexLayout{};
-    flexLayout.num_planes = numPlanes;
-    flexLayout.planes = planes.data();
+        planes.resize(numPlanes);
+        flexLayout.num_planes = numPlanes;
+        flexLayout.planes = planes.data();
 
-    if (mMapper->valid()) {
-        const Gralloc2::Device::Rect& accessRect =
-            *reinterpret_cast<Gralloc2::Device::Rect*>(&accessRegion);
-        Gralloc2::FlexLayout& layout =
-            *reinterpret_cast<Gralloc2::FlexLayout*>(&flexLayout);
-        error = static_cast<gralloc1_error_t>(mMapper->lock(
-                    handle, usage, usage, accessRect, fenceFd, layout));
-    } else {
-        sp<Fence> fence = new Fence(fenceFd);
         error = mDevice->lockFlex(handle,
                 static_cast<gralloc1_producer_usage_t>(usage),
                 static_cast<gralloc1_consumer_usage_t>(usage),
diff --git a/libs/ui/PixelFormat.cpp b/libs/ui/PixelFormat.cpp
index cab1dde..734472d 100644
--- a/libs/ui/PixelFormat.cpp
+++ b/libs/ui/PixelFormat.cpp
@@ -22,6 +22,8 @@
 
 uint32_t bytesPerPixel(PixelFormat format) {
     switch (format) {
+        case PIXEL_FORMAT_RGBA_FP16:
+            return 8;
         case PIXEL_FORMAT_RGBA_8888:
         case PIXEL_FORMAT_RGBX_8888:
         case PIXEL_FORMAT_BGRA_8888:
@@ -38,6 +40,8 @@
 
 uint32_t bitsPerPixel(PixelFormat format) {
     switch (format) {
+        case PIXEL_FORMAT_RGBA_FP16:
+            return 64;
         case PIXEL_FORMAT_RGBA_8888:
         case PIXEL_FORMAT_RGBX_8888:
         case PIXEL_FORMAT_BGRA_8888:
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 73e5e07..874e712 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -643,8 +643,8 @@
 EGLAPI EGLBoolean eglGetFrameTimestampsANDROID(EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
 EGLAPI EGLBoolean eglQueryTimestampSupportedANDROID(EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
 #else
-typedef EGLAPI EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
-typedef EGLAPI EGLBoolean (EGLAPIENTRYP PFNEGLQUERYTIMESTAMPSUPPORTEDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETFRAMETIMESTAMPSANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint framesAgo, EGLint numTimestamps, const EGLint *timestamps, EGLnsecsANDROID *values);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYTIMESTAMPSUPPORTEDANDROID) (EGLDisplay dpy, EGLSurface surface, EGLint timestamp);
 #endif
 #endif
 
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index c1efd1c..4e9cb5b 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -18,16 +18,16 @@
 #include <assert.h>
 #include <atomic>
 #include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
 #include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/ioctl.h>
 #include <sys/types.h>
 #include <sys/mman.h>
+#include <unistd.h>
 
-#include <cutils/log.h>
+#include <android/log.h>
 
 #include <utils/threads.h>
 #include <ui/ANativeObjectBase.h>
@@ -1459,6 +1459,9 @@
     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 
+    if (ggl_unlikely(num_config==NULL))
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+
     GLint numConfigs = NELEM(gConfigs);
     if (!configs) {
         *num_config = numConfigs;
@@ -1478,8 +1481,8 @@
 {
     if (egl_display_t::is_valid(dpy) == EGL_FALSE)
         return setError(EGL_BAD_DISPLAY, EGL_FALSE);
-    
-    if (ggl_unlikely(num_config==0)) {
+
+    if (ggl_unlikely(num_config==NULL)) {
         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
     }
 
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 6a8aac8..60c4b36 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -26,24 +26,28 @@
     name: "libEGL.ndk",
     symbol_file: "libEGL.map.txt",
     first_version: "9",
+    unversioned_until: "current",
 }
 
 ndk_library {
     name: "libGLESv1_CM.ndk",
     symbol_file: "libGLESv1_CM.map.txt",
     first_version: "9",
+    unversioned_until: "current",
 }
 
 ndk_library {
     name: "libGLESv2.ndk",
     symbol_file: "libGLESv2.map.txt",
     first_version: "9",
+    unversioned_until: "current",
 }
 
 ndk_library {
     name: "libGLESv3.ndk",
     symbol_file: "libGLESv3.map.txt",
     first_version: "18",
+    unversioned_until: "current",
 }
 
 cc_defaults {
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 49f501d..27d81fe 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -15,15 +15,15 @@
  */
 
 #include <ctype.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <dlfcn.h>
-#include <limits.h>
 #include <dirent.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
-#include <cutils/log.h>
+#include <android/log.h>
 #include <cutils/properties.h>
 
 #include <EGL/egl.h>
@@ -98,24 +98,6 @@
 
 // ----------------------------------------------------------------------------
 
-static char const * getProcessCmdline() {
-    long pid = getpid();
-    char procPath[128];
-    snprintf(procPath, 128, "/proc/%ld/cmdline", pid);
-    FILE * file = fopen(procPath, "r");
-    if (file) {
-        static char cmdline[256];
-        char *str = fgets(cmdline, sizeof(cmdline) - 1, file);
-        fclose(file);
-        if (str) {
-            return cmdline;
-        }
-    }
-    return NULL;
-}
-
-// ----------------------------------------------------------------------------
-
 Loader::driver_t::driver_t(void* gles)
 {
     dso[0] = gles;
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 18cf261..4245a92 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -24,7 +24,7 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
-#include <cutils/log.h>
+#include <android/log.h>
 #include <cutils/atomic.h>
 #include <cutils/properties.h>
 
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 71538d6..3af7e93 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -16,8 +16,8 @@
 
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include <dlfcn.h>
 #include <ctype.h>
+#include <dlfcn.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -27,11 +27,11 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
-#include <cutils/log.h>
+#include <android/log.h>
 #include <cutils/atomic.h>
 #include <cutils/compiler.h>
-#include <cutils/properties.h>
 #include <cutils/memory.h>
+#include <cutils/properties.h>
 
 #include <gui/ISurfaceComposer.h>
 
@@ -476,6 +476,7 @@
         // modify the EGLconfig's format before setting the native window's
         // format.
 
+        // TODO: Add support for HAL_PIXEL_FORMAT_RGBA_FP16
         // by default, just pick RGBA_8888
         EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
         android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
diff --git a/opengl/libs/EGL/egl_tls.cpp b/opengl/libs/EGL/egl_tls.cpp
index f3739aa..1257004 100644
--- a/opengl/libs/EGL/egl_tls.cpp
+++ b/opengl/libs/EGL/egl_tls.cpp
@@ -14,10 +14,10 @@
  ** limitations under the License.
  */
 
-#include <stdlib.h>
 #include <pthread.h>
+#include <stdlib.h>
 
-#include <cutils/log.h>
+#include <android/log.h>
 #include <cutils/properties.h>
 
 #include <utils/CallStack.h>
@@ -26,7 +26,6 @@
 
 #include "egl_tls.h"
 
-
 namespace android {
 
 pthread_key_t egl_tls_t::sKey = TLS_KEY_NOT_INITIALIZED;
diff --git a/opengl/libs/EGL/getProcAddress.cpp b/opengl/libs/EGL/getProcAddress.cpp
index 336c264..450c402 100644
--- a/opengl/libs/EGL/getProcAddress.cpp
+++ b/opengl/libs/EGL/getProcAddress.cpp
@@ -15,10 +15,10 @@
  */
 
 #include <ctype.h>
-#include <stdlib.h>
 #include <errno.h>
+#include <stdlib.h>
 
-#include <cutils/log.h>
+#include <android/log.h>
 
 #include "egldefs.h"
 
diff --git a/opengl/libs/GLES2/gl2.cpp b/opengl/libs/GLES2/gl2.cpp
index 6dd87c2..c206041 100644
--- a/opengl/libs/GLES2/gl2.cpp
+++ b/opengl/libs/GLES2/gl2.cpp
@@ -15,12 +15,11 @@
  */
 
 #include <ctype.h>
-#include <string.h>
 #include <errno.h>
-
+#include <string.h>
 #include <sys/ioctl.h>
 
-#include <cutils/log.h>
+#include <android/log.h>
 #include <cutils/properties.h>
 
 #include "../hooks.h"
diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp
index 8bde4e5..e698fcd 100644
--- a/opengl/libs/GLES_CM/gl.cpp
+++ b/opengl/libs/GLES_CM/gl.cpp
@@ -1,31 +1,30 @@
-/* 
+/*
  ** Copyright 2007, 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 
+ ** 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 
+ **     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 
+ ** 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 <ctype.h>
-#include <string.h>
 #include <errno.h>
-
+#include <string.h>
 #include <sys/ioctl.h>
 
+#include <android/log.h>
+#include <cutils/properties.h>
+
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
-#include <cutils/log.h>
-#include <cutils/properties.h>
-
 #include "../hooks.h"
 #include "../egl_impl.h"
 
diff --git a/services/audiomanager/Android.bp b/services/audiomanager/Android.bp
new file mode 100644
index 0000000..04dd967
--- /dev/null
+++ b/services/audiomanager/Android.bp
@@ -0,0 +1,18 @@
+cc_library_shared {
+    name: "libaudiomanager",
+
+    srcs: ["IAudioManager.cpp"],
+
+    shared_libs: [
+        "libutils",
+        "libbinder",
+        "liblog",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wunused",
+        "-Wunreachable-code",
+    ],
+}
diff --git a/services/audiomanager/IAudioManager.cpp b/services/audiomanager/IAudioManager.cpp
new file mode 100644
index 0000000..a41804f
--- /dev/null
+++ b/services/audiomanager/IAudioManager.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "IAudioManager"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <binder/Parcel.h>
+#include <audiomanager/AudioManager.h>
+#include <audiomanager/IAudioManager.h>
+
+namespace android {
+
+class BpAudioManager : public BpInterface<IAudioManager>
+{
+public:
+    explicit BpAudioManager(const sp<IBinder>& impl)
+        : BpInterface<IAudioManager>(impl)
+    {
+    }
+
+    virtual audio_unique_id_t trackPlayer(int playerType, int usage, int content) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
+        data.writeInt32(1); // non-null PlayerIdCard parcelable
+        // marshall PlayerIdCard data
+        data.writeInt32((int32_t) playerType);
+        //   write attributes of PlayerIdCard
+        data.writeInt32(usage);
+        data.writeInt32(content);
+        data.writeInt32(0 /*source: none here, this is a player*/);
+        data.writeInt32(0 /*flags*/);
+        //   write attributes' tags
+        data.writeInt32(1 /*FLATTEN_TAGS*/);
+        data.writeString16(String16("")); // no tags
+        //   write attributes' bundle
+        data.writeInt32(-1977 /*ATTR_PARCEL_IS_NULL_BUNDLE*/); // no bundle
+        // get new PIId in reply
+        const status_t res = remote()->transact(TRACK_PLAYER, data, &reply, 0);
+        if (res != OK || reply.readExceptionCode() != 0) {
+            ALOGE("trackPlayer() failed, piid is %d", PLAYER_PIID_INVALID);
+            return PLAYER_PIID_INVALID;
+        } else {
+            const audio_unique_id_t piid = (audio_unique_id_t) reply.readInt32();
+            ALOGV("trackPlayer() returned piid %d", piid);
+            return piid;
+        }
+    }
+
+    virtual status_t playerAttributes(audio_unique_id_t piid, int usage, int content) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
+        data.writeInt32(piid);
+        data.writeInt32(1); // non-null AudioAttributes parcelable
+        data.writeInt32(usage);
+        data.writeInt32(content);
+        data.writeInt32(0 /*source: none here, this is a player*/);
+        data.writeInt32(0 /*flags*/);
+        //   write attributes' tags
+        data.writeInt32(1 /*FLATTEN_TAGS*/);
+        data.writeString16(String16("")); // no tags
+        //   write attributes' bundle
+        data.writeInt32(-1977 /*ATTR_PARCEL_IS_NULL_BUNDLE*/); // no bundle
+        return remote()->transact(PLAYER_ATTRIBUTES, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    virtual status_t playerEvent(int piid, int event) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
+        data.writeInt32(piid);
+        data.writeInt32(event);
+        return remote()->transact(PLAYER_EVENT, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    virtual status_t releasePlayer(int piid) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
+        data.writeInt32(piid);
+        return remote()->transact(RELEASE_PLAYER, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(AudioManager, "android.media.IAudioService");
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/services/batteryservice/BatteryProperties.cpp b/services/batteryservice/BatteryProperties.cpp
index d89d4c9..8fa111d 100644
--- a/services/batteryservice/BatteryProperties.cpp
+++ b/services/batteryservice/BatteryProperties.cpp
@@ -41,6 +41,7 @@
     batteryLevel = p->readInt32();
     batteryVoltage = p->readInt32();
     batteryTemperature = p->readInt32();
+    batteryFullCharge = p->readInt32();
     batteryChargeCounter = p->readInt32();
     batteryTechnology = String8((p->readString16()).string());
     return OK;
@@ -58,6 +59,7 @@
     p->writeInt32(batteryLevel);
     p->writeInt32(batteryVoltage);
     p->writeInt32(batteryTemperature);
+    p->writeInt32(batteryFullCharge);
     p->writeInt32(batteryChargeCounter);
     p->writeString16(String16(batteryTechnology));
     return OK;
diff --git a/services/inputflinger/InputApplication.cpp b/services/inputflinger/InputApplication.cpp
index a99e637..9e90631 100644
--- a/services/inputflinger/InputApplication.cpp
+++ b/services/inputflinger/InputApplication.cpp
@@ -18,7 +18,7 @@
 
 #include "InputApplication.h"
 
-#include <cutils/log.h>
+#include <android/log.h>
 
 namespace android {
 
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 3f69d49..793d59a 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -45,16 +45,16 @@
 
 #include "InputDispatcher.h"
 
-#include <utils/Trace.h>
-#include <cutils/log.h>
-#include <powermanager/PowerManager.h>
-#include <ui/Region.h>
-
-#include <stddef.h>
-#include <unistd.h>
 #include <errno.h>
 #include <limits.h>
+#include <stddef.h>
 #include <time.h>
+#include <unistd.h>
+
+#include <android/log.h>
+#include <utils/Trace.h>
+#include <powermanager/PowerManager.h>
+#include <ui/Region.h>
 
 #define INDENT "  "
 #define INDENT2 "    "
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index dded47d..2ee222b 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -20,7 +20,7 @@
 
 #include "InputListener.h"
 
-#include <cutils/log.h>
+#include <android/log.h>
 
 namespace android {
 
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 6a6547b..6fe4d36 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -20,7 +20,7 @@
 
 #include "InputManager.h"
 
-#include <cutils/log.h>
+#include <android/log.h>
 
 namespace android {
 
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 4dec34b..fbc7b12 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -44,17 +44,18 @@
 
 #include "InputReader.h"
 
-#include <cutils/log.h>
-#include <input/Keyboard.h>
-#include <input/VirtualKeyMap.h>
-
+#include <errno.h>
 #include <inttypes.h>
+#include <limits.h>
+#include <math.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <math.h>
+
+#include <android/log.h>
+
+#include <input/Keyboard.h>
+#include <input/VirtualKeyMap.h>
 
 #define INDENT "  "
 #define INDENT2 "    "
diff --git a/services/inputflinger/InputWindow.cpp b/services/inputflinger/InputWindow.cpp
index d7b514b..297b068 100644
--- a/services/inputflinger/InputWindow.cpp
+++ b/services/inputflinger/InputWindow.cpp
@@ -19,7 +19,7 @@
 
 #include "InputWindow.h"
 
-#include <cutils/log.h>
+#include <android/log.h>
 
 #include <ui/Rect.h>
 #include <ui/Region.h>
diff --git a/services/inputflinger/host/InputFlinger.cpp b/services/inputflinger/host/InputFlinger.cpp
index 859c3b8..8edea3f 100644
--- a/services/inputflinger/host/InputFlinger.cpp
+++ b/services/inputflinger/host/InputFlinger.cpp
@@ -16,21 +16,19 @@
 
 #define LOG_TAG "InputFlinger"
 
-
 #include <stdint.h>
+#include <sys/types.h>
 #include <unistd.h>
 
-#include <sys/types.h>
-
-#include "InputFlinger.h"
-#include "InputDriver.h"
-
+#include <android/log.h>
 #include <binder/IPCThreadState.h>
 #include <binder/PermissionCache.h>
 #include <hardware/input.h>
-#include <cutils/log.h>
 #include <private/android_filesystem_config.h>
 
+#include "InputFlinger.h"
+#include "InputDriver.h"
+
 namespace android {
 
 const String16 sAccessInputFlingerPermission("android.permission.ACCESS_INPUT_FLINGER");
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 7b47709..2e44736 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -868,7 +868,7 @@
     }
 }
 
-Vector<Sensor> SensorService::getSensorList(const String16& opPackageName) {
+Vector<Sensor> SensorService::getSensorList(const String16& /* opPackageName */) {
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.sensors", value, "0");
     const Vector<Sensor>& initialSensorList = (atoi(value)) ?
@@ -876,14 +876,7 @@
     Vector<Sensor> accessibleSensorList;
     for (size_t i = 0; i < initialSensorList.size(); i++) {
         Sensor sensor = initialSensorList[i];
-        if (canAccessSensor(sensor, "getSensorList", opPackageName)) {
-            accessibleSensorList.add(sensor);
-        } else {
-            ALOGI("Skipped sensor %s because it requires permission %s and app op %d",
-                  sensor.getName().string(),
-                  sensor.getRequiredPermission().string(),
-                  sensor.getRequiredAppOp());
-        }
+        accessibleSensorList.add(sensor);
     }
     makeUuidsIntoIdsForSensorList(accessibleSensorList);
     return accessibleSensorList;
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 20fe0fd..fcc9241 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -42,6 +42,7 @@
 LOCAL_C_INCLUDES := \
     frameworks/native/vulkan/include \
     external/vulkan-validation-layers/libs/vkjson \
+    system/libhwbinder/fast_msgq/include \
 
 LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
@@ -68,10 +69,6 @@
     LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
 endif
 
-ifeq ($(TARGET_DISABLE_TRIPLE_BUFFERING),true)
-    LOCAL_CFLAGS += -DTARGET_DISABLE_TRIPLE_BUFFERING
-endif
-
 ifeq ($(TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS),true)
     LOCAL_CFLAGS += -DFORCE_HWC_COPY_FOR_VIRTUAL_DISPLAYS
 endif
@@ -130,13 +127,14 @@
 
 LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
 
-LOCAL_STATIC_LIBRARIES := libtrace_proto libvkjson
+LOCAL_STATIC_LIBRARIES := libhwcomposer-command-buffer libtrace_proto libvkjson
 LOCAL_SHARED_LIBRARIES := \
     android.hardware.graphics.allocator@2.0 \
     android.hardware.graphics.composer@2.1 \
     libcutils \
     liblog \
     libdl \
+    libfmq \
     libhardware \
     libhidlbase \
     libhidltransport \
@@ -150,6 +148,7 @@
     libgui \
     libpowermanager \
     libvulkan \
+    libsync \
     libprotobuf-cpp-lite \
     libbase \
     android.hardware.power@1.0
diff --git a/services/surfaceflinger/DdmConnection.cpp b/services/surfaceflinger/DdmConnection.cpp
index 659c2c8..ba09b36 100644
--- a/services/surfaceflinger/DdmConnection.cpp
+++ b/services/surfaceflinger/DdmConnection.cpp
@@ -15,8 +15,10 @@
  */
 
 #include <dlfcn.h>
+#include <sys/types.h>
+#include <unistd.h>
 
-#include <cutils/log.h>
+#include <android/log.h>
 
 #include "jni.h"
 #include "DdmConnection.h"
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index 836fb89..3229b66 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -22,20 +22,19 @@
 
 #include <math.h>
 
-#include <cutils/log.h>
+#include <algorithm>
 
-#include <ui/Fence.h>
-
+#include <android/log.h>
 #include <utils/String8.h>
 #include <utils/Thread.h>
 #include <utils/Trace.h>
 #include <utils/Vector.h>
 
+#include <ui/Fence.h>
+
 #include "DispSync.h"
 #include "EventLog/EventLog.h"
 
-#include <algorithm>
-
 using std::max;
 using std::min;
 
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 06f67ba..b952fd7 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -91,7 +91,7 @@
 template<typename T, typename U>
 T unwrapRet(Return<T>& ret, const U& default_val)
 {
-    return (ret.getStatus().isOk()) ? static_cast<T>(ret) :
+    return (ret.isOk()) ? static_cast<T>(ret) :
         static_cast<T>(default_val);
 }
 
@@ -100,63 +100,69 @@
     return unwrapRet(ret, kDefaultError);
 }
 
-template<typename T>
-void assignFromHidlVec(std::vector<T>& vec, const hidl_vec<T>& data)
-{
-    vec.clear();
-    vec.insert(vec.begin(), &data[0], &data[data.size()]);
-}
-
 } // anonymous namespace
 
 Composer::Composer()
+    : mWriter(kWriterInitialSize)
 {
-    mService = IComposer::getService("hwcomposer");
-    if (mService == nullptr) {
+    mComposer = IComposer::getService("hwcomposer");
+    if (mComposer == nullptr) {
         LOG_ALWAYS_FATAL("failed to get hwcomposer service");
     }
+
+    mComposer->createClient(
+            [&](const auto& tmpError, const auto& tmpClient)
+            {
+                if (tmpError == Error::NONE) {
+                    mClient = tmpClient;
+                }
+            });
+    if (mClient == nullptr) {
+        LOG_ALWAYS_FATAL("failed to create composer client");
+    }
 }
 
-std::vector<IComposer::Capability> Composer::getCapabilities() const
+std::vector<IComposer::Capability> Composer::getCapabilities()
 {
     std::vector<IComposer::Capability> capabilities;
-    mService->getCapabilities(
+    mComposer->getCapabilities(
             [&](const auto& tmpCapabilities) {
-                assignFromHidlVec(capabilities, tmpCapabilities);
+                capabilities = tmpCapabilities;
             });
 
     return capabilities;
 }
 
-std::string Composer::dumpDebugInfo() const
+std::string Composer::dumpDebugInfo()
 {
     std::string info;
-    mService->dumpDebugInfo([&](const auto& tmpInfo) {
+    mComposer->dumpDebugInfo([&](const auto& tmpInfo) {
         info = tmpInfo.c_str();
     });
 
     return info;
 }
 
-void Composer::registerCallback(const sp<IComposerCallback>& callback) const
+void Composer::registerCallback(const sp<IComposerCallback>& callback)
 {
-    auto ret = mService->registerCallback(callback);
-    if (!ret.getStatus().isOk()) {
+    auto ret = mClient->registerCallback(callback);
+    if (!ret.isOk()) {
         ALOGE("failed to register IComposerCallback");
     }
 }
 
-uint32_t Composer::getMaxVirtualDisplayCount() const
+uint32_t Composer::getMaxVirtualDisplayCount()
 {
-    auto ret = mService->getMaxVirtualDisplayCount();
+    auto ret = mClient->getMaxVirtualDisplayCount();
     return unwrapRet(ret, 0);
 }
 
 Error Composer::createVirtualDisplay(uint32_t width, uint32_t height,
-            PixelFormat& format, Display& display) const
+            PixelFormat* format, Display* outDisplay)
 {
+    const uint32_t bufferSlotCount = 1;
     Error error = kDefaultError;
-    mService->createVirtualDisplay(width, height, format,
+    mClient->createVirtualDisplay(width, height, *format, bufferSlotCount,
             [&](const auto& tmpError, const auto& tmpDisplay,
                 const auto& tmpFormat) {
                 error = tmpError;
@@ -164,209 +170,188 @@
                     return;
                 }
 
-                display = tmpDisplay;
-                format = tmpFormat;
+                *outDisplay = tmpDisplay;
+                *format = tmpFormat;
             });
 
     return error;
 }
 
-Error Composer::destroyVirtualDisplay(Display display) const
+Error Composer::destroyVirtualDisplay(Display display)
 {
-    auto ret = mService->destroyVirtualDisplay(display);
+    auto ret = mClient->destroyVirtualDisplay(display);
     return unwrapRet(ret);
 }
 
-Error Composer::acceptDisplayChanges(Display display) const
+Error Composer::acceptDisplayChanges(Display display)
 {
-    auto ret = mService->acceptDisplayChanges(display);
-    return unwrapRet(ret);
+    mWriter.selectDisplay(display);
+    mWriter.acceptDisplayChanges();
+    return Error::NONE;
 }
 
-Error Composer::createLayer(Display display, Layer& layer) const
+Error Composer::createLayer(Display display, Layer* outLayer)
 {
+    const uint32_t bufferSlotCount = 1;
     Error error = kDefaultError;
-    mService->createLayer(display,
+    mClient->createLayer(display, bufferSlotCount,
             [&](const auto& tmpError, const auto& tmpLayer) {
                 error = tmpError;
                 if (error != Error::NONE) {
                     return;
                 }
 
-                layer = tmpLayer;
+                *outLayer = tmpLayer;
             });
 
     return error;
 }
 
-Error Composer::destroyLayer(Display display, Layer layer) const
+Error Composer::destroyLayer(Display display, Layer layer)
 {
-    auto ret = mService->destroyLayer(display, layer);
+    auto ret = mClient->destroyLayer(display, layer);
     return unwrapRet(ret);
 }
 
-Error Composer::getActiveConfig(Display display, Config& config) const
+Error Composer::getActiveConfig(Display display, Config* outConfig)
 {
     Error error = kDefaultError;
-    mService->getActiveConfig(display,
+    mClient->getActiveConfig(display,
             [&](const auto& tmpError, const auto& tmpConfig) {
                 error = tmpError;
                 if (error != Error::NONE) {
                     return;
                 }
 
-                config = tmpConfig;
+                *outConfig = tmpConfig;
             });
 
     return error;
 }
 
 Error Composer::getChangedCompositionTypes(Display display,
-        std::vector<Layer>& layers,
-        std::vector<IComposer::Composition>& types) const
+        std::vector<Layer>* outLayers,
+        std::vector<IComposerClient::Composition>* outTypes)
 {
-    Error error = kDefaultError;
-    mService->getChangedCompositionTypes(display,
-            [&](const auto& tmpError, const auto& tmpLayers,
-                const auto& tmpTypes) {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                assignFromHidlVec(layers, tmpLayers);
-                assignFromHidlVec(types, tmpTypes);
-            });
-
-    return error;
+    mReader.takeChangedCompositionTypes(display, outLayers, outTypes);
+    return Error::NONE;
 }
 
 Error Composer::getColorModes(Display display,
-        std::vector<ColorMode>& modes) const
+        std::vector<ColorMode>* outModes)
 {
     Error error = kDefaultError;
-    mService->getColorModes(display,
+    mClient->getColorModes(display,
             [&](const auto& tmpError, const auto& tmpModes) {
                 error = tmpError;
                 if (error != Error::NONE) {
                     return;
                 }
 
-                assignFromHidlVec(modes, tmpModes);
+                *outModes = tmpModes;
             });
 
     return error;
 }
 
 Error Composer::getDisplayAttribute(Display display, Config config,
-        IComposer::Attribute attribute, int32_t& value) const
+        IComposerClient::Attribute attribute, int32_t* outValue)
 {
     Error error = kDefaultError;
-    mService->getDisplayAttribute(display, config, attribute,
+    mClient->getDisplayAttribute(display, config, attribute,
             [&](const auto& tmpError, const auto& tmpValue) {
                 error = tmpError;
                 if (error != Error::NONE) {
                     return;
                 }
 
-                value = tmpValue;
+                *outValue = tmpValue;
             });
 
     return error;
 }
 
 Error Composer::getDisplayConfigs(Display display,
-        std::vector<Config>& configs) const
+        std::vector<Config>* outConfigs)
 {
     Error error = kDefaultError;
-    mService->getDisplayConfigs(display,
+    mClient->getDisplayConfigs(display,
             [&](const auto& tmpError, const auto& tmpConfigs) {
                 error = tmpError;
                 if (error != Error::NONE) {
                     return;
                 }
 
-                assignFromHidlVec(configs, tmpConfigs);
+                *outConfigs = tmpConfigs;
             });
 
     return error;
 }
 
-Error Composer::getDisplayName(Display display, std::string& name) const
+Error Composer::getDisplayName(Display display, std::string* outName)
 {
     Error error = kDefaultError;
-    mService->getDisplayName(display,
+    mClient->getDisplayName(display,
             [&](const auto& tmpError, const auto& tmpName) {
                 error = tmpError;
                 if (error != Error::NONE) {
                     return;
                 }
 
-                name = tmpName.c_str();
+                *outName = tmpName.c_str();
             });
 
     return error;
 }
 
 Error Composer::getDisplayRequests(Display display,
-        uint32_t& displayRequestMask, std::vector<Layer>& layers,
-        std::vector<uint32_t>& layerRequestMasks) const
+        uint32_t* outDisplayRequestMask, std::vector<Layer>* outLayers,
+        std::vector<uint32_t>* outLayerRequestMasks)
 {
-    Error error = kDefaultError;
-    mService->getDisplayRequests(display,
-            [&](const auto& tmpError, const auto& tmpDisplayRequestMask,
-                const auto& tmpLayers, const auto& tmpLayerRequestMasks) {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                displayRequestMask = tmpDisplayRequestMask;
-                assignFromHidlVec(layers, tmpLayers);
-                assignFromHidlVec(layerRequestMasks, tmpLayerRequestMasks);
-            });
-
-    return error;
+    mReader.takeDisplayRequests(display, outDisplayRequestMask,
+            outLayers, outLayerRequestMasks);
+    return Error::NONE;
 }
 
-Error Composer::getDisplayType(Display display, IComposer::DisplayType& type) const
+Error Composer::getDisplayType(Display display,
+        IComposerClient::DisplayType* outType)
 {
     Error error = kDefaultError;
-    mService->getDisplayType(display,
+    mClient->getDisplayType(display,
             [&](const auto& tmpError, const auto& tmpType) {
                 error = tmpError;
                 if (error != Error::NONE) {
                     return;
                 }
 
-                type = tmpType;
+                *outType = tmpType;
             });
 
     return error;
 }
 
-Error Composer::getDozeSupport(Display display, bool& support) const
+Error Composer::getDozeSupport(Display display, bool* outSupport)
 {
     Error error = kDefaultError;
-    mService->getDozeSupport(display,
+    mClient->getDozeSupport(display,
             [&](const auto& tmpError, const auto& tmpSupport) {
                 error = tmpError;
                 if (error != Error::NONE) {
                     return;
                 }
 
-                support = tmpSupport;
+                *outSupport = tmpSupport;
             });
 
     return error;
 }
 
-Error Composer::getHdrCapabilities(Display display, std::vector<Hdr>& types,
-        float& maxLuminance, float& maxAverageLuminance,
-        float& minLuminance) const
+Error Composer::getHdrCapabilities(Display display,
+        std::vector<Hdr>* outTypes, float* outMaxLuminance,
+        float* outMaxAverageLuminance, float* outMinLuminance)
 {
     Error error = kDefaultError;
-    mService->getHdrCapabilities(display,
+    mClient->getHdrCapabilities(display,
             [&](const auto& tmpError, const auto& tmpTypes,
                 const auto& tmpMaxLuminance,
                 const auto& tmpMaxAverageLuminance,
@@ -376,276 +361,584 @@
                     return;
                 }
 
-                assignFromHidlVec(types, tmpTypes);
-                maxLuminance = tmpMaxLuminance;
-                maxAverageLuminance = tmpMaxAverageLuminance;
-                minLuminance = tmpMinLuminance;
+                *outTypes = tmpTypes;
+                *outMaxLuminance = tmpMaxLuminance;
+                *outMaxAverageLuminance = tmpMaxAverageLuminance;
+                *outMinLuminance = tmpMinLuminance;
             });
 
     return error;
 }
 
-Error Composer::getReleaseFences(Display display, std::vector<Layer>& layers,
-        std::vector<int>& releaseFences) const
+Error Composer::getReleaseFences(Display display,
+        std::vector<Layer>* outLayers, std::vector<int>* outReleaseFences)
 {
-    Error error = kDefaultError;
-    mService->getReleaseFences(display,
-            [&](const auto& tmpError, const auto& tmpLayers,
-                const auto& tmpReleaseFences) {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
-
-                if (static_cast<int>(tmpLayers.size()) !=
-                        tmpReleaseFences->numFds) {
-                    ALOGE("invalid releaseFences outputs: "
-                          "layer count %zu != fence count %d",
-                          tmpLayers.size(), tmpReleaseFences->numFds);
-                    error = Error::NO_RESOURCES;
-                    return;
-                }
-
-                // dup the file descriptors
-                std::vector<int> tmpFds;
-                tmpFds.reserve(tmpReleaseFences->numFds);
-                for (int i = 0; i < tmpReleaseFences->numFds; i++) {
-                    int fd = dup(tmpReleaseFences->data[i]);
-                    if (fd < 0) {
-                        break;
-                    }
-                    tmpFds.push_back(fd);
-                }
-                if (static_cast<int>(tmpFds.size()) <
-                        tmpReleaseFences->numFds) {
-                    for (auto fd : tmpFds) {
-                        close(fd);
-                    }
-
-                    error = Error::NO_RESOURCES;
-                    return;
-                }
-
-                assignFromHidlVec(layers, tmpLayers);
-                releaseFences = std::move(tmpFds);
-            });
-
-    return error;
+    mReader.takeReleaseFences(display, outLayers, outReleaseFences);
+    return Error::NONE;
 }
 
-Error Composer::presentDisplay(Display display, int& presentFence) const
+Error Composer::presentDisplay(Display display, int* outPresentFence)
 {
-    Error error = kDefaultError;
-    mService->presentDisplay(display,
-            [&](const auto& tmpError, const auto& tmpPresentFence) {
-                error = tmpError;
-                if (error != Error::NONE) {
-                    return;
-                }
+    mWriter.selectDisplay(display);
+    mWriter.presentDisplay();
 
-                if (tmpPresentFence->numFds == 1) {
-                    int fd = dup(tmpPresentFence->data[0]);
-                    if (fd >= 0) {
-                        presentFence = fd;
-                    } else {
-                        error = Error::NO_RESOURCES;
-                    }
-                } else {
-                    presentFence = -1;
-                }
-            });
+    Error error = execute();
+    if (error != Error::NONE) {
+        return error;
+    }
 
-    return error;
+    mReader.takePresentFence(display, outPresentFence);
+
+    return Error::NONE;
 }
 
-Error Composer::setActiveConfig(Display display, Config config) const
+Error Composer::setActiveConfig(Display display, Config config)
 {
-    auto ret = mService->setActiveConfig(display, config);
+    auto ret = mClient->setActiveConfig(display, config);
     return unwrapRet(ret);
 }
 
 Error Composer::setClientTarget(Display display, const native_handle_t* target,
         int acquireFence, Dataspace dataspace,
-        const std::vector<IComposer::Rect>& damage) const
+        const std::vector<IComposerClient::Rect>& damage)
 {
-    BufferHandle tmpTarget(target);
-    FenceHandle tmpAcquireFence(acquireFence, true);
-
-    hidl_vec<IComposer::Rect> tmpDamage;
-    tmpDamage.setToExternal(const_cast<IComposer::Rect*>(damage.data()),
-            damage.size());
-
-    auto ret = mService->setClientTarget(display, tmpTarget,
-            tmpAcquireFence, dataspace, tmpDamage);
-    return unwrapRet(ret);
+    mWriter.selectDisplay(display);
+    mWriter.setClientTarget(0, target, acquireFence, dataspace, damage);
+    return Error::NONE;
 }
 
-Error Composer::setColorMode(Display display, ColorMode mode) const
+Error Composer::setColorMode(Display display, ColorMode mode)
 {
-    auto ret = mService->setColorMode(display, mode);
+    auto ret = mClient->setColorMode(display, mode);
     return unwrapRet(ret);
 }
 
 Error Composer::setColorTransform(Display display, const float* matrix,
-        ColorTransform hint) const
+        ColorTransform hint)
 {
-    hidl_vec<float> tmpMatrix;
-    tmpMatrix.setToExternal(const_cast<float*>(matrix), 16);
-
-    auto ret = mService->setColorTransform(display, tmpMatrix, hint);
-    return unwrapRet(ret);
+    mWriter.selectDisplay(display);
+    mWriter.setColorTransform(matrix, hint);
+    return Error::NONE;
 }
 
 Error Composer::setOutputBuffer(Display display, const native_handle_t* buffer,
-        int releaseFence) const
+        int releaseFence)
 {
-    BufferHandle tmpBuffer(buffer);
-    FenceHandle tmpReleaseFence(releaseFence, false);
+    mWriter.selectDisplay(display);
+    mWriter.setOutputBuffer(0, buffer, dup(releaseFence));
+    return Error::NONE;
+}
 
-    auto ret = mService->setOutputBuffer(display, tmpBuffer, tmpReleaseFence);
+Error Composer::setPowerMode(Display display, IComposerClient::PowerMode mode)
+{
+    auto ret = mClient->setPowerMode(display, mode);
     return unwrapRet(ret);
 }
 
-Error Composer::setPowerMode(Display display, IComposer::PowerMode mode) const
+Error Composer::setVsyncEnabled(Display display, IComposerClient::Vsync enabled)
 {
-    auto ret = mService->setPowerMode(display, mode);
+    auto ret = mClient->setVsyncEnabled(display, enabled);
     return unwrapRet(ret);
 }
 
-Error Composer::setVsyncEnabled(Display display, IComposer::Vsync enabled) const
+Error Composer::setClientTargetSlotCount(Display display)
 {
-    auto ret = mService->setVsyncEnabled(display, enabled);
+    const uint32_t bufferSlotCount = 1;
+    auto ret = mClient->setClientTargetSlotCount(display, bufferSlotCount);
     return unwrapRet(ret);
 }
 
-Error Composer::validateDisplay(Display display, uint32_t& numTypes, uint32_t&
-        numRequests) const
+Error Composer::validateDisplay(Display display, uint32_t* outNumTypes,
+        uint32_t* outNumRequests)
 {
+    mWriter.selectDisplay(display);
+    mWriter.validateDisplay();
+
+    Error error = execute();
+    if (error != Error::NONE) {
+        return error;
+    }
+
+    mReader.hasChanges(display, outNumTypes, outNumRequests);
+
+    return Error::NONE;
+}
+
+Error Composer::setCursorPosition(Display display, Layer layer,
+        int32_t x, int32_t y)
+{
+    mWriter.selectDisplay(display);
+    mWriter.selectLayer(layer);
+    mWriter.setLayerCursorPosition(x, y);
+    return Error::NONE;
+}
+
+Error Composer::setLayerBuffer(Display display, Layer layer,
+        const native_handle_t* buffer, int acquireFence)
+{
+    mWriter.selectDisplay(display);
+    mWriter.selectLayer(layer);
+    mWriter.setLayerBuffer(0, buffer, acquireFence);
+    return Error::NONE;
+}
+
+Error Composer::setLayerSurfaceDamage(Display display, Layer layer,
+        const std::vector<IComposerClient::Rect>& damage)
+{
+    mWriter.selectDisplay(display);
+    mWriter.selectLayer(layer);
+    mWriter.setLayerSurfaceDamage(damage);
+    return Error::NONE;
+}
+
+Error Composer::setLayerBlendMode(Display display, Layer layer,
+        IComposerClient::BlendMode mode)
+{
+    mWriter.selectDisplay(display);
+    mWriter.selectLayer(layer);
+    mWriter.setLayerBlendMode(mode);
+    return Error::NONE;
+}
+
+Error Composer::setLayerColor(Display display, Layer layer,
+        const IComposerClient::Color& color)
+{
+    mWriter.selectDisplay(display);
+    mWriter.selectLayer(layer);
+    mWriter.setLayerColor(color);
+    return Error::NONE;
+}
+
+Error Composer::setLayerCompositionType(Display display, Layer layer,
+        IComposerClient::Composition type)
+{
+    mWriter.selectDisplay(display);
+    mWriter.selectLayer(layer);
+    mWriter.setLayerCompositionType(type);
+    return Error::NONE;
+}
+
+Error Composer::setLayerDataspace(Display display, Layer layer,
+        Dataspace dataspace)
+{
+    mWriter.selectDisplay(display);
+    mWriter.selectLayer(layer);
+    mWriter.setLayerDataspace(dataspace);
+    return Error::NONE;
+}
+
+Error Composer::setLayerDisplayFrame(Display display, Layer layer,
+        const IComposerClient::Rect& frame)
+{
+    mWriter.selectDisplay(display);
+    mWriter.selectLayer(layer);
+    mWriter.setLayerDisplayFrame(frame);
+    return Error::NONE;
+}
+
+Error Composer::setLayerPlaneAlpha(Display display, Layer layer,
+        float alpha)
+{
+    mWriter.selectDisplay(display);
+    mWriter.selectLayer(layer);
+    mWriter.setLayerPlaneAlpha(alpha);
+    return Error::NONE;
+}
+
+Error Composer::setLayerSidebandStream(Display display, Layer layer,
+        const native_handle_t* stream)
+{
+    mWriter.selectDisplay(display);
+    mWriter.selectLayer(layer);
+    mWriter.setLayerSidebandStream(stream);
+    return Error::NONE;
+}
+
+Error Composer::setLayerSourceCrop(Display display, Layer layer,
+        const IComposerClient::FRect& crop)
+{
+    mWriter.selectDisplay(display);
+    mWriter.selectLayer(layer);
+    mWriter.setLayerSourceCrop(crop);
+    return Error::NONE;
+}
+
+Error Composer::setLayerTransform(Display display, Layer layer,
+        Transform transform)
+{
+    mWriter.selectDisplay(display);
+    mWriter.selectLayer(layer);
+    mWriter.setLayerTransform(transform);
+    return Error::NONE;
+}
+
+Error Composer::setLayerVisibleRegion(Display display, Layer layer,
+        const std::vector<IComposerClient::Rect>& visible)
+{
+    mWriter.selectDisplay(display);
+    mWriter.selectLayer(layer);
+    mWriter.setLayerVisibleRegion(visible);
+    return Error::NONE;
+}
+
+Error Composer::setLayerZOrder(Display display, Layer layer, uint32_t z)
+{
+    mWriter.selectDisplay(display);
+    mWriter.selectLayer(layer);
+    mWriter.setLayerZOrder(z);
+    return Error::NONE;
+}
+
+Error Composer::execute()
+{
+    // prepare input command queue
+    bool queueChanged = false;
+    uint32_t commandLength = 0;
+    hidl_vec<hidl_handle> commandHandles;
+    if (!mWriter.writeQueue(&queueChanged, &commandLength, &commandHandles)) {
+        mWriter.reset();
+        return Error::NO_RESOURCES;
+    }
+
+    // set up new input command queue if necessary
+    if (queueChanged) {
+        auto ret = mClient->setInputCommandQueue(*mWriter.getMQDescriptor());
+        auto error = unwrapRet(ret);
+        if (error != Error::NONE) {
+            mWriter.reset();
+            return error;
+        }
+    }
+
     Error error = kDefaultError;
-    mService->validateDisplay(display,
-            [&](const auto& tmpError, const auto& tmpNumTypes,
-                const auto& tmpNumRequests) {
+    mClient->executeCommands(commandLength, commandHandles,
+            [&](const auto& tmpError, const auto& tmpOutChanged,
+                const auto& tmpOutLength, const auto& tmpOutHandles)
+            {
                 error = tmpError;
+
+                // set up new output command queue if necessary
+                if (error == Error::NONE && tmpOutChanged) {
+                    error = kDefaultError;
+                    mClient->getOutputCommandQueue(
+                            [&](const auto& tmpError,
+                                const auto& tmpDescriptor)
+                            {
+                                error = tmpError;
+                                if (error != Error::NONE) {
+                                    return;
+                                }
+
+                                mReader.setMQDescriptor(tmpDescriptor);
+                            });
+                }
+
                 if (error != Error::NONE) {
                     return;
                 }
 
-                numTypes = tmpNumTypes;
-                numRequests = tmpNumRequests;
+                if (mReader.readQueue(tmpOutLength, tmpOutHandles)) {
+                    error = mReader.parse();
+                    mReader.reset();
+                } else {
+                    error = Error::NO_RESOURCES;
+                }
             });
 
+    if (error == Error::NONE) {
+        std::vector<CommandReader::CommandError> commandErrors =
+            mReader.takeErrors();
+
+        for (const auto& cmdErr : commandErrors) {
+            auto command = mWriter.getCommand(cmdErr.location);
+
+            if (command == IComposerClient::Command::VALIDATE_DISPLAY ||
+                command == IComposerClient::Command::PRESENT_DISPLAY) {
+                error = cmdErr.error;
+            } else {
+                ALOGW("command 0x%x generated error %d",
+                        command, cmdErr.error);
+            }
+        }
+    }
+
+    mWriter.reset();
+
     return error;
 }
 
-Error Composer::setCursorPosition(Display display, Layer layer,
-        int32_t x, int32_t y) const
+CommandReader::~CommandReader()
 {
-    auto ret = mService->setCursorPosition(display, layer, x, y);
-    return unwrapRet(ret);
+    resetData();
 }
 
-Error Composer::setLayerBuffer(Display display, Layer layer,
-        const native_handle_t* buffer, int acquireFence) const
+Error CommandReader::parse()
 {
-    BufferHandle tmpBuffer(buffer);
-    FenceHandle tmpAcquireFence(acquireFence, true);
+    resetData();
 
-    auto ret = mService->setLayerBuffer(display, layer,
-            tmpBuffer, tmpAcquireFence);
-    return unwrapRet(ret);
+    IComposerClient::Command command;
+    uint16_t length = 0;
+
+    while (!isEmpty()) {
+        if (!beginCommand(&command, &length)) {
+            break;
+        }
+
+        bool parsed = false;
+        switch (command) {
+        case IComposerClient::Command::SELECT_DISPLAY:
+            parsed = parseSelectDisplay(length);
+            break;
+        case IComposerClient::Command::SET_ERROR:
+            parsed = parseSetError(length);
+            break;
+        case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES:
+            parsed = parseSetChangedCompositionTypes(length);
+            break;
+        case IComposerClient::Command::SET_DISPLAY_REQUESTS:
+            parsed = parseSetDisplayRequests(length);
+            break;
+        case IComposerClient::Command::SET_PRESENT_FENCE:
+            parsed = parseSetPresentFence(length);
+            break;
+        case IComposerClient::Command::SET_RELEASE_FENCES:
+            parsed = parseSetReleaseFences(length);
+            break;
+        default:
+            parsed = false;
+            break;
+        }
+
+        endCommand();
+
+        if (!parsed) {
+            ALOGE("failed to parse command 0x%x length %" PRIu16,
+                    command, length);
+            break;
+        }
+    }
+
+    return isEmpty() ? Error::NONE : Error::NO_RESOURCES;
 }
 
-Error Composer::setLayerSurfaceDamage(Display display, Layer layer,
-        const std::vector<IComposer::Rect>& damage) const
+bool CommandReader::parseSelectDisplay(uint16_t length)
 {
-    hidl_vec<IComposer::Rect> tmpDamage;
-    tmpDamage.setToExternal(const_cast<IComposer::Rect*>(damage.data()),
-            damage.size());
+    if (length != CommandWriter::kSelectDisplayLength) {
+        return false;
+    }
 
-    auto ret = mService->setLayerSurfaceDamage(display, layer, tmpDamage);
-    return unwrapRet(ret);
+    mCurrentReturnData = &mReturnData[read64()];
+
+    return true;
 }
 
-Error Composer::setLayerBlendMode(Display display, Layer layer,
-        IComposer::BlendMode mode) const
+bool CommandReader::parseSetError(uint16_t length)
 {
-    auto ret = mService->setLayerBlendMode(display, layer, mode);
-    return unwrapRet(ret);
+    if (length != CommandWriter::kSetErrorLength) {
+        return false;
+    }
+
+    auto location = read();
+    auto error = static_cast<Error>(readSigned());
+
+    mErrors.emplace_back(CommandError{location, error});
+
+    return true;
 }
 
-Error Composer::setLayerColor(Display display, Layer layer,
-        const IComposer::Color& color) const
+bool CommandReader::parseSetChangedCompositionTypes(uint16_t length)
 {
-    auto ret = mService->setLayerColor(display, layer, color);
-    return unwrapRet(ret);
+    // (layer id, composition type) pairs
+    if (length % 3 != 0 || !mCurrentReturnData) {
+        return false;
+    }
+
+    uint32_t count = length / 3;
+    mCurrentReturnData->changedLayers.reserve(count);
+    mCurrentReturnData->compositionTypes.reserve(count);
+    while (count > 0) {
+        auto layer = read64();
+        auto type = static_cast<IComposerClient::Composition>(readSigned());
+
+        mCurrentReturnData->changedLayers.push_back(layer);
+        mCurrentReturnData->compositionTypes.push_back(type);
+
+        count--;
+    }
+
+    return true;
 }
 
-Error Composer::setLayerCompositionType(Display display, Layer layer,
-        IComposer::Composition type) const
+bool CommandReader::parseSetDisplayRequests(uint16_t length)
 {
-    auto ret = mService->setLayerCompositionType(display, layer, type);
-    return unwrapRet(ret);
+    // display requests followed by (layer id, layer requests) pairs
+    if (length % 3 != 1 || !mCurrentReturnData) {
+        return false;
+    }
+
+    mCurrentReturnData->displayRequests = read();
+
+    uint32_t count = (length - 1) / 3;
+    mCurrentReturnData->requestedLayers.reserve(count);
+    mCurrentReturnData->requestMasks.reserve(count);
+    while (count > 0) {
+        auto layer = read64();
+        auto layerRequestMask = read();
+
+        mCurrentReturnData->requestedLayers.push_back(layer);
+        mCurrentReturnData->requestMasks.push_back(layerRequestMask);
+
+        count--;
+    }
+
+    return true;
 }
 
-Error Composer::setLayerDataspace(Display display, Layer layer,
-        Dataspace dataspace) const
+bool CommandReader::parseSetPresentFence(uint16_t length)
 {
-    auto ret = mService->setLayerDataspace(display, layer, dataspace);
-    return unwrapRet(ret);
+    if (length != CommandWriter::kSetPresentFenceLength ||
+            !mCurrentReturnData) {
+        return false;
+    }
+
+    if (mCurrentReturnData->presentFence >= 0) {
+        close(mCurrentReturnData->presentFence);
+    }
+    mCurrentReturnData->presentFence = readFence();
+
+    return true;
 }
 
-Error Composer::setLayerDisplayFrame(Display display, Layer layer,
-        const IComposer::Rect& frame) const
+bool CommandReader::parseSetReleaseFences(uint16_t length)
 {
-    auto ret = mService->setLayerDisplayFrame(display, layer, frame);
-    return unwrapRet(ret);
+    // (layer id, release fence index) pairs
+    if (length % 3 != 0 || !mCurrentReturnData) {
+        return false;
+    }
+
+    uint32_t count = length / 3;
+    mCurrentReturnData->releasedLayers.reserve(count);
+    mCurrentReturnData->releaseFences.reserve(count);
+    while (count > 0) {
+        auto layer = read64();
+        auto fence = readFence();
+
+        mCurrentReturnData->releasedLayers.push_back(layer);
+        mCurrentReturnData->releaseFences.push_back(fence);
+
+        count--;
+    }
+
+    return true;
 }
 
-Error Composer::setLayerPlaneAlpha(Display display, Layer layer,
-        float alpha) const
+void CommandReader::resetData()
 {
-    auto ret = mService->setLayerPlaneAlpha(display, layer, alpha);
-    return unwrapRet(ret);
+    mErrors.clear();
+
+    for (auto& data : mReturnData) {
+        if (data.second.presentFence >= 0) {
+            close(data.second.presentFence);
+        }
+        for (auto fence : data.second.releaseFences) {
+            if (fence >= 0) {
+                close(fence);
+            }
+        }
+    }
+
+    mReturnData.clear();
+    mCurrentReturnData = nullptr;
 }
 
-Error Composer::setLayerSidebandStream(Display display, Layer layer,
-        const native_handle_t* stream) const
+std::vector<CommandReader::CommandError> CommandReader::takeErrors()
 {
-    BufferHandle tmpStream(stream);
-
-    auto ret = mService->setLayerSidebandStream(display, layer, tmpStream);
-    return unwrapRet(ret);
+    return std::move(mErrors);
 }
 
-Error Composer::setLayerSourceCrop(Display display, Layer layer,
-        const IComposer::FRect& crop) const
+bool CommandReader::hasChanges(Display display,
+        uint32_t* outNumChangedCompositionTypes,
+        uint32_t* outNumLayerRequestMasks) const
 {
-    auto ret = mService->setLayerSourceCrop(display, layer, crop);
-    return unwrapRet(ret);
+    auto found = mReturnData.find(display);
+    if (found == mReturnData.end()) {
+        *outNumChangedCompositionTypes = 0;
+        *outNumLayerRequestMasks = 0;
+        return false;
+    }
+
+    const ReturnData& data = found->second;
+
+    *outNumChangedCompositionTypes = data.compositionTypes.size();
+    *outNumLayerRequestMasks = data.requestMasks.size();
+
+    return !(data.compositionTypes.empty() && data.requestMasks.empty());
 }
 
-Error Composer::setLayerTransform(Display display, Layer layer,
-        Transform transform) const
+void CommandReader::takeChangedCompositionTypes(Display display,
+        std::vector<Layer>* outLayers,
+        std::vector<IComposerClient::Composition>* outTypes)
 {
-    auto ret = mService->setLayerTransform(display, layer, transform);
-    return unwrapRet(ret);
+    auto found = mReturnData.find(display);
+    if (found == mReturnData.end()) {
+        outLayers->clear();
+        outTypes->clear();
+        return;
+    }
+
+    ReturnData& data = found->second;
+
+    *outLayers = std::move(data.changedLayers);
+    *outTypes = std::move(data.compositionTypes);
 }
 
-Error Composer::setLayerVisibleRegion(Display display, Layer layer,
-        const std::vector<IComposer::Rect>& visible) const
+void CommandReader::takeDisplayRequests(Display display,
+        uint32_t* outDisplayRequestMask, std::vector<Layer>* outLayers,
+        std::vector<uint32_t>* outLayerRequestMasks)
 {
-    hidl_vec<IComposer::Rect> tmpVisible;
-    tmpVisible.setToExternal(const_cast<IComposer::Rect*>(visible.data()),
-            visible.size());
+    auto found = mReturnData.find(display);
+    if (found == mReturnData.end()) {
+        *outDisplayRequestMask = 0;
+        outLayers->clear();
+        outLayerRequestMasks->clear();
+        return;
+    }
 
-    auto ret = mService->setLayerVisibleRegion(display, layer, tmpVisible);
-    return unwrapRet(ret);
+    ReturnData& data = found->second;
+
+    *outDisplayRequestMask = data.displayRequests;
+    *outLayers = std::move(data.requestedLayers);
+    *outLayerRequestMasks = std::move(data.requestMasks);
 }
 
-Error Composer::setLayerZOrder(Display display, Layer layer, uint32_t z) const
+void CommandReader::takeReleaseFences(Display display,
+        std::vector<Layer>* outLayers, std::vector<int>* outReleaseFences)
 {
-    auto ret = mService->setLayerZOrder(display, layer, z);
-    return unwrapRet(ret);
+    auto found = mReturnData.find(display);
+    if (found == mReturnData.end()) {
+        outLayers->clear();
+        outReleaseFences->clear();
+        return;
+    }
+
+    ReturnData& data = found->second;
+
+    *outLayers = std::move(data.releasedLayers);
+    *outReleaseFences = std::move(data.releaseFences);
+}
+
+void CommandReader::takePresentFence(Display display, int* outPresentFence)
+{
+    auto found = mReturnData.find(display);
+    if (found == mReturnData.end()) {
+        *outPresentFence = -1;
+        return;
+    }
+
+    ReturnData& data = found->second;
+
+    *outPresentFence = data.presentFence;
+    data.presentFence = -1;
 }
 
 } // namespace Hwc2
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index b8f7c20..6e42ba0 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -17,11 +17,16 @@
 #ifndef ANDROID_SF_COMPOSER_HAL_H
 #define ANDROID_SF_COMPOSER_HAL_H
 
+#include <memory>
 #include <string>
+#include <unordered_map>
+#include <utility>
 #include <vector>
 
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
 #include <utils/StrongPointer.h>
+#include <IComposerCommandBuffer.h>
+#include <MessageQueue.h>
 
 namespace android {
 
@@ -36,102 +41,195 @@
 
 using android::hardware::graphics::composer::V2_1::IComposer;
 using android::hardware::graphics::composer::V2_1::IComposerCallback;
+using android::hardware::graphics::composer::V2_1::IComposerClient;
 using android::hardware::graphics::composer::V2_1::Error;
 using android::hardware::graphics::composer::V2_1::Display;
 using android::hardware::graphics::composer::V2_1::Layer;
 using android::hardware::graphics::composer::V2_1::Config;
 
+using android::hardware::graphics::composer::V2_1::CommandWriter;
+using android::hardware::graphics::composer::V2_1::CommandReaderBase;
+
+using android::hardware::kSynchronizedReadWrite;
+using android::hardware::MessageQueue;
+using android::hardware::MQDescriptorSync;
+using android::hardware::hidl_vec;
+using android::hardware::hidl_handle;
+
+class CommandReader : public CommandReaderBase {
+public:
+    ~CommandReader();
+
+    // Parse and execute commands from the command queue.  The commands are
+    // actually return values from the server and will be saved in ReturnData.
+    Error parse();
+
+    // Get and clear saved errors.
+    struct CommandError {
+        uint32_t location;
+        Error error;
+    };
+    std::vector<CommandError> takeErrors();
+
+    bool hasChanges(Display display, uint32_t* outNumChangedCompositionTypes,
+            uint32_t* outNumLayerRequestMasks) const;
+
+    // Get and clear saved changed composition types.
+    void takeChangedCompositionTypes(Display display,
+            std::vector<Layer>* outLayers,
+            std::vector<IComposerClient::Composition>* outTypes);
+
+    // Get and clear saved display requests.
+    void takeDisplayRequests(Display display,
+        uint32_t* outDisplayRequestMask, std::vector<Layer>* outLayers,
+        std::vector<uint32_t>* outLayerRequestMasks);
+
+    // Get and clear saved release fences.
+    void takeReleaseFences(Display display, std::vector<Layer>* outLayers,
+            std::vector<int>* outReleaseFences);
+
+    // Get and clear saved present fence.
+    void takePresentFence(Display display, int* outPresentFence);
+
+private:
+    void resetData();
+
+    bool parseSelectDisplay(uint16_t length);
+    bool parseSetError(uint16_t length);
+    bool parseSetChangedCompositionTypes(uint16_t length);
+    bool parseSetDisplayRequests(uint16_t length);
+    bool parseSetPresentFence(uint16_t length);
+    bool parseSetReleaseFences(uint16_t length);
+
+    struct ReturnData {
+        uint32_t displayRequests = 0;
+
+        std::vector<Layer> changedLayers;
+        std::vector<IComposerClient::Composition> compositionTypes;
+
+        std::vector<Layer> requestedLayers;
+        std::vector<uint32_t> requestMasks;
+
+        int presentFence = -1;
+
+        std::vector<Layer> releasedLayers;
+        std::vector<int> releaseFences;
+    };
+
+    std::vector<CommandError> mErrors;
+    std::unordered_map<Display, ReturnData> mReturnData;
+
+    // When SELECT_DISPLAY is parsed, this is updated to point to the
+    // display's return data in mReturnData.  We use it to avoid repeated
+    // map lookups.
+    ReturnData* mCurrentReturnData;
+};
+
 // Composer is a wrapper to IComposer, a proxy to server-side composer.
 class Composer {
 public:
     Composer();
 
-    std::vector<IComposer::Capability> getCapabilities() const;
-    std::string dumpDebugInfo() const;
+    std::vector<IComposer::Capability> getCapabilities();
+    std::string dumpDebugInfo();
 
-    void registerCallback(const sp<IComposerCallback>& callback) const;
+    void registerCallback(const sp<IComposerCallback>& callback);
 
-    uint32_t getMaxVirtualDisplayCount() const;
+    uint32_t getMaxVirtualDisplayCount();
     Error createVirtualDisplay(uint32_t width, uint32_t height,
-            PixelFormat& format, Display& display) const;
-    Error destroyVirtualDisplay(Display display) const;
+            PixelFormat* format, Display* outDisplay);
+    Error destroyVirtualDisplay(Display display);
 
-    Error acceptDisplayChanges(Display display) const;
+    Error acceptDisplayChanges(Display display);
 
-    Error createLayer(Display display, Layer& layer) const;
-    Error destroyLayer(Display display, Layer layer) const;
+    Error createLayer(Display display, Layer* outLayer);
+    Error destroyLayer(Display display, Layer layer);
 
-    Error getActiveConfig(Display display, Config& config) const;
+    Error getActiveConfig(Display display, Config* outConfig);
     Error getChangedCompositionTypes(Display display,
-            std::vector<Layer>& layers,
-            std::vector<IComposer::Composition>& types) const;
-    Error getColorModes(Display display, std::vector<ColorMode>& modes) const;
+            std::vector<Layer>* outLayers,
+            std::vector<IComposerClient::Composition>* outTypes);
+    Error getColorModes(Display display, std::vector<ColorMode>* outModes);
     Error getDisplayAttribute(Display display, Config config,
-            IComposer::Attribute attribute, int32_t& value) const;
-    Error getDisplayConfigs(Display display,
-            std::vector<Config>& configs) const;
-    Error getDisplayName(Display display, std::string& name) const;
+            IComposerClient::Attribute attribute, int32_t* outValue);
+    Error getDisplayConfigs(Display display, std::vector<Config>* outConfigs);
+    Error getDisplayName(Display display, std::string* outName);
 
-    Error getDisplayRequests(Display display, uint32_t& displayRequestMask,
-            std::vector<Layer>& layers,
-            std::vector<uint32_t>& layerRequestMasks) const;
+    Error getDisplayRequests(Display display, uint32_t* outDisplayRequestMask,
+            std::vector<Layer>* outLayers,
+            std::vector<uint32_t>* outLayerRequestMasks);
 
-    Error getDisplayType(Display display, IComposer::DisplayType& type) const;
-    Error getDozeSupport(Display display, bool& support) const;
-    Error getHdrCapabilities(Display display, std::vector<Hdr>& types,
-            float& maxLuminance, float& maxAverageLuminance,
-            float& minLuminance) const;
+    Error getDisplayType(Display display,
+            IComposerClient::DisplayType* outType);
+    Error getDozeSupport(Display display, bool* outSupport);
+    Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes,
+            float* outMaxLuminance, float* outMaxAverageLuminance,
+            float* outMinLuminance);
 
-    Error getReleaseFences(Display display, std::vector<Layer>& layers,
-            std::vector<int>& releaseFences) const;
+    Error getReleaseFences(Display display, std::vector<Layer>* outLayers,
+            std::vector<int>* outReleaseFences);
 
-    Error presentDisplay(Display display, int& presentFence) const;
+    Error presentDisplay(Display display, int* outPresentFence);
 
-    Error setActiveConfig(Display display, Config config) const;
+    Error setActiveConfig(Display display, Config config);
     Error setClientTarget(Display display, const native_handle_t* target,
             int acquireFence, Dataspace dataspace,
-            const std::vector<IComposer::Rect>& damage) const;
-    Error setColorMode(Display display, ColorMode mode) const;
+            const std::vector<IComposerClient::Rect>& damage);
+    Error setColorMode(Display display, ColorMode mode);
     Error setColorTransform(Display display, const float* matrix,
-            ColorTransform hint) const;
+            ColorTransform hint);
     Error setOutputBuffer(Display display, const native_handle_t* buffer,
-            int releaseFence) const;
-    Error setPowerMode(Display display, IComposer::PowerMode mode) const;
-    Error setVsyncEnabled(Display display, IComposer::Vsync enabled) const;
+            int releaseFence);
+    Error setPowerMode(Display display, IComposerClient::PowerMode mode);
+    Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled);
 
-    Error validateDisplay(Display display, uint32_t& numTypes,
-            uint32_t& numRequests) const;
+    Error setClientTargetSlotCount(Display display);
+
+    Error validateDisplay(Display display, uint32_t* outNumTypes,
+            uint32_t* outNumRequests);
 
     Error setCursorPosition(Display display, Layer layer,
-            int32_t x, int32_t y) const;
+            int32_t x, int32_t y);
     Error setLayerBuffer(Display display, Layer layer,
-            const native_handle_t* buffer, int acquireFence) const;
+            const native_handle_t* buffer, int acquireFence);
     Error setLayerSurfaceDamage(Display display, Layer layer,
-            const std::vector<IComposer::Rect>& damage) const;
+            const std::vector<IComposerClient::Rect>& damage);
     Error setLayerBlendMode(Display display, Layer layer,
-            IComposer::BlendMode mode) const;
+            IComposerClient::BlendMode mode);
     Error setLayerColor(Display display, Layer layer,
-            const IComposer::Color& color) const;
+            const IComposerClient::Color& color);
     Error setLayerCompositionType(Display display, Layer layer,
-            IComposer::Composition type) const;
+            IComposerClient::Composition type);
     Error setLayerDataspace(Display display, Layer layer,
-            Dataspace dataspace) const;
+            Dataspace dataspace);
     Error setLayerDisplayFrame(Display display, Layer layer,
-            const IComposer::Rect& frame) const;
+            const IComposerClient::Rect& frame);
     Error setLayerPlaneAlpha(Display display, Layer layer,
-            float alpha) const;
+            float alpha);
     Error setLayerSidebandStream(Display display, Layer layer,
-            const native_handle_t* stream) const;
+            const native_handle_t* stream);
     Error setLayerSourceCrop(Display display, Layer layer,
-            const IComposer::FRect& crop) const;
+            const IComposerClient::FRect& crop);
     Error setLayerTransform(Display display, Layer layer,
-            Transform transform) const;
+            Transform transform);
     Error setLayerVisibleRegion(Display display, Layer layer,
-            const std::vector<IComposer::Rect>& visible) const;
-    Error setLayerZOrder(Display display, Layer layer, uint32_t z) const;
+            const std::vector<IComposerClient::Rect>& visible);
+    Error setLayerZOrder(Display display, Layer layer, uint32_t z);
 
 private:
-    sp<IComposer> mService;
+    // Many public functions above simply write a command into the command
+    // queue to batch the calls.  validateDisplay and presentDisplay will call
+    // this function to execute the command queue.
+    Error execute();
+
+    sp<IComposer> mComposer;
+    sp<IComposerClient> mClient;
+
+    // 64KiB minus a small space for metadata such as read/write pointers
+    static constexpr size_t kWriterInitialSize =
+        64 * 1024 / sizeof(uint32_t) - 16;
+    CommandWriter mWriter;
+    CommandReader mReader;
 };
 
 } // namespace Hwc2
diff --git a/services/surfaceflinger/DisplayHardware/FloatRect.h b/services/surfaceflinger/DisplayHardware/FloatRect.h
deleted file mode 100644
index 151eaaa..0000000
--- a/services/surfaceflinger/DisplayHardware/FloatRect.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SF_FLOAT_RECT
-#define ANDROID_SF_FLOAT_RECT
-
-#include <ui/Rect.h>
-#include <utils/TypeHelpers.h>
-
-namespace android {
-
-class FloatRect
-{
-public:
-    float left;
-    float top;
-    float right;
-    float bottom;
-
-    inline FloatRect()
-        : left(0), top(0), right(0), bottom(0) { }
-    inline FloatRect(const Rect& other)  // NOLINT(implicit)
-        : left(other.left), top(other.top), right(other.right), bottom(other.bottom) { }
-
-    inline float getWidth() const { return right - left; }
-    inline float getHeight() const { return bottom - top; }
-};
-
-}; // namespace android
-
-#endif // ANDROID_SF_FLOAT_RECT
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 61c231d..96dd55f 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -19,13 +19,12 @@
 #undef LOG_TAG
 #define LOG_TAG "FramebufferSurface"
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
 #include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
-#include <cutils/log.h>
-
+#include <android/log.h>
 #include <utils/String8.h>
 
 #include <ui/Rect.h>
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index dd909aa..c89ca83 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -23,7 +23,7 @@
 #include "HWC2.h"
 #include "ComposerHal.h"
 
-#include "FloatRect.h"
+#include <gfx/FloatRect.h>
 
 #include <ui/Fence.h>
 #include <ui/GraphicBuffer.h>
@@ -74,12 +74,12 @@
 }
 
 using android::Fence;
-using android::FloatRect;
 using android::GraphicBuffer;
 using android::HdrCapabilities;
 using android::Rect;
 using android::Region;
 using android::sp;
+using android::gfx::FloatRect;
 using android::hardware::Return;
 using android::hardware::Void;
 
@@ -231,7 +231,7 @@
 #else
     auto intFormat = static_cast<Hwc2::PixelFormat>(*format);
     auto intError = mComposer->createVirtualDisplay(width, height,
-            intFormat, displayId);
+            &intFormat, &displayId);
 #endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
@@ -286,6 +286,9 @@
 {
     if (connected == Connection::Connected) {
         if (!display->isConnected()) {
+#ifndef BYPASS_IHWC
+            mComposer->setClientTargetSlotCount(display->getId());
+#endif
             display->loadConfigs();
             display->setConnected(true);
         }
@@ -587,7 +590,7 @@
 #ifdef BYPASS_IHWC
     int32_t intError = mDevice.mCreateLayer(mDevice.mHwcDevice, mId, &layerId);
 #else
-    auto intError = mDevice.mComposer->createLayer(mId, layerId);
+    auto intError = mDevice.mComposer->createLayer(mId, &layerId);
 #endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
@@ -609,7 +612,7 @@
     int32_t intError = mDevice.mGetActiveConfig(mDevice.mHwcDevice, mId,
             &configId);
 #else
-    auto intError = mDevice.mComposer->getActiveConfig(mId, configId);
+    auto intError = mDevice.mComposer->getActiveConfig(mId, &configId);
 #endif
     auto error = static_cast<Error>(intError);
 
@@ -650,9 +653,9 @@
             &numElements, layerIds.data(), types.data());
 #else
     std::vector<Hwc2::Layer> layerIds;
-    std::vector<Hwc2::IComposer::Composition> types;
+    std::vector<Hwc2::IComposerClient::Composition> types;
     auto intError = mDevice.mComposer->getChangedCompositionTypes(mId,
-            layerIds, types);
+            &layerIds, &types);
     uint32_t numElements = layerIds.size();
     auto error = static_cast<Error>(intError);
 #endif
@@ -696,7 +699,7 @@
     error = static_cast<Error>(intError);
 #else
     std::vector<Hwc2::ColorMode> modes;
-    auto intError = mDevice.mComposer->getColorModes(mId, modes);
+    auto intError = mDevice.mComposer->getColorModes(mId, &modes);
     uint32_t numModes = modes.size();
     auto error = static_cast<Error>(intError);
 #endif
@@ -742,7 +745,7 @@
     *outName = std::string(rawName.cbegin(), rawName.cend());
     return Error::None;
 #else
-    auto intError = mDevice.mComposer->getDisplayName(mId, *outName);
+    auto intError = mDevice.mComposer->getDisplayName(mId, outName);
     return static_cast<Error>(intError);
 #endif
 }
@@ -772,7 +775,7 @@
     std::vector<Hwc2::Layer> layerIds;
     std::vector<uint32_t> layerRequests;
     auto intError = mDevice.mComposer->getDisplayRequests(mId,
-            intDisplayRequests, layerIds, layerRequests);
+            &intDisplayRequests, &layerIds, &layerRequests);
     uint32_t numElements = layerIds.size();
     auto error = static_cast<Error>(intError);
 #endif
@@ -805,9 +808,9 @@
     int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
             &intType);
 #else
-    Hwc2::IComposer::DisplayType intType =
-        Hwc2::IComposer::DisplayType::INVALID;
-    auto intError = mDevice.mComposer->getDisplayType(mId, intType);
+    Hwc2::IComposerClient::DisplayType intType =
+        Hwc2::IComposerClient::DisplayType::INVALID;
+    auto intError = mDevice.mComposer->getDisplayType(mId, &intType);
 #endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
@@ -826,7 +829,7 @@
             &intSupport);
 #else
     bool intSupport = false;
-    auto intError = mDevice.mComposer->getDozeSupport(mId, intSupport);
+    auto intError = mDevice.mComposer->getDozeSupport(mId, &intSupport);
 #endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
@@ -858,8 +861,8 @@
     error = static_cast<HWC2::Error>(intError);
 #else
     std::vector<Hwc2::Hdr> intTypes;
-    auto intError = mDevice.mComposer->getHdrCapabilities(mId, intTypes,
-            maxLuminance, maxAverageLuminance, minLuminance);
+    auto intError = mDevice.mComposer->getHdrCapabilities(mId, &intTypes,
+            &maxLuminance, &maxAverageLuminance, &minLuminance);
     auto error = static_cast<HWC2::Error>(intError);
 
     std::vector<int32_t> types;
@@ -898,7 +901,7 @@
     std::vector<Hwc2::Layer> layerIds;
     std::vector<int> fenceFds;
     auto intError = mDevice.mComposer->getReleaseFences(mId,
-            layerIds, fenceFds);
+            &layerIds, &fenceFds);
     auto error = static_cast<Error>(intError);
     uint32_t numElements = layerIds.size();
 #endif
@@ -926,12 +929,12 @@
 
 Error Display::present(sp<Fence>* outPresentFence)
 {
-    int32_t presentFenceFd = 0;
+    int32_t presentFenceFd = -1;
 #ifdef BYPASS_IHWC
     int32_t intError = mDevice.mPresentDisplay(mDevice.mHwcDevice, mId,
             &presentFenceFd);
 #else
-    auto intError = mDevice.mComposer->presentDisplay(mId, presentFenceFd);
+    auto intError = mDevice.mComposer->presentDisplay(mId, &presentFenceFd);
 #endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
@@ -970,7 +973,7 @@
 #else
     auto intError = mDevice.mComposer->setClientTarget(mId, target, fenceFd,
             static_cast<Hwc2::Dataspace>(dataspace),
-            std::vector<Hwc2::IComposer::Rect>());
+            std::vector<Hwc2::IComposerClient::Rect>());
 #endif
     return static_cast<Error>(intError);
 }
@@ -1020,7 +1023,7 @@
     auto intMode = static_cast<int32_t>(mode);
     int32_t intError = mDevice.mSetPowerMode(mDevice.mHwcDevice, mId, intMode);
 #else
-    auto intMode = static_cast<Hwc2::IComposer::PowerMode>(mode);
+    auto intMode = static_cast<Hwc2::IComposerClient::PowerMode>(mode);
     auto intError = mDevice.mComposer->setPowerMode(mId, intMode);
 #endif
     return static_cast<Error>(intError);
@@ -1033,7 +1036,7 @@
     int32_t intError = mDevice.mSetVsyncEnabled(mDevice.mHwcDevice, mId,
             intEnabled);
 #else
-    auto intEnabled = static_cast<Hwc2::IComposer::Vsync>(enabled);
+    auto intEnabled = static_cast<Hwc2::IComposerClient::Vsync>(enabled);
     auto intError = mDevice.mComposer->setVsyncEnabled(mId, intEnabled);
 #endif
     return static_cast<Error>(intError);
@@ -1048,7 +1051,7 @@
             &numTypes, &numRequests);
 #else
     auto intError = mDevice.mComposer->validateDisplay(mId,
-            numTypes, numRequests);
+            &numTypes, &numRequests);
 #endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None && error != Error::HasChanges) {
@@ -1069,9 +1072,9 @@
     int32_t intError = mDevice.mGetDisplayAttribute(mDevice.mHwcDevice, mId,
             configId, static_cast<int32_t>(attribute), &value);
 #else
-    auto intError = mDevice.mComposer->getDisplayAttribute(mId,
-            configId, static_cast<Hwc2::IComposer::Attribute>(attribute),
-            value);
+    auto intError = mDevice.mComposer->getDisplayAttribute(mId, configId,
+            static_cast<Hwc2::IComposerClient::Attribute>(attribute),
+            &value);
 #endif
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
@@ -1118,7 +1121,7 @@
     error = static_cast<Error>(intError);
 #else
     std::vector<Hwc2::Config> configIds;
-    auto intError = mDevice.mComposer->getDisplayConfigs(mId, configIds);
+    auto intError = mDevice.mComposer->getDisplayConfigs(mId, &configIds);
     auto error = static_cast<Error>(intError);
 #endif
     if (error != Error::None) {
@@ -1221,7 +1224,7 @@
                 mDisplayId, mId, {0, nullptr});
 #else
         intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
-                mId, std::vector<Hwc2::IComposer::Rect>());
+                mId, std::vector<Hwc2::IComposerClient::Rect>());
 #endif
     } else {
         size_t rectCount = 0;
@@ -1230,7 +1233,7 @@
 #ifdef BYPASS_IHWC
         std::vector<hwc_rect_t> hwcRects;
 #else
-        std::vector<Hwc2::IComposer::Rect> hwcRects;
+        std::vector<Hwc2::IComposerClient::Rect> hwcRects;
 #endif
         for (size_t rect = 0; rect < rectCount; ++rect) {
             hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
@@ -1260,7 +1263,7 @@
     int32_t intError = mDevice.mSetLayerBlendMode(mDevice.mHwcDevice,
             mDisplayId, mId, intMode);
 #else
-    auto intMode = static_cast<Hwc2::IComposer::BlendMode>(mode);
+    auto intMode = static_cast<Hwc2::IComposerClient::BlendMode>(mode);
     auto intError = mDevice.mComposer->setLayerBlendMode(mDisplayId,
             mId, intMode);
 #endif
@@ -1273,7 +1276,7 @@
     int32_t intError = mDevice.mSetLayerColor(mDevice.mHwcDevice, mDisplayId,
             mId, color);
 #else
-    Hwc2::IComposer::Color hwcColor{color.r, color.g, color.b, color.a};
+    Hwc2::IComposerClient::Color hwcColor{color.r, color.g, color.b, color.a};
     auto intError = mDevice.mComposer->setLayerColor(mDisplayId,
             mId, hwcColor);
 #endif
@@ -1287,7 +1290,7 @@
     int32_t intError = mDevice.mSetLayerCompositionType(mDevice.mHwcDevice,
             mDisplayId, mId, intType);
 #else
-    auto intType = static_cast<Hwc2::IComposer::Composition>(type);
+    auto intType = static_cast<Hwc2::IComposerClient::Composition>(type);
     auto intError = mDevice.mComposer->setLayerCompositionType(mDisplayId,
             mId, intType);
 #endif
@@ -1315,7 +1318,7 @@
     int32_t intError = mDevice.mSetLayerDisplayFrame(mDevice.mHwcDevice,
             mDisplayId, mId, hwcRect);
 #else
-    Hwc2::IComposer::Rect hwcRect{frame.left, frame.top,
+    Hwc2::IComposerClient::Rect hwcRect{frame.left, frame.top,
         frame.right, frame.bottom};
     auto intError = mDevice.mComposer->setLayerDisplayFrame(mDisplayId,
             mId, hwcRect);
@@ -1359,7 +1362,7 @@
     int32_t intError = mDevice.mSetLayerSourceCrop(mDevice.mHwcDevice,
             mDisplayId, mId, hwcRect);
 #else
-    Hwc2::IComposer::FRect hwcRect{
+    Hwc2::IComposerClient::FRect hwcRect{
         crop.left, crop.top, crop.right, crop.bottom};
     auto intError = mDevice.mComposer->setLayerSourceCrop(mDisplayId,
             mId, hwcRect);
@@ -1389,7 +1392,7 @@
 #ifdef BYPASS_IHWC
     std::vector<hwc_rect_t> hwcRects;
 #else
-    std::vector<Hwc2::IComposer::Rect> hwcRects;
+    std::vector<Hwc2::IComposerClient::Rect> hwcRects;
 #endif
     for (size_t rect = 0; rect < rectCount; ++rect) {
         hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 33fb8cb..5b894ba 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -38,13 +38,15 @@
 
 namespace android {
     class Fence;
-    class FloatRect;
     class GraphicBuffer;
     class Rect;
     class Region;
+    namespace gfx {
+        class FloatRect;
+    }
     namespace Hwc2 {
         class Composer;
-    };
+    }
 }
 
 namespace HWC2 {
@@ -57,6 +59,8 @@
 typedef std::function<void(std::shared_ptr<Display>)> RefreshCallback;
 typedef std::function<void(std::shared_ptr<Display>, nsecs_t)> VsyncCallback;
 
+// C++ Wrapper around hwc2_device_t. Load all functions pointers
+// and handle callback registration.
 class Device
 {
 public:
@@ -207,6 +211,7 @@
     std::vector<std::pair<std::shared_ptr<Display>, nsecs_t>> mPendingVsyncs;
 };
 
+// Convenience C++ class to access hwc2_device_t Display functions directly.
 class Display : public std::enable_shared_from_this<Display>
 {
 public:
@@ -368,6 +373,7 @@
     std::unordered_map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
 };
 
+// Convenience C++ class to access hwc2_device_t Layer functions directly.
 class Layer
 {
 public:
@@ -394,7 +400,7 @@
     [[clang::warn_unused_result]] Error setSidebandStream(
             const native_handle_t* stream);
     [[clang::warn_unused_result]] Error setSourceCrop(
-            const android::FloatRect& crop);
+            const android::gfx::FloatRect& crop);
     [[clang::warn_unused_result]] Error setTransform(Transform transform);
     [[clang::warn_unused_result]] Error setVisibleRegion(
             const android::Region& region);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
index c4f845d..51e92b2 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
@@ -22,15 +22,16 @@
 
 #include "HWC2On1Adapter.h"
 
-#include <hardware/hwcomposer.h>
-#include <log/log.h>
-#include <utils/Trace.h>
-
-#include <cstdlib>
-#include <chrono>
 #include <inttypes.h>
+
+#include <chrono>
+#include <cstdlib>
 #include <sstream>
 
+#include <android/log.h>
+#include <hardware/hwcomposer.h>
+#include <utils/Trace.h>
+
 using namespace std::chrono_literals;
 
 static bool operator==(const hwc_color_t& lhs, const hwc_color_t& rhs) {
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
index aa96004..9abdc38 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
@@ -40,6 +40,10 @@
 
 namespace android {
 
+// For devices unable to provide an implementation of HWC2 (see hwcomposer2.h),
+// we provide an adapter able to talk to HWC1 (see hwcomposer.h). It translates
+// streamed function calls ala HWC2 model to batched array of structs calls ala
+// HWC1 model.
 class HWC2On1Adapter : public hwc2_device_t
 {
 public:
@@ -135,6 +139,24 @@
             void operator()(struct hwc_display_contents_1* contents);
     };
 
+    // The semantics of the fences returned by the device differ between
+    // hwc1.set() and hwc2.present(). Read hwcomposer.h and hwcomposer2.h
+    // for more information.
+    //
+    // Release fences in hwc1 are obtained on set() for a frame n and signaled
+    // when the layer buffer is not needed for read operations anymore
+    // (typically on frame n+1). In HWC2, release fences are obtained with a
+    // special call after present() for frame n. These fences signal
+    // on frame n: More specifically, the fence for a given buffer provided in
+    // frame n will signal when the prior buffer is no longer required.
+    //
+    // A retire fence (HWC1) is signaled when a composition is replaced
+    // on the panel whereas a present fence (HWC2) is signaled when a
+    // composition starts to be displayed on a panel.
+    //
+    // The HWC2to1Adapter emulates the new fence semantics for a frame
+    // n by returning the fence from frame n-1. For frame 0, the adapter
+    // returns NO_FENCE.
     class DeferredFence {
         public:
             DeferredFence()
@@ -150,6 +172,7 @@
             }
 
         private:
+            // There are always two fences in this queue.
             std::queue<sp<Fence>> mFences;
     };
 
@@ -234,7 +257,10 @@
 
             bool prepare();
             HWC1Contents cloneRequestedContents() const;
+
+            // Called after hwc.prepare() with responses from the device.
             void setReceivedContents(HWC1Contents contents);
+
             bool hasChanges() const;
             HWC2::Error set(hwc_display_contents_1& hwcContents);
             void addRetireFence(int fenceFd);
@@ -288,6 +314,10 @@
                     std::unordered_map<android_color_mode_t, uint32_t> mHwc1Ids;
             };
 
+            // Store changes requested from the device upon calling prepare().
+            // Handles change request to:
+            //   - Layer composition type.
+            //   - Layer hints.
             class Changes {
                 public:
                     uint32_t getNumTypes() const {
@@ -336,8 +366,13 @@
             void reallocateHwc1Contents();
             void assignHwc1LayerIds();
 
+            // Called after a response to prepare() has been received:
+            // Ingest composition type changes requested by the device.
             void updateTypeChanges(const struct hwc_layer_1& hwc1Layer,
                     const Layer& layer);
+
+            // Called after a response to prepare() has been received:
+            // Ingest layer hint changes requested by the device.
             void updateLayerRequests(const struct hwc_layer_1& hwc1Layer,
                     const Layer& layer);
 
@@ -361,8 +396,11 @@
             mutable std::recursive_mutex mStateMutex;
 
             bool mZIsDirty;
-            HWC1Contents mHwc1RequestedContents;
-            HWC1Contents mHwc1ReceivedContents;
+
+            // Array of structs exchanged between client and hwc1 device.
+            HWC1Contents mHwc1RequestedContents; // Sent to device upon calling prepare().
+            HWC1Contents mHwc1ReceivedContents;  // Returned by device after prepare().
+
             DeferredFence mRetireFence;
 
             // Will only be non-null after the layer has been validated but
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index c82b0c4..3f38c86 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -43,7 +43,7 @@
 
 #include <android/configuration.h>
 
-#include <cutils/log.h>
+#include <android/log.h>
 #include <cutils/properties.h>
 
 #include "HWComposer.h"
@@ -602,7 +602,7 @@
     return mDisplayData[displayId].lastPresentFence;
 }
 
-bool HWComposer::retireFenceRepresentsStartOfScanout() const {
+bool HWComposer::presentFenceRepresentsStartOfScanout() const {
     return mAdapter ? false : true;
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index e63bdd4..2713505 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -121,10 +121,10 @@
     // get the present fence received from the last call to present.
     sp<Fence> getPresentFence(int32_t displayId) const;
 
-    // Returns true if the retire fence represents the start of the display
+    // Returns true if the present fence represents the start of the display
     // controller's scan out. This should be true for all HWC2 implementations,
     // except for the wrapper around HWC1 implementations.
-    bool retireFenceRepresentsStartOfScanout() const;
+    bool presentFenceRepresentsStartOfScanout() const;
 
     // Get last release fence for the given layer
     sp<Fence> getLayerReleaseFence(int32_t displayId,
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
index 2102457..af280a4 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
@@ -39,7 +39,7 @@
 
 #include <android/configuration.h>
 
-#include <cutils/log.h>
+#include <android/log.h>
 #include <cutils/properties.h>
 
 #include <system/graphics.h>
@@ -1031,7 +1031,7 @@
     virtual void setFrame(const Rect& frame) {
         getLayer()->displayFrame = reinterpret_cast<hwc_rect_t const&>(frame);
     }
-    virtual void setCrop(const FloatRect& crop) {
+    virtual void setCrop(const gfx::FloatRect& crop) {
         if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
             getLayer()->sourceCropf = reinterpret_cast<hwc_frect_t const&>(crop);
         } else {
@@ -1159,6 +1159,7 @@
     switch (format) {
     case PIXEL_FORMAT_RGBA_8888:    return String8("RGBA_8888");
     case PIXEL_FORMAT_RGBX_8888:    return String8("RGBx_8888");
+    case PIXEL_FORMAT_RGBA_FP16:    return String8("RGBA_FP16");
     case PIXEL_FORMAT_RGB_888:      return String8("RGB_888");
     case PIXEL_FORMAT_RGB_565:      return String8("RGB_565");
     case PIXEL_FORMAT_BGRA_8888:    return String8("BGRA_8888");
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
index 170e382..bca25ac 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
@@ -48,12 +48,14 @@
 // ---------------------------------------------------------------------------
 
 class Fence;
-class FloatRect;
 class GraphicBuffer;
 class NativeHandle;
 class Region;
 class String8;
 class SurfaceFlinger;
+namespace gfx {
+    class FloatRect;
+}
 
 class HWComposer
 {
@@ -168,7 +170,7 @@
         virtual void setBlending(uint32_t blending) = 0;
         virtual void setTransform(uint32_t transform) = 0;
         virtual void setFrame(const Rect& frame) = 0;
-        virtual void setCrop(const FloatRect& crop) = 0;
+        virtual void setCrop(const gfx::FloatRect& crop) = 0;
         virtual void setVisibleRegionScreen(const Region& reg) = 0;
         virtual void setSurfaceDamage(const Region& reg) = 0;
         virtual void setSidebandStream(const sp<NativeHandle>& stream) = 0;
diff --git a/services/surfaceflinger/DisplayHardware/PowerHAL.cpp b/services/surfaceflinger/DisplayHardware/PowerHAL.cpp
index 1c0a1fe..a6f076e 100644
--- a/services/surfaceflinger/DisplayHardware/PowerHAL.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerHAL.cpp
@@ -18,7 +18,7 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <cutils/log.h>
+#include <android/log.h>
 #include <utils/Errors.h>
 
 #include <binder/IServiceManager.h>
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 0511df2..6a98f03 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -281,7 +281,7 @@
 #endif
                     &qbo);
             if (result == NO_ERROR) {
-                updateQueueBufferOutput(qbo);
+                updateQueueBufferOutput(std::move(qbo));
             }
         } else {
             // If the surface hadn't actually been updated, then we only went
@@ -516,7 +516,8 @@
         mOutputFence = mFbFence;
     }
 
-    *output = mQueueBufferOutput;
+    // This moves the frame timestamps and keeps a copy of all other fields.
+    *output = std::move(mQueueBufferOutput);
     return NO_ERROR;
 }
 
@@ -555,8 +556,9 @@
     status_t result = mSource[SOURCE_SINK]->connect(listener, api,
             producerControlledByApp, &qbo);
     if (result == NO_ERROR) {
-        updateQueueBufferOutput(qbo);
-        *output = mQueueBufferOutput;
+        updateQueueBufferOutput(std::move(qbo));
+        // This moves the frame timestamps and keeps a copy of all other fields.
+        *output = std::move(mQueueBufferOutput);
     }
     return result;
 }
@@ -615,8 +617,8 @@
 }
 
 void VirtualDisplaySurface::updateQueueBufferOutput(
-        const QueueBufferOutput& qbo) {
-    mQueueBufferOutput = qbo;
+        QueueBufferOutput&& qbo) {
+    mQueueBufferOutput = std::move(qbo);
     mQueueBufferOutput.transformHint = 0;
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index b435bf5..d37dc0a 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -136,7 +136,7 @@
     static Source fbSourceForCompositionType(CompositionType type);
     status_t dequeueBuffer(Source source, PixelFormat format, uint32_t usage,
             int* sslot, sp<Fence>* fence);
-    void updateQueueBufferOutput(const QueueBufferOutput& qbo);
+    void updateQueueBufferOutput(QueueBufferOutput&& qbo);
     void resetPerFrameState();
     status_t refreshOutputBuffer();
 
@@ -181,6 +181,8 @@
     // The QueueBufferOutput with the latest info from the sink, and with the
     // transform hint cleared. Since we defer queueBuffer from the GLES driver
     // to the sink, we have to return the previous version.
+    // Moves instead of copies are performed to avoid duplicate
+    // FrameEventHistoryDeltas.
     QueueBufferOutput mQueueBufferOutput;
 
     // Details of the current sink buffer. These become valid when a buffer is
diff --git a/services/surfaceflinger/EventLog/EventLog.cpp b/services/surfaceflinger/EventLog/EventLog.cpp
index 47bab83..365a0bd 100644
--- a/services/surfaceflinger/EventLog/EventLog.cpp
+++ b/services/surfaceflinger/EventLog/EventLog.cpp
@@ -16,7 +16,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <cutils/log.h>
+#include <log/log.h>
 #include <utils/String8.h>
 
 #include "EventLog.h"
diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp
index c09bbe4..99c4daa 100644
--- a/services/surfaceflinger/FrameTracker.cpp
+++ b/services/surfaceflinger/FrameTracker.cpp
@@ -19,13 +19,11 @@
 
 #include <inttypes.h>
 
-#include <cutils/log.h>
-
-#include <ui/Fence.h>
-#include <ui/FrameStats.h>
-
+#include <android/log.h>
 #include <utils/String8.h>
 
+#include <ui/FrameStats.h>
+
 #include "FrameTracker.h"
 #include "EventLog/EventLog.h"
 
@@ -48,9 +46,10 @@
     mFrameRecords[mOffset].frameReadyTime = readyTime;
 }
 
-void FrameTracker::setFrameReadyFence(const sp<Fence>& readyFence) {
+void FrameTracker::setFrameReadyFence(
+        std::shared_ptr<FenceTime>&& readyFence) {
     Mutex::Autolock lock(mMutex);
-    mFrameRecords[mOffset].frameReadyFence = readyFence;
+    mFrameRecords[mOffset].frameReadyFence = std::move(readyFence);
     mNumFences++;
 }
 
@@ -59,9 +58,10 @@
     mFrameRecords[mOffset].actualPresentTime = presentTime;
 }
 
-void FrameTracker::setActualPresentFence(const sp<Fence>& readyFence) {
+void FrameTracker::setActualPresentFence(
+        std::shared_ptr<FenceTime>&& readyFence) {
     Mutex::Autolock lock(mMutex);
-    mFrameRecords[mOffset].actualPresentFence = readyFence;
+    mFrameRecords[mOffset].actualPresentFence = std::move(readyFence);
     mNumFences++;
 }
 
@@ -95,10 +95,6 @@
         mFrameRecords[mOffset].actualPresentFence = NULL;
         mNumFences--;
     }
-
-    // Clean up the signaled fences to keep the number of open fence FDs in
-    // this process reasonable.
-    processFencesLocked();
 }
 
 void FrameTracker::clearStats() {
@@ -107,8 +103,8 @@
         mFrameRecords[i].desiredPresentTime = 0;
         mFrameRecords[i].frameReadyTime = 0;
         mFrameRecords[i].actualPresentTime = 0;
-        mFrameRecords[i].frameReadyFence.clear();
-        mFrameRecords[i].actualPresentFence.clear();
+        mFrameRecords[i].frameReadyFence.reset();
+        mFrameRecords[i].actualPresentFence.reset();
     }
     mNumFences = 0;
     mFrameRecords[mOffset].desiredPresentTime = INT64_MAX;
@@ -156,7 +152,7 @@
         size_t idx = (mOffset+NUM_FRAME_RECORDS-i) % NUM_FRAME_RECORDS;
         bool updated = false;
 
-        const sp<Fence>& rfence = records[idx].frameReadyFence;
+        const std::shared_ptr<FenceTime>& rfence = records[idx].frameReadyFence;
         if (rfence != NULL) {
             records[idx].frameReadyTime = rfence->getSignalTime();
             if (records[idx].frameReadyTime < INT64_MAX) {
@@ -166,7 +162,8 @@
             }
         }
 
-        const sp<Fence>& pfence = records[idx].actualPresentFence;
+        const std::shared_ptr<FenceTime>& pfence =
+                records[idx].actualPresentFence;
         if (pfence != NULL) {
             records[idx].actualPresentTime = pfence->getSignalTime();
             if (records[idx].actualPresentTime < INT64_MAX) {
diff --git a/services/surfaceflinger/FrameTracker.h b/services/surfaceflinger/FrameTracker.h
index cd5e3f3..adcdfb5 100644
--- a/services/surfaceflinger/FrameTracker.h
+++ b/services/surfaceflinger/FrameTracker.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_FRAMETRACKER_H
 #define ANDROID_FRAMETRACKER_H
 
+#include <ui/FenceTime.h>
+
 #include <stddef.h>
 
 #include <utils/Mutex.h>
@@ -26,7 +28,6 @@
 namespace android {
 
 class String8;
-class Fence;
 
 // FrameTracker tracks information about the most recently rendered frames. It
 // uses a circular buffer of frame records, and is *NOT* thread-safe -
@@ -60,7 +61,7 @@
 
     // setFrameReadyFence sets the fence that is used to get the time at which
     // the current frame became ready to be presented to the user.
-    void setFrameReadyFence(const sp<Fence>& readyFence);
+    void setFrameReadyFence(std::shared_ptr<FenceTime>&& readyFence);
 
     // setActualPresentTime sets the timestamp at which the current frame became
     // visible to the user.
@@ -68,7 +69,7 @@
 
     // setActualPresentFence sets the fence that is used to get the time
     // at which the current frame became visible to the user.
-    void setActualPresentFence(const sp<Fence>& fence);
+    void setActualPresentFence(std::shared_ptr<FenceTime>&& fence);
 
     // setDisplayRefreshPeriod sets the display refresh period in nanoseconds.
     // This is used to compute frame presentation duration statistics relative
@@ -100,8 +101,8 @@
         nsecs_t desiredPresentTime;
         nsecs_t frameReadyTime;
         nsecs_t actualPresentTime;
-        sp<Fence> frameReadyFence;
-        sp<Fence> actualPresentFence;
+        std::shared_ptr<FenceTime> frameReadyFence;
+        std::shared_ptr<FenceTime> actualPresentFence;
     };
 
     // processFences iterates over all the frame records that have a fence set
diff --git a/services/surfaceflinger/GpuService.cpp b/services/surfaceflinger/GpuService.cpp
index b993dfb..71052fb 100644
--- a/services/surfaceflinger/GpuService.cpp
+++ b/services/surfaceflinger/GpuService.cpp
@@ -16,6 +16,7 @@
 
 #include "GpuService.h"
 
+#include <binder/IResultReceiver.h>
 #include <binder/Parcel.h>
 #include <utils/String8.h>
 #include <vkjson.h>
@@ -35,6 +36,7 @@
 status_t BnGpuService::onTransact(uint32_t code, const Parcel& data,
         Parcel* reply, uint32_t flags)
 {
+    status_t status;
     switch (code) {
     case SHELL_COMMAND_TRANSACTION: {
         int in = data.readFileDescriptor();
@@ -45,7 +47,16 @@
         for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
            args.add(data.readString16());
         }
-        return shellCommand(in, out, err, args);
+        sp<IBinder> unusedCallback;
+        sp<IResultReceiver> resultReceiver;
+        if ((status = data.readNullableStrongBinder(&unusedCallback)) != OK)
+            return status;
+        if ((status = data.readNullableStrongBinder(&resultReceiver)) != OK)
+            return status;
+        status = shellCommand(in, out, err, args);
+        if (resultReceiver != nullptr)
+            resultReceiver->send(status);
+        return OK;
     }
 
     default:
@@ -71,12 +82,15 @@
     for (size_t i = 0, n = args.size(); i < n; i++)
         ALOGV("  arg[%zu]: '%s'", i, String8(args[i]).string());
 
-    if (args[0] == String16("vkjson"))
-        return cmd_vkjson(out, err);
-    else if (args[0] == String16("help"))
-        return cmd_help(out);
-
-    return NO_ERROR;
+    if (args.size() >= 1) {
+        if (args[0] == String16("vkjson"))
+            return cmd_vkjson(out, err);
+        if (args[0] == String16("help"))
+            return cmd_help(out);
+    }
+    // no command, or unrecognized command
+    cmd_help(err);
+    return BAD_VALUE;
 }
 
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 38b6eca..9eaf57b 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -165,9 +165,9 @@
     mSurfaceFlingerConsumer->setContentsChangedListener(this);
     mSurfaceFlingerConsumer->setName(mName);
 
-#ifndef TARGET_DISABLE_TRIPLE_BUFFERING
-    mProducer->setMaxDequeuedBufferCount(2);
-#endif
+    if (mFlinger->isLayerTripleBufferingDisabled()) {
+        mProducer->setMaxDequeuedBufferCount(2);
+    }
 
     const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
     updateTransformHint(hw);
@@ -377,10 +377,10 @@
     return reduce(win, activeTransparentRegion);
 }
 
-FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
+gfx::FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
     // the content crop is the area of the content that gets scaled to the
     // layer's size.
-    FloatRect crop(getContentCrop());
+    gfx::FloatRect crop = getContentCrop().toFloatRect();
 
     // the crop is the area of the window that gets cropped, but not
     // scaled in any ways.
@@ -585,7 +585,7 @@
         hwcInfo.displayFrame = transformedFrame;
     }
 
-    FloatRect sourceCrop = computeCrop(displayDevice);
+    gfx::FloatRect sourceCrop = computeCrop(displayDevice);
     error = hwcLayer->setSourceCrop(sourceCrop);
     if (error != HWC2::Error::None) {
         ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
@@ -1189,6 +1189,7 @@
     switch (format) {
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_RGBA_FP16:
             return false;
     }
     // in all other case, we have no blending (also for unknown formats)
@@ -1740,41 +1741,23 @@
     return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
 }
 
-bool Layer::onPostComposition(sp<Fence> glDoneFence) {
+bool Layer::onPostComposition(
+        const std::shared_ptr<FenceTime>& glDoneFence,
+        const std::shared_ptr<FenceTime>& presentFence,
+        const std::shared_ptr<FenceTime>& retireFence) {
+    mAcquireTimeline.updateSignalTimes();
+    mReleaseTimeline.updateSignalTimes();
+
     // mFrameLatencyNeeded is true when a new frame was latched for the
     // composition.
-
     if (!mFrameLatencyNeeded)
         return false;
 
-    const HWComposer& hwc = mFlinger->getHwComposer();
-#ifdef USE_HWC2
-    sp<Fence> retireFence = Fence::NO_FENCE;
-    sp<Fence> presentFence = Fence::NO_FENCE;
-    sp<Fence> presentOrRetireFence = Fence::NO_FENCE;
-    if (hwc.retireFenceRepresentsStartOfScanout()) {
-        presentFence = hwc.getPresentFence(HWC_DISPLAY_PRIMARY);
-        presentOrRetireFence = presentFence;
-    } else {
-        retireFence = hwc.getPresentFence(HWC_DISPLAY_PRIMARY);
-        presentOrRetireFence = retireFence;
-    }
-    bool wasGpuComposited = mHwcLayers.count(HWC_DISPLAY_PRIMARY) ?
-            mHwcLayers.at(HWC_DISPLAY_PRIMARY).compositionType ==
-            HWC2::Composition::Client : true;
-#else
-    sp<Fence> retireFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
-    sp<Fence> presentFence = Fence::NO_FENCE;
-    sp<Fence> presentOrRetireFence = retireFence;
-    bool wasGpuComposited = mIsGlesComposition;
-#endif
-
     // Update mFrameEventHistory.
     {
         Mutex::Autolock lock(mFrameEventHistoryMutex);
         mFrameEventHistory.addPostComposition(mCurrentFrameNumber,
-                wasGpuComposited ? glDoneFence : Fence::NO_FENCE,
-                presentFence);
+                glDoneFence, presentFence);
         mFrameEventHistory.addRetire(mPreviousFrameNumber,
                 retireFence);
     }
@@ -1783,22 +1766,28 @@
     nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp();
     mFrameTracker.setDesiredPresentTime(desiredPresentTime);
 
-    sp<Fence> frameReadyFence = mSurfaceFlingerConsumer->getCurrentFence();
+    std::shared_ptr<FenceTime> frameReadyFence =
+            mSurfaceFlingerConsumer->getCurrentFenceTime();
     if (frameReadyFence->isValid()) {
-        mFrameTracker.setFrameReadyFence(frameReadyFence);
+        mFrameTracker.setFrameReadyFence(std::move(frameReadyFence));
     } else {
         // There was no fence for this frame, so assume that it was ready
         // to be presented at the desired present time.
         mFrameTracker.setFrameReadyTime(desiredPresentTime);
     }
 
-    if (presentOrRetireFence->isValid()) {
-        mFrameTracker.setActualPresentFence(presentOrRetireFence);
+    if (presentFence->isValid()) {
+        mFrameTracker.setActualPresentFence(
+                std::shared_ptr<FenceTime>(presentFence));
+    } else if (retireFence->isValid()) {
+        mFrameTracker.setActualPresentFence(
+                std::shared_ptr<FenceTime>(retireFence));
     } else {
         // The HWC doesn't support present fences, so use the refresh
         // timestamp instead.
-        nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
-        mFrameTracker.setActualPresentTime(presentTime);
+        mFrameTracker.setActualPresentTime(
+            mFlinger->getHwComposer().getRefreshTimestamp(
+                HWC_DISPLAY_PRIMARY));
     }
 
     mFrameTracker.advanceFrame();
@@ -1809,9 +1798,13 @@
 #ifdef USE_HWC2
 void Layer::releasePendingBuffer() {
     mSurfaceFlingerConsumer->releasePendingBuffer();
-    Mutex::Autolock lock(mFrameEventHistoryMutex);
-    mFrameEventHistory.addRelease(mPreviousFrameNumber,
+    auto releaseFenceTime = std::make_shared<FenceTime>(
             mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
+    mReleaseTimeline.push(releaseFenceTime);
+
+    Mutex::Autolock lock(mFrameEventHistoryMutex);
+    mFrameEventHistory.addRelease(
+            mPreviousFrameNumber, std::move(releaseFenceTime));
 }
 #endif
 
@@ -1984,8 +1977,11 @@
         Mutex::Autolock lock(mFrameEventHistoryMutex);
         mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime);
 #ifndef USE_HWC2
-        mFrameEventHistory.addRelease(mPreviousFrameNumber,
+        auto releaseFenceTime = std::make_shared<FenceTime>(
                 mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
+        mReleaseTimeline.push(releaseFenceTime);
+        mFrameEventHistory.addRelease(
+                mPreviousFrameNumber, std::move(releaseFenceTime));
 #endif
     }
 
@@ -2183,7 +2179,7 @@
     const Rect& frame = hwcInfo.displayFrame;
     result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top,
             frame.right, frame.bottom);
-    const FloatRect& crop = hwcInfo.sourceCrop;
+    const gfx::FloatRect& crop = hwcInfo.sourceCrop;
     result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top,
             crop.right, crop.bottom);
 
@@ -2220,6 +2216,7 @@
         FrameEventHistoryDelta *outDelta) {
     Mutex::Autolock lock(mFrameEventHistoryMutex);
     if (newTimestamps) {
+        mAcquireTimeline.push(newTimestamps->acquireFence);
         mFrameEventHistory.addQueue(*newTimestamps);
     }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index f006726..c3eab37 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -27,6 +27,8 @@
 #include <utils/String8.h>
 #include <utils/Timers.h>
 
+#include <gfx/FloatRect.h>
+
 #include <ui/FrameStats.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
@@ -46,7 +48,6 @@
 #include "Transform.h"
 
 #include "DisplayHardware/HWComposer.h"
-#include "DisplayHardware/FloatRect.h"
 #include "RenderEngine/Mesh.h"
 #include "RenderEngine/Texture.h"
 
@@ -121,9 +122,11 @@
         int32_t sequence; // changes when visible regions can change
         bool modified;
 
+        // Crop is expressed in layer space coordinate.
         Rect crop;
         Rect requestedCrop;
 
+        // finalCrop is expressed in display space coordinate.
         Rect finalCrop;
 
         // If set, defers this state update until the Layer identified by handle
@@ -276,7 +279,10 @@
      * called after composition.
      * returns true if the layer latched a new buffer this frame.
      */
-    bool onPostComposition(sp<Fence> glCompositionDoneFence);
+    bool onPostComposition(
+            const std::shared_ptr<FenceTime>& glDoneFence,
+            const std::shared_ptr<FenceTime>& presentFence,
+            const std::shared_ptr<FenceTime>& retireFence);
 
 #ifdef USE_HWC2
     // If a buffer was replaced this frame, release the former buffer
@@ -454,7 +460,7 @@
     bool needsFiltering(const sp<const DisplayDevice>& hw) const;
 
     uint32_t getEffectiveUsage(uint32_t usage) const;
-    FloatRect computeCrop(const sp<const DisplayDevice>& hw) const;
+    gfx::FloatRect computeCrop(const sp<const DisplayDevice>& hw) const;
     bool isCropped() const;
     static bool getOpacityForFormat(uint32_t format);
 
@@ -586,6 +592,8 @@
     // Accessed by both consumer and producer on main and binder threads.
     Mutex mFrameEventHistoryMutex;
     ConsumerFrameEventHistory mFrameEventHistory;
+    FenceTimeline mAcquireTimeline;
+    FenceTimeline mReleaseTimeline;
 
     // main thread
     sp<GraphicBuffer> mActiveBuffer;
@@ -624,7 +632,7 @@
         HWC2::Composition compositionType;
         bool clearClientTarget;
         Rect displayFrame;
-        FloatRect sourceCrop;
+        gfx::FloatRect sourceCrop;
     };
     std::unordered_map<int32_t, HWCInfo> mHwcLayers;
 #else
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 359ca4e..8bf6e82 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -49,7 +49,7 @@
         wp<IBinder> mProducer;
     };
 
-    mFlinger->postMessageAsync(new MessageCleanUpList(mFlinger, asBinder(this)));
+    mFlinger->postMessageAsync(new MessageCleanUpList(mFlinger, asBinder(mProducer)));
 }
 
 status_t MonitoredProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
@@ -156,7 +156,7 @@
 }
 
 IBinder* MonitoredProducer::onAsBinder() {
-    return IInterface::asBinder(mProducer).get();
+    return this;
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index 17adaa7..becc740 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -27,7 +27,7 @@
 
 // MonitoredProducer wraps an IGraphicBufferProducer so that SurfaceFlinger will
 // be notified upon its destruction
-class MonitoredProducer : public IGraphicBufferProducer {
+class MonitoredProducer : public BnGraphicBufferProducer {
 public:
     MonitoredProducer(const sp<IGraphicBufferProducer>& producer,
             const sp<SurfaceFlinger>& flinger);
diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp
index 0424e0c..38a0039 100644
--- a/services/surfaceflinger/RenderEngine/Program.cpp
+++ b/services/surfaceflinger/RenderEngine/Program.cpp
@@ -16,12 +16,12 @@
 
 #include <stdint.h>
 
-#include <log/log.h>
+#include <android/log.h>
+#include <utils/String8.h>
 
 #include "Program.h"
 #include "ProgramCache.h"
 #include "Description.h"
-#include <utils/String8.h>
 
 namespace android {
 
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 2b82d0e..986c6df 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include <cutils/log.h>
+#include <android/log.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index dde8d11..193b702 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -28,7 +28,7 @@
 
 #include <EGL/egl.h>
 
-#include <cutils/log.h>
+#include <android/log.h>
 #include <cutils/properties.h>
 
 #include <binder/IPCThreadState.h>
@@ -189,6 +189,10 @@
     property_get("debug.sf.disable_hwc_vds", value, "0");
     mUseHwcVirtualDisplays = !atoi(value);
     ALOGI_IF(!mUseHwcVirtualDisplays, "Disabling HWC virtual displays");
+
+    property_get("ro.sf.disable_triple_buffer", value, "0");
+    mLayerTripleBufferingDisabled = !atoi(value);
+    ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering");
 }
 
 void SurfaceFlinger::onFirstRef()
@@ -573,7 +577,7 @@
         FrameEvent::ACQUIRE,
         FrameEvent::FIRST_REFRESH_START,
         FrameEvent::GL_COMPOSITION_DONE,
-        getHwComposer().retireFenceRepresentsStartOfScanout() ?
+        getHwComposer().presentFenceRepresentsStartOfScanout() ?
                 FrameEvent::DISPLAY_PRESENT : FrameEvent::DISPLAY_RETIRE,
         FrameEvent::RELEASE,
     };
@@ -1226,26 +1230,45 @@
         layer->releasePendingBuffer();
     }
 
-    bool hadClientComposition = mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY);
-
     const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
-    sp<Fence> glCompositionDoneFence = hadClientComposition
-                                     ? hw->getClientTargetAcquireFence()
-                                     : Fence::NO_FENCE;
+
+    std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
+    if (mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) {
+        glCompositionDoneFenceTime =
+                std::make_shared<FenceTime>(hw->getClientTargetAcquireFence());
+        mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime);
+    } else {
+        glCompositionDoneFenceTime = FenceTime::NO_FENCE;
+    }
+    mGlCompositionDoneTimeline.updateSignalTimes();
+
+    sp<Fence> displayFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
+    auto displayFenceTime = std::make_shared<FenceTime>(displayFence);
+    mDisplayTimeline.push(displayFenceTime);
+    mDisplayTimeline.updateSignalTimes();
+
+    const std::shared_ptr<FenceTime>* presentFenceTime = &FenceTime::NO_FENCE;
+    const std::shared_ptr<FenceTime>* retireFenceTime = &FenceTime::NO_FENCE;
+    if (mHwc->presentFenceRepresentsStartOfScanout()) {
+        presentFenceTime = &displayFenceTime;
+    } else {
+        retireFenceTime = &displayFenceTime;
+    }
+
     const LayerVector& layers(mDrawingState.layersSortedByZ);
     const size_t count = layers.size();
     for (size_t i=0 ; i<count ; i++) {
-        bool frameLatched = layers[i]->onPostComposition(glCompositionDoneFence);
+        bool frameLatched =
+                layers[i]->onPostComposition(glCompositionDoneFenceTime,
+                        *presentFenceTime, *retireFenceTime);
         if (frameLatched) {
             recordBufferingStats(layers[i]->getName().string(),
                     layers[i]->getOccupancyHistory(false));
         }
     }
 
-    sp<Fence> presentFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
-
-    if (presentFence->isValid()) {
-        if (mPrimaryDispSync.addPresentFence(presentFence)) {
+    if (displayFence->isValid()) {
+        if (mPrimaryDispSync.addPresentFence(displayFence)) {
             enableHardwareVsync();
         } else {
             disableHardwareVsync(false);
@@ -1261,8 +1284,9 @@
     if (mAnimCompositionPending) {
         mAnimCompositionPending = false;
 
-        if (presentFence->isValid()) {
-            mAnimFrameTracker.setActualPresentFence(presentFence);
+        if (displayFenceTime->isValid()) {
+            mAnimFrameTracker.setActualPresentFence(
+                    std::move(displayFenceTime));
         } else {
             // The HWC doesn't support present fences, so use the refresh
             // timestamp instead.
@@ -2932,21 +2956,18 @@
     mAnimFrameTracker.logAndResetStats(String8("<win-anim>"));
 }
 
-/*static*/ void SurfaceFlinger::appendSfConfigString(String8& result)
+void SurfaceFlinger::appendSfConfigString(String8& result) const
 {
-    static const char* config =
-            " [sf"
+    result.append(" [sf");
 #ifdef HAS_CONTEXT_PRIORITY
-            " HAS_CONTEXT_PRIORITY"
+    result.append(" HAS_CONTEXT_PRIORITY");
 #endif
 #ifdef NEVER_DEFAULT_TO_ASYNC_MODE
-            " NEVER_DEFAULT_TO_ASYNC_MODE"
+    result.append(" NEVER_DEFAULT_TO_ASYNC_MODE");
 #endif
-#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
-            " TARGET_DISABLE_TRIPLE_BUFFERING"
-#endif
-            "]";
-    result.append(config);
+    if (isLayerTripleBufferingDisabled())
+        result.append(" DISABLE_TRIPLE_BUFFERING");
+    result.append("]");
 }
 
 void SurfaceFlinger::dumpStaticScreenStats(String8& result) const
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 4ec1a72..f7f9ef5 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -37,6 +37,7 @@
 
 #include <binder/IMemory.h>
 
+#include <ui/FenceTime.h>
 #include <ui/PixelFormat.h>
 #include <ui/mat4.h>
 
@@ -437,7 +438,7 @@
     void clearStatsLocked(const Vector<String16>& args, size_t& index, String8& result);
     void dumpAllLocked(const Vector<String16>& args, size_t& index, String8& result) const;
     bool startDdmConnection();
-    static void appendSfConfigString(String8& result);
+    void appendSfConfigString(String8& result) const;
     void checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr,
             const sp<const DisplayDevice>& hw,
             uint32_t minLayerZ, uint32_t maxLayerZ);
@@ -452,6 +453,9 @@
             std::vector<OccupancyTracker::Segment>&& history);
     void dumpBufferingStats(String8& result) const;
 
+    bool isLayerTripleBufferingDisabled() const {
+        return this->mLayerTripleBufferingDisabled;
+    }
     /* ------------------------------------------------------------------------
      * Attributes
      */
@@ -501,6 +505,8 @@
     sp<Fence> mPreviousPresentFence = Fence::NO_FENCE;
     bool mHadClientComposition = false;
 #endif
+    FenceTimeline mGlCompositionDoneTimeline;
+    FenceTimeline mDisplayTimeline;
 
     // this may only be written from the main thread with mStateLock held
     // it may be read from other threads with mStateLock held
@@ -523,6 +529,9 @@
     SurfaceInterceptor mInterceptor;
     bool mUseHwcVirtualDisplays = true;
 
+    // Restrict layers to use two buffers in their bufferqueues.
+    bool mLayerTripleBufferingDisabled = false;
+
     // these are thread safe
     mutable MessageQueue mEventQueue;
     FrameTracker mAnimFrameTracker;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 55edc15..5c42450 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -27,7 +27,7 @@
 
 #include <EGL/egl.h>
 
-#include <cutils/log.h>
+#include <android/log.h>
 #include <cutils/properties.h>
 
 #include <binder/IPCThreadState.h>
@@ -164,7 +164,6 @@
 {
     ALOGI("SurfaceFlinger is starting");
 
-    // debugging stuff...
     char value[PROPERTY_VALUE_MAX];
 
     property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
@@ -187,6 +186,10 @@
     property_get("debug.sf.disable_hwc_vds", value, "0");
     mUseHwcVirtualDisplays = !atoi(value);
     ALOGI_IF(!mUseHwcVirtualDisplays, "Disabling HWC virtual displays");
+
+    property_get("ro.sf.disable_triple_buffer", value, "0");
+    mLayerTripleBufferingDisabled = !atoi(value);
+    ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering");
 }
 
 void SurfaceFlinger::onFirstRef()
@@ -1136,27 +1139,35 @@
     const HWComposer& hwc = getHwComposer();
     const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
 
-    bool hadGlesComposition =
-            getHwComposer().hasGlesComposition(hw->getHwcDisplayId());
-    sp<Fence> glCompositionDoneFence = hadGlesComposition
-                                     ? hw->getClientTargetAcquireFence()
-                                     : Fence::NO_FENCE;
+    std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
+    if (getHwComposer().hasGlesComposition(hw->getHwcDisplayId())) {
+        glCompositionDoneFenceTime =
+                std::make_shared<FenceTime>(hw->getClientTargetAcquireFence());
+        mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime);
+    } else {
+        glCompositionDoneFenceTime = FenceTime::NO_FENCE;
+    }
+    mGlCompositionDoneTimeline.updateSignalTimes();
+
+    sp<Fence> displayFence = mHwc->getDisplayFence(HWC_DISPLAY_PRIMARY);
+    const std::shared_ptr<FenceTime>& presentFenceTime = FenceTime::NO_FENCE;
+    auto retireFenceTime = std::make_shared<FenceTime>(displayFence);
+    mDisplayTimeline.push(retireFenceTime);
+    mDisplayTimeline.updateSignalTimes();
 
     const LayerVector& layers(mDrawingState.layersSortedByZ);
     const size_t count = layers.size();
     for (size_t i=0 ; i<count ; i++) {
         bool frameLatched = layers[i]->onPostComposition(
-                glCompositionDoneFence);
+                glCompositionDoneFenceTime, presentFenceTime, retireFenceTime);
         if (frameLatched) {
             recordBufferingStats(layers[i]->getName().string(),
                     layers[i]->getOccupancyHistory(false));
         }
     }
 
-    sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
-
-    if (presentFence->isValid()) {
-        if (mPrimaryDispSync.addPresentFence(presentFence)) {
+    if (displayFence->isValid()) {
+        if (mPrimaryDispSync.addPresentFence(displayFence)) {
             enableHardwareVsync();
         } else {
             disableHardwareVsync(false);
@@ -1172,8 +1183,8 @@
     if (mAnimCompositionPending) {
         mAnimCompositionPending = false;
 
-        if (presentFence->isValid()) {
-            mAnimFrameTracker.setActualPresentFence(presentFence);
+        if (retireFenceTime->isValid()) {
+            mAnimFrameTracker.setActualPresentFence(std::move(retireFenceTime));
         } else {
             // The HWC doesn't support present fences, so use the refresh
             // timestamp instead.
@@ -2851,21 +2862,18 @@
     mAnimFrameTracker.logAndResetStats(String8("<win-anim>"));
 }
 
-/*static*/ void SurfaceFlinger::appendSfConfigString(String8& result)
+void SurfaceFlinger::appendSfConfigString(String8& result) const
 {
-    static const char* config =
-            " [sf"
+    result.append(" [sf");
 #ifdef HAS_CONTEXT_PRIORITY
-            " HAS_CONTEXT_PRIORITY"
+    result.append(" HAS_CONTEXT_PRIORITY");
 #endif
 #ifdef NEVER_DEFAULT_TO_ASYNC_MODE
-            " NEVER_DEFAULT_TO_ASYNC_MODE"
+    result.append(" NEVER_DEFAULT_TO_ASYNC_MODE");
 #endif
-#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
-            " TARGET_DISABLE_TRIPLE_BUFFERING"
-#endif
-            "]";
-    result.append(config);
+    if (isLayerTripleBufferingDisabled())
+        result.append(" DISABLE_TRIPLE_BUFFERING");
+    result.append("]");
 }
 
 void SurfaceFlinger::dumpStaticScreenStats(String8& result) const
diff --git a/vulkan/api/platform.api b/vulkan/api/platform.api
index 7aa19e7..fb8e3ce 100644
--- a/vulkan/api/platform.api
+++ b/vulkan/api/platform.api
@@ -48,3 +48,5 @@
 // VK_USE_PLATFORM_WIN32_KHR
 @internal type void* HINSTANCE
 @internal type void* HWND
+@internal type void* HANDLE
+@internal class SECURITY_ATTRIBUTES {}
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
index 37cc448..ed89fc6 100644
--- a/vulkan/api/vulkan.api
+++ b/vulkan/api/vulkan.api
@@ -28,7 +28,7 @@
 // API version (major.minor.patch)
 define VERSION_MAJOR 1
 define VERSION_MINOR 0
-define VERSION_PATCH 22
+define VERSION_PATCH 38
 
 // API limits
 define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
@@ -75,10 +75,16 @@
 @extension("VK_KHR_win32_surface") define VK_KHR_WIN32_SURFACE_SPEC_VERSION     5
 @extension("VK_KHR_win32_surface") define VK_KHR_WIN32_SURFACE_NAME             "VK_KHR_win32_surface"
 
-@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION     5
+@extension("VK_KHR_incremental_present") define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1
+@extension("VK_KHR_incremental_present") define VK_KHR_INCREMENTAL_PRESENT_NAME         "VK_KHR_incremental_present"
+
+@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION     6
 @extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_NAME             "VK_ANDROID_native_buffer"
 
-@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION       3
+@extension("VK_GOOGLE_display_timing") define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION     1
+@extension("VK_GOOGLE_display_timing") define VK_GOOGLE_DISPLAY_TIMING_NAME             "VK_GOOGLE_display_timing"
+
+@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION       4
 @extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_NAME               "VK_EXT_debug_report"
 
 @extension("VK_NV_glsl_shader") define VK_NV_GLSL_SHADER_SPEC_VERSION           1
@@ -108,6 +114,43 @@
 @extension("VK_NV_dedicated_allocation") define VK_NV_DEDICATED_ALLOCATION_SPEC_VERSION 1
 @extension("VK_NV_dedicated_allocation") define VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME "VK_NV_dedicated_allocation"
 
+@extension("VK_KHR_get_physical_device_properties2") define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 1
+@extension("VK_KHR_get_physical_device_properties2") define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2"
+
+@extension("VK_AMD_draw_indirect_count") define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
+@extension("VK_AMD_draw_indirect_count") define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count"
+
+@extension("VK_AMD_negative_viewport_height") define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION 1
+@extension("VK_AMD_negative_viewport_height") define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME "VK_AMD_negative_viewport_height"
+
+@extension("VK_AMD_gpu_shader_half_float") define VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION 1
+@extension("VK_AMD_gpu_shader_half_float") define VK_AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME "VK_AMD_gpu_shader_half_float"
+
+@extension("VK_AMD_shader_ballot") define VK_AMD_SHADER_BALLOT_SPEC_VERSION 1
+@extension("VK_AMD_shader_ballot") define VK_AMD_SHADER_BALLOT_EXTENSION_NAME "VK_AMD_shader_ballot"
+
+@extension("VK_IMG_format_pvrtc") define VK_IMG_FORMAT_PVRTC_SPEC_VERSION 1
+@extension("VK_IMG_format_pvrtc") define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc"
+
+@extension("VK_NV_external_memory_capabilities") define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
+@extension("VK_NV_external_memory_capabilities") define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_NV_external_memory_capabilities"
+
+@extension("VK_NV_external_memory") define VK_NV_EXTERNAL_MEMORY_SPEC_VERSION 1
+@extension("VK_NV_external_memory") define VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME "VK_NV_external_memory"
+
+@extension("VK_NV_external_memory_win32") define VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
+@extension("VK_NV_external_memory_win32") define VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_NV_external_memory_win32"
+
+@extension("VK_NV_win32_keyed_mutex") define VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION 1
+@extension("VK_NV_win32_keyed_mutex") define VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_NV_win32_keyed_mutex"
+
+@extension("VK_EXT_validation_flags") define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 1
+@extension("VK_EXT_validation_flags") define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags"
+
+@extension("VK_NVX_device_generated_commands") define VK_NVX_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 1
+@extension("VK_NVX_device_generated_commands") define VK_NVX_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NVX_device_generated_commands"
+
+
 
 /////////////
 //  Types  //
@@ -156,6 +199,9 @@
 
 @extension("VK_EXT_debug_report") @nonDispatchHandle type u64 VkDebugReportCallbackEXT
 
+@extension("VK_NVX_device_generated_commands") @nonDispatchHandle type u64 VkObjectTableNVX
+@extension("VK_NVX_device_generated_commands") @nonDispatchHandle type u64 VkIndirectCommandsLayoutNVX
+
 
 /////////////
 //  Enums  //
@@ -596,6 +642,30 @@
     VK_FORMAT_ASTC_12x10_SRGB_BLOCK                         = 182,
     VK_FORMAT_ASTC_12x12_UNORM_BLOCK                        = 183,
     VK_FORMAT_ASTC_12x12_SRGB_BLOCK                         = 184,
+
+    //@extension("VK_IMG_format_pvrtc")
+    VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000,
+
+    //@extension("VK_IMG_format_pvrtc")
+    VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001,
+
+    //@extension("VK_IMG_format_pvrtc")
+    VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG = 1000054002,
+
+    //@extension("VK_IMG_format_pvrtc")
+    VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG = 1000054003,
+
+    //@extension("VK_IMG_format_pvrtc")
+    VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG = 1000054004,
+
+    //@extension("VK_IMG_format_pvrtc")
+    VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005,
+
+    //@extension("VK_IMG_format_pvrtc")
+    VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006,
+
+    //@extension("VK_IMG_format_pvrtc")
+    VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007,
 }
 
 /// Structure type enumerant
@@ -679,8 +749,15 @@
     //@extension("VK_KHR_win32_surface")
     VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR             = 1000009000,
 
+    //@extension("VK_KHR_incremental_present")
+    VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR                       = 1000084000,
+
     //@extension("VK_ANDROID_native_buffer")
     VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID                     = 1000010000,
+    VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID       = 1000010001,
+
+    //@extension("VK_GOOGLE_display_timing")
+    VK_STRUCTURE_TYPE_PRESENT_TIMES_GOOGLE                      = 1000092000,
 
     //@extension("VK_EXT_debug_report")
     VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT     = 1000011000,
@@ -705,6 +782,72 @@
 
     //@extension("VK_NV_dedicated_allocation")
     VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002,
+
+    //@extension("VK_NV_external_memory")
+    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000,
+
+    //@extension("VK_NV_external_memory")
+    VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001,
+
+    //@extension("VK_NV_external_memory_win32")
+    VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000,
+
+    //@extension("VK_NV_external_memory_win32")
+    VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057001,
+
+    //@extension("VK_NV_win32_keyed_mutex")
+    VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000,
+
+    //@extension("VK_KHR_get_physical_device_properties2")
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR = 1000059000,
+
+    //@extension("VK_KHR_get_physical_device_properties2")
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR = 1000059001,
+
+    //@extension("VK_KHR_get_physical_device_properties2")
+    VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR = 1000059002,
+
+    //@extension("VK_KHR_get_physical_device_properties2")
+    VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059003,
+
+    //@extension("VK_KHR_get_physical_device_properties2")
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR = 1000059004,
+
+    //@extension("VK_KHR_get_physical_device_properties2")
+    VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR = 1000059005,
+
+    //@extension("VK_KHR_get_physical_device_properties2")
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR = 1000059006,
+
+    //@extension("VK_KHR_get_physical_device_properties2")
+    VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059007,
+
+    //@extension("VK_KHR_get_physical_device_properties2")
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = 1000059008,
+
+    //@extension("VK_EXT_validation_flags")
+    VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000,
+
+    //@extension("VK_KHR_incremental_present")
+    VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
+
+    //@extension("VK_NVX_device_generated_commands")
+    VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000,
+
+    //@extension("VK_NVX_device_generated_commands")
+    VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001,
+
+    //@extension("VK_NVX_device_generated_commands")
+    VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX = 1000086002,
+
+    //@extension("VK_NVX_device_generated_commands")
+    VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX = 1000086003,
+
+    //@extension("VK_NVX_device_generated_commands")
+    VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX = 1000086004,
+
+    //@extension("VK_NVX_device_generated_commands")
+    VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX = 1000086005,
 }
 
 enum VkSubpassContents {
@@ -819,6 +962,10 @@
     VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT             = 26,
     VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT           = 27,
     VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT            = 28,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT             = 29,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT        = 30,
+    VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT        = 31,
+    VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32,
 }
 
 @extension("VK_EXT_debug_report")
@@ -833,6 +980,31 @@
     VK_RASTERIZATION_ORDER_RELAXED_AMD                      = 1,
 }
 
+@extension("VK_EXT_validation_flags")
+enum VkValidationCheckEXT {
+    VK_VALIDATION_CHECK_ALL_EXT                             = 0,
+}
+
+@extension("VK_NVX_device_generated_commands")
+enum VkIndirectCommandsTokenTypeNVX {
+    VK_INDIRECT_COMMANDS_TOKEN_PIPELINE_NVX = 0,
+    VK_INDIRECT_COMMANDS_TOKEN_DESCRIPTOR_SET_NVX = 1,
+    VK_INDIRECT_COMMANDS_TOKEN_INDEX_BUFFER_NVX = 2,
+    VK_INDIRECT_COMMANDS_TOKEN_VERTEX_BUFFER_NVX = 3,
+    VK_INDIRECT_COMMANDS_TOKEN_PUSH_CONSTANT_NVX = 4,
+    VK_INDIRECT_COMMANDS_TOKEN_DRAW_INDEXED_NVX = 5,
+    VK_INDIRECT_COMMANDS_TOKEN_DRAW_NVX = 6,
+    VK_INDIRECT_COMMANDS_TOKEN_DISPATCH_NVX = 7,
+}
+
+@extension("VK_NVX_device_generated_commands")
+enum VkObjectEntryTypeNVX {
+    VK_OBJECT_ENTRY_DESCRIPTOR_SET_NVX = 0,
+    VK_OBJECT_ENTRY_PIPELINE_NVX = 1,
+    VK_OBJECT_ENTRY_INDEX_BUFFER_NVX = 2,
+    VK_OBJECT_ENTRY_VERTEX_BUFFER_NVX = 3,
+    VK_OBJECT_ENTRY_PUSH_CONSTANT_NVX = 4,
+}
 
 /////////////////
 //  Bitfields  //
@@ -883,6 +1055,12 @@
     VK_ACCESS_HOST_WRITE_BIT                                = 0x00004000,
     VK_ACCESS_MEMORY_READ_BIT                               = 0x00008000,
     VK_ACCESS_MEMORY_WRITE_BIT                              = 0x00010000,
+
+    //@extension("VK_NVX_device_generated_commands")
+    VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX                  = 0x00020000,
+
+    //@extension("VK_NVX_device_generated_commands")
+    VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX                 = 0x00040000,
 }
 
 /// Buffer usage flags
@@ -1107,6 +1285,9 @@
 
     VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT                      = 0x00008000,  /// All stages of the graphics pipeline
     VK_PIPELINE_STAGE_ALL_COMMANDS_BIT                      = 0x00010000,  /// All graphics, compute, copy, and transition commands
+
+    //@extension("VK_NVX_device_generated_commands")
+    VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX               = 0x00020000,
 }
 
 /// Render pass attachment description flags
@@ -1376,6 +1557,50 @@
     VK_DEBUG_REPORT_DEBUG_BIT_EXT                           = 0x00000010,
 }
 
+@extension("VK_ANDROID_native_buffer")
+type VkFlags VkSwapchainImageUsageFlagsANDROID
+@extension("VK_ANDROID_native_buffer")
+bitfield VkSwapchainImageUsageFlagBitsANDROID {
+    VK_SWAPCHAIN_IMAGE_USAGE_FLAGS_FRONT_BUFFER_BIT_ANDROID = 0x00000001,
+}
+
+@extension("VK_NV_external_memory_capabilities")
+type VkFlags VkExternalMemoryHandleTypeFlagsNV
+@extension("VK_NV_external_memory_capabilities")
+bitfield VkExternalMemoryHandleTypeFlagBitsNV {
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV = 0x00000001,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV = 0x00000002,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV = 0x00000004,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV = 0x00000008,
+}
+
+@extension("VK_NV_external_memory_capabilities")
+type VkFlags VkExternalMemoryFeatureFlagsNV
+@extension("VK_NV_external_memory_capabilities")
+bitfield VkExternalMemoryFeatureFlagBitsNV {
+    VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV = 0x00000001,
+    VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV = 0x00000002,
+    VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV = 0x00000004,
+}
+
+@extension("VK_NVX_device_generated_commands")
+type VkFlags VkIndirectCommandsLayoutUsageFlagsNVX
+@extension("VK_NVX_device_generated_commands")
+bitfield VkIndirectCommandsLayoutUsageFlagBitsNVX {
+    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX = 0x00000001,
+    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX = 0x00000002,
+    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX = 0x00000004,
+    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX = 0x00000008,
+}
+
+@extension("VK_NVX_device_generated_commands")
+type VkFlags VkObjectEntryUsageFlagsNVX
+@extension("VK_NVX_device_generated_commands")
+bitfield VkObjectEntryUsageFlagBitsNVX {
+    VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX = 0x00000001,
+    VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX = 0x00000002,
+}
+
 
 //////////////////
 //  Structures  //
@@ -2661,6 +2886,27 @@
     platform.HWND                               hwnd
 }
 
+@extension("VK_KHR_incremental_present")
+class VkRectLayerKHR {
+    VkOffset2D                                  offset
+    VkExtent2D                                  extent
+    uint32_t                                    layer
+}
+
+@extension("VK_KHR_incremental_present")
+class VkPresentRegionKHR {
+    uint32_t                                    rectangleCount
+    const VkRectLayerKHR*                       pRectangles
+}
+
+@extension("VK_KHR_incremental_present")
+class VkPresentRegionsKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    uint32_t                                    swapchainCount
+    const VkPresentRegionKHR*                   pRegions
+}
+
 @extension("VK_ANDROID_native_buffer")
 class VkNativeBufferANDROID {
     VkStructureType                             sType
@@ -2671,6 +2917,41 @@
     int                                         usage
 }
 
+@extension("VK_ANDROID_native_buffer")
+class VkSwapchainImageCreateInfoANDROID {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkSwapchainImageUsageFlagBitsANDROID        flags
+
+@extension("VK_GOOGLE_display_timing")
+class VkRefreshCycleDurationGOOGLE {
+    uint64_t                                    minRefreshDuration
+    uint64_t                                    maxRefreshDuration
+}
+
+@extension("VK_GOOGLE_display_timing")
+class VkPastPresentationTimingGOOGLE {
+    uint32_t                                    presentID
+    uint64_t                                    desiredPresentTime
+    uint64_t                                    actualPresentTime
+    uint64_t                                    earliestPresentTime
+    uint64_t                                    presentMargin
+}
+
+@extension("VK_GOOGLE_display_timing")
+class VkPresentTimeGOOGLE {
+    uint32_t                                    presentID
+    uint64_t                                    desiredPresentTime
+}
+
+@extension("VK_GOOGLE_display_timing")
+class VkPresentTimesInfoGOOGLE {
+    VkStructureType                             sType
+    const void*                                 pNext
+    uint32_t                                    swapchainCount
+    const VkPresentTimeGOOGLE*                  pTimes
+}
+
 @extension("VK_EXT_debug_report")
 class VkDebugReportCallbackCreateInfoEXT {
     VkStructureType                             sType
@@ -2737,6 +3018,284 @@
     VkBuffer                                    buffer
 }
 
+@extension("VK_KHR_get_physical_device_properties2")
+class VkPhysicalDeviceFeatures2KHR {
+    VkStructureType                             sType
+    void*                                       pNext
+    VkPhysicalDeviceFeatures                    features
+}
+
+@extension("VK_KHR_get_physical_device_properties2")
+class VkPhysicalDeviceProperties2KHR {
+    VkStructureType                             sType
+    void*                                       pNext
+    VkPhysicalDeviceProperties                  properties
+}
+
+@extension("VK_KHR_get_physical_device_properties2")
+class VkFormatProperties2KHR {
+    VkStructureType                             sType
+    void*                                       pNext
+    VkFormatProperties                          formatProperties
+}
+
+@extension("VK_KHR_get_physical_device_properties2")
+class VkImageFormatProperties2KHR {
+    VkStructureType                             sType
+    void*                                       pNext
+    VkImageFormatProperties                     imageFormatProperties
+}
+
+@extension("VK_KHR_get_physical_device_properties2")
+class VkPhysicalDeviceImageFormatInfo2KHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkFormat                                    format
+    VkImageType                                 type
+    VkImageTiling                               tiling
+    VkImageUsageFlags                           usage
+    VkImageCreateFlags                          flags
+}
+
+@extension("VK_KHR_get_physical_device_properties2")
+class VkQueueFamilyProperties2KHR {
+    VkStructureType                             sType
+    void*                                       pNext
+    VkQueueFamilyProperties                     queueFamilyProperties
+}
+
+@extension("VK_KHR_get_physical_device_properties2")
+class VkPhysicalDeviceMemoryProperties2KHR {
+    VkStructureType                             sType
+    void*                                       pNext
+    VkPhysicalDeviceMemoryProperties            memoryProperties
+}
+
+@extension("VK_KHR_get_physical_device_properties2")
+class VkSparseImageFormatProperties2KHR {
+    VkStructureType                             sType
+    void*                                       pNext
+    VkSparseImageFormatProperties               properties
+}
+
+@extension("VK_KHR_get_physical_device_properties2")
+class VkPhysicalDeviceSparseImageFormatInfo2KHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkFormat                                    format
+    VkImageType                                 type
+    VkSampleCountFlagBits                       samples
+    VkImageUsageFlags                           usage
+    VkImageTiling                               tiling
+}
+
+@extension("VK_KHR_incremental_present")
+class VkRectLayerKHR {
+    VkOffset2D                                  offset
+    VkExtent2D                                  extent
+    u32                                         layer
+}
+
+@extension("VK_KHR_incremental_present")
+class VkPresentRegionKHR {
+    u32                                         rectangleCount
+    const VkRectLayerKHR*                       pRectangles
+}
+
+@extension("VK_KHR_incremental_present")
+class VkPresentRegionsKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    u32                                         swapchainCount
+    const VkPresentRegionKHR*                   pRegions
+}
+
+@extension("VK_NV_external_memory_capabilities")
+class VkExternalImageFormatPropertiesNV {
+    VkImageFormatProperties                     imageFormatProperties
+    VkExternalMemoryFeatureFlagsNV              externalMemoryFeatures
+    VkExternalMemoryHandleTypeFlagsNV           exportFromImportedHandleTypes
+    VkExternalMemoryHandleTypeFlagsNV           compatibleHandleTypes
+}
+
+@extension("VK_NV_external_memory")
+class VkExternalMemoryImageCreateInfoNV {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkExternalMemoryHandleTypeFlagsNV           handleTypes
+}
+
+@extension("VK_NV_external_memory")
+class VkExportMemoryAllocateInfoNV {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkExternalMemoryHandleTypeFlagsNV           handleTypes
+}
+
+@extension("VK_NV_external_memory_win32")
+class VkImportMemoryWin32HandleInfoNV {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkExternalMemoryHandleTypeFlagsNV           handleType
+    platform.HANDLE                             handle
+}
+
+@extension("VK_NV_external_memory_win32")
+class VkExportMemoryWin32HandleInfoNV {
+    VkStructureType                             sType
+    const void*                                 pNext
+    const platform.SECURITY_ATTRIBUTES*         pAttributes
+    u32                                         dwAccess
+}
+
+@extension("VK_NV_win32_keyed_mutex")
+class VkWin32KeyedMutexAcquireReleaseInfoNV {
+    VkStructureType                             sType
+    const void*                                 pNext
+    u32                                         acquireCount
+    const VkDeviceMemory*                       pAcquireSyncs
+    const u64*                                  pAcquireKeys
+    const u32*                                  pAcquireTimeoutMilliseconds
+    u32                                         releaseCount
+    const VkDeviceMemory*                       pReleaseSyncs
+    const u64*                                  pReleaseKeys
+}
+
+@extension("VK_EXT_validation_flags")
+class VkValidationFlagsEXT {
+    VkStructureType                             sType
+    const void*                                 pNext
+    u32                                         disabledValidationCheckCount
+    VkValidationCheckEXT*                       pDisabledValidationChecks
+}
+
+@extension("VK_NVX_device_generated_commands")
+class VkDeviceGeneratedCommandsFeaturesNVX {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkBool32                                    computeBindingPointSupport
+}
+
+@extension("VK_NVX_device_generated_commands")
+class VkDeviceGeneratedCommandsLimitsNVX {
+    VkStructureType                             sType
+    const void*                                 pNext
+    u32                                         maxIndirectCommandsLayoutTokenCount
+    u32                                         maxObjectEntryCounts
+    u32                                         minSequenceCountBufferOffsetAlignment
+    u32                                         minSequenceIndexBufferOffsetAlignment
+    u32                                         minCommandsTokenBufferOffsetAlignment
+}
+
+@extension("VK_NVX_device_generated_commands")
+class VkIndirectCommandsTokenNVX {
+    VkIndirectCommandsTokenTypeNVX              tokenType
+    VkBuffer                                    buffer
+    VkDeviceSize                                offset
+}
+
+@extension("VK_NVX_device_generated_commands")
+class VkIndirectCommandsLayoutTokenNVX {
+    VkIndirectCommandsTokenTypeNVX              tokenType
+    u32                                         bindingUnit
+    u32                                         dynamicCount
+    u32                                         divisor
+}
+
+@extension("VK_NVX_device_generated_commands")
+class VkIndirectCommandsLayoutCreateInfoNVX {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkPipelineBindPoint                         pipelineBindPoint
+    VkIndirectCommandsLayoutUsageFlagsNVX       flags
+    u32                                         tokenCount
+    const VkIndirectCommandsLayoutTokenNVX*     pTokens
+}
+
+@extension("VK_NVX_device_generated_commands")
+class VkCmdProcessCommandsInfoNVX {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkObjectTableNVX                            objectTable
+    VkIndirectCommandsLayoutNVX                 indirectCommandsLayout
+    u32                                         indirectCommandsTokenCount
+    const VkIndirectCommandsTokenNVX*           pIndirectCommandsTokens
+    u32                                         maxSequencesCount
+    VkCommandBuffer                             targetCommandBuffer
+    VkBuffer                                    sequencesCountBuffer
+    VkDeviceSize                                sequencesCountOffset
+    VkBuffer                                    sequencesIndexBuffer
+    VkDeviceSize                                sequencesIndexOffset
+}
+
+@extension("VK_NVX_device_generated_commands")
+class VkCmdReserveSpaceForCommandsInfoNVX {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkObjectTableNVX                            objectTable
+    VkIndirectCommandsLayoutNVX                 indirectCommandsLayout
+    u32                                         maxSequencesCount
+}
+
+@extension("VK_NVX_device_generated_commands")
+class VkObjectTableCreateInfoNVX {
+    VkStructureType                             sType
+    const void*                                 pNext
+    u32                                         objectCount
+    const VkObjectEntryTypeNVX*                 pObjectEntryTypes
+    const u32*                                  pObjectEntryCounts
+    const VkObjectEntryUsageFlagsNVX*           pObjectEntryUsageFlags
+    u32                                         maxUniformBuffersPerDescriptor
+    u32                                         maxStorageBuffersPerDescriptor
+    u32                                         maxStorageImagesPerDescriptor
+    u32                                         maxSampledImagesPerDescriptor
+    u32                                         maxPipelineLayouts
+}
+
+@extension("VK_NVX_device_generated_commands")
+class VkObjectTableEntryNVX {
+    VkObjectEntryTypeNVX                        type
+    VkObjectEntryUsageFlagsNVX                  flags
+}
+
+@extension("VK_NVX_device_generated_commands")
+class VkObjectTablePipelineEntryNVX {
+    VkObjectEntryTypeNVX                        type
+    VkObjectEntryUsageFlagsNVX                  flags
+    VkPipeline                                  pipeline
+}
+
+@extension("VK_NVX_device_generated_commands")
+class VkObjectTableDescriptorSetEntryNVX {
+    VkObjectEntryTypeNVX                        type
+    VkObjectEntryUsageFlagsNVX                  flags
+    VkPipelineLayout                            pipelineLayout
+    VkDescriptorSet                             descriptorSet
+}
+
+@extension("VK_NVX_device_generated_commands")
+class VkObjectTableVertexBufferEntryNVX {
+    VkObjectEntryTypeNVX                        type
+    VkObjectEntryUsageFlagsNVX                  flags
+    VkBuffer                                    buffer
+}
+
+@extension("VK_NVX_device_generated_commands")
+class VkObjectTableIndexBufferEntryNVX {
+    VkObjectEntryTypeNVX                        type
+    VkObjectEntryUsageFlagsNVX                  flags
+    VkBuffer                                    buffer
+}
+
+@extension("VK_NVX_device_generated_commands")
+class VkObjectTablePushConstantEntryNVX {
+    VkObjectEntryTypeNVX                        type
+    VkObjectEntryUsageFlagsNVX                  flags
+    VkPipelineLayout                            pipelineLayout
+    VkShaderStageFlags                          stageFlags
+}
+
+
 
 ////////////////
 //  Commands  //
@@ -5281,6 +5840,16 @@
 }
 
 @extension("VK_ANDROID_native_buffer")
+cmd VkResult vkGetSwapchainGrallocUsage2ANDROID(
+        VkDevice                                device,
+        VkFormat                                format,
+        VkImageUsageFlags                       imageUsage,
+        VkSwapchainImageUsageFlagsANDROID       swapchainImageUsage,
+        int*                                    grallocUsage) {
+    return ?
+}
+
+@extension("VK_ANDROID_native_buffer")
 cmd VkResult vkAcquireImageANDROID(
         VkDevice                                device,
         VkImage                                 image,
@@ -5300,6 +5869,41 @@
     return ?
 }
 
+@extension("VK_GOOGLE_display_timing")
+cmd VkResult vkGetRefreshCycleDurationGOOGLE(
+        VkDevice                                 device,
+        VkSwapchainKHR                           swapchain,
+        VkRefreshCycleDurationGOOGLE*            pDisplayTimingProperties) {
+    deviceObject := GetDevice(device)
+    swapchainObject := GetSwapchain(swapchain)
+
+    displayTimingProperties := ?
+    pDisplayTimingProperties[0] = displayTimingProperties
+
+    return ?
+}
+
+@extension("VK_GOOGLE_display_timing")
+cmd VkResult vkGetPastPresentationTimingGOOGLE(
+        VkDevice                                 device,
+        VkSwapchainKHR                           swapchain,
+        u32*                                     pPresentationTimingCount,
+        VkPastPresentationTimingGOOGLE*          pPresentationTimings) {
+    deviceObject := GetDevice(device)
+
+    count := as!u32(?)
+    pPresentationTimingCount[0] = count
+    presentationTimings := pPresentationTimings[0:count]
+
+    for i in (0 .. count) {
+        presentationTiming := ?
+        presentationTimings[i] = presentationTiming
+        State.Timings[presentationTiming] = new!PresentationTiming(device: device)
+    }
+
+    return ?
+}
+
 @extension("VK_EXT_debug_report")
 @external type void* PFN_vkDebugReportCallbackEXT
 @extension("VK_EXT_debug_report")
@@ -5374,6 +5978,169 @@
         VkDebugMarkerMarkerInfoEXT*                 pMarkerInfo) {
 }
 
+@extension("VK_KHR_get_physical_device_properties2")
+cmd void vkGetPhysicalDeviceFeatures2KHR(
+        VkPhysicalDevice                            physicalDevice,
+        VkPhysicalDeviceFeatures2KHR*               pFeatures) {
+}
+
+@extension("VK_KHR_get_physical_device_properties2")
+cmd void vkGetPhysicalDeviceProperties2KHR(
+        VkPhysicalDevice                            physicalDevice,
+        VkPhysicalDeviceProperties2KHR*             pProperties) {
+}
+
+@extension("VK_KHR_get_physical_device_properties2")
+cmd void vkGetPhysicalDeviceFormatProperties2KHR(
+        VkPhysicalDevice                            physicalDevice,
+        VkFormat                                    format,
+        VkFormatProperties2KHR*                     pFormatProperties) {
+}
+
+@extension("VK_KHR_get_physical_device_properties2")
+cmd VkResult vkGetPhysicalDeviceImageFormatProperties2KHR(
+        VkPhysicalDevice                            physicalDevice,
+        const VkPhysicalDeviceImageFormatInfo2KHR*  pImageFormatInfo,
+        VkImageFormatProperties2KHR*                pImageFormatProperties) {
+    return ?
+}
+
+@extension("VK_KHR_get_physical_device_properties2")
+cmd void vkGetPhysicalDeviceQueueFamilyProperties2KHR(
+        VkPhysicalDevice                            physicalDevice,
+        u32*                                        pQueueFamilyPropertyCount,
+        VkQueueFamilyProperties2KHR*                pQueueFamilyProperties) {
+}
+
+@extension("VK_KHR_get_physical_device_properties2")
+cmd void vkGetPhysicalDeviceMemoryProperties2KHR(
+        VkPhysicalDevice                            physicalDevice,
+        VkPhysicalDeviceMemoryProperties2KHR*       pMemoryProperties) {
+}
+
+@extension("VK_KHR_get_physical_device_properties2")
+cmd void vkGetPhysicalDeviceSparseImageFormatProperties2KHR(
+        VkPhysicalDevice                            physicalDevice,
+        const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo,
+        u32*                                        pPropertyCount,
+        VkSparseImageFormatProperties2KHR*          pProperties) {
+}
+
+@extension("VK_AMD_draw_indirect_count")
+cmd void vkCmdDrawIndirectCountAMD(
+        VkCommandBuffer                             commandBuffer,
+        VkBuffer                                    buffer,
+        VkDeviceSize                                offset,
+        VkBuffer                                    countBuffer,
+        VkDeviceSize                                countBufferOffset,
+        u32                                         maxDrawCount,
+        u32                                         stride) {
+}
+
+@extension("VK_AMD_draw_indirect_count")
+cmd void vkCmdDrawIndexedIndirectCountAMD(
+        VkCommandBuffer                             commandBuffer,
+        VkBuffer                                    buffer,
+        VkDeviceSize                                offset,
+        VkBuffer                                    countBuffer,
+        VkDeviceSize                                countBufferOffset,
+        u32                                         maxDrawCount,
+        u32                                         stride) {
+}
+
+@extension("VK_NV_external_memory_capabilities")
+cmd VkResult vkGetPhysicalDeviceExternalImageFormatPropertiesNV(
+        VkPhysicalDevice                            physicalDevice,
+        VkFormat                                    format,
+        VkImageType                                 type,
+        VkImageTiling                               tiling,
+        VkImageUsageFlags                           usage,
+        VkImageCreateFlags                          flags,
+        VkExternalMemoryHandleTypeFlagsNV           externalHandleType,
+        VkExternalImageFormatPropertiesNV*          pExternalImageFormatProperties) {
+    return ?
+}
+
+@extension("VK_NV_external_memory_win32")
+cmd VkResult vkGetMemoryWin32HandleNV(
+        VkDevice                                    device,
+        VkDeviceMemory                              memory,
+        VkExternalMemoryHandleTypeFlagsNV           handleType,
+        platform.HANDLE*                            pHandle) {
+    return ?
+}
+
+@extension("VK_NV_external_memory_win32")
+cmd void  vkCmdProcessCommandsNVX(
+        VkCommandBuffer                             commandBuffer,
+        const VkCmdProcessCommandsInfoNVX*          pProcessCommandsInfo) {
+}
+
+@extension("VK_NV_external_memory_win32")
+cmd void  vkCmdReserveSpaceForCommandsNVX(
+        VkCommandBuffer                             commandBuffer,
+        const VkCmdReserveSpaceForCommandsInfoNVX*  pReserveSpaceInfo) {
+}
+
+@extension("VK_NV_external_memory_win32")
+cmd VkResult  vkCreateIndirectCommandsLayoutNVX(
+        VkDevice                                    device,
+        const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkIndirectCommandsLayoutNVX*                pIndirectCommandsLayout) {
+    return ?
+}
+
+@extension("VK_NV_external_memory_win32")
+cmd void  vkDestroyIndirectCommandsLayoutNVX(
+        VkDevice                                    device,
+        VkIndirectCommandsLayoutNVX                 indirectCommandsLayout,
+        const VkAllocationCallbacks*                pAllocator) {
+}
+
+@extension("VK_NV_external_memory_win32")
+cmd VkResult  vkCreateObjectTableNVX(
+        VkDevice                                    device,
+        const VkObjectTableCreateInfoNVX*           pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkObjectTableNVX*                           pObjectTable) {
+    return ?
+}
+
+@extension("VK_NV_external_memory_win32")
+cmd void  vkDestroyObjectTableNVX(
+        VkDevice                                    device,
+        VkObjectTableNVX                            objectTable,
+        const VkAllocationCallbacks*                pAllocator) {
+}
+
+@extension("VK_NV_external_memory_win32")
+cmd VkResult  vkRegisterObjectsNVX(
+        VkDevice                                    device,
+        VkObjectTableNVX                            objectTable,
+        u32                                         objectCount,
+        const VkObjectTableEntryNVX* const*         ppObjectTableEntries,
+        const u32*                                  pObjectIndices) {
+    return ?
+}
+
+@extension("VK_NV_external_memory_win32")
+cmd VkResult  vkUnregisterObjectsNVX(
+        VkDevice                                    device,
+        VkObjectTableNVX                            objectTable,
+        u32                                         objectCount,
+        const VkObjectEntryTypeNVX*                 pObjectEntryTypes,
+        const u32*                                  pObjectIndices) {
+    return ?
+}
+
+@extension("VK_NV_external_memory_win32")
+cmd void  vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX(
+        VkPhysicalDevice                            physicalDevice,
+        VkDeviceGeneratedCommandsFeaturesNVX*       pFeatures,
+        VkDeviceGeneratedCommandsLimitsNVX*         pLimits) {
+}
+
 
 ////////////////
 // Validation //
diff --git a/vulkan/doc/implementors_guide/implementors_guide.adoc b/vulkan/doc/implementors_guide/implementors_guide.adoc
index 7ace777..ce21791 100644
--- a/vulkan/doc/implementors_guide/implementors_guide.adoc
+++ b/vulkan/doc/implementors_guide/implementors_guide.adoc
@@ -59,6 +59,28 @@
 ----
 The +format+ and +imageUsage+ parameters are taken from the +VkSwapchainCreateInfoKHR+ structure. The driver should fill +*grallocUsage+ with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers.
 
+Implementations may further need swapchain buffers to be allocated with implementation-defined private gralloc usage flags that depend not only on +format+ and +imageUsage+, but also on the intended usage of the swapchain. The additional usage bits are defined as
+[source,c]
+----
+typedef enum VkSwapchainImageUsageFlagBitsANDROID {
+    VK_SWAPCHAIN_IMAGE_USAGE_FRONT_BUFFER_BIT_ANDROID = 0x00000001,
+    VK_SWAPCHAIN_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSwapchainImageUsageFlagBitsANDROID;
+typedef VkFlags VkSwapchainImageUsageFlagsANDROID;
+----
+
+If the driver provides the +vkGetSwapchainGrallocUsage2ANDROID+ function, the platform will use it in preference to +vkGetSwapchainGrallocUsageANDROID+ when translating a requested format, image usage flags, and swapchain image usage flags into gralloc usage flags. +vkGetSwapchainGrallocUsage2ANDROID+ behaves in the same way as +vkGetSwapchainGrallocUsageANDROID+, and is declared as
+[source,c]
+----
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainGrallocUsage2ANDROID(
+    VkDevice            device,
+    VkFormat            format,
+    VkImageUsageFlags   imageUsage,
+    VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
+    int*                grallocUsage
+);
+----
+
 +VkNativeBufferANDROID+ is a +vkCreateImage+ extension structure for creating an image backed by a gralloc buffer. This structure is provided to +vkCreateImage+ in the +VkImageCreateInfo+ structure chain. Calls to +vkCreateImage+ with this structure will happen during the first call to +vkGetSwapChainInfoWSI(.. VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI ..)+. The WSI implementation will allocate the number of native buffers requested for the swapchain, then create a +VkImage+ for each one.
 
 [source,c]
@@ -78,6 +100,7 @@
 ----
 
 When creating a gralloc-backed image, the +VkImageCreateInfo+ will have:
+[source,txt]
 ----
   .imageType           = VK_IMAGE_TYPE_2D
   .format              = a VkFormat matching the format requested for the gralloc buffer
@@ -93,6 +116,17 @@
   .pQueueFamilyIndices = VkSwapChainCreateInfoWSI::pQueueFamilyIndices
 ----
 
+Additionally, when any swapchain image usage flags are required for the swapchain, the platform will provide a +VkSwapchainImageCreateInfoANDROID+ extension structure in the +VkImageCreateInfo+ chain provided to +vkCreateImage+, containing the swapchain image usage flags:
+[source,c]
+----
+typedef struct {
+    VkStructureType                        sType; // must be VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID
+    const void*                            pNext;
+
+    VkSwapchainImageUsageFlagBitsANDROID   usage;
+} VkSwapchainImageCreateInfoANDROID;
+----
+
 +vkAcquireImageANDROID+ acquires ownership of a swapchain image and imports an
 externally-signalled native fence into both an existing VkSemaphore object
 and an existing VkFence object:
@@ -139,6 +173,8 @@
 
 This will be called during +vkQueuePresentWSI+ on the provided queue. Effects are similar to +vkQueueSignalSemaphore+, except with a native fence instead of a semaphore. The native fence must: not signal until the +waitSemaphoreCount+ semaphores in +pWaitSemaphores+ have signaled. Unlike +vkQueueSignalSemaphore+, however, this call creates and returns the synchronization object that will be signalled rather than having it provided as input. If the queue is already idle when this function is called, it is allowed but not required to set +*pNativeFenceFd+ to -1. The file descriptor returned in +*pNativeFenceFd+ is owned and will be closed by the caller. Many drivers will be able to ignore the +image+ parameter, but some may need to prepare CPU-side data structures associated with a gralloc buffer for use by external image consumers. Preparing buffer contents for use by external consumers should have been done asynchronously as part of transitioning the image to +VK_IMAGE_LAYOUT_PRESENT_SRC_KHR+.
 
+If +image+ was created with +VK_SWAPCHAIN_IMAGE_USAGE_FRONT_BUFFER_BIT_ANDROID+, then the driver must tolerate +vkQueueSignalReleaseImageANDROID+ being called repeatedly without intervening calls to +vkAcquireImageANDROID+.
+
 == History ==
 
 . *2015-07-08* Initial version
@@ -158,4 +194,9 @@
 . *2016-01-08*
    * Added waitSemaphoreCount and pWaitSemaphores parameters to vkQueueSignalReleaseImageANDROID.
 . *2016-06-17*
-   * Updates to reflect final behavior, closed some TBDs now that they've BDed.
\ No newline at end of file
+   * Updates to reflect final behavior, closed some TBDs now that they've BDed.
+. *2017-01-06*
+   * Extension version 6
+   * Added VkSwapchainImageUsageFlagBitsANDROID
+   * Added vkGetSwapchainGrallocUsage2ANDROID
+   * Added VkSwapchainImageCreateInfoANDROID
diff --git a/vulkan/doc/implementors_guide/implementors_guide.html b/vulkan/doc/implementors_guide/implementors_guide.html
index 0bfeb81..5ff1269 100644
--- a/vulkan/doc/implementors_guide/implementors_guide.html
+++ b/vulkan/doc/implementors_guide/implementors_guide.html
@@ -730,7 +730,7 @@
 /*]]>*/
 </script>
 </head>
-<body class="book">
+<body class="article">
 <div id="header">
 <h1>Vulkan on Android Implementor&#8217;s Guide</h1>
 <span id="revnumber">version 5</span>
@@ -795,7 +795,7 @@
 <div class="paragraph"><p>The <span class="monospaced">vk_wsi_swapchin</span> and <span class="monospaced">vk_wsi_device_swapchain</span> extensions are primarily be implemented by the platform and live in <span class="monospaced">libvulkan.so</span>. The <span class="monospaced">VkSwapchain</span> object and all interaction with <span class="monospaced">ANativeWindow</span> will be handled by the platform and not exposed to drivers. The WSI implementation will rely on a few private interfaces to the driver for this implementation. These will be loaded through the driver&#8217;s <span class="monospaced">vkGetDeviceProcAddr</span> functions, after passing through any enabled layers.</p></div>
 <div class="paragraph"><p>Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags. When creating a swapchain, the platform will ask the driver to translate the requested format and image usage flags into gralloc usage flags by calling</p></div>
 <div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+<div class="content"><!-- Generator: GNU source-highlight 3.1.6
 by Lorenzo Bettini
 http://www.lorenzobettini.it
 http://www.gnu.org/software/src-highlite -->
@@ -806,9 +806,33 @@
     <span style="color: #009900">int</span><span style="color: #990000">*</span>                grallocUsage
 <span style="color: #990000">);</span></tt></pre></div></div>
 <div class="paragraph"><p>The <span class="monospaced">format</span> and <span class="monospaced">imageUsage</span> parameters are taken from the <span class="monospaced">VkSwapchainCreateInfoKHR</span> structure. The driver should fill <span class="monospaced">*grallocUsage</span> with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers.</p></div>
+<div class="paragraph"><p>Implementations may further need swapchain buffers to be allocated with implementation-defined private gralloc usage flags that depend not only on <span class="monospaced">format</span> and <span class="monospaced">imageUsage</span>, but also on the intended usage of the swapchain. The additional usage bits are defined as</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.6
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">typedef</span></span> <span style="font-weight: bold"><span style="color: #0000FF">enum</span></span> VkSwapchainImageUsageFlagBitsANDROID <span style="color: #FF0000">{</span>
+    VK_SWAPCHAIN_IMAGE_USAGE_FRONT_BUFFER_BIT_ANDROID <span style="color: #990000">=</span> <span style="color: #993399">0x00000001</span><span style="color: #990000">,</span>
+    VK_SWAPCHAIN_IMAGE_USAGE_FLAG_BITS_MAX_ENUM <span style="color: #990000">=</span> <span style="color: #993399">0x7FFFFFFF</span>
+<span style="color: #FF0000">}</span> VkSwapchainImageUsageFlagBitsANDROID<span style="color: #990000">;</span>
+<span style="font-weight: bold"><span style="color: #0000FF">typedef</span></span> <span style="color: #008080">VkFlags</span> VkSwapchainImageUsageFlagsANDROID<span style="color: #990000">;</span></tt></pre></div></div>
+<div class="paragraph"><p>If the driver provides the <span class="monospaced">vkGetSwapchainGrallocUsage2ANDROID</span> function, the platform will use it in preference to <span class="monospaced">vkGetSwapchainGrallocUsageANDROID</span> when translating a requested format, image usage flags, and swapchain image usage flags into gralloc usage flags. <span class="monospaced">vkGetSwapchainGrallocUsage2ANDROID</span> behaves in the same way as <span class="monospaced">vkGetSwapchainGrallocUsageANDROID</span>, and is declared as</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.6
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>VKAPI_ATTR <span style="color: #008080">VkResult</span> <span style="color: #008080">VKAPI_CALL</span> <span style="font-weight: bold"><span style="color: #000000">vkGetSwapchainGrallocUsage2ANDROID</span></span><span style="color: #990000">(</span>
+    <span style="color: #008080">VkDevice</span>            device<span style="color: #990000">,</span>
+    <span style="color: #008080">VkFormat</span>            format<span style="color: #990000">,</span>
+    <span style="color: #008080">VkImageUsageFlags</span>   imageUsage<span style="color: #990000">,</span>
+    <span style="color: #008080">VkSwapchainImageUsageFlagsANDROID</span> swapchainImageUsage<span style="color: #990000">,</span>
+    <span style="color: #009900">int</span><span style="color: #990000">*</span>                grallocUsage
+<span style="color: #990000">);</span></tt></pre></div></div>
 <div class="paragraph"><p><span class="monospaced">VkNativeBufferANDROID</span> is a <span class="monospaced">vkCreateImage</span> extension structure for creating an image backed by a gralloc buffer. This structure is provided to <span class="monospaced">vkCreateImage</span> in the <span class="monospaced">VkImageCreateInfo</span> structure chain. Calls to <span class="monospaced">vkCreateImage</span> with this structure will happen during the first call to <span class="monospaced">vkGetSwapChainInfoWSI(.. VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI ..)</span>. The WSI implementation will allocate the number of native buffers requested for the swapchain, then create a <span class="monospaced">VkImage</span> for each one.</p></div>
 <div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+<div class="content"><!-- Generator: GNU source-highlight 3.1.6
 by Lorenzo Bettini
 http://www.lorenzobettini.it
 http://www.gnu.org/software/src-highlite -->
@@ -826,8 +850,11 @@
 <span style="color: #FF0000">}</span> VkNativeBufferANDROID<span style="color: #990000">;</span></tt></pre></div></div>
 <div class="paragraph"><p>When creating a gralloc-backed image, the <span class="monospaced">VkImageCreateInfo</span> will have:</p></div>
 <div class="listingblock">
-<div class="content monospaced">
-<pre>  .imageType           = VK_IMAGE_TYPE_2D
+<div class="content"><!-- Generator: GNU source-highlight 3.1.6
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>  .imageType           = VK_IMAGE_TYPE_2D
   .format              = a VkFormat matching the format requested for the gralloc buffer
   .extent              = the 2D dimensions requested for the gralloc buffer
   .mipLevels           = 1
@@ -838,13 +865,24 @@
   .flags               = 0
   .sharingMode         = VkSwapChainCreateInfoWSI::sharingMode
   .queueFamilyCount    = VkSwapChainCreateInfoWSI::queueFamilyCount
-  .pQueueFamilyIndices = VkSwapChainCreateInfoWSI::pQueueFamilyIndices</pre>
-</div></div>
+  .pQueueFamilyIndices = VkSwapChainCreateInfoWSI::pQueueFamilyIndices</tt></pre></div></div>
+<div class="paragraph"><p>Additionally, when any swapchain image usage flags are required for the swapchain, the platform will provide a <span class="monospaced">VkSwapchainImageCreateInfoANDROID</span> extension structure in the <span class="monospaced">VkImageCreateInfo</span> chain provided to <span class="monospaced">vkCreateImage</span>, containing the swapchain image usage flags:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.6
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">typedef</span></span> <span style="font-weight: bold"><span style="color: #0000FF">struct</span></span> <span style="color: #FF0000">{</span>
+    <span style="color: #008080">VkStructureType</span>                        sType<span style="color: #990000">;</span> <span style="font-style: italic"><span style="color: #9A1900">// must be VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID</span></span>
+    <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> <span style="color: #009900">void</span><span style="color: #990000">*</span>                            pNext<span style="color: #990000">;</span>
+
+    <span style="color: #008080">VkSwapchainImageUsageFlagBitsANDROID</span>   usage<span style="color: #990000">;</span>
+<span style="color: #FF0000">}</span> VkSwapchainImageCreateInfoANDROID<span style="color: #990000">;</span></tt></pre></div></div>
 <div class="paragraph"><p><span class="monospaced">vkAcquireImageANDROID</span> acquires ownership of a swapchain image and imports an
 externally-signalled native fence into both an existing VkSemaphore object
 and an existing VkFence object:</p></div>
 <div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+<div class="content"><!-- Generator: GNU source-highlight 3.1.6
 by Lorenzo Bettini
 http://www.lorenzobettini.it
 http://www.gnu.org/software/src-highlite -->
@@ -872,7 +910,7 @@
 is as if the native fence was already signalled.</p></div>
 <div class="paragraph"><p><span class="monospaced">vkQueueSignalReleaseImageANDROID</span> prepares a swapchain image for external use, and creates a native fence and schedules it to be signalled when prior work on the queue has completed.</p></div>
 <div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+<div class="content"><!-- Generator: GNU source-highlight 3.1.6
 by Lorenzo Bettini
 http://www.lorenzobettini.it
 http://www.gnu.org/software/src-highlite -->
@@ -884,6 +922,7 @@
     <span style="color: #009900">int</span><span style="color: #990000">*</span>                pNativeFenceFd
 <span style="color: #990000">);</span></tt></pre></div></div>
 <div class="paragraph"><p>This will be called during <span class="monospaced">vkQueuePresentWSI</span> on the provided queue. Effects are similar to <span class="monospaced">vkQueueSignalSemaphore</span>, except with a native fence instead of a semaphore. The native fence must: not signal until the <span class="monospaced">waitSemaphoreCount</span> semaphores in <span class="monospaced">pWaitSemaphores</span> have signaled. Unlike <span class="monospaced">vkQueueSignalSemaphore</span>, however, this call creates and returns the synchronization object that will be signalled rather than having it provided as input. If the queue is already idle when this function is called, it is allowed but not required to set <span class="monospaced">*pNativeFenceFd</span> to -1. The file descriptor returned in <span class="monospaced">*pNativeFenceFd</span> is owned and will be closed by the caller. Many drivers will be able to ignore the <span class="monospaced">image</span> parameter, but some may need to prepare CPU-side data structures associated with a gralloc buffer for use by external image consumers. Preparing buffer contents for use by external consumers should have been done asynchronously as part of transitioning the image to <span class="monospaced">VK_IMAGE_LAYOUT_PRESENT_SRC_KHR</span>.</p></div>
+<div class="paragraph"><p>If <span class="monospaced">image</span> was created with <span class="monospaced">VK_SWAPCHAIN_IMAGE_USAGE_FRONT_BUFFER_BIT_ANDROID</span>, then the driver must tolerate <span class="monospaced">vkQueueSignalReleaseImageANDROID</span> being called repeatedly without intervening calls to <span class="monospaced">vkAcquireImageANDROID</span>.</p></div>
 </div>
 </div>
 <div class="sect1">
@@ -978,6 +1017,33 @@
 </li>
 </ul></div>
 </li>
+<li>
+<p>
+<strong>2017-01-06</strong>
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Extension version 6
+</p>
+</li>
+<li>
+<p>
+Added VkSwapchainImageUsageFlagBitsANDROID
+</p>
+</li>
+<li>
+<p>
+Added vkGetSwapchainGrallocUsage2ANDROID
+</p>
+</li>
+<li>
+<p>
+Added VkSwapchainImageCreateInfoANDROID
+</p>
+</li>
+</ul></div>
+</li>
 </ol></div>
 </div>
 </div>
@@ -986,7 +1052,7 @@
 <div id="footer">
 <div id="footer-text">
 Version 5<br>
-Last updated 2016-06-17 13:54:25 PDT
+Last updated 2017-01-09 09:52:43 NZDT
 </div>
 </div>
 </body>
diff --git a/vulkan/include/vulkan/vk_android_native_buffer.h b/vulkan/include/vulkan/vk_android_native_buffer.h
index d0ebf81..0fd041a 100644
--- a/vulkan/include/vulkan/vk_android_native_buffer.h
+++ b/vulkan/include/vulkan/vk_android_native_buffer.h
@@ -27,12 +27,18 @@
 #define VK_ANDROID_native_buffer 1
 
 #define VK_ANDROID_NATIVE_BUFFER_EXTENSION_NUMBER 11
-#define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION     5
+#define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION     6
 #define VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME   "VK_ANDROID_native_buffer"
 
 #define VK_ANDROID_NATIVE_BUFFER_ENUM(type,id)    ((type)(1000000000 + (1000 * (VK_ANDROID_NATIVE_BUFFER_EXTENSION_NUMBER - 1)) + (id)))
 #define VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID   VK_ANDROID_NATIVE_BUFFER_ENUM(VkStructureType, 0)
 
+typedef enum VkSwapchainImageUsageFlagBitsANDROID {
+    VK_SWAPCHAIN_IMAGE_USAGE_FRONT_BUFFER_BIT_ANDROID = 0x00000001,
+    VK_SWAPCHAIN_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSwapchainImageUsageFlagBitsANDROID;
+typedef VkFlags VkSwapchainImageUsageFlagsANDROID;
+
 typedef struct {
     VkStructureType             sType; // must be VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID
     const void*                 pNext;
@@ -46,7 +52,15 @@
     int                         usage;
 } VkNativeBufferANDROID;
 
+typedef struct {
+    VkStructureType                        sType; // must be VK_STRUCTURE_TYPE_SWAPCHAIN_IMAGE_CREATE_INFO_ANDROID
+    const void*                            pNext;
+
+    VkSwapchainImageUsageFlagBitsANDROID   usage;
+} VkSwapchainImageCreateInfoANDROID;
+
 typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainGrallocUsageANDROID)(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
+typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainGrallocUsage2ANDROID)(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, int* grallocUsage);
 typedef VkResult (VKAPI_PTR *PFN_vkAcquireImageANDROID)(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
 typedef VkResult (VKAPI_PTR *PFN_vkQueueSignalReleaseImageANDROID)(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
 
@@ -57,6 +71,13 @@
     VkImageUsageFlags   imageUsage,
     int*                grallocUsage
 );
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainGrallocUsage2ANDROID(
+    VkDevice            device,
+    VkFormat            format,
+    VkImageUsageFlags   imageUsage,
+    VkSwapchainImageUsageFlagsANDROID swapchainImageUsage,
+    int*                grallocUsage
+);
 VKAPI_ATTR VkResult VKAPI_CALL vkAcquireImageANDROID(
     VkDevice            device,
     VkImage             image,
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
index 16a43b6..6ddce8f 100644
--- a/vulkan/include/vulkan/vulkan.h
+++ b/vulkan/include/vulkan/vulkan.h
@@ -43,7 +43,7 @@
 #define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
 #define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
 // Version of this file
-#define VK_HEADER_VERSION 22
+#define VK_HEADER_VERSION 38
 
 
 #define VK_NULL_HANDLE 0
@@ -53,11 +53,13 @@
 #define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
 
 
+#if !defined(VK_DEFINE_NON_DISPATCHABLE_HANDLE)
 #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
         #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
 #else
         #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
 #endif
+#endif
         
 
 
@@ -219,6 +221,28 @@
     VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV = 1000026001,
     VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV = 1000026002,
     VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR = 1000084000,
+    VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV = 1000056000,
+    VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV = 1000056001,
+    VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057000,
+    VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV = 1000057001,
+    VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV = 1000058000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR = 1000059000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR = 1000059001,
+    VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR = 1000059002,
+    VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059003,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR = 1000059004,
+    VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR = 1000059005,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR = 1000059006,
+    VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR = 1000059007,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR = 1000059008,
+    VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT = 1000061000,
+    VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX = 1000086000,
+    VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX = 1000086001,
+    VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX = 1000086002,
+    VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX = 1000086003,
+    VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX = 1000086004,
+    VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX = 1000086005,
+    VK_STRUCTURE_TYPE_PRESENT_TIMES_GOOGLE = 1000092000,
     VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO,
     VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO,
     VK_STRUCTURE_TYPE_RANGE_SIZE = (VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO - VK_STRUCTURE_TYPE_APPLICATION_INFO + 1),
@@ -431,6 +455,14 @@
     VK_FORMAT_ASTC_12x10_SRGB_BLOCK = 182,
     VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183,
     VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184,
+    VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG = 1000054000,
+    VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG = 1000054001,
+    VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG = 1000054002,
+    VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG = 1000054003,
+    VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG = 1000054004,
+    VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG = 1000054005,
+    VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG = 1000054006,
+    VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG = 1000054007,
     VK_FORMAT_BEGIN_RANGE = VK_FORMAT_UNDEFINED,
     VK_FORMAT_END_RANGE = VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
     VK_FORMAT_RANGE_SIZE = (VK_FORMAT_ASTC_12x12_SRGB_BLOCK - VK_FORMAT_UNDEFINED + 1),
@@ -903,6 +935,7 @@
     VK_PIPELINE_STAGE_HOST_BIT = 0x00004000,
     VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000,
     VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000,
+    VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX = 0x00020000,
     VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkPipelineStageFlagBits;
 typedef VkFlags VkPipelineStageFlags;
@@ -1077,6 +1110,8 @@
     VK_ACCESS_HOST_WRITE_BIT = 0x00004000,
     VK_ACCESS_MEMORY_READ_BIT = 0x00008000,
     VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000,
+    VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX = 0x00020000,
+    VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX = 0x00040000,
     VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkAccessFlagBits;
 typedef VkFlags VkAccessFlags;
@@ -3716,6 +3751,117 @@
 #define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION 1
 #define VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME "VK_KHR_sampler_mirror_clamp_to_edge"
 
+
+#define VK_KHR_get_physical_device_properties2 1
+#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION 1
+#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME "VK_KHR_get_physical_device_properties2"
+
+typedef struct VkPhysicalDeviceFeatures2KHR {
+    VkStructureType             sType;
+    void*                       pNext;
+    VkPhysicalDeviceFeatures    features;
+} VkPhysicalDeviceFeatures2KHR;
+
+typedef struct VkPhysicalDeviceProperties2KHR {
+    VkStructureType               sType;
+    void*                         pNext;
+    VkPhysicalDeviceProperties    properties;
+} VkPhysicalDeviceProperties2KHR;
+
+typedef struct VkFormatProperties2KHR {
+    VkStructureType       sType;
+    void*                 pNext;
+    VkFormatProperties    formatProperties;
+} VkFormatProperties2KHR;
+
+typedef struct VkImageFormatProperties2KHR {
+    VkStructureType            sType;
+    void*                      pNext;
+    VkImageFormatProperties    imageFormatProperties;
+} VkImageFormatProperties2KHR;
+
+typedef struct VkPhysicalDeviceImageFormatInfo2KHR {
+    VkStructureType       sType;
+    const void*           pNext;
+    VkFormat              format;
+    VkImageType           type;
+    VkImageTiling         tiling;
+    VkImageUsageFlags     usage;
+    VkImageCreateFlags    flags;
+} VkPhysicalDeviceImageFormatInfo2KHR;
+
+typedef struct VkQueueFamilyProperties2KHR {
+    VkStructureType            sType;
+    void*                      pNext;
+    VkQueueFamilyProperties    queueFamilyProperties;
+} VkQueueFamilyProperties2KHR;
+
+typedef struct VkPhysicalDeviceMemoryProperties2KHR {
+    VkStructureType                     sType;
+    void*                               pNext;
+    VkPhysicalDeviceMemoryProperties    memoryProperties;
+} VkPhysicalDeviceMemoryProperties2KHR;
+
+typedef struct VkSparseImageFormatProperties2KHR {
+    VkStructureType                  sType;
+    void*                            pNext;
+    VkSparseImageFormatProperties    properties;
+} VkSparseImageFormatProperties2KHR;
+
+typedef struct VkPhysicalDeviceSparseImageFormatInfo2KHR {
+    VkStructureType          sType;
+    const void*              pNext;
+    VkFormat                 format;
+    VkImageType              type;
+    VkSampleCountFlagBits    samples;
+    VkImageUsageFlags        usage;
+    VkImageTiling            tiling;
+} VkPhysicalDeviceSparseImageFormatInfo2KHR;
+
+
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2KHR* pFeatures);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2KHR* pProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties2KHR)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2KHR* pFormatProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2KHR* pImageFormatInfo, VkImageFormatProperties2KHR* pImageFormatProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties2KHR* pQueueFamilyProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2KHR)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo, uint32_t* pPropertyCount, VkSparseImageFormatProperties2KHR* pProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2KHR(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceFeatures2KHR*               pFeatures);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties2KHR(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceProperties2KHR*             pProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2KHR(
+    VkPhysicalDevice                            physicalDevice,
+    VkFormat                                    format,
+    VkFormatProperties2KHR*                     pFormatProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2KHR(
+    VkPhysicalDevice                            physicalDevice,
+    const VkPhysicalDeviceImageFormatInfo2KHR*  pImageFormatInfo,
+    VkImageFormatProperties2KHR*                pImageFormatProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2KHR(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t*                                   pQueueFamilyPropertyCount,
+    VkQueueFamilyProperties2KHR*                pQueueFamilyProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2KHR(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceMemoryProperties2KHR*       pMemoryProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR(
+    VkPhysicalDevice                            physicalDevice,
+    const VkPhysicalDeviceSparseImageFormatInfo2KHR* pFormatInfo,
+    uint32_t*                                   pPropertyCount,
+    VkSparseImageFormatProperties2KHR*          pProperties);
+#endif
+
 #define VK_KHR_incremental_present 1
 #define VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION 1
 #define VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME "VK_KHR_incremental_present"
@@ -3741,7 +3887,7 @@
 #define VK_EXT_debug_report 1
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
 
-#define VK_EXT_DEBUG_REPORT_SPEC_VERSION  3
+#define VK_EXT_DEBUG_REPORT_SPEC_VERSION  4
 #define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
 #define VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
 
@@ -3776,9 +3922,13 @@
     VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT = 26,
     VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT = 27,
     VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = 28,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT = 29,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT = 30,
+    VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT = 31,
+    VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT = 32,
     VK_DEBUG_REPORT_OBJECT_TYPE_BEGIN_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
-    VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
-    VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1),
+    VK_DEBUG_REPORT_OBJECT_TYPE_END_RANGE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT,
+    VK_DEBUG_REPORT_OBJECT_TYPE_RANGE_SIZE_EXT = (VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT - VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT + 1),
     VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF
 } VkDebugReportObjectTypeEXT;
 
@@ -3977,6 +4127,460 @@
 } VkDedicatedAllocationMemoryAllocateInfoNV;
 
 
+#define VK_GOOGLE_display_timing 1
+#define VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION 1
+#define VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME "VK_GOOGLE_display_timing"
+
+typedef struct VkRefreshCycleDurationGOOGLE {
+    uint64_t    minRefreshDuration;
+    uint64_t    maxRefreshDuration;
+} VkRefreshCycleDurationGOOGLE;
+
+typedef struct VkPastPresentationTimingGOOGLE {
+    uint32_t    presentID;
+    uint64_t    desiredPresentTime;
+    uint64_t    actualPresentTime;
+    uint64_t    earliestPresentTime;
+    uint64_t    presentMargin;
+} VkPastPresentationTimingGOOGLE;
+
+typedef struct VkPresentTimeGOOGLE {
+    uint32_t    presentID;
+    uint64_t    desiredPresentTime;
+} VkPresentTimeGOOGLE;
+
+typedef struct VkPresentTimesInfoGOOGLE {
+    VkStructureType               sType;
+    const void*                   pNext;
+    uint32_t                      swapchainCount;
+    const VkPresentTimeGOOGLE*    pTimes;
+} VkPresentTimesInfoGOOGLE;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetRefreshCycleDurationGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPastPresentationTimingGOOGLE)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetRefreshCycleDurationGOOGLE(
+    VkDevice                                    device,
+    VkSwapchainKHR                              swapchain,
+    VkRefreshCycleDurationGOOGLE*               pDisplayTimingProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE(
+    VkDevice                                    device,
+    VkSwapchainKHR                              swapchain,
+    uint32_t*                                   pPresentationTimingCount,
+    VkPastPresentationTimingGOOGLE*             pPresentationTimings);
+#endif
+
+
+#define VK_AMD_draw_indirect_count 1
+#define VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION 1
+#define VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME "VK_AMD_draw_indirect_count"
+
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirectCountAMD)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountAMD(
+    VkCommandBuffer                             commandBuffer,
+    VkBuffer                                    buffer,
+    VkDeviceSize                                offset,
+    VkBuffer                                    countBuffer,
+    VkDeviceSize                                countBufferOffset,
+    uint32_t                                    maxDrawCount,
+    uint32_t                                    stride);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD(
+    VkCommandBuffer                             commandBuffer,
+    VkBuffer                                    buffer,
+    VkDeviceSize                                offset,
+    VkBuffer                                    countBuffer,
+    VkDeviceSize                                countBufferOffset,
+    uint32_t                                    maxDrawCount,
+    uint32_t                                    stride);
+#endif
+
+#define VK_AMD_negative_viewport_height 1
+#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION 1
+#define VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME "VK_AMD_negative_viewport_height"
+
+
+#define VK_AMD_gpu_shader_half_float 1
+#define VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION 1
+#define VK_AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME "VK_AMD_gpu_shader_half_float"
+
+
+#define VK_AMD_shader_ballot 1
+#define VK_AMD_SHADER_BALLOT_SPEC_VERSION 1
+#define VK_AMD_SHADER_BALLOT_EXTENSION_NAME "VK_AMD_shader_ballot"
+
+
+#define VK_IMG_format_pvrtc 1
+#define VK_IMG_FORMAT_PVRTC_SPEC_VERSION  1
+#define VK_IMG_FORMAT_PVRTC_EXTENSION_NAME "VK_IMG_format_pvrtc"
+
+
+#define VK_NV_external_memory_capabilities 1
+#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION 1
+#define VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME "VK_NV_external_memory_capabilities"
+
+
+typedef enum VkExternalMemoryHandleTypeFlagBitsNV {
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV = 0x00000001,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV = 0x00000002,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV = 0x00000004,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV = 0x00000008,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
+} VkExternalMemoryHandleTypeFlagBitsNV;
+typedef VkFlags VkExternalMemoryHandleTypeFlagsNV;
+
+typedef enum VkExternalMemoryFeatureFlagBitsNV {
+    VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV = 0x00000001,
+    VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV = 0x00000002,
+    VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV = 0x00000004,
+    VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM_NV = 0x7FFFFFFF
+} VkExternalMemoryFeatureFlagBitsNV;
+typedef VkFlags VkExternalMemoryFeatureFlagsNV;
+
+typedef struct VkExternalImageFormatPropertiesNV {
+    VkImageFormatProperties              imageFormatProperties;
+    VkExternalMemoryFeatureFlagsNV       externalMemoryFeatures;
+    VkExternalMemoryHandleTypeFlagsNV    exportFromImportedHandleTypes;
+    VkExternalMemoryHandleTypeFlagsNV    compatibleHandleTypes;
+} VkExternalImageFormatPropertiesNV;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkExternalMemoryHandleTypeFlagsNV externalHandleType, VkExternalImageFormatPropertiesNV* pExternalImageFormatProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceExternalImageFormatPropertiesNV(
+    VkPhysicalDevice                            physicalDevice,
+    VkFormat                                    format,
+    VkImageType                                 type,
+    VkImageTiling                               tiling,
+    VkImageUsageFlags                           usage,
+    VkImageCreateFlags                          flags,
+    VkExternalMemoryHandleTypeFlagsNV           externalHandleType,
+    VkExternalImageFormatPropertiesNV*          pExternalImageFormatProperties);
+#endif
+
+#define VK_NV_external_memory 1
+#define VK_NV_EXTERNAL_MEMORY_SPEC_VERSION 1
+#define VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME "VK_NV_external_memory"
+
+typedef struct VkExternalMemoryImageCreateInfoNV {
+    VkStructureType                      sType;
+    const void*                          pNext;
+    VkExternalMemoryHandleTypeFlagsNV    handleTypes;
+} VkExternalMemoryImageCreateInfoNV;
+
+typedef struct VkExportMemoryAllocateInfoNV {
+    VkStructureType                      sType;
+    const void*                          pNext;
+    VkExternalMemoryHandleTypeFlagsNV    handleTypes;
+} VkExportMemoryAllocateInfoNV;
+
+
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+#define VK_NV_external_memory_win32 1
+#define VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
+#define VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_NV_external_memory_win32"
+
+typedef struct VkImportMemoryWin32HandleInfoNV {
+    VkStructureType                      sType;
+    const void*                          pNext;
+    VkExternalMemoryHandleTypeFlagsNV    handleType;
+    HANDLE                               handle;
+} VkImportMemoryWin32HandleInfoNV;
+
+typedef struct VkExportMemoryWin32HandleInfoNV {
+    VkStructureType               sType;
+    const void*                   pNext;
+    const SECURITY_ATTRIBUTES*    pAttributes;
+    DWORD                         dwAccess;
+} VkExportMemoryWin32HandleInfoNV;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleNV)(VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagsNV handleType, HANDLE* pHandle);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleNV(
+    VkDevice                                    device,
+    VkDeviceMemory                              memory,
+    VkExternalMemoryHandleTypeFlagsNV           handleType,
+    HANDLE*                                     pHandle);
+#endif
+#endif /* VK_USE_PLATFORM_WIN32_KHR */
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+#define VK_NV_win32_keyed_mutex 1
+#define VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION 1
+#define VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_NV_win32_keyed_mutex"
+
+typedef struct VkWin32KeyedMutexAcquireReleaseInfoNV {
+    VkStructureType          sType;
+    const void*              pNext;
+    uint32_t                 acquireCount;
+    const VkDeviceMemory*    pAcquireSyncs;
+    const uint64_t*          pAcquireKeys;
+    const uint32_t*          pAcquireTimeoutMilliseconds;
+    uint32_t                 releaseCount;
+    const VkDeviceMemory*    pReleaseSyncs;
+    const uint64_t*          pReleaseKeys;
+} VkWin32KeyedMutexAcquireReleaseInfoNV;
+
+
+#endif /* VK_USE_PLATFORM_WIN32_KHR */
+
+#define VK_EXT_validation_flags 1
+#define VK_EXT_VALIDATION_FLAGS_SPEC_VERSION 1
+#define VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME "VK_EXT_validation_flags"
+
+
+typedef enum VkValidationCheckEXT {
+    VK_VALIDATION_CHECK_ALL_EXT = 0,
+    VK_VALIDATION_CHECK_BEGIN_RANGE_EXT = VK_VALIDATION_CHECK_ALL_EXT,
+    VK_VALIDATION_CHECK_END_RANGE_EXT = VK_VALIDATION_CHECK_ALL_EXT,
+    VK_VALIDATION_CHECK_RANGE_SIZE_EXT = (VK_VALIDATION_CHECK_ALL_EXT - VK_VALIDATION_CHECK_ALL_EXT + 1),
+    VK_VALIDATION_CHECK_MAX_ENUM_EXT = 0x7FFFFFFF
+} VkValidationCheckEXT;
+
+typedef struct VkValidationFlagsEXT {
+    VkStructureType          sType;
+    const void*              pNext;
+    uint32_t                 disabledValidationCheckCount;
+    VkValidationCheckEXT*    pDisabledValidationChecks;
+} VkValidationFlagsEXT;
+
+
+
+#define VK_NVX_device_generated_commands 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkObjectTableNVX)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkIndirectCommandsLayoutNVX)
+
+#define VK_NVX_DEVICE_GENERATED_COMMANDS_SPEC_VERSION 1
+#define VK_NVX_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME "VK_NVX_device_generated_commands"
+
+
+typedef enum VkIndirectCommandsTokenTypeNVX {
+    VK_INDIRECT_COMMANDS_TOKEN_PIPELINE_NVX = 0,
+    VK_INDIRECT_COMMANDS_TOKEN_DESCRIPTOR_SET_NVX = 1,
+    VK_INDIRECT_COMMANDS_TOKEN_INDEX_BUFFER_NVX = 2,
+    VK_INDIRECT_COMMANDS_TOKEN_VERTEX_BUFFER_NVX = 3,
+    VK_INDIRECT_COMMANDS_TOKEN_PUSH_CONSTANT_NVX = 4,
+    VK_INDIRECT_COMMANDS_TOKEN_DRAW_INDEXED_NVX = 5,
+    VK_INDIRECT_COMMANDS_TOKEN_DRAW_NVX = 6,
+    VK_INDIRECT_COMMANDS_TOKEN_DISPATCH_NVX = 7,
+    VK_INDIRECT_COMMANDS_TOKEN_TYPE_BEGIN_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_PIPELINE_NVX,
+    VK_INDIRECT_COMMANDS_TOKEN_TYPE_END_RANGE_NVX = VK_INDIRECT_COMMANDS_TOKEN_DISPATCH_NVX,
+    VK_INDIRECT_COMMANDS_TOKEN_TYPE_RANGE_SIZE_NVX = (VK_INDIRECT_COMMANDS_TOKEN_DISPATCH_NVX - VK_INDIRECT_COMMANDS_TOKEN_PIPELINE_NVX + 1),
+    VK_INDIRECT_COMMANDS_TOKEN_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkIndirectCommandsTokenTypeNVX;
+
+typedef enum VkObjectEntryTypeNVX {
+    VK_OBJECT_ENTRY_DESCRIPTOR_SET_NVX = 0,
+    VK_OBJECT_ENTRY_PIPELINE_NVX = 1,
+    VK_OBJECT_ENTRY_INDEX_BUFFER_NVX = 2,
+    VK_OBJECT_ENTRY_VERTEX_BUFFER_NVX = 3,
+    VK_OBJECT_ENTRY_PUSH_CONSTANT_NVX = 4,
+    VK_OBJECT_ENTRY_TYPE_BEGIN_RANGE_NVX = VK_OBJECT_ENTRY_DESCRIPTOR_SET_NVX,
+    VK_OBJECT_ENTRY_TYPE_END_RANGE_NVX = VK_OBJECT_ENTRY_PUSH_CONSTANT_NVX,
+    VK_OBJECT_ENTRY_TYPE_RANGE_SIZE_NVX = (VK_OBJECT_ENTRY_PUSH_CONSTANT_NVX - VK_OBJECT_ENTRY_DESCRIPTOR_SET_NVX + 1),
+    VK_OBJECT_ENTRY_TYPE_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkObjectEntryTypeNVX;
+
+
+typedef enum VkIndirectCommandsLayoutUsageFlagBitsNVX {
+    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX = 0x00000001,
+    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX = 0x00000002,
+    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX = 0x00000004,
+    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX = 0x00000008,
+    VK_INDIRECT_COMMANDS_LAYOUT_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkIndirectCommandsLayoutUsageFlagBitsNVX;
+typedef VkFlags VkIndirectCommandsLayoutUsageFlagsNVX;
+
+typedef enum VkObjectEntryUsageFlagBitsNVX {
+    VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX = 0x00000001,
+    VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX = 0x00000002,
+    VK_OBJECT_ENTRY_USAGE_FLAG_BITS_MAX_ENUM_NVX = 0x7FFFFFFF
+} VkObjectEntryUsageFlagBitsNVX;
+typedef VkFlags VkObjectEntryUsageFlagsNVX;
+
+typedef struct VkDeviceGeneratedCommandsFeaturesNVX {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkBool32           computeBindingPointSupport;
+} VkDeviceGeneratedCommandsFeaturesNVX;
+
+typedef struct VkDeviceGeneratedCommandsLimitsNVX {
+    VkStructureType    sType;
+    const void*        pNext;
+    uint32_t           maxIndirectCommandsLayoutTokenCount;
+    uint32_t           maxObjectEntryCounts;
+    uint32_t           minSequenceCountBufferOffsetAlignment;
+    uint32_t           minSequenceIndexBufferOffsetAlignment;
+    uint32_t           minCommandsTokenBufferOffsetAlignment;
+} VkDeviceGeneratedCommandsLimitsNVX;
+
+typedef struct VkIndirectCommandsTokenNVX {
+    VkIndirectCommandsTokenTypeNVX    tokenType;
+    VkBuffer                          buffer;
+    VkDeviceSize                      offset;
+} VkIndirectCommandsTokenNVX;
+
+typedef struct VkIndirectCommandsLayoutTokenNVX {
+    VkIndirectCommandsTokenTypeNVX    tokenType;
+    uint32_t                          bindingUnit;
+    uint32_t                          dynamicCount;
+    uint32_t                          divisor;
+} VkIndirectCommandsLayoutTokenNVX;
+
+typedef struct VkIndirectCommandsLayoutCreateInfoNVX {
+    VkStructureType                            sType;
+    const void*                                pNext;
+    VkPipelineBindPoint                        pipelineBindPoint;
+    VkIndirectCommandsLayoutUsageFlagsNVX      flags;
+    uint32_t                                   tokenCount;
+    const VkIndirectCommandsLayoutTokenNVX*    pTokens;
+} VkIndirectCommandsLayoutCreateInfoNVX;
+
+typedef struct VkCmdProcessCommandsInfoNVX {
+    VkStructureType                      sType;
+    const void*                          pNext;
+    VkObjectTableNVX                     objectTable;
+    VkIndirectCommandsLayoutNVX          indirectCommandsLayout;
+    uint32_t                             indirectCommandsTokenCount;
+    const VkIndirectCommandsTokenNVX*    pIndirectCommandsTokens;
+    uint32_t                             maxSequencesCount;
+    VkCommandBuffer                      targetCommandBuffer;
+    VkBuffer                             sequencesCountBuffer;
+    VkDeviceSize                         sequencesCountOffset;
+    VkBuffer                             sequencesIndexBuffer;
+    VkDeviceSize                         sequencesIndexOffset;
+} VkCmdProcessCommandsInfoNVX;
+
+typedef struct VkCmdReserveSpaceForCommandsInfoNVX {
+    VkStructureType                sType;
+    const void*                    pNext;
+    VkObjectTableNVX               objectTable;
+    VkIndirectCommandsLayoutNVX    indirectCommandsLayout;
+    uint32_t                       maxSequencesCount;
+} VkCmdReserveSpaceForCommandsInfoNVX;
+
+typedef struct VkObjectTableCreateInfoNVX {
+    VkStructureType                      sType;
+    const void*                          pNext;
+    uint32_t                             objectCount;
+    const VkObjectEntryTypeNVX*          pObjectEntryTypes;
+    const uint32_t*                      pObjectEntryCounts;
+    const VkObjectEntryUsageFlagsNVX*    pObjectEntryUsageFlags;
+    uint32_t                             maxUniformBuffersPerDescriptor;
+    uint32_t                             maxStorageBuffersPerDescriptor;
+    uint32_t                             maxStorageImagesPerDescriptor;
+    uint32_t                             maxSampledImagesPerDescriptor;
+    uint32_t                             maxPipelineLayouts;
+} VkObjectTableCreateInfoNVX;
+
+typedef struct VkObjectTableEntryNVX {
+    VkObjectEntryTypeNVX          type;
+    VkObjectEntryUsageFlagsNVX    flags;
+} VkObjectTableEntryNVX;
+
+typedef struct VkObjectTablePipelineEntryNVX {
+    VkObjectEntryTypeNVX          type;
+    VkObjectEntryUsageFlagsNVX    flags;
+    VkPipeline                    pipeline;
+} VkObjectTablePipelineEntryNVX;
+
+typedef struct VkObjectTableDescriptorSetEntryNVX {
+    VkObjectEntryTypeNVX          type;
+    VkObjectEntryUsageFlagsNVX    flags;
+    VkPipelineLayout              pipelineLayout;
+    VkDescriptorSet               descriptorSet;
+} VkObjectTableDescriptorSetEntryNVX;
+
+typedef struct VkObjectTableVertexBufferEntryNVX {
+    VkObjectEntryTypeNVX          type;
+    VkObjectEntryUsageFlagsNVX    flags;
+    VkBuffer                      buffer;
+} VkObjectTableVertexBufferEntryNVX;
+
+typedef struct VkObjectTableIndexBufferEntryNVX {
+    VkObjectEntryTypeNVX          type;
+    VkObjectEntryUsageFlagsNVX    flags;
+    VkBuffer                      buffer;
+} VkObjectTableIndexBufferEntryNVX;
+
+typedef struct VkObjectTablePushConstantEntryNVX {
+    VkObjectEntryTypeNVX          type;
+    VkObjectEntryUsageFlagsNVX    flags;
+    VkPipelineLayout              pipelineLayout;
+    VkShaderStageFlags            stageFlags;
+} VkObjectTablePushConstantEntryNVX;
+
+
+typedef void (VKAPI_PTR *PFN_vkCmdProcessCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdProcessCommandsInfoNVX* pProcessCommandsInfo);
+typedef void (VKAPI_PTR *PFN_vkCmdReserveSpaceForCommandsNVX)(VkCommandBuffer commandBuffer, const VkCmdReserveSpaceForCommandsInfoNVX* pReserveSpaceInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateIndirectCommandsLayoutNVX)(VkDevice device, const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkIndirectCommandsLayoutNVX* pIndirectCommandsLayout);
+typedef void (VKAPI_PTR *PFN_vkDestroyIndirectCommandsLayoutNVX)(VkDevice device, VkIndirectCommandsLayoutNVX indirectCommandsLayout, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateObjectTableNVX)(VkDevice device, const VkObjectTableCreateInfoNVX* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkObjectTableNVX* pObjectTable);
+typedef void (VKAPI_PTR *PFN_vkDestroyObjectTableNVX)(VkDevice device, VkObjectTableNVX objectTable, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkRegisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectTableEntryNVX* const*    ppObjectTableEntries, const uint32_t* pObjectIndices);
+typedef VkResult (VKAPI_PTR *PFN_vkUnregisterObjectsNVX)(VkDevice device, VkObjectTableNVX objectTable, uint32_t objectCount, const VkObjectEntryTypeNVX* pObjectEntryTypes, const uint32_t* pObjectIndices);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX)(VkPhysicalDevice physicalDevice, VkDeviceGeneratedCommandsFeaturesNVX* pFeatures, VkDeviceGeneratedCommandsLimitsNVX* pLimits);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkCmdProcessCommandsNVX(
+    VkCommandBuffer                             commandBuffer,
+    const VkCmdProcessCommandsInfoNVX*          pProcessCommandsInfo);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdReserveSpaceForCommandsNVX(
+    VkCommandBuffer                             commandBuffer,
+    const VkCmdReserveSpaceForCommandsInfoNVX*  pReserveSpaceInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateIndirectCommandsLayoutNVX(
+    VkDevice                                    device,
+    const VkIndirectCommandsLayoutCreateInfoNVX* pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkIndirectCommandsLayoutNVX*                pIndirectCommandsLayout);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyIndirectCommandsLayoutNVX(
+    VkDevice                                    device,
+    VkIndirectCommandsLayoutNVX                 indirectCommandsLayout,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateObjectTableNVX(
+    VkDevice                                    device,
+    const VkObjectTableCreateInfoNVX*           pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkObjectTableNVX*                           pObjectTable);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyObjectTableNVX(
+    VkDevice                                    device,
+    VkObjectTableNVX                            objectTable,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkRegisterObjectsNVX(
+    VkDevice                                    device,
+    VkObjectTableNVX                            objectTable,
+    uint32_t                                    objectCount,
+    const VkObjectTableEntryNVX* const*         ppObjectTableEntries,
+    const uint32_t*                             pObjectIndices);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkUnregisterObjectsNVX(
+    VkDevice                                    device,
+    VkObjectTableNVX                            objectTable,
+    uint32_t                                    objectCount,
+    const VkObjectEntryTypeNVX*                 pObjectEntryTypes,
+    const uint32_t*                             pObjectIndices);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX(
+    VkPhysicalDevice                            physicalDevice,
+    VkDeviceGeneratedCommandsFeaturesNVX*       pFeatures,
+    VkDeviceGeneratedCommandsLimitsNVX*         pLimits);
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 5a0a93b..ba883f7 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -17,6 +17,7 @@
     name: "libvulkan.ndk",
     symbol_file: "libvulkan.map.txt",
     first_version: "24",
+    unversioned_until: "current",
 }
 
 cc_library_shared {
@@ -46,6 +47,7 @@
         "-Wno-c99-extensions",
         "-Wno-c++98-compat-pedantic",
         "-Wno-exit-time-destructors",
+        "-Wno-float-equal",
         "-Wno-global-constructors",
         "-Wno-zero-length-array",
     ],
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index b699fe9..f5daca7 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -27,8 +27,9 @@
 #include <mutex>
 #include <new>
 #include <utility>
+
+#include <android/log.h>
 #include <cutils/properties.h>
-#include <log/log.h>
 
 #include <vulkan/vk_layer_interface.h>
 #include "api.h"
@@ -1048,7 +1049,8 @@
 VkResult LayerChain::CreateInstance(const VkInstanceCreateInfo* create_info,
                                     const VkAllocationCallbacks* allocator,
                                     VkInstance* instance_out) {
-    LayerChain chain(true, driver::DebugReportLogger(*create_info),
+    const driver::DebugReportLogger logger(*create_info);
+    LayerChain chain(true, logger,
                      (allocator) ? *allocator : driver::GetDefaultAllocator());
 
     VkResult result = chain.ActivateLayers(create_info->ppEnabledLayerNames,
@@ -1073,8 +1075,9 @@
                                   const VkDeviceCreateInfo* create_info,
                                   const VkAllocationCallbacks* allocator,
                                   VkDevice* dev_out) {
+    const driver::DebugReportLogger logger = driver::Logger(physical_dev);
     LayerChain chain(
-        false, driver::Logger(physical_dev),
+        false, logger,
         (allocator) ? *allocator : driver::GetData(physical_dev).allocator);
 
     VkResult result = chain.ActivateLayers(
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
index a57ba72..b4e256a 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -18,7 +18,7 @@
 
 #include <string.h>
 #include <algorithm>
-#include <log/log.h>
+#include <android/log.h>
 
 // to catch mismatches between vulkan.h and this file
 #undef VK_NO_PROTOTYPES
@@ -29,11 +29,11 @@
 
 #define UNLIKELY(expr) __builtin_expect((expr), 0)
 
-#define INIT_PROC(obj, proc)                                           \
+#define INIT_PROC(required, obj, proc)                                 \
     do {                                                               \
         data.dispatch.proc =                                           \
             reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \
-        if (UNLIKELY(!data.dispatch.proc)) {                           \
+        if (UNLIKELY(required && !data.dispatch.proc)) {               \
             ALOGE("missing " #obj " proc: vk" #proc);                  \
             success = false;                                           \
         }                                                              \
@@ -41,10 +41,10 @@
 
 // Exported extension functions may be invoked even when their extensions
 // are disabled.  Dispatch to stubs when that happens.
-#define INIT_PROC_EXT(ext, obj, proc)            \
+#define INIT_PROC_EXT(ext, required, obj, proc)  \
     do {                                         \
         if (extensions[driver::ProcHook::ext])   \
-            INIT_PROC(obj, proc);                \
+            INIT_PROC(required, obj, proc);      \
         else                                     \
             data.dispatch.proc = disabled##proc; \
     } while (0)
@@ -118,24 +118,24 @@
     bool success = true;
 
     // clang-format off
-    INIT_PROC(instance, DestroyInstance);
-    INIT_PROC(instance, EnumeratePhysicalDevices);
-    INIT_PROC(instance, GetInstanceProcAddr);
-    INIT_PROC(instance, GetPhysicalDeviceProperties);
-    INIT_PROC(instance, GetPhysicalDeviceQueueFamilyProperties);
-    INIT_PROC(instance, GetPhysicalDeviceMemoryProperties);
-    INIT_PROC(instance, GetPhysicalDeviceFeatures);
-    INIT_PROC(instance, GetPhysicalDeviceFormatProperties);
-    INIT_PROC(instance, GetPhysicalDeviceImageFormatProperties);
-    INIT_PROC(instance, CreateDevice);
-    INIT_PROC(instance, EnumerateDeviceExtensionProperties);
-    INIT_PROC(instance, GetPhysicalDeviceSparseImageFormatProperties);
-    INIT_PROC_EXT(KHR_surface, instance, DestroySurfaceKHR);
-    INIT_PROC_EXT(KHR_surface, instance, GetPhysicalDeviceSurfaceSupportKHR);
-    INIT_PROC_EXT(KHR_surface, instance, GetPhysicalDeviceSurfaceCapabilitiesKHR);
-    INIT_PROC_EXT(KHR_surface, instance, GetPhysicalDeviceSurfaceFormatsKHR);
-    INIT_PROC_EXT(KHR_surface, instance, GetPhysicalDeviceSurfacePresentModesKHR);
-    INIT_PROC_EXT(KHR_android_surface, instance, CreateAndroidSurfaceKHR);
+    INIT_PROC(true, instance, DestroyInstance);
+    INIT_PROC(true, instance, EnumeratePhysicalDevices);
+    INIT_PROC(true, instance, GetInstanceProcAddr);
+    INIT_PROC(true, instance, GetPhysicalDeviceProperties);
+    INIT_PROC(true, instance, GetPhysicalDeviceQueueFamilyProperties);
+    INIT_PROC(true, instance, GetPhysicalDeviceMemoryProperties);
+    INIT_PROC(true, instance, GetPhysicalDeviceFeatures);
+    INIT_PROC(true, instance, GetPhysicalDeviceFormatProperties);
+    INIT_PROC(true, instance, GetPhysicalDeviceImageFormatProperties);
+    INIT_PROC(true, instance, CreateDevice);
+    INIT_PROC(true, instance, EnumerateDeviceExtensionProperties);
+    INIT_PROC(true, instance, GetPhysicalDeviceSparseImageFormatProperties);
+    INIT_PROC_EXT(KHR_surface, true, instance, DestroySurfaceKHR);
+    INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfaceSupportKHR);
+    INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfaceCapabilitiesKHR);
+    INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfaceFormatsKHR);
+    INIT_PROC_EXT(KHR_surface, true, instance, GetPhysicalDeviceSurfacePresentModesKHR);
+    INIT_PROC_EXT(KHR_android_surface, true, instance, CreateAndroidSurfaceKHR);
     // clang-format on
 
     return success;
@@ -149,132 +149,132 @@
     bool success = true;
 
     // clang-format off
-    INIT_PROC(dev, GetDeviceProcAddr);
-    INIT_PROC(dev, DestroyDevice);
-    INIT_PROC(dev, GetDeviceQueue);
-    INIT_PROC(dev, QueueSubmit);
-    INIT_PROC(dev, QueueWaitIdle);
-    INIT_PROC(dev, DeviceWaitIdle);
-    INIT_PROC(dev, AllocateMemory);
-    INIT_PROC(dev, FreeMemory);
-    INIT_PROC(dev, MapMemory);
-    INIT_PROC(dev, UnmapMemory);
-    INIT_PROC(dev, FlushMappedMemoryRanges);
-    INIT_PROC(dev, InvalidateMappedMemoryRanges);
-    INIT_PROC(dev, GetDeviceMemoryCommitment);
-    INIT_PROC(dev, GetBufferMemoryRequirements);
-    INIT_PROC(dev, BindBufferMemory);
-    INIT_PROC(dev, GetImageMemoryRequirements);
-    INIT_PROC(dev, BindImageMemory);
-    INIT_PROC(dev, GetImageSparseMemoryRequirements);
-    INIT_PROC(dev, QueueBindSparse);
-    INIT_PROC(dev, CreateFence);
-    INIT_PROC(dev, DestroyFence);
-    INIT_PROC(dev, ResetFences);
-    INIT_PROC(dev, GetFenceStatus);
-    INIT_PROC(dev, WaitForFences);
-    INIT_PROC(dev, CreateSemaphore);
-    INIT_PROC(dev, DestroySemaphore);
-    INIT_PROC(dev, CreateEvent);
-    INIT_PROC(dev, DestroyEvent);
-    INIT_PROC(dev, GetEventStatus);
-    INIT_PROC(dev, SetEvent);
-    INIT_PROC(dev, ResetEvent);
-    INIT_PROC(dev, CreateQueryPool);
-    INIT_PROC(dev, DestroyQueryPool);
-    INIT_PROC(dev, GetQueryPoolResults);
-    INIT_PROC(dev, CreateBuffer);
-    INIT_PROC(dev, DestroyBuffer);
-    INIT_PROC(dev, CreateBufferView);
-    INIT_PROC(dev, DestroyBufferView);
-    INIT_PROC(dev, CreateImage);
-    INIT_PROC(dev, DestroyImage);
-    INIT_PROC(dev, GetImageSubresourceLayout);
-    INIT_PROC(dev, CreateImageView);
-    INIT_PROC(dev, DestroyImageView);
-    INIT_PROC(dev, CreateShaderModule);
-    INIT_PROC(dev, DestroyShaderModule);
-    INIT_PROC(dev, CreatePipelineCache);
-    INIT_PROC(dev, DestroyPipelineCache);
-    INIT_PROC(dev, GetPipelineCacheData);
-    INIT_PROC(dev, MergePipelineCaches);
-    INIT_PROC(dev, CreateGraphicsPipelines);
-    INIT_PROC(dev, CreateComputePipelines);
-    INIT_PROC(dev, DestroyPipeline);
-    INIT_PROC(dev, CreatePipelineLayout);
-    INIT_PROC(dev, DestroyPipelineLayout);
-    INIT_PROC(dev, CreateSampler);
-    INIT_PROC(dev, DestroySampler);
-    INIT_PROC(dev, CreateDescriptorSetLayout);
-    INIT_PROC(dev, DestroyDescriptorSetLayout);
-    INIT_PROC(dev, CreateDescriptorPool);
-    INIT_PROC(dev, DestroyDescriptorPool);
-    INIT_PROC(dev, ResetDescriptorPool);
-    INIT_PROC(dev, AllocateDescriptorSets);
-    INIT_PROC(dev, FreeDescriptorSets);
-    INIT_PROC(dev, UpdateDescriptorSets);
-    INIT_PROC(dev, CreateFramebuffer);
-    INIT_PROC(dev, DestroyFramebuffer);
-    INIT_PROC(dev, CreateRenderPass);
-    INIT_PROC(dev, DestroyRenderPass);
-    INIT_PROC(dev, GetRenderAreaGranularity);
-    INIT_PROC(dev, CreateCommandPool);
-    INIT_PROC(dev, DestroyCommandPool);
-    INIT_PROC(dev, ResetCommandPool);
-    INIT_PROC(dev, AllocateCommandBuffers);
-    INIT_PROC(dev, FreeCommandBuffers);
-    INIT_PROC(dev, BeginCommandBuffer);
-    INIT_PROC(dev, EndCommandBuffer);
-    INIT_PROC(dev, ResetCommandBuffer);
-    INIT_PROC(dev, CmdBindPipeline);
-    INIT_PROC(dev, CmdSetViewport);
-    INIT_PROC(dev, CmdSetScissor);
-    INIT_PROC(dev, CmdSetLineWidth);
-    INIT_PROC(dev, CmdSetDepthBias);
-    INIT_PROC(dev, CmdSetBlendConstants);
-    INIT_PROC(dev, CmdSetDepthBounds);
-    INIT_PROC(dev, CmdSetStencilCompareMask);
-    INIT_PROC(dev, CmdSetStencilWriteMask);
-    INIT_PROC(dev, CmdSetStencilReference);
-    INIT_PROC(dev, CmdBindDescriptorSets);
-    INIT_PROC(dev, CmdBindIndexBuffer);
-    INIT_PROC(dev, CmdBindVertexBuffers);
-    INIT_PROC(dev, CmdDraw);
-    INIT_PROC(dev, CmdDrawIndexed);
-    INIT_PROC(dev, CmdDrawIndirect);
-    INIT_PROC(dev, CmdDrawIndexedIndirect);
-    INIT_PROC(dev, CmdDispatch);
-    INIT_PROC(dev, CmdDispatchIndirect);
-    INIT_PROC(dev, CmdCopyBuffer);
-    INIT_PROC(dev, CmdCopyImage);
-    INIT_PROC(dev, CmdBlitImage);
-    INIT_PROC(dev, CmdCopyBufferToImage);
-    INIT_PROC(dev, CmdCopyImageToBuffer);
-    INIT_PROC(dev, CmdUpdateBuffer);
-    INIT_PROC(dev, CmdFillBuffer);
-    INIT_PROC(dev, CmdClearColorImage);
-    INIT_PROC(dev, CmdClearDepthStencilImage);
-    INIT_PROC(dev, CmdClearAttachments);
-    INIT_PROC(dev, CmdResolveImage);
-    INIT_PROC(dev, CmdSetEvent);
-    INIT_PROC(dev, CmdResetEvent);
-    INIT_PROC(dev, CmdWaitEvents);
-    INIT_PROC(dev, CmdPipelineBarrier);
-    INIT_PROC(dev, CmdBeginQuery);
-    INIT_PROC(dev, CmdEndQuery);
-    INIT_PROC(dev, CmdResetQueryPool);
-    INIT_PROC(dev, CmdWriteTimestamp);
-    INIT_PROC(dev, CmdCopyQueryPoolResults);
-    INIT_PROC(dev, CmdPushConstants);
-    INIT_PROC(dev, CmdBeginRenderPass);
-    INIT_PROC(dev, CmdNextSubpass);
-    INIT_PROC(dev, CmdEndRenderPass);
-    INIT_PROC(dev, CmdExecuteCommands);
-    INIT_PROC_EXT(KHR_swapchain, dev, CreateSwapchainKHR);
-    INIT_PROC_EXT(KHR_swapchain, dev, DestroySwapchainKHR);
-    INIT_PROC_EXT(KHR_swapchain, dev, GetSwapchainImagesKHR);
-    INIT_PROC_EXT(KHR_swapchain, dev, AcquireNextImageKHR);
-    INIT_PROC_EXT(KHR_swapchain, dev, QueuePresentKHR);
+    INIT_PROC(true, dev, GetDeviceProcAddr);
+    INIT_PROC(true, dev, DestroyDevice);
+    INIT_PROC(true, dev, GetDeviceQueue);
+    INIT_PROC(true, dev, QueueSubmit);
+    INIT_PROC(true, dev, QueueWaitIdle);
+    INIT_PROC(true, dev, DeviceWaitIdle);
+    INIT_PROC(true, dev, AllocateMemory);
+    INIT_PROC(true, dev, FreeMemory);
+    INIT_PROC(true, dev, MapMemory);
+    INIT_PROC(true, dev, UnmapMemory);
+    INIT_PROC(true, dev, FlushMappedMemoryRanges);
+    INIT_PROC(true, dev, InvalidateMappedMemoryRanges);
+    INIT_PROC(true, dev, GetDeviceMemoryCommitment);
+    INIT_PROC(true, dev, GetBufferMemoryRequirements);
+    INIT_PROC(true, dev, BindBufferMemory);
+    INIT_PROC(true, dev, GetImageMemoryRequirements);
+    INIT_PROC(true, dev, BindImageMemory);
+    INIT_PROC(true, dev, GetImageSparseMemoryRequirements);
+    INIT_PROC(true, dev, QueueBindSparse);
+    INIT_PROC(true, dev, CreateFence);
+    INIT_PROC(true, dev, DestroyFence);
+    INIT_PROC(true, dev, ResetFences);
+    INIT_PROC(true, dev, GetFenceStatus);
+    INIT_PROC(true, dev, WaitForFences);
+    INIT_PROC(true, dev, CreateSemaphore);
+    INIT_PROC(true, dev, DestroySemaphore);
+    INIT_PROC(true, dev, CreateEvent);
+    INIT_PROC(true, dev, DestroyEvent);
+    INIT_PROC(true, dev, GetEventStatus);
+    INIT_PROC(true, dev, SetEvent);
+    INIT_PROC(true, dev, ResetEvent);
+    INIT_PROC(true, dev, CreateQueryPool);
+    INIT_PROC(true, dev, DestroyQueryPool);
+    INIT_PROC(true, dev, GetQueryPoolResults);
+    INIT_PROC(true, dev, CreateBuffer);
+    INIT_PROC(true, dev, DestroyBuffer);
+    INIT_PROC(true, dev, CreateBufferView);
+    INIT_PROC(true, dev, DestroyBufferView);
+    INIT_PROC(true, dev, CreateImage);
+    INIT_PROC(true, dev, DestroyImage);
+    INIT_PROC(true, dev, GetImageSubresourceLayout);
+    INIT_PROC(true, dev, CreateImageView);
+    INIT_PROC(true, dev, DestroyImageView);
+    INIT_PROC(true, dev, CreateShaderModule);
+    INIT_PROC(true, dev, DestroyShaderModule);
+    INIT_PROC(true, dev, CreatePipelineCache);
+    INIT_PROC(true, dev, DestroyPipelineCache);
+    INIT_PROC(true, dev, GetPipelineCacheData);
+    INIT_PROC(true, dev, MergePipelineCaches);
+    INIT_PROC(true, dev, CreateGraphicsPipelines);
+    INIT_PROC(true, dev, CreateComputePipelines);
+    INIT_PROC(true, dev, DestroyPipeline);
+    INIT_PROC(true, dev, CreatePipelineLayout);
+    INIT_PROC(true, dev, DestroyPipelineLayout);
+    INIT_PROC(true, dev, CreateSampler);
+    INIT_PROC(true, dev, DestroySampler);
+    INIT_PROC(true, dev, CreateDescriptorSetLayout);
+    INIT_PROC(true, dev, DestroyDescriptorSetLayout);
+    INIT_PROC(true, dev, CreateDescriptorPool);
+    INIT_PROC(true, dev, DestroyDescriptorPool);
+    INIT_PROC(true, dev, ResetDescriptorPool);
+    INIT_PROC(true, dev, AllocateDescriptorSets);
+    INIT_PROC(true, dev, FreeDescriptorSets);
+    INIT_PROC(true, dev, UpdateDescriptorSets);
+    INIT_PROC(true, dev, CreateFramebuffer);
+    INIT_PROC(true, dev, DestroyFramebuffer);
+    INIT_PROC(true, dev, CreateRenderPass);
+    INIT_PROC(true, dev, DestroyRenderPass);
+    INIT_PROC(true, dev, GetRenderAreaGranularity);
+    INIT_PROC(true, dev, CreateCommandPool);
+    INIT_PROC(true, dev, DestroyCommandPool);
+    INIT_PROC(true, dev, ResetCommandPool);
+    INIT_PROC(true, dev, AllocateCommandBuffers);
+    INIT_PROC(true, dev, FreeCommandBuffers);
+    INIT_PROC(true, dev, BeginCommandBuffer);
+    INIT_PROC(true, dev, EndCommandBuffer);
+    INIT_PROC(true, dev, ResetCommandBuffer);
+    INIT_PROC(true, dev, CmdBindPipeline);
+    INIT_PROC(true, dev, CmdSetViewport);
+    INIT_PROC(true, dev, CmdSetScissor);
+    INIT_PROC(true, dev, CmdSetLineWidth);
+    INIT_PROC(true, dev, CmdSetDepthBias);
+    INIT_PROC(true, dev, CmdSetBlendConstants);
+    INIT_PROC(true, dev, CmdSetDepthBounds);
+    INIT_PROC(true, dev, CmdSetStencilCompareMask);
+    INIT_PROC(true, dev, CmdSetStencilWriteMask);
+    INIT_PROC(true, dev, CmdSetStencilReference);
+    INIT_PROC(true, dev, CmdBindDescriptorSets);
+    INIT_PROC(true, dev, CmdBindIndexBuffer);
+    INIT_PROC(true, dev, CmdBindVertexBuffers);
+    INIT_PROC(true, dev, CmdDraw);
+    INIT_PROC(true, dev, CmdDrawIndexed);
+    INIT_PROC(true, dev, CmdDrawIndirect);
+    INIT_PROC(true, dev, CmdDrawIndexedIndirect);
+    INIT_PROC(true, dev, CmdDispatch);
+    INIT_PROC(true, dev, CmdDispatchIndirect);
+    INIT_PROC(true, dev, CmdCopyBuffer);
+    INIT_PROC(true, dev, CmdCopyImage);
+    INIT_PROC(true, dev, CmdBlitImage);
+    INIT_PROC(true, dev, CmdCopyBufferToImage);
+    INIT_PROC(true, dev, CmdCopyImageToBuffer);
+    INIT_PROC(true, dev, CmdUpdateBuffer);
+    INIT_PROC(true, dev, CmdFillBuffer);
+    INIT_PROC(true, dev, CmdClearColorImage);
+    INIT_PROC(true, dev, CmdClearDepthStencilImage);
+    INIT_PROC(true, dev, CmdClearAttachments);
+    INIT_PROC(true, dev, CmdResolveImage);
+    INIT_PROC(true, dev, CmdSetEvent);
+    INIT_PROC(true, dev, CmdResetEvent);
+    INIT_PROC(true, dev, CmdWaitEvents);
+    INIT_PROC(true, dev, CmdPipelineBarrier);
+    INIT_PROC(true, dev, CmdBeginQuery);
+    INIT_PROC(true, dev, CmdEndQuery);
+    INIT_PROC(true, dev, CmdResetQueryPool);
+    INIT_PROC(true, dev, CmdWriteTimestamp);
+    INIT_PROC(true, dev, CmdCopyQueryPoolResults);
+    INIT_PROC(true, dev, CmdPushConstants);
+    INIT_PROC(true, dev, CmdBeginRenderPass);
+    INIT_PROC(true, dev, CmdNextSubpass);
+    INIT_PROC(true, dev, CmdEndRenderPass);
+    INIT_PROC(true, dev, CmdExecuteCommands);
+    INIT_PROC_EXT(KHR_swapchain, true, dev, CreateSwapchainKHR);
+    INIT_PROC_EXT(KHR_swapchain, true, dev, DestroySwapchainKHR);
+    INIT_PROC_EXT(KHR_swapchain, true, dev, GetSwapchainImagesKHR);
+    INIT_PROC_EXT(KHR_swapchain, true, dev, AcquireNextImageKHR);
+    INIT_PROC_EXT(KHR_swapchain, true, dev, QueuePresentKHR);
     // clang-format on
 
     return success;
@@ -425,6 +425,8 @@
 VKAPI_ATTR VkResult AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex);
 VKAPI_ATTR VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo);
 VKAPI_ATTR VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+VKAPI_ATTR VkResult GetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties);
+VKAPI_ATTR VkResult GetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings);
 
 VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices) {
     return GetData(instance).dispatch.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
@@ -451,13 +453,22 @@
         "vkEnumerateInstanceLayerProperties",
         "vkEnumeratePhysicalDevices",
         "vkGetInstanceProcAddr",
+        "vkGetPhysicalDeviceExternalImageFormatPropertiesNV",
         "vkGetPhysicalDeviceFeatures",
+        "vkGetPhysicalDeviceFeatures2KHR",
         "vkGetPhysicalDeviceFormatProperties",
+        "vkGetPhysicalDeviceFormatProperties2KHR",
+        "vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX",
         "vkGetPhysicalDeviceImageFormatProperties",
+        "vkGetPhysicalDeviceImageFormatProperties2KHR",
         "vkGetPhysicalDeviceMemoryProperties",
+        "vkGetPhysicalDeviceMemoryProperties2KHR",
         "vkGetPhysicalDeviceProperties",
+        "vkGetPhysicalDeviceProperties2KHR",
         "vkGetPhysicalDeviceQueueFamilyProperties",
+        "vkGetPhysicalDeviceQueueFamilyProperties2KHR",
         "vkGetPhysicalDeviceSparseImageFormatProperties",
+        "vkGetPhysicalDeviceSparseImageFormatProperties2KHR",
         "vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
         "vkGetPhysicalDeviceSurfaceFormatsKHR",
         "vkGetPhysicalDeviceSurfacePresentModesKHR",
@@ -1199,6 +1210,14 @@
     return GetData(instance).dispatch.CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
 }
 
+VKAPI_ATTR VkResult GetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
+    return GetData(device).dispatch.GetRefreshCycleDurationGOOGLE(device, swapchain, pDisplayTimingProperties);
+}
+
+VKAPI_ATTR VkResult GetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings) {
+    return GetData(device).dispatch.GetPastPresentationTimingGOOGLE(device, swapchain, pPresentationTimingCount, pPresentationTimings);
+}
+
 
 }  // anonymous namespace
 
diff --git a/vulkan/libvulkan/api_gen.h b/vulkan/libvulkan/api_gen.h
index 7f8d274..918c1f5 100644
--- a/vulkan/libvulkan/api_gen.h
+++ b/vulkan/libvulkan/api_gen.h
@@ -177,6 +177,8 @@
     PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR;
     PFN_vkAcquireNextImageKHR AcquireNextImageKHR;
     PFN_vkQueuePresentKHR QueuePresentKHR;
+    PFN_vkGetRefreshCycleDurationGOOGLE GetRefreshCycleDurationGOOGLE;
+    PFN_vkGetPastPresentationTimingGOOGLE GetPastPresentationTimingGOOGLE;
     // clang-format on
 };
 
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
index f9a4670..2c70d46 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -92,7 +92,7 @@

 #include <string.h>
 #include <algorithm>
-#include <log/log.h>
+#include <android/log.h>

 // to catch mismatches between vulkan.h and this file
 #undef VK_NO_PROTOTYPES
@@ -271,7 +271,7 @@

 #include <string.h>
 #include <algorithm>
-#include <log/log.h>
+#include <android/log.h>

 #include "driver.h"

@@ -389,10 +389,10 @@
 {{define "C++.DefineInitProcMacro"}}
   #define UNLIKELY(expr) __builtin_expect((expr), 0)

-  #define INIT_PROC(obj, proc) do {                             \
+  #define INIT_PROC(required, obj, proc) do {                   \
       data.{{$}}.proc = reinterpret_cast<PFN_vk ## proc>(       \
               get_proc(obj, "vk" # proc));                      \
-      if (UNLIKELY(!data.{{$}}.proc)) {                         \
+      if (UNLIKELY(required && !data.{{$}}.proc)) {             \
           ALOGE("missing " # obj " proc: vk" # proc);           \
           success = false;                                      \
       }                                                         \
@@ -409,10 +409,11 @@
   {{AssertType $ "Function"}}
 
   {{$ext := GetAnnotation $ "extension"}}
+  {{$required := (Macro "IsRequiredFunction" $)}}
   {{if $ext}}
-    INIT_PROC_EXT({{Macro "BaseName" $ext}}, §
+    INIT_PROC_EXT({{Macro "BaseName" $ext}}, {{$required}}, §
   {{else}}
-    INIT_PROC(§
+    INIT_PROC({{$required}}, §
   {{end}}
 
   {{if (Macro "IsInstanceDispatched" $)}}
@@ -427,6 +428,25 @@
 
 {{/*
 ------------------------------------------------------------------------------
+  Emits true if a function /must/ be resolved. The only time this is not
+  the case is for extension-added functions added in a later revision of the
+  extension, and where we have to cope with drivers written against an older
+  revision.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsRequiredFunction"}}
+  {{AssertType $ "Function"}}
+
+  {{if eq $.Name "vkGetSwapchainGrallocUsage2ANDROID"}}
+    false
+  {{else}}
+    true
+  {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
   Emits true if a function is exported and instance-dispatched.
 ------------------------------------------------------------------------------
 */}}
@@ -490,9 +510,9 @@
 {{define "api.C++.DefineInitProcExtMacro"}}
   // Exported extension functions may be invoked even when their extensions
   // are disabled.  Dispatch to stubs when that happens.
-  #define INIT_PROC_EXT(ext, obj, proc) do {                    \
+  #define INIT_PROC_EXT(ext, required, obj, proc) do {          \
       if (extensions[driver::ProcHook::ext])                    \
-        INIT_PROC(obj, proc);                                   \
+        INIT_PROC(required, obj, proc);                         \
       else                                                      \
         data.dispatch.proc = disabled ## proc;                  \
   } while(0)
@@ -677,8 +697,11 @@
 VK_ANDROID_native_buffer
 VK_EXT_debug_report
 VK_KHR_android_surface
+VK_KHR_incremental_present
 VK_KHR_surface
 VK_KHR_swapchain
+VK_KHR_incremental_present
+VK_GOOGLE_display_timing
 {{end}}
 
 
@@ -792,9 +815,9 @@
 -------------------------------------------------------------------------------
 */}}
 {{define "driver.C++.DefineInitProcExtMacro"}}
-  #define INIT_PROC_EXT(ext, obj, proc) do {                    \
+  #define INIT_PROC_EXT(ext, required, obj, proc) do {          \
       if (extensions[ProcHook::ext])                            \
-        INIT_PROC(obj, proc);                                   \
+        INIT_PROC(required, obj, proc);                         \
   } while(0)
 {{end}}
 
@@ -1125,6 +1148,8 @@
   {{     if eq $ext "VK_KHR_surface"}}true
   {{else if eq $ext "VK_KHR_swapchain"}}true
   {{else if eq $ext "VK_KHR_android_surface"}}true
+  {{else if eq $ext "VK_KHR_incremental_present"}}true
+  {{else if eq $ext "VK_GOOGLE_display_timing"}}true
   {{end}}
 {{end}}
 
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 2555272..8b9b9d2 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -660,26 +660,49 @@
     uint32_t* pPropertyCount,
     VkExtensionProperties* pProperties) {
     const InstanceData& data = GetData(physicalDevice);
+    static const std::array<VkExtensionProperties, 1> loader_extensions = {{
+        // WSI extensions
+        {VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
+         VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION},
+    }};
+
+    // enumerate our extensions first
+    if (!pLayerName && pProperties) {
+        uint32_t count = std::min(
+            *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
+
+        std::copy_n(loader_extensions.begin(), count, pProperties);
+
+        if (count < loader_extensions.size()) {
+            *pPropertyCount = count;
+            return VK_INCOMPLETE;
+        }
+
+        pProperties += count;
+        *pPropertyCount -= count;
+    }
 
     VkResult result = data.driver.EnumerateDeviceExtensionProperties(
         physicalDevice, pLayerName, pPropertyCount, pProperties);
-    if (result != VK_SUCCESS && result != VK_INCOMPLETE)
-        return result;
 
-    if (!pProperties)
-        return result;
+    if (pProperties) {
+        // map VK_ANDROID_native_buffer to VK_KHR_swapchain
+        for (uint32_t i = 0; i < *pPropertyCount; i++) {
+            auto& prop = pProperties[i];
 
-    // map VK_ANDROID_native_buffer to VK_KHR_swapchain
-    for (uint32_t i = 0; i < *pPropertyCount; i++) {
-        auto& prop = pProperties[i];
+            if (strcmp(prop.extensionName,
+                       VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
+                continue;
 
-        if (strcmp(prop.extensionName,
-                   VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
-            continue;
+            memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
+                   sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
+            prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
+        }
+    }
 
-        memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
-               sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
-        prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
+    // restore loader extension count
+    if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE)) {
+        *pPropertyCount += loader_extensions.size();
     }
 
     return result;
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
index a1612c7..d74d9e9 100644
--- a/vulkan/libvulkan/driver.h
+++ b/vulkan/libvulkan/driver.h
@@ -18,9 +18,11 @@
 #define LIBVULKAN_DRIVER_H 1
 
 #include <inttypes.h>
+
 #include <bitset>
 #include <type_traits>
-#include <log/log.h>
+
+#include <android/log.h>
 
 #include <vulkan/vulkan.h>
 #include <hardware/hwvulkan.h>
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index d979a34..e27b3d1 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -18,7 +18,7 @@
 
 #include <string.h>
 #include <algorithm>
-#include <log/log.h>
+#include <android/log.h>
 
 #include "driver.h"
 
@@ -73,6 +73,24 @@
     }
 }
 
+VKAPI_ATTR VkResult checkedGetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
+    if (GetData(device).hook_extensions[ProcHook::GOOGLE_display_timing]) {
+        return GetRefreshCycleDurationGOOGLE(device, swapchain, pDisplayTimingProperties);
+    } else {
+        Logger(device).Err(device, "VK_GOOGLE_display_timing not enabled. vkGetRefreshCycleDurationGOOGLE not executed.");
+        return VK_SUCCESS;
+    }
+}
+
+VKAPI_ATTR VkResult checkedGetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings) {
+    if (GetData(device).hook_extensions[ProcHook::GOOGLE_display_timing]) {
+        return GetPastPresentationTimingGOOGLE(device, swapchain, pPresentationTimingCount, pPresentationTimings);
+    } else {
+        Logger(device).Err(device, "VK_GOOGLE_display_timing not enabled. vkGetPastPresentationTimingGOOGLE not executed.");
+        return VK_SUCCESS;
+    }
+}
+
 // clang-format on
 
 const ProcHook g_proc_hooks[] = {
@@ -218,6 +236,13 @@
         nullptr,
     },
     {
+        "vkGetPastPresentationTimingGOOGLE",
+        ProcHook::DEVICE,
+        ProcHook::GOOGLE_display_timing,
+        reinterpret_cast<PFN_vkVoidFunction>(GetPastPresentationTimingGOOGLE),
+        reinterpret_cast<PFN_vkVoidFunction>(checkedGetPastPresentationTimingGOOGLE),
+    },
+    {
         "vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
         ProcHook::INSTANCE,
         ProcHook::KHR_surface,
@@ -246,6 +271,20 @@
         nullptr,
     },
     {
+        "vkGetRefreshCycleDurationGOOGLE",
+        ProcHook::DEVICE,
+        ProcHook::GOOGLE_display_timing,
+        reinterpret_cast<PFN_vkVoidFunction>(GetRefreshCycleDurationGOOGLE),
+        reinterpret_cast<PFN_vkVoidFunction>(checkedGetRefreshCycleDurationGOOGLE),
+    },
+    {
+        "vkGetSwapchainGrallocUsage2ANDROID",
+        ProcHook::DEVICE,
+        ProcHook::ANDROID_native_buffer,
+        nullptr,
+        nullptr,
+    },
+    {
         "vkGetSwapchainGrallocUsageANDROID",
         ProcHook::DEVICE,
         ProcHook::ANDROID_native_buffer,
@@ -295,26 +334,27 @@
     if (strcmp(name, "VK_KHR_android_surface") == 0) return ProcHook::KHR_android_surface;
     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_GOOGLE_display_timing") == 0) return ProcHook::GOOGLE_display_timing;
     // clang-format on
     return ProcHook::EXTENSION_UNKNOWN;
 }
 
 #define UNLIKELY(expr) __builtin_expect((expr), 0)
 
-#define INIT_PROC(obj, proc)                                           \
+#define INIT_PROC(required, obj, proc)                                 \
     do {                                                               \
         data.driver.proc =                                             \
             reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \
-        if (UNLIKELY(!data.driver.proc)) {                             \
+        if (UNLIKELY(required && !data.driver.proc)) {                 \
             ALOGE("missing " #obj " proc: vk" #proc);                  \
             success = false;                                           \
         }                                                              \
     } while (0)
 
-#define INIT_PROC_EXT(ext, obj, proc)  \
-    do {                               \
-        if (extensions[ProcHook::ext]) \
-            INIT_PROC(obj, proc);      \
+#define INIT_PROC_EXT(ext, required, obj, proc) \
+    do {                                        \
+        if (extensions[ProcHook::ext])          \
+            INIT_PROC(required, obj, proc);     \
     } while (0)
 
 bool InitDriverTable(VkInstance instance,
@@ -324,14 +364,14 @@
     bool success = true;
 
     // clang-format off
-    INIT_PROC(instance, DestroyInstance);
-    INIT_PROC(instance, EnumeratePhysicalDevices);
-    INIT_PROC(instance, GetInstanceProcAddr);
-    INIT_PROC(instance, CreateDevice);
-    INIT_PROC(instance, EnumerateDeviceExtensionProperties);
-    INIT_PROC_EXT(EXT_debug_report, instance, CreateDebugReportCallbackEXT);
-    INIT_PROC_EXT(EXT_debug_report, instance, DestroyDebugReportCallbackEXT);
-    INIT_PROC_EXT(EXT_debug_report, instance, DebugReportMessageEXT);
+    INIT_PROC(true, instance, DestroyInstance);
+    INIT_PROC(true, instance, EnumeratePhysicalDevices);
+    INIT_PROC(true, instance, GetInstanceProcAddr);
+    INIT_PROC(true, instance, CreateDevice);
+    INIT_PROC(true, instance, EnumerateDeviceExtensionProperties);
+    INIT_PROC_EXT(EXT_debug_report, true, instance, CreateDebugReportCallbackEXT);
+    INIT_PROC_EXT(EXT_debug_report, true, instance, DestroyDebugReportCallbackEXT);
+    INIT_PROC_EXT(EXT_debug_report, true, instance, DebugReportMessageEXT);
     // clang-format on
 
     return success;
@@ -344,15 +384,16 @@
     bool success = true;
 
     // clang-format off
-    INIT_PROC(dev, GetDeviceProcAddr);
-    INIT_PROC(dev, DestroyDevice);
-    INIT_PROC(dev, GetDeviceQueue);
-    INIT_PROC(dev, CreateImage);
-    INIT_PROC(dev, DestroyImage);
-    INIT_PROC(dev, AllocateCommandBuffers);
-    INIT_PROC_EXT(ANDROID_native_buffer, dev, GetSwapchainGrallocUsageANDROID);
-    INIT_PROC_EXT(ANDROID_native_buffer, dev, AcquireImageANDROID);
-    INIT_PROC_EXT(ANDROID_native_buffer, dev, QueueSignalReleaseImageANDROID);
+    INIT_PROC(true, dev, GetDeviceProcAddr);
+    INIT_PROC(true, dev, DestroyDevice);
+    INIT_PROC(true, dev, GetDeviceQueue);
+    INIT_PROC(true, dev, CreateImage);
+    INIT_PROC(true, dev, DestroyImage);
+    INIT_PROC(true, dev, AllocateCommandBuffers);
+    INIT_PROC_EXT(ANDROID_native_buffer, true, dev, GetSwapchainGrallocUsageANDROID);
+    INIT_PROC_EXT(ANDROID_native_buffer, false, dev, GetSwapchainGrallocUsage2ANDROID);
+    INIT_PROC_EXT(ANDROID_native_buffer, true, dev, AcquireImageANDROID);
+    INIT_PROC_EXT(ANDROID_native_buffer, true, dev, QueueSignalReleaseImageANDROID);
     // clang-format on
 
     return success;
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index a60b2fe..167f88c 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -38,6 +38,7 @@
         KHR_android_surface,
         KHR_surface,
         KHR_swapchain,
+        GOOGLE_display_timing,
 
         EXTENSION_CORE,  // valid bit
         EXTENSION_COUNT,
@@ -74,6 +75,7 @@
     PFN_vkDestroyImage DestroyImage;
     PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
     PFN_vkGetSwapchainGrallocUsageANDROID GetSwapchainGrallocUsageANDROID;
+    PFN_vkGetSwapchainGrallocUsage2ANDROID GetSwapchainGrallocUsage2ANDROID;
     PFN_vkAcquireImageANDROID AcquireImageANDROID;
     PFN_vkQueueSignalReleaseImageANDROID QueueSignalReleaseImageANDROID;
     // clang-format on
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
index 8f35f4d..5f6d243 100644
--- a/vulkan/libvulkan/layers_extensions.cpp
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -19,16 +19,17 @@
 #include <alloca.h>
 #include <dirent.h>
 #include <dlfcn.h>
-#include <mutex>
-#include <sys/prctl.h>
-#include <string>
 #include <string.h>
+#include <sys/prctl.h>
+
+#include <mutex>
+#include <string>
 #include <vector>
 
-#include <android-base/strings.h>
+#include <android/log.h>
 #include <android/dlext.h>
+#include <android-base/strings.h>
 #include <cutils/properties.h>
-#include <log/log.h>
 #include <ziparchive/zip_archive.h>
 
 #include <vulkan/vulkan_loader_data.h>
diff --git a/vulkan/libvulkan/stubhal.cpp b/vulkan/libvulkan/stubhal.cpp
index 869317b..3de8970 100644
--- a/vulkan/libvulkan/stubhal.cpp
+++ b/vulkan/libvulkan/stubhal.cpp
@@ -29,8 +29,10 @@
 #include <array>
 #include <bitset>
 #include <mutex>
+
+#include <android/log.h>
 #include <hardware/hwvulkan.h>
-#include <log/log.h>
+
 #include "stubhal.h"
 
 namespace vulkan {
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 7e90503..807b81a 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -16,8 +16,8 @@
 
 #include <algorithm>
 
+#include <android/log.h>
 #include <gui/BufferQueue.h>
-#include <log/log.h>
 #include <sync/sync.h>
 #include <utils/StrongPointer.h>
 
@@ -122,10 +122,13 @@
 
 struct Swapchain {
     Swapchain(Surface& surface_, uint32_t num_images_)
-        : surface(surface_), num_images(num_images_) {}
+        : surface(surface_),
+          num_images(num_images_),
+          frame_timestamps_enabled(false) {}
 
     Surface& surface;
     uint32_t num_images;
+    bool frame_timestamps_enabled;
 
     struct Image {
         Image() : image(VK_NULL_HANDLE), dequeue_fence(-1), dequeued(false) {}
@@ -723,9 +726,14 @@
                          const VkAllocationCallbacks* allocator) {
     const auto& dispatch = GetData(device).driver;
     Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
+    if (!swapchain)
+        return;
     bool active = swapchain->surface.swapchain_handle == swapchain_handle;
     ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr;
 
+    if (swapchain->frame_timestamps_enabled) {
+        native_window_enable_frame_timestamps(window, false);
+    }
     for (uint32_t i = 0; i < swapchain->num_images; i++)
         ReleaseSwapchainImage(device, window, -1, swapchain->images[i]);
     if (active)
@@ -866,7 +874,8 @@
     VkResult final_result = VK_SUCCESS;
 
     // Look at the pNext chain for supported extension structs:
-    const VkPresentRegionsKHR* present_regions = NULL;
+    const VkPresentRegionsKHR* present_regions = nullptr;
+    const VkPresentTimesInfoGOOGLE* present_times = nullptr;
     const VkPresentRegionsKHR* next =
         reinterpret_cast<const VkPresentRegionsKHR*>(present_info->pNext);
     while (next) {
@@ -874,6 +883,10 @@
             case VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR:
                 present_regions = next;
                 break;
+            case VK_STRUCTURE_TYPE_PRESENT_TIMES_GOOGLE:
+                present_times =
+                    reinterpret_cast<const VkPresentTimesInfoGOOGLE*>(next);
+                break;
             default:
                 ALOGV("QueuePresentKHR ignoring unrecognized pNext->sType = %x",
                       next->sType);
@@ -885,10 +898,16 @@
         present_regions &&
             present_regions->swapchainCount != present_info->swapchainCount,
         "VkPresentRegions::swapchainCount != VkPresentInfo::swapchainCount");
+    ALOGV_IF(present_times &&
+                 present_times->swapchainCount != present_info->swapchainCount,
+             "VkPresentTimesInfoGOOGLE::swapchainCount != "
+             "VkPresentInfo::swapchainCount");
     const VkPresentRegionKHR* regions =
-        (present_regions) ? present_regions->pRegions : NULL;
+        (present_regions) ? present_regions->pRegions : nullptr;
+    const VkPresentTimeGOOGLE* times =
+        (present_times) ? present_times->pTimes : nullptr;
     const VkAllocationCallbacks* allocator = &GetData(device).allocator;
-    android_native_rect_t* rects = NULL;
+    android_native_rect_t* rects = nullptr;
     uint32_t nrects = 0;
 
     for (uint32_t sc = 0; sc < present_info->swapchainCount; sc++) {
@@ -896,7 +915,8 @@
             *SwapchainFromHandle(present_info->pSwapchains[sc]);
         uint32_t image_idx = present_info->pImageIndices[sc];
         Swapchain::Image& img = swapchain.images[image_idx];
-        const VkPresentRegionKHR* region = (regions) ? &regions[sc] : NULL;
+        const VkPresentRegionKHR* region = (regions) ? &regions[sc] : nullptr;
+        const VkPresentTimeGOOGLE* time = (times) ? &times[sc] : nullptr;
         VkResult swapchain_result = VK_SUCCESS;
         VkResult result;
         int err;
@@ -953,6 +973,19 @@
                     }
                     native_window_set_surface_damage(window, rects, rcount);
                 }
+                if (time) {
+                    if (!swapchain.frame_timestamps_enabled) {
+                        native_window_enable_frame_timestamps(window, true);
+                        swapchain.frame_timestamps_enabled = true;
+                    }
+                    // TODO(ianelliott): need to store the presentID (and
+                    // desiredPresentTime), so it can be later correlated to
+                    // this present.  Probably modify the following function
+                    // (and below) to plumb a path to store it in FrameEvents
+                    // code, on the producer side.
+                    native_window_set_buffers_timestamp(
+                        window, static_cast<int64_t>(time->desiredPresentTime));
+                }
                 err = window->queueBuffer(window, img.buffer.get(), fence);
                 // queueBuffer always closes fence, even on error
                 if (err != 0) {
@@ -990,5 +1023,44 @@
     return final_result;
 }
 
+VKAPI_ATTR
+VkResult GetRefreshCycleDurationGOOGLE(
+    VkDevice,
+    VkSwapchainKHR,
+    VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties) {
+    VkResult result = VK_SUCCESS;
+
+    // TODO(ianelliott): FULLY IMPLEMENT THIS FUNCTION!!!
+    pDisplayTimingProperties->minRefreshDuration = 16666666666;
+    pDisplayTimingProperties->maxRefreshDuration = 16666666666;
+
+    return result;
+}
+
+VKAPI_ATTR
+VkResult GetPastPresentationTimingGOOGLE(
+    VkDevice,
+    VkSwapchainKHR swapchain_handle,
+    uint32_t* count,
+    VkPastPresentationTimingGOOGLE* timings) {
+    Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
+    ANativeWindow* window = swapchain.surface.window.get();
+    VkResult result = VK_SUCCESS;
+
+    if (!swapchain.frame_timestamps_enabled) {
+        native_window_enable_frame_timestamps(window, true);
+        swapchain.frame_timestamps_enabled = true;
+    }
+
+    // TODO(ianelliott): FULLY IMPLEMENT THIS FUNCTION!!!
+    if (timings) {
+        *count = 0;
+    } else {
+        *count = 0;
+    }
+
+    return result;
+}
+
 }  // namespace driver
 }  // namespace vulkan
diff --git a/vulkan/libvulkan/swapchain.h b/vulkan/libvulkan/swapchain.h
index 2c60c49..8aac427 100644
--- a/vulkan/libvulkan/swapchain.h
+++ b/vulkan/libvulkan/swapchain.h
@@ -34,6 +34,8 @@
 VKAPI_ATTR VkResult GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain_handle, uint32_t* count, VkImage* images);
 VKAPI_ATTR VkResult AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain_handle, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* image_index);
 VKAPI_ATTR VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info);
+VKAPI_ATTR VkResult GetRefreshCycleDurationGOOGLE(VkDevice device, VkSwapchainKHR swapchain, VkRefreshCycleDurationGOOGLE* pDisplayTimingProperties);
+VKAPI_ATTR VkResult GetPastPresentationTimingGOOGLE(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pPresentationTimingCount, VkPastPresentationTimingGOOGLE* pPresentationTimings);
 // clang-format on
 
 }  // namespace driver
diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp
index 05ebcac..4a520ee 100644
--- a/vulkan/nulldrv/null_driver.cpp
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -16,13 +16,14 @@
 
 #include <hardware/hwvulkan.h>
 
-#include <algorithm>
-#include <array>
 #include <inttypes.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include <log/log.h>
+#include <algorithm>
+#include <array>
+
+#include <android/log.h>
 #include <utils/Errors.h>
 
 #include "null_driver_gen.h"
@@ -886,6 +887,16 @@
     return VK_SUCCESS;
 }
 
+VkResult GetSwapchainGrallocUsage2ANDROID(VkDevice,
+                                          VkFormat,
+                                          VkImageUsageFlags,
+                                          VkSwapchainImageUsageFlagsANDROID,
+                                          int* grallocUsage) {
+    // The null driver never reads or writes the gralloc buffer
+    *grallocUsage = 0;
+    return VK_SUCCESS;
+}
+
 VkResult AcquireImageANDROID(VkDevice,
                              VkImage,
                              int fence,
diff --git a/vulkan/nulldrv/null_driver_gen.cpp b/vulkan/nulldrv/null_driver_gen.cpp
index b078ad1..5ae31a2 100644
--- a/vulkan/nulldrv/null_driver_gen.cpp
+++ b/vulkan/nulldrv/null_driver_gen.cpp
@@ -180,6 +180,7 @@
     {"vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPipelineCacheData>(GetPipelineCacheData))},
     {"vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetQueryPoolResults>(GetQueryPoolResults))},
     {"vkGetRenderAreaGranularity", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetRenderAreaGranularity>(GetRenderAreaGranularity))},
+    {"vkGetSwapchainGrallocUsage2ANDROID", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetSwapchainGrallocUsage2ANDROID>(GetSwapchainGrallocUsage2ANDROID))},
     {"vkGetSwapchainGrallocUsageANDROID", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetSwapchainGrallocUsageANDROID>(GetSwapchainGrallocUsageANDROID))},
     {"vkInvalidateMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkInvalidateMappedMemoryRanges>(InvalidateMappedMemoryRanges))},
     {"vkMapMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkMapMemory>(MapMemory))},
diff --git a/vulkan/nulldrv/null_driver_gen.h b/vulkan/nulldrv/null_driver_gen.h
index 4052d26..25a4371 100644
--- a/vulkan/nulldrv/null_driver_gen.h
+++ b/vulkan/nulldrv/null_driver_gen.h
@@ -166,6 +166,7 @@
 VKAPI_ATTR void CmdEndRenderPass(VkCommandBuffer commandBuffer);
 VKAPI_ATTR void CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
 VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
+VKAPI_ATTR VkResult GetSwapchainGrallocUsage2ANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, VkSwapchainImageUsageFlagsANDROID swapchainImageUsage, 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);
 VKAPI_ATTR VkResult CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);
diff --git a/vulkan/tools/vkinfo.cpp b/vulkan/tools/vkinfo.cpp
index 7cf85e6..89bc926 100644
--- a/vulkan/tools/vkinfo.cpp
+++ b/vulkan/tools/vkinfo.cpp
@@ -14,18 +14,17 @@
  * limitations under the License.
  */
 
-#include <algorithm>
-#include <array>
 #include <inttypes.h>
 #include <stdlib.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <array>
 #include <sstream>
 #include <vector>
 
 #include <vulkan/vulkan.h>
 
-#define LOG_TAG "vkinfo"
-#include <log/log.h>
-
 namespace {
 
 struct Options {
@@ -177,7 +176,7 @@
         .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
         .queueFamilyIndex = 0,
         .queueCount = 1,
-        queue_priorities
+        .pQueuePriorities = queue_priorities
     };
     // clang-format off
     const char *kValidationLayers[] = {