Added protobuf to gather layer info.

Use protobuf to gather information about the layers. This change also
uses protobuf for the layer dumpsys.

Test: Ran dumpsys for layers to confirm the data was correct.

Change-Id: Iec474e57a4fb9de1e548440d6a08685505947278
diff --git a/include/layerproto b/include/layerproto
new file mode 120000
index 0000000..ef21a4e
--- /dev/null
+++ b/include/layerproto
@@ -0,0 +1 @@
+../services/surfaceflinger/layerproto/include/layerproto/
\ No newline at end of file
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 64a2a50..bd7f0ea 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -5,4 +5,4 @@
     export_static_lib_headers = ["libserviceutils"],
 }
 
-subdirs = ["tests/fakehwc"]
\ No newline at end of file
+subdirs = ["tests/fakehwc", "layerproto"]
\ No newline at end of file
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 390263f..d8152e0 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -39,6 +39,7 @@
     RenderEngine/RenderEngine.cpp \
     RenderEngine/Texture.cpp \
     RenderEngine/GLES20RenderEngine.cpp \
+    LayerProtoHelper.cpp \
 
 LOCAL_MODULE := libsurfaceflinger
 LOCAL_C_INCLUDES := \
@@ -98,7 +99,8 @@
     libsync \
     libprotobuf-cpp-lite \
     libbase \
-    android.hardware.power@1.0
+    android.hardware.power@1.0 \
+    liblayers_proto
 
 LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := \
     android.hardware.graphics.allocator@2.0 \
@@ -145,7 +147,8 @@
     libutils \
     libui \
     libgui \
-    libdl
+    libdl \
+    liblayers_proto
 
 LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain
 LOCAL_STATIC_LIBRARIES := libtrace_proto \
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 956f7f6..27739ce 100755
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -56,6 +56,7 @@
 #include "RenderEngine/RenderEngine.h"
 
 #include <mutex>
+#include "LayerProtoHelper.h"
 
 #define DEBUG_RESIZE    0
 
@@ -2826,6 +2827,82 @@
     mDrawingParent = mCurrentParent;
 }
 
+void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) {
+    const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
+    const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
+    const State& state = useDrawing ? mDrawingState : mCurrentState;
+
+    Transform requestedTransform = state.active.transform;
+    Transform transform = getTransform();
+
+    layerInfo->set_id(sequence);
+    layerInfo->set_name(getName().c_str());
+    layerInfo->set_type(String8(getTypeId()));
+
+    for (const auto& child : children) {
+        layerInfo->add_children(child->sequence);
+    }
+
+    for (const wp<Layer>& weakRelative : state.zOrderRelatives) {
+        sp<Layer> strongRelative = weakRelative.promote();
+        if (strongRelative != nullptr) {
+            layerInfo->add_relatives(strongRelative->sequence);
+        }
+    }
+
+    LayerProtoHelper::writeToProto(state.activeTransparentRegion,
+                                   layerInfo->mutable_transparent_region());
+    LayerProtoHelper::writeToProto(visibleRegion, layerInfo->mutable_visible_region());
+    LayerProtoHelper::writeToProto(surfaceDamageRegion, layerInfo->mutable_damage_region());
+
+    layerInfo->set_layer_stack(getLayerStack());
+    layerInfo->set_z(state.z);
+
+    PositionProto* position = layerInfo->mutable_position();
+    position->set_x(transform.tx());
+    position->set_y(transform.ty());
+
+    PositionProto* requestedPosition = layerInfo->mutable_requested_position();
+    requestedPosition->set_x(requestedTransform.tx());
+    requestedPosition->set_y(requestedTransform.ty());
+
+    SizeProto* size = layerInfo->mutable_size();
+    size->set_w(state.active.w);
+    size->set_h(state.active.h);
+
+    LayerProtoHelper::writeToProto(state.crop, layerInfo->mutable_crop());
+    LayerProtoHelper::writeToProto(state.finalCrop, layerInfo->mutable_final_crop());
+
+    layerInfo->set_is_opaque(isOpaque(state));
+    layerInfo->set_invalidate(contentDirty);
+    layerInfo->set_dataspace(dataspaceDetails(getDataSpace()));
+    layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat()));
+    LayerProtoHelper::writeToProto(getColor(), layerInfo->mutable_color());
+    LayerProtoHelper::writeToProto(state.color, layerInfo->mutable_requested_color());
+    layerInfo->set_flags(state.flags);
+
+    LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform());
+    LayerProtoHelper::writeToProto(requestedTransform, layerInfo->mutable_requested_transform());
+
+    auto parent = getParent();
+    if (parent != nullptr) {
+        layerInfo->set_parent(parent->sequence);
+    }
+
+    auto zOrderRelativeOf = state.zOrderRelativeOf.promote();
+    if (zOrderRelativeOf != nullptr) {
+        layerInfo->set_z_order_relative_of(zOrderRelativeOf->sequence);
+    }
+
+    auto activeBuffer = getActiveBuffer();
+    if (activeBuffer != nullptr) {
+        LayerProtoHelper::writeToProto(activeBuffer, layerInfo->mutable_active_buffer());
+    }
+
+    layerInfo->set_queued_frames(getQueuedFrameCount());
+    layerInfo->set_refresh_pending(isBufferLatched());
+}
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 47924ae..06c4863 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -49,9 +49,12 @@
 #include "DisplayHardware/HWComposerBufferCache.h"
 #include "RenderEngine/Mesh.h"
 #include "RenderEngine/Texture.h"
+#include <layerproto/LayerProtoHeader.h>
 
 #include <math/vec4.h>
 
+using namespace android::surfaceflinger;
+
 namespace android {
 
 // ---------------------------------------------------------------------------
@@ -303,6 +306,8 @@
      */
     virtual bool isFixedSize() const;
 
+    void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
+
 protected:
     /*
      * onDraw - draws the surface.
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
new file mode 100644
index 0000000..6a33148
--- /dev/null
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "LayerProtoHelper.h"
+
+namespace android {
+namespace surfaceflinger {
+void LayerProtoHelper::writeToProto(const Region& region, RegionProto* regionProto) {
+    Region::const_iterator head = region.begin();
+    Region::const_iterator const tail = region.end();
+    uint64_t address = reinterpret_cast<uint64_t>(&region);
+    regionProto->set_id(address);
+    while (head != tail) {
+        RectProto* rectProto = regionProto->add_rect();
+        writeToProto(*head, rectProto);
+        head++;
+    }
+}
+
+void LayerProtoHelper::writeToProto(const Rect& rect, RectProto* rectProto) {
+    rectProto->set_left(rect.left);
+    rectProto->set_top(rect.top);
+    rectProto->set_bottom(rect.bottom);
+    rectProto->set_right(rect.right);
+}
+
+void LayerProtoHelper::writeToProto(const half4 color, ColorProto* colorProto) {
+    colorProto->set_r(color.r);
+    colorProto->set_g(color.g);
+    colorProto->set_b(color.b);
+    colorProto->set_a(color.a);
+}
+
+void LayerProtoHelper::writeToProto(const Transform& transform, TransformProto* transformProto) {
+    transformProto->set_dsdx(transform[0][0]);
+    transformProto->set_dtdx(transform[0][1]);
+    transformProto->set_dsdy(transform[1][0]);
+    transformProto->set_dtdy(transform[1][1]);
+}
+
+void LayerProtoHelper::writeToProto(const sp<GraphicBuffer>& buffer,
+                                    ActiveBufferProto* activeBufferProto) {
+    activeBufferProto->set_width(buffer->getWidth());
+    activeBufferProto->set_height(buffer->getHeight());
+    activeBufferProto->set_stride(buffer->getStride());
+    activeBufferProto->set_format(buffer->format);
+}
+
+} // namespace surfaceflinger
+} // namespace android
diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h
new file mode 100644
index 0000000..45a0b5d
--- /dev/null
+++ b/services/surfaceflinger/LayerProtoHelper.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <layerproto/LayerProtoHeader.h>
+
+#include <ui/GraphicBuffer.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+#include <Transform.h>
+
+#include <math/vec4.h>
+
+namespace android {
+namespace surfaceflinger {
+class LayerProtoHelper {
+public:
+    static void writeToProto(const Rect& rect, RectProto* rectProto);
+    static void writeToProto(const Region& region, RegionProto* regionProto);
+    static void writeToProto(const half4 color, ColorProto* colorProto);
+    static void writeToProto(const Transform& transform, TransformProto* transformProto);
+    static void writeToProto(const sp<GraphicBuffer>& buffer, ActiveBufferProto* activeBufferProto);
+};
+
+} // namespace surfaceflinger
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5982422..4a98252 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -90,6 +90,8 @@
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <configstore/Utils.h>
 
+#include <layerproto/LayerProtoParser.h>
+
 #define DISPLAY_COUNT       1
 
 /*
@@ -3532,6 +3534,13 @@
                 dumpWideColorInfo(result);
                 dumpAll = false;
             }
+
+            if ((index < numArgs) && (args[index] == String16("--proto"))) {
+                index++;
+                LayersProto layersProto = dumpProtoInfo();
+                result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize());
+                dumpAll = false;
+            }
         }
 
         if (dumpAll) {
@@ -3727,6 +3736,16 @@
     result.append("\n");
 }
 
+LayersProto SurfaceFlinger::dumpProtoInfo() const {
+    LayersProto layersProto;
+    mCurrentState.traverseInZOrder([&](Layer* layer) {
+        LayerProto* layerProto = layersProto.add_layers();
+        layer->writeToProto(layerProto, LayerVector::StateSet::Current);
+    });
+
+    return layersProto;
+}
+
 void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
         String8& result) const
 {
@@ -3791,9 +3810,10 @@
     colorizer.bold(result);
     result.appendFormat("Visible layers (count = %zu)\n", mNumLayers);
     colorizer.reset(result);
-    mCurrentState.traverseInZOrder([&](Layer* layer) {
-        result.append(to_string(layer->getLayerDebugInfo()).c_str());
-    });
+
+    LayersProto layersProto = dumpProtoInfo();
+    auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
+    result.append(LayerProtoParser::layersToString(layerTree).c_str());
 
     /*
      * Dump Display state
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 2cba500..9030124 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -78,6 +78,10 @@
 #include <thread>
 #include <utility>
 
+#include <layerproto/LayerProtoHeader.h>
+
+using namespace android::surfaceflinger;
+
 namespace android {
 
 // ---------------------------------------------------------------------------
@@ -622,6 +626,7 @@
             std::vector<OccupancyTracker::Segment>&& history);
     void dumpBufferingStats(String8& result) const;
     void dumpWideColorInfo(String8& result) const;
+    LayersProto dumpProtoInfo() const;
 
     bool isLayerTripleBufferingDisabled() const {
         return this->mLayerTripleBufferingDisabled;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index b718ec8..ed7641f 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -87,6 +87,8 @@
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <configstore/Utils.h>
 
+#include <layerproto/LayerProtoParser.h>
+
 #define DISPLAY_COUNT       1
 
 /*
@@ -3073,6 +3075,13 @@
                 dumpFrameEventsLocked(result);
                 dumpAll = false;
             }
+
+            if ((index < numArgs) && (args[index] == String16("--proto"))) {
+                index++;
+                LayersProto layersProto = dumpProtoInfo();
+                result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize());
+                dumpAll = false;
+            }
         }
 
         if (dumpAll) {
@@ -3243,6 +3252,16 @@
     result.append("\n");
 }
 
+LayersProto SurfaceFlinger::dumpProtoInfo() const {
+    LayersProto layersProto;
+    mCurrentState.traverseInZOrder([&](Layer* layer) {
+        LayerProto* layerProto = layersProto.add_layers();
+        layer->writeToProto(layerProto, LayerVector::StateSet::Current);
+    });
+
+    return layersProto;
+}
+
 void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
         String8& result) const
 {
@@ -3302,9 +3321,10 @@
     colorizer.bold(result);
     result.appendFormat("Visible layers (count = %zu)\n", mNumLayers);
     colorizer.reset(result);
-    mCurrentState.traverseInZOrder([&](Layer* layer) {
-        result.append(to_string(layer->getLayerDebugInfo()).c_str());
-    });
+
+    LayersProto layersProto = dumpProtoInfo();
+    auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
+    result.append(LayerProtoParser::layersToString(layerTree).c_str());
 
     /*
      * Dump Display state
diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp
new file mode 100644
index 0000000..4c52bdf
--- /dev/null
+++ b/services/surfaceflinger/layerproto/Android.bp
@@ -0,0 +1,35 @@
+cc_library_shared {
+    name: "liblayers_proto",
+    vendor_available: true,
+    export_include_dirs: ["include"],
+
+    srcs: [
+        "LayerProtoParser.cpp",
+        "layers.proto",
+    ],
+
+    shared_libs: [
+        "libui",
+        "libprotobuf-cpp-lite",
+        "libbase",
+    ],
+
+    proto: {
+        export_proto_headers: true,
+    },
+
+    cppflags: [
+        "-Werror",
+        "-Wno-unused-parameter",
+        "-Wno-format",
+        "-Wno-c++98-compat-pedantic",
+        "-Wno-float-conversion",
+        "-Wno-disabled-macro-expansion",
+        "-Wno-float-equal",
+        "-Wno-sign-conversion",
+        "-Wno-padded",
+        "-Wno-old-style-cast",
+        "-Wno-undef",
+    ],
+
+}
\ No newline at end of file
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
new file mode 100644
index 0000000..6554167
--- /dev/null
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <layerproto/LayerProtoParser.h>
+
+namespace android {
+namespace surfaceflinger {
+bool sortLayers(const LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs) {
+    uint32_t ls = lhs->layerStack;
+    uint32_t rs = rhs->layerStack;
+    if (ls != rs) return ls < rs;
+
+    uint32_t lz = lhs->z;
+    uint32_t rz = rhs->z;
+    if (lz != rz) return lz < rz;
+
+    return lhs->id < rhs->id;
+}
+
+std::vector<const LayerProtoParser::Layer*> LayerProtoParser::generateLayerTree(
+        const LayersProto& layersProto) {
+    auto layerMap = generateMap(layersProto);
+
+    std::vector<const Layer*> layers;
+    std::for_each(layerMap.begin(), layerMap.end(),
+                  [&](const std::pair<const int32_t, Layer*>& ref) {
+                      if (ref.second->parent == nullptr) {
+                          // only save top level layers
+                          layers.push_back(ref.second);
+                      }
+                  });
+
+    std::sort(layers.begin(), layers.end(), sortLayers);
+    return layers;
+}
+
+std::unordered_map<int32_t, LayerProtoParser::Layer*> LayerProtoParser::generateMap(
+        const LayersProto& layersProto) {
+    std::unordered_map<int32_t, Layer*> layerMap;
+
+    for (int i = 0; i < layersProto.layers_size(); i++) {
+        const LayerProto& layerProto = layersProto.layers(i);
+        layerMap[layerProto.id()] = generateLayer(layerProto);
+    }
+
+    for (int i = 0; i < layersProto.layers_size(); i++) {
+        const LayerProto& layerProto = layersProto.layers(i);
+        updateChildrenAndRelative(layerProto, layerMap);
+    }
+
+    return layerMap;
+}
+
+LayerProtoParser::Layer* LayerProtoParser::generateLayer(const LayerProto& layerProto) {
+    Layer* layer = new Layer();
+    layer->id = layerProto.id();
+    layer->name = layerProto.name();
+    layer->type = layerProto.type();
+    layer->transparentRegion = generateRegion(layerProto.transparent_region());
+    layer->visibleRegion = generateRegion(layerProto.visible_region());
+    layer->damageRegion = generateRegion(layerProto.damage_region());
+    layer->layerStack = layerProto.layer_stack();
+    layer->z = layerProto.z();
+    layer->position = {layerProto.position().x(), layerProto.position().y()};
+    layer->requestedPosition = {layerProto.requested_position().x(),
+                                layerProto.requested_position().y()};
+    layer->size = {layerProto.size().w(), layerProto.size().h()};
+    layer->crop = generateRect(layerProto.crop());
+    layer->finalCrop = generateRect(layerProto.final_crop());
+    layer->isOpaque = layerProto.is_opaque();
+    layer->invalidate = layerProto.invalidate();
+    layer->dataspace = layerProto.dataspace();
+    layer->pixelFormat = layerProto.pixel_format();
+    layer->color = {layerProto.color().r(), layerProto.color().g(), layerProto.color().b(),
+                    layerProto.color().a()};
+    layer->requestedColor = {layerProto.requested_color().r(), layerProto.requested_color().g(),
+                             layerProto.requested_color().b(), layerProto.requested_color().a()};
+    layer->flags = layerProto.flags();
+    layer->transform = generateTransform(layerProto.transform());
+    layer->requestedTransform = generateTransform(layerProto.requested_transform());
+    layer->activeBuffer = generateActiveBuffer(layerProto.active_buffer());
+    layer->queuedFrames = layerProto.queued_frames();
+    layer->refreshPending = layerProto.refresh_pending();
+
+    return layer;
+}
+
+LayerProtoParser::Region LayerProtoParser::generateRegion(const RegionProto& regionProto) {
+    LayerProtoParser::Region region;
+    region.id = regionProto.id();
+    for (int i = 0; i < regionProto.rect_size(); i++) {
+        const RectProto& rectProto = regionProto.rect(i);
+        region.rects.push_back(generateRect(rectProto));
+    }
+
+    return region;
+}
+
+LayerProtoParser::Rect LayerProtoParser::generateRect(const RectProto& rectProto) {
+    LayerProtoParser::Rect rect;
+    rect.left = rectProto.left();
+    rect.top = rectProto.top();
+    rect.right = rectProto.right();
+    rect.bottom = rectProto.bottom();
+
+    return rect;
+}
+
+LayerProtoParser::Transform LayerProtoParser::generateTransform(
+        const TransformProto& transformProto) {
+    LayerProtoParser::Transform transform;
+    transform.dsdx = transformProto.dsdx();
+    transform.dtdx = transformProto.dtdx();
+    transform.dsdy = transformProto.dsdy();
+    transform.dtdy = transformProto.dtdy();
+
+    return transform;
+}
+
+LayerProtoParser::ActiveBuffer LayerProtoParser::generateActiveBuffer(
+        const ActiveBufferProto& activeBufferProto) {
+    LayerProtoParser::ActiveBuffer activeBuffer;
+    activeBuffer.width = activeBufferProto.width();
+    activeBuffer.height = activeBufferProto.height();
+    activeBuffer.stride = activeBufferProto.stride();
+    activeBuffer.format = activeBufferProto.format();
+
+    return activeBuffer;
+}
+
+void LayerProtoParser::updateChildrenAndRelative(const LayerProto& layerProto,
+                                                 std::unordered_map<int32_t, Layer*>& layerMap) {
+    auto currLayer = layerMap[layerProto.id()];
+
+    for (int i = 0; i < layerProto.children_size(); i++) {
+        if (layerMap.count(layerProto.children(i)) > 0) {
+            auto childLayer = layerMap[layerProto.children(i)];
+            currLayer->children.push_back(childLayer);
+        }
+    }
+
+    for (int i = 0; i < layerProto.relatives_size(); i++) {
+        if (layerMap.count(layerProto.relatives(i)) > 0) {
+            auto relativeLayer = layerMap[layerProto.relatives(i)];
+            currLayer->relatives.push_back(relativeLayer);
+        }
+    }
+
+    if (layerProto.has_parent()) {
+        if (layerMap.count(layerProto.parent()) > 0) {
+            auto parentLayer = layerMap[layerProto.parent()];
+            currLayer->parent = parentLayer;
+        }
+    }
+
+    if (layerProto.has_z_order_relative_of()) {
+        if (layerMap.count(layerProto.z_order_relative_of()) > 0) {
+            auto relativeLayer = layerMap[layerProto.z_order_relative_of()];
+            currLayer->zOrderRelativeOf = relativeLayer;
+        }
+    }
+}
+
+std::string LayerProtoParser::layersToString(
+        const std::vector<const LayerProtoParser::Layer*> layers) {
+    std::string result;
+    for (const LayerProtoParser::Layer* layer : layers) {
+        if (layer->zOrderRelativeOf != nullptr) {
+            continue;
+        }
+        result.append(layerToString(layer).c_str());
+    }
+
+    return result;
+}
+
+std::string LayerProtoParser::layerToString(const LayerProtoParser::Layer* layer) {
+    std::string result;
+
+    std::vector<const Layer*> traverse(layer->relatives);
+    for (const LayerProtoParser::Layer* child : layer->children) {
+        if (child->zOrderRelativeOf != nullptr) {
+            continue;
+        }
+
+        traverse.push_back(child);
+    }
+
+    std::sort(traverse.begin(), traverse.end(), sortLayers);
+
+    size_t i = 0;
+    for (; i < traverse.size(); i++) {
+        const auto& relative = traverse[i];
+        if (relative->z >= 0) {
+            break;
+        }
+        result.append(layerToString(relative).c_str());
+    }
+    result.append(layer->to_string().c_str());
+    result.append("\n");
+    for (; i < traverse.size(); i++) {
+        const auto& relative = traverse[i];
+        result.append(layerToString(relative).c_str());
+    }
+
+    return result;
+}
+
+} // namespace surfaceflinger
+} // namespace android
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h
new file mode 100644
index 0000000..054d4f2
--- /dev/null
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Projectlayerproto/LayerProtoHeader.h
+ *
+ * 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 is used here to disable the warnings emitted from the protobuf
+// headers. By adding #pragma before including layer.pb.h, it supresses
+// protobuf warnings, but allows the rest of the files to continuing using
+// the current flags.
+// This file should be included instead of directly including layer.b.h
+#pragma GCC system_header
+#include <layers.pb.h>
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
new file mode 100644
index 0000000..7b94cef
--- /dev/null
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <layerproto/LayerProtoHeader.h>
+
+#include <math/vec4.h>
+
+#include <android-base/stringprintf.h>
+#include <ui/DebugUtils.h>
+#include <unordered_map>
+#include <vector>
+
+using android::base::StringAppendF;
+using android::base::StringPrintf;
+
+namespace android {
+namespace surfaceflinger {
+
+class LayerProtoParser {
+public:
+    class ActiveBuffer {
+    public:
+        uint32_t width;
+        uint32_t height;
+        uint32_t stride;
+        int32_t format;
+
+        std::string to_string() const {
+            return StringPrintf("[%4ux%4u:%4u,%s]", width, height, stride,
+                                decodePixelFormat(format).c_str());
+        }
+    };
+
+    class Transform {
+    public:
+        float dsdx;
+        float dtdx;
+        float dsdy;
+        float dtdy;
+
+        std::string to_string() const {
+            return StringPrintf("[%.2f, %.2f][%.2f, %.2f]", static_cast<double>(dsdx),
+                                static_cast<double>(dtdx), static_cast<double>(dsdy),
+                                static_cast<double>(dtdy));
+        }
+    };
+
+    class Rect {
+    public:
+        int32_t left;
+        int32_t top;
+        int32_t right;
+        int32_t bottom;
+
+        std::string to_string() const {
+            return StringPrintf("[%3d, %3d, %3d, %3d]", left, top, right, bottom);
+        }
+    };
+
+    class Region {
+    public:
+        uint64_t id;
+        std::vector<Rect> rects;
+
+        std::string to_string(const char* what) const {
+            std::string result =
+                    StringPrintf("  Region %s (this=%lx count=%d)\n", what,
+                                 static_cast<unsigned long>(id), static_cast<int>(rects.size()));
+
+            for (auto& rect : rects) {
+                StringAppendF(&result, "    %s\n", rect.to_string().c_str());
+            }
+
+            return result;
+        }
+    };
+
+    class Layer {
+    public:
+        int32_t id;
+        std::string name;
+        std::vector<const Layer*> children;
+        std::vector<const Layer*> relatives;
+        std::string type;
+        LayerProtoParser::Region transparentRegion;
+        LayerProtoParser::Region visibleRegion;
+        LayerProtoParser::Region damageRegion;
+        uint32_t layerStack;
+        int32_t z;
+        float2 position;
+        float2 requestedPosition;
+        int2 size;
+        LayerProtoParser::Rect crop;
+        LayerProtoParser::Rect finalCrop;
+        bool isOpaque;
+        bool invalidate;
+        std::string dataspace;
+        std::string pixelFormat;
+        half4 color;
+        half4 requestedColor;
+        uint32_t flags;
+        Transform transform;
+        Transform requestedTransform;
+        Layer* parent = 0;
+        Layer* zOrderRelativeOf = 0;
+        LayerProtoParser::ActiveBuffer activeBuffer;
+        int32_t queuedFrames;
+        bool refreshPending;
+
+        std::string to_string() const {
+            std::string result;
+            StringAppendF(&result, "+ %s (%s)\n", type.c_str(), name.c_str());
+            result.append(transparentRegion.to_string("TransparentRegion").c_str());
+            result.append(visibleRegion.to_string("VisibleRegion").c_str());
+            result.append(damageRegion.to_string("SurfaceDamageRegion").c_str());
+
+            StringAppendF(&result, "      layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), ",
+                          layerStack, z, static_cast<double>(position.x),
+                          static_cast<double>(position.y), size.x, size.y);
+
+            StringAppendF(&result, "crop=%s, finalCrop=%s, ", crop.to_string().c_str(),
+                          finalCrop.to_string().c_str());
+            StringAppendF(&result, "isOpaque=%1d, invalidate=%1d, ", isOpaque, invalidate);
+            StringAppendF(&result, "dataspace=%s, ", dataspace.c_str());
+            StringAppendF(&result, "pixelformat=%s, ", pixelFormat.c_str());
+            StringAppendF(&result, "color=(%.3f,%.3f,%.3f,%.3f), flags=0x%08x, ",
+                          static_cast<double>(color.r), static_cast<double>(color.g),
+                          static_cast<double>(color.b), static_cast<double>(color.a), flags);
+            StringAppendF(&result, "tr=%s", transform.to_string().c_str());
+            result.append("\n");
+            StringAppendF(&result, "      parent=%s\n",
+                          parent == nullptr ? "none" : parent->name.c_str());
+            StringAppendF(&result, "      zOrderRelativeOf=%s\n",
+                          zOrderRelativeOf == nullptr ? "none" : zOrderRelativeOf->name.c_str());
+            StringAppendF(&result, "      activeBuffer=%s,", activeBuffer.to_string().c_str());
+            StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d", queuedFrames,
+                          refreshPending);
+
+            return result;
+        }
+    };
+
+    static std::vector<const Layer*> generateLayerTree(const LayersProto& layersProto);
+    static std::string layersToString(const std::vector<const LayerProtoParser::Layer*> layers);
+
+private:
+    static std::unordered_map<int32_t, Layer*> generateMap(const LayersProto& layersProto);
+    static LayerProtoParser::Layer* generateLayer(const LayerProto& layerProto);
+    static LayerProtoParser::Region generateRegion(const RegionProto& regionProto);
+    static LayerProtoParser::Rect generateRect(const RectProto& rectProto);
+    static LayerProtoParser::Transform generateTransform(const TransformProto& transformProto);
+    static LayerProtoParser::ActiveBuffer generateActiveBuffer(
+            const ActiveBufferProto& activeBufferProto);
+    static void updateChildrenAndRelative(const LayerProto& layerProto,
+                                          std::unordered_map<int32_t, Layer*>& layerMap);
+
+    static std::string layerToString(const LayerProtoParser::Layer* layer);
+};
+
+} // namespace surfaceflinger
+} // namespace android
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
new file mode 100644
index 0000000..d27dc9b
--- /dev/null
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -0,0 +1,110 @@
+// Definitions for SurfaceFlinger layers.
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+package android.surfaceflinger;
+
+// Contains a list of all layers.
+message LayersProto {
+  repeated LayerProto layers = 1;
+}
+
+// Information about each layer.
+message LayerProto {
+  // unique id per layer.
+  optional int32 id = 1;
+  // unique name per layer.
+  optional string name = 2;
+  // list of children this layer may have. May be empty.
+  repeated int32 children = 3;
+  // list of layers that are z order relative to this layer.
+  repeated int32 relatives = 4;
+  // The type of layer, ex Color, Layer
+  optional string type = 5;
+  optional RegionProto transparent_region = 6;
+  optional RegionProto visible_region = 7;
+  optional RegionProto damage_region = 8;
+  optional uint32 layer_stack = 9;
+  // The layer's z order. Can be z order in layer stack, relative to parent,
+  // or relative to another layer specified in zOrderRelative.
+  optional int32 z = 10;
+  // The layer's position on the display.
+  optional PositionProto position = 11;
+  // The layer's requested position.
+  optional PositionProto requested_position = 12;
+  // The layer's size.
+  optional SizeProto size = 13;
+  // The layer's crop in it's own bounds.
+  optional RectProto crop = 14;
+  // The layer's crop in it's parent's bounds.
+  optional RectProto final_crop = 15;
+  optional bool is_opaque = 16;
+  optional bool invalidate = 17;
+  optional string dataspace = 18;
+  optional string pixel_format = 19;
+  // The layer's actual color.
+  optional ColorProto color = 20;
+  // The layer's requested color.
+  optional ColorProto requested_color = 21;
+  // Can be any combination of
+  //    hidden = 0x01
+  //    opaque = 0x02,
+  //    secure = 0x80,
+  optional uint32 flags = 22;
+  // The layer's actual transform
+  optional TransformProto transform = 23;
+  // The layer's requested transform.
+  optional TransformProto requested_transform = 24;
+  // The parent layer. This value can be null if there is no parent.
+  optional int32 parent = 25 [default = -1];
+  // The layer that this layer has a z order relative to. This value can be null.
+  optional int32 z_order_relative_of = 26 [default = -1];
+  // This value can be null if there's nothing to draw.
+  optional ActiveBufferProto active_buffer = 27;
+  // The number of frames available.
+  optional int32 queued_frames = 28;
+  optional bool refresh_pending = 29;
+}
+
+message PositionProto {
+  optional float x = 1;
+  optional float y = 2;
+}
+
+message SizeProto {
+  optional int32 w = 1;
+  optional int32 h = 2;
+}
+
+message TransformProto {
+  optional float dsdx = 1;
+  optional float dtdx = 2;
+  optional float dsdy = 3;
+  optional float dtdy = 4;
+}
+
+message RegionProto {
+  optional uint64 id = 1;
+  repeated RectProto rect = 2;
+}
+
+message RectProto {
+  optional int32 left   = 1;
+  optional int32 top    = 2;
+  optional int32 right  = 3;
+  optional int32 bottom = 4;
+}
+
+message ActiveBufferProto {
+  optional uint32 width = 1;
+  optional uint32 height = 2;
+  optional uint32 stride = 3;
+  optional int32 format = 4;
+}
+
+message ColorProto {
+  optional float r = 1;
+  optional float g = 2;
+  optional float b = 3;
+  optional float a = 4;
+}
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 94f3f25..212b9e7 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -22,7 +22,8 @@
         "libsync",
         "libfmq",
         "libbase",
-        "libhidltransport"
+        "libhidltransport",
+        "liblayers_proto"
     ],
     static_libs: [
         "libhwcomposer-client",