Merge "Fixed incorrect usage of native fences" into pi-dev
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 3ec0163..cb6d0c6 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -82,6 +82,28 @@
     chmod 0666 /sys/kernel/debug/tracing/events/lowmemorykiller/enable
     chmod 0666 /sys/kernel/tracing/events/lowmemorykiller/enable
 
+    # disk
+    chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_enter/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter/enable
+    chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_exit/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit/enable
+    chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_begin/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin/enable
+    chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_end/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_end/enable
+    chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_begin/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable
+    chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_end/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable
+    chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_enter/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable
+    chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_exit/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable
+    chmod 0666 /sys/kernel/tracing/events/block/block_rq_issue/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_issue/enable
+    chmod 0666 /sys/kernel/tracing/events/block/block_rq_complete/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable
+
 # Tracing disabled by default
     write /sys/kernel/debug/tracing/tracing_on 0
     write /sys/kernel/tracing/tracing_on 0
diff --git a/cmds/atrace/atrace_userdebug.rc b/cmds/atrace/atrace_userdebug.rc
index 9d632cc..93a29ba 100644
--- a/cmds/atrace/atrace_userdebug.rc
+++ b/cmds/atrace/atrace_userdebug.rc
@@ -19,25 +19,3 @@
     chmod 0666 /sys/kernel/debug/tracing/events/irq/enable
     chmod 0666 /sys/kernel/tracing/events/ipi/enable
     chmod 0666 /sys/kernel/debug/tracing/events/ipi/enable
-
-    # disk
-    chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_enter/enable
-    chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_enter/enable
-    chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_sync_file_exit/enable
-    chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_sync_file_exit/enable
-    chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_begin/enable
-    chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_begin/enable
-    chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_write_end/enable
-    chmod 0666 /sys/kernel/debug/tracing/events/f2fs/f2fs_write_end/enable
-    chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_begin/enable
-    chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_begin/enable
-    chmod 0666 /sys/kernel/tracing/events/ext4/ext4_da_write_end/enable
-    chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_da_write_end/enable
-    chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_enter/enable
-    chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable
-    chmod 0666 /sys/kernel/tracing/events/ext4/ext4_sync_file_exit/enable
-    chmod 0666 /sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable
-    chmod 0666 /sys/kernel/tracing/events/block/block_rq_issue/enable
-    chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_issue/enable
-    chmod 0666 /sys/kernel/tracing/events/block/block_rq_complete/enable
-    chmod 0666 /sys/kernel/debug/tracing/events/block/block_rq_complete/enable
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 9648ede..80ef788 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -32,14 +32,20 @@
 #include <sys/time.h>
 #include <sys/wait.h>
 #include <unistd.h>
+
+#include <chrono>
+#include <functional>
+#include <future>
 #include <memory>
 #include <regex>
 #include <set>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include <android-base/file.h>
 #include <android-base/properties.h>
+#include <android-base/scopeguard.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
@@ -53,6 +59,7 @@
 #include <private/android_filesystem_config.h>
 #include <private/android_logger.h>
 #include <serviceutils/PriorityDumper.h>
+#include <utils/StrongPointer.h>
 #include "DumpstateInternal.h"
 #include "DumpstateSectionReporter.h"
 #include "DumpstateService.h"
@@ -1533,77 +1540,101 @@
     printf("== Board\n");
     printf("========================================================\n");
 
-    ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
-    if (dumpstate_device == nullptr) {
-        MYLOGE("No IDumpstateDevice implementation\n");
-        return;
-    }
-
     if (!IsZipping()) {
         MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
         return;
     }
 
-    std::string path[NUM_OF_DUMPS];
-    android::base::unique_fd fd[NUM_OF_DUMPS];
-    int numFds = 0;
-
+    std::vector<std::string> paths;
+    std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
     for (int i = 0; i < NUM_OF_DUMPS; i++) {
-        path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i];
-        MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str());
+        paths.emplace_back(kDumpstateBoardPath + kDumpstateBoardFiles[i]);
+        remover.emplace_back(android::base::make_scope_guard(std::bind(
+            [](std::string path) {
+                if (remove(path.c_str()) != 0 && errno != ENOENT) {
+                    MYLOGE("Could not remove(%s): %s\n", path.c_str(), strerror(errno));
+                }
+            },
+            paths[i])));
+    }
 
-        fd[i] = android::base::unique_fd(
-            TEMP_FAILURE_RETRY(open(path[i].c_str(),
-            O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
-            S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
-        if (fd[i] < 0) {
-            MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno));
-            return;
-        } else {
-            numFds++;
+    // Given that bugreport is required to diagnose failures, it's better to
+    // drop the result of IDumpstateDevice than to block the rest of bugreport
+    // for an arbitrary amount of time.
+    std::packaged_task<std::unique_ptr<ssize_t[]>()>
+        dumpstate_task([paths]() -> std::unique_ptr<ssize_t[]> {
+            ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
+            if (dumpstate_device == nullptr) {
+                MYLOGE("No IDumpstateDevice implementation\n");
+                return nullptr;
+            }
+
+            using ScopedNativeHandle =
+                std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
+            ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
+                                      [](native_handle_t* handle) {
+                                          native_handle_close(handle);
+                                          native_handle_delete(handle);
+                                      });
+            if (handle == nullptr) {
+                MYLOGE("Could not create native_handle\n");
+                return nullptr;
+            }
+
+            for (size_t i = 0; i < paths.size(); i++) {
+                MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
+
+                android::base::unique_fd fd(TEMP_FAILURE_RETRY(
+                    open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
+                         S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
+                if (fd < 0) {
+                    MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
+                    return nullptr;
+                }
+                handle.get()->data[i] = fd.release();
+            }
+
+            android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get());
+            if (!status.isOk()) {
+                MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
+                return nullptr;
+            }
+            auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
+            for (size_t i = 0; i < paths.size(); i++) {
+                struct stat s;
+                if (fstat(handle.get()->data[i], &s) == -1) {
+                    MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
+                           strerror(errno));
+                    file_sizes[i] = -1;
+                    continue;
+                }
+                file_sizes[i] = s.st_size;
+            }
+            return file_sizes;
+        });
+    auto result = dumpstate_task.get_future();
+    std::thread(std::move(dumpstate_task)).detach();
+    if (result.wait_for(10s) != std::future_status::ready) {
+        MYLOGE("dumpstateBoard timed out after 10s\n");
+        return;
+    }
+    std::unique_ptr<ssize_t[]> file_sizes = result.get();
+    if (file_sizes == nullptr) {
+        return;
+    }
+
+    for (size_t i = 0; i < paths.size(); i++) {
+        if (file_sizes[i] == -1) {
+            continue;
         }
-    }
-
-    native_handle_t *handle = native_handle_create(numFds, 0);
-    if (handle == nullptr) {
-        MYLOGE("Could not create native_handle\n");
-        return;
-    }
-
-    for (int i = 0; i < numFds; i++) {
-        handle->data[i] = fd[i].release();
-    }
-
-    // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call.
-    android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle);
-    if (!status.isOk()) {
-        MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
-        native_handle_close(handle);
-        native_handle_delete(handle);
-        return;
-    }
-
-    for (int i = 0; i < numFds; i++) {
-        struct stat s;
-        if (fstat(handle->data[i], &s) == -1) {
-            MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno);
-        } else if (s.st_size > 0) {
-            AddZipEntry(kDumpstateBoardFiles[i], path[i]);
-        } else {
+        if (file_sizes[i] == 0) {
             MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
+            continue;
         }
+        AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
     }
 
     printf("*** See dumpstate-board.txt entry ***\n");
-
-    native_handle_close(handle);
-    native_handle_delete(handle);
-
-    for (int i = 0; i < numFds; i++) {
-        if (remove(path[i].c_str()) != 0) {
-            MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno));
-        }
-    }
 }
 
 static void ShowUsageAndExit(int exitCode = 1) {
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index e53a223..833ffbf 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -22,6 +22,7 @@
 #include <errno.h>
 #include <fstream>
 #include <fts.h>
+#include <functional>
 #include <inttypes.h>
 #include <regex>
 #include <stdlib.h>
@@ -2412,27 +2413,25 @@
 
 // This kernel feature is experimental.
 // TODO: remove local definition once upstreamed
-#ifndef FS_IOC_SET_FSVERITY
-struct fsverity_set {
-    __u64 offset;
-    __u64 flags;
+#ifndef FS_IOC_ENABLE_VERITY
+
+#define FS_IOC_ENABLE_VERITY           _IO('f', 133)
+#define FS_IOC_SET_VERITY_MEASUREMENT  _IOW('f', 134, struct fsverity_measurement)
+
+#define FS_VERITY_ALG_SHA256           1
+
+struct fsverity_measurement {
+    __u16 digest_algorithm;
+    __u16 digest_size;
+    __u32 reserved1;
+    __u64 reserved2[3];
+    __u8 digest[];
 };
 
-struct fsverity_root_hash {
-    short root_hash_algorithm;
-    short flags;
-    __u8 reserved[4];
-    __u8 root_hash[64];
-};
-
-#define FS_IOC_MEASURE_FSVERITY        _IOW('f', 133, struct fsverity_root_hash)
-#define FS_IOC_SET_FSVERITY            _IOW('f', 134, struct fsverity_set)
-
-#define FSVERITY_FLAG_ENABLED          0x0001
 #endif
 
 binder::Status InstalldNativeService::installApkVerity(const std::string& filePath,
-        const ::android::base::unique_fd& verityInputAshmem) {
+        const ::android::base::unique_fd& verityInputAshmem, int32_t contentSize) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_PATH(filePath);
     std::lock_guard<std::recursive_mutex> lock(mLock);
@@ -2440,7 +2439,7 @@
     if (!android::base::GetBoolProperty(kPropApkVerityMode, false)) {
         return ok();
     }
-#if DEBUG
+#ifndef NDEBUG
     ASSERT_PAGE_SIZE_4K();
 #endif
     // TODO: also check fsverity support in the current file system if compiled with DEBUG.
@@ -2449,15 +2448,14 @@
         return error("FD is not an ashmem");
     }
 
-    // TODO(71871109): Validate filePath.
     // 1. Seek to the next page boundary beyond the end of the file.
     ::android::base::unique_fd wfd(open(filePath.c_str(), O_WRONLY));
     if (wfd.get() < 0) {
-        return error("Failed to open " + filePath + ": " + strerror(errno));
+        return error("Failed to open " + filePath);
     }
     struct stat st;
     if (fstat(wfd.get(), &st) < 0) {
-        return error("Failed to stat " + filePath + ": " + strerror(errno));
+        return error("Failed to stat " + filePath);
     }
     // fsverity starts from the block boundary.
     off_t padding = kVerityPageSize - st.st_size % kVerityPageSize;
@@ -2465,38 +2463,51 @@
         padding = 0;
     }
     if (lseek(wfd.get(), st.st_size + padding, SEEK_SET) < 0) {
-        return error("Failed to lseek " + filePath + ": " + strerror(errno));
+        return error("Failed to lseek " + filePath);
     }
 
-    // 2. Write everything in the ashmem to the file.
-    int size = ashmem_get_size_region(verityInputAshmem.get());
-    if (size < 0) {
-        return error("Failed to get ashmem size: " + std::to_string(size));
+    // 2. Write everything in the ashmem to the file.  Note that allocated
+    //    ashmem size is multiple of page size, which is different from the
+    //    actual content size.
+    int shmSize = ashmem_get_size_region(verityInputAshmem.get());
+    if (shmSize < 0) {
+        return error("Failed to get ashmem size: " + std::to_string(shmSize));
     }
-    void* data = mmap(NULL, size, PROT_READ, MAP_SHARED, verityInputAshmem.get(), 0);
-    if (data == MAP_FAILED) {
-        return error("Failed to mmap the ashmem: " + std::string(strerror(errno)));
+    if (contentSize < 0) {
+        return error("Invalid content size: " + std::to_string(contentSize));
     }
-    char* cursor = reinterpret_cast<char*>(data);
-    int remaining = size;
+    if (contentSize > shmSize) {
+        return error("Content size overflow: " + std::to_string(contentSize) + " > " +
+                     std::to_string(shmSize));
+    }
+    auto data = std::unique_ptr<void, std::function<void (void *)>>(
+        mmap(NULL, contentSize, PROT_READ, MAP_SHARED, verityInputAshmem.get(), 0),
+        [contentSize] (void* ptr) {
+          if (ptr != MAP_FAILED) {
+            munmap(ptr, contentSize);
+          }
+        });
+
+    if (data.get() == MAP_FAILED) {
+        return error("Failed to mmap the ashmem");
+    }
+    char* cursor = reinterpret_cast<char*>(data.get());
+    int remaining = contentSize;
     while (remaining > 0) {
         int ret = TEMP_FAILURE_RETRY(write(wfd.get(), cursor, remaining));
         if (ret < 0) {
-            munmap(data, size);
             return error("Failed to write to " + filePath + " (" + std::to_string(remaining) +
-                         + "/" + std::to_string(size) + "): " + strerror(errno));
+                         + "/" + std::to_string(contentSize) + ")");
         }
         cursor += ret;
         remaining -= ret;
     }
-    munmap(data, size);
+    wfd.reset();
 
-    // 3. Enable fsverity. Once it's done, the file becomes immutable.
-    struct fsverity_set config;
-    config.offset = st.st_size;
-    config.flags = FSVERITY_FLAG_ENABLED;
-    if (ioctl(wfd.get(), FS_IOC_SET_FSVERITY, &config) < 0) {
-        return error("Failed to enable fsverity on " + filePath + ": " + strerror(errno));
+    // 3. Enable fsverity (needs readonly fd. Once it's done, the file becomes immutable.
+    ::android::base::unique_fd rfd(open(filePath.c_str(), O_RDONLY));
+    if (ioctl(rfd.get(), FS_IOC_ENABLE_VERITY, nullptr) < 0) {
+        return error("Failed to enable fsverity on " + filePath);
     }
     return ok();
 }
@@ -2516,17 +2527,19 @@
                      std::to_string(expectedHash.size()));
     }
 
-    // TODO(71871109): Validate filePath.
     ::android::base::unique_fd fd(open(filePath.c_str(), O_RDONLY));
     if (fd.get() < 0) {
         return error("Failed to open " + filePath + ": " + strerror(errno));
     }
 
-    struct fsverity_root_hash config;
-    memset(&config, 0, sizeof(config));
-    config.root_hash_algorithm = 0;  // SHA256
-    memcpy(config.root_hash, expectedHash.data(), std::min(sizeof(config.root_hash), kSha256Size));
-    if (ioctl(fd.get(), FS_IOC_MEASURE_FSVERITY, &config) < 0) {
+    unsigned int buffer_size = sizeof(fsverity_measurement) + kSha256Size;
+    std::vector<char> buffer(buffer_size, 0);
+
+    fsverity_measurement* config = reinterpret_cast<fsverity_measurement*>(buffer.data());
+    config->digest_algorithm = FS_VERITY_ALG_SHA256;
+    config->digest_size = kSha256Size;
+    memcpy(config->digest, expectedHash.data(), kSha256Size);
+    if (ioctl(fd.get(), FS_IOC_SET_VERITY_MEASUREMENT, config) < 0) {
         // This includes an expected failure case with no FSVerity setup. It normally happens when
         // the apk does not contains the Merkle tree root hash.
         return error("Failed to measure fsverity on " + filePath + ": " + strerror(errno));
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 2a31967..cebd3f9 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -123,7 +123,7 @@
     binder::Status deleteOdex(const std::string& apkPath, const std::string& instructionSet,
             const std::unique_ptr<std::string>& outputPath);
     binder::Status installApkVerity(const std::string& filePath,
-            const ::android::base::unique_fd& verityInput);
+            const ::android::base::unique_fd& verityInput, int32_t contentSize);
     binder::Status assertFsverityRootHashMatches(const std::string& filePath,
             const std::vector<uint8_t>& expectedHash);
     binder::Status reconcileSecondaryDexFile(const std::string& dexPath,
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 0c364bd..91e20b7 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -85,7 +85,8 @@
             @utf8InCpp String outputPath);
     void deleteOdex(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
             @nullable @utf8InCpp String outputPath);
-    void installApkVerity(@utf8InCpp String filePath, in FileDescriptor verityInput);
+    void installApkVerity(@utf8InCpp String filePath, in FileDescriptor verityInput,
+            int contentSize);
     void assertFsverityRootHashMatches(@utf8InCpp String filePath, in byte[] expectedHash);
 
     boolean reconcileSecondaryDexFile(@utf8InCpp String dexPath, @utf8InCpp String pkgName,
diff --git a/libs/arect/include/android/rect.h b/libs/arect/include/android/rect.h
index 80741c0..b36728e 100644
--- a/libs/arect/include/android/rect.h
+++ b/libs/arect/include/android/rect.h
@@ -33,23 +33,26 @@
 #endif
 
 /**
- * {@link ARect} is a struct that represents a rectangular window area.
+ * Rectangular window area.
  *
- * It is used with {@link
- * ANativeActivityCallbacks::onContentRectChanged} event callback and
- * ANativeWindow_lock() function.
+ * This is the NDK equivalent of the android.graphics.Rect class in Java. It is
+ * used with {@link ANativeActivityCallbacks::onContentRectChanged} event
+ * callback and the ANativeWindow_lock() function.
+ *
+ * In a valid ARect, left <= right and top <= bottom. ARect with left=0, top=10,
+ * right=1, bottom=11 contains only one pixel at x=0, y=10.
  */
 typedef struct ARect {
 #ifdef __cplusplus
     typedef int32_t value_type;
 #endif
-    /** left position */
+    /// Minimum X coordinate of the rectangle.
     int32_t left;
-    /** top position */
+    /// Minimum Y coordinate of the rectangle.
     int32_t top;
-    /** left position */
+    /// Maximum X coordinate of the rectangle.
     int32_t right;
-    /** bottom position */
+    /// Maximum Y coordinate of the rectangle.
     int32_t bottom;
 } ARect;
 
diff --git a/libs/binder/ActivityManager.cpp b/libs/binder/ActivityManager.cpp
index 9adac26..2728f35 100644
--- a/libs/binder/ActivityManager.cpp
+++ b/libs/binder/ActivityManager.cpp
@@ -80,6 +80,15 @@
     }
 }
 
+bool ActivityManager::isUidActive(const uid_t uid, const String16& callingPackage)
+{
+    sp<IActivityManager> service = getService();
+    if (service != NULL) {
+        return service->isUidActive(uid, callingPackage);
+    }
+    return false;
+}
+
 status_t ActivityManager::linkToDeath(const sp<IBinder::DeathRecipient>& recipient) {
     sp<IActivityManager> service = getService();
     if (service != NULL) {
diff --git a/libs/binder/IActivityManager.cpp b/libs/binder/IActivityManager.cpp
index b7a5fd9..428db4d 100644
--- a/libs/binder/IActivityManager.cpp
+++ b/libs/binder/IActivityManager.cpp
@@ -78,6 +78,18 @@
          data.writeStrongBinder(IInterface::asBinder(observer));
          remote()->transact(UNREGISTER_UID_OBSERVER_TRANSACTION, data, &reply);
     }
+
+    virtual bool isUidActive(const uid_t uid, const String16& callingPackage)
+    {
+         Parcel data, reply;
+         data.writeInterfaceToken(IActivityManager::getInterfaceDescriptor());
+         data.writeInt32(uid);
+         data.writeString16(callingPackage);
+         remote()->transact(IS_UID_ACTIVE_TRANSACTION, data, &reply);
+         // fail on exception
+         if (reply.readExceptionCode() != 0) return false;
+         return reply.readInt32() == 1;
+    }
 };
 
 // ------------------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/ActivityManager.h b/libs/binder/include/binder/ActivityManager.h
index 397382f..3090cae 100644
--- a/libs/binder/include/binder/ActivityManager.h
+++ b/libs/binder/include/binder/ActivityManager.h
@@ -50,6 +50,7 @@
                              const int32_t cutpoint,
                              const String16& callingPackage);
     void unregisterUidObserver(const sp<IUidObserver>& observer);
+    bool isUidActive(const uid_t uid, const String16& callingPackage);
 
     status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient);
     status_t unlinkToDeath(const sp<IBinder::DeathRecipient>& recipient);
diff --git a/libs/binder/include/binder/IActivityManager.h b/libs/binder/include/binder/IActivityManager.h
index bac2a99..6607c0e 100644
--- a/libs/binder/include/binder/IActivityManager.h
+++ b/libs/binder/include/binder/IActivityManager.h
@@ -35,11 +35,13 @@
                                      const int32_t cutpoint,
                                      const String16& callingPackage) = 0;
     virtual void unregisterUidObserver(const sp<IUidObserver>& observer) = 0;
+    virtual bool isUidActive(const uid_t uid, const String16& callingPackage) = 0;
 
     enum {
         OPEN_CONTENT_URI_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
         REGISTER_UID_OBSERVER_TRANSACTION,
-        UNREGISTER_UID_OBSERVER_TRANSACTION
+        UNREGISTER_UID_OBSERVER_TRANSACTION,
+        IS_UID_ACTIVE_TRANSACTION
     };
 };
 
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 0244bb5..e22bc70 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -43,6 +43,8 @@
 
 namespace android {
 
+using ui::ColorMode;
+
 class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
 {
 public:
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 2e1c24b..6a1aebd 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -44,6 +44,8 @@
 
 namespace android {
 
+using ui::ColorMode;
+
 Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp)
       : mGraphicBufferProducer(bufferProducer),
         mCrop(Rect::EMPTY_RECT),
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 3cf49d6..bbf681e 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -43,6 +43,8 @@
 #include <private/gui/ComposerService.h>
 
 namespace android {
+
+using ui::ColorMode;
 // ---------------------------------------------------------------------------
 
 ANDROID_SINGLETON_STATIC_INSTANCE(ComposerService);
@@ -629,7 +631,7 @@
         int32_t ownerUid)
 {
     sp<SurfaceControl> sur;
-    status_t err = NO_ERROR;
+    status_t err = mStatus;
 
     if (mStatus == NO_ERROR) {
         sp<IBinder> handle;
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index afe9358..3591090 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -30,7 +30,7 @@
 #include <ui/FrameStats.h>
 #include <ui/PixelFormat.h>
 #include <ui/GraphicBuffer.h>
-#include <ui/GraphicsTypes.h>
+#include <ui/GraphicTypes.h>
 
 #include <vector>
 
@@ -161,10 +161,10 @@
     virtual status_t setActiveConfig(const sp<IBinder>& display, int id) = 0;
 
     virtual status_t getDisplayColorModes(const sp<IBinder>& display,
-            Vector<ColorMode>* outColorModes) = 0;
-    virtual ColorMode getActiveColorMode(const sp<IBinder>& display) = 0;
+            Vector<ui::ColorMode>* outColorModes) = 0;
+    virtual ui::ColorMode getActiveColorMode(const sp<IBinder>& display) = 0;
     virtual status_t setActiveColorMode(const sp<IBinder>& display,
-            ColorMode colorMode) = 0;
+            ui::ColorMode colorMode) = 0;
 
     /* Capture the specified screen. requires READ_FRAME_BUFFER permission
      * This function will fail if there is a secure window on screen.
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index b45ce4f..ffc22f6 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -29,7 +29,7 @@
 #include <utils/threads.h>
 
 #include <ui/FrameStats.h>
-#include <ui/GraphicsTypes.h>
+#include <ui/GraphicTypes.h>
 #include <ui/PixelFormat.h>
 
 #include <gui/CpuConsumer.h>
@@ -89,13 +89,14 @@
 
     // Gets the list of supported color modes for the given display
     static status_t getDisplayColorModes(const sp<IBinder>& display,
-            Vector<ColorMode>* outColorModes);
+            Vector<ui::ColorMode>* outColorModes);
 
     // Gets the active color mode for the given display
-    static ColorMode getActiveColorMode(const sp<IBinder>& display);
+    static ui::ColorMode getActiveColorMode(const sp<IBinder>& display);
 
     // Sets the active color mode for the given display
-    static status_t setActiveColorMode(const sp<IBinder>& display, ColorMode colorMode);
+    static status_t setActiveColorMode(const sp<IBinder>& display,
+            ui::ColorMode colorMode);
 
     /* Triggers screen on/off or low power mode and waits for it to complete */
     static void setDisplayPowerMode(const sp<IBinder>& display, int mode);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 66d5595..2c02ba6 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -42,6 +42,7 @@
 // retrieve wide-color and hdr settings from configstore
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
+using ui::ColorMode;
 
 using Transaction = SurfaceComposerClient::Transaction;
 
@@ -58,7 +59,6 @@
 
 class SurfaceTest : public ::testing::Test {
 protected:
-
     SurfaceTest() {
         ProcessState::self()->startThreadPool();
     }
@@ -93,6 +93,16 @@
     sp<SurfaceControl> mSurfaceControl;
 };
 
+TEST_F(SurfaceTest, CreateSurfaceReturnsErrorBadClient) {
+    mComposerClient->dispose();
+    ASSERT_EQ(NO_INIT, mComposerClient->initCheck());
+
+    sp<SurfaceControl> sc;
+    status_t err = mComposerClient->createSurfaceChecked(
+            String8("Test Surface"), 32, 32, PIXEL_FORMAT_RGBA_8888, &sc, 0);
+    ASSERT_EQ(NO_INIT, err);
+}
+
 TEST_F(SurfaceTest, QueuesToWindowComposerIsTrueWhenVisible) {
     sp<ANativeWindow> anw(mSurface);
     int result = -123;
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index a477bf2..cc67aca 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -41,9 +41,11 @@
     AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM           = 1,
 
     /**
+     * 32 bits per pixel, 8 bits per channel format where alpha values are
+     * ignored (always opaque).
      * Corresponding formats:
      *   Vulkan: VK_FORMAT_R8G8B8A8_UNORM
-     *   OpenGL ES: GL_RGBA8
+     *   OpenGL ES: GL_RGB8
      */
     AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM           = 2,
 
@@ -124,40 +126,49 @@
     AHARDWAREBUFFER_FORMAT_S8_UINT                  = 0x35,
 };
 
+/**
+ * Buffer usage flags, specifying how the buffer will be accessed.
+ */
 enum {
-    /* The buffer will never be read by the CPU */
+    /// The buffer will never be read by the CPU.
     AHARDWAREBUFFER_USAGE_CPU_READ_NEVER        = 0UL,
-    /* The buffer will sometimes be read by the CPU */
+    /// The buffer will sometimes be read by the CPU.
     AHARDWAREBUFFER_USAGE_CPU_READ_RARELY       = 2UL,
-    /* The buffer will often be read by the CPU */
+    /// The buffer will often be read by the CPU.
     AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN        = 3UL,
-    /* CPU read value mask */
+    /// CPU read value mask.
     AHARDWAREBUFFER_USAGE_CPU_READ_MASK         = 0xFUL,
 
-    /* The buffer will never be written by the CPU */
+    /// The buffer will never be written by the CPU.
     AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER       = 0UL << 4,
-    /* The buffer will sometimes be written to by the CPU */
+    /// The buffer will sometimes be written to by the CPU.
     AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY      = 2UL << 4,
-    /* The buffer will often be written to by the CPU */
+    /// The buffer will often be written to by the CPU.
     AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN       = 3UL << 4,
-    /* CPU write value mask */
+    /// CPU write value mask.
     AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK        = 0xFUL << 4,
 
-    /* The buffer will be read from by the GPU */
+    /// The buffer will be read from by the GPU as a texture.
     AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE      = 1UL << 8,
-    /* The buffer will be written to by the GPU */
+    /**
+     * The buffer will be written to by the GPU as a framebuffer attachment.
+     * Note that the name of this flag is somewhat misleading: it does not imply
+     * that the buffer contains a color format. A buffer with depth or stencil
+     * format that will be used as a framebuffer attachment should also have
+     * this flag.
+     */
     AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT       = 1UL << 9,
-    /* The buffer must not be used outside of a protected hardware path */
+    /// The buffer must not be used outside of a protected hardware path.
     AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT      = 1UL << 14,
-    /* The buffer will be read by a hardware video encoder */
+    /// The buffer will be read by a hardware video encoder.
     AHARDWAREBUFFER_USAGE_VIDEO_ENCODE           = 1UL << 16,
-    /* The buffer will be used for sensor direct data */
+    /// The buffer will be used for direct writes from sensors.
     AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA     = 1UL << 23,
-    /* The buffer will be used as a shader storage or uniform buffer object */
+    /// The buffer will be used as a shader storage or uniform buffer object.
     AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER        = 1UL << 24,
-    /* The buffer will be used as a cube map texture */
+    /// The buffer will be used as a cube map texture.
     AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP               = 1UL << 25,
-    /* The buffer contains a complete mipmap hierarchy */
+    /// The buffer contains a complete mipmap hierarchy.
     AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE        = 1UL << 26,
 
     AHARDWAREBUFFER_USAGE_VENDOR_0  = 1ULL << 28,
@@ -182,15 +193,19 @@
     AHARDWAREBUFFER_USAGE_VENDOR_19 = 1ULL << 63,
 };
 
+/**
+ * Buffer description. Used for allocating new buffers and querying parameters
+ * of existing ones.
+ */
 typedef struct AHardwareBuffer_Desc {
-    uint32_t    width;      // width in pixels
-    uint32_t    height;     // height in pixels
-    uint32_t    layers;     // number of images
-    uint32_t    format;     // One of AHARDWAREBUFFER_FORMAT_*
-    uint64_t    usage;      // Combination of AHARDWAREBUFFER_USAGE_*
-    uint32_t    stride;     // Stride in pixels, ignored for AHardwareBuffer_allocate()
-    uint32_t    rfu0;       // Initialize to zero, reserved for future use
-    uint64_t    rfu1;       // Initialize to zero, reserved for future use
+    uint32_t    width;      ///< Width in pixels.
+    uint32_t    height;     ///< Height in pixels.
+    uint32_t    layers;     ///< Number of images in an image array.
+    uint32_t    format;     ///< One of AHARDWAREBUFFER_FORMAT_*
+    uint64_t    usage;      ///< Combination of AHARDWAREBUFFER_USAGE_*
+    uint32_t    stride;     ///< Row stride in pixels, ignored for AHardwareBuffer_allocate()
+    uint32_t    rfu0;       ///< Initialize to zero, reserved for future use.
+    uint64_t    rfu1;       ///< Initialize to zero, reserved for future use.
 } AHardwareBuffer_Desc;
 
 typedef struct AHardwareBuffer AHardwareBuffer;
@@ -199,8 +214,8 @@
  * Allocates a buffer that backs an AHardwareBuffer using the passed
  * AHardwareBuffer_Desc.
  *
- * Returns NO_ERROR on success, or an error number of the allocation fails for
- * any reason.
+ * \return NO_ERROR on success, or an error number of the allocation fails for
+ * any reason. The returned buffer has a reference count of 1.
  */
 int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc,
         AHardwareBuffer** outBuffer);
@@ -223,7 +238,7 @@
 void AHardwareBuffer_describe(const AHardwareBuffer* buffer,
         AHardwareBuffer_Desc* outDesc);
 
-/*
+/**
  * Lock the AHardwareBuffer for reading or writing, depending on the usage flags
  * passed.  This call may block if the hardware needs to finish rendering or if
  * CPU caches need to be synchronized, or possibly for other implementation-
@@ -231,16 +246,16 @@
  * descriptor that will be signaled when the buffer is locked, otherwise the
  * caller will block until the buffer is available.
  *
- * If rect is not NULL, the caller promises to modify only data in the area
+ * If \a rect is not NULL, the caller promises to modify only data in the area
  * specified by rect. If rect is NULL, the caller may modify the contents of the
  * entire buffer.
  *
  * The content of the buffer outside of the specified rect is NOT modified
  * by this call.
  *
- * The buffer usage may only specify AHARDWAREBUFFER_USAGE_CPU_*. If set, then
- * outVirtualAddress is filled with the address of the buffer in virtual memory,
- * otherwise this function will fail.
+ * The \a usage parameter may only specify AHARDWAREBUFFER_USAGE_CPU_*. If set,
+ * then outVirtualAddress is filled with the address of the buffer in virtual
+ * memory.
  *
  * THREADING CONSIDERATIONS:
  *
@@ -252,38 +267,38 @@
  * may return an error or leave the buffer's content into an indeterminate
  * state.
  *
- * Returns NO_ERROR on success, BAD_VALUE if the buffer is NULL or if the usage
+ * \return NO_ERROR on success, BAD_VALUE if \a buffer is NULL or if the usage
  * flags are not a combination of AHARDWAREBUFFER_USAGE_CPU_*, or an error
  * number of the lock fails for any reason.
  */
 int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage,
         int32_t fence, const ARect* rect, void** outVirtualAddress);
 
-/*
+/**
  * Unlock the AHardwareBuffer; must be called after all changes to the buffer
  * are completed by the caller. If fence is not NULL then it will be set to a
  * file descriptor that is signaled when all pending work on the buffer is
  * completed. The caller is responsible for closing the fence when it is no
  * longer needed.
  *
- * Returns NO_ERROR on success, BAD_VALUE if the buffer is NULL, or an error
- * number of the lock fails for any reason.
+ * \return NO_ERROR on success, BAD_VALUE if \a buffer is NULL, or an error
+ * number if the unlock fails for any reason.
  */
 int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence);
 
-/*
+/**
  * Send the AHardwareBuffer to an AF_UNIX socket.
  *
- * Returns NO_ERROR on success, BAD_VALUE if the buffer is NULL, or an error
- * number of the lock fails for any reason.
+ * \return NO_ERROR on success, BAD_VALUE if \a buffer is NULL, or an error
+ * number if the operation fails for any reason.
  */
 int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, int socketFd);
 
-/*
+/**
  * Receive the AHardwareBuffer from an AF_UNIX socket.
  *
- * Returns NO_ERROR on success, BAD_VALUE if the buffer is NULL, or an error
- * number of the lock fails for any reason.
+ * \return NO_ERROR on success, BAD_VALUE if \a outBuffer is NULL, or an error
+ * number if the operation fails for any reason.
  */
 int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer);
 
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index f2d6f7a..d5e5e9d 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -85,23 +85,23 @@
  * A pointer can be obtained using {@link ANativeWindow_lock()}.
  */
 typedef struct ANativeWindow_Buffer {
-    // The number of pixels that are show horizontally.
+    /// The number of pixels that are shown horizontally.
     int32_t width;
 
-    // The number of pixels that are shown vertically.
+    /// The number of pixels that are shown vertically.
     int32_t height;
 
-    // The number of *pixels* that a line in the buffer takes in
-    // memory. This may be >= width.
+    /// The number of *pixels* that a line in the buffer takes in
+    /// memory. This may be >= width.
     int32_t stride;
 
-    // The format of the buffer. One of AHARDWAREBUFFER_FORMAT_*
+    /// The format of the buffer. One of AHARDWAREBUFFER_FORMAT_*
     int32_t format;
 
-    // The actual bits.
+    /// The actual bits.
     void* bits;
 
-    // Do not touch.
+    /// Do not touch.
     uint32_t reserved[6];
 } ANativeWindow_Buffer;
 
diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp
index d7e191d..58fed84 100644
--- a/libs/ui/DebugUtils.cpp
+++ b/libs/ui/DebugUtils.cpp
@@ -22,7 +22,7 @@
 #include <string>
 
 using android::base::StringPrintf;
-using android::ColorMode;
+using android::ui::ColorMode;
 
 std::string decodeStandard(android_dataspace dataspace) {
     const uint32_t dataspaceSelect = (dataspace & HAL_DATASPACE_STANDARD_MASK);
@@ -234,6 +234,33 @@
     return android::base::StringPrintf("Unknown color mode %d", colorMode);
 }
 
+std::string decodeColorTransform(android_color_transform colorTransform) {
+    switch (colorTransform) {
+        case HAL_COLOR_TRANSFORM_IDENTITY:
+            return std::string("Identity");
+
+        case HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX:
+            return std::string("Arbitrary matrix");
+
+        case HAL_COLOR_TRANSFORM_VALUE_INVERSE:
+            return std::string("Inverse value");
+
+        case HAL_COLOR_TRANSFORM_GRAYSCALE:
+            return std::string("Grayscale");
+
+        case HAL_COLOR_TRANSFORM_CORRECT_PROTANOPIA:
+            return std::string("Correct protanopia");
+
+        case HAL_COLOR_TRANSFORM_CORRECT_DEUTERANOPIA:
+            return std::string("Correct deuteranopia");
+
+        case HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA:
+            return std::string("Correct tritanopia");
+    }
+
+    return android::base::StringPrintf("Unknown color transform %d", colorTransform);
+}
+
 // Converts a PixelFormat to a human-readable string.  Max 11 chars.
 // (Could use a table of prefab String8 objects.)
 std::string decodePixelFormat(android::PixelFormat format) {
diff --git a/libs/ui/include/ui/DebugUtils.h b/libs/ui/include/ui/DebugUtils.h
index 3370107..5e5df43 100644
--- a/libs/ui/include/ui/DebugUtils.h
+++ b/libs/ui/include/ui/DebugUtils.h
@@ -16,7 +16,7 @@
 
 #pragma once
 
-#include <ui/GraphicsTypes.h>
+#include <ui/GraphicTypes.h>
 #include <ui/PixelFormat.h>
 
 #include <string>
@@ -29,6 +29,7 @@
 std::string decodeTransfer(android_dataspace dataspace);
 std::string decodeRange(android_dataspace dataspace);
 std::string dataspaceDetails(android_dataspace dataspace);
-std::string decodeColorMode(android::ColorMode colormode);
+std::string decodeColorMode(android::ui::ColorMode colormode);
+std::string decodeColorTransform(android_color_transform colorTransform);
 std::string decodePixelFormat(android::PixelFormat format);
 std::string to_string(const android::Rect& rect);
diff --git a/libs/ui/include/ui/GraphicsTypes.h b/libs/ui/include/ui/GraphicTypes.h
similarity index 85%
rename from libs/ui/include/ui/GraphicsTypes.h
rename to libs/ui/include/ui/GraphicTypes.h
index fa9a812..39893b2 100644
--- a/libs/ui/include/ui/GraphicsTypes.h
+++ b/libs/ui/include/ui/GraphicTypes.h
@@ -19,8 +19,12 @@
 #include <android/hardware/graphics/common/1.1/types.h>
 #include <system/graphics.h>
 
+// android::ui::* in this header file will alias different types as
+// the HIDL interface is updated.
 namespace android {
+namespace ui {
 
 using android::hardware::graphics::common::V1_0::ColorMode;
 
+}  // namespace ui
 }  // namespace android
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index 3ce5c9f..660a200 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -769,9 +769,14 @@
 
   auto s3 = p->CreateConsumer();
   EXPECT_FALSE(s3);
+  // Note that here the expected error code is EOPNOTSUPP as the socket towards
+  // ProducerChannel has been teared down.
   EXPECT_EQ(s3.error(), EOPNOTSUPP);
 
   s3 = c->CreateConsumer();
   EXPECT_FALSE(s3);
-  EXPECT_EQ(s3.error(), EOPNOTSUPP);
+  // Note that here the expected error code is EPIPE returned from
+  // ConsumerChannel::HandleMessage as the socket is still open but the producer
+  // is gone.
+  EXPECT_EQ(s3.error(), EPIPE);
 }
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index b453d19..f3a9ad8 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -94,6 +94,7 @@
 char const * const gExtensionString  =
         "EGL_KHR_image "                        // mandatory
         "EGL_KHR_image_base "                   // mandatory
+        "EGL_KHR_image_gl_colorspace "
         "EGL_KHR_image_pixmap "
         "EGL_KHR_lock_surface "
         "EGL_KHR_gl_colorspace "
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index c3f4f58..9a449fa 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -105,6 +105,36 @@
     return value ? "true" : "false";
 }
 
+static std::string motionActionToString(int32_t action) {
+    // Convert MotionEvent action to string
+    switch(action & AMOTION_EVENT_ACTION_MASK) {
+        case AMOTION_EVENT_ACTION_DOWN:
+            return "DOWN";
+        case AMOTION_EVENT_ACTION_MOVE:
+            return "MOVE";
+        case AMOTION_EVENT_ACTION_UP:
+            return "UP";
+        case AMOTION_EVENT_ACTION_POINTER_DOWN:
+            return "POINTER_DOWN";
+        case AMOTION_EVENT_ACTION_POINTER_UP:
+            return "POINTER_UP";
+    }
+    return StringPrintf("%" PRId32, action);
+}
+
+static std::string keyActionToString(int32_t action) {
+    // Convert KeyEvent action to string
+    switch(action) {
+        case AKEY_EVENT_ACTION_DOWN:
+            return "DOWN";
+        case AKEY_EVENT_ACTION_UP:
+            return "UP";
+        case AKEY_EVENT_ACTION_MULTIPLE:
+            return "MULTIPLE";
+    }
+    return StringPrintf("%" PRId32, action);
+}
+
 static inline int32_t getMotionEventActionPointerIndex(int32_t action) {
     return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK)
             >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
@@ -3976,11 +4006,11 @@
 }
 
 void InputDispatcher::KeyEntry::appendDescription(std::string& msg) const {
-    msg += StringPrintf("KeyEvent(deviceId=%d, source=0x%08x, action=%d, "
+    msg += StringPrintf("KeyEvent(deviceId=%d, source=0x%08x, action=%s, "
             "flags=0x%08x, keyCode=%d, scanCode=%d, metaState=0x%08x, "
             "repeatCount=%d), policyFlags=0x%08x",
-            deviceId, source, action, flags, keyCode, scanCode, metaState,
-            repeatCount, policyFlags);
+            deviceId, source, keyActionToString(action).c_str(), flags, keyCode,
+            scanCode, metaState, repeatCount, policyFlags);
 }
 
 void InputDispatcher::KeyEntry::recycle() {
@@ -4021,11 +4051,11 @@
 }
 
 void InputDispatcher::MotionEntry::appendDescription(std::string& msg) const {
-    msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, action=%d, actionButton=0x%08x, "
+    msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, action=%s, actionButton=0x%08x, "
             "flags=0x%08x, metaState=0x%08x, buttonState=0x%08x, "
             "edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, displayId=%d, pointers=[",
-            deviceId, source, action, actionButton, flags, metaState, buttonState, edgeFlags,
-            xPrecision, yPrecision, displayId);
+            deviceId, source, motionActionToString(action).c_str(), actionButton, flags, metaState,
+            buttonState, edgeFlags, xPrecision, yPrecision, displayId);
     for (uint32_t i = 0; i < pointerCount; i++) {
         if (i) {
             msg += ", ";
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 2bd0a19..8e9e7fd 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -86,6 +86,7 @@
 SensorService::SensorService()
     : mInitCheck(NO_INIT), mSocketBufferSize(SOCKET_BUFFER_SIZE_NON_BATCHED),
       mWakeLockAcquired(false) {
+    mUidPolicy = new UidPolicy(this);
 }
 
 bool SensorService::initializeHmacKey() {
@@ -283,7 +284,6 @@
             enableSchedFifoMode();
 
             // Start watching UID changes to apply policy.
-            mUidPolicy = new UidPolicy(this);
             mUidPolicy->registerSelf();
         }
     }
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index ba28eb5..ff994f5 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -105,6 +105,7 @@
         "Layer.cpp",
         "LayerProtoHelper.cpp",
         "LayerRejecter.cpp",
+        "LayerStats.cpp",
         "LayerVector.cpp",
         "MessageQueue.cpp",
         "MonitoredProducer.cpp",
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index fe0b30b..8281ce0 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -49,13 +49,12 @@
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <configstore/Utils.h>
 
-// ----------------------------------------------------------------------------
-using namespace android;
-// ----------------------------------------------------------------------------
+namespace android {
 
 // retrieve triple buffer setting from configstore
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
+using android::ui::ColorMode;
 
 /*
  * Initialize the display to the specified values.
@@ -98,6 +97,7 @@
       mPowerMode(initialPowerMode),
       mActiveConfig(0),
       mActiveColorMode(ColorMode::NATIVE),
+      mColorTransform(HAL_COLOR_TRANSFORM_IDENTITY),
       mDisplayHasWideColor(supportWideColor),
       mDisplayHasHdr(supportHdr)
 {
@@ -268,6 +268,16 @@
     return mActiveColorMode;
 }
 
+void DisplayDevice::setColorTransform(const mat4& transform) {
+    const bool isIdentity = (transform == mat4());
+    mColorTransform =
+            isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY : HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX;
+}
+
+android_color_transform_t DisplayDevice::getColorTransform() const {
+    return mColorTransform;
+}
+
 void DisplayDevice::setCompositionDataSpace(android_dataspace dataspace) {
     ANativeWindow* const window = mNativeWindow.get();
     native_window_set_buffers_data_space(window, dataspace);
@@ -454,7 +464,11 @@
                         tr[0][1], tr[1][1], tr[2][1], tr[0][2], tr[1][2], tr[2][2]);
     auto const surface = static_cast<Surface*>(window);
     android_dataspace dataspace = surface->getBuffersDataSpace();
-    result.appendFormat("   dataspace: %s (%d)\n", dataspaceDetails(dataspace).c_str(), dataspace);
+    result.appendFormat("   wideColor=%d, hdr=%d, colorMode=%s, dataspace: %s (%d)\n",
+                        mDisplayHasWideColor, mDisplayHasHdr,
+                        decodeColorMode(mActiveColorMode).c_str(),
+                        dataspaceDetails(dataspace).c_str(), dataspace);
+
 
     String8 surfaceDump;
     mDisplaySurface->dumpAsString(surfaceDump);
@@ -474,3 +488,5 @@
     viewport.makeInvalid();
     frame.makeInvalid();
 }
+
+}  // namespace android
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index fbb0d46..31bb4d0 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -21,6 +21,8 @@
 
 #include <stdlib.h>
 
+#include <math/mat4.h>
+
 #include <ui/Region.h>
 
 #include <binder/IBinder.h>
@@ -31,7 +33,7 @@
 
 #include <gui/ISurfaceComposer.h>
 #include <hardware/hwcomposer_defs.h>
-#include <ui/GraphicsTypes.h>
+#include <ui/GraphicTypes.h>
 #include "RenderArea.h"
 #include "RenderEngine/Surface.h"
 
@@ -161,8 +163,10 @@
     void setPowerMode(int mode);
     bool isDisplayOn() const;
 
-    ColorMode getActiveColorMode() const;
-    void setActiveColorMode(ColorMode mode);
+    ui::ColorMode getActiveColorMode() const;
+    void setActiveColorMode(ui::ColorMode mode);
+    android_color_transform_t getColorTransform() const;
+    void setColorTransform(const mat4& transform);
     void setCompositionDataSpace(android_dataspace dataspace);
 
     /* ------------------------------------------------------------------------
@@ -236,7 +240,9 @@
     // Current active config
     int mActiveConfig;
     // current active color mode
-    ColorMode mActiveColorMode;
+    ui::ColorMode mActiveColorMode;
+    // Current color transform
+    android_color_transform_t mColorTransform;
 
     // Need to know if display is wide-color capable or not.
     // Initialized by SurfaceFlinger when the DisplayDevice is created.
@@ -285,7 +291,7 @@
     bool needsFiltering() const override { return mDevice->needsFiltering(); }
     Rect getSourceCrop() const override { return mSourceCrop; }
     bool getWideColorSupport() const override { return mDevice->getWideColorSupport(); }
-    ColorMode getActiveColorMode() const override {
+    ui::ColorMode getActiveColorMode() const override {
         return mDevice->getActiveColorMode();
     }
 
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 4faba3b..9398bde 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -177,9 +177,9 @@
 
 void FramebufferSurface::dumpAsString(String8& result) const {
     Mutex::Autolock lock(mMutex);
-    result.appendFormat("FramebufferSurface: dataspace: %s(%d)\n",
+    result.appendFormat("  FramebufferSurface: dataspace: %s(%d)\n",
                         dataspaceDetails(mDataSpace).c_str(), mDataSpace);
-    ConsumerBase::dumpLocked(result, "");
+    ConsumerBase::dumpLocked(result, "   ");
 }
 
 void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 0c77aba..c2425ce 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -362,21 +362,10 @@
     return Error::None;
 }
 
-Error Display::getColorModes(std::vector<android::ColorMode>* outModes) const
+Error Display::getColorModes(std::vector<android::ui::ColorMode>* outModes) const
 {
-    std::vector<android::ColorMode> modes;
-    auto intError = mComposer.getColorModes(mId, &modes);
-    uint32_t numModes = modes.size();
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        return error;
-    }
-
-    outModes->resize(numModes);
-    for (size_t i = 0; i < numModes; i++) {
-        (*outModes)[i] = modes[i];
-    }
-    return Error::None;
+    auto intError = mComposer.getColorModes(mId, outModes);
+    return static_cast<Error>(intError);
 }
 
 std::vector<std::shared_ptr<const Display::Config>> Display::getConfigs() const
@@ -537,7 +526,7 @@
     return static_cast<Error>(intError);
 }
 
-Error Display::setColorMode(android::ColorMode mode)
+Error Display::setColorMode(android::ui::ColorMode mode)
 {
     auto intError = mComposer.setColorMode(mId, mode);
     return static_cast<Error>(intError);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 5b53b54..71c094a 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -25,7 +25,7 @@
 
 #include <gui/HdrMetadata.h>
 #include <math/mat4.h>
-#include <ui/GraphicsTypes.h>
+#include <ui/GraphicTypes.h>
 #include <ui/HdrCapabilities.h>
 
 #include <utils/Log.h>
@@ -211,7 +211,7 @@
     [[clang::warn_unused_result]] Error getChangedCompositionTypes(
             std::unordered_map<Layer*, Composition>* outTypes);
     [[clang::warn_unused_result]] Error getColorModes(
-            std::vector<android::ColorMode>* outModes) const;
+            std::vector<android::ui::ColorMode>* outModes) const;
 
     // Doesn't call into the HWC2 device, so no errors are possible
     std::vector<std::shared_ptr<const Config>> getConfigs() const;
@@ -235,7 +235,8 @@
             uint32_t slot, const android::sp<android::GraphicBuffer>& target,
             const android::sp<android::Fence>& acquireFence,
             android_dataspace_t dataspace);
-    [[clang::warn_unused_result]] Error setColorMode(android::ColorMode mode);
+    [[clang::warn_unused_result]] Error setColorMode(
+            android::ui::ColorMode mode);
     [[clang::warn_unused_result]] Error setColorTransform(
             const android::mat4& matrix, android_color_transform_t hint);
     [[clang::warn_unused_result]] Error setOutputBuffer(
@@ -246,8 +247,8 @@
     [[clang::warn_unused_result]] Error validate(uint32_t* outNumTypes,
             uint32_t* outNumRequests);
     [[clang::warn_unused_result]] Error presentOrValidate(uint32_t* outNumTypes,
-                                                 uint32_t* outNumRequests,
-                                                          android::sp<android::Fence>* outPresentFence, uint32_t* state);
+            uint32_t* outNumRequests,
+            android::sp<android::Fence>* outPresentFence, uint32_t* state);
 
     // Other Display methods
 
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 6d5917d..6bf2ee9 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -311,8 +311,8 @@
     return config;
 }
 
-std::vector<ColorMode> HWComposer::getColorModes(int32_t displayId) const {
-    std::vector<ColorMode> modes;
+std::vector<ui::ColorMode> HWComposer::getColorModes(int32_t displayId) const {
+    std::vector<ui::ColorMode> modes;
 
     if (!isValidDisplay(displayId)) {
         ALOGE("getColorModes: Attempted to access invalid display %d",
@@ -324,13 +324,13 @@
     if (error != HWC2::Error::None) {
         ALOGE("getColorModes failed for display %d: %s (%d)", displayId,
                 to_string(error).c_str(), static_cast<int32_t>(error));
-        return std::vector<ColorMode>();
+        return std::vector<ui::ColorMode>();
     }
 
     return modes;
 }
 
-status_t HWComposer::setActiveColorMode(int32_t displayId, ColorMode mode) {
+status_t HWComposer::setActiveColorMode(int32_t displayId, ui::ColorMode mode) {
     if (!isValidDisplay(displayId)) {
         ALOGE("setActiveColorMode: Display %d is not valid", displayId);
         return BAD_INDEX;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index c442b2f..0366a0d 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -23,7 +23,7 @@
 #include <sys/types.h>
 
 #include <ui/Fence.h>
-#include <ui/GraphicsTypes.h>
+#include <ui/GraphicTypes.h>
 
 #include <utils/BitSet.h>
 #include <utils/Condition.h>
@@ -159,9 +159,9 @@
     std::shared_ptr<const HWC2::Display::Config>
             getActiveConfig(int32_t displayId) const;
 
-    std::vector<ColorMode> getColorModes(int32_t displayId) const;
+    std::vector<ui::ColorMode> getColorModes(int32_t displayId) const;
 
-    status_t setActiveColorMode(int32_t displayId, ColorMode mode);
+    status_t setActiveColorMode(int32_t displayId, ui::ColorMode mode);
 
     bool isUsingVrComposer() const;
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2499a98..5c945ed 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -42,6 +42,7 @@
 #include <gui/LayerDebugInfo.h>
 #include <gui/Surface.h>
 
+#include "BufferLayer.h"
 #include "Colorizer.h"
 #include "DisplayDevice.h"
 #include "Layer.h"
@@ -628,19 +629,14 @@
         transform = Transform(invTransform) * tr * bufferOrientation;
     }
 
-    // STOPSHIP (b/72106793): If we have less than 25% scaling, HWC usually needs to use the rotator
-    // to handle it. However, there is one guaranteed frame of jank when we switch to using the
-    // rotator. In the meantime, we force GL composition instead until we have a better fix for the
-    // HWC issue.
-    bool extremeScaling = abs(t[0][0]) <= 0.25 || abs(t[1][1]) <= 0.25;
-
     // this gives us only the "orientation" component of the transform
     const uint32_t orientation = transform.getOrientation();
-    if (orientation & Transform::ROT_INVALID || extremeScaling) {
+    if (orientation & Transform::ROT_INVALID) {
         // we can only handle simple transformation
         hwcInfo.forceClientComposition = true;
     } else {
         auto transform = static_cast<HWC2::Transform>(orientation);
+        hwcInfo.transform = transform;
         auto error = hwcLayer->setTransform(transform);
         ALOGE_IF(error != HWC2::Error::None,
                  "[%s] Failed to set transform %s: "
@@ -1494,7 +1490,11 @@
 
     const Layer::State& layerState(getDrawingState());
     const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(hwcId);
-    result.appendFormat("  %10d | ", layerState.z);
+    if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) {
+        result.appendFormat("  rel %6d | ", layerState.z);
+    } else {
+        result.appendFormat("  %10d | ", layerState.z);
+    }
     result.appendFormat("%10s | ", to_string(getCompositionType(hwcId)).c_str());
     const Rect& frame = hwcInfo.displayFrame;
     result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom);
@@ -1925,6 +1925,31 @@
     layerInfo->set_app_id(state.appId);
 }
 
+void Layer::writeToProto(LayerProto* layerInfo, int32_t hwcId) {
+    writeToProto(layerInfo, LayerVector::StateSet::Drawing);
+
+    const auto& hwcInfo = getBE().mHwcLayers.at(hwcId);
+
+    const Rect& frame = hwcInfo.displayFrame;
+    LayerProtoHelper::writeToProto(frame, layerInfo->mutable_hwc_frame());
+
+    const FloatRect& crop = hwcInfo.sourceCrop;
+    LayerProtoHelper::writeToProto(crop, layerInfo->mutable_hwc_crop());
+
+    const int32_t transform = static_cast<int32_t>(hwcInfo.transform);
+    layerInfo->set_hwc_transform(transform);
+
+    const int32_t compositionType = static_cast<int32_t>(hwcInfo.compositionType);
+    layerInfo->set_hwc_composition_type(compositionType);
+
+    if (std::strcmp(getTypeId(), "BufferLayer") == 0 &&
+        static_cast<BufferLayer*>(this)->isProtected()) {
+        layerInfo->set_is_protected(true);
+    } else {
+        layerInfo->set_is_protected(false);
+    }
+}
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 9a9b5e6..69ffb20 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -113,7 +113,8 @@
                 layer(nullptr),
                 forceClientComposition(false),
                 compositionType(HWC2::Composition::Invalid),
-                clearClientTarget(false) {}
+                clearClientTarget(false),
+                transform(HWC2::Transform::None) {}
 
         HWComposer* hwc;
         HWC2::Layer* layer;
@@ -123,6 +124,7 @@
         Rect displayFrame;
         FloatRect sourceCrop;
         HWComposerBufferCache bufferCache;
+        HWC2::Transform transform;
     };
 
     // A layer can be attached to multiple displays when operating in mirror mode
@@ -357,6 +359,8 @@
     void writeToProto(LayerProto* layerInfo,
                       LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
 
+    void writeToProto(LayerProto* layerInfo, int32_t hwcId);
+
 protected:
     /*
      * onDraw - draws the surface.
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
index 6a33148..cc39550 100644
--- a/services/surfaceflinger/LayerProtoHelper.cpp
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -37,6 +37,13 @@
     rectProto->set_right(rect.right);
 }
 
+void LayerProtoHelper::writeToProto(const FloatRect& rect, FloatRectProto* rectProto) {
+    rectProto->set_left(rect.left);
+    rectProto->set_top(rect.top);
+    rectProto->set_bottom(rect.bottom);
+    rectProto->set_right(rect.right);
+}
+
 void LayerProtoHelper::writeToProto(const half4 color, ColorProto* colorProto) {
     colorProto->set_r(color.r);
     colorProto->set_g(color.g);
diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h
index 45a0b5d..860da63 100644
--- a/services/surfaceflinger/LayerProtoHelper.h
+++ b/services/surfaceflinger/LayerProtoHelper.h
@@ -29,6 +29,7 @@
 class LayerProtoHelper {
 public:
     static void writeToProto(const Rect& rect, RectProto* rectProto);
+    static void writeToProto(const FloatRect& rect, FloatRectProto* rectProto);
     static void writeToProto(const Region& region, RegionProto* regionProto);
     static void writeToProto(const half4 color, ColorProto* colorProto);
     static void writeToProto(const Transform& transform, TransformProto* transformProto);
@@ -36,4 +37,4 @@
 };
 
 } // namespace surfaceflinger
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/LayerStats.cpp b/services/surfaceflinger/LayerStats.cpp
new file mode 100644
index 0000000..38ea6ed
--- /dev/null
+++ b/services/surfaceflinger/LayerStats.cpp
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#undef LOG_TAG
+#define LOG_TAG "LayerStats"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "LayerStats.h"
+#include "DisplayHardware/HWComposer.h"
+#include "ui/DebugUtils.h"
+
+#include <android-base/stringprintf.h>
+#include <log/log.h>
+#include <utils/String8.h>
+#include <utils/Trace.h>
+
+namespace android {
+
+void LayerStats::enable() {
+    ATRACE_CALL();
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mEnabled) return;
+    mLayerShapeStatsMap.clear();
+    mEnabled = true;
+    ALOGD("Logging enabled");
+}
+
+void LayerStats::disable() {
+    ATRACE_CALL();
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (!mEnabled) return;
+    mEnabled = false;
+    ALOGD("Logging disabled");
+}
+
+void LayerStats::clear() {
+    ATRACE_CALL();
+    std::lock_guard<std::mutex> lock(mMutex);
+    mLayerShapeStatsMap.clear();
+    ALOGD("Cleared current layer stats");
+}
+
+bool LayerStats::isEnabled() {
+    return mEnabled;
+}
+
+void LayerStats::traverseLayerTreeStatsLocked(
+        std::vector<std::unique_ptr<LayerProtoParser::Layer>> layerTree,
+        const LayerProtoParser::LayerGlobal* layerGlobal, std::vector<std::string>& layerShapeVec) {
+    for (std::unique_ptr<LayerProtoParser::Layer>& layer : layerTree) {
+        if (!layer) continue;
+        traverseLayerTreeStatsLocked(std::move(layer->children), layerGlobal, layerShapeVec);
+        std::string key = "";
+        base::StringAppendF(&key, ",%s", layer->type.c_str());
+        base::StringAppendF(&key, ",%s", layerCompositionType(layer->hwcCompositionType));
+        base::StringAppendF(&key, ",%d", layer->isProtected);
+        base::StringAppendF(&key, ",%s", layerTransform(layer->hwcTransform));
+        base::StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format));
+        base::StringAppendF(&key, ",%s", layer->dataspace.c_str());
+        base::StringAppendF(&key, ",%s",
+                            destinationLocation(layer->hwcFrame.left, layerGlobal->resolution[0],
+                                                true));
+        base::StringAppendF(&key, ",%s",
+                            destinationLocation(layer->hwcFrame.top, layerGlobal->resolution[1],
+                                                false));
+        base::StringAppendF(&key, ",%s",
+                            destinationSize(layer->hwcFrame.right - layer->hwcFrame.left,
+                                            layerGlobal->resolution[0], true));
+        base::StringAppendF(&key, ",%s",
+                            destinationSize(layer->hwcFrame.bottom - layer->hwcFrame.top,
+                                            layerGlobal->resolution[1], false));
+        base::StringAppendF(&key, ",%s", scaleRatioWH(layer.get()).c_str());
+        base::StringAppendF(&key, ",%s", alpha(static_cast<float>(layer->color.a)));
+
+        layerShapeVec.push_back(key);
+        ALOGV("%s", key.c_str());
+    }
+}
+
+void LayerStats::logLayerStats(const LayersProto& layersProto) {
+    ATRACE_CALL();
+    ALOGV("Logging");
+    auto layerGlobal = LayerProtoParser::generateLayerGlobalInfo(layersProto);
+    auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
+    std::vector<std::string> layerShapeVec;
+
+    std::lock_guard<std::mutex> lock(mMutex);
+    traverseLayerTreeStatsLocked(std::move(layerTree), &layerGlobal, layerShapeVec);
+
+    std::string layerShapeKey =
+            base::StringPrintf("%d,%s,%s,%s", static_cast<int32_t>(layerShapeVec.size()),
+                               layerGlobal.colorMode.c_str(), layerGlobal.colorTransform.c_str(),
+                               layerTransform(layerGlobal.globalTransform));
+    ALOGV("%s", layerShapeKey.c_str());
+
+    std::sort(layerShapeVec.begin(), layerShapeVec.end(), std::greater<std::string>());
+    for (auto const& s : layerShapeVec) {
+        layerShapeKey += s;
+    }
+
+    mLayerShapeStatsMap[layerShapeKey]++;
+}
+
+void LayerStats::dump(String8& result) {
+    ATRACE_CALL();
+    ALOGD("Dumping");
+    std::lock_guard<std::mutex> lock(mMutex);
+    result.append("Frequency,LayerCount,ColorMode,ColorTransform,Orientation\n");
+    result.append("LayerType,CompositionType,IsProtected,Transform,PixelFormat,Dataspace,");
+    result.append("DstX,DstY,DstWidth,DstHeight,WScale,HScale,Alpha\n");
+    for (auto& u : mLayerShapeStatsMap) {
+        result.appendFormat("%u,%s\n", u.second, u.first.c_str());
+    }
+}
+
+const char* LayerStats::destinationLocation(int32_t location, int32_t range, bool isHorizontal) {
+    static const char* locationArray[8] = {"0", "1/8", "1/4", "3/8", "1/2", "5/8", "3/4", "7/8"};
+    int32_t ratio = location * 8 / range;
+    if (ratio < 0) return "N/A";
+    if (isHorizontal) {
+        // X location is divided into 4 buckets {"0", "1/4", "1/2", "3/4"}
+        if (ratio > 6) return "3/4";
+        // use index 0, 2, 4, 6
+        return locationArray[ratio & ~1];
+    }
+    if (ratio > 7) return "7/8";
+    return locationArray[ratio];
+}
+
+const char* LayerStats::destinationSize(int32_t size, int32_t range, bool isWidth) {
+    static const char* sizeArray[8] = {"1/8", "1/4", "3/8", "1/2", "5/8", "3/4", "7/8", "1"};
+    int32_t ratio = size * 8 / range;
+    if (ratio < 0) return "N/A";
+    if (isWidth) {
+        // width is divided into 4 buckets {"1/4", "1/2", "3/4", "1"}
+        if (ratio > 6) return "1";
+        // use index 1, 3, 5, 7
+        return sizeArray[ratio | 1];
+    }
+    if (ratio > 7) return "1";
+    return sizeArray[ratio];
+}
+
+const char* LayerStats::layerTransform(int32_t transform) {
+    return getTransformName(static_cast<hwc_transform_t>(transform));
+}
+
+const char* LayerStats::layerCompositionType(int32_t compositionType) {
+    return getCompositionName(static_cast<hwc2_composition_t>(compositionType));
+}
+
+const char* LayerStats::layerPixelFormat(int32_t pixelFormat) {
+    return decodePixelFormat(pixelFormat).c_str();
+}
+
+std::string LayerStats::scaleRatioWH(const LayerProtoParser::Layer* layer) {
+    if (!layer->type.compare("ColorLayer")) return "N/A,N/A";
+    std::string ret = "";
+    if (isRotated(layer->hwcTransform)) {
+        ret += scaleRatio(layer->hwcFrame.right - layer->hwcFrame.left,
+                          static_cast<int32_t>(layer->hwcCrop.bottom - layer->hwcCrop.top));
+        ret += ",";
+        ret += scaleRatio(layer->hwcFrame.bottom - layer->hwcFrame.top,
+                          static_cast<int32_t>(layer->hwcCrop.right - layer->hwcCrop.left));
+    } else {
+        ret += scaleRatio(layer->hwcFrame.right - layer->hwcFrame.left,
+                          static_cast<int32_t>(layer->hwcCrop.right - layer->hwcCrop.left));
+        ret += ",";
+        ret += scaleRatio(layer->hwcFrame.bottom - layer->hwcFrame.top,
+                          static_cast<int32_t>(layer->hwcCrop.bottom - layer->hwcCrop.top));
+    }
+    return ret;
+}
+
+const char* LayerStats::scaleRatio(int32_t destinationScale, int32_t sourceScale) {
+    // Make scale buckets from <1/64 to >= 16, to avoid floating point
+    // calculation, x64 on destinationScale first
+    int32_t scale = destinationScale * 64 / sourceScale;
+    if (!scale) return "<1/64";
+    if (scale < 2) return "1/64";
+    if (scale < 4) return "1/32";
+    if (scale < 8) return "1/16";
+    if (scale < 16) return "1/8";
+    if (scale < 32) return "1/4";
+    if (scale < 64) return "1/2";
+    if (scale < 128) return "1";
+    if (scale < 256) return "2";
+    if (scale < 512) return "4";
+    if (scale < 1024) return "8";
+    return ">=16";
+}
+
+const char* LayerStats::alpha(float a) {
+    if (a == 1.0f) return "1.0";
+    if (a > 0.9f) return "0.99";
+    if (a > 0.8f) return "0.9";
+    if (a > 0.7f) return "0.8";
+    if (a > 0.6f) return "0.7";
+    if (a > 0.5f) return "0.6";
+    if (a > 0.4f) return "0.5";
+    if (a > 0.3f) return "0.4";
+    if (a > 0.2f) return "0.3";
+    if (a > 0.1f) return "0.2";
+    if (a > 0.0f) return "0.1";
+    return "0.0";
+}
+
+bool LayerStats::isRotated(int32_t transform) {
+    return transform & HWC_TRANSFORM_ROT_90;
+}
+
+bool LayerStats::isVFlipped(int32_t transform) {
+    return transform & HWC_TRANSFORM_FLIP_V;
+}
+
+bool LayerStats::isHFlipped(int32_t transform) {
+    return transform & HWC_TRANSFORM_FLIP_H;
+}
+
+}  // namespace android
diff --git a/services/surfaceflinger/LayerStats.h b/services/surfaceflinger/LayerStats.h
new file mode 100644
index 0000000..7871fc6
--- /dev/null
+++ b/services/surfaceflinger/LayerStats.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <layerproto/LayerProtoHeader.h>
+#include <layerproto/LayerProtoParser.h>
+#include <mutex>
+#include <unordered_map>
+
+using namespace android::surfaceflinger;
+
+namespace android {
+class String8;
+
+class LayerStats {
+public:
+    void enable();
+    void disable();
+    void clear();
+    bool isEnabled();
+    void logLayerStats(const LayersProto& layersProto);
+    void dump(String8& result);
+
+private:
+    // Traverse layer tree to get all visible layers' stats
+    void traverseLayerTreeStatsLocked(
+            std::vector<std::unique_ptr<LayerProtoParser::Layer>> layerTree,
+            const LayerProtoParser::LayerGlobal* layerGlobal,
+            std::vector<std::string>& layerShapeVec);
+    // Convert layer's top-left position into 8x8 percentage of the display
+    static const char* destinationLocation(int32_t location, int32_t range, bool isHorizontal);
+    // Convert layer's size into 8x8 percentage of the display
+    static const char* destinationSize(int32_t size, int32_t range, bool isWidth);
+    // Return the name of the transform
+    static const char* layerTransform(int32_t transform);
+    // Return the name of the composition type
+    static const char* layerCompositionType(int32_t compositionType);
+    // Return the name of the pixel format
+    static const char* layerPixelFormat(int32_t pixelFormat);
+    // Calculate scale ratios of layer's width/height with rotation information
+    static std::string scaleRatioWH(const LayerProtoParser::Layer* layer);
+    // Calculate scale ratio from source to destination and convert to string
+    static const char* scaleRatio(int32_t destinationScale, int32_t sourceScale);
+    // Bucket the alpha into designed buckets
+    static const char* alpha(float a);
+    // Return whether the original buffer is rotated in final composition
+    static bool isRotated(int32_t transform);
+    // Return whether the original buffer is V-flipped in final composition
+    static bool isVFlipped(int32_t transform);
+    // Return whether the original buffer is H-flipped in final composition
+    static bool isHFlipped(int32_t transform);
+
+    bool mEnabled = false;
+    // Protect mLayersStatsMap
+    std::mutex mMutex;
+    // Hashmap for tracking the frame(layer shape) stats
+    // KEY is a concatenation of all layers' properties within a frame
+    // VALUE is the number of times this particular set has been scanned out
+    std::unordered_map<std::string, uint32_t> mLayerShapeStatsMap;
+};
+
+}  // namespace android
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index b9c4909..bf0707f 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <ui/GraphicsTypes.h>
+#include <ui/GraphicTypes.h>
 
 #include "Transform.h"
 
@@ -32,7 +32,7 @@
     int getReqWidth() const { return mReqWidth; };
     Transform::orientation_flags getRotationFlags() const { return mRotationFlags; };
     virtual bool getWideColorSupport() const = 0;
-    virtual ColorMode getActiveColorMode() const = 0;
+    virtual ui::ColorMode getActiveColorMode() const = 0;
 
     status_t updateDimensions();
 
diff --git a/services/surfaceflinger/RenderEngine/Surface.cpp b/services/surfaceflinger/RenderEngine/Surface.cpp
index 3c29e4b..0d20f1f 100644
--- a/services/surfaceflinger/RenderEngine/Surface.cpp
+++ b/services/surfaceflinger/RenderEngine/Surface.cpp
@@ -66,7 +66,7 @@
 
 EGLint Surface::queryConfig(EGLint attrib) const {
     EGLint value;
-    if (!eglGetConfigAttrib(mEGLConfig, mEGLConfig, attrib, &value)) {
+    if (!eglGetConfigAttrib(mEGLDisplay, mEGLConfig, attrib, &value)) {
         value = 0;
     }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2f653ef..f7f5b58 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -104,6 +104,7 @@
 
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
+using ui::ColorMode;
 
 namespace {
 class ConditionalLock {
@@ -1483,6 +1484,7 @@
     setUpHWComposer();
     doDebugFlashRegions();
     doTracing("handleRefresh");
+    logLayerStats();
     doComposition();
     postComposition(refreshStartTime);
 
@@ -1552,6 +1554,25 @@
     }
 }
 
+void SurfaceFlinger::logLayerStats() {
+    ATRACE_CALL();
+    if (CC_UNLIKELY(mLayerStats.isEnabled())) {
+        int32_t hwcId = -1;
+        for (size_t dpy = 0; dpy < mDisplays.size(); ++dpy) {
+            const sp<const DisplayDevice>& displayDevice(mDisplays[dpy]);
+            if (displayDevice->isPrimary()) {
+                hwcId = displayDevice->getHwcDisplayId();
+                break;
+            }
+        }
+        if (hwcId < 0) {
+            ALOGE("LayerStats: Hmmm, no primary display?");
+            return;
+        }
+        mLayerStats.logLayerStats(dumpVisibleLayersProtoInfo(hwcId));
+    }
+}
+
 void SurfaceFlinger::preComposition(nsecs_t refreshStartTime)
 {
     ATRACE_CALL();
@@ -1939,6 +1960,7 @@
             continue;
         }
         if (colorMatrix != mPreviousColorMatrix) {
+            displayDevice->setColorTransform(colorMatrix);
             status_t result = getBE().mHwc->setColorTransform(hwcId, colorMatrix);
             ALOGE_IF(result != NO_ERROR, "Failed to set color transform on "
                     "display %zd: %d", displayId, result);
@@ -3656,6 +3678,7 @@
         ALOGE("Attempting to set unknown power mode: %d\n", mode);
         getHwComposer().setPowerMode(type, mode);
     }
+    ALOGD("Finished set power mode=%d, type=%d", mode, hw->getDisplayType());
 }
 
 void SurfaceFlinger::setPowerMode(const sp<IBinder>& display, int mode) {
@@ -3770,6 +3793,34 @@
                 dumpWideColorInfo(result);
                 dumpAll = false;
             }
+
+            if ((index < numArgs) &&
+                (args[index] == String16("--enable-layer-stats"))) {
+                index++;
+                mLayerStats.enable();
+                dumpAll = false;
+            }
+
+            if ((index < numArgs) &&
+                (args[index] == String16("--disable-layer-stats"))) {
+                index++;
+                mLayerStats.disable();
+                dumpAll = false;
+            }
+
+            if ((index < numArgs) &&
+                (args[index] == String16("--clear-layer-stats"))) {
+                index++;
+                mLayerStats.clear();
+                dumpAll = false;
+            }
+
+            if ((index < numArgs) &&
+                (args[index] == String16("--dump-layer-stats"))) {
+                index++;
+                mLayerStats.dump(result);
+                dumpAll = false;
+            }
         }
 
         if (dumpAll) {
@@ -3977,6 +4028,29 @@
     return layersProto;
 }
 
+LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(int32_t hwcId) const {
+    LayersProto layersProto;
+    const sp<DisplayDevice>& displayDevice(mDisplays[hwcId]);
+
+    SizeProto* resolution = layersProto.mutable_resolution();
+    resolution->set_w(displayDevice->getWidth());
+    resolution->set_h(displayDevice->getHeight());
+
+    layersProto.set_color_mode(decodeColorMode(displayDevice->getActiveColorMode()));
+    layersProto.set_color_transform(decodeColorTransform(displayDevice->getColorTransform()));
+    layersProto.set_global_transform(
+            static_cast<int32_t>(displayDevice->getOrientationTransform()));
+
+    mDrawingState.traverseInZOrder([&](Layer* layer) {
+        if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(hwcId)) {
+            LayerProto* layerProto = layersProto.add_layers();
+            layer->writeToProto(layerProto, hwcId);
+        }
+    });
+
+    return layersProto;
+}
+
 void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
         String8& result) const
 {
@@ -4047,6 +4121,7 @@
     LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current);
     auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
     result.append(LayerProtoParser::layersToString(std::move(layerTree)).c_str());
+    result.append("\n");
 
     /*
      * Dump Display state
@@ -4059,6 +4134,7 @@
         const sp<const DisplayDevice>& hw(mDisplays[dpy]);
         hw->dump(result);
     }
+    result.append("\n");
 
     /*
      * Dump SurfaceFlinger global state
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 42d8112..c7c3088 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -55,6 +55,7 @@
 #include "DisplayDevice.h"
 #include "DispSync.h"
 #include "FrameTracker.h"
+#include "LayerStats.h"
 #include "LayerVector.h"
 #include "MessageQueue.h"
 #include "SurfaceInterceptor.h"
@@ -410,9 +411,9 @@
             Vector<DisplayInfo>* configs);
     virtual int getActiveConfig(const sp<IBinder>& display);
     virtual status_t getDisplayColorModes(const sp<IBinder>& display,
-            Vector<ColorMode>* configs);
-    virtual ColorMode getActiveColorMode(const sp<IBinder>& display);
-    virtual status_t setActiveColorMode(const sp<IBinder>& display, ColorMode colorMode);
+            Vector<ui::ColorMode>* configs);
+    virtual ui::ColorMode getActiveColorMode(const sp<IBinder>& display);
+    virtual status_t setActiveColorMode(const sp<IBinder>& display, ui::ColorMode colorMode);
     virtual void setPowerMode(const sp<IBinder>& display, int mode);
     virtual status_t setActiveConfig(const sp<IBinder>& display, int id);
     virtual status_t clearAnimationFrameStats();
@@ -462,7 +463,7 @@
                               bool stateLockHeld);
 
     // Called on the main thread in response to setActiveColorMode()
-    void setActiveColorModeInternal(const sp<DisplayDevice>& hw, ColorMode colorMode);
+    void setActiveColorModeInternal(const sp<DisplayDevice>& hw, ui::ColorMode colorMode);
 
     // Returns whether the transaction actually modified any state
     bool handleMessageTransaction();
@@ -635,7 +636,7 @@
 
     // Given a dataSpace, returns the appropriate color_mode to use
     // to display that dataSpace.
-    ColorMode pickColorMode(android_dataspace dataSpace) const;
+    ui::ColorMode pickColorMode(android_dataspace dataSpace) const;
     android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b,
             bool hasHdr) const;
 
@@ -645,6 +646,7 @@
     void doComposition();
     void doDebugFlashRegions();
     void doTracing(const char* where);
+    void logLayerStats();
     void doDisplayComposition(const sp<const DisplayDevice>& displayDevice, const Region& dirtyRegion);
 
     // compose surfaces for display hw. this fails if using GL and the surface
@@ -711,6 +713,7 @@
     void dumpBufferingStats(String8& result) const;
     void dumpWideColorInfo(String8& result) const;
     LayersProto dumpProtoInfo(LayerVector::StateSet stateSet) const;
+    LayersProto dumpVisibleLayersProtoInfo(int32_t hwcId) const;
 
     bool isLayerTripleBufferingDisabled() const {
         return this->mLayerTripleBufferingDisabled;
@@ -797,6 +800,7 @@
     std::unique_ptr<SurfaceInterceptor> mInterceptor =
             std::make_unique<impl::SurfaceInterceptor>(this);
     SurfaceTracing mTracing;
+    LayerStats mLayerStats;
     bool mUseHwcVirtualDisplays = false;
 
     // Restrict layers to use two buffers in their bufferqueues.
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
index 47e5d1f..fcf42f0 100644
--- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -42,6 +42,16 @@
     return sortLayers(lhs.get(), rhs.get());
 }
 
+const LayerProtoParser::LayerGlobal LayerProtoParser::generateLayerGlobalInfo(
+        const LayersProto& layersProto) {
+    LayerGlobal layerGlobal;
+    layerGlobal.resolution = {layersProto.resolution().w(), layersProto.resolution().h()};
+    layerGlobal.colorMode = layersProto.color_mode();
+    layerGlobal.colorTransform = layersProto.color_transform();
+    layerGlobal.globalTransform = layersProto.global_transform();
+    return layerGlobal;
+}
+
 std::vector<std::unique_ptr<LayerProtoParser::Layer>> LayerProtoParser::generateLayerTree(
         const LayersProto& layersProto) {
     std::unordered_map<int32_t, LayerProtoParser::Layer*> layerMap = generateMap(layersProto);
@@ -106,8 +116,13 @@
     layer->activeBuffer = generateActiveBuffer(layerProto.active_buffer());
     layer->queuedFrames = layerProto.queued_frames();
     layer->refreshPending = layerProto.refresh_pending();
+    layer->hwcFrame = generateRect(layerProto.hwc_frame());
+    layer->hwcCrop = generateFloatRect(layerProto.hwc_crop());
+    layer->hwcTransform = layerProto.hwc_transform();
     layer->windowType = layerProto.window_type();
     layer->appId = layerProto.app_id();
+    layer->hwcCompositionType = layerProto.hwc_composition_type();
+    layer->isProtected = layerProto.is_protected();
 
     return layer;
 }
@@ -133,6 +148,16 @@
     return rect;
 }
 
+LayerProtoParser::FloatRect LayerProtoParser::generateFloatRect(const FloatRectProto& rectProto) {
+    LayerProtoParser::FloatRect rect;
+    rect.left = rectProto.left();
+    rect.top = rectProto.top();
+    rect.right = rectProto.right();
+    rect.bottom = rectProto.bottom();
+
+    return rect;
+}
+
 LayerProtoParser::Transform LayerProtoParser::generateTransform(
         const TransformProto& transformProto) {
     LayerProtoParser::Transform transform;
@@ -246,6 +271,10 @@
     return StringPrintf("[%3d, %3d, %3d, %3d]", left, top, right, bottom);
 }
 
+std::string LayerProtoParser::FloatRect::to_string() const {
+    return StringPrintf("[%.2f, %.2f, %.2f, %.2f]", left, top, right, bottom);
+}
+
 std::string LayerProtoParser::Region::to_string(const char* what) const {
     std::string result =
             StringPrintf("  Region %s (this=%lx count=%d)\n", what, static_cast<unsigned long>(id),
@@ -273,7 +302,7 @@
                   finalCrop.to_string().c_str());
     StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate);
     StringAppendF(&result, "dataspace=%s, ", dataspace.c_str());
-    StringAppendF(&result, "pixelformat=%s, ", pixelFormat.c_str());
+    StringAppendF(&result, "defaultPixelFormat=%s, ", pixelFormat.c_str());
     StringAppendF(&result, "color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ",
                   static_cast<double>(color.r), static_cast<double>(color.g),
                   static_cast<double>(color.b), static_cast<double>(color.a), flags);
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
index b56a6fb..74a6f28 100644
--- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#pragma once
 
 #include <layerproto/LayerProtoHeader.h>
 
@@ -57,6 +58,16 @@
         std::string to_string() const;
     };
 
+    class FloatRect {
+    public:
+        float left;
+        float top;
+        float right;
+        float bottom;
+
+        std::string to_string() const;
+    };
+
     class Region {
     public:
         uint64_t id;
@@ -96,12 +107,26 @@
         LayerProtoParser::ActiveBuffer activeBuffer;
         int32_t queuedFrames;
         bool refreshPending;
+        LayerProtoParser::Rect hwcFrame;
+        LayerProtoParser::FloatRect hwcCrop;
+        int32_t hwcTransform;
         int32_t windowType;
         int32_t appId;
+        int32_t hwcCompositionType;
+        bool isProtected;
 
         std::string to_string() const;
     };
 
+    class LayerGlobal {
+    public:
+        int2 resolution;
+        std::string colorMode;
+        std::string colorTransform;
+        int32_t globalTransform;
+    };
+
+    static const LayerGlobal generateLayerGlobalInfo(const LayersProto& layersProto);
     static std::vector<std::unique_ptr<Layer>> generateLayerTree(const LayersProto& layersProto);
     static std::string layersToString(std::vector<std::unique_ptr<LayerProtoParser::Layer>> layers);
 
@@ -110,6 +135,7 @@
     static LayerProtoParser::Layer* generateLayer(const LayerProto& layerProto);
     static LayerProtoParser::Region generateRegion(const RegionProto& regionProto);
     static LayerProtoParser::Rect generateRect(const RectProto& rectProto);
+    static LayerProtoParser::FloatRect generateFloatRect(const FloatRectProto& rectProto);
     static LayerProtoParser::Transform generateTransform(const TransformProto& transformProto);
     static LayerProtoParser::ActiveBuffer generateActiveBuffer(
             const ActiveBufferProto& activeBufferProto);
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index f18386b..77c6675 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -7,6 +7,10 @@
 // Contains a list of all layers.
 message LayersProto {
   repeated LayerProto layers = 1;
+  optional SizeProto resolution = 2;
+  optional string color_mode = 3;
+  optional string color_transform = 4;
+  optional int32 global_transform = 5;
 }
 
 // Information about each layer.
@@ -64,8 +68,18 @@
   // The number of frames available.
   optional int32 queued_frames = 28;
   optional bool refresh_pending = 29;
-  optional int32 window_type = 30;
-  optional int32 app_id = 31;
+  // The layer's composer backend destination frame
+  optional RectProto hwc_frame = 30;
+  // The layer's composer backend source crop
+  optional FloatRectProto hwc_crop = 31;
+  // The layer's composer backend transform
+  optional int32 hwc_transform = 32;
+  optional int32 window_type = 33;
+  optional int32 app_id = 34;
+  // The layer's composition type
+  optional int32 hwc_composition_type = 35;
+  // If it's a buffer layer, indicate if the content is protected
+  optional bool is_protected = 36;
 }
 
 message PositionProto {
@@ -97,6 +111,13 @@
   optional int32 bottom = 4;
 }
 
+message FloatRectProto {
+  optional float left = 1;
+  optional float top = 2;
+  optional float right = 3;
+  optional float bottom = 4;
+}
+
 message ActiveBufferProto {
   optional uint32 width = 1;
   optional uint32 height = 2;
@@ -109,4 +130,4 @@
   optional float g = 2;
   optional float b = 3;
   optional float a = 4;
-}
\ No newline at end of file
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
index 86e2e1e..b3f1b69 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
@@ -22,7 +22,7 @@
 #include <android-base/unique_fd.h>
 #include <hardware/hardware.h>
 #include <sync/sync.h>
-#include <ui/GraphicsTypes.h>
+#include <ui/GraphicTypes.h>
 
 #define HWC2_INCLUDE_STRINGIFICATION
 #define HWC2_USE_CPP11
@@ -35,7 +35,7 @@
 #include "Hwc2TestClientTarget.h"
 #include "Hwc2TestVirtualDisplay.h"
 
-using android::ColorMode;
+using android::ui::ColorMode;
 
 void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData,
         hwc2_display_t display, int32_t connected);
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index e141b91..c38c12b 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -134,7 +134,6 @@
            channel_id(), buffer_id(), buffer_state_->load());
   for (auto consumer : consumer_channels_) {
     consumer->OnProducerClosed();
-    service()->SetChannel(consumer->channel_id(), nullptr);
   }
   Hangup();
 }
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index dec39e0..741fbb8 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -500,13 +500,36 @@
                 // both we and HAL can take part in
                 hook_extensions_.set(ext_bit);
                 break;
-            case ProcHook::EXTENSION_UNKNOWN:
             case ProcHook::KHR_get_physical_device_properties2:
-                // HAL's extensions
+            case ProcHook::EXTENSION_UNKNOWN:
+                // Extensions we don't need to do anything about at this level
                 break;
-            default:
-                ALOGW("Ignored invalid instance extension %s", name);
+
+            case ProcHook::KHR_incremental_present:
+            case ProcHook::KHR_shared_presentable_image:
+            case ProcHook::KHR_swapchain:
+            case ProcHook::EXT_hdr_metadata:
+            case ProcHook::ANDROID_external_memory_android_hardware_buffer:
+            case ProcHook::ANDROID_native_buffer:
+            case ProcHook::GOOGLE_display_timing:
+            case ProcHook::EXTENSION_CORE:
+            case ProcHook::EXTENSION_COUNT:
+                // Device and meta extensions. If we ever get here it's a bug in
+                // our code. But enumerating them lets us avoid having a default
+                // case, and default hides other bugs.
+                ALOGE(
+                    "CreateInfoWrapper::FilterExtension: invalid instance "
+                    "extension '%s'. FIX ME",
+                    name);
                 return;
+
+            // Don't use a default case. Without it, -Wswitch will tell us
+            // at compile time if someone adds a new ProcHook extension but
+            // doesn't handle it above. That's a real bug that has
+            // not-immediately-obvious effects.
+            //
+            // default:
+            //     break;
         }
     } else {
         switch (ext_bit) {
@@ -524,12 +547,36 @@
             case ProcHook::EXT_hdr_metadata:
                 hook_extensions_.set(ext_bit);
                 break;
+            case ProcHook::ANDROID_external_memory_android_hardware_buffer:
             case ProcHook::EXTENSION_UNKNOWN:
-                // HAL's extensions
+                // Extensions we don't need to do anything about at this level
                 break;
-            default:
-                ALOGW("Ignored invalid device extension %s", name);
+
+            case ProcHook::KHR_android_surface:
+            case ProcHook::KHR_get_physical_device_properties2:
+            case ProcHook::KHR_get_surface_capabilities2:
+            case ProcHook::KHR_surface:
+            case ProcHook::EXT_debug_report:
+            case ProcHook::EXT_swapchain_colorspace:
+            case ProcHook::ANDROID_native_buffer:
+            case ProcHook::EXTENSION_CORE:
+            case ProcHook::EXTENSION_COUNT:
+                // Instance and meta extensions. If we ever get here it's a bug
+                // in our code. But enumerating them lets us avoid having a
+                // default case, and default hides other bugs.
+                ALOGE(
+                    "CreateInfoWrapper::FilterExtension: invalid device "
+                    "extension '%s'. FIX ME",
+                    name);
                 return;
+
+            // Don't use a default case. Without it, -Wswitch will tell us
+            // at compile time if someone adds a new ProcHook extension but
+            // doesn't handle it above. That's a real bug that has
+            // not-immediately-obvious effects.
+            //
+            // default:
+            //     break;
         }
     }