Merge "Restore ability of system to screenshot secure layers."
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index b97df35..143192e 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -831,28 +831,30 @@
     }
 }
 
+static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
+
 static void DoLogcat() {
     unsigned long timeout_ms;
     // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
     // calculate timeout
     timeout_ms = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
-    if (timeout_ms < 20000) {
-        timeout_ms = 20000;
+    if (timeout_ms < MINIMUM_LOGCAT_TIMEOUT_MS) {
+        timeout_ms = MINIMUM_LOGCAT_TIMEOUT_MS;
     }
     RunCommand("SYSTEM LOG",
                {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
                CommandOptions::WithTimeoutInMs(timeout_ms).Build());
     timeout_ms = logcat_timeout("events");
-    if (timeout_ms < 20000) {
-        timeout_ms = 20000;
+    if (timeout_ms < MINIMUM_LOGCAT_TIMEOUT_MS) {
+        timeout_ms = MINIMUM_LOGCAT_TIMEOUT_MS;
     }
     RunCommand("EVENT LOG",
                {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid",
                         "-d", "*:v"},
                CommandOptions::WithTimeoutInMs(timeout_ms).Build());
     timeout_ms = logcat_timeout("radio");
-    if (timeout_ms < 20000) {
-        timeout_ms = 20000;
+    if (timeout_ms < MINIMUM_LOGCAT_TIMEOUT_MS) {
+        timeout_ms = MINIMUM_LOGCAT_TIMEOUT_MS;
     }
     RunCommand("RADIO LOG",
                {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid",
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index c713e9e..7ee4d49 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -92,6 +92,7 @@
         "FrameTimestamps.cpp",
         "GLConsumer.cpp",
         "GuiConfig.cpp",
+        "HdrMetadata.cpp",
         "IDisplayEventConnection.cpp",
         "IConsumerListener.cpp",
         "IGraphicBufferConsumer.cpp",
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index 69b5962..f7409dc 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -98,6 +98,7 @@
         size = FlattenableUtils::align<4>(size);
     }
     size += mSurfaceDamage.getFlattenedSize();
+    size += mHdrMetadata.getFlattenedSize();
     size = FlattenableUtils::align<8>(size);
     return size + getPodSize();
 }
@@ -151,6 +152,10 @@
     if (err) return err;
     FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize());
 
+    err = mHdrMetadata.flatten(buffer, size);
+    if (err) return err;
+    FlattenableUtils::advance(buffer, size, mHdrMetadata.getFlattenedSize());
+
     // Check we still have enough space
     if (size < getPodSize()) {
         return NO_MEMORY;
@@ -212,6 +217,10 @@
     if (err) return err;
     FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize());
 
+    err = mHdrMetadata.unflatten(buffer, size);
+    if (err) return err;
+    FlattenableUtils::advance(buffer, size, mHdrMetadata.getFlattenedSize());
+
     // Check we still have enough space
     if (size < getPodSize()) {
         return NO_MEMORY;
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index c5cab2d..add857c 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -765,6 +765,7 @@
             &crop, &scalingMode, &transform, &acquireFence, &stickyTransform,
             &getFrameTimestamps);
     const Region& surfaceDamage = input.getSurfaceDamage();
+    const HdrMetadata& hdrMetadata = input.getHdrMetadata();
 
     if (acquireFence == NULL) {
         BQ_LOGE("queueBuffer: fence is NULL");
@@ -825,9 +826,9 @@
         }
 
         BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 " dataSpace=%d"
-                " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
-                slot, mCore->mFrameCounter + 1, requestedPresentTimestamp,
-                dataSpace, crop.left, crop.top, crop.right, crop.bottom,
+                " validHdrMetadataTypes=0x%x crop=[%d,%d,%d,%d] transform=%#x scale=%s",
+                slot, mCore->mFrameCounter + 1, requestedPresentTimestamp, dataSpace,
+                hdrMetadata.validTypes, crop.left, crop.top, crop.right, crop.bottom,
                 transform,
                 BufferItem::scalingModeName(static_cast<uint32_t>(scalingMode)));
 
@@ -866,6 +867,7 @@
         item.mTimestamp = requestedPresentTimestamp;
         item.mIsAutoTimestamp = isAutoTimestamp;
         item.mDataSpace = dataSpace;
+        item.mHdrMetadata = hdrMetadata;
         item.mFrameNumber = currentFrameNumber;
         item.mSlot = slot;
         item.mFence = acquireFence;
diff --git a/libs/gui/HdrMetadata.cpp b/libs/gui/HdrMetadata.cpp
new file mode 100644
index 0000000..299bdfa
--- /dev/null
+++ b/libs/gui/HdrMetadata.cpp
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#include <gui/HdrMetadata.h>
+
+namespace android {
+
+size_t HdrMetadata::getFlattenedSize() const {
+    size_t size = sizeof(validTypes);
+    if (validTypes & SMPTE2086) {
+        size += sizeof(smpte2086);
+    }
+    if (validTypes & CTA861_3) {
+        size += sizeof(cta8613);
+    }
+    return size;
+}
+
+status_t HdrMetadata::flatten(void* buffer, size_t size) const {
+    if (size < getFlattenedSize()) {
+        return NO_MEMORY;
+    }
+
+    FlattenableUtils::write(buffer, size, validTypes);
+    if (validTypes & SMPTE2086) {
+        FlattenableUtils::write(buffer, size, smpte2086);
+    }
+    if (validTypes & CTA861_3) {
+        FlattenableUtils::write(buffer, size, cta8613);
+    }
+
+    return NO_ERROR;
+}
+
+status_t HdrMetadata::unflatten(void const* buffer, size_t size) {
+    if (size < sizeof(validTypes)) {
+        return NO_MEMORY;
+    }
+    FlattenableUtils::read(buffer, size, validTypes);
+    if (validTypes & SMPTE2086) {
+        if (size < sizeof(smpte2086)) {
+            return NO_MEMORY;
+        }
+        FlattenableUtils::read(buffer, size, smpte2086);
+    }
+    if (validTypes & CTA861_3) {
+        if (size < sizeof(cta8613)) {
+            return NO_MEMORY;
+        }
+        FlattenableUtils::read(buffer, size, cta8613);
+    }
+
+    return NO_ERROR;
+}
+
+} // namespace android
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 71e22ce..7e49024 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -951,7 +951,8 @@
 size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
     return minFlattenedSize() +
             fence->getFlattenedSize() +
-            surfaceDamage.getFlattenedSize();
+            surfaceDamage.getFlattenedSize() +
+            hdrMetadata.getFlattenedSize();
 }
 
 size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
@@ -978,7 +979,12 @@
     if (result != NO_ERROR) {
         return result;
     }
-    return surfaceDamage.flatten(buffer, size);
+    result = surfaceDamage.flatten(buffer, size);
+    if (result != NO_ERROR) {
+        return result;
+    }
+    FlattenableUtils::advance(buffer, size, surfaceDamage.getFlattenedSize());
+    return hdrMetadata.flatten(buffer, size);
 }
 
 status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
@@ -1002,7 +1008,12 @@
     if (result != NO_ERROR) {
         return result;
     }
-    return surfaceDamage.unflatten(buffer, size);
+    result = surfaceDamage.unflatten(buffer, size);
+    if (result != NO_ERROR) {
+        return result;
+    }
+    FlattenableUtils::advance(buffer, size, surfaceDamage.getFlattenedSize());
+    return hdrMetadata.unflatten(buffer, size);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 80216bc..a4aec6e 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -667,6 +667,9 @@
             mDataSpace, crop, mScalingMode, mTransform ^ mStickyTransform,
             fence, mStickyTransform, mEnableFrameTimestamps);
 
+    // we should send HDR metadata as needed if this becomes a bottleneck
+    input.setHdrMetadata(mHdrMetadata);
+
     if (mConnectedToCpu || mDirtyRegion.bounds() == Rect::INVALID_RECT) {
         input.setSurfaceDamage(Region::INVALID_REGION);
     } else {
@@ -944,6 +947,12 @@
     case NATIVE_WINDOW_SET_BUFFERS_DATASPACE:
         res = dispatchSetBuffersDataSpace(args);
         break;
+    case NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA:
+        res = dispatchSetBuffersSmpte2086Metadata(args);
+        break;
+    case NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA:
+        res = dispatchSetBuffersCta8613Metadata(args);
+        break;
     case NATIVE_WINDOW_SET_SURFACE_DAMAGE:
         res = dispatchSetSurfaceDamage(args);
         break;
@@ -1088,6 +1097,18 @@
     return setBuffersDataSpace(dataspace);
 }
 
+int Surface::dispatchSetBuffersSmpte2086Metadata(va_list args) {
+    const android_smpte2086_metadata* metadata =
+        va_arg(args, const android_smpte2086_metadata*);
+    return setBuffersSmpte2086Metadata(metadata);
+}
+
+int Surface::dispatchSetBuffersCta8613Metadata(va_list args) {
+    const android_cta861_3_metadata* metadata =
+        va_arg(args, const android_cta861_3_metadata*);
+    return setBuffersCta8613Metadata(metadata);
+}
+
 int Surface::dispatchSetSurfaceDamage(va_list args) {
     android_native_rect_t* rects = va_arg(args, android_native_rect_t*);
     size_t numRects = va_arg(args, size_t);
@@ -1512,6 +1533,30 @@
     return NO_ERROR;
 }
 
+int Surface::setBuffersSmpte2086Metadata(const android_smpte2086_metadata* metadata) {
+    ALOGV("Surface::setBuffersSmpte2086Metadata");
+    Mutex::Autolock lock(mMutex);
+    if (metadata) {
+        mHdrMetadata.smpte2086 = *metadata;
+        mHdrMetadata.validTypes |= HdrMetadata::SMPTE2086;
+    } else {
+        mHdrMetadata.validTypes &= ~HdrMetadata::SMPTE2086;
+    }
+    return NO_ERROR;
+}
+
+int Surface::setBuffersCta8613Metadata(const android_cta861_3_metadata* metadata) {
+    ALOGV("Surface::setBuffersCta8613Metadata");
+    Mutex::Autolock lock(mMutex);
+    if (metadata) {
+        mHdrMetadata.cta8613 = *metadata;
+        mHdrMetadata.validTypes |= HdrMetadata::CTA861_3;
+    } else {
+        mHdrMetadata.validTypes &= ~HdrMetadata::CTA861_3;
+    }
+    return NO_ERROR;
+}
+
 android_dataspace_t Surface::getBuffersDataSpace() {
     ALOGV("Surface::getBuffersDataSpace");
     Mutex::Autolock lock(mMutex);
diff --git a/libs/gui/include/gui/BufferItem.h b/libs/gui/include/gui/BufferItem.h
index 55637a9..7740b9f 100644
--- a/libs/gui/include/gui/BufferItem.h
+++ b/libs/gui/include/gui/BufferItem.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_GUI_BUFFERITEM_H
 #define ANDROID_GUI_BUFFERITEM_H
 
+#include <gui/HdrMetadata.h>
+
 #include <ui/FenceTime.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
@@ -86,6 +88,9 @@
     // dataSpace is format-dependent.
     android_dataspace mDataSpace;
 
+    // mHdrMetadata is the HDR metadata associated with this buffer slot.
+    HdrMetadata mHdrMetadata;
+
     // mFrameNumber is the number of the queued frame for this slot.
     uint64_t mFrameNumber;
 
diff --git a/libs/gui/include/gui/HdrMetadata.h b/libs/gui/include/gui/HdrMetadata.h
new file mode 100644
index 0000000..cd01952
--- /dev/null
+++ b/libs/gui/include/gui/HdrMetadata.h
@@ -0,0 +1,43 @@
+/*
+ * 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 <stdint.h>
+
+#include <system/graphics.h>
+#include <utils/Flattenable.h>
+
+namespace android {
+
+struct HdrMetadata : public LightFlattenable<HdrMetadata> {
+    enum Type : uint32_t {
+        SMPTE2086 = 1 << 0,
+        CTA861_3  = 1 << 1,
+    };
+    uint32_t validTypes{0};
+
+    android_smpte2086_metadata smpte2086{};
+    android_cta861_3_metadata cta8613{};
+
+    // LightFlattenable
+    bool isFixedSize() const { return false; }
+    size_t getFlattenedSize() const;
+    status_t flatten(void* buffer, size_t size) const;
+    status_t unflatten(void const* buffer, size_t size);
+};
+
+} // namespace android
diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h
index 039dc0d..722833e 100644
--- a/libs/gui/include/gui/IGraphicBufferProducer.h
+++ b/libs/gui/include/gui/IGraphicBufferProducer.h
@@ -31,6 +31,7 @@
 #include <ui/Region.h>
 
 #include <gui/FrameTimestamps.h>
+#include <gui/HdrMetadata.h>
 
 #include <hidl/HybridInterface.h>
 #include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>
@@ -354,6 +355,9 @@
         const Region& getSurfaceDamage() const { return surfaceDamage; }
         void setSurfaceDamage(const Region& damage) { surfaceDamage = damage; }
 
+        const HdrMetadata& getHdrMetadata() const { return hdrMetadata; }
+        void setHdrMetadata(const HdrMetadata& metadata) { hdrMetadata = metadata; }
+
     private:
         int64_t timestamp{0};
         int isAutoTimestamp{0};
@@ -365,6 +369,7 @@
         sp<Fence> fence;
         Region surfaceDamage;
         bool getFrameTimestamps{false};
+        HdrMetadata hdrMetadata;
     };
 
     struct QueueBufferOutput : public Flattenable<QueueBufferOutput> {
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 354f23a..641d62c 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -17,8 +17,9 @@
 #ifndef ANDROID_GUI_SURFACE_H
 #define ANDROID_GUI_SURFACE_H
 
-#include <gui/IGraphicBufferProducer.h>
 #include <gui/BufferQueueDefs.h>
+#include <gui/HdrMetadata.h>
+#include <gui/IGraphicBufferProducer.h>
 
 #include <ui/ANativeObjectBase.h>
 #include <ui/Region.h>
@@ -214,6 +215,8 @@
     int dispatchUnlockAndPost(va_list args);
     int dispatchSetSidebandStream(va_list args);
     int dispatchSetBuffersDataSpace(va_list args);
+    int dispatchSetBuffersSmpte2086Metadata(va_list args);
+    int dispatchSetBuffersCta8613Metadata(va_list args);
     int dispatchSetSurfaceDamage(va_list args);
     int dispatchSetSharedBufferMode(va_list args);
     int dispatchSetAutoRefresh(va_list args);
@@ -243,6 +246,8 @@
     virtual int setBuffersStickyTransform(uint32_t transform);
     virtual int setBuffersTimestamp(int64_t timestamp);
     virtual int setBuffersDataSpace(android_dataspace dataSpace);
+    virtual int setBuffersSmpte2086Metadata(const android_smpte2086_metadata* metadata);
+    virtual int setBuffersCta8613Metadata(const android_cta861_3_metadata* metadata);
     virtual int setCrop(Rect const* rect);
     virtual int setUsage(uint64_t reqUsage);
     virtual void setSurfaceDamage(android_native_rect_t* rects, size_t numRects);
@@ -339,6 +344,10 @@
     // means that the buffer contains some type of color data.
     android_dataspace mDataSpace;
 
+    // mHdrMetadata is the HDR metadata that will be used for the next buffer
+    // queue operation.  There is no HDR metadata by default.
+    HdrMetadata mHdrMetadata;
+
     // mCrop is the crop rectangle that will be used for the next buffer
     // that gets queued. It is set by calling setCrop.
     Rect mCrop;
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 470a338..cd29d4a 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -47,6 +47,9 @@
 static bool hasWideColorDisplay =
         getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
 
+static bool hasHdrDisplay =
+        getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasHDRDisplay>(false);
+
 class FakeSurfaceComposer;
 class FakeProducerFrameEventHistory;
 
@@ -294,6 +297,68 @@
     ASSERT_EQ(hasWideColorDisplay, supported);
 }
 
+TEST_F(SurfaceTest, GetHdrSupport) {
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+
+    sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+    consumer->consumerConnect(dummyConsumer, false);
+    consumer->setConsumerName(String8("TestConsumer"));
+
+    sp<Surface> surface = new Surface(producer);
+    sp<ANativeWindow> window(surface);
+    native_window_api_connect(window.get(), NATIVE_WINDOW_API_CPU);
+
+    bool supported;
+    status_t result = surface->getHdrSupport(&supported);
+    ASSERT_EQ(NO_ERROR, result);
+
+    // NOTE: This is not a CTS test.
+    // This test verifies that when the BoardConfig TARGET_HAS_HDR_DISPLAY
+    // is TRUE, getHdrSupport is also true.
+    // TODO: Add check for an HDR color mode on the primary display.
+    ASSERT_EQ(hasHdrDisplay, supported);
+}
+
+TEST_F(SurfaceTest, SetHdrMetadata) {
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+
+    sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+    consumer->consumerConnect(dummyConsumer, false);
+    consumer->setConsumerName(String8("TestConsumer"));
+
+    sp<Surface> surface = new Surface(producer);
+    sp<ANativeWindow> window(surface);
+    native_window_api_connect(window.get(), NATIVE_WINDOW_API_CPU);
+
+    bool supported;
+    status_t result = surface->getHdrSupport(&supported);
+    ASSERT_EQ(NO_ERROR, result);
+
+    if (!hasHdrDisplay || !supported) {
+        return;
+    }
+    const android_smpte2086_metadata smpte2086 = {
+        {0.680, 0.320},
+        {0.265, 0.690},
+        {0.150, 0.060},
+        {0.3127, 0.3290},
+        100.0,
+        0.1,
+    };
+    const android_cta861_3_metadata cta861_3 = {
+        78.0,
+        62.0,
+    };
+    int error = native_window_set_buffers_smpte2086_metadata(window.get(), &smpte2086);
+    ASSERT_EQ(error, NO_ERROR);
+    error = native_window_set_buffers_cta861_3_metadata(window.get(), &cta861_3);
+    ASSERT_EQ(error, NO_ERROR);
+}
+
 TEST_F(SurfaceTest, DynamicSetBufferCount) {
     sp<IGraphicBufferProducer> producer;
     sp<IGraphicBufferConsumer> consumer;
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 6490804..69e0951 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -225,6 +225,8 @@
     NATIVE_WINDOW_GET_HDR_SUPPORT               = 29,
     NATIVE_WINDOW_SET_USAGE64                   = 30,
     NATIVE_WINDOW_GET_CONSUMER_USAGE64          = 31,
+    NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA = 32,
+    NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA = 33,
 // clang-format on
 };
 
@@ -700,6 +702,42 @@
 }
 
 /*
+ * native_window_set_buffers_smpte2086_metadata(..., metadata)
+ * All buffers queued after this call will be associated with the SMPTE
+ * ST.2086 metadata specified.
+ *
+ * metadata specifies additional information about the contents of the buffer
+ * that may affect how it's displayed.  When it is nullptr, it means no such
+ * information is available.  No SMPTE ST.2086 metadata is associated with the
+ * buffers by default.
+ */
+static inline int native_window_set_buffers_smpte2086_metadata(
+        struct ANativeWindow* window,
+        const struct android_smpte2086_metadata* metadata)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA,
+            metadata);
+}
+
+/*
+ * native_window_set_buffers_cta861_3_metadata(..., metadata)
+ * All buffers queued after this call will be associated with the CTA-861.3
+ * metadata specified.
+ *
+ * metadata specifies additional information about the contents of the buffer
+ * that may affect how it's displayed.  When it is nullptr, it means no such
+ * information is available.  No CTA-861.3 metadata is associated with the
+ * buffers by default.
+ */
+static inline int native_window_set_buffers_cta861_3_metadata(
+        struct ANativeWindow* window,
+        const struct android_cta861_3_metadata* metadata)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA,
+            metadata);
+}
+
+/*
  * native_window_set_buffers_transform(..., int transform)
  * All buffers queued after this call will be displayed transformed according
  * to the transform parameter specified.
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 4194dea..86492fd 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -1805,7 +1805,7 @@
     ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, "
             "xOffset=%f, yOffset=%f, scaleFactor=%f, "
             "pointerIds=0x%x",
-            connection->getInputChannelName(), inputTarget->flags,
+            connection->getInputChannelName().c_str(), inputTarget->flags,
             inputTarget->xOffset, inputTarget->yOffset,
             inputTarget->scaleFactor, inputTarget->pointerIds.value);
 #endif
@@ -1815,7 +1815,7 @@
     if (connection->status != Connection::STATUS_NORMAL) {
 #if DEBUG_DISPATCH_CYCLE
         ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
-                connection->getInputChannelName(), connection->getStatusLabel());
+                connection->getInputChannelName().c_str(), connection->getStatusLabel());
 #endif
         return;
     }
@@ -1833,7 +1833,7 @@
             }
 #if DEBUG_FOCUS
             ALOGD("channel '%s' ~ Split motion event.",
-                    connection->getInputChannelName());
+                    connection->getInputChannelName().c_str());
             logOutboundMotionDetailsLocked("  ", splitMotionEntry);
 #endif
             enqueueDispatchEntriesLocked(currentTime, connection,
@@ -1897,7 +1897,7 @@
                 dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
 #if DEBUG_DISPATCH_CYCLE
             ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent key event",
-                    connection->getInputChannelName());
+                    connection->getInputChannelName().c_str());
 #endif
             delete dispatchEntry;
             return; // skip the inconsistent event
@@ -1925,7 +1925,7 @@
                         motionEntry->deviceId, motionEntry->source, motionEntry->displayId)) {
 #if DEBUG_DISPATCH_CYCLE
         ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover enter event",
-                connection->getInputChannelName());
+                connection->getInputChannelName().c_str());
 #endif
             dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
         }
@@ -1942,7 +1942,7 @@
                 dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags)) {
 #if DEBUG_DISPATCH_CYCLE
             ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: skipping inconsistent motion event",
-                    connection->getInputChannelName());
+                    connection->getInputChannelName().c_str());
 #endif
             delete dispatchEntry;
             return; // skip the inconsistent event
@@ -1965,7 +1965,7 @@
         const sp<Connection>& connection) {
 #if DEBUG_DISPATCH_CYCLE
     ALOGD("channel '%s' ~ startDispatchCycle",
-            connection->getInputChannelName());
+            connection->getInputChannelName().c_str());
 #endif
 
     while (connection->status == Connection::STATUS_NORMAL
@@ -2048,7 +2048,8 @@
                     ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "
                             "This is unexpected because the wait queue is empty, so the pipe "
                             "should be empty and we shouldn't have any problems writing an "
-                            "event to it, status=%d", connection->getInputChannelName(), status);
+                            "event to it, status=%d", connection->getInputChannelName().c_str(),
+                            status);
                     abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
                 } else {
                     // Pipe is full and we are waiting for the app to finish process some events
@@ -2056,13 +2057,13 @@
 #if DEBUG_DISPATCH_CYCLE
                     ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "
                             "waiting for the application to catch up",
-                            connection->getInputChannelName());
+                            connection->getInputChannelName().c_str());
 #endif
                     connection->inputPublisherBlocked = true;
                 }
             } else {
                 ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
-                        "status=%d", connection->getInputChannelName(), status);
+                        "status=%d", connection->getInputChannelName().c_str(), status);
                 abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
             }
             return;
@@ -2080,7 +2081,7 @@
         const sp<Connection>& connection, uint32_t seq, bool handled) {
 #if DEBUG_DISPATCH_CYCLE
     ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s",
-            connection->getInputChannelName(), seq, toString(handled));
+            connection->getInputChannelName().c_str(), seq, toString(handled));
 #endif
 
     connection->inputPublisherBlocked = false;
@@ -2098,7 +2099,7 @@
         const sp<Connection>& connection, bool notify) {
 #if DEBUG_DISPATCH_CYCLE
     ALOGD("channel '%s' ~ abortBrokenDispatchCycle - notify=%s",
-            connection->getInputChannelName(), toString(notify));
+            connection->getInputChannelName().c_str(), toString(notify));
 #endif
 
     // Clear the dispatch queues.
@@ -2151,7 +2152,7 @@
         if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
             if (!(events & ALOOPER_EVENT_INPUT)) {
                 ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "
-                        "events=0x%x", connection->getInputChannelName(), events);
+                        "events=0x%x", connection->getInputChannelName().c_str(), events);
                 return 1;
             }
 
@@ -2178,7 +2179,7 @@
             notify = status != DEAD_OBJECT || !connection->monitor;
             if (notify) {
                 ALOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",
-                        connection->getInputChannelName(), status);
+                        connection->getInputChannelName().c_str(), status);
             }
         } else {
             // Monitor channels are never explicitly unregistered.
@@ -2187,7 +2188,7 @@
             notify = !connection->monitor;
             if (notify) {
                 ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred.  "
-                        "events=0x%x", connection->getInputChannelName(), events);
+                        "events=0x%x", connection->getInputChannelName().c_str(), events);
             }
         }
 
@@ -2237,7 +2238,7 @@
 #if DEBUG_OUTBOUND_EVENT_DETAILS
         ALOGD("channel '%s' ~ Synthesized %zu cancelation events to bring channel back in sync "
                 "with reality: %s, mode=%d.",
-                connection->getInputChannelName(), cancelationEvents.size(),
+                connection->getInputChannelName().c_str(), cancelationEvents.size(),
                 options.reason, options.mode);
 #endif
         for (size_t i = 0; i < cancelationEvents.size(); i++) {
@@ -3285,7 +3286,8 @@
             const sp<Connection>& connection = mConnectionsByFd.valueAt(i);
             dump += StringPrintf(INDENT2 "%zu: channelName='%s', windowName='%s', "
                     "status=%s, monitor=%s, inputPublisherBlocked=%s\n",
-                    i, connection->getInputChannelName(), connection->getWindowName(),
+                    i, connection->getInputChannelName().c_str(),
+                    connection->getWindowName().c_str(),
                     connection->getStatusLabel(), toString(connection->monitor),
                     toString(connection->inputPublisherBlocked));
 
@@ -3451,7 +3453,7 @@
 void InputDispatcher::onDispatchCycleBrokenLocked(
         nsecs_t currentTime, const sp<Connection>& connection) {
     ALOGE("channel '%s' ~ Channel is unrecoverably broken and will be disposed!",
-            connection->getInputChannelName());
+            connection->getInputChannelName().c_str());
 
     CommandEntry* commandEntry = postCommandLocked(
             & InputDispatcher::doNotifyInputChannelBrokenLockedInterruptible);
@@ -3568,7 +3570,7 @@
         if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
             std::string msg =
                     StringPrintf("Window '%s' spent %0.1fms processing the last input event: ",
-                    connection->getWindowName(), eventDuration * 0.000001f);
+                    connection->getWindowName().c_str(), eventDuration * 0.000001f);
             dispatchEntry->eventEntry->appendDescription(msg);
             ALOGI("%s", msg.c_str());
         }
@@ -3811,7 +3813,7 @@
 void InputDispatcher::traceOutboundQueueLengthLocked(const sp<Connection>& connection) {
     if (ATRACE_ENABLED()) {
         char counterName[40];
-        snprintf(counterName, sizeof(counterName), "oq:%s", connection->getWindowName());
+        snprintf(counterName, sizeof(counterName), "oq:%s", connection->getWindowName().c_str());
         ATRACE_INT(counterName, connection->outboundQueue.count());
     }
 }
@@ -3819,7 +3821,7 @@
 void InputDispatcher::traceWaitQueueLengthLocked(const sp<Connection>& connection) {
     if (ATRACE_ENABLED()) {
         char counterName[40];
-        snprintf(counterName, sizeof(counterName), "wq:%s", connection->getWindowName());
+        snprintf(counterName, sizeof(counterName), "wq:%s", connection->getWindowName().c_str());
         ATRACE_INT(counterName, connection->waitQueue.count());
     }
 }
@@ -4397,9 +4399,9 @@
 InputDispatcher::Connection::~Connection() {
 }
 
-const char* InputDispatcher::Connection::getWindowName() const {
+const std::string InputDispatcher::Connection::getWindowName() const {
     if (inputWindowHandle != NULL) {
-        return inputWindowHandle->getName().c_str();
+        return inputWindowHandle->getName();
     }
     if (monitor) {
         return "monitor";
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 92b3a9c..8da8450 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -831,9 +831,9 @@
         explicit Connection(const sp<InputChannel>& inputChannel,
                 const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
 
-        inline const char* getInputChannelName() const { return inputChannel->getName().c_str(); }
+        inline const std::string getInputChannelName() const { return inputChannel->getName(); }
 
-        const char* getWindowName() const;
+        const std::string getWindowName() const;
         const char* getStatusLabel() const;
 
         DispatchEntry* findWaitQueueEntry(uint32_t seq);
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 976dde2..bf61236 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -340,6 +340,7 @@
     mCurrentScalingMode = item.mScalingMode;
     mCurrentTimestamp = item.mTimestamp;
     mCurrentDataSpace = item.mDataSpace;
+    mCurrentHdrMetadata = item.mHdrMetadata;
     mCurrentFence = item.mFence;
     mCurrentFenceTime = item.mFenceTime;
     mCurrentFrameNumber = item.mFrameNumber;
@@ -447,6 +448,12 @@
     return mCurrentDataSpace;
 }
 
+const HdrMetadata& BufferLayerConsumer::getCurrentHdrMetadata() const {
+    BLC_LOGV("getCurrentHdrMetadata");
+    Mutex::Autolock lock(mMutex);
+    return mCurrentHdrMetadata;
+}
+
 uint64_t BufferLayerConsumer::getFrameNumber() {
     BLC_LOGV("getFrameNumber");
     Mutex::Autolock lock(mMutex);
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index 9b18608..51c2b41 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -21,6 +21,7 @@
 
 #include <gui/BufferQueueDefs.h>
 #include <gui/ConsumerBase.h>
+#include <gui/HdrMetadata.h>
 
 #include <ui/FenceTime.h>
 #include <ui/GraphicBuffer.h>
@@ -121,6 +122,10 @@
     // set by the most recent call to updateTexImage.
     android_dataspace getCurrentDataSpace();
 
+    // getCurrentHdrMetadata retrieves the HDR metadata associated with the
+    // texture image set by the most recent call to updateTexImage.
+    const HdrMetadata& getCurrentHdrMetadata() const;
+
     // getFrameNumber retrieves the frame number associated with the texture
     // image set by the most recent call to updateTexImage.
     //
@@ -316,6 +321,10 @@
     // gets set each time updateTexImage is called.
     android_dataspace mCurrentDataSpace;
 
+    // mCurrentHdrMetadata is the HDR metadata for the current texture. It
+    // gets set each time updateTexImage is called.
+    HdrMetadata mCurrentHdrMetadata;
+
     // mCurrentFrameNumber is the frame counter for the current texture.
     // It gets set each time updateTexImage is called.
     uint64_t mCurrentFrameNumber;