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