Merge "Add SurfaceInterceptor initial implementation"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index bf99017..4319dc2 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -35,6 +35,7 @@
 #include <unistd.h>
 
 #include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
 #include <cutils/properties.h>
 
 #include "private/android_filesystem_config.h"
@@ -43,7 +44,6 @@
 #include <cutils/log.h>
 
 #include "dumpstate.h"
-#include "ScopedFd.h"
 #include "ziparchive/zip_writer.h"
 
 #include <openssl/sha.h>
@@ -629,8 +629,9 @@
 }
 
 bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
-    ScopedFd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
-    if (fd.get() == -1) {
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK
+            | O_CLOEXEC)));
+    if (fd == -1) {
         MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
         return false;
     }
@@ -1069,9 +1070,9 @@
 }
 
 static std::string SHA256_file_hash(std::string filepath) {
-    ScopedFd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC
-            | O_NOFOLLOW)));
-    if (fd.get() == -1) {
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
+            | O_CLOEXEC | O_NOFOLLOW)));
+    if (fd == -1) {
         MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
         return NULL;
     }
diff --git a/cmds/servicemanager/binder.h b/cmds/servicemanager/binder.h
index 7915fc2..881ab07 100644
--- a/cmds/servicemanager/binder.h
+++ b/cmds/servicemanager/binder.h
@@ -5,7 +5,7 @@
 #define _BINDER_H_
 
 #include <sys/ioctl.h>
-#include <linux/binder.h>
+#include <linux/android/binder.h>
 
 struct binder_state;
 
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 42ed148..a06fb4a 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -27,7 +27,7 @@
 #include <utils/String16.h>
 #include <utils/Vector.h>
 #include <utils/Flattenable.h>
-#include <linux/binder.h>
+#include <linux/android/binder.h>
 
 #include <binder/IInterface.h>
 #include <binder/Parcelable.h>
@@ -246,6 +246,7 @@
 
     const char*         readCString() const;
     String8             readString8() const;
+    status_t            readString8(String8* pArg) const;
     String16            readString16() const;
     status_t            readString16(String16* pArg) const;
     status_t            readString16(std::unique_ptr<String16>* pArg) const;
@@ -586,10 +587,12 @@
     if (ret == OK) {
         *val = interface_cast<T>(tmp);
 
-        if (val->get() == nullptr) {
-            return UNKNOWN_ERROR;
+        if (val->get() == nullptr && tmp.get() != nullptr) {
+            ret = UNKNOWN_ERROR;
         }
     }
+
+    return ret;
 }
 
 template<typename T, typename U>
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index fe4b1fa..2bfb649 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -79,7 +79,8 @@
     // needed gralloc buffers.
     static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
             sp<IGraphicBufferConsumer>* outConsumer,
-            const sp<IGraphicBufferAlloc>& allocator = NULL);
+            const sp<IGraphicBufferAlloc>& allocator = NULL,
+            bool consumerIsSurfaceFlinger = false);
 
 private:
     BufferQueue(); // Create through createBufferQueue
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index 838632c..d2bd32e 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -29,7 +29,7 @@
 public:
     friend class BufferQueue; // Needed to access binderDied
 
-    BufferQueueProducer(const sp<BufferQueueCore>& core);
+    BufferQueueProducer(const sp<BufferQueueCore>& core, bool consumerIsSurfaceFlinger = false);
     virtual ~BufferQueueProducer();
 
     // requestBuffer returns the GraphicBuffer for slot N.
@@ -225,6 +225,10 @@
 
     uint32_t mStickyTransform;
 
+    // This controls whether the GraphicBuffer pointer in the BufferItem is
+    // cleared after being queued
+    bool mConsumerIsSurfaceFlinger;
+
     // This saves the fence from the last queueBuffer, such that the
     // next queueBuffer call can throttle buffer production. The prior
     // queueBuffer's fence is not nessessarily available elsewhere,
diff --git a/include/gui/IConsumerListener.h b/include/gui/IConsumerListener.h
index 1efcf3c..9b0d919 100644
--- a/include/gui/IConsumerListener.h
+++ b/include/gui/IConsumerListener.h
@@ -49,7 +49,8 @@
     // previous frames are pending. Frames queued while in synchronous mode
     // always trigger the callback. The item passed to the callback will contain
     // all of the information about the queued frame except for its
-    // GraphicBuffer pointer, which will always be null.
+    // GraphicBuffer pointer, which will always be null (except if the consumer
+    // is SurfaceFlinger).
     //
     // This is called without any lock held and can be called concurrently
     // by multiple threads.
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index c62bc58..9353042 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -339,20 +339,19 @@
         void setSurfaceDamage(const Region& damage) { surfaceDamage = damage; }
 
     private:
-        int64_t timestamp;
-        int isAutoTimestamp;
-        android_dataspace dataSpace;
+        int64_t timestamp{0};
+        int isAutoTimestamp{0};
+        android_dataspace dataSpace{HAL_DATASPACE_UNKNOWN};
         Rect crop;
-        int scalingMode;
-        uint32_t transform;
-        uint32_t stickyTransform;
+        int scalingMode{0};
+        uint32_t transform{0};
+        uint32_t stickyTransform{0};
         sp<Fence> fence;
         Region surfaceDamage;
     };
 
     // QueueBufferOutput must be a POD structure
     struct __attribute__ ((__packed__)) QueueBufferOutput {
-        inline QueueBufferOutput() { }
         // outWidth - filled with default width applied to the buffer
         // outHeight - filled with default height applied to the buffer
         // outTransformHint - filled with default transform applied to the buffer
@@ -379,10 +378,10 @@
             nextFrameNumber = inNextFrameNumber;
         }
     private:
-        uint32_t width;
-        uint32_t height;
-        uint32_t transformHint;
-        uint32_t numPendingBuffers;
+        uint32_t width{0};
+        uint32_t height{0};
+        uint32_t transformHint{0};
+        uint32_t numPendingBuffers{0};
         uint64_t nextFrameNumber{0};
     };
 
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index af26721..74a4123 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -137,6 +137,12 @@
      * should be used */
     virtual status_t setActiveConfig(const sp<IBinder>& display, int id) = 0;
 
+    virtual status_t getDisplayColorModes(const sp<IBinder>& display,
+            Vector<android_color_mode_t>* outColorModes) = 0;
+    virtual android_color_mode_t getActiveColorMode(const sp<IBinder>& display) = 0;
+    virtual status_t setActiveColorMode(const sp<IBinder>& display,
+            android_color_mode_t colorMode) = 0;
+
     /* Capture the specified screen. requires READ_FRAME_BUFFER permission
      * This function will fail if there is a secure window on screen.
      */
@@ -193,6 +199,9 @@
         SET_POWER_MODE,
         GET_DISPLAY_STATS,
         GET_HDR_CAPABILITIES,
+        GET_DISPLAY_COLOR_MODES,
+        GET_ACTIVE_COLOR_MODE,
+        SET_ACTIVE_COLOR_MODE,
     };
 
     virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 95e8b70..b8ee331 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -83,6 +83,16 @@
     // returned by getDisplayInfo
     static status_t setActiveConfig(const sp<IBinder>& display, int id);
 
+    // Gets the list of supported color modes for the given display
+    static status_t getDisplayColorModes(const sp<IBinder>& display,
+            Vector<android_color_mode_t>* outColorModes);
+
+    // Gets the active color mode for the given display
+    static android_color_mode_t getActiveColorMode(const sp<IBinder>& display);
+
+    // Sets the active color mode for the given display
+    static status_t setActiveColorMode(const sp<IBinder>& display, android_color_mode_t 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/include/media/openmax/OMX_Core.h b/include/media/openmax/OMX_Core.h
index eeacf43..bb974b3 100644
--- a/include/media/openmax/OMX_Core.h
+++ b/include/media/openmax/OMX_Core.h
@@ -516,6 +516,9 @@
      *  but must signal the event no more than 40ms after the first frame in the batch. The frames
      *  must be ordered by system timestamp inside and across batches.
      *
+     *  The component shall signal the render-timestamp of the very first frame (as well as the
+     *  first frame after each flush) unbatched (with nData1 set to 1) within 5 msec.
+     *
      *  If component is doing frame-rate conversion, it must signal the render time of each
      *  converted frame, and must interpolate media timestamps for in-between frames.
      *
@@ -753,15 +756,21 @@
     When the command is "OMX_CommandStateSet" the component will queue a
     state transition to the new state idenfied in nParam.
 
+    The component shall transition from executing to loaded state within 500 msec.
+
     When the command is "OMX_CommandFlush", to flush a port's buffer queues,
     the command will force the component to return all buffers NOT CURRENTLY
     BEING PROCESSED to the application, in the order in which the buffers
     were received.
 
+    The component shall finish flusing each port within 5 msec.
+
     When the command is "OMX_CommandPortDisable" or
     "OMX_CommandPortEnable", the component's port (given by the value of
     nParam) will be stopped or restarted.
 
+    The component shall finish disabling/reenabling each port within 5 msec.
+
     When the command "OMX_CommandMarkBuffer" is used to mark a buffer, the
     pCmdData will point to a OMX_MARKTYPE structure containing the component
     handle of the component to examine the buffer chain for the mark.  nParam1
diff --git a/include/private/binder/binder_module.h b/include/private/binder/binder_module.h
index a8dd64f..2f11622 100644
--- a/include/private/binder/binder_module.h
+++ b/include/private/binder/binder_module.h
@@ -24,7 +24,7 @@
 /* obtain structures and constants from the kernel header */
 
 #include <sys/ioctl.h>
-#include <linux/binder.h>
+#include <linux/android/binder.h>
 
 #ifdef __cplusplus
 }   // namespace android
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index 4b3fcc6..292dd3b 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -74,10 +74,10 @@
     status_t    read(const Parcel& input);
 
             struct matrix22_t {
-                float   dsdx;
-                float   dtdx;
-                float   dsdy;
-                float   dtdy;
+                float   dsdx{0};
+                float   dtdx{0};
+                float   dsdy{0};
+                float   dtdy{0};
             };
             sp<IBinder>     surface;
             uint32_t        what;
diff --git a/include/ui/DisplayInfo.h b/include/ui/DisplayInfo.h
index ad73ee7..842806e 100644
--- a/include/ui/DisplayInfo.h
+++ b/include/ui/DisplayInfo.h
@@ -26,17 +26,16 @@
 namespace android {
 
 struct DisplayInfo {
-    uint32_t w;
-    uint32_t h;
-    float xdpi;
-    float ydpi;
-    float fps;
-    float density;
-    uint8_t orientation;
-    bool secure;
-    nsecs_t appVsyncOffset;
-    nsecs_t presentationDeadline;
-    int colorTransform;
+    uint32_t w{0};
+    uint32_t h{0};
+    float xdpi{0};
+    float ydpi{0};
+    float fps{0};
+    float density{0};
+    uint8_t orientation{0};
+    bool secure{false};
+    nsecs_t appVsyncOffset{0};
+    nsecs_t presentationDeadline{0};
 };
 
 /* Display orientations as defined in Surface.java and ISurfaceComposer.h. */
diff --git a/include/ui/DisplayStatInfo.h b/include/ui/DisplayStatInfo.h
index 0549a83..09543ec 100644
--- a/include/ui/DisplayStatInfo.h
+++ b/include/ui/DisplayStatInfo.h
@@ -22,8 +22,8 @@
 namespace android {
 
 struct DisplayStatInfo {
-    nsecs_t vsyncTime;
-    nsecs_t vsyncPeriod;
+    nsecs_t vsyncTime{0};
+    nsecs_t vsyncPeriod{0};
 };
 
 }; // namespace android
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
index 74bad7a..b57b02a 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -44,20 +44,21 @@
 
 LOCAL_PATH:= $(call my-dir)
 
+binder_cflags := -Wall -Wextra -Werror
+ifneq ($(TARGET_USES_64_BIT_BINDER),true)
+ifneq ($(TARGET_IS_64_BIT),true)
+binder_cflags += -DBINDER_IPC_32BIT=1
+endif
+endif
+
 include $(CLEAR_VARS)
 LOCAL_MODULE := libbinder
 LOCAL_SHARED_LIBRARIES := libbase liblog libcutils libutils
 LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbase libutils
 
-LOCAL_CLANG := true
 LOCAL_SANITIZE := integer
 LOCAL_SRC_FILES := $(sources)
-ifneq ($(TARGET_USES_64_BIT_BINDER),true)
-ifneq ($(TARGET_IS_64_BIT),true)
-LOCAL_CFLAGS += -DBINDER_IPC_32BIT=1
-endif
-endif
-LOCAL_CFLAGS += -Werror
+LOCAL_CFLAGS := $(binder_cflags)
 include $(BUILD_SHARED_LIBRARY)
 
 include $(CLEAR_VARS)
@@ -65,10 +66,5 @@
 LOCAL_STATIC_LIBRARIES := libbase libutils
 LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := libbase libutils
 LOCAL_SRC_FILES := $(sources)
-ifneq ($(TARGET_USES_64_BIT_BINDER),true)
-ifneq ($(TARGET_IS_64_BIT),true)
-LOCAL_CFLAGS += -DBINDER_IPC_32BIT=1
-endif
-endif
-LOCAL_CFLAGS += -Werror
+LOCAL_CFLAGS := $(binder_cflags)
 include $(BUILD_STATIC_LIBRARY)
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index c4d47ca..7ce2a31 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -237,6 +237,10 @@
 
             // XXX can't add virtuals until binaries are updated.
             //return shellCommand(in, out, err, args, resultReceiver);
+            (void)in;
+            (void)out;
+            (void)err;
+
             if (resultReceiver != NULL) {
                 resultReceiver->send(INVALID_OPERATION);
             }
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 5a2492e..d566456 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -1842,13 +1842,37 @@
 
 String8 Parcel::readString8() const
 {
-    int32_t size = readInt32();
-    // watch for potential int overflow adding 1 for trailing NUL
-    if (size > 0 && size < INT32_MAX) {
-        const char* str = (const char*)readInplace(size+1);
-        if (str) return String8(str, size);
+    String8 retString;
+    status_t status = readString8(&retString);
+    if (status != OK) {
+        // We don't care about errors here, so just return an empty string.
+        return String8();
     }
-    return String8();
+    return retString;
+}
+
+status_t Parcel::readString8(String8* pArg) const
+{
+    int32_t size;
+    status_t status = readInt32(&size);
+    if (status != OK) {
+        return status;
+    }
+    // watch for potential int overflow from size+1
+    if (size < 0 || size >= INT32_MAX) {
+        return BAD_VALUE;
+    }
+    // |writeString8| writes nothing for empty string.
+    if (size == 0) {
+        *pArg = String8();
+        return OK;
+    }
+    const char* str = (const char*)readInplace(size + 1);
+    if (str == NULL) {
+        return BAD_VALUE;
+    }
+    pArg->setTo(str, size);
+    return OK;
 }
 
 String16 Parcel::readString16() const
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index 5c5651c..e7078ba 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -420,7 +420,6 @@
     RETURN_IF_FAILED(parcel->readInt32(&num_entries));
 
     for (; num_entries > 0; --num_entries) {
-        size_t start_pos = parcel->dataPosition();
         String16 key;
         int32_t value_type;
         RETURN_IF_FAILED(parcel->readString16(&key));
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index 5e3924a..2ffeb0d 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -66,6 +66,9 @@
     addAligned(size, mIsDroppable);
     addAligned(size, mAcquireCalled);
     addAligned(size, mTransformToDisplayInverse);
+    addAligned(size, mAutoRefresh);
+    addAligned(size, mQueuedBuffer);
+    addAligned(size, mIsStale);
     return size;
 }
 
@@ -151,6 +154,9 @@
     writeAligned(buffer, size, mIsDroppable);
     writeAligned(buffer, size, mAcquireCalled);
     writeAligned(buffer, size, mTransformToDisplayInverse);
+    writeAligned(buffer, size, mAutoRefresh);
+    writeAligned(buffer, size, mQueuedBuffer);
+    writeAligned(buffer, size, mIsStale);
 
     return NO_ERROR;
 }
@@ -207,6 +213,9 @@
     readAligned(buffer, size, mIsDroppable);
     readAligned(buffer, size, mAcquireCalled);
     readAligned(buffer, size, mTransformToDisplayInverse);
+    readAligned(buffer, size, mAutoRefresh);
+    readAligned(buffer, size, mQueuedBuffer);
+    readAligned(buffer, size, mIsStale);
 
     return NO_ERROR;
 }
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 6de98f5..47f5eba 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -72,7 +72,8 @@
 
 void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
         sp<IGraphicBufferConsumer>* outConsumer,
-        const sp<IGraphicBufferAlloc>& allocator) {
+        const sp<IGraphicBufferAlloc>& allocator,
+        bool consumerIsSurfaceFlinger) {
     LOG_ALWAYS_FATAL_IF(outProducer == NULL,
             "BufferQueue: outProducer must not be NULL");
     LOG_ALWAYS_FATAL_IF(outConsumer == NULL,
@@ -82,7 +83,7 @@
     LOG_ALWAYS_FATAL_IF(core == NULL,
             "BufferQueue: failed to create BufferQueueCore");
 
-    sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core));
+    sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
     LOG_ALWAYS_FATAL_IF(producer == NULL,
             "BufferQueue: failed to create BufferQueueProducer");
 
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index b574f9d..a9eac90 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -92,6 +92,7 @@
     mSharedBufferSlot(INVALID_BUFFER_SLOT),
     mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
             HAL_DATASPACE_UNKNOWN),
+    mLastQueuedSlot(INVALID_BUFFER_SLOT),
     mUniqueId(getUniqueId())
 {
     if (allocator == NULL) {
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index b7b56f0..3411dca 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -41,12 +41,15 @@
 
 namespace android {
 
-BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) :
+BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core,
+        bool consumerIsSurfaceFlinger) :
     mCore(core),
     mSlots(core->mSlots),
     mConsumerName(),
     mStickyTransform(0),
+    mConsumerIsSurfaceFlinger(consumerIsSurfaceFlinger),
     mLastQueueBufferFence(Fence::NO_FENCE),
+    mLastQueuedTransform(0),
     mCallbackMutex(),
     mNextCallbackTicket(0),
     mCurrentCallbackTicket(0),
@@ -912,9 +915,14 @@
         VALIDATE_CONSISTENCY();
     } // Autolock scope
 
-    // Don't send the GraphicBuffer through the callback, and don't send
-    // the slot number, since the consumer shouldn't need it
-    item.mGraphicBuffer.clear();
+    // It is okay not to clear the GraphicBuffer when the consumer is SurfaceFlinger because
+    // it is guaranteed that the BufferQueue is inside SurfaceFlinger's process and
+    // there will be no Binder call
+    if (!mConsumerIsSurfaceFlinger) {
+        item.mGraphicBuffer.clear();
+    }
+
+    // Don't send the slot number through the callback since the consumer shouldn't need it
     item.mSlot = BufferItem::INVALID_BUFFER_SLOT;
 
     // Call back without the main BufferQueue lock held, but with the callback
diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp
index d4d4702..ac6ace6 100644
--- a/libs/gui/IGraphicBufferAlloc.cpp
+++ b/libs/gui/IGraphicBufferAlloc.cpp
@@ -101,7 +101,7 @@
             uint32_t height = data.readUint32();
             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
             uint32_t usage = data.readUint32();
-            status_t error;
+            status_t error = NO_ERROR;
             sp<GraphicBuffer> result =
                     createGraphicBuffer(width, height, format, usage, &error);
             reply->writeInt32(error);
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 015945a..0a8e6a5 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -32,6 +32,8 @@
 
 #include <private/gui/LayerState.h>
 
+#include <system/graphics.h>
+
 #include <ui/DisplayInfo.h>
 #include <ui/DisplayStatInfo.h>
 #include <ui/HdrCapabilities.h>
@@ -269,6 +271,82 @@
         return reply.readInt32();
     }
 
+    virtual status_t getDisplayColorModes(const sp<IBinder>& display,
+            Vector<android_color_mode_t>* outColorModes) {
+        Parcel data, reply;
+        status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        if (result != NO_ERROR) {
+            ALOGE("getDisplayColorModes failed to writeInterfaceToken: %d", result);
+            return result;
+        }
+        result = data.writeStrongBinder(display);
+        if (result != NO_ERROR) {
+            ALOGE("getDisplayColorModes failed to writeStrongBinder: %d", result);
+            return result;
+        }
+        result = remote()->transact(BnSurfaceComposer::GET_DISPLAY_COLOR_MODES, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("getDisplayColorModes failed to transact: %d", result);
+            return result;
+        }
+        result = static_cast<status_t>(reply.readInt32());
+        if (result == NO_ERROR) {
+            size_t numModes = reply.readUint32();
+            outColorModes->clear();
+            outColorModes->resize(numModes);
+            for (size_t i = 0; i < numModes; ++i) {
+                outColorModes->replaceAt(static_cast<android_color_mode_t>(reply.readInt32()), i);
+            }
+        }
+        return result;
+    }
+
+    virtual android_color_mode_t getActiveColorMode(const sp<IBinder>& display) {
+        Parcel data, reply;
+        status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        if (result != NO_ERROR) {
+            ALOGE("getActiveColorMode failed to writeInterfaceToken: %d", result);
+            return static_cast<android_color_mode_t>(result);
+        }
+        result = data.writeStrongBinder(display);
+        if (result != NO_ERROR) {
+            ALOGE("getActiveColorMode failed to writeStrongBinder: %d", result);
+            return static_cast<android_color_mode_t>(result);
+        }
+        result = remote()->transact(BnSurfaceComposer::GET_ACTIVE_COLOR_MODE, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("getActiveColorMode failed to transact: %d", result);
+            return static_cast<android_color_mode_t>(result);
+        }
+        return static_cast<android_color_mode_t>(reply.readInt32());
+    }
+
+    virtual status_t setActiveColorMode(const sp<IBinder>& display,
+            android_color_mode_t colorMode) {
+        Parcel data, reply;
+        status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        if (result != NO_ERROR) {
+            ALOGE("setActiveColorMode failed to writeInterfaceToken: %d", result);
+            return result;
+        }
+        result = data.writeStrongBinder(display);
+        if (result != NO_ERROR) {
+            ALOGE("setActiveColorMode failed to writeStrongBinder: %d", result);
+            return result;
+        }
+        result = data.writeInt32(colorMode);
+        if (result != NO_ERROR) {
+            ALOGE("setActiveColorMode failed to writeInt32: %d", result);
+            return result;
+        }
+        result = remote()->transact(BnSurfaceComposer::SET_ACTIVE_COLOR_MODE, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("setActiveColorMode failed to transact: %d", result);
+            return result;
+        }
+        return static_cast<status_t>(reply.readInt32());
+    }
+
     virtual status_t clearAnimationFrameStats() {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -469,6 +547,56 @@
             reply->writeInt32(result);
             return NO_ERROR;
         }
+        case GET_DISPLAY_COLOR_MODES: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            Vector<android_color_mode_t> colorModes;
+            sp<IBinder> display = nullptr;
+            status_t result = data.readStrongBinder(&display);
+            if (result != NO_ERROR) {
+                ALOGE("getDisplayColorModes failed to readStrongBinder: %d", result);
+                return result;
+            }
+            result = getDisplayColorModes(display, &colorModes);
+            reply->writeInt32(result);
+            if (result == NO_ERROR) {
+                reply->writeUint32(static_cast<uint32_t>(colorModes.size()));
+                for (size_t i = 0; i < colorModes.size(); ++i) {
+                    reply->writeInt32(colorModes[i]);
+                }
+            }
+            return NO_ERROR;
+        }
+        case GET_ACTIVE_COLOR_MODE: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> display = nullptr;
+            status_t result = data.readStrongBinder(&display);
+            if (result != NO_ERROR) {
+                ALOGE("getActiveColorMode failed to readStrongBinder: %d", result);
+                return result;
+            }
+            android_color_mode_t colorMode = getActiveColorMode(display);
+            result = reply->writeInt32(static_cast<int32_t>(colorMode));
+            return result;
+        }
+        case SET_ACTIVE_COLOR_MODE: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> display = nullptr;
+            status_t result = data.readStrongBinder(&display);
+            if (result != NO_ERROR) {
+                ALOGE("getActiveColorMode failed to readStrongBinder: %d", result);
+                return result;
+            }
+            int32_t colorModeInt = 0;
+            result = data.readInt32(&colorModeInt);
+            if (result != NO_ERROR) {
+                ALOGE("setActiveColorMode failed to readInt32: %d", result);
+                return result;
+            }
+            result = setActiveColorMode(display,
+                    static_cast<android_color_mode_t>(colorModeInt));
+            result = reply->writeInt32(result);
+            return result;
+        }
         case CLEAR_ANIMATION_FRAME_STATS: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             status_t result = clearAnimationFrameStats();
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 059223d..1c460e8 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -29,6 +29,8 @@
 #include <binder/IMemory.h>
 #include <binder/IServiceManager.h>
 
+#include <system/graphics.h>
+
 #include <ui/DisplayInfo.h>
 
 #include <gui/CpuConsumer.h>
@@ -771,6 +773,20 @@
     return ComposerService::getComposerService()->setActiveConfig(display, id);
 }
 
+status_t SurfaceComposerClient::getDisplayColorModes(const sp<IBinder>& display,
+        Vector<android_color_mode_t>* outColorModes) {
+    return ComposerService::getComposerService()->getDisplayColorModes(display, outColorModes);
+}
+
+android_color_mode_t SurfaceComposerClient::getActiveColorMode(const sp<IBinder>& display) {
+    return ComposerService::getComposerService()->getActiveColorMode(display);
+}
+
+status_t SurfaceComposerClient::setActiveColorMode(const sp<IBinder>& display,
+        android_color_mode_t colorMode) {
+    return ComposerService::getComposerService()->setActiveColorMode(display, colorMode);
+}
+
 void SurfaceComposerClient::setDisplayPowerMode(const sp<IBinder>& token,
         int mode) {
     ComposerService::getComposerService()->setPowerMode(token, mode);
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 246346b..fb2b857 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -796,6 +796,11 @@
         return NO_MEMORY;
     }
 
+    if (numRects > (UINT32_MAX / sizeof(Rect))) {
+        android_errorWriteWithInfoLog(0x534e4554, "29983260", -1, NULL, 0);
+        return NO_MEMORY;
+    }
+
     Region result;
     result.mStorage.clear();
     for (size_t r = 0; r < numRects; ++r) {
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index a67b3ff..5c2c0ad 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -415,6 +415,17 @@
 }
 
 // ----------------------------------------------------------------------------
+#ifdef USE_HWC2
+void DisplayDevice::setActiveColorMode(android_color_mode_t mode) {
+    mActiveColorMode = mode;
+}
+
+android_color_mode_t DisplayDevice::getActiveColorMode() const {
+    return mActiveColorMode;
+}
+#endif
+
+// ----------------------------------------------------------------------------
 
 void DisplayDevice::setLayerStack(uint32_t stack) {
     mLayerStack = stack;
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index dd9b104..105e980 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -182,6 +182,11 @@
     void setPowerMode(int mode);
     bool isDisplayOn() const;
 
+#ifdef USE_HWC2
+    android_color_mode_t getActiveColorMode() const;
+    void setActiveColorMode(android_color_mode_t mode);
+#endif
+
     /* ------------------------------------------------------------------------
      * Display active config management.
      */
@@ -252,6 +257,10 @@
     int mPowerMode;
     // Current active config
     int mActiveConfig;
+#ifdef USE_HWC2
+    // current active color mode
+    android_color_mode_t mActiveColorMode;
+#endif
 };
 
 }; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 87a0e9a..4fe3cfd 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -581,7 +581,7 @@
     return Error::None;
 }
 
-Error Display::getColorModes(std::vector<int32_t>* outModes) const
+Error Display::getColorModes(std::vector<android_color_mode_t>* outModes) const
 {
     uint32_t numModes = 0;
     int32_t intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId,
@@ -599,7 +599,10 @@
         return error;
     }
 
-    std::swap(*outModes, modes);
+    outModes->resize(numModes);
+    for (size_t i = 0; i < numModes; i++) {
+        (*outModes)[i] = static_cast<android_color_mode_t>(modes[i]);
+    }
     return Error::None;
 }
 
@@ -805,7 +808,7 @@
     return static_cast<Error>(intError);
 }
 
-Error Display::setColorMode(int32_t mode)
+Error Display::setColorMode(android_color_mode_t mode)
 {
     int32_t intError = mDevice.mSetColorMode(mDevice.mHwcDevice, mId, mode);
     return static_cast<Error>(intError);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index beb7bc6..fb04af8 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -282,7 +282,7 @@
     [[clang::warn_unused_result]] Error getChangedCompositionTypes(
             std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes);
     [[clang::warn_unused_result]] Error getColorModes(
-            std::vector<int32_t>* outModes) const;
+            std::vector<android_color_mode_t>* outModes) const;
 
     // Doesn't call into the HWC2 device, so no errors are possible
     std::vector<std::shared_ptr<const Config>> getConfigs() const;
@@ -307,7 +307,7 @@
             buffer_handle_t target,
             const android::sp<android::Fence>& acquireFence,
             android_dataspace_t dataspace);
-    [[clang::warn_unused_result]] Error setColorMode(int32_t mode);
+    [[clang::warn_unused_result]] Error setColorMode(android_color_mode_t mode);
     [[clang::warn_unused_result]] Error setColorTransform(
             const android::mat4& matrix, android_color_transform_t hint);
     [[clang::warn_unused_result]] Error setOutputBuffer(
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
index 0528d7b..7bca0f1 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
@@ -75,7 +75,7 @@
 
 using namespace HWC2;
 
-static constexpr Attribute ColorTransform = static_cast<Attribute>(6);
+static constexpr Attribute ColorMode = static_cast<Attribute>(6);
 
 namespace android {
 
@@ -268,9 +268,7 @@
                     &Display::setClientTarget, buffer_handle_t, int32_t,
                     int32_t, hwc_region_t>);
         case FunctionDescriptor::SetColorMode:
-            return asFP<HWC2_PFN_SET_COLOR_MODE>(
-                    displayHook<decltype(&Display::setColorMode),
-                    &Display::setColorMode, int32_t>);
+            return asFP<HWC2_PFN_SET_COLOR_MODE>(setColorModeHook);
         case FunctionDescriptor::SetColorTransform:
             return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook);
         case FunctionDescriptor::SetOutputBuffer:
@@ -562,6 +560,7 @@
     mHwc1Id(-1),
     mConfigs(),
     mActiveConfig(nullptr),
+    mActiveColorMode(static_cast<android_color_mode_t>(-1)),
     mName(),
     mType(type),
     mPowerMode(PowerMode::Off),
@@ -894,7 +893,7 @@
     return Error::None;
 }
 
-Error HWC2On1Adapter::Display::setColorMode(int32_t mode)
+Error HWC2On1Adapter::Display::setColorMode(android_color_mode_t mode)
 {
     std::unique_lock<std::recursive_mutex> lock (mStateMutex);
 
@@ -1198,11 +1197,14 @@
         newConfig->setAttribute(Attribute::DpiY,
                 values[attributeMap[HWC_DISPLAY_DPI_Y]]);
         if (hasColor) {
-            newConfig->setAttribute(ColorTransform,
+            // In HWC1, color modes are referred to as color transforms. To avoid confusion with
+            // the HWC2 concept of color transforms, we internally refer to them as color modes for
+            // both HWC1 and 2.
+            newConfig->setAttribute(ColorMode,
                     values[attributeMap[HWC_DISPLAY_COLOR_TRANSFORM]]);
         }
 
-        // We can only do this after attempting to read the color transform
+        // We can only do this after attempting to read the color mode
         newConfig->setHwc1Id(hwc1ConfigId);
 
         for (auto& existingConfig : mConfigs) {
@@ -1678,8 +1680,8 @@
 
 void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id)
 {
-    int32_t colorTransform = getAttribute(ColorTransform);
-    mHwc1Ids.emplace(colorTransform, id);
+    android_color_mode_t colorMode = static_cast<android_color_mode_t>(getAttribute(ColorMode));
+    mHwc1Ids.emplace(colorMode, id);
 }
 
 bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const
@@ -1692,18 +1694,20 @@
     return false;
 }
 
-int32_t HWC2On1Adapter::Display::Config::getColorModeForHwc1Id(
-        uint32_t id) const
+Error HWC2On1Adapter::Display::Config::getColorModeForHwc1Id(
+        uint32_t id, android_color_mode_t* outMode) const
 {
     for (const auto& idPair : mHwc1Ids) {
         if (id == idPair.second) {
-            return idPair.first;
+            *outMode = idPair.first;
+            return Error::None;
         }
     }
-    return -1;
+    ALOGE("Unable to find color mode for HWC ID %" PRIu32 " on config %u", id, mId);
+    return Error::BadParameter;
 }
 
-Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(int32_t mode,
+Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(android_color_mode_t mode,
         uint32_t* outId) const
 {
     for (const auto& idPair : mHwc1Ids) {
@@ -1726,25 +1730,26 @@
             return false;
         }
     }
-    int32_t otherColorTransform = other.getAttribute(ColorTransform);
-    if (mHwc1Ids.count(otherColorTransform) != 0) {
+    android_color_mode_t otherColorMode =
+            static_cast<android_color_mode_t>(other.getAttribute(ColorMode));
+    if (mHwc1Ids.count(otherColorMode) != 0) {
         ALOGE("Attempted to merge two configs (%u and %u) which appear to be "
-                "identical", mHwc1Ids.at(otherColorTransform),
-                other.mHwc1Ids.at(otherColorTransform));
+                "identical", mHwc1Ids.at(otherColorMode),
+                other.mHwc1Ids.at(otherColorMode));
         return false;
     }
-    mHwc1Ids.emplace(otherColorTransform,
-            other.mHwc1Ids.at(otherColorTransform));
+    mHwc1Ids.emplace(otherColorMode,
+            other.mHwc1Ids.at(otherColorMode));
     return true;
 }
 
-std::set<int32_t> HWC2On1Adapter::Display::Config::getColorTransforms() const
+std::set<android_color_mode_t> HWC2On1Adapter::Display::Config::getColorModes() const
 {
-    std::set<int32_t> colorTransforms;
+    std::set<android_color_mode_t> colorModes;
     for (const auto& idPair : mHwc1Ids) {
-        colorTransforms.emplace(idPair.first);
+        colorModes.emplace(idPair.first);
     }
-    return colorTransforms;
+    return colorModes;
 }
 
 std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const
@@ -1787,15 +1792,15 @@
 
 
     for (const auto& id : mHwc1Ids) {
-        int32_t colorTransform = id.first;
+        android_color_mode_t colorMode = id.first;
         uint32_t hwc1Id = id.second;
         std::memset(buffer, 0, BUFFER_SIZE);
-        if (colorTransform == mDisplay.mActiveColorMode) {
+        if (colorMode == mDisplay.mActiveColorMode) {
             writtenBytes = snprintf(buffer, BUFFER_SIZE, " [%u/%d]", hwc1Id,
-                    colorTransform);
+                    colorMode);
         } else {
             writtenBytes = snprintf(buffer, BUFFER_SIZE, " %u/%d", hwc1Id,
-                    colorTransform);
+                    colorMode);
         }
         output.append(buffer, writtenBytes);
     }
@@ -1814,10 +1819,10 @@
 
 void HWC2On1Adapter::Display::populateColorModes()
 {
-    mColorModes = mConfigs[0]->getColorTransforms();
+    mColorModes = mConfigs[0]->getColorModes();
     for (const auto& config : mConfigs) {
-        std::set<int32_t> intersection;
-        auto configModes = config->getColorTransforms();
+        std::set<android_color_mode_t> intersection;
+        auto configModes = config->getColorModes();
         std::set_intersection(mColorModes.cbegin(), mColorModes.cend(),
                 configModes.cbegin(), configModes.cend(),
                 std::inserter(intersection, intersection.begin()));
@@ -1830,7 +1835,7 @@
     if (mDevice.mHwc1Device->getActiveConfig == nullptr) {
         ALOGV("getActiveConfig is null, choosing config 0");
         mActiveConfig = mConfigs[0];
-        mActiveColorMode = -1;
+        mActiveColorMode = HAL_COLOR_MODE_NATIVE;
         return;
     }
 
@@ -1842,7 +1847,13 @@
                 ALOGV("Setting active config to %d for HWC1 config %u",
                         config->getId(), activeConfig);
                 mActiveConfig = config;
-                mActiveColorMode = config->getColorModeForHwc1Id(activeConfig);
+                if (config->getColorModeForHwc1Id(activeConfig, &mActiveColorMode) != Error::None) {
+                    // This should never happen since we checked for the config's presence before
+                    // setting it as active.
+                    ALOGE("Unable to find color mode for active HWC1 config %d",
+                            config->getId());
+                    mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+                }
                 break;
             }
         }
@@ -1850,7 +1861,7 @@
             ALOGV("Unable to find active HWC1 config %u, defaulting to "
                     "config 0", activeConfig);
             mActiveConfig = mConfigs[0];
-            mActiveColorMode = -1;
+            mActiveColorMode = HAL_COLOR_MODE_NATIVE;
         }
     }
 }
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
index dc7c355..e447c3c 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
@@ -213,7 +213,7 @@
             HWC2::Error setClientTarget(buffer_handle_t target,
                     int32_t acquireFence, int32_t dataspace,
                     hwc_region_t damage);
-            HWC2::Error setColorMode(int32_t mode);
+            HWC2::Error setColorMode(android_color_mode_t mode);
             HWC2::Error setColorTransform(android_color_transform_t hint);
             HWC2::Error setOutputBuffer(buffer_handle_t buffer,
                     int32_t releaseFence);
@@ -247,6 +247,7 @@
                 public:
                     Config(Display& display)
                       : mDisplay(display),
+                        mId(0),
                         mAttributes() {}
 
                     bool isOnDisplay(const Display& display) const {
@@ -258,8 +259,9 @@
 
                     void setHwc1Id(uint32_t id);
                     bool hasHwc1Id(uint32_t id) const;
-                    int32_t getColorModeForHwc1Id(uint32_t id) const;
-                    HWC2::Error getHwc1IdForColorMode(int32_t mode,
+                    HWC2::Error getColorModeForHwc1Id(uint32_t id,
+                            android_color_mode_t *outMode) const;
+                    HWC2::Error getHwc1IdForColorMode(android_color_mode_t mode,
                             uint32_t* outId) const;
 
                     void setId(hwc2_config_t id) { mId = id; }
@@ -269,7 +271,7 @@
                     // mode. Returns whether the merge was successful
                     bool merge(const Config& other);
 
-                    std::set<int32_t> getColorTransforms() const;
+                    std::set<android_color_mode_t> getColorModes() const;
 
                     // splitLine divides the output into two lines suitable for
                     // dumpsys SurfaceFlinger
@@ -281,7 +283,7 @@
                     std::unordered_map<HWC2::Attribute, int32_t> mAttributes;
 
                     // Maps from color transform to HWC1 config ID
-                    std::unordered_map<int32_t, uint32_t> mHwc1Ids;
+                    std::unordered_map<android_color_mode_t, uint32_t> mHwc1Ids;
             };
 
             class Changes {
@@ -378,8 +380,8 @@
 
             std::vector<std::shared_ptr<Config>> mConfigs;
             std::shared_ptr<const Config> mActiveConfig;
-            std::set<int32_t> mColorModes;
-            int32_t mActiveColorMode;
+            std::set<android_color_mode_t> mColorModes;
+            android_color_mode_t mActiveColorMode;
             std::string mName;
             HWC2::DisplayType mType;
             HWC2::PowerMode mPowerMode;
@@ -432,6 +434,12 @@
                 hint);
     }
 
+    static int32_t setColorModeHook(hwc2_device_t* device,
+            hwc2_display_t display, int32_t /*android_color_mode_t*/ intMode) {
+        auto mode = static_cast<android_color_mode_t>(intMode);
+        return callDisplayFunction(device, display, &Display::setColorMode, mode);
+    }
+
     static int32_t setPowerModeHook(hwc2_device_t* device,
             hwc2_display_t display, int32_t intMode) {
         auto mode = static_cast<HWC2::PowerMode>(intMode);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 199848f..4ac58c5 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -364,8 +364,8 @@
     return config;
 }
 
-std::vector<int32_t> HWComposer::getColorModes(int32_t displayId) const {
-    std::vector<int32_t> modes;
+std::vector<android_color_mode_t> HWComposer::getColorModes(int32_t displayId) const {
+    std::vector<android_color_mode_t> modes;
 
     if (!isValidDisplay(displayId)) {
         ALOGE("getColorModes: Attempted to access invalid display %d",
@@ -379,12 +379,31 @@
     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<int32_t>();
+        return std::vector<android_color_mode_t>();
     }
 
     return modes;
 }
 
+status_t HWComposer::setActiveColorMode(int32_t displayId, android_color_mode_t mode) {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("setActiveColorMode: Display %d is not valid", displayId);
+        return BAD_INDEX;
+    }
+
+    auto& displayData = mDisplayData[displayId];
+    auto error = displayData.hwcDisplay->setColorMode(mode);
+    if (error != HWC2::Error::None) {
+        ALOGE("setActiveConfig: Failed to set color mode %d on display %d: "
+                "%s (%d)", mode, displayId, to_string(error).c_str(),
+                static_cast<int32_t>(error));
+        return UNKNOWN_ERROR;
+    }
+
+    return NO_ERROR;
+}
+
+
 void HWComposer::setVsyncEnabled(int32_t disp, HWC2::Vsync enabled) {
     if (disp < 0 || disp >= HWC_DISPLAY_VIRTUAL) {
         ALOGD("setVsyncEnabled: Ignoring for virtual display %d", disp);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 17676ae..41671f6 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -154,7 +154,9 @@
     std::shared_ptr<const HWC2::Display::Config>
             getActiveConfig(int32_t displayId) const;
 
-    std::vector<int32_t> getColorModes(int32_t displayId) const;
+    std::vector<android_color_mode_t> getColorModes(int32_t displayId) const;
+
+    status_t setActiveColorMode(int32_t displayId, android_color_mode_t mode);
 
     // for debugging ----------------------------------------------------------
     void dump(String8& out) const;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
index 9d92f61..2102457 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
@@ -42,6 +42,8 @@
 #include <cutils/log.h>
 #include <cutils/properties.h>
 
+#include <system/graphics.h>
+
 #include "HWComposer.h"
 
 #include "../Layer.h"           // needed only for debugging
@@ -403,7 +405,7 @@
                     config.ydpi = values[i] / 1000.0f;
                     break;
                 case HWC_DISPLAY_COLOR_TRANSFORM:
-                    config.colorTransform = values[i];
+                    config.colorMode = static_cast<android_color_mode_t>(values[i]);
                     break;
                 default:
                     ALOG_ASSERT(false, "unknown display attribute[%zu] %#x",
@@ -519,6 +521,11 @@
     return mDisplayData[disp].configs[currentConfig].refresh;
 }
 
+android_color_mode_t HWComposer::getColorMode(int disp) const {
+    size_t currentConfig = mDisplayData[disp].currentConfig;
+    return mDisplayData[disp].configs[currentConfig].colorMode;
+}
+
 const Vector<HWComposer::DisplayConfig>& HWComposer::getConfigs(int disp) const {
     return mDisplayData[disp].configs;
 }
@@ -1182,10 +1189,10 @@
             for (size_t c = 0; c < disp.configs.size(); ++c) {
                 const DisplayConfig& config(disp.configs[c]);
                 result.appendFormat("    %s%zd: %ux%u, xdpi=%f, ydpi=%f"
-                        ", refresh=%" PRId64 ", colorTransform=%d\n",
+                        ", refresh=%" PRId64 ", colorMode=%d\n",
                         c == disp.currentConfig ? "* " : "", c,
                         config.width, config.height, config.xdpi, config.ydpi,
-                        config.refresh, config.colorTransform);
+                        config.refresh, config.colorMode);
             }
 
             if (disp.list) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
index c861817..170e382 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
@@ -22,6 +22,8 @@
 
 #include <hardware/hwcomposer_defs.h>
 
+#include <system/graphics.h>
+
 #include <ui/Fence.h>
 
 #include <utils/BitSet.h>
@@ -257,7 +259,15 @@
         float xdpi;
         float ydpi;
         nsecs_t refresh;
-        int colorTransform;
+        android_color_mode_t colorMode;
+        bool operator==(const DisplayConfig& rhs) const {
+            return width == rhs.width &&
+                    height == rhs.height &&
+                    xdpi == rhs.xdpi &&
+                    ydpi == rhs.ydpi &&
+                    refresh == rhs.refresh &&
+                    colorMode == rhs.colorMode;
+        }
     };
 
     // Query display parameters.  Pass in a display index (e.g.
@@ -274,6 +284,7 @@
     float getDpiX(int disp) const;
     float getDpiY(int disp) const;
     nsecs_t getRefreshPeriod(int disp) const;
+    android_color_mode_t getColorMode(int disp) const;
 
     const Vector<DisplayConfig>& getConfigs(int disp) const;
     size_t getCurrentConfig(int disp) const;
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index dd88adb..bdd94e3 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -226,6 +226,7 @@
             timestamp = mVSyncEvent[i].header.timestamp;
             if (timestamp) {
                 // we have a vsync event to dispatch
+                mFlinger.mInterceptor.saveVSyncEvent(timestamp);
                 *event = mVSyncEvent[i];
                 mVSyncEvent[i].header.timestamp = 0;
                 vsyncCount = mVSyncEvent[i].vsync.count;
diff --git a/services/surfaceflinger/GpuService.cpp b/services/surfaceflinger/GpuService.cpp
index b981180..b993dfb 100644
--- a/services/surfaceflinger/GpuService.cpp
+++ b/services/surfaceflinger/GpuService.cpp
@@ -92,82 +92,27 @@
     }
     fprintf(outs,
         "GPU Service commands:\n"
-        "  vkjson   dump Vulkan device capabilities as JSON\n");
+        "  vkjson   dump Vulkan properties as JSON\n");
     fclose(outs);
     return NO_ERROR;
 }
 
-VkResult vkjsonPrint(FILE* out, FILE* err) {
-    VkResult result;
-
-    const VkApplicationInfo app_info = {
-        VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr,
-        "vkjson", 1,    /* app name, version */
-        "", 0,          /* engine name, version */
-        VK_API_VERSION_1_0
-    };
-    const VkInstanceCreateInfo instance_info = {
-        VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, nullptr,
-        0,              /* flags */
-        &app_info,
-        0, nullptr,     /* layers */
-        0, nullptr,     /* extensions */
-    };
-    VkInstance instance;
-    result = vkCreateInstance(&instance_info, nullptr, &instance);
-    if (result != VK_SUCCESS) {
-        fprintf(err, "vkCreateInstance failed: %d\n", result);
-        return result;
-    }
-
-    uint32_t ngpu = 0;
-    result = vkEnumeratePhysicalDevices(instance, &ngpu, nullptr);
-    if (result != VK_SUCCESS) {
-        fprintf(err, "vkEnumeratePhysicalDevices failed: %d\n", result);
-        return result;
-    }
-    std::vector<VkPhysicalDevice> gpus(ngpu, VK_NULL_HANDLE);
-    result = vkEnumeratePhysicalDevices(instance, &ngpu, gpus.data());
-    if (result != VK_SUCCESS) {
-        fprintf(err, "vkEnumeratePhysicalDevices failed: %d\n", result);
-        return result;
-    }
-
-    for (size_t i = 0, n = gpus.size(); i < n; i++) {
-        auto props = VkJsonGetAllProperties(gpus[i]);
-        std::string json = VkJsonAllPropertiesToJson(props);
-        fwrite(json.data(), 1, json.size(), out);
-        if (i < n - 1)
-            fputc(',', out);
-        fputc('\n', out);
-    }
-
-    vkDestroyInstance(instance, nullptr);
-
-    return VK_SUCCESS;
+void vkjsonPrint(FILE* out) {
+    std::string json = VkJsonInstanceToJson(VkJsonGetInstance());
+    fwrite(json.data(), 1, json.size(), out);
+    fputc('\n', out);
 }
 
-status_t cmd_vkjson(int out, int err) {
-    int errnum;
+status_t cmd_vkjson(int out, int /*err*/) {
     FILE* outs = fdopen(out, "w");
     if (!outs) {
-        errnum = errno;
+        int errnum = errno;
         ALOGE("vkjson: failed to create output stream: %s", strerror(errnum));
         return -errnum;
     }
-    FILE* errs = fdopen(err, "w");
-    if (!errs) {
-        errnum = errno;
-        ALOGE("vkjson: failed to create error stream: %s", strerror(errnum));
-        fclose(outs);
-        return -errnum;
-    }
-    fprintf(outs, "[\n");
-    VkResult result = vkjsonPrint(outs, errs);
-    fprintf(outs, "]\n");
-    fclose(errs);
+    vkjsonPrint(outs);
     fclose(outs);
-    return result >= 0 ? NO_ERROR : UNKNOWN_ERROR;
+    return NO_ERROR;
 }
 
 } // anonymous namespace
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6024fa9..d00791d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -51,6 +51,8 @@
 
 #include "RenderEngine/RenderEngine.h"
 
+#include <mutex>
+
 #define DEBUG_RESIZE    0
 
 namespace android {
@@ -153,10 +155,9 @@
     // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
     sp<IGraphicBufferProducer> producer;
     sp<IGraphicBufferConsumer> consumer;
-    BufferQueue::createBufferQueue(&producer, &consumer);
+    BufferQueue::createBufferQueue(&producer, &consumer, nullptr, true);
     mProducer = new MonitoredProducer(producer, mFlinger);
-    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName,
-            this);
+    mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName, this);
     mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
     mSurfaceFlingerConsumer->setContentsChangedListener(this);
     mSurfaceFlingerConsumer->setName(mName);
@@ -210,7 +211,8 @@
     // Add this buffer from our internal queue tracker
     { // Autolock scope
         Mutex::Autolock lock(mQueueItemLock);
-
+        mFlinger->mInterceptor.saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
+                item.mGraphicBuffer->getHeight(), item.mFrameNumber);
         // Reset the frame number tracker when we receive the first buffer after
         // a frame number reset
         if (item.mFrameNumber == 1) {
@@ -310,22 +312,6 @@
     return NO_ERROR;
 }
 
-/*
- * The layer handle is just a BBinder object passed to the client
- * (remote process) -- we don't keep any reference on our side such that
- * the dtor is called when the remote side let go of its reference.
- *
- * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
- * this layer when the handle is destroyed.
- */
-class Layer::Handle : public BBinder, public LayerCleaner {
-    public:
-        Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
-            : LayerCleaner(flinger, layer), owner(layer) {}
-
-        wp<Layer> owner;
-};
-
 sp<IBinder> Layer::getHandle() {
     Mutex::Autolock _l(mLock);
 
@@ -1089,6 +1075,20 @@
     return static_cast<uint32_t>(producerStickyTransform);
 }
 
+bool Layer::latchUnsignaledBuffers() {
+    static bool propertyLoaded = false;
+    static bool latch = false;
+    static std::mutex mutex;
+    std::lock_guard<std::mutex> lock(mutex);
+    if (!propertyLoaded) {
+        char value[PROPERTY_VALUE_MAX] = {};
+        property_get("debug.sf.latch_unsignaled", value, "0");
+        latch = atoi(value);
+        propertyLoaded = true;
+    }
+    return latch;
+}
+
 uint64_t Layer::getHeadFrameNumber() const {
     Mutex::Autolock lock(mQueueItemLock);
     if (!mQueueItems.empty()) {
@@ -1100,6 +1100,10 @@
 
 bool Layer::headFenceHasSignaled() const {
 #ifdef USE_HWC2
+    if (latchUnsignaledBuffers()) {
+        return true;
+    }
+
     Mutex::Autolock lock(mQueueItemLock);
     if (mQueueItems.empty()) {
         return true;
@@ -2236,17 +2240,6 @@
 
 // ---------------------------------------------------------------------------
 
-Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
-        const sp<Layer>& layer)
-    : mFlinger(flinger), mLayer(layer) {
-}
-
-Layer::LayerCleaner::~LayerCleaner() {
-    // destroy client resources
-    mFlinger->onLayerDestroyed(mLayer);
-}
-
-// ---------------------------------------------------------------------------
 }; // namespace android
 
 #if defined(__gl_h_)
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 78a8427..a63656e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -180,11 +180,6 @@
     Rect computeBounds(const Region& activeTransparentRegion) const;
     Rect computeBounds() const;
 
-    class Handle;
-    sp<IBinder> getHandle();
-    sp<IGraphicBufferProducer> getProducer() const;
-    const String8& getName() const;
-
     int32_t getSequence() const { return sequence; }
 
     // -----------------------------------------------------------------------
@@ -423,9 +418,6 @@
 protected:
     // constant
     sp<SurfaceFlinger> mFlinger;
-
-    virtual void onFirstRef();
-
     /*
      * Trivial class, used to ensure that mFlinger->onLayerDestroyed(mLayer)
      * is called.
@@ -434,13 +426,24 @@
         sp<SurfaceFlinger> mFlinger;
         wp<Layer> mLayer;
     protected:
-        ~LayerCleaner();
+        ~LayerCleaner() {
+            // destroy client resources
+            mFlinger->onLayerDestroyed(mLayer);
+        }
     public:
-        LayerCleaner(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer);
+        LayerCleaner(const sp<SurfaceFlinger>& flinger,
+                const sp<Layer>& layer)
+            : mFlinger(flinger), mLayer(layer) {
+        }
     };
 
 
+    virtual void onFirstRef();
+
+
+
 private:
+    friend class SurfaceInterceptor;
     // Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener
     virtual void onFrameAvailable(const BufferItem& item) override;
     virtual void onFrameReplaced(const BufferItem& item) override;
@@ -465,6 +468,9 @@
     // Temporary - Used only for LEGACY camera mode.
     uint32_t getProducerStickyTransform() const;
 
+    // Loads the corresponding system property once per process
+    static bool latchUnsignaledBuffers();
+
     // -----------------------------------------------------------------------
 
     class SyncPoint
@@ -524,6 +530,25 @@
     // the Surface Controller) if set.
     uint32_t getEffectiveScalingMode() const;
 public:
+    /*
+     * The layer handle is just a BBinder object passed to the client
+     * (remote process) -- we don't keep any reference on our side such that
+     * the dtor is called when the remote side let go of its reference.
+     *
+     * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
+     * this layer when the handle is destroyed.
+     */
+    class Handle : public BBinder, public LayerCleaner {
+        public:
+            Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
+                : LayerCleaner(flinger, layer), owner(layer) {}
+
+            wp<Layer> owner;
+    };
+
+    sp<IBinder> getHandle();
+    sp<IGraphicBufferProducer> getProducer() const;
+    const String8& getName() const;
     void notifyAvailableFrames();
 private:
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5583f0a..72ad53d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -162,6 +162,7 @@
         mLastTransactionTime(0),
         mBootFinished(false),
         mForceFullDamage(false),
+        mInterceptor(),
         mPrimaryDispSync("PrimaryDispSync"),
         mPrimaryHWVsyncEnabled(false),
         mHWVsyncAvailable(false),
@@ -192,6 +193,10 @@
     }
     ALOGI_IF(mDebugRegion, "showupdates enabled");
     ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
+
+    property_get("debug.sf.disable_backpressure", value, "0");
+    mPropagateBackpressure = !atoi(value);
+    ALOGI_IF(!mPropagateBackpressure, "Disabling backpressure propagation");
 }
 
 void SurfaceFlinger::onFirstRef()
@@ -644,18 +649,7 @@
         // All non-virtual displays are currently considered secure.
         info.secure = true;
 
-        // DisplayManager expects each color mode to be its own display
-        // info record.
-        std::vector<int32_t> modes = getHwComposer().getColorModes(type);
-
-        if (modes.size() == 0) {
-            info.colorTransform = 0;
-            configs->push_back(info);
-        }
-        for (int32_t mode : modes) {
-            info.colorTransform = mode;
-            configs->push_back(info);
-        }
+        configs->push_back(info);
     }
 
     return NO_ERROR;
@@ -717,6 +711,7 @@
             if (mMode < 0 || mMode >= static_cast<int>(configs.size())) {
                 ALOGE("Attempt to set active config = %d for display with %zu configs",
                         mMode, configs.size());
+                return true;
             }
             sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
             if (hw == NULL) {
@@ -735,6 +730,101 @@
     postMessageSync(msg);
     return NO_ERROR;
 }
+status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& display,
+        Vector<android_color_mode_t>* outColorModes) {
+    if ((outColorModes == nullptr) || (display.get() == nullptr)) {
+        return BAD_VALUE;
+    }
+
+    if (!display.get()) {
+        return NAME_NOT_FOUND;
+    }
+
+    int32_t type = NAME_NOT_FOUND;
+    for (int i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
+        if (display == mBuiltinDisplays[i]) {
+            type = i;
+            break;
+        }
+    }
+
+    if (type < 0) {
+        return type;
+    }
+
+    std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(type);
+    outColorModes->clear();
+    std::copy(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes));
+
+    return NO_ERROR;
+}
+
+android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp<IBinder>& display) {
+    sp<DisplayDevice> device(getDisplayDevice(display));
+    if (device != nullptr) {
+        return device->getActiveColorMode();
+    }
+    return static_cast<android_color_mode_t>(BAD_VALUE);
+}
+
+void SurfaceFlinger::setActiveColorModeInternal(const sp<DisplayDevice>& hw,
+        android_color_mode_t mode) {
+    ALOGD("Set active color mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
+          this);
+    int32_t type = hw->getDisplayType();
+    android_color_mode_t currentMode = hw->getActiveColorMode();
+
+    if (mode == currentMode) {
+        ALOGD("Screen type=%d is already in color mode=%d", hw->getDisplayType(), mode);
+        return;
+    }
+
+    if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
+        ALOGW("Trying to set config for virtual display");
+        return;
+    }
+
+    hw->setActiveColorMode(mode);
+    getHwComposer().setActiveColorMode(type, mode);
+}
+
+
+status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& display,
+        android_color_mode_t colorMode) {
+    class MessageSetActiveColorMode: public MessageBase {
+        SurfaceFlinger& mFlinger;
+        sp<IBinder> mDisplay;
+        android_color_mode_t mMode;
+    public:
+        MessageSetActiveColorMode(SurfaceFlinger& flinger, const sp<IBinder>& disp,
+                               android_color_mode_t mode) :
+            mFlinger(flinger), mDisplay(disp) { mMode = mode; }
+        virtual bool handler() {
+            Vector<android_color_mode_t> modes;
+            mFlinger.getDisplayColorModes(mDisplay, &modes);
+            bool exists = std::find(std::begin(modes), std::end(modes), mMode) != std::end(modes);
+            if (mMode < 0 || !exists) {
+                ALOGE("Attempt to set invalid active color mode = %d for display %p", mMode,
+                        mDisplay.get());
+                return true;
+            }
+            sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
+            if (hw == nullptr) {
+                ALOGE("Attempt to set active color mode = %d for null display %p",
+                        mMode, mDisplay.get());
+            } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
+                ALOGW("Attempt to set active color mode= %d for virtual display",
+                        mMode);
+            } else {
+                mFlinger.setActiveColorModeInternal(hw, mMode);
+            }
+            return true;
+        }
+    };
+    sp<MessageBase> msg = new MessageSetActiveColorMode(*this, display, colorMode);
+    postMessageSync(msg);
+    return NO_ERROR;
+}
 
 status_t SurfaceFlinger::clearAnimationFrameStats() {
     Mutex::Autolock _l(mStateLock);
@@ -937,7 +1027,7 @@
                     mPreviousPresentFence != Fence::NO_FENCE &&
                     mPreviousPresentFence->getSignalTime() == INT64_MAX;
             ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
-            if (frameMissed) {
+            if (mPropagateBackpressure && frameMissed) {
                 signalLayerUpdate();
                 break;
             }
@@ -2213,6 +2303,8 @@
     }
 
     if (transactionFlags) {
+        mInterceptor.saveLayerUpdates(state, flags);
+
         // this triggers the transaction
         setTransactionFlags(transactionFlags);
 
@@ -2373,7 +2465,6 @@
         uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
         sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp)
 {
-    //ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string());
     if (int32_t(w|h) < 0) {
         ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
                 int(w), int(h));
@@ -2408,6 +2499,7 @@
     if (result != NO_ERROR) {
         return result;
     }
+    mInterceptor.saveLayerCreate(layer);
 
     setTransactionFlags(eTransactionNeeded);
     return result;
@@ -2455,6 +2547,7 @@
     status_t err = NO_ERROR;
     sp<Layer> l(client->getLayerUser(handle));
     if (l != NULL) {
+        mInterceptor.saveLayerDelete(l);
         err = removeLayer(l);
         ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
                 "error removing layer=%p (%s)", l.get(), strerror(-err));
@@ -3185,6 +3278,18 @@
                 mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
                 return NO_ERROR;
             }
+            case 1020: { // Layer updates interceptor
+                n = data.readInt32();
+                if (n) {
+                    ALOGV("Interceptor enabled");
+                    mInterceptor.enable(mDrawingState.layersSortedByZ);
+                }
+                else{
+                    ALOGV("Interceptor disabled");
+                    mInterceptor.disable();
+                }
+                return NO_ERROR;
+            }
         }
     }
     return err;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f063aaf..c38f688 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -46,6 +46,8 @@
 
 #include <hardware/hwcomposer_defs.h>
 
+#include <system/graphics.h>
+
 #include <private/gui/LayerState.h>
 
 #include "Barrier.h"
@@ -54,6 +56,7 @@
 #include "FenceTracker.h"
 #include "FrameTracker.h"
 #include "MessageQueue.h"
+#include "SurfaceInterceptor.h"
 
 #include "DisplayHardware/HWComposer.h"
 #include "Effects/Daltonizer.h"
@@ -146,6 +149,7 @@
 private:
     friend class Client;
     friend class DisplayEventConnection;
+    friend class EventThread;
     friend class Layer;
     friend class MonitoredProducer;
 
@@ -222,6 +226,10 @@
     virtual status_t getDisplayConfigs(const sp<IBinder>& display,
             Vector<DisplayInfo>* configs);
     virtual int getActiveConfig(const sp<IBinder>& display);
+    virtual status_t getDisplayColorModes(const sp<IBinder>& display,
+            Vector<android_color_mode_t>* configs);
+    virtual android_color_mode_t getActiveColorMode(const sp<IBinder>& display);
+    virtual status_t setActiveColorMode(const sp<IBinder>& display, android_color_mode_t colorMode);
     virtual void setPowerMode(const sp<IBinder>& display, int mode);
     virtual status_t setActiveConfig(const sp<IBinder>& display, int id);
     virtual status_t clearAnimationFrameStats();
@@ -260,6 +268,9 @@
     // called on the main thread in response to setPowerMode()
     void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode);
 
+    // Called on the main thread in response to setActiveColorMode()
+    void setActiveColorModeInternal(const sp<DisplayDevice>& hw, android_color_mode_t colorMode);
+
     // Returns whether the transaction actually modified any state
     bool handleMessageTransaction();
 
@@ -368,6 +379,16 @@
         return mDisplays.valueFor(dpy);
     }
 
+    int32_t getDisplayType(const sp<IBinder>& display) {
+        if (!display.get()) return NAME_NOT_FOUND;
+        for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) {
+            if (display == mBuiltinDisplays[i]) {
+                return i;
+            }
+        }
+        return NAME_NOT_FOUND;
+    }
+
     // mark a region of a layer stack dirty. this updates the dirty
     // region of all screens presenting this layer stack.
     void invalidateLayerStack(uint32_t layerStack, const Region& dirty);
@@ -507,6 +528,10 @@
     bool mBootFinished;
     bool mForceFullDamage;
     FenceTracker mFenceTracker;
+#ifdef USE_HWC2
+    bool mPropagateBackpressure = true;
+#endif
+    SurfaceInterceptor mInterceptor;
 
     // these are thread safe
     mutable MessageQueue mEventQueue;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 4ddad94..123407c 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -59,6 +59,8 @@
 #include <private/android_filesystem_config.h>
 #include <private/gui/SyncFeatures.h>
 
+#include <set>
+
 #include "Client.h"
 #include "clz.h"
 #include "Colorizer.h"
@@ -161,6 +163,7 @@
         mLastTransactionTime(0),
         mBootFinished(false),
         mForceFullDamage(false),
+        mInterceptor(),
         mPrimaryDispSync("PrimaryDispSync"),
         mPrimaryHWVsyncEnabled(false),
         mHWVsyncAvailable(false),
@@ -587,20 +590,8 @@
         return BAD_VALUE;
     }
 
-    if (!display.get())
-        return NAME_NOT_FOUND;
-
-    int32_t type = NAME_NOT_FOUND;
-    for (int i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
-        if (display == mBuiltinDisplays[i]) {
-            type = i;
-            break;
-        }
-    }
-
-    if (type < 0) {
-        return type;
-    }
+    int32_t type = getDisplayType(display);
+    if (type < 0) return type;
 
     // TODO: Not sure if display density should handled by SF any longer
     class Density {
@@ -662,7 +653,6 @@
         info.ydpi = ydpi;
         info.fps = float(1e9 / hwConfig.refresh);
         info.appVsyncOffset = VSYNC_EVENT_PHASE_OFFSET_NS;
-        info.colorTransform = hwConfig.colorTransform;
 
         // This is how far in advance a buffer must be queued for
         // presentation at a given time.  If you want a buffer to appear
@@ -763,6 +753,55 @@
     return NO_ERROR;
 }
 
+status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& display,
+        Vector<android_color_mode_t>* outColorModes) {
+    if (outColorModes == nullptr || display.get() == nullptr) {
+        return BAD_VALUE;
+    }
+
+    int32_t type = getDisplayType(display);
+    if (type < 0) return type;
+
+    std::set<android_color_mode_t> colorModes;
+    for (const HWComposer::DisplayConfig& hwConfig : getHwComposer().getConfigs(type)) {
+        colorModes.insert(hwConfig.colorMode);
+    }
+
+    outColorModes->clear();
+    std::copy(colorModes.cbegin(), colorModes.cend(), std::back_inserter(*outColorModes));
+
+    return NO_ERROR;
+}
+
+android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp<IBinder>& display) {
+    if (display.get() == nullptr) return static_cast<android_color_mode_t>(BAD_VALUE);
+
+    int32_t type = getDisplayType(display);
+    if (type < 0) return static_cast<android_color_mode_t>(type);
+
+    return getHwComposer().getColorMode(type);
+}
+
+status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& display,
+        android_color_mode_t colorMode) {
+    if (display.get() == nullptr || colorMode < 0) {
+        return BAD_VALUE;
+    }
+
+    int32_t type = getDisplayType(display);
+    if (type < 0) return type;
+    const Vector<HWComposer::DisplayConfig>& hwConfigs = getHwComposer().getConfigs(type);
+    HWComposer::DisplayConfig desiredConfig = hwConfigs[getHwComposer().getCurrentConfig(type)];
+    desiredConfig.colorMode = colorMode;
+    for (size_t c = 0; c < hwConfigs.size(); ++c) {
+        const HWComposer::DisplayConfig config = hwConfigs[c];
+        if (config == desiredConfig) {
+            return setActiveConfig(display, c);
+        }
+    }
+    return BAD_VALUE;
+}
+
 status_t SurfaceFlinger::clearAnimationFrameStats() {
     Mutex::Autolock _l(mStateLock);
     mAnimFrameTracker.clearStats();
@@ -2186,6 +2225,8 @@
     }
 
     if (transactionFlags) {
+        mInterceptor.saveLayerUpdates(state, flags);
+
         // this triggers the transaction
         setTransactionFlags(transactionFlags);
 
@@ -2346,7 +2387,6 @@
         uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
         sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp)
 {
-    //ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string());
     if (int32_t(w|h) < 0) {
         ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
                 int(w), int(h));
@@ -2381,6 +2421,7 @@
     if (result != NO_ERROR) {
         return result;
     }
+    mInterceptor.saveLayerCreate(layer);
 
     setTransactionFlags(eTransactionNeeded);
     return result;
@@ -2428,6 +2469,7 @@
     status_t err = NO_ERROR;
     sp<Layer> l(client->getLayerUser(handle));
     if (l != NULL) {
+        mInterceptor.saveLayerDelete(l);
         err = removeLayer(l);
         ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
                 "error removing layer=%p (%s)", l.get(), strerror(-err));
@@ -3155,6 +3197,18 @@
                 mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
                 return NO_ERROR;
             }
+            case 1020: { // Layer updates interceptor
+                n = data.readInt32();
+                if (n) {
+                    ALOGV("Interceptor enabled");
+                    mInterceptor.enable(mDrawingState.layersSortedByZ);
+                }
+                else{
+                    ALOGV("Interceptor disabled");
+                    mInterceptor.disable();
+                }
+                return NO_ERROR;
+            }
         }
     }
     return err;
diff --git a/vulkan/libvulkan/Android.mk b/vulkan/libvulkan/Android.mk
index d2e28ff..4d2cffc 100644
--- a/vulkan/libvulkan/Android.mk
+++ b/vulkan/libvulkan/Android.mk
@@ -25,7 +25,9 @@
 	-Weverything -Werror \
 	-Wno-padded \
 	-Wno-switch-enum \
-	-Wno-undef
+	-Wno-undef \
+	-Wno-cast-calling-convention
+
 #LOCAL_CFLAGS += -DLOG_NDEBUG=0
 LOCAL_CPPFLAGS := -std=c++14 \
 	-Wno-c99-extensions \