Add metadata store to surfaces

This adds a key/value metadata storage mechanism to
surfaces that allows the windowmanager to pass information
to the surfaceflinger frontend.

This then moves the existing metadata (window type and
ownerUID) into this metadata structure.

Bug: 122925737
Test: Phone boots and surfaces fling. Some unittests
Change-Id: I72c574737b7f75be2311a341812b15d385f507ed
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 3521e89..b148015 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -108,6 +108,7 @@
         "ISurfaceComposerClient.cpp",
         "ITransactionCompletedListener.cpp",
         "LayerDebugInfo.cpp",
+        "LayerMetadata.cpp",
         "LayerState.cpp",
         "OccupancyTracker.cpp",
         "StreamSplitter.cpp",
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
index 928ef95..129558b 100644
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ b/libs/gui/ISurfaceComposerClient.cpp
@@ -47,26 +47,26 @@
     ~BpSurfaceComposerClient() override;
 
     status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format,
-                           uint32_t flags, const sp<IBinder>& parent, int32_t windowType,
-                           int32_t ownerUid, sp<IBinder>* handle,
-                           sp<IGraphicBufferProducer>* gbp) override {
+                           uint32_t flags, const sp<IBinder>& parent, LayerMetadata metadata,
+                           sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) override {
         return callRemote<decltype(&ISurfaceComposerClient::createSurface)>(Tag::CREATE_SURFACE,
                                                                             name, width, height,
                                                                             format, flags, parent,
-                                                                            windowType, ownerUid,
+                                                                            std::move(metadata),
                                                                             handle, gbp);
     }
 
     status_t createWithSurfaceParent(const String8& name, uint32_t width, uint32_t height,
                                      PixelFormat format, uint32_t flags,
-                                     const sp<IGraphicBufferProducer>& parent, int32_t windowType,
-                                     int32_t ownerUid, sp<IBinder>* handle,
+                                     const sp<IGraphicBufferProducer>& parent,
+                                     LayerMetadata metadata, sp<IBinder>* handle,
                                      sp<IGraphicBufferProducer>* gbp) override {
         return callRemote<decltype(
                 &ISurfaceComposerClient::createWithSurfaceParent)>(Tag::CREATE_WITH_SURFACE_PARENT,
                                                                    name, width, height, format,
-                                                                   flags, parent, windowType,
-                                                                   ownerUid, handle, gbp);
+                                                                   flags, parent,
+                                                                   std::move(metadata), handle,
+                                                                   gbp);
     }
 
     status_t clearLayerFrameStats(const sp<IBinder>& handle) const override {
diff --git a/libs/gui/LayerMetadata.cpp b/libs/gui/LayerMetadata.cpp
new file mode 100644
index 0000000..c8a2b07
--- /dev/null
+++ b/libs/gui/LayerMetadata.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/stringprintf.h>
+#include <binder/Parcel.h>
+#include <gui/LayerMetadata.h>
+
+using android::base::StringPrintf;
+
+namespace android {
+
+LayerMetadata::LayerMetadata() = default;
+
+LayerMetadata::LayerMetadata(std::unordered_map<uint32_t, std::vector<uint8_t>> map)
+      : mMap(std::move(map)) {}
+
+LayerMetadata::LayerMetadata(const LayerMetadata& other) = default;
+
+LayerMetadata::LayerMetadata(LayerMetadata&& other) = default;
+
+void LayerMetadata::merge(const LayerMetadata& other) {
+    for (const auto& entry : other.mMap) {
+        mMap[entry.first] = entry.second;
+    }
+}
+
+status_t LayerMetadata::writeToParcel(Parcel* parcel) const {
+    parcel->writeInt32(static_cast<int>(mMap.size()));
+    status_t status = OK;
+    for (const auto& entry : mMap) {
+        status = parcel->writeUint32(entry.first);
+        if (status != OK) {
+            break;
+        }
+        status = parcel->writeByteVector(entry.second);
+        if (status != OK) {
+            break;
+        }
+    }
+    return status;
+}
+
+status_t LayerMetadata::readFromParcel(const Parcel* parcel) {
+    int size = parcel->readInt32();
+    status_t status = OK;
+    mMap.clear();
+    for (int i = 0; i < size; ++i) {
+        uint32_t key = parcel->readUint32();
+        status = parcel->readByteVector(&mMap[key]);
+        if (status != OK) {
+            break;
+        }
+    }
+    return status;
+}
+
+LayerMetadata& LayerMetadata::operator=(const LayerMetadata& other) {
+    mMap = other.mMap;
+    return *this;
+}
+
+LayerMetadata& LayerMetadata::operator=(LayerMetadata&& other) {
+    mMap = std::move(other.mMap);
+    return *this;
+}
+
+bool LayerMetadata::has(uint32_t key) const {
+    return mMap.count(key);
+}
+
+int32_t LayerMetadata::getInt32(uint32_t key, int32_t fallback) const {
+    if (!has(key)) return fallback;
+    const std::vector<uint8_t>& data = mMap.at(key);
+    if (data.size() < sizeof(uint32_t)) return fallback;
+    Parcel p;
+    p.setData(data.data(), data.size());
+    return p.readInt32();
+}
+
+void LayerMetadata::setInt32(uint32_t key, int32_t value) {
+    std::vector<uint8_t>& data = mMap[key];
+    Parcel p;
+    p.writeInt32(value);
+    data.resize(p.dataSize());
+    memcpy(data.data(), p.data(), p.dataSize());
+}
+
+std::string LayerMetadata::itemToString(uint32_t key, const char* separator) const {
+    if (!has(key)) return std::string();
+    switch (key) {
+        case METADATA_OWNER_UID:
+            return StringPrintf("ownerUID%s%d", separator, getInt32(key, 0));
+        case METADATA_WINDOW_TYPE:
+            return StringPrintf("windowType%s%d", separator, getInt32(key, 0));
+        default:
+            return StringPrintf("%d%s%dbytes", key, separator,
+                                static_cast<int>(mMap.at(key).size()));
+    }
+}
+
+} // namespace android
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index ab92973..6091d3f 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -96,6 +96,7 @@
 
     output.writeStrongBinder(cachedBuffer.token);
     output.writeInt32(cachedBuffer.bufferId);
+    output.writeParcelable(metadata);
 
     output.writeFloat(colorAlpha);
     output.writeUint32(static_cast<uint32_t>(colorDataspace));
@@ -172,6 +173,7 @@
 
     cachedBuffer.token = input.readStrongBinder();
     cachedBuffer.bufferId = input.readInt32();
+    input.readParcelable(&metadata);
 
     colorAlpha = input.readFloat();
     colorDataspace = static_cast<ui::Dataspace>(input.readUint32());
@@ -396,6 +398,10 @@
         what |= eColorDataspaceChanged;
         colorDataspace = other.colorDataspace;
     }
+    if (other.what & eMetadataChanged) {
+        what |= eMetadataChanged;
+        metadata.merge(other.metadata);
+    }
     if ((other.what & what) != other.what) {
         ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
               "other.what=0x%" PRIu64 " what=0x%" PRIu64,
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 6c1c52e..67d9361 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -539,6 +539,20 @@
     return *this;
 }
 
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setMetadata(
+        const sp<SurfaceControl>& sc, uint32_t key, std::vector<uint8_t> data) {
+    layer_state_t* s = getLayerState(sc);
+    if (!s) {
+        mStatus = BAD_INDEX;
+        return *this;
+    }
+    s->what |= layer_state_t::eMetadataChanged;
+    s->metadata.mMap[key] = std::move(data);
+
+    registerSurfaceControlForCallback(sc);
+    return *this;
+}
+
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setMatrix(
         const sp<SurfaceControl>& sc, float dsdx, float dtdx,
         float dtdy, float dsdy) {
@@ -1141,26 +1155,19 @@
     mStatus = NO_INIT;
 }
 
-sp<SurfaceControl> SurfaceComposerClient::createSurface(
-        const String8& name,
-        uint32_t w,
-        uint32_t h,
-        PixelFormat format,
-        uint32_t flags,
-        SurfaceControl* parent,
-        int32_t windowType,
-        int32_t ownerUid)
-{
+sp<SurfaceControl> SurfaceComposerClient::createSurface(const String8& name, uint32_t w, uint32_t h,
+                                                        PixelFormat format, uint32_t flags,
+                                                        SurfaceControl* parent,
+                                                        LayerMetadata metadata) {
     sp<SurfaceControl> s;
-    createSurfaceChecked(name, w, h, format, &s, flags, parent, windowType, ownerUid);
+    createSurfaceChecked(name, w, h, format, &s, flags, parent, std::move(metadata));
     return s;
 }
 
 sp<SurfaceControl> SurfaceComposerClient::createWithSurfaceParent(const String8& name, uint32_t w,
                                                                   uint32_t h, PixelFormat format,
                                                                   uint32_t flags, Surface* parent,
-                                                                  int32_t windowType,
-                                                                  int32_t ownerUid) {
+                                                                  LayerMetadata metadata) {
     sp<SurfaceControl> sur;
     status_t err = mStatus;
 
@@ -1169,8 +1176,8 @@
         sp<IGraphicBufferProducer> parentGbp = parent->getIGraphicBufferProducer();
         sp<IGraphicBufferProducer> gbp;
 
-        err = mClient->createWithSurfaceParent(name, w, h, format, flags, parentGbp, windowType,
-                                               ownerUid, &handle, &gbp);
+        err = mClient->createWithSurfaceParent(name, w, h, format, flags, parentGbp,
+                                               std::move(metadata), &handle, &gbp);
         ALOGE_IF(err, "SurfaceComposerClient::createWithSurfaceParent error %s", strerror(-err));
         if (err == NO_ERROR) {
             return new SurfaceControl(this, handle, gbp, true /* owned */);
@@ -1179,17 +1186,11 @@
     return nullptr;
 }
 
-status_t SurfaceComposerClient::createSurfaceChecked(
-        const String8& name,
-        uint32_t w,
-        uint32_t h,
-        PixelFormat format,
-        sp<SurfaceControl>* outSurface,
-        uint32_t flags,
-        SurfaceControl* parent,
-        int32_t windowType,
-        int32_t ownerUid)
-{
+status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,
+                                                     PixelFormat format,
+                                                     sp<SurfaceControl>* outSurface, uint32_t flags,
+                                                     SurfaceControl* parent,
+                                                     LayerMetadata metadata) {
     sp<SurfaceControl> sur;
     status_t err = mStatus;
 
@@ -1201,8 +1202,9 @@
         if (parent != nullptr) {
             parentHandle = parent->getHandle();
         }
-        err = mClient->createSurface(name, w, h, format, flags, parentHandle,
-                windowType, ownerUid, &handle, &gbp);
+
+        err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),
+                                     &handle, &gbp);
         ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
         if (err == NO_ERROR) {
             *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);
diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h
index f443df8..32ac9e8 100644
--- a/libs/gui/include/gui/ISurfaceComposerClient.h
+++ b/libs/gui/include/gui/ISurfaceComposerClient.h
@@ -18,8 +18,11 @@
 
 #include <binder/IInterface.h>
 #include <binder/SafeInterface.h>
+#include <gui/LayerMetadata.h>
 #include <ui/PixelFormat.h>
 
+#include <unordered_map>
+
 namespace android {
 
 class FrameStats;
@@ -51,8 +54,8 @@
      * Requires ACCESS_SURFACE_FLINGER permission
      */
     virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,
-                                   uint32_t flags, const sp<IBinder>& parent, int32_t windowType,
-                                   int32_t ownerUid, sp<IBinder>* handle,
+                                   uint32_t flags, const sp<IBinder>& parent,
+                                   LayerMetadata metadata, sp<IBinder>* handle,
                                    sp<IGraphicBufferProducer>* gbp) = 0;
 
     /*
@@ -61,8 +64,7 @@
     virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
                                              PixelFormat format, uint32_t flags,
                                              const sp<IGraphicBufferProducer>& parent,
-                                             int32_t windowType, int32_t ownerUid,
-                                             sp<IBinder>* handle,
+                                             LayerMetadata metadata, sp<IBinder>* handle,
                                              sp<IGraphicBufferProducer>* gbp) = 0;
 
     /*
diff --git a/libs/gui/include/gui/LayerMetadata.h b/libs/gui/include/gui/LayerMetadata.h
new file mode 100644
index 0000000..5012181
--- /dev/null
+++ b/libs/gui/include/gui/LayerMetadata.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <binder/Parcelable.h>
+
+#include <unordered_map>
+
+namespace android {
+
+enum { METADATA_OWNER_UID = 1, METADATA_WINDOW_TYPE = 2 };
+
+struct LayerMetadata : public Parcelable {
+    std::unordered_map<uint32_t, std::vector<uint8_t>> mMap;
+
+    LayerMetadata();
+    LayerMetadata(const LayerMetadata& other);
+    LayerMetadata(LayerMetadata&& other);
+    explicit LayerMetadata(std::unordered_map<uint32_t, std::vector<uint8_t>> map);
+    LayerMetadata& operator=(const LayerMetadata& other);
+    LayerMetadata& operator=(LayerMetadata&& other);
+
+    void merge(const LayerMetadata& other);
+
+    status_t writeToParcel(Parcel* parcel) const override;
+    status_t readFromParcel(const Parcel* parcel) override;
+
+    bool has(uint32_t key) const;
+    int32_t getInt32(uint32_t key, int32_t fallback) const;
+    void setInt32(uint32_t key, int32_t value);
+
+    std::string itemToString(uint32_t key, const char* separator) const;
+};
+
+} // namespace android
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 9063e7f..afd843f 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -30,6 +30,7 @@
 #include <input/InputWindow.h>
 #endif
 
+#include <gui/LayerMetadata.h>
 #include <math/vec3.h>
 #include <ui/GraphicTypes.h>
 #include <ui/Rect.h>
@@ -87,6 +88,7 @@
         eCachedBufferChanged = 0x2'00000000,
         eColorAlphaChanged = 0x4'00000000,
         eColorDataspaceChanged = 0x8'00000000,
+        eMetadataChanged = 0x10'00000000,
     };
 
     layer_state_t()
@@ -187,6 +189,8 @@
 
     float colorAlpha;
     ui::Dataspace colorDataspace;
+
+    LayerMetadata metadata;
 };
 
 struct ComposerState {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 24b656b..bffe3f9 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -159,39 +159,33 @@
     static sp<SurfaceComposerClient> getDefault();
 
     //! Create a surface
-    sp<SurfaceControl> createSurface(
-            const String8& name,// name of the surface
-            uint32_t w,         // width in pixel
-            uint32_t h,         // height in pixel
-            PixelFormat format, // pixel-format desired
-            uint32_t flags = 0, // usage flags
-            SurfaceControl* parent = nullptr, // parent
-            int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.)
-            int32_t ownerUid = -1 // UID of the task
+    sp<SurfaceControl> createSurface(const String8& name,              // name of the surface
+                                     uint32_t w,                       // width in pixel
+                                     uint32_t h,                       // height in pixel
+                                     PixelFormat format,               // pixel-format desired
+                                     uint32_t flags = 0,               // usage flags
+                                     SurfaceControl* parent = nullptr, // parent
+                                     LayerMetadata metadata = LayerMetadata() // metadata
     );
 
-    status_t createSurfaceChecked(
-            const String8& name, // name of the surface
-            uint32_t w,          // width in pixel
-            uint32_t h,          // height in pixel
-            PixelFormat format,  // pixel-format desired
-            sp<SurfaceControl>* outSurface,
-            uint32_t flags = 0,               // usage flags
-            SurfaceControl* parent = nullptr, // parent
-            int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.)
-            int32_t ownerUid = -1    // UID of the task
+    status_t createSurfaceChecked(const String8& name, // name of the surface
+                                  uint32_t w,          // width in pixel
+                                  uint32_t h,          // height in pixel
+                                  PixelFormat format,  // pixel-format desired
+                                  sp<SurfaceControl>* outSurface,
+                                  uint32_t flags = 0,                      // usage flags
+                                  SurfaceControl* parent = nullptr,        // parent
+                                  LayerMetadata metadata = LayerMetadata() // metadata
     );
 
     //! Create a surface
-    sp<SurfaceControl> createWithSurfaceParent(
-            const String8& name,       // name of the surface
-            uint32_t w,                // width in pixel
-            uint32_t h,                // height in pixel
-            PixelFormat format,        // pixel-format desired
-            uint32_t flags = 0,        // usage flags
-            Surface* parent = nullptr, // parent
-            int32_t windowType = -1,   // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.)
-            int32_t ownerUid = -1      // UID of the task
+    sp<SurfaceControl> createWithSurfaceParent(const String8& name,       // name of the surface
+                                               uint32_t w,                // width in pixel
+                                               uint32_t h,                // height in pixel
+                                               PixelFormat format,        // pixel-format desired
+                                               uint32_t flags = 0,        // usage flags
+                                               Surface* parent = nullptr, // parent
+                                               LayerMetadata metadata = LayerMetadata() // metadata
     );
 
     //! Create a virtual display
@@ -302,6 +296,8 @@
         Transaction& setCrop_legacy(const sp<SurfaceControl>& sc, const Rect& crop);
         Transaction& setCornerRadius(const sp<SurfaceControl>& sc, float cornerRadius);
         Transaction& setLayerStack(const sp<SurfaceControl>& sc, uint32_t layerStack);
+        Transaction& setMetadata(const sp<SurfaceControl>& sc, uint32_t key,
+                                 std::vector<uint8_t> data);
         // Defers applying any changes made in this transaction until the Layer
         // identified by handle reaches the given frameNumber. If the Layer identified
         // by handle is removed, then we will apply this transaction regardless of
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 0e447d8..0ca3759 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -73,14 +73,10 @@
     return lbc;
 }
 
-
-status_t Client::createSurface(
-        const String8& name,
-        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
-        const sp<IBinder>& parentHandle, int32_t windowType, int32_t ownerUid,
-        sp<IBinder>* handle,
-        sp<IGraphicBufferProducer>* gbp)
-{
+status_t Client::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,
+                               uint32_t flags, const sp<IBinder>& parentHandle,
+                               LayerMetadata metadata, sp<IBinder>* handle,
+                               sp<IGraphicBufferProducer>* gbp) {
     sp<Layer> parent = nullptr;
     if (parentHandle != nullptr) {
         auto layerHandle = reinterpret_cast<Layer::Handle*>(parentHandle.get());
@@ -91,14 +87,14 @@
     }
 
     // We rely on createLayer to check permissions.
-    return mFlinger->createLayer(name, this, w, h, format, flags, windowType,
-                                 ownerUid, handle, gbp, &parent);
+    return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp,
+                                 &parent);
 }
 
 status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
                                          PixelFormat format, uint32_t flags,
                                          const sp<IGraphicBufferProducer>& parent,
-                                         int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
+                                         LayerMetadata metadata, sp<IBinder>* handle,
                                          sp<IGraphicBufferProducer>* gbp) {
     if (mFlinger->authenticateSurfaceTexture(parent) == false) {
         return BAD_VALUE;
@@ -111,8 +107,7 @@
 
     sp<IBinder> parentHandle = layer->getHandle();
 
-    return createSurface(name, w, h, format, flags, parentHandle, windowType, ownerUid, handle,
-                         gbp);
+    return createSurface(name, w, h, format, flags, parentHandle, std::move(metadata), handle, gbp);
 }
 
 status_t Client::clearLayerFrameStats(const sp<IBinder>& handle) const {
diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h
index 0f5ee4c..74e4818 100644
--- a/services/surfaceflinger/Client.h
+++ b/services/surfaceflinger/Client.h
@@ -51,18 +51,16 @@
 
 private:
     // ISurfaceComposerClient interface
-    virtual status_t createSurface(
-            const String8& name,
-            uint32_t w, uint32_t h,PixelFormat format, uint32_t flags,
-            const sp<IBinder>& parent, int32_t windowType, int32_t ownerUid,
-            sp<IBinder>* handle,
-            sp<IGraphicBufferProducer>* gbp);
+    virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,
+                                   uint32_t flags, const sp<IBinder>& parent,
+                                   LayerMetadata metadata, sp<IBinder>* handle,
+                                   sp<IGraphicBufferProducer>* gbp);
 
     virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
                                              PixelFormat format, uint32_t flags,
                                              const sp<IGraphicBufferProducer>& parent,
-                                             int32_t windowType, int32_t ownerUid,
-                                             sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp);
+                                             LayerMetadata metadata, sp<IBinder>* handle,
+                                             sp<IGraphicBufferProducer>* gbp);
 
     virtual status_t clearLayerFrameStats(const sp<IBinder>& handle) const;
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index ef77590..272793a 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -94,8 +94,6 @@
     mCurrentState.layerStack = 0;
     mCurrentState.sequence = 0;
     mCurrentState.requested_legacy = mCurrentState.active_legacy;
-    mCurrentState.appId = 0;
-    mCurrentState.type = 0;
     mCurrentState.active.w = UINT32_MAX;
     mCurrentState.active.h = UINT32_MAX;
     mCurrentState.active.transform.set(0, 0);
@@ -600,14 +598,16 @@
              to_string(error).c_str(), static_cast<int32_t>(error));
     getBE().compositionInfo.hwc.z = z;
 
-    int type = s.type;
-    int appId = s.appId;
+    int type = s.metadata.getInt32(METADATA_WINDOW_TYPE, 0);
+    int appId = s.metadata.getInt32(METADATA_OWNER_UID, 0);
     sp<Layer> parent = mDrawingParent.promote();
     if (parent.get()) {
         auto& parentState = parent->getDrawingState();
-        if (parentState.type >= 0 || parentState.appId >= 0) {
-            type = parentState.type;
-            appId = parentState.appId;
+        const int parentType = parentState.metadata.getInt32(METADATA_WINDOW_TYPE, 0);
+        const int parentAppId = parentState.metadata.getInt32(METADATA_OWNER_UID, 0);
+        if (parentType >= 0 || parentAppId >= 0) {
+            type = parentType;
+            appId = parentAppId;
         }
     }
 
@@ -1316,11 +1316,14 @@
     return true;
 }
 
-void Layer::setInfo(int32_t type, int32_t appId) {
-    mCurrentState.appId = appId;
-    mCurrentState.type = type;
+bool Layer::setMetadata(LayerMetadata data) {
+    bool changed = data.mMap != mCurrentState.metadata.mMap;
+    if (!changed) return false;
+    mCurrentState.metadata = std::move(data);
+    mCurrentState.sequence++;
     mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
+    return true;
 }
 
 bool Layer::setLayerStack(uint32_t layerStack) {
@@ -2088,8 +2091,6 @@
 
     layerInfo->set_queued_frames(getQueuedFrameCount());
     layerInfo->set_refresh_pending(isBufferLatched());
-    layerInfo->set_window_type(state.type);
-    layerInfo->set_app_id(state.appId);
     layerInfo->set_curr_frame(mCurrentFrameNumber);
     layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
 
@@ -2101,6 +2102,11 @@
             barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy);
         }
     }
+
+    auto protoMap = layerInfo->mutable_metadata();
+    for (const auto& entry : state.metadata.mMap) {
+        (*protoMap)[entry.first] = std::string(entry.second.cbegin(), entry.second.cend());
+    }
 }
 
 void Layer::writeToProto(LayerProto* layerInfo, DisplayId displayId) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 685f419..b0efb54 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -167,8 +167,7 @@
         Region activeTransparentRegion_legacy;
         Region requestedTransparentRegion_legacy;
 
-        int32_t appId;
-        int32_t type;
+        LayerMetadata metadata;
 
         // If non-null, a Surface this Surface's Z-order is interpreted relative to.
         wp<Layer> zOrderRelativeOf;
@@ -284,7 +283,7 @@
                                               uint64_t frameNumber);
     virtual void deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber);
     virtual bool setOverrideScalingMode(int32_t overrideScalingMode);
-    virtual void setInfo(int32_t type, int32_t appId);
+    virtual bool setMetadata(LayerMetadata data);
     virtual bool reparentChildren(const sp<IBinder>& layer);
     virtual void setChildrenDrawingParent(const sp<Layer>& layer);
     virtual bool reparent(const sp<IBinder>& newParentHandle);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 299499d..04c1ba0 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3983,6 +3983,9 @@
             ALOGE("Attempt to update InputWindowInfo without permission ACCESS_SURFACE_FLINGER");
         }
     }
+    if (what & layer_state_t::eMetadataChanged) {
+        if (layer->setMetadata(s.metadata)) flags |= eTraversalNeeded;
+    }
     std::vector<sp<CallbackHandle>> callbackHandles;
     if ((what & layer_state_t::eListenerCallbacksChanged) && (!s.listenerCallbacks.empty())) {
         mTransactionCompletedThread.run();
@@ -4011,13 +4014,10 @@
     return flags;
 }
 
-status_t SurfaceFlinger::createLayer(
-        const String8& name,
-        const sp<Client>& client,
-        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
-        int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
-        sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent)
-{
+status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w,
+                                     uint32_t h, PixelFormat format, uint32_t flags,
+                                     LayerMetadata metadata, sp<IBinder>* handle,
+                                     sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent) {
     if (int32_t(w|h) < 0) {
         ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
                 int(w), int(h));
@@ -4073,12 +4073,15 @@
 
     // window type is WINDOW_TYPE_DONT_SCREENSHOT from SurfaceControl.java
     // TODO b/64227542
-    if (windowType == 441731) {
-        windowType = 2024; // TYPE_NAVIGATION_BAR_PANEL
-        layer->setPrimaryDisplayOnly();
+    if (metadata.has(METADATA_WINDOW_TYPE)) {
+        int32_t windowType = metadata.getInt32(METADATA_WINDOW_TYPE, 0);
+        if (windowType == 441731) {
+            metadata.setInt32(METADATA_WINDOW_TYPE, 2024); // TYPE_NAVIGATION_BAR_PANEL
+            layer->setPrimaryDisplayOnly();
+        }
     }
 
-    layer->setInfo(windowType, ownerUid);
+    layer->setMetadata(std::move(metadata));
 
     bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess();
     result = addClientLayer(client, *handle, *gbp, layer, *parent,
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 68a602c..5219e2f 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -141,7 +141,6 @@
     ENHANCED = 2,
 };
 
-
 class SurfaceFlingerBE
 {
 public:
@@ -556,10 +555,9 @@
     /* ------------------------------------------------------------------------
      * Layer management
      */
-    status_t createLayer(const String8& name, const sp<Client>& client,
-            uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
-            int32_t windowType, int32_t ownerUid, sp<IBinder>* handle,
-            sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent);
+    status_t createLayer(const String8& name, const sp<Client>& client, uint32_t w, uint32_t h,
+                         PixelFormat format, uint32_t flags, LayerMetadata metadata,
+                         sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent);
 
     status_t createBufferQueueLayer(const sp<Client>& client, const String8& name, uint32_t w,
                                     uint32_t h, uint32_t flags, PixelFormat& format,
diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp
index ac147fe..cb368b0 100644
--- a/services/surfaceflinger/layerproto/Android.bp
+++ b/services/surfaceflinger/layerproto/Android.bp
@@ -1,6 +1,5 @@
 cc_library_shared {
     name: "liblayers_proto",
-    vendor_available: true,
     export_include_dirs: ["include"],
 
     srcs: [
@@ -11,6 +10,7 @@
 
     shared_libs: [
         "android.hardware.graphics.common@1.1",
+        "libgui",
         "libui",
         "libprotobuf-cpp-lite",
         "libbase",
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
index d020a39..5c72fea 100644
--- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -117,11 +117,15 @@
     layer.hwcFrame = generateRect(layerProto.hwc_frame());
     layer.hwcCrop = generateFloatRect(layerProto.hwc_crop());
     layer.hwcTransform = layerProto.hwc_transform();
-    layer.windowType = layerProto.window_type();
-    layer.appId = layerProto.app_id();
     layer.hwcCompositionType = layerProto.hwc_composition_type();
     layer.isProtected = layerProto.is_protected();
     layer.cornerRadius = layerProto.corner_radius();
+    for (const auto& entry : layerProto.metadata()) {
+        const std::string& dataStr = entry.second;
+        std::vector<uint8_t>& outData = layer.metadata.mMap[entry.first];
+        outData.resize(dataStr.size());
+        memcpy(outData.data(), dataStr.data(), dataStr.size());
+    }
 
     return layer;
 }
@@ -310,7 +314,14 @@
     StringAppendF(&result, "      activeBuffer=%s,", activeBuffer.to_string().c_str());
     StringAppendF(&result, " tr=%s", bufferTransform.to_string().c_str());
     StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d,", queuedFrames, refreshPending);
-    StringAppendF(&result, " windowType=%d, appId=%d", windowType, appId);
+    StringAppendF(&result, " metadata={");
+    bool first = true;
+    for (const auto& entry : metadata.mMap) {
+        if (!first) result.append(", ");
+        first = false;
+        result.append(metadata.itemToString(entry.first, ":"));
+    }
+    result.append("}");
 
     return result;
 }
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
index a794ca5..d1b2b1f 100644
--- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -17,6 +17,7 @@
 
 #include <layerproto/LayerProtoHeader.h>
 
+#include <gui/LayerMetadata.h>
 #include <math/vec4.h>
 
 #include <memory>
@@ -110,11 +111,10 @@
         LayerProtoParser::Rect hwcFrame;
         LayerProtoParser::FloatRect hwcCrop;
         int32_t hwcTransform;
-        int32_t windowType;
-        int32_t appId;
         int32_t hwcCompositionType;
         bool isProtected;
         float cornerRadius;
+        LayerMetadata metadata;
 
         std::string to_string() const;
     };
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index b100438..4c756d9 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -74,8 +74,8 @@
   optional FloatRectProto hwc_crop = 31;
   // The layer's composer backend transform
   optional int32 hwc_transform = 32;
-  optional int32 window_type = 33;
-  optional int32 app_id = 34;
+  optional int32 window_type = 33 [deprecated=true];
+  optional int32 app_id = 34 [deprecated=true];
   // The layer's composition type
   optional int32 hwc_composition_type = 35;
   // If it's a buffer layer, indicate if the content is protected
@@ -89,6 +89,8 @@
   optional int32 effective_scaling_mode = 40;
   // Layer's corner radius.
   optional float corner_radius = 41;
+  // Metadata map. May be empty.
+  map<int32, bytes> metadata = 42;
 }
 
 message PositionProto {
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index e34e568..b2bcb45 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -42,6 +42,7 @@
         "EventThreadTest.cpp",
         "IdleTimerTest.cpp",
         "LayerHistoryTest.cpp",
+        "LayerMetadataTest.cpp",
         "SchedulerTest.cpp",
         "SchedulerUtilsTest.cpp",
         "RefreshRateStatsTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp b/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp
new file mode 100644
index 0000000..92c9f92
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "LibSurfaceFlingerUnittests"
+
+#include <binder/Parcel.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <gui/LayerMetadata.h>
+#include <log/log.h>
+
+namespace android {
+namespace {
+
+class LayerMetadataTest : public testing::Test {
+public:
+    LayerMetadataTest();
+    ~LayerMetadataTest() override;
+};
+
+LayerMetadataTest::LayerMetadataTest() {
+    const ::testing::TestInfo* const test_info =
+            ::testing::UnitTest::GetInstance()->current_test_info();
+    ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+}
+
+LayerMetadataTest::~LayerMetadataTest() {
+    const ::testing::TestInfo* const test_info =
+            ::testing::UnitTest::GetInstance()->current_test_info();
+    ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
+}
+
+TEST_F(LayerMetadataTest, testLayerMetadata) {
+    LayerMetadata metadata;
+
+    ASSERT_EQ(0, metadata.mMap.size());
+
+    // Test non-set
+    ASSERT_EQ(3, metadata.getInt32(4, 3));
+
+    // Make sure it's still unset
+    ASSERT_EQ(5, metadata.getInt32(4, 5));
+
+    metadata.setInt32(4, 2);
+    ASSERT_EQ(2, metadata.getInt32(4, 0));
+
+    // data is too small
+    metadata.mMap[2] = std::vector<uint8_t>{'a', 'b'};
+    ASSERT_EQ(0, metadata.getInt32(2, 0));
+
+    LayerMetadata second;
+    std::vector<uint8_t> someData{'c', 'd', '\0'};
+    second.mMap[2] = someData;
+    second.setInt32(6, 5);
+    metadata.merge(second);
+
+    ASSERT_EQ(3, metadata.mMap.size());
+    ASSERT_EQ(someData, second.mMap[2]);
+    ASSERT_EQ(5, metadata.getInt32(6, 0));
+    ASSERT_EQ(2, metadata.getInt32(4, 0));
+
+    Parcel p;
+    metadata.writeToParcel(&p);
+    LayerMetadata reconstructed;
+    reconstructed.setInt32(3, 1); // to make sure it gets replaced
+    p.setDataPosition(0);
+    reconstructed.readFromParcel(&p);
+    ASSERT_EQ(metadata.mMap, reconstructed.mMap);
+}
+
+} // namespace
+} // namespace android