Merge "Implement Display Layer Stats V0.1"
diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp
index d7e191d..d5654cc 100644
--- a/libs/ui/DebugUtils.cpp
+++ b/libs/ui/DebugUtils.cpp
@@ -234,6 +234,33 @@
return android::base::StringPrintf("Unknown color mode %d", colorMode);
}
+std::string decodeColorTransform(android_color_transform colorTransform) {
+ switch (colorTransform) {
+ case HAL_COLOR_TRANSFORM_IDENTITY:
+ return std::string("Identity");
+
+ case HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX:
+ return std::string("Arbitrary matrix");
+
+ case HAL_COLOR_TRANSFORM_VALUE_INVERSE:
+ return std::string("Inverse value");
+
+ case HAL_COLOR_TRANSFORM_GRAYSCALE:
+ return std::string("Grayscale");
+
+ case HAL_COLOR_TRANSFORM_CORRECT_PROTANOPIA:
+ return std::string("Correct protanopia");
+
+ case HAL_COLOR_TRANSFORM_CORRECT_DEUTERANOPIA:
+ return std::string("Correct deuteranopia");
+
+ case HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA:
+ return std::string("Correct tritanopia");
+ }
+
+ return android::base::StringPrintf("Unknown color transform %d", colorTransform);
+}
+
// Converts a PixelFormat to a human-readable string. Max 11 chars.
// (Could use a table of prefab String8 objects.)
std::string decodePixelFormat(android::PixelFormat format) {
diff --git a/libs/ui/include/ui/DebugUtils.h b/libs/ui/include/ui/DebugUtils.h
index 3370107..7690093 100644
--- a/libs/ui/include/ui/DebugUtils.h
+++ b/libs/ui/include/ui/DebugUtils.h
@@ -30,5 +30,6 @@
std::string decodeRange(android_dataspace dataspace);
std::string dataspaceDetails(android_dataspace dataspace);
std::string decodeColorMode(android::ColorMode colormode);
+std::string decodeColorTransform(android_color_transform colorTransform);
std::string decodePixelFormat(android::PixelFormat format);
std::string to_string(const android::Rect& rect);
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index fe0b30b..e4161bb 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -98,6 +98,7 @@
mPowerMode(initialPowerMode),
mActiveConfig(0),
mActiveColorMode(ColorMode::NATIVE),
+ mColorTransform(HAL_COLOR_TRANSFORM_IDENTITY),
mDisplayHasWideColor(supportWideColor),
mDisplayHasHdr(supportHdr)
{
@@ -268,6 +269,16 @@
return mActiveColorMode;
}
+void DisplayDevice::setColorTransform(const mat4& transform) {
+ const bool isIdentity = (transform == mat4());
+ mColorTransform =
+ isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY : HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX;
+}
+
+android_color_transform_t DisplayDevice::getColorTransform() const {
+ return mColorTransform;
+}
+
void DisplayDevice::setCompositionDataSpace(android_dataspace dataspace) {
ANativeWindow* const window = mNativeWindow.get();
native_window_set_buffers_data_space(window, dataspace);
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index fbb0d46..c1ef2e8 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -21,6 +21,8 @@
#include <stdlib.h>
+#include <math/mat4.h>
+
#include <ui/Region.h>
#include <binder/IBinder.h>
@@ -163,6 +165,8 @@
ColorMode getActiveColorMode() const;
void setActiveColorMode(ColorMode mode);
+ android_color_transform_t getColorTransform() const;
+ void setColorTransform(const mat4& transform);
void setCompositionDataSpace(android_dataspace dataspace);
/* ------------------------------------------------------------------------
@@ -237,6 +241,8 @@
int mActiveConfig;
// current active color mode
ColorMode mActiveColorMode;
+ // Current color transform
+ android_color_transform_t mColorTransform;
// Need to know if display is wide-color capable or not.
// Initialized by SurfaceFlinger when the DisplayDevice is created.
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 7aa660e..5428e2e 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -42,6 +42,7 @@
#include <gui/LayerDebugInfo.h>
#include <gui/Surface.h>
+#include "BufferLayer.h"
#include "Colorizer.h"
#include "DisplayDevice.h"
#include "Layer.h"
@@ -1929,6 +1930,16 @@
const int32_t transform = static_cast<int32_t>(hwcInfo.transform);
layerInfo->set_hwc_transform(transform);
+
+ const int32_t compositionType = static_cast<int32_t>(hwcInfo.compositionType);
+ layerInfo->set_hwc_composition_type(compositionType);
+
+ if (std::strcmp(getTypeId(), "BufferLayer") == 0 &&
+ static_cast<BufferLayer*>(this)->isProtected()) {
+ layerInfo->set_is_protected(true);
+ } else {
+ layerInfo->set_is_protected(false);
+ }
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerStats.cpp b/services/surfaceflinger/LayerStats.cpp
index ad1043f..38ea6ed 100644
--- a/services/surfaceflinger/LayerStats.cpp
+++ b/services/surfaceflinger/LayerStats.cpp
@@ -19,6 +19,7 @@
#include "LayerStats.h"
#include "DisplayHardware/HWComposer.h"
+#include "ui/DebugUtils.h"
#include <android-base/stringprintf.h>
#include <log/log.h>
@@ -31,7 +32,7 @@
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mMutex);
if (mEnabled) return;
- mLayerStatsMap.clear();
+ mLayerShapeStatsMap.clear();
mEnabled = true;
ALOGD("Logging enabled");
}
@@ -47,7 +48,7 @@
void LayerStats::clear() {
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mMutex);
- mLayerStatsMap.clear();
+ mLayerShapeStatsMap.clear();
ALOGD("Cleared current layer stats");
}
@@ -57,42 +58,69 @@
void LayerStats::traverseLayerTreeStatsLocked(
std::vector<std::unique_ptr<LayerProtoParser::Layer>> layerTree,
- const LayerProtoParser::LayerGlobal* layerGlobal) {
+ const LayerProtoParser::LayerGlobal* layerGlobal, std::vector<std::string>& layerShapeVec) {
for (std::unique_ptr<LayerProtoParser::Layer>& layer : layerTree) {
if (!layer) continue;
- traverseLayerTreeStatsLocked(std::move(layer->children), layerGlobal);
- std::string key =
- base::StringPrintf("%s,%s,%s,%s,%s,%s,%s,%s,%s",
- destinationLocation(layer->hwcFrame.left,
- layerGlobal->resolution[0], true),
- destinationLocation(layer->hwcFrame.top,
- layerGlobal->resolution[1], false),
- destinationSize(layer->hwcFrame.right - layer->hwcFrame.left,
- layerGlobal->resolution[0], true),
- destinationSize(layer->hwcFrame.bottom - layer->hwcFrame.top,
- layerGlobal->resolution[1], false),
- layer->type.c_str(), scaleRatioWH(layer.get()).c_str(),
- layerTransform(layer->hwcTransform), layer->pixelFormat.c_str(),
- layer->dataspace.c_str());
- mLayerStatsMap[key]++;
+ traverseLayerTreeStatsLocked(std::move(layer->children), layerGlobal, layerShapeVec);
+ std::string key = "";
+ base::StringAppendF(&key, ",%s", layer->type.c_str());
+ base::StringAppendF(&key, ",%s", layerCompositionType(layer->hwcCompositionType));
+ base::StringAppendF(&key, ",%d", layer->isProtected);
+ base::StringAppendF(&key, ",%s", layerTransform(layer->hwcTransform));
+ base::StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format));
+ base::StringAppendF(&key, ",%s", layer->dataspace.c_str());
+ base::StringAppendF(&key, ",%s",
+ destinationLocation(layer->hwcFrame.left, layerGlobal->resolution[0],
+ true));
+ base::StringAppendF(&key, ",%s",
+ destinationLocation(layer->hwcFrame.top, layerGlobal->resolution[1],
+ false));
+ base::StringAppendF(&key, ",%s",
+ destinationSize(layer->hwcFrame.right - layer->hwcFrame.left,
+ layerGlobal->resolution[0], true));
+ base::StringAppendF(&key, ",%s",
+ destinationSize(layer->hwcFrame.bottom - layer->hwcFrame.top,
+ layerGlobal->resolution[1], false));
+ base::StringAppendF(&key, ",%s", scaleRatioWH(layer.get()).c_str());
+ base::StringAppendF(&key, ",%s", alpha(static_cast<float>(layer->color.a)));
+
+ layerShapeVec.push_back(key);
+ ALOGV("%s", key.c_str());
}
}
void LayerStats::logLayerStats(const LayersProto& layersProto) {
ATRACE_CALL();
+ ALOGV("Logging");
auto layerGlobal = LayerProtoParser::generateLayerGlobalInfo(layersProto);
auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
+ std::vector<std::string> layerShapeVec;
+
std::lock_guard<std::mutex> lock(mMutex);
- traverseLayerTreeStatsLocked(std::move(layerTree), &layerGlobal);
+ traverseLayerTreeStatsLocked(std::move(layerTree), &layerGlobal, layerShapeVec);
+
+ std::string layerShapeKey =
+ base::StringPrintf("%d,%s,%s,%s", static_cast<int32_t>(layerShapeVec.size()),
+ layerGlobal.colorMode.c_str(), layerGlobal.colorTransform.c_str(),
+ layerTransform(layerGlobal.globalTransform));
+ ALOGV("%s", layerShapeKey.c_str());
+
+ std::sort(layerShapeVec.begin(), layerShapeVec.end(), std::greater<std::string>());
+ for (auto const& s : layerShapeVec) {
+ layerShapeKey += s;
+ }
+
+ mLayerShapeStatsMap[layerShapeKey]++;
}
void LayerStats::dump(String8& result) {
ATRACE_CALL();
ALOGD("Dumping");
- result.append("Count,DstPosX,DstPosY,DstWidth,DstHeight,LayerType,WScale,HScale,");
- result.append("Transform,PixelFormat,Dataspace\n");
std::lock_guard<std::mutex> lock(mMutex);
- for (auto& u : mLayerStatsMap) {
+ result.append("Frequency,LayerCount,ColorMode,ColorTransform,Orientation\n");
+ result.append("LayerType,CompositionType,IsProtected,Transform,PixelFormat,Dataspace,");
+ result.append("DstX,DstY,DstWidth,DstHeight,WScale,HScale,Alpha\n");
+ for (auto& u : mLayerShapeStatsMap) {
result.appendFormat("%u,%s\n", u.second, u.first.c_str());
}
}
@@ -129,6 +157,14 @@
return getTransformName(static_cast<hwc_transform_t>(transform));
}
+const char* LayerStats::layerCompositionType(int32_t compositionType) {
+ return getCompositionName(static_cast<hwc2_composition_t>(compositionType));
+}
+
+const char* LayerStats::layerPixelFormat(int32_t pixelFormat) {
+ return decodePixelFormat(pixelFormat).c_str();
+}
+
std::string LayerStats::scaleRatioWH(const LayerProtoParser::Layer* layer) {
if (!layer->type.compare("ColorLayer")) return "N/A,N/A";
std::string ret = "";
@@ -166,6 +202,21 @@
return ">=16";
}
+const char* LayerStats::alpha(float a) {
+ if (a == 1.0f) return "1.0";
+ if (a > 0.9f) return "0.99";
+ if (a > 0.8f) return "0.9";
+ if (a > 0.7f) return "0.8";
+ if (a > 0.6f) return "0.7";
+ if (a > 0.5f) return "0.6";
+ if (a > 0.4f) return "0.5";
+ if (a > 0.3f) return "0.4";
+ if (a > 0.2f) return "0.3";
+ if (a > 0.1f) return "0.2";
+ if (a > 0.0f) return "0.1";
+ return "0.0";
+}
+
bool LayerStats::isRotated(int32_t transform) {
return transform & HWC_TRANSFORM_ROT_90;
}
diff --git a/services/surfaceflinger/LayerStats.h b/services/surfaceflinger/LayerStats.h
index 9522725..7871fc6 100644
--- a/services/surfaceflinger/LayerStats.h
+++ b/services/surfaceflinger/LayerStats.h
@@ -38,18 +38,25 @@
private:
// Traverse layer tree to get all visible layers' stats
void traverseLayerTreeStatsLocked(
- std::vector<std::unique_ptr<LayerProtoParser::Layer>> layerTree,
- const LayerProtoParser::LayerGlobal* layerGlobal);
+ std::vector<std::unique_ptr<LayerProtoParser::Layer>> layerTree,
+ const LayerProtoParser::LayerGlobal* layerGlobal,
+ std::vector<std::string>& layerShapeVec);
// Convert layer's top-left position into 8x8 percentage of the display
static const char* destinationLocation(int32_t location, int32_t range, bool isHorizontal);
// Convert layer's size into 8x8 percentage of the display
static const char* destinationSize(int32_t size, int32_t range, bool isWidth);
// Return the name of the transform
static const char* layerTransform(int32_t transform);
+ // Return the name of the composition type
+ static const char* layerCompositionType(int32_t compositionType);
+ // Return the name of the pixel format
+ static const char* layerPixelFormat(int32_t pixelFormat);
// Calculate scale ratios of layer's width/height with rotation information
static std::string scaleRatioWH(const LayerProtoParser::Layer* layer);
// Calculate scale ratio from source to destination and convert to string
static const char* scaleRatio(int32_t destinationScale, int32_t sourceScale);
+ // Bucket the alpha into designed buckets
+ static const char* alpha(float a);
// Return whether the original buffer is rotated in final composition
static bool isRotated(int32_t transform);
// Return whether the original buffer is V-flipped in final composition
@@ -60,10 +67,10 @@
bool mEnabled = false;
// Protect mLayersStatsMap
std::mutex mMutex;
- // Hashmap for tracking the layer stats
- // KEY is a concatenation of a particular set of layer properties
- // VALUE is the number of times this particular get scanned out
- std::unordered_map<std::string, uint32_t> mLayerStatsMap;
+ // Hashmap for tracking the frame(layer shape) stats
+ // KEY is a concatenation of all layers' properties within a frame
+ // VALUE is the number of times this particular set has been scanned out
+ std::unordered_map<std::string, uint32_t> mLayerShapeStatsMap;
};
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6b3c5a4..b9e5d3f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1959,6 +1959,7 @@
continue;
}
if (colorMatrix != mPreviousColorMatrix) {
+ displayDevice->setColorTransform(colorMatrix);
status_t result = getBE().mHwc->setColorTransform(hwcId, colorMatrix);
ALOGE_IF(result != NO_ERROR, "Failed to set color transform on "
"display %zd: %d", displayId, result);
@@ -4028,15 +4029,19 @@
LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(int32_t hwcId) const {
LayersProto layersProto;
-
const sp<DisplayDevice>& displayDevice(mDisplays[hwcId]);
+
SizeProto* resolution = layersProto.mutable_resolution();
resolution->set_w(displayDevice->getWidth());
resolution->set_h(displayDevice->getHeight());
+ layersProto.set_color_mode(decodeColorMode(displayDevice->getActiveColorMode()));
+ layersProto.set_color_transform(decodeColorTransform(displayDevice->getColorTransform()));
+ layersProto.set_global_transform(
+ static_cast<int32_t>(displayDevice->getOrientationTransform()));
+
mDrawingState.traverseInZOrder([&](Layer* layer) {
- if (!layer->visibleRegion.isEmpty() &&
- layer->getBE().mHwcLayers.count(hwcId)) {
+ if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(hwcId)) {
LayerProto* layerProto = layersProto.add_layers();
layer->writeToProto(layerProto, hwcId);
}
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
index b10e07b..452592e 100644
--- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -44,7 +44,12 @@
const LayerProtoParser::LayerGlobal LayerProtoParser::generateLayerGlobalInfo(
const LayersProto& layersProto) {
- return {{layersProto.resolution().w(), layersProto.resolution().h()}};
+ LayerGlobal layerGlobal;
+ layerGlobal.resolution = {layersProto.resolution().w(), layersProto.resolution().h()};
+ layerGlobal.colorMode = layersProto.color_mode();
+ layerGlobal.colorTransform = layersProto.color_transform();
+ layerGlobal.globalTransform = layersProto.global_transform();
+ return layerGlobal;
}
std::vector<std::unique_ptr<LayerProtoParser::Layer>> LayerProtoParser::generateLayerTree(
@@ -116,6 +121,8 @@
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();
return layer;
}
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
index fd893da..74a6f28 100644
--- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -112,6 +112,8 @@
int32_t hwcTransform;
int32_t windowType;
int32_t appId;
+ int32_t hwcCompositionType;
+ bool isProtected;
std::string to_string() const;
};
@@ -119,6 +121,9 @@
class LayerGlobal {
public:
int2 resolution;
+ std::string colorMode;
+ std::string colorTransform;
+ int32_t globalTransform;
};
static const LayerGlobal generateLayerGlobalInfo(const LayersProto& layersProto);
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index 6675aae..77c6675 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -8,6 +8,9 @@
message LayersProto {
repeated LayerProto layers = 1;
optional SizeProto resolution = 2;
+ optional string color_mode = 3;
+ optional string color_transform = 4;
+ optional int32 global_transform = 5;
}
// Information about each layer.
@@ -73,6 +76,10 @@
optional int32 hwc_transform = 32;
optional int32 window_type = 33;
optional int32 app_id = 34;
+ // The layer's composition type
+ optional int32 hwc_composition_type = 35;
+ // If it's a buffer layer, indicate if the content is protected
+ optional bool is_protected = 36;
}
message PositionProto {