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/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