Merge changes from topic "sf-perfetto-integration-2" into main
* changes:
Revert^2 Integrate transaction tracing with perfetto
Revert^2 Integrate layer tracing with perfetto
Revert^2 Revert layer proto format back to proto2
Revert^2 Move proto definitions to external/perfetto
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index eda52bf..1718e0b 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -198,9 +198,12 @@
"StartPropertySetThread.cpp",
"SurfaceFlinger.cpp",
"SurfaceFlingerDefaultFactory.cpp",
+ "Tracing/LayerDataSource.cpp",
"Tracing/LayerTracing.cpp",
+ "Tracing/TransactionDataSource.cpp",
"Tracing/TransactionTracing.cpp",
"Tracing/TransactionProtoParser.cpp",
+ "Tracing/tools/LayerTraceGenerator.cpp",
"TransactionCallbackInvoker.cpp",
"TunnelModeEnabledReporter.cpp",
],
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index cdf7cff..9a5173b 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -139,7 +139,7 @@
using PresentState = frametimeline::SurfaceFrame::PresentState;
-Layer::Layer(const LayerCreationArgs& args)
+Layer::Layer(const surfaceflinger::LayerCreationArgs& args)
: sequence(args.sequence),
mFlinger(sp<SurfaceFlinger>::fromExisting(args.flinger)),
mName(base::StringPrintf("%s#%d", args.name.c_str(), sequence)),
@@ -1000,8 +1000,8 @@
uint32_t flags = ISurfaceComposerClient::eFXSurfaceEffect;
std::string name = mName + "BackgroundColorLayer";
mDrawingState.bgColorLayer = mFlinger->getFactory().createEffectLayer(
- LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), flags,
- LayerMetadata()));
+ surfaceflinger::LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), flags,
+ LayerMetadata()));
// add to child list
addChild(mDrawingState.bgColorLayer);
@@ -2203,8 +2203,9 @@
setTransactionFlags(eTransactionNeeded);
}
-LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags) {
- LayerProto* layerProto = layersProto.add_layers();
+perfetto::protos::LayerProto* Layer::writeToProto(perfetto::protos::LayersProto& layersProto,
+ uint32_t traceFlags) {
+ perfetto::protos::LayerProto* layerProto = layersProto.add_layers();
writeToProtoDrawingState(layerProto);
writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags);
@@ -2221,20 +2222,22 @@
return layerProto;
}
-void Layer::writeCompositionStateToProto(LayerProto* layerProto, ui::LayerStack layerStack) {
+void Layer::writeCompositionStateToProto(perfetto::protos::LayerProto* layerProto,
+ ui::LayerStack layerStack) {
ftl::FakeGuard guard(mFlinger->mStateLock); // Called from the main thread.
ftl::FakeGuard mainThreadGuard(kMainThreadContext);
// Only populate for the primary display.
if (const auto display = mFlinger->getDisplayFromLayerStack(layerStack)) {
const auto compositionType = getCompositionType(*display);
- layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType));
+ layerProto->set_hwc_composition_type(
+ static_cast<perfetto::protos::HwcCompositionType>(compositionType));
LayerProtoHelper::writeToProto(getVisibleRegion(display),
[&]() { return layerProto->mutable_visible_region(); });
}
}
-void Layer::writeToProtoDrawingState(LayerProto* layerInfo) {
+void Layer::writeToProtoDrawingState(perfetto::protos::LayerProto* layerInfo) {
const ui::Transform transform = getTransform();
auto buffer = getExternalTexture();
if (buffer != nullptr) {
@@ -2273,8 +2276,8 @@
layerInfo->set_shadow_radius(mEffectiveShadowRadius);
}
-void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet,
- uint32_t traceFlags) {
+void Layer::writeToProtoCommonState(perfetto::protos::LayerProto* layerInfo,
+ LayerVector::StateSet stateSet, uint32_t traceFlags) {
const bool useDrawing = stateSet == LayerVector::StateSet::Drawing;
const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren;
const State& state = useDrawing ? mDrawingState : mDrawingState;
@@ -2322,15 +2325,11 @@
auto parent = useDrawing ? mDrawingParent.promote() : mCurrentParent.promote();
if (parent != nullptr) {
layerInfo->set_parent(parent->sequence);
- } else {
- layerInfo->set_parent(-1);
}
auto zOrderRelativeOf = state.zOrderRelativeOf.promote();
if (zOrderRelativeOf != nullptr) {
layerInfo->set_z_order_relative_of(zOrderRelativeOf->sequence);
- } else {
- layerInfo->set_z_order_relative_of(-1);
}
layerInfo->set_is_relative_of(state.isRelativeOf);
@@ -3630,7 +3629,8 @@
}
sp<Layer> Layer::createClone(uint32_t mirrorRootId) {
- LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata());
+ surfaceflinger::LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0,
+ LayerMetadata());
sp<Layer> layer = mFlinger->getFactory().createBufferStateLayer(args);
layer->setInitialValuesForClone(sp<Layer>::fromExisting(this), mirrorRootId);
return layer;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 7b6c56b..dc4ceb0 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -235,7 +235,7 @@
bool useVsyncIdForRefreshRateSelection = false;
};
- explicit Layer(const LayerCreationArgs& args);
+ explicit Layer(const surfaceflinger::LayerCreationArgs& args);
virtual ~Layer();
static bool isLayerFocusedBasedOnPriority(int32_t priority);
@@ -634,17 +634,19 @@
bool isRemovedFromCurrentState() const;
- LayerProto* writeToProto(LayersProto& layersProto, uint32_t traceFlags);
- void writeCompositionStateToProto(LayerProto* layerProto, ui::LayerStack layerStack);
+ perfetto::protos::LayerProto* writeToProto(perfetto::protos::LayersProto& layersProto,
+ uint32_t traceFlags);
+ void writeCompositionStateToProto(perfetto::protos::LayerProto* layerProto,
+ ui::LayerStack layerStack);
// Write states that are modified by the main thread. This includes drawing
// state as well as buffer data. This should be called in the main or tracing
// thread.
- void writeToProtoDrawingState(LayerProto* layerInfo);
+ void writeToProtoDrawingState(perfetto::protos::LayerProto* layerInfo);
// Write drawing or current state. If writing current state, the caller should hold the
// external mStateLock. If writing drawing state, this function should be called on the
// main or tracing thread.
- void writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet,
+ void writeToProtoCommonState(perfetto::protos::LayerProto* layerInfo, LayerVector::StateSet,
uint32_t traceFlags = LayerTracing::TRACE_ALL);
gui::WindowInfo::Type getWindowType() const { return mWindowType; }
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
index 341f041..144e1f5 100644
--- a/services/surfaceflinger/LayerProtoHelper.cpp
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -29,28 +29,30 @@
namespace surfaceflinger {
-void LayerProtoHelper::writePositionToProto(const float x, const float y,
- std::function<PositionProto*()> getPositionProto) {
+void LayerProtoHelper::writePositionToProto(
+ const float x, const float y,
+ std::function<perfetto::protos::PositionProto*()> getPositionProto) {
if (x != 0 || y != 0) {
// Use a lambda do avoid writing the object header when the object is empty
- PositionProto* position = getPositionProto();
+ perfetto::protos::PositionProto* position = getPositionProto();
position->set_x(x);
position->set_y(y);
}
}
-void LayerProtoHelper::writeSizeToProto(const uint32_t w, const uint32_t h,
- std::function<SizeProto*()> getSizeProto) {
+void LayerProtoHelper::writeSizeToProto(
+ const uint32_t w, const uint32_t h,
+ std::function<perfetto::protos::SizeProto*()> getSizeProto) {
if (w != 0 || h != 0) {
// Use a lambda do avoid writing the object header when the object is empty
- SizeProto* size = getSizeProto();
+ perfetto::protos::SizeProto* size = getSizeProto();
size->set_w(w);
size->set_h(h);
}
}
-void LayerProtoHelper::writeToProto(const Region& region,
- std::function<RegionProto*()> getRegionProto) {
+void LayerProtoHelper::writeToProto(
+ const Region& region, std::function<perfetto::protos::RegionProto*()> getRegionProto) {
if (region.isEmpty()) {
return;
}
@@ -58,7 +60,8 @@
writeToProto(region, getRegionProto());
}
-void LayerProtoHelper::writeToProto(const Region& region, RegionProto* regionProto) {
+void LayerProtoHelper::writeToProto(const Region& region,
+ perfetto::protos::RegionProto* regionProto) {
if (region.isEmpty()) {
return;
}
@@ -72,7 +75,8 @@
}
}
-void LayerProtoHelper::readFromProto(const RegionProto& regionProto, Region& outRegion) {
+void LayerProtoHelper::readFromProto(const perfetto::protos::RegionProto& regionProto,
+ Region& outRegion) {
for (int i = 0; i < regionProto.rect_size(); i++) {
Rect rect;
readFromProto(regionProto.rect(i), rect);
@@ -80,32 +84,34 @@
}
}
-void LayerProtoHelper::writeToProto(const Rect& rect, std::function<RectProto*()> getRectProto) {
+void LayerProtoHelper::writeToProto(const Rect& rect,
+ std::function<perfetto::protos::RectProto*()> getRectProto) {
if (rect.left != 0 || rect.right != 0 || rect.top != 0 || rect.bottom != 0) {
// Use a lambda do avoid writing the object header when the object is empty
writeToProto(rect, getRectProto());
}
}
-void LayerProtoHelper::writeToProto(const Rect& rect, RectProto* rectProto) {
+void LayerProtoHelper::writeToProto(const Rect& rect, perfetto::protos::RectProto* rectProto) {
rectProto->set_left(rect.left);
rectProto->set_top(rect.top);
rectProto->set_bottom(rect.bottom);
rectProto->set_right(rect.right);
}
-void LayerProtoHelper::readFromProto(const RectProto& proto, Rect& outRect) {
+void LayerProtoHelper::readFromProto(const perfetto::protos::RectProto& proto, Rect& outRect) {
outRect.left = proto.left();
outRect.top = proto.top();
outRect.bottom = proto.bottom();
outRect.right = proto.right();
}
-void LayerProtoHelper::writeToProto(const FloatRect& rect,
- std::function<FloatRectProto*()> getFloatRectProto) {
+void LayerProtoHelper::writeToProto(
+ const FloatRect& rect,
+ std::function<perfetto::protos::FloatRectProto*()> getFloatRectProto) {
if (rect.left != 0 || rect.right != 0 || rect.top != 0 || rect.bottom != 0) {
// Use a lambda do avoid writing the object header when the object is empty
- FloatRectProto* rectProto = getFloatRectProto();
+ perfetto::protos::FloatRectProto* rectProto = getFloatRectProto();
rectProto->set_left(rect.left);
rectProto->set_top(rect.top);
rectProto->set_bottom(rect.bottom);
@@ -113,10 +119,11 @@
}
}
-void LayerProtoHelper::writeToProto(const half4 color, std::function<ColorProto*()> getColorProto) {
+void LayerProtoHelper::writeToProto(const half4 color,
+ std::function<perfetto::protos::ColorProto*()> getColorProto) {
if (color.r != 0 || color.g != 0 || color.b != 0 || color.a != 0) {
// Use a lambda do avoid writing the object header when the object is empty
- ColorProto* colorProto = getColorProto();
+ perfetto::protos::ColorProto* colorProto = getColorProto();
colorProto->set_r(color.r);
colorProto->set_g(color.g);
colorProto->set_b(color.b);
@@ -125,7 +132,7 @@
}
void LayerProtoHelper::writeToProtoDeprecated(const ui::Transform& transform,
- TransformProto* transformProto) {
+ perfetto::protos::TransformProto* transformProto) {
const uint32_t type = transform.getType() | (transform.getOrientation() << 8);
transformProto->set_type(type);
@@ -141,7 +148,7 @@
}
void LayerProtoHelper::writeTransformToProto(const ui::Transform& transform,
- TransformProto* transformProto) {
+ perfetto::protos::TransformProto* transformProto) {
const uint32_t type = transform.getType() | (transform.getOrientation() << 8);
transformProto->set_type(type);
@@ -156,12 +163,13 @@
}
}
-void LayerProtoHelper::writeToProto(const renderengine::ExternalTexture& buffer,
- std::function<ActiveBufferProto*()> getActiveBufferProto) {
+void LayerProtoHelper::writeToProto(
+ const renderengine::ExternalTexture& buffer,
+ std::function<perfetto::protos::ActiveBufferProto*()> getActiveBufferProto) {
if (buffer.getWidth() != 0 || buffer.getHeight() != 0 || buffer.getUsage() != 0 ||
buffer.getPixelFormat() != 0) {
// Use a lambda do avoid writing the object header when the object is empty
- ActiveBufferProto* activeBufferProto = getActiveBufferProto();
+ auto* activeBufferProto = getActiveBufferProto();
activeBufferProto->set_width(buffer.getWidth());
activeBufferProto->set_height(buffer.getHeight());
activeBufferProto->set_stride(buffer.getUsage());
@@ -171,12 +179,12 @@
void LayerProtoHelper::writeToProto(
const WindowInfo& inputInfo, const wp<Layer>& touchableRegionBounds,
- std::function<InputWindowInfoProto*()> getInputWindowInfoProto) {
+ std::function<perfetto::protos::InputWindowInfoProto*()> getInputWindowInfoProto) {
if (inputInfo.token == nullptr) {
return;
}
- InputWindowInfoProto* proto = getInputWindowInfoProto();
+ perfetto::protos::InputWindowInfoProto* proto = getInputWindowInfoProto();
proto->set_layout_params_flags(inputInfo.layoutParamsFlags.get());
proto->set_input_config(inputInfo.inputConfig.get());
using U = std::underlying_type_t<WindowInfo::Type>;
@@ -209,7 +217,8 @@
}
}
-void LayerProtoHelper::writeToProto(const mat4 matrix, ColorTransformProto* colorTransformProto) {
+void LayerProtoHelper::writeToProto(const mat4 matrix,
+ perfetto::protos::ColorTransformProto* colorTransformProto) {
for (int i = 0; i < mat4::ROW_SIZE; i++) {
for (int j = 0; j < mat4::COL_SIZE; j++) {
colorTransformProto->add_val(matrix[i][j]);
@@ -217,7 +226,8 @@
}
}
-void LayerProtoHelper::readFromProto(const ColorTransformProto& colorTransformProto, mat4& matrix) {
+void LayerProtoHelper::readFromProto(
+ const perfetto::protos::ColorTransformProto& colorTransformProto, mat4& matrix) {
for (int i = 0; i < mat4::ROW_SIZE; i++) {
for (int j = 0; j < mat4::COL_SIZE; j++) {
matrix[i][j] = colorTransformProto.val(i * mat4::COL_SIZE + j);
@@ -225,7 +235,8 @@
}
}
-void LayerProtoHelper::writeToProto(const android::BlurRegion region, BlurRegion* proto) {
+void LayerProtoHelper::writeToProto(const android::BlurRegion region,
+ perfetto::protos::BlurRegion* proto) {
proto->set_blur_radius(region.blurRadius);
proto->set_corner_radius_tl(region.cornerRadiusTL);
proto->set_corner_radius_tr(region.cornerRadiusTR);
@@ -238,7 +249,8 @@
proto->set_bottom(region.bottom);
}
-void LayerProtoHelper::readFromProto(const BlurRegion& proto, android::BlurRegion& outRegion) {
+void LayerProtoHelper::readFromProto(const perfetto::protos::BlurRegion& proto,
+ android::BlurRegion& outRegion) {
outRegion.blurRadius = proto.blur_radius();
outRegion.cornerRadiusTL = proto.corner_radius_tl();
outRegion.cornerRadiusTR = proto.corner_radius_tr();
@@ -251,7 +263,8 @@
outRegion.bottom = proto.bottom();
}
-LayersProto LayerProtoFromSnapshotGenerator::generate(const frontend::LayerHierarchy& root) {
+perfetto::protos::LayersProto LayerProtoFromSnapshotGenerator::generate(
+ const frontend::LayerHierarchy& root) {
mLayersProto.clear_layers();
std::unordered_set<uint64_t> stackIdsToSkip;
if ((mTraceFlags & LayerTracing::TRACE_VIRTUAL_DISPLAYS) == 0) {
@@ -310,7 +323,7 @@
void LayerProtoFromSnapshotGenerator::writeHierarchyToProto(
const frontend::LayerHierarchy& root, frontend::LayerHierarchy::TraversalPath& path) {
using Variant = frontend::LayerHierarchy::Variant;
- LayerProto* layerProto = mLayersProto.add_layers();
+ perfetto::protos::LayerProto* layerProto = mLayersProto.add_layers();
const frontend::RequestedLayerState& layer = *root.getLayer();
frontend::LayerSnapshot* snapshot = getSnapshot(path, layer);
LayerProtoHelper::writeSnapshotToProto(layerProto, layer, *snapshot, mTraceFlags);
@@ -349,7 +362,7 @@
}
}
-void LayerProtoHelper::writeSnapshotToProto(LayerProto* layerInfo,
+void LayerProtoHelper::writeSnapshotToProto(perfetto::protos::LayerProto* layerInfo,
const frontend::RequestedLayerState& requestedState,
const frontend::LayerSnapshot& snapshot,
uint32_t traceFlags) {
@@ -446,9 +459,9 @@
[&]() { return layerInfo->mutable_destination_frame(); });
}
-google::protobuf::RepeatedPtrField<DisplayProto> LayerProtoHelper::writeDisplayInfoToProto(
- const frontend::DisplayInfos& displayInfos) {
- google::protobuf::RepeatedPtrField<DisplayProto> displays;
+google::protobuf::RepeatedPtrField<perfetto::protos::DisplayProto>
+LayerProtoHelper::writeDisplayInfoToProto(const frontend::DisplayInfos& displayInfos) {
+ google::protobuf::RepeatedPtrField<perfetto::protos::DisplayProto> displays;
displays.Reserve(displayInfos.size());
for (const auto& [layerStack, displayInfo] : displayInfos) {
auto displayProto = displays.Add();
diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h
index 346685f..20c2260 100644
--- a/services/surfaceflinger/LayerProtoHelper.h
+++ b/services/surfaceflinger/LayerProtoHelper.h
@@ -35,39 +35,47 @@
namespace surfaceflinger {
class LayerProtoHelper {
public:
- static void writePositionToProto(const float x, const float y,
- std::function<PositionProto*()> getPositionProto);
+ static void writePositionToProto(
+ const float x, const float y,
+ std::function<perfetto::protos::PositionProto*()> getPositionProto);
static void writeSizeToProto(const uint32_t w, const uint32_t h,
- std::function<SizeProto*()> getSizeProto);
- static void writeToProto(const Rect& rect, std::function<RectProto*()> getRectProto);
- static void writeToProto(const Rect& rect, RectProto* rectProto);
- static void readFromProto(const RectProto& proto, Rect& outRect);
+ std::function<perfetto::protos::SizeProto*()> getSizeProto);
+ static void writeToProto(const Rect& rect,
+ std::function<perfetto::protos::RectProto*()> getRectProto);
+ static void writeToProto(const Rect& rect, perfetto::protos::RectProto* rectProto);
+ static void readFromProto(const perfetto::protos::RectProto& proto, Rect& outRect);
static void writeToProto(const FloatRect& rect,
- std::function<FloatRectProto*()> getFloatRectProto);
- static void writeToProto(const Region& region, std::function<RegionProto*()> getRegionProto);
- static void writeToProto(const Region& region, RegionProto* regionProto);
- static void readFromProto(const RegionProto& regionProto, Region& outRegion);
- static void writeToProto(const half4 color, std::function<ColorProto*()> getColorProto);
+ std::function<perfetto::protos::FloatRectProto*()> getFloatRectProto);
+ static void writeToProto(const Region& region,
+ std::function<perfetto::protos::RegionProto*()> getRegionProto);
+ static void writeToProto(const Region& region, perfetto::protos::RegionProto* regionProto);
+ static void readFromProto(const perfetto::protos::RegionProto& regionProto, Region& outRegion);
+ static void writeToProto(const half4 color,
+ std::function<perfetto::protos::ColorProto*()> getColorProto);
// This writeToProto for transform is incorrect, but due to backwards compatibility, we can't
// update Layers to use it. Use writeTransformToProto for any new transform proto data.
static void writeToProtoDeprecated(const ui::Transform& transform,
- TransformProto* transformProto);
+ perfetto::protos::TransformProto* transformProto);
static void writeTransformToProto(const ui::Transform& transform,
- TransformProto* transformProto);
- static void writeToProto(const renderengine::ExternalTexture& buffer,
- std::function<ActiveBufferProto*()> getActiveBufferProto);
- static void writeToProto(const gui::WindowInfo& inputInfo,
- const wp<Layer>& touchableRegionBounds,
- std::function<InputWindowInfoProto*()> getInputWindowInfoProto);
- static void writeToProto(const mat4 matrix, ColorTransformProto* colorTransformProto);
- static void readFromProto(const ColorTransformProto& colorTransformProto, mat4& matrix);
- static void writeToProto(const android::BlurRegion region, BlurRegion*);
- static void readFromProto(const BlurRegion& proto, android::BlurRegion& outRegion);
- static void writeSnapshotToProto(LayerProto* outProto,
+ perfetto::protos::TransformProto* transformProto);
+ static void writeToProto(
+ const renderengine::ExternalTexture& buffer,
+ std::function<perfetto::protos::ActiveBufferProto*()> getActiveBufferProto);
+ static void writeToProto(
+ const gui::WindowInfo& inputInfo, const wp<Layer>& touchableRegionBounds,
+ std::function<perfetto::protos::InputWindowInfoProto*()> getInputWindowInfoProto);
+ static void writeToProto(const mat4 matrix,
+ perfetto::protos::ColorTransformProto* colorTransformProto);
+ static void readFromProto(const perfetto::protos::ColorTransformProto& colorTransformProto,
+ mat4& matrix);
+ static void writeToProto(const android::BlurRegion region, perfetto::protos::BlurRegion*);
+ static void readFromProto(const perfetto::protos::BlurRegion& proto,
+ android::BlurRegion& outRegion);
+ static void writeSnapshotToProto(perfetto::protos::LayerProto* outProto,
const frontend::RequestedLayerState& requestedState,
const frontend::LayerSnapshot& snapshot, uint32_t traceFlags);
- static google::protobuf::RepeatedPtrField<DisplayProto> writeDisplayInfoToProto(
- const frontend::DisplayInfos&);
+ static google::protobuf::RepeatedPtrField<perfetto::protos::DisplayProto>
+ writeDisplayInfoToProto(const frontend::DisplayInfos&);
};
class LayerProtoFromSnapshotGenerator {
@@ -80,7 +88,7 @@
mLegacyLayers(legacyLayers),
mDisplayInfos(displayInfos),
mTraceFlags(traceFlags) {}
- LayersProto generate(const frontend::LayerHierarchy& root);
+ perfetto::protos::LayersProto generate(const frontend::LayerHierarchy& root);
private:
void writeHierarchyToProto(const frontend::LayerHierarchy& root,
@@ -92,7 +100,7 @@
const std::unordered_map<uint32_t, sp<Layer>>& mLegacyLayers;
const frontend::DisplayInfos& mDisplayInfos;
uint32_t mTraceFlags;
- LayersProto mLayersProto;
+ perfetto::protos::LayersProto mLayersProto;
// winscope expects all the layers, so provide a snapshot even if it not currently drawing
std::unordered_map<frontend::LayerHierarchy::TraversalPath, frontend::LayerSnapshot,
frontend::LayerHierarchy::TraversalPathHash>
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index bc626f3..38188c0 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -320,8 +320,6 @@
const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled";
-static const int MAX_TRACING_MEMORY = 1024 * 1024 * 1024; // 1GB
-
// ---------------------------------------------------------------------------
int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
bool SurfaceFlinger::useHwcForRgbToYuv;
@@ -483,6 +481,7 @@
if (!mIsUserBuild && base::GetBoolProperty("debug.sf.enable_transaction_tracing"s, true)) {
mTransactionTracing.emplace();
+ mLayerTracing.setTransactionTracing(*mTransactionTracing);
}
mIgnoreHdrCameraLayers = ignore_hdr_camera_layers(false);
@@ -827,6 +826,17 @@
initScheduler(display);
dispatchDisplayHotplugEvent(display->getPhysicalId(), true);
+ mLayerTracing.setTakeLayersSnapshotProtoFunction([&](uint32_t traceFlags) {
+ auto snapshot = perfetto::protos::LayersSnapshotProto{};
+ mScheduler
+ ->schedule([&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) {
+ snapshot = takeLayersSnapshotProto(traceFlags, TimePoint::now(),
+ mLastCommittedVsyncId, true);
+ })
+ .wait();
+ return snapshot;
+ });
+
// Commit secondary display(s).
processDisplayChangesLocked();
@@ -2378,11 +2388,6 @@
mTimeStats->incrementMissedFrames();
}
- if (mTracingEnabledChanged) {
- mLayerTracingEnabled = mLayerTracing.isEnabled();
- mTracingEnabledChanged = false;
- }
-
// If a mode set is pending and the fence hasn't fired yet, wait for the next commit.
if (std::any_of(frameTargets.begin(), frameTargets.end(),
[this](const auto& pair) FTL_FAKE_GUARD(mStateLock)
@@ -2509,11 +2514,9 @@
if (!mustComposite) {
updateInputFlinger(vsyncId, pacesetterFrameTarget.frameBeginTime());
}
+ doActiveLayersTracingIfNeeded(false, mVisibleRegionsDirty,
+ pacesetterFrameTarget.frameBeginTime(), vsyncId);
- if (mLayerTracingEnabled && !mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
- // This will block and tracing should only be enabled for debugging.
- addToLayerTracing(mVisibleRegionsDirty, pacesetterFrameTarget.frameBeginTime(), vsyncId);
- }
mLastCommittedVsyncId = vsyncId;
persistDisplayBrightness(mustComposite);
@@ -2735,10 +2738,8 @@
mLayersWithQueuedFrames.clear();
mLayersIdsWithQueuedFrames.clear();
- if (mLayerTracingEnabled && mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
- // This will block and should only be used for debugging.
- addToLayerTracing(mVisibleRegionsDirty, pacesetterTarget.frameBeginTime(), vsyncId);
- }
+ doActiveLayersTracingIfNeeded(true, mVisibleRegionsDirty, pacesetterTarget.frameBeginTime(),
+ vsyncId);
updateInputFlinger(vsyncId, pacesetterTarget.frameBeginTime());
@@ -5889,9 +5890,10 @@
}
if (dumpLayers) {
- LayersTraceFileProto traceFileProto = mLayerTracing.createTraceFileProto();
- LayersTraceProto* layersTrace = traceFileProto.add_entry();
- LayersProto layersProto = dumpProtoFromMainThread();
+ perfetto::protos::LayersTraceFileProto traceFileProto =
+ mLayerTracing.createTraceFileProto();
+ perfetto::protos::LayersSnapshotProto* layersTrace = traceFileProto.add_entry();
+ perfetto::protos::LayersProto layersProto = dumpProtoFromMainThread();
layersTrace->mutable_layers()->Swap(&layersProto);
auto displayProtos = dumpDisplayProto();
layersTrace->mutable_displays()->Swap(&displayProtos);
@@ -6117,7 +6119,7 @@
}
}
-LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const {
+perfetto::protos::LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const {
std::unordered_set<uint64_t> stackIdsToSkip;
// Determine if virtual layers display should be skipped
@@ -6130,7 +6132,7 @@
}
if (mLegacyFrontEndEnabled) {
- LayersProto layersProto;
+ perfetto::protos::LayersProto layersProto;
for (const sp<Layer>& layer : mDrawingState.layersSortedByZ) {
if (stackIdsToSkip.find(layer->getLayerStack().id) != stackIdsToSkip.end()) {
continue;
@@ -6145,10 +6147,11 @@
.generate(mLayerHierarchyBuilder.getHierarchy());
}
-google::protobuf::RepeatedPtrField<DisplayProto> SurfaceFlinger::dumpDisplayProto() const {
- google::protobuf::RepeatedPtrField<DisplayProto> displays;
+google::protobuf::RepeatedPtrField<perfetto::protos::DisplayProto>
+SurfaceFlinger::dumpDisplayProto() const {
+ google::protobuf::RepeatedPtrField<perfetto::protos::DisplayProto> displays;
for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
- DisplayProto* displayProto = displays.Add();
+ perfetto::protos::DisplayProto* displayProto = displays.Add();
displayProto->set_id(display->getId().value);
displayProto->set_name(display->getDisplayName());
displayProto->set_layer_stack(display->getLayerStack().id);
@@ -6175,10 +6178,11 @@
getHwComposer().dump(result);
}
-void SurfaceFlinger::dumpOffscreenLayersProto(LayersProto& layersProto, uint32_t traceFlags) const {
+void SurfaceFlinger::dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto,
+ uint32_t traceFlags) const {
// Add a fake invisible root layer to the proto output and parent all the offscreen layers to
// it.
- LayerProto* rootProto = layersProto.add_layers();
+ perfetto::protos::LayerProto* rootProto = layersProto.add_layers();
const int32_t offscreenRootLayerId = INT32_MAX - 2;
rootProto->set_id(offscreenRootLayerId);
rootProto->set_name("Offscreen Root");
@@ -6189,12 +6193,12 @@
rootProto->add_children(offscreenLayer->sequence);
// Add layer
- LayerProto* layerProto = offscreenLayer->writeToProto(layersProto, traceFlags);
+ auto* layerProto = offscreenLayer->writeToProto(layersProto, traceFlags);
layerProto->set_parent(offscreenRootLayerId);
}
}
-LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) {
+perfetto::protos::LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) {
return mScheduler->schedule([=] { return dumpDrawingStateProto(traceFlags); }).get();
}
@@ -6363,11 +6367,6 @@
StringAppendF(&result, " transaction time: %f us\n", inTransactionDuration / 1000.0);
- /*
- * Tracing state
- */
- mLayerTracing.dump(result);
-
result.append("\nTransaction tracing: ");
if (mTransactionTracing) {
result.append("enabled\n");
@@ -6719,42 +6718,13 @@
case 1024: {
return NAME_NOT_FOUND;
}
- case 1025: { // Set layer tracing
- n = data.readInt32();
- bool tracingEnabledChanged;
- if (n == 1) {
- int64_t fixedStartingTime = data.readInt64();
- ALOGD("LayerTracing enabled");
- tracingEnabledChanged = mLayerTracing.enable();
- if (tracingEnabledChanged) {
- const TimePoint startingTime = fixedStartingTime
- ? TimePoint::fromNs(fixedStartingTime)
- : TimePoint::now();
-
- mScheduler
- ->schedule([this, startingTime]() FTL_FAKE_GUARD(
- mStateLock) FTL_FAKE_GUARD(kMainThreadContext) {
- constexpr bool kVisibleRegionDirty = true;
- addToLayerTracing(kVisibleRegionDirty, startingTime,
- mLastCommittedVsyncId);
- })
- .wait();
- }
- } else if (n == 2) {
- std::string filename = std::string(data.readCString());
- ALOGD("LayerTracing disabled. Trace wrote to %s", filename.c_str());
- tracingEnabledChanged = mLayerTracing.disable(filename.c_str());
- } else {
- ALOGD("LayerTracing disabled");
- tracingEnabledChanged = mLayerTracing.disable();
- }
- mTracingEnabledChanged = tracingEnabledChanged;
- reply->writeInt32(NO_ERROR);
- return NO_ERROR;
+ // Deprecated, use perfetto to start/stop the layer tracing
+ case 1025: {
+ return NAME_NOT_FOUND;
}
- case 1026: { // Get layer tracing status
- reply->writeBool(mLayerTracing.isEnabled());
- return NO_ERROR;
+ // Deprecated, execute "adb shell perfetto --query" to see the ongoing tracing sessions
+ case 1026: {
+ return NAME_NOT_FOUND;
}
// Is a DisplayColorSetting supported?
case 1027: {
@@ -6782,19 +6752,9 @@
case 1028: { // Unused.
return NAME_NOT_FOUND;
}
- // Set buffer size for SF tracing (value in KB)
+ // Deprecated, use perfetto to set the active layer tracing buffer size
case 1029: {
- n = data.readInt32();
- if (n <= 0 || n > MAX_TRACING_MEMORY) {
- ALOGW("Invalid buffer size: %d KB", n);
- reply->writeInt32(BAD_VALUE);
- return BAD_VALUE;
- }
-
- ALOGD("Updating trace buffer to %d KB", n);
- mLayerTracing.setBufferSize(n * 1024);
- reply->writeInt32(NO_ERROR);
- return NO_ERROR;
+ return NAME_NOT_FOUND;
}
// Is device color managed?
case 1030: {
@@ -6834,13 +6794,9 @@
}
return NO_ERROR;
}
- // Set trace flags
+ // Deprecated, use perfetto to set layer trace flags
case 1033: {
- n = data.readUint32();
- ALOGD("Updating trace flags to 0x%x", n);
- mLayerTracing.setTraceFlags(n);
- reply->writeInt32(NO_ERROR);
- return NO_ERROR;
+ return NAME_NOT_FOUND;
}
case 1034: {
n = data.readInt32();
@@ -6985,7 +6941,7 @@
// Transaction tracing is always running but allow the user to temporarily
// increase the buffer when actively debugging.
mTransactionTracing->setBufferSize(
- TransactionTracing::ACTIVE_TRACING_BUFFER_SIZE);
+ TransactionTracing::LEGACY_ACTIVE_TRACING_BUFFER_SIZE);
} else {
TransactionTraceWriter::getInstance().invoke("", /* overwrite= */ true);
mTransactionTracing->setBufferSize(
@@ -6995,13 +6951,10 @@
reply->writeInt32(NO_ERROR);
return NO_ERROR;
}
- case 1042: { // Write layers trace or transaction trace to file
+ case 1042: { // Write transaction trace to file
if (mTransactionTracing) {
mTransactionTracing->writeToFile();
}
- if (mLayerTracingEnabled) {
- mLayerTracing.writeToFile();
- }
reply->writeInt32(NO_ERROR);
return NO_ERROR;
}
@@ -8788,19 +8741,50 @@
return update;
}
-void SurfaceFlinger::addToLayerTracing(bool visibleRegionDirty, TimePoint time, VsyncId vsyncId) {
- const uint32_t tracingFlags = mLayerTracing.getFlags();
- LayersProto layers(dumpDrawingStateProto(tracingFlags));
- if (tracingFlags & LayerTracing::TRACE_EXTRA) {
+void SurfaceFlinger::doActiveLayersTracingIfNeeded(bool isCompositionComputed,
+ bool visibleRegionDirty, TimePoint time,
+ VsyncId vsyncId) {
+ if (!mLayerTracing.isActiveTracingStarted()) {
+ return;
+ }
+ if (isCompositionComputed !=
+ mLayerTracing.isActiveTracingFlagSet(LayerTracing::Flag::TRACE_COMPOSITION)) {
+ return;
+ }
+ if (!visibleRegionDirty &&
+ !mLayerTracing.isActiveTracingFlagSet(LayerTracing::Flag::TRACE_BUFFERS)) {
+ return;
+ }
+ auto snapshot = takeLayersSnapshotProto(mLayerTracing.getActiveTracingFlags(), time, vsyncId,
+ visibleRegionDirty);
+ mLayerTracing.addProtoSnapshotToOstream(std::move(snapshot), LayerTracing::Mode::MODE_ACTIVE);
+}
+
+perfetto::protos::LayersSnapshotProto SurfaceFlinger::takeLayersSnapshotProto(
+ uint32_t traceFlags, TimePoint time, VsyncId vsyncId, bool visibleRegionDirty) {
+ ATRACE_CALL();
+ perfetto::protos::LayersSnapshotProto snapshot;
+ snapshot.set_elapsed_realtime_nanos(time.ns());
+ snapshot.set_vsync_id(ftl::to_underlying(vsyncId));
+ snapshot.set_where(visibleRegionDirty ? "visibleRegionsDirty" : "bufferLatched");
+ snapshot.set_excludes_composition_state((traceFlags & LayerTracing::Flag::TRACE_COMPOSITION) ==
+ 0);
+
+ auto layers = dumpDrawingStateProto(traceFlags);
+ if (traceFlags & LayerTracing::Flag::TRACE_EXTRA) {
dumpOffscreenLayersProto(layers);
}
- std::string hwcDump;
- if (tracingFlags & LayerTracing::TRACE_HWC) {
+ *snapshot.mutable_layers() = std::move(layers);
+
+ if (traceFlags & LayerTracing::Flag::TRACE_HWC) {
+ std::string hwcDump;
dumpHwc(hwcDump);
+ snapshot.set_hwc_blob(std::move(hwcDump));
}
- auto displays = dumpDisplayProto();
- mLayerTracing.notify(visibleRegionDirty, time.ns(), ftl::to_underlying(vsyncId), &layers,
- std::move(hwcDump), &displays);
+
+ *snapshot.mutable_displays() = dumpDisplayProto();
+
+ return snapshot;
}
// sfdo functions
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 79dcd0d..dc4e7cf 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -368,7 +368,6 @@
friend class RefreshRateOverlay;
friend class RegionSamplingThread;
friend class LayerRenderArea;
- friend class LayerTracing;
friend class SurfaceComposerAIDL;
friend class DisplayRenderArea;
@@ -1092,17 +1091,20 @@
void dumpWideColorInfo(std::string& result) const REQUIRES(mStateLock);
void dumpHdrInfo(std::string& result) const REQUIRES(mStateLock);
- LayersProto dumpDrawingStateProto(uint32_t traceFlags) const;
- void dumpOffscreenLayersProto(LayersProto& layersProto,
+ perfetto::protos::LayersProto dumpDrawingStateProto(uint32_t traceFlags) const;
+ void dumpOffscreenLayersProto(perfetto::protos::LayersProto& layersProto,
uint32_t traceFlags = LayerTracing::TRACE_ALL) const;
- google::protobuf::RepeatedPtrField<DisplayProto> dumpDisplayProto() const;
- void addToLayerTracing(bool visibleRegionDirty, TimePoint, VsyncId)
+ google::protobuf::RepeatedPtrField<perfetto::protos::DisplayProto> dumpDisplayProto() const;
+ void doActiveLayersTracingIfNeeded(bool isCompositionComputed, bool visibleRegionDirty,
+ TimePoint, VsyncId) REQUIRES(kMainThreadContext);
+ perfetto::protos::LayersSnapshotProto takeLayersSnapshotProto(uint32_t flags, TimePoint,
+ VsyncId, bool visibleRegionDirty)
REQUIRES(kMainThreadContext);
// Dumps state from HW Composer
void dumpHwc(std::string& result) const;
- LayersProto dumpProtoFromMainThread(uint32_t traceFlags = LayerTracing::TRACE_ALL)
- EXCLUDES(mStateLock);
+ perfetto::protos::LayersProto dumpProtoFromMainThread(
+ uint32_t traceFlags = LayerTracing::TRACE_ALL) EXCLUDES(mStateLock);
void dumpOffscreenLayers(std::string& result) EXCLUDES(mStateLock);
void dumpPlannerInfo(const DumpArgs& args, std::string& result) const REQUIRES(mStateLock);
@@ -1261,10 +1263,7 @@
bool mBackpressureGpuComposition = false;
LayerTracing mLayerTracing;
- bool mLayerTracingEnabled = false;
-
std::optional<TransactionTracing> mTransactionTracing;
- std::atomic<bool> mTracingEnabledChanged = false;
const std::shared_ptr<TimeStats> mTimeStats;
const std::unique_ptr<FrameTracer> mFrameTracer;
diff --git a/services/surfaceflinger/Tracing/LayerDataSource.cpp b/services/surfaceflinger/Tracing/LayerDataSource.cpp
new file mode 100644
index 0000000..474fef8
--- /dev/null
+++ b/services/surfaceflinger/Tracing/LayerDataSource.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "LayerTracing"
+
+#include "LayerDataSource.h"
+
+#include <log/log.h>
+#include <perfetto/config/android/surfaceflinger_layers_config.pbzero.h>
+
+namespace android {
+
+void LayerDataSource::Initialize(LayerTracing& layerTracing) {
+ mLayerTracing.store(&layerTracing);
+
+ auto args = perfetto::TracingInitArgs{};
+ args.backends = perfetto::kSystemBackend;
+ // We are tracing ~50kb/entry and the default shmem buffer size (256kb) could be overrun.
+ // A shmem buffer overrun typically just stalls layer tracing, however when the stall
+ // lasts for too long perfetto assumes there is a deadlock and aborts surfaceflinger.
+ args.shmem_size_hint_kb = 1024;
+ perfetto::Tracing::Initialize(args);
+
+ perfetto::DataSourceDescriptor descriptor;
+ descriptor.set_name(android::LayerDataSource::kName);
+ LayerDataSource::Register(descriptor);
+}
+
+void LayerDataSource::UnregisterLayerTracing() {
+ mLayerTracing.store(nullptr);
+}
+
+void LayerDataSource::OnSetup(const LayerDataSource::SetupArgs& args) {
+ const auto configRaw = args.config->surfaceflinger_layers_config_raw();
+ const auto config = perfetto::protos::pbzero::SurfaceFlingerLayersConfig::Decoder{configRaw};
+
+ if (config.has_mode() && config.mode() != LayerTracing::Mode::MODE_UNSPECIFIED) {
+ mMode = static_cast<LayerTracing::Mode>(config.mode());
+ } else {
+ mMode = LayerTracing::Mode::MODE_GENERATED;
+ ALOGV("Received config with unspecified 'mode'. Using 'GENERATED' as default");
+ }
+
+ mFlags = 0;
+ for (auto it = config.trace_flags(); it; ++it) {
+ mFlags |= static_cast<uint32_t>(*it);
+ }
+}
+
+void LayerDataSource::OnStart(const LayerDataSource::StartArgs&) {
+ ALOGV("Received OnStart event (mode = 0x%02x, flags = 0x%02x)", mMode, mFlags);
+ if (auto* p = mLayerTracing.load()) {
+ p->onStart(mMode, mFlags);
+ }
+}
+
+void LayerDataSource::OnFlush(const LayerDataSource::FlushArgs&) {
+ ALOGV("Received OnFlush event (mode = 0x%02x, flags = 0x%02x)", mMode, mFlags);
+ if (auto* p = mLayerTracing.load()) {
+ p->onFlush(mMode, mFlags);
+ }
+}
+
+void LayerDataSource::OnStop(const LayerDataSource::StopArgs&) {
+ ALOGV("Received OnStop event (mode = 0x%02x, flags = 0x%02x)", mMode, mFlags);
+ if (auto* p = mLayerTracing.load()) {
+ p->onStop(mMode);
+ }
+}
+
+LayerTracing::Mode LayerDataSource::GetMode() const {
+ return mMode;
+}
+
+std::atomic<LayerTracing*> LayerDataSource::mLayerTracing = nullptr;
+
+} // namespace android
+
+PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::LayerDataSource);
diff --git a/services/surfaceflinger/Tracing/LayerDataSource.h b/services/surfaceflinger/Tracing/LayerDataSource.h
new file mode 100644
index 0000000..7944092
--- /dev/null
+++ b/services/surfaceflinger/Tracing/LayerDataSource.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "LayerTracing.h"
+
+#include <perfetto/tracing.h>
+
+#include <atomic>
+
+namespace android {
+
+/*
+ * Thread local storage used for fast (lock free) read of data source's properties.
+ *
+ */
+struct LayerDataSourceTlsState {
+ template <typename TraceContext>
+ explicit LayerDataSourceTlsState(const TraceContext& trace_context) {
+ auto dataSource = trace_context.GetDataSourceLocked();
+ mMode = dataSource.valid()
+ ? dataSource->GetMode()
+ : perfetto::protos::pbzero::SurfaceFlingerLayersConfig::Mode::MODE_GENERATED;
+ }
+
+ LayerTracing::Mode mMode;
+};
+
+struct LayerDataSourceTraits : public perfetto::DefaultDataSourceTraits {
+ using TlsStateType = LayerDataSourceTlsState;
+};
+
+/*
+ * Defines the Perfetto custom data source 'android.surfaceflinger.layers'.
+ *
+ * Registers the data source with Perfetto, listens to Perfetto events (setup/start/flush/stop)
+ * and writes trace packets to Perfetto.
+ *
+ */
+class LayerDataSource : public perfetto::DataSource<LayerDataSource, LayerDataSourceTraits> {
+public:
+ static void Initialize(LayerTracing&);
+ static void UnregisterLayerTracing();
+ void OnSetup(const SetupArgs&) override;
+ void OnStart(const StartArgs&) override;
+ void OnFlush(const FlushArgs&) override;
+ void OnStop(const StopArgs&) override;
+ LayerTracing::Mode GetMode() const;
+
+ static constexpr auto* kName = "android.surfaceflinger.layers";
+ static constexpr perfetto::BufferExhaustedPolicy kBufferExhaustedPolicy =
+ perfetto::BufferExhaustedPolicy::kStall;
+ static constexpr bool kRequiresCallbacksUnderLock = false;
+
+private:
+ static std::atomic<LayerTracing*> mLayerTracing;
+ LayerTracing::Mode mMode;
+ std::uint32_t mFlags;
+};
+
+} // namespace android
+
+PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(android::LayerDataSource);
diff --git a/services/surfaceflinger/Tracing/LayerTracing.cpp b/services/surfaceflinger/Tracing/LayerTracing.cpp
index b92d50b..e55b4c2 100644
--- a/services/surfaceflinger/Tracing/LayerTracing.cpp
+++ b/services/surfaceflinger/Tracing/LayerTracing.cpp
@@ -18,131 +18,177 @@
#define LOG_TAG "LayerTracing"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <filesystem>
-
-#include <SurfaceFlinger.h>
-#include <android-base/stringprintf.h>
-#include <log/log.h>
-#include <utils/SystemClock.h>
-#include <utils/Trace.h>
-
#include "LayerTracing.h"
-#include "TransactionRingBuffer.h"
+
+#include "LayerDataSource.h"
+#include "Tracing/tools/LayerTraceGenerator.h"
+#include "TransactionTracing.h"
+
+#include <log/log.h>
+#include <perfetto/tracing.h>
+#include <utils/Timers.h>
+#include <utils/Trace.h>
namespace android {
-LayerTracing::LayerTracing()
- : mBuffer(std::make_unique<TransactionRingBuffer<LayersTraceFileProto, LayersTraceProto>>()) {
+LayerTracing::LayerTracing() {
+ mTakeLayersSnapshotProto = [](uint32_t) { return perfetto::protos::LayersSnapshotProto{}; };
+ LayerDataSource::Initialize(*this);
}
-LayerTracing::~LayerTracing() = default;
+LayerTracing::~LayerTracing() {
+ LayerDataSource::UnregisterLayerTracing();
+}
-bool LayerTracing::enable() {
- std::scoped_lock lock(mTraceLock);
- if (mEnabled) {
- return false;
+void LayerTracing::setTakeLayersSnapshotProtoFunction(
+ const std::function<perfetto::protos::LayersSnapshotProto(uint32_t)>& callback) {
+ mTakeLayersSnapshotProto = callback;
+}
+
+void LayerTracing::setTransactionTracing(TransactionTracing& transactionTracing) {
+ mTransactionTracing = &transactionTracing;
+}
+
+void LayerTracing::setOutputStream(std::ostream& outStream) {
+ mOutStream = std::ref(outStream);
+}
+
+void LayerTracing::onStart(Mode mode, uint32_t flags) {
+ switch (mode) {
+ case Mode::MODE_ACTIVE: {
+ mActiveTracingFlags.store(flags);
+ mIsActiveTracingStarted.store(true);
+ ALOGV("Starting active tracing (waiting for initial snapshot)");
+ // It might take a while before a layers change occurs and a "spontaneous" snapshot is
+ // taken. Let's manually take a snapshot, so that the trace's first entry will contain
+ // the current layers state.
+ addProtoSnapshotToOstream(mTakeLayersSnapshotProto(flags), Mode::MODE_ACTIVE);
+ ALOGV("Started active tracing (traced initial snapshot)");
+ break;
+ }
+ case Mode::MODE_GENERATED: {
+ ALOGV("Started generated tracing (waiting for OnFlush event to generated layers)");
+ break;
+ }
+ case Mode::MODE_DUMP: {
+ ALOGV("Starting dump tracing (dumping single snapshot)");
+ auto snapshot = mTakeLayersSnapshotProto(flags);
+ addProtoSnapshotToOstream(std::move(snapshot), Mode::MODE_DUMP);
+ ALOGV("Started dump tracing (dumped single snapshot)");
+ break;
+ }
+ default: {
+ ALOGE("Started unknown tracing mode (0x%02x)", mode);
+ }
}
- mBuffer->setSize(mBufferSizeInBytes);
- mEnabled = true;
- return true;
}
-bool LayerTracing::disable(std::string filename, bool writeToFile) {
- std::scoped_lock lock(mTraceLock);
- if (!mEnabled) {
- return false;
+void LayerTracing::onFlush(Mode mode, uint32_t flags) {
+ // In "generated" mode process the buffer of transactions (owned by TransactionTracing),
+ // generate a sequence of layers snapshots and write them to perfetto.
+ if (mode != Mode::MODE_GENERATED) {
+ return;
}
- mEnabled = false;
- if (writeToFile) {
- LayersTraceFileProto fileProto = createTraceFileProto();
- mBuffer->writeToFile(fileProto, filename);
+
+ if (!mTransactionTracing) {
+ ALOGV("Skipping layers trace generation (transactions tracing disabled)");
+ return;
}
- mBuffer->reset();
- return true;
+
+ auto transactionTrace = mTransactionTracing->writeToProto();
+ LayerTraceGenerator{}.generate(transactionTrace, flags);
+ ALOGV("Flushed generated tracing");
}
-void LayerTracing::appendToStream(std::ofstream& out) {
- std::scoped_lock lock(mTraceLock);
- LayersTraceFileProto fileProto = createTraceFileProto();
- mBuffer->appendToStream(fileProto, out);
- mBuffer->reset();
-}
-
-bool LayerTracing::isEnabled() const {
- std::scoped_lock lock(mTraceLock);
- return mEnabled;
-}
-
-status_t LayerTracing::writeToFile(std::string filename) {
- std::scoped_lock lock(mTraceLock);
- if (!mEnabled) {
- return STATUS_OK;
+void LayerTracing::onStop(Mode mode) {
+ if (mode == Mode::MODE_ACTIVE) {
+ mIsActiveTracingStarted.store(false);
+ ALOGV("Stopped active tracing");
}
- LayersTraceFileProto fileProto = createTraceFileProto();
- return mBuffer->writeToFile(fileProto, filename);
}
-void LayerTracing::setTraceFlags(uint32_t flags) {
- std::scoped_lock lock(mTraceLock);
- mFlags = flags;
+void LayerTracing::addProtoSnapshotToOstream(perfetto::protos::LayersSnapshotProto&& snapshot,
+ Mode mode) {
+ ATRACE_CALL();
+ if (mOutStream) {
+ writeSnapshotToStream(std::move(snapshot));
+ } else {
+ writeSnapshotToPerfetto(snapshot, mode);
+ }
}
-void LayerTracing::setBufferSize(size_t bufferSizeInBytes) {
- std::scoped_lock lock(mTraceLock);
- mBufferSizeInBytes = bufferSizeInBytes;
+bool LayerTracing::isActiveTracingStarted() const {
+ return mIsActiveTracingStarted.load();
}
-bool LayerTracing::flagIsSet(uint32_t flags) const {
- return (mFlags & flags) == flags;
-}
-uint32_t LayerTracing::getFlags() const {
- return mFlags;
+uint32_t LayerTracing::getActiveTracingFlags() const {
+ return mActiveTracingFlags.load();
}
-LayersTraceFileProto LayerTracing::createTraceFileProto() {
- LayersTraceFileProto fileProto;
- fileProto.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
- LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
- auto timeOffsetNs = static_cast<std::uint64_t>(systemTime(SYSTEM_TIME_REALTIME) -
- systemTime(SYSTEM_TIME_MONOTONIC));
+bool LayerTracing::isActiveTracingFlagSet(Flag flag) const {
+ return (mActiveTracingFlags.load() & flag) != 0;
+}
+
+perfetto::protos::LayersTraceFileProto LayerTracing::createTraceFileProto() {
+ perfetto::protos::LayersTraceFileProto fileProto;
+ fileProto.set_magic_number(
+ static_cast<uint64_t>(perfetto::protos::LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H)
+ << 32 |
+ perfetto::protos::LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
+ auto timeOffsetNs = static_cast<uint64_t>(systemTime(SYSTEM_TIME_REALTIME) -
+ systemTime(SYSTEM_TIME_MONOTONIC));
fileProto.set_real_to_elapsed_time_offset_nanos(timeOffsetNs);
return fileProto;
}
-void LayerTracing::dump(std::string& result) const {
- std::scoped_lock lock(mTraceLock);
- base::StringAppendF(&result, "Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
- mBuffer->dump(result);
+void LayerTracing::writeSnapshotToStream(perfetto::protos::LayersSnapshotProto&& snapshot) const {
+ auto fileProto = createTraceFileProto();
+ *fileProto.add_entry() = std::move(snapshot);
+ mOutStream->get() << fileProto.SerializeAsString();
}
-void LayerTracing::notify(bool visibleRegionDirty, int64_t time, int64_t vsyncId,
- LayersProto* layers, std::string hwcDump,
- google::protobuf::RepeatedPtrField<DisplayProto>* displays) {
- std::scoped_lock lock(mTraceLock);
- if (!mEnabled) {
- return;
+void LayerTracing::writeSnapshotToPerfetto(const perfetto::protos::LayersSnapshotProto& snapshot,
+ Mode mode) {
+ const auto snapshotBytes = snapshot.SerializeAsString();
+
+ LayerDataSource::Trace([&](LayerDataSource::TraceContext context) {
+ if (mode != context.GetCustomTlsState()->mMode) {
+ return;
+ }
+ if (!checkAndUpdateLastVsyncIdWrittenToPerfetto(mode, snapshot.vsync_id())) {
+ return;
+ }
+ {
+ auto packet = context.NewTracePacket();
+ packet->set_timestamp(static_cast<uint64_t>(snapshot.elapsed_realtime_nanos()));
+ packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
+ auto* snapshotProto = packet->set_surfaceflinger_layers_snapshot();
+ snapshotProto->AppendRawProtoBytes(snapshotBytes.data(), snapshotBytes.size());
+ }
+ {
+ // TODO (b/162206162): remove empty packet when perfetto bug is fixed.
+ // It is currently needed in order not to lose the last trace entry.
+ context.NewTracePacket();
+ }
+ });
+}
+
+bool LayerTracing::checkAndUpdateLastVsyncIdWrittenToPerfetto(Mode mode, std::int64_t vsyncId) {
+ // In some situations (e.g. two bugreports taken shortly one after the other) the generated
+ // sequence of layers snapshots might overlap. Here we check the snapshot's vsyncid to make
+ // sure that in generated tracing mode a given snapshot is written only once to perfetto.
+ if (mode != Mode::MODE_GENERATED) {
+ return true;
}
- if (!visibleRegionDirty && !flagIsSet(LayerTracing::TRACE_BUFFERS)) {
- return;
+ auto lastVsyncId = mLastVsyncIdWrittenToPerfetto.load();
+ while (lastVsyncId < vsyncId) {
+ if (mLastVsyncIdWrittenToPerfetto.compare_exchange_strong(lastVsyncId, vsyncId)) {
+ return true;
+ }
}
- ATRACE_CALL();
- LayersTraceProto entry;
- entry.set_elapsed_realtime_nanos(time);
- const char* where = visibleRegionDirty ? "visibleRegionsDirty" : "bufferLatched";
- entry.set_where(where);
- entry.mutable_layers()->Swap(layers);
-
- if (flagIsSet(LayerTracing::TRACE_HWC)) {
- entry.set_hwc_blob(hwcDump);
- }
- if (!flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
- entry.set_excludes_composition_state(true);
- }
- entry.mutable_displays()->Swap(displays);
- entry.set_vsync_id(vsyncId);
- mBuffer->emplace(std::move(entry));
+ return false;
}
} // namespace android
diff --git a/services/surfaceflinger/Tracing/LayerTracing.h b/services/surfaceflinger/Tracing/LayerTracing.h
index 7c0d23d..349cc40 100644
--- a/services/surfaceflinger/Tracing/LayerTracing.h
+++ b/services/surfaceflinger/Tracing/LayerTracing.h
@@ -16,42 +16,77 @@
#pragma once
-#include <android-base/thread_annotations.h>
#include <layerproto/LayerProtoHeader.h>
-#include <utils/Errors.h>
-#include <utils/StrongPointer.h>
-#include <utils/Timers.h>
-#include <memory>
-#include <mutex>
-
-using namespace android::surfaceflinger;
+#include <atomic>
+#include <functional>
+#include <optional>
+#include <ostream>
namespace android {
-template <typename FileProto, typename EntryProto>
-class TransactionRingBuffer;
-
-class SurfaceFlinger;
+class TransactionTracing;
/*
* LayerTracing records layer states during surface flinging. Manages tracing state and
* configuration.
+ *
+ * The traced data can then be collected with Perfetto.
+ *
+ * The Perfetto custom data source LayerDataSource is registered with perfetto. The data source
+ * is used to listen to perfetto events (setup, start, stop, flush) and to write trace packets
+ * to perfetto.
+ *
+ * The user can configure/start/stop tracing via /system/bin/perfetto.
+ *
+ * Tracing can operate in the following modes.
+ *
+ * ACTIVE mode:
+ * A layers snapshot is taken and written to perfetto for each vsyncid commit.
+ *
+ * GENERATED mode:
+ * Listens to the perfetto 'flush' event (e.g. when a bugreport is taken).
+ * When a 'flush' event is received, the ring buffer of transactions (hold by TransactionTracing)
+ * is processed by LayerTraceGenerator, a sequence of layers snapshots is generated
+ * and written to perfetto.
+ *
+ * DUMP mode:
+ * When the 'start' event is received a single layers snapshot is taken
+ * and written to perfetto.
+ *
+ *
+ * E.g. start active mode tracing:
+ *
+ adb shell -t perfetto \
+ -c - --txt \
+ -o /data/misc/perfetto-traces/trace \
+ <<EOF
+ unique_session_name: "surfaceflinger_layers_active"
+ buffers: {
+ size_kb: 63488
+ fill_policy: RING_BUFFER
+ }
+ data_sources: {
+ config {
+ name: "android.surfaceflinger.layers"
+ surfaceflinger_layers_config: {
+ mode: MODE_ACTIVE
+ trace_flags: TRACE_FLAG_INPUT
+ trace_flags: TRACE_FLAG_COMPOSITION
+ trace_flags: TRACE_FLAG_HWC
+ trace_flags: TRACE_FLAG_BUFFERS
+ trace_flags: TRACE_FLAG_VIRTUAL_DISPLAYS
+ }
+ }
+ }
+ EOF
+ *
*/
class LayerTracing {
public:
- LayerTracing();
- ~LayerTracing();
- bool enable();
- bool disable(std::string filename = FILE_NAME, bool writeToFile = true);
- void appendToStream(std::ofstream& out);
- bool isEnabled() const;
- status_t writeToFile(std::string filename = FILE_NAME);
- static LayersTraceFileProto createTraceFileProto();
- void notify(bool visibleRegionDirty, int64_t time, int64_t vsyncId, LayersProto* layers,
- std::string hwcDump, google::protobuf::RepeatedPtrField<DisplayProto>* displays);
+ using Mode = perfetto::protos::pbzero::SurfaceFlingerLayersConfig::Mode;
- enum : uint32_t {
+ enum Flag : uint32_t {
TRACE_INPUT = 1 << 1,
TRACE_COMPOSITION = 1 << 2,
TRACE_EXTRA = 1 << 3,
@@ -60,20 +95,39 @@
TRACE_VIRTUAL_DISPLAYS = 1 << 6,
TRACE_ALL = TRACE_INPUT | TRACE_COMPOSITION | TRACE_EXTRA,
};
- void setTraceFlags(uint32_t flags);
- bool flagIsSet(uint32_t flags) const;
- uint32_t getFlags() const;
- void setBufferSize(size_t bufferSizeInBytes);
- void dump(std::string&) const;
+
+ LayerTracing();
+ ~LayerTracing();
+ void setTakeLayersSnapshotProtoFunction(
+ const std::function<perfetto::protos::LayersSnapshotProto(uint32_t)>&);
+ void setTransactionTracing(TransactionTracing&);
+ void setOutputStream(std::ostream&);
+
+ // Start event from perfetto data source
+ void onStart(Mode mode, uint32_t flags);
+ // Flush event from perfetto data source
+ void onFlush(Mode mode, uint32_t flags);
+ // Stop event from perfetto data source
+ void onStop(Mode mode);
+
+ void addProtoSnapshotToOstream(perfetto::protos::LayersSnapshotProto&& snapshot, Mode mode);
+ bool isActiveTracingStarted() const;
+ uint32_t getActiveTracingFlags() const;
+ bool isActiveTracingFlagSet(Flag flag) const;
+ static perfetto::protos::LayersTraceFileProto createTraceFileProto();
private:
- static constexpr auto FILE_NAME = "/data/misc/wmtrace/layers_trace.winscope";
- uint32_t mFlags = TRACE_INPUT;
- mutable std::mutex mTraceLock;
- bool mEnabled GUARDED_BY(mTraceLock) = false;
- std::unique_ptr<TransactionRingBuffer<LayersTraceFileProto, LayersTraceProto>> mBuffer
- GUARDED_BY(mTraceLock);
- size_t mBufferSizeInBytes GUARDED_BY(mTraceLock) = 20 * 1024 * 1024;
+ void writeSnapshotToStream(perfetto::protos::LayersSnapshotProto&& snapshot) const;
+ void writeSnapshotToPerfetto(const perfetto::protos::LayersSnapshotProto& snapshot, Mode mode);
+ bool checkAndUpdateLastVsyncIdWrittenToPerfetto(Mode mode, std::int64_t vsyncId);
+
+ std::function<perfetto::protos::LayersSnapshotProto(uint32_t)> mTakeLayersSnapshotProto;
+ TransactionTracing* mTransactionTracing;
+
+ std::atomic<bool> mIsActiveTracingStarted{false};
+ std::atomic<uint32_t> mActiveTracingFlags{0};
+ std::atomic<std::int64_t> mLastVsyncIdWrittenToPerfetto{-1};
+ std::optional<std::reference_wrapper<std::ostream>> mOutStream;
};
} // namespace android
diff --git a/services/surfaceflinger/Tracing/TransactionDataSource.cpp b/services/surfaceflinger/Tracing/TransactionDataSource.cpp
new file mode 100644
index 0000000..05b89b8
--- /dev/null
+++ b/services/surfaceflinger/Tracing/TransactionDataSource.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2023 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 "TransactionDataSource.h"
+#include "TransactionTracing.h"
+
+#undef LOG_TAG
+#define LOG_TAG "TransactionTracing"
+
+#include <log/log.h>
+
+namespace android {
+
+void TransactionDataSource::Initialize(TransactionTracing& transactionTracing) {
+ mTransactionTracing.store(&transactionTracing);
+
+ auto args = perfetto::TracingInitArgs{};
+ args.backends = perfetto::kSystemBackend;
+ perfetto::Tracing::Initialize(args);
+
+ perfetto::DataSourceDescriptor descriptor;
+ descriptor.set_name(kName);
+ TransactionDataSource::Register(descriptor);
+}
+
+void TransactionDataSource::UnregisterTransactionTracing() {
+ mTransactionTracing.store(nullptr);
+}
+
+void TransactionDataSource::OnSetup(const TransactionDataSource::SetupArgs& args) {
+ const auto configRaw = args.config->surfaceflinger_transactions_config_raw();
+ const auto config =
+ perfetto::protos::pbzero::SurfaceFlingerTransactionsConfig::Decoder{configRaw};
+
+ if (config.has_mode() && config.mode() != TransactionTracing::Mode::MODE_UNSPECIFIED) {
+ mMode = static_cast<TransactionTracing::Mode>(config.mode());
+ } else {
+ mMode = TransactionTracing::Mode::MODE_CONTINUOUS;
+ ALOGV("Received config with unspecified 'mode'. Using 'CONTINUOUS' as default");
+ }
+}
+
+void TransactionDataSource::OnStart(const StartArgs&) {
+ ALOGV("Received OnStart event");
+ if (auto* p = mTransactionTracing.load()) {
+ p->onStart(mMode);
+ }
+}
+
+void TransactionDataSource::OnFlush(const FlushArgs&) {
+ ALOGV("Received OnFlush event");
+ if (auto* p = mTransactionTracing.load()) {
+ p->onFlush(mMode);
+ }
+}
+
+void TransactionDataSource::OnStop(const StopArgs&) {
+ ALOGV("Received OnStop event");
+}
+
+TransactionTracing::Mode TransactionDataSource::GetMode() const {
+ return mMode;
+}
+
+std::atomic<TransactionTracing*> TransactionDataSource::mTransactionTracing = nullptr;
+
+} // namespace android
+
+PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::TransactionDataSource);
diff --git a/services/surfaceflinger/Tracing/TransactionDataSource.h b/services/surfaceflinger/Tracing/TransactionDataSource.h
new file mode 100644
index 0000000..be8373b
--- /dev/null
+++ b/services/surfaceflinger/Tracing/TransactionDataSource.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "TransactionTracing.h"
+
+#include <perfetto/tracing.h>
+
+namespace android {
+
+/*
+ * Thread local storage used for fast (lock free) read of data source's properties.
+ *
+ */
+struct TransactionDataSourceTlsState {
+ template <typename TraceContext>
+ explicit TransactionDataSourceTlsState(const TraceContext& trace_context) {
+ auto dataSource = trace_context.GetDataSourceLocked();
+ mMode = dataSource.valid() ? dataSource->GetMode()
+ : TransactionTracing::Mode::MODE_CONTINUOUS;
+ }
+
+ TransactionTracing::Mode mMode;
+};
+
+struct TransactionDataSourceTraits : public perfetto::DefaultDataSourceTraits {
+ using TlsStateType = TransactionDataSourceTlsState;
+};
+
+/*
+ * Defines the Perfetto custom data source 'android.surfaceflinger.transactions'.
+ *
+ * Registers the data source with Perfetto, listens to Perfetto events (setup/start/flush/stop)
+ * and writes trace packets to Perfetto.
+ *
+ */
+class TransactionDataSource
+ : public perfetto::DataSource<TransactionDataSource, TransactionDataSourceTraits> {
+public:
+ static void Initialize(TransactionTracing&);
+ static void UnregisterTransactionTracing();
+ void OnSetup(const SetupArgs&) override;
+ void OnStart(const StartArgs&) override;
+ void OnFlush(const FlushArgs&) override;
+ void OnStop(const StopArgs&) override;
+ TransactionTracing::Mode GetMode() const;
+
+ static constexpr auto* kName = "android.surfaceflinger.transactions";
+ static constexpr perfetto::BufferExhaustedPolicy kBufferExhaustedPolicy =
+ perfetto::BufferExhaustedPolicy::kStall;
+ static constexpr bool kRequiresCallbacksUnderLock = false;
+
+private:
+ static std::atomic<TransactionTracing*> mTransactionTracing;
+ TransactionTracing::Mode mMode;
+};
+
+} // namespace android
+
+PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(android::TransactionDataSource);
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
index b1e3d63..2dc89b5 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
@@ -51,8 +51,8 @@
~FakeExternalTexture() = default;
};
-proto::TransactionState TransactionProtoParser::toProto(const TransactionState& t) {
- proto::TransactionState proto;
+perfetto::protos::TransactionState TransactionProtoParser::toProto(const TransactionState& t) {
+ perfetto::protos::TransactionState proto;
proto.set_pid(t.originPid);
proto.set_uid(t.originUid);
proto.set_vsync_id(t.frameTimelineInfo.vsyncId);
@@ -79,21 +79,21 @@
return proto;
}
-proto::TransactionState TransactionProtoParser::toProto(
+perfetto::protos::TransactionState TransactionProtoParser::toProto(
const std::map<uint32_t /* layerId */, TracingLayerState>& states) {
- proto::TransactionState proto;
+ perfetto::protos::TransactionState proto;
proto.mutable_layer_changes()->Reserve(static_cast<int32_t>(states.size()));
for (auto& [layerId, state] : states) {
- proto::LayerState layerProto = toProto(state);
+ perfetto::protos::LayerState layerProto = toProto(state);
layerProto.set_has_sideband_stream(state.hasSidebandStream);
proto.mutable_layer_changes()->Add(std::move(layerProto));
}
return proto;
}
-proto::LayerState TransactionProtoParser::toProto(
+perfetto::protos::LayerState TransactionProtoParser::toProto(
const ResolvedComposerState& resolvedComposerState) {
- proto::LayerState proto;
+ perfetto::protos::LayerState proto;
auto& layer = resolvedComposerState.state;
proto.set_layer_id(resolvedComposerState.layerId);
proto.set_what(layer.what);
@@ -114,7 +114,7 @@
proto.set_mask(layer.mask);
}
if (layer.what & layer_state_t::eMatrixChanged) {
- proto::LayerState_Matrix22* matrixProto = proto.mutable_matrix();
+ perfetto::protos::LayerState_Matrix22* matrixProto = proto.mutable_matrix();
matrixProto->set_dsdx(layer.matrix.dsdx);
matrixProto->set_dsdy(layer.matrix.dsdy);
matrixProto->set_dtdx(layer.matrix.dtdx);
@@ -132,7 +132,7 @@
}
if (layer.what & layer_state_t::eColorChanged) {
- proto::LayerState_Color3* colorProto = proto.mutable_color();
+ perfetto::protos::LayerState_Color3* colorProto = proto.mutable_color();
colorProto->set_r(layer.color.r);
colorProto->set_g(layer.color.g);
colorProto->set_b(layer.color.b);
@@ -150,13 +150,14 @@
LayerProtoHelper::writeToProto(layer.crop, proto.mutable_crop());
}
if (layer.what & layer_state_t::eBufferChanged) {
- proto::LayerState_BufferData* bufferProto = proto.mutable_buffer_data();
+ perfetto::protos::LayerState_BufferData* bufferProto = proto.mutable_buffer_data();
if (resolvedComposerState.externalTexture) {
bufferProto->set_buffer_id(resolvedComposerState.externalTexture->getId());
bufferProto->set_width(resolvedComposerState.externalTexture->getWidth());
bufferProto->set_height(resolvedComposerState.externalTexture->getHeight());
- bufferProto->set_pixel_format(static_cast<proto::LayerState_BufferData_PixelFormat>(
- resolvedComposerState.externalTexture->getPixelFormat()));
+ bufferProto->set_pixel_format(
+ static_cast<perfetto::protos::LayerState_BufferData_PixelFormat>(
+ resolvedComposerState.externalTexture->getPixelFormat()));
bufferProto->set_usage(resolvedComposerState.externalTexture->getUsage());
}
bufferProto->set_frame_number(layer.bufferData->frameNumber);
@@ -191,7 +192,8 @@
if (layer.what & layer_state_t::eInputInfoChanged) {
if (layer.windowInfoHandle) {
const gui::WindowInfo* inputInfo = layer.windowInfoHandle->getInfo();
- proto::LayerState_WindowInfo* windowInfoProto = proto.mutable_window_info_handle();
+ perfetto::protos::LayerState_WindowInfo* windowInfoProto =
+ proto.mutable_window_info_handle();
windowInfoProto->set_layout_params_flags(inputInfo->layoutParamsFlags.get());
windowInfoProto->set_layout_params_type(
static_cast<int32_t>(inputInfo->layoutParamsType));
@@ -204,7 +206,7 @@
windowInfoProto->set_has_wallpaper(inputInfo->inputConfig.test(
gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER));
windowInfoProto->set_global_scale_factor(inputInfo->globalScaleFactor);
- proto::Transform* transformProto = windowInfoProto->mutable_transform();
+ perfetto::protos::Transform* transformProto = windowInfoProto->mutable_transform();
transformProto->set_dsdx(inputInfo->transform.dsdx());
transformProto->set_dtdx(inputInfo->transform.dtdx());
transformProto->set_dtdy(inputInfo->transform.dtdy());
@@ -219,7 +221,7 @@
if (layer.what & layer_state_t::eBackgroundColorChanged) {
proto.set_bg_color_alpha(layer.bgColor.a);
proto.set_bg_color_dataspace(static_cast<int32_t>(layer.bgColorDataspace));
- proto::LayerState_Color3* colorProto = proto.mutable_color();
+ perfetto::protos::LayerState_Color3* colorProto = proto.mutable_color();
colorProto->set_r(layer.bgColor.r);
colorProto->set_g(layer.bgColor.g);
colorProto->set_b(layer.bgColor.b);
@@ -255,13 +257,13 @@
}
if (layer.what & layer_state_t::eDropInputModeChanged) {
proto.set_drop_input_mode(
- static_cast<proto::LayerState_DropInputMode>(layer.dropInputMode));
+ static_cast<perfetto::protos::LayerState_DropInputMode>(layer.dropInputMode));
}
return proto;
}
-proto::DisplayState TransactionProtoParser::toProto(const DisplayState& display) {
- proto::DisplayState proto;
+perfetto::protos::DisplayState TransactionProtoParser::toProto(const DisplayState& display) {
+ perfetto::protos::DisplayState proto;
proto.set_what(display.what);
proto.set_id(mMapper->getDisplayId(display.token));
@@ -285,8 +287,8 @@
return proto;
}
-proto::LayerCreationArgs TransactionProtoParser::toProto(const LayerCreationArgs& args) {
- proto::LayerCreationArgs proto;
+perfetto::protos::LayerCreationArgs TransactionProtoParser::toProto(const LayerCreationArgs& args) {
+ perfetto::protos::LayerCreationArgs proto;
proto.set_layer_id(args.sequence);
proto.set_name(args.name);
proto.set_flags(args.flags);
@@ -297,7 +299,8 @@
return proto;
}
-TransactionState TransactionProtoParser::fromProto(const proto::TransactionState& proto) {
+TransactionState TransactionProtoParser::fromProto(
+ const perfetto::protos::TransactionState& proto) {
TransactionState t;
t.originPid = proto.pid();
t.originUid = proto.uid();
@@ -323,7 +326,7 @@
return t;
}
-void TransactionProtoParser::fromProto(const proto::LayerCreationArgs& proto,
+void TransactionProtoParser::fromProto(const perfetto::protos::LayerCreationArgs& proto,
LayerCreationArgs& outArgs) {
outArgs.sequence = proto.layer_id();
@@ -335,7 +338,7 @@
outArgs.layerStackToMirror.id = proto.layer_stack_to_mirror();
}
-void TransactionProtoParser::mergeFromProto(const proto::LayerState& proto,
+void TransactionProtoParser::mergeFromProto(const perfetto::protos::LayerState& proto,
TracingLayerState& outState) {
ResolvedComposerState resolvedComposerState;
fromProto(proto, resolvedComposerState);
@@ -360,7 +363,7 @@
}
}
-void TransactionProtoParser::fromProto(const proto::LayerState& proto,
+void TransactionProtoParser::fromProto(const perfetto::protos::LayerState& proto,
ResolvedComposerState& resolvedComposerState) {
auto& layer = resolvedComposerState.state;
resolvedComposerState.layerId = proto.layer_id();
@@ -381,7 +384,7 @@
layer.mask = proto.mask();
}
if (proto.what() & layer_state_t::eMatrixChanged) {
- const proto::LayerState_Matrix22& matrixProto = proto.matrix();
+ const perfetto::protos::LayerState_Matrix22& matrixProto = proto.matrix();
layer.matrix.dsdx = matrixProto.dsdx();
layer.matrix.dsdy = matrixProto.dsdy();
layer.matrix.dtdx = matrixProto.dtdx();
@@ -399,7 +402,7 @@
}
if (proto.what() & layer_state_t::eColorChanged) {
- const proto::LayerState_Color3& colorProto = proto.color();
+ const perfetto::protos::LayerState_Color3& colorProto = proto.color();
layer.color.r = colorProto.r();
layer.color.g = colorProto.g();
layer.color.b = colorProto.b();
@@ -417,7 +420,7 @@
LayerProtoHelper::readFromProto(proto.crop(), layer.crop);
}
if (proto.what() & layer_state_t::eBufferChanged) {
- const proto::LayerState_BufferData& bufferProto = proto.buffer_data();
+ const perfetto::protos::LayerState_BufferData& bufferProto = proto.buffer_data();
layer.bufferData =
std::make_shared<fake::BufferData>(bufferProto.buffer_id(), bufferProto.width(),
bufferProto.height(), bufferProto.pixel_format(),
@@ -460,7 +463,7 @@
if ((proto.what() & layer_state_t::eInputInfoChanged) && proto.has_window_info_handle()) {
gui::WindowInfo inputInfo;
- const proto::LayerState_WindowInfo& windowInfoProto = proto.window_info_handle();
+ const perfetto::protos::LayerState_WindowInfo& windowInfoProto = proto.window_info_handle();
inputInfo.layoutParamsFlags =
static_cast<gui::WindowInfo::Flag>(windowInfoProto.layout_params_flags());
@@ -472,7 +475,7 @@
ftl::Flags<gui::WindowInfo::InputConfig>(windowInfoProto.input_config());
inputInfo.surfaceInset = windowInfoProto.surface_inset();
inputInfo.globalScaleFactor = windowInfoProto.global_scale_factor();
- const proto::Transform& transformProto = windowInfoProto.transform();
+ const perfetto::protos::Transform& transformProto = windowInfoProto.transform();
inputInfo.transform.set(transformProto.dsdx(), transformProto.dtdx(), transformProto.dtdy(),
transformProto.dsdy());
inputInfo.transform.set(transformProto.tx(), transformProto.ty());
@@ -485,7 +488,7 @@
if (proto.what() & layer_state_t::eBackgroundColorChanged) {
layer.bgColor.a = proto.bg_color_alpha();
layer.bgColorDataspace = static_cast<ui::Dataspace>(proto.bg_color_dataspace());
- const proto::LayerState_Color3& colorProto = proto.color();
+ const perfetto::protos::LayerState_Color3& colorProto = proto.color();
layer.bgColor.r = colorProto.r();
layer.bgColor.g = colorProto.g();
layer.bgColor.b = colorProto.b();
@@ -525,7 +528,7 @@
}
}
-DisplayState TransactionProtoParser::fromProto(const proto::DisplayState& proto) {
+DisplayState TransactionProtoParser::fromProto(const perfetto::protos::DisplayState& proto) {
DisplayState display;
display.what = proto.what();
display.token = mMapper->getDisplayHandle(proto.id());
@@ -550,7 +553,7 @@
return display;
}
-void asProto(proto::Transform* proto, const ui::Transform& transform) {
+void asProto(perfetto::protos::Transform* proto, const ui::Transform& transform) {
proto->set_dsdx(transform.dsdx());
proto->set_dtdx(transform.dtdx());
proto->set_dtdy(transform.dtdy());
@@ -559,9 +562,9 @@
proto->set_ty(transform.ty());
}
-proto::DisplayInfo TransactionProtoParser::toProto(const frontend::DisplayInfo& displayInfo,
- uint32_t layerStack) {
- proto::DisplayInfo proto;
+perfetto::protos::DisplayInfo TransactionProtoParser::toProto(
+ const frontend::DisplayInfo& displayInfo, uint32_t layerStack) {
+ perfetto::protos::DisplayInfo proto;
proto.set_layer_stack(layerStack);
proto.set_display_id(displayInfo.info.displayId);
proto.set_logical_width(displayInfo.info.logicalWidth);
@@ -577,12 +580,13 @@
return proto;
}
-void fromProto2(ui::Transform& outTransform, const proto::Transform& proto) {
+void fromProto2(ui::Transform& outTransform, const perfetto::protos::Transform& proto) {
outTransform.set(proto.dsdx(), proto.dtdx(), proto.dtdy(), proto.dsdy());
outTransform.set(proto.tx(), proto.ty());
}
-frontend::DisplayInfo TransactionProtoParser::fromProto(const proto::DisplayInfo& proto) {
+frontend::DisplayInfo TransactionProtoParser::fromProto(
+ const perfetto::protos::DisplayInfo& proto) {
frontend::DisplayInfo displayInfo;
displayInfo.info.displayId = proto.display_id();
displayInfo.info.logicalWidth = proto.logical_width();
@@ -599,10 +603,10 @@
}
void TransactionProtoParser::fromProto(
- const google::protobuf::RepeatedPtrField<proto::DisplayInfo>& proto,
+ const google::protobuf::RepeatedPtrField<perfetto::protos::DisplayInfo>& proto,
frontend::DisplayInfos& outDisplayInfos) {
outDisplayInfos.clear();
- for (const proto::DisplayInfo& displayInfo : proto) {
+ for (const perfetto::protos::DisplayInfo& displayInfo : proto) {
outDisplayInfos.emplace_or_replace(ui::LayerStack::fromValue(displayInfo.layer_stack()),
fromProto(displayInfo));
}
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.h b/services/surfaceflinger/Tracing/TransactionProtoParser.h
index 457c3be..b3ab71c 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.h
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.h
@@ -44,25 +44,25 @@
TransactionProtoParser(std::unique_ptr<FlingerDataMapper> provider)
: mMapper(std::move(provider)) {}
- proto::TransactionState toProto(const TransactionState&);
- proto::TransactionState toProto(const std::map<uint32_t /* layerId */, TracingLayerState>&);
- proto::LayerCreationArgs toProto(const LayerCreationArgs& args);
- proto::LayerState toProto(const ResolvedComposerState&);
- static proto::DisplayInfo toProto(const frontend::DisplayInfo&, uint32_t layerStack);
+ perfetto::protos::TransactionState toProto(const TransactionState&);
+ perfetto::protos::TransactionState toProto(
+ const std::map<uint32_t /* layerId */, TracingLayerState>&);
+ perfetto::protos::LayerCreationArgs toProto(const LayerCreationArgs& args);
+ perfetto::protos::LayerState toProto(const ResolvedComposerState&);
+ static perfetto::protos::DisplayInfo toProto(const frontend::DisplayInfo&, uint32_t layerStack);
- TransactionState fromProto(const proto::TransactionState&);
- void mergeFromProto(const proto::LayerState&, TracingLayerState& outState);
- void fromProto(const proto::LayerCreationArgs&, LayerCreationArgs& outArgs);
+ TransactionState fromProto(const perfetto::protos::TransactionState&);
+ void mergeFromProto(const perfetto::protos::LayerState&, TracingLayerState& outState);
+ void fromProto(const perfetto::protos::LayerCreationArgs&, LayerCreationArgs& outArgs);
std::unique_ptr<FlingerDataMapper> mMapper;
- static frontend::DisplayInfo fromProto(const proto::DisplayInfo&);
- static void fromProto(const google::protobuf::RepeatedPtrField<proto::DisplayInfo>&,
+ static frontend::DisplayInfo fromProto(const perfetto::protos::DisplayInfo&);
+ static void fromProto(const google::protobuf::RepeatedPtrField<perfetto::protos::DisplayInfo>&,
frontend::DisplayInfos& outDisplayInfos);
private:
- proto::DisplayState toProto(const DisplayState&);
- void fromProto(const proto::LayerState&, ResolvedComposerState& out);
- DisplayState fromProto(const proto::DisplayState&);
-
+ perfetto::protos::DisplayState toProto(const DisplayState&);
+ void fromProto(const perfetto::protos::LayerState&, ResolvedComposerState& out);
+ DisplayState fromProto(const perfetto::protos::DisplayState&);
};
} // namespace android::surfaceflinger
diff --git a/services/surfaceflinger/Tracing/TransactionRingBuffer.h b/services/surfaceflinger/Tracing/TransactionRingBuffer.h
index e6f85ca..7d1d3fd 100644
--- a/services/surfaceflinger/Tracing/TransactionRingBuffer.h
+++ b/services/surfaceflinger/Tracing/TransactionRingBuffer.h
@@ -47,7 +47,7 @@
mUsedInBytes = 0U;
}
- void writeToProto(FileProto& fileProto) {
+ void writeToProto(FileProto& fileProto) const {
fileProto.mutable_entry()->Reserve(static_cast<int>(mStorage.size()) +
fileProto.entry().size());
for (const std::string& entry : mStorage) {
@@ -56,24 +56,6 @@
}
}
- status_t writeToFile(FileProto& fileProto, std::string filename) {
- ATRACE_CALL();
- writeToProto(fileProto);
- std::string output;
- if (!fileProto.SerializeToString(&output)) {
- ALOGE("Could not serialize proto.");
- return UNKNOWN_ERROR;
- }
-
- // -rw-r--r--
- const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
- if (!android::base::WriteStringToFile(output, filename, mode, getuid(), getgid(), true)) {
- ALOGE("Could not save the proto file %s", filename.c_str());
- return PERMISSION_DENIED;
- }
- return NO_ERROR;
- }
-
status_t appendToStream(FileProto& fileProto, std::ofstream& out) {
ATRACE_CALL();
writeToProto(fileProto);
diff --git a/services/surfaceflinger/Tracing/TransactionTracing.cpp b/services/surfaceflinger/Tracing/TransactionTracing.cpp
index bc69191..0517984 100644
--- a/services/surfaceflinger/Tracing/TransactionTracing.cpp
+++ b/services/surfaceflinger/Tracing/TransactionTracing.cpp
@@ -25,6 +25,7 @@
#include "Client.h"
#include "FrontEnd/LayerCreationArgs.h"
+#include "TransactionDataSource.h"
#include "TransactionTracing.h"
namespace android {
@@ -34,15 +35,20 @@
: mProtoParser(std::make_unique<TransactionProtoParser::FlingerDataMapper>()) {
std::scoped_lock lock(mTraceLock);
- mBuffer.setSize(mBufferSizeInBytes);
+ mBuffer.setSize(CONTINUOUS_TRACING_BUFFER_SIZE);
+
mStartingTimestamp = systemTime();
+
{
std::scoped_lock lock(mMainThreadLock);
mThread = std::thread(&TransactionTracing::loop, this);
}
+
+ TransactionDataSource::Initialize(*this);
}
TransactionTracing::~TransactionTracing() {
+ TransactionDataSource::UnregisterTransactionTracing();
std::thread thread;
{
std::scoped_lock lock(mMainThreadLock);
@@ -53,29 +59,103 @@
if (thread.joinable()) {
thread.join();
}
+}
- writeToFile();
+void TransactionTracing::onStart(TransactionTracing::Mode mode) {
+ // In "active" mode write the ring buffer (starting state + following sequence of transactions)
+ // to perfetto when tracing starts (only once).
+ if (mode != Mode::MODE_ACTIVE) {
+ return;
+ }
+
+ writeRingBufferToPerfetto(TransactionTracing::Mode::MODE_ACTIVE);
+
+ ALOGV("Started active mode tracing (wrote initial transactions ring buffer to perfetto)");
+}
+
+void TransactionTracing::onFlush(TransactionTracing::Mode mode) {
+ // In "continuous" mode write the ring buffer (starting state + following sequence of
+ // transactions) to perfetto when a "flush" event is received (bugreport is taken or tracing is
+ // stopped).
+ if (mode != Mode::MODE_CONTINUOUS) {
+ return;
+ }
+
+ writeRingBufferToPerfetto(TransactionTracing::Mode::MODE_CONTINUOUS);
+
+ ALOGV("Flushed continuous mode tracing (wrote transactions ring buffer to perfetto");
+}
+
+void TransactionTracing::writeRingBufferToPerfetto(TransactionTracing::Mode mode) {
+ // Write the ring buffer (starting state + following sequence of transactions) to perfetto
+ // tracing sessions with the specified mode.
+ const auto fileProto = writeToProto();
+
+ TransactionDataSource::Trace([&](TransactionDataSource::TraceContext context) {
+ // Write packets only to tracing sessions with specified mode
+ if (context.GetCustomTlsState()->mMode != mode) {
+ return;
+ }
+ for (const auto& entryProto : fileProto.entry()) {
+ const auto entryBytes = entryProto.SerializeAsString();
+
+ auto packet = context.NewTracePacket();
+ packet->set_timestamp(static_cast<uint64_t>(entryProto.elapsed_realtime_nanos()));
+ packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
+
+ auto* transactionsProto = packet->set_surfaceflinger_transactions();
+ transactionsProto->AppendRawProtoBytes(entryBytes.data(), entryBytes.size());
+ }
+ {
+ // TODO (b/162206162): remove empty packet when perfetto bug is fixed.
+ // It is currently needed in order not to lose the last trace entry.
+ context.NewTracePacket();
+ }
+ });
}
status_t TransactionTracing::writeToFile(const std::string& filename) {
- std::scoped_lock lock(mTraceLock);
- proto::TransactionTraceFile fileProto = createTraceFileProto();
- addStartingStateToProtoLocked(fileProto);
- return mBuffer.writeToFile(fileProto, filename);
+ auto fileProto = writeToProto();
+
+ std::string output;
+ if (!fileProto.SerializeToString(&output)) {
+ ALOGE("Could not serialize proto.");
+ return UNKNOWN_ERROR;
+ }
+
+ // -rw-r--r--
+ const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+ if (!android::base::WriteStringToFile(output, filename, mode, getuid(), getgid(), true)) {
+ ALOGE("Could not save the proto file %s", filename.c_str());
+ return PERMISSION_DENIED;
+ }
+
+ return NO_ERROR;
+}
+
+perfetto::protos::TransactionTraceFile TransactionTracing::writeToProto() {
+ std::scoped_lock<std::mutex> lock(mTraceLock);
+ perfetto::protos::TransactionTraceFile fileProto = createTraceFileProto();
+ const auto startingStateProto = createStartingStateProtoLocked();
+ if (startingStateProto) {
+ *fileProto.add_entry() = std::move(*startingStateProto);
+ }
+ mBuffer.writeToProto(fileProto);
+ return fileProto;
}
void TransactionTracing::setBufferSize(size_t bufferSizeInBytes) {
std::scoped_lock lock(mTraceLock);
- mBufferSizeInBytes = bufferSizeInBytes;
- mBuffer.setSize(mBufferSizeInBytes);
+ mBuffer.setSize(bufferSizeInBytes);
}
-proto::TransactionTraceFile TransactionTracing::createTraceFileProto() const {
- proto::TransactionTraceFile proto;
- proto.set_magic_number(uint64_t(proto::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_H) << 32 |
- proto::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_L);
- auto timeOffsetNs = static_cast<std::uint64_t>(systemTime(SYSTEM_TIME_REALTIME) -
- systemTime(SYSTEM_TIME_MONOTONIC));
+perfetto::protos::TransactionTraceFile TransactionTracing::createTraceFileProto() const {
+ perfetto::protos::TransactionTraceFile proto;
+ proto.set_magic_number(
+ uint64_t(perfetto::protos::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_H) << 32 |
+ perfetto::protos::TransactionTraceFile_MagicNumber_MAGIC_NUMBER_L);
+ auto timeOffsetNs = static_cast<uint64_t>(systemTime(SYSTEM_TIME_REALTIME) -
+ systemTime(SYSTEM_TIME_MONOTONIC));
proto.set_real_to_elapsed_time_offset_nanos(timeOffsetNs);
proto.set_version(TRACING_VERSION);
return proto;
@@ -89,7 +169,8 @@
}
void TransactionTracing::addQueuedTransaction(const TransactionState& transaction) {
- proto::TransactionState* state = new proto::TransactionState(mProtoParser.toProto(transaction));
+ perfetto::protos::TransactionState* state =
+ new perfetto::protos::TransactionState(mProtoParser.toProto(transaction));
mTransactionQueue.push(state);
}
@@ -152,7 +233,7 @@
ATRACE_CALL();
std::scoped_lock lock(mTraceLock);
std::vector<std::string> removedEntries;
- proto::TransactionTraceEntry entryProto;
+ perfetto::protos::TransactionTraceEntry entryProto;
while (auto incomingTransaction = mTransactionQueue.pop()) {
auto transaction = *incomingTransaction;
@@ -204,14 +285,37 @@
std::string serializedProto;
entryProto.SerializeToString(&serializedProto);
- entryProto.Clear();
+
+ TransactionDataSource::Trace([&](TransactionDataSource::TraceContext context) {
+ // In "active" mode write each committed transaction to perfetto.
+ // Note: the starting state is written (once) when the perfetto "start" event is
+ // received.
+ if (context.GetCustomTlsState()->mMode != Mode::MODE_ACTIVE) {
+ return;
+ }
+ {
+ auto packet = context.NewTracePacket();
+ packet->set_timestamp(static_cast<uint64_t>(entryProto.elapsed_realtime_nanos()));
+ packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
+ auto* transactions = packet->set_surfaceflinger_transactions();
+ transactions->AppendRawProtoBytes(serializedProto.data(), serializedProto.size());
+ }
+ {
+ // TODO (b/162206162): remove empty packet when perfetto bug is fixed.
+ // It is currently needed in order not to lose the last trace entry.
+ context.NewTracePacket();
+ }
+ });
+
std::vector<std::string> entries = mBuffer.emplace(std::move(serializedProto));
removedEntries.reserve(removedEntries.size() + entries.size());
removedEntries.insert(removedEntries.end(), std::make_move_iterator(entries.begin()),
std::make_move_iterator(entries.end()));
+
+ entryProto.Clear();
}
- proto::TransactionTraceEntry removedEntryProto;
+ perfetto::protos::TransactionTraceEntry removedEntryProto;
for (const std::string& removedEntry : removedEntries) {
removedEntryProto.ParseFromString(removedEntry);
updateStartingStateLocked(removedEntryProto);
@@ -236,7 +340,7 @@
base::ScopedLockAssertion assumeLocked(mTraceLock);
mTransactionsAddedToBufferCv.wait_for(lock, std::chrono::milliseconds(100),
[&]() REQUIRES(mTraceLock) {
- proto::TransactionTraceEntry entry;
+ perfetto::protos::TransactionTraceEntry entry;
if (mBuffer.used() > 0) {
entry.ParseFromString(mBuffer.back());
}
@@ -268,19 +372,19 @@
}
void TransactionTracing::updateStartingStateLocked(
- const proto::TransactionTraceEntry& removedEntry) {
+ const perfetto::protos::TransactionTraceEntry& removedEntry) {
mStartingTimestamp = removedEntry.elapsed_realtime_nanos();
// Keep track of layer starting state so we can reconstruct the layer state as we purge
// transactions from the buffer.
- for (const proto::LayerCreationArgs& addedLayer : removedEntry.added_layers()) {
+ for (const perfetto::protos::LayerCreationArgs& addedLayer : removedEntry.added_layers()) {
TracingLayerState& startingState = mStartingStates[addedLayer.layer_id()];
startingState.layerId = addedLayer.layer_id();
mProtoParser.fromProto(addedLayer, startingState.args);
}
// Merge layer states to starting transaction state.
- for (const proto::TransactionState& transaction : removedEntry.transactions()) {
- for (const proto::LayerState& layerState : transaction.layer_changes()) {
+ for (const perfetto::protos::TransactionState& transaction : removedEntry.transactions()) {
+ for (const perfetto::protos::LayerState& layerState : transaction.layer_changes()) {
auto it = mStartingStates.find(layerState.layer_id());
if (it == mStartingStates.end()) {
// TODO(b/238781169) make this log fatal when we switch over to using new fe
@@ -307,43 +411,38 @@
}
}
-void TransactionTracing::addStartingStateToProtoLocked(proto::TransactionTraceFile& proto) {
- if (mStartingStates.size() == 0) {
- return;
+std::optional<perfetto::protos::TransactionTraceEntry>
+TransactionTracing::createStartingStateProtoLocked() {
+ if (mStartingStates.empty()) {
+ return std::nullopt;
}
- proto::TransactionTraceEntry* entryProto = proto.add_entry();
- entryProto->set_elapsed_realtime_nanos(mStartingTimestamp);
- entryProto->set_vsync_id(0);
+ perfetto::protos::TransactionTraceEntry entryProto;
+ entryProto.set_elapsed_realtime_nanos(mStartingTimestamp);
+ entryProto.set_vsync_id(0);
- entryProto->mutable_added_layers()->Reserve(static_cast<int32_t>(mStartingStates.size()));
+ entryProto.mutable_added_layers()->Reserve(static_cast<int32_t>(mStartingStates.size()));
for (auto& [layerId, state] : mStartingStates) {
- entryProto->mutable_added_layers()->Add(mProtoParser.toProto(state.args));
+ entryProto.mutable_added_layers()->Add(mProtoParser.toProto(state.args));
}
- proto::TransactionState transactionProto = mProtoParser.toProto(mStartingStates);
+ perfetto::protos::TransactionState transactionProto = mProtoParser.toProto(mStartingStates);
transactionProto.set_vsync_id(0);
transactionProto.set_post_time(mStartingTimestamp);
- entryProto->mutable_transactions()->Add(std::move(transactionProto));
+ entryProto.mutable_transactions()->Add(std::move(transactionProto));
- entryProto->mutable_destroyed_layer_handles()->Reserve(
+ entryProto.mutable_destroyed_layer_handles()->Reserve(
static_cast<int32_t>(mRemovedLayerHandlesAtStart.size()));
for (const uint32_t destroyedLayerHandleId : mRemovedLayerHandlesAtStart) {
- entryProto->mutable_destroyed_layer_handles()->Add(destroyedLayerHandleId);
+ entryProto.mutable_destroyed_layer_handles()->Add(destroyedLayerHandleId);
}
- entryProto->mutable_displays()->Reserve(static_cast<int32_t>(mStartingDisplayInfos.size()));
+ entryProto.mutable_displays()->Reserve(static_cast<int32_t>(mStartingDisplayInfos.size()));
for (auto& [layerStack, displayInfo] : mStartingDisplayInfos) {
- entryProto->mutable_displays()->Add(mProtoParser.toProto(displayInfo, layerStack.id));
+ entryProto.mutable_displays()->Add(mProtoParser.toProto(displayInfo, layerStack.id));
}
-}
-proto::TransactionTraceFile TransactionTracing::writeToProto() {
- std::scoped_lock<std::mutex> lock(mTraceLock);
- proto::TransactionTraceFile proto = createTraceFileProto();
- addStartingStateToProtoLocked(proto);
- mBuffer.writeToProto(proto);
- return proto;
+ return entryProto;
}
} // namespace android
diff --git a/services/surfaceflinger/Tracing/TransactionTracing.h b/services/surfaceflinger/Tracing/TransactionTracing.h
index 422b5f3..ddbf3e4 100644
--- a/services/surfaceflinger/Tracing/TransactionTracing.h
+++ b/services/surfaceflinger/Tracing/TransactionTracing.h
@@ -22,8 +22,8 @@
#include <utils/Singleton.h>
#include <utils/Timers.h>
-#include <memory>
#include <mutex>
+#include <optional>
#include <thread>
#include "FrontEnd/DisplayInfo.h"
@@ -41,7 +41,7 @@
class TransactionTracingTest;
/*
- * Records all committed transactions into a ring bufffer.
+ * Records all committed transactions into a ring buffer.
*
* Transactions come in via the binder thread. They are serialized to proto
* and stored in a map using the transaction id as key. Main thread will
@@ -49,26 +49,104 @@
* the tracing thread. The tracing thread will then wake up and add the
* committed transactions to the ring buffer.
*
- * When generating SF dump state, we will flush the buffer to a file which
- * will then be included in the bugreport.
+ * The traced data can then be collected via:
+ * - Perfetto (preferred).
+ * - File system, after triggering the disk write through SF backdoor. This is legacy and is going
+ * to be phased out.
+ *
+ * The Perfetto custom data source TransactionDataSource is registered with perfetto and is used
+ * to listen to perfetto events (setup, start, stop, flush) and to write trace packets to perfetto.
+ *
+ * The user can configure/start/stop tracing via /system/bin/perfetto.
+ *
+ * Tracing can operate in the following modes.
+ *
+ * ACTIVE mode:
+ * The transactions ring buffer (starting state + following committed transactions) is written
+ * (only once) to perfetto when the 'start' event is received.
+ * Transactions are then written to perfetto each time they are committed.
+ * On the receiver side, the data source is to be configured to periodically
+ * flush data to disk providing virtually infinite storage.
+ *
+ * CONTINUOUS mode:
+ * Listens to the perfetto 'flush' event (e.g. when a bugreport is taken).
+ * When a 'flush' event is received, the ring buffer of transactions (starting state + following
+ * committed transactions) is written to perfetto. On the receiver side, the data source is to be
+ * configured with a dedicated buffer large enough to store all the flushed data.
+ *
+ *
+ * E.g. start active mode tracing:
+ *
+ adb shell perfetto \
+ -c - --txt \
+ -o /data/misc/perfetto-traces/trace \
+ <<EOF
+ unique_session_name: "surfaceflinger_transactions_active"
+ buffers: {
+ size_kb: 1024
+ fill_policy: RING_BUFFER
+ }
+ data_sources: {
+ config {
+ name: "android.surfaceflinger.transactions"
+ surfaceflinger_transactions_config: {
+ mode: MODE_ACTIVE
+ }
+ }
+ }
+ write_into_file: true
+ file_write_period_ms: 100
+ EOF
+ *
+ *
+ * E.g. start continuous mode tracing:
+ *
+ adb shell perfetto \
+ -c - --txt \
+ -o /data/misc/perfetto-traces/trace \
+ <<EOF
+ unique_session_name: "surfaceflinger_transactions_continuous"
+ buffers: {
+ size_kb: 1024
+ fill_policy: RING_BUFFER
+ }
+ data_sources: {
+ config {
+ name: "android.surfaceflinger.transactions"
+ surfaceflinger_transactions_config: {
+ mode: MODE_CONTINUOUS
+ }
+ }
+ }
+ EOF
*
*/
class TransactionTracing {
public:
+ using Mode = perfetto::protos::pbzero::SurfaceFlingerTransactionsConfig::Mode;
+
TransactionTracing();
~TransactionTracing();
+ // Start event from perfetto data source
+ void onStart(Mode mode);
+ // Flush event from perfetto data source
+ void onFlush(Mode mode);
+
void addQueuedTransaction(const TransactionState&);
void addCommittedTransactions(int64_t vsyncId, nsecs_t commitTime, frontend::Update& update,
const frontend::DisplayInfos&, bool displayInfoChanged);
status_t writeToFile(const std::string& filename = FILE_PATH);
+ // Return buffer contents as trace file proto
+ perfetto::protos::TransactionTraceFile writeToProto() EXCLUDES(mMainThreadLock);
void setBufferSize(size_t bufferSizeInBytes);
void onLayerRemoved(int layerId);
void dump(std::string&) const;
// Wait until all the committed transactions for the specified vsync id are added to the buffer.
void flush() EXCLUDES(mMainThreadLock);
+
static constexpr auto CONTINUOUS_TRACING_BUFFER_SIZE = 512 * 1024;
- static constexpr auto ACTIVE_TRACING_BUFFER_SIZE = 100 * 1024 * 1024;
+ static constexpr auto LEGACY_ACTIVE_TRACING_BUFFER_SIZE = 100 * 1024 * 1024;
// version 1 - switching to support new frontend
static constexpr auto TRACING_VERSION = 1;
@@ -85,14 +163,15 @@
}
mutable std::mutex mTraceLock;
- TransactionRingBuffer<proto::TransactionTraceFile, proto::TransactionTraceEntry> mBuffer
+ TransactionRingBuffer<perfetto::protos::TransactionTraceFile,
+ perfetto::protos::TransactionTraceEntry>
+ mBuffer GUARDED_BY(mTraceLock);
+ std::unordered_map<uint64_t, perfetto::protos::TransactionState> mQueuedTransactions
GUARDED_BY(mTraceLock);
- size_t mBufferSizeInBytes GUARDED_BY(mTraceLock) = CONTINUOUS_TRACING_BUFFER_SIZE;
- std::unordered_map<uint64_t, proto::TransactionState> mQueuedTransactions
- GUARDED_BY(mTraceLock);
- LocklessStack<proto::TransactionState> mTransactionQueue;
+ LocklessStack<perfetto::protos::TransactionState> mTransactionQueue;
nsecs_t mStartingTimestamp GUARDED_BY(mTraceLock);
- std::unordered_map<int, proto::LayerCreationArgs> mCreatedLayers GUARDED_BY(mTraceLock);
+ std::unordered_map<int, perfetto::protos::LayerCreationArgs> mCreatedLayers
+ GUARDED_BY(mTraceLock);
std::map<uint32_t /* layerId */, TracingLayerState> mStartingStates GUARDED_BY(mTraceLock);
frontend::DisplayInfos mStartingDisplayInfos GUARDED_BY(mTraceLock);
@@ -122,17 +201,17 @@
std::vector<uint32_t /* layerId */> mPendingDestroyedLayers; // only accessed by main thread
int64_t mLastUpdatedVsyncId = -1;
- proto::TransactionTraceFile createTraceFileProto() const;
+ void writeRingBufferToPerfetto(TransactionTracing::Mode mode);
+ perfetto::protos::TransactionTraceFile createTraceFileProto() const;
void loop();
void addEntry(const std::vector<CommittedUpdates>& committedTransactions,
const std::vector<uint32_t>& removedLayers) EXCLUDES(mTraceLock);
int32_t getLayerIdLocked(const sp<IBinder>& layerHandle) REQUIRES(mTraceLock);
void tryPushToTracingThread() EXCLUDES(mMainThreadLock);
- void addStartingStateToProtoLocked(proto::TransactionTraceFile& proto) REQUIRES(mTraceLock);
- void updateStartingStateLocked(const proto::TransactionTraceEntry& entry) REQUIRES(mTraceLock);
- // TEST
- // Return buffer contents as trace file proto
- proto::TransactionTraceFile writeToProto() EXCLUDES(mMainThreadLock);
+ std::optional<perfetto::protos::TransactionTraceEntry> createStartingStateProtoLocked()
+ REQUIRES(mTraceLock);
+ void updateStartingStateLocked(const perfetto::protos::TransactionTraceEntry& entry)
+ REQUIRES(mTraceLock);
};
class TransactionTraceWriter : public Singleton<TransactionTraceWriter> {
diff --git a/services/surfaceflinger/Tracing/tools/Android.bp b/services/surfaceflinger/Tracing/tools/Android.bp
index b6435a8..2ff09c3 100644
--- a/services/surfaceflinger/Tracing/tools/Android.bp
+++ b/services/surfaceflinger/Tracing/tools/Android.bp
@@ -31,7 +31,6 @@
srcs: [
":libsurfaceflinger_sources",
":libsurfaceflinger_mock_sources",
- ":layertracegenerator_sources",
"main.cpp",
],
static_libs: [
@@ -41,15 +40,3 @@
"libsurfaceflinger_mocks_headers",
],
}
-
-filegroup {
- name: "layertracegenerator_sources",
- srcs: [
- "LayerTraceGenerator.cpp",
- ],
-}
-
-cc_library_headers {
- name: "layertracegenerator_headers",
- export_include_dirs: ["."],
-}
diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
index 321b8ba..62c362e 100644
--- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
+++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
@@ -40,8 +40,10 @@
namespace android {
using namespace ftl::flag_operators;
-bool LayerTraceGenerator::generate(const proto::TransactionTraceFile& traceFile,
- const char* outputLayersTracePath, bool onlyLastEntry) {
+bool LayerTraceGenerator::generate(const perfetto::protos::TransactionTraceFile& traceFile,
+ std::uint32_t traceFlags,
+ std::optional<std::reference_wrapper<std::ostream>> outStream,
+ bool onlyLastEntry) {
if (traceFile.entry_size() == 0) {
ALOGD("Trace file is empty");
return false;
@@ -49,6 +51,11 @@
TransactionProtoParser parser(std::make_unique<TransactionProtoParser::FlingerDataMapper>());
+ LayerTracing layerTracing;
+ if (outStream) {
+ layerTracing.setOutputStream(outStream->get());
+ }
+
// frontend
frontend::LayerLifecycleManager lifecycleManager;
frontend::LayerHierarchyBuilder hierarchyBuilder{{}};
@@ -60,18 +67,10 @@
property_get("ro.surface_flinger.supports_background_blur", value, "0");
bool supportsBlur = atoi(value);
- LayerTracing layerTracing;
- layerTracing.setTraceFlags(LayerTracing::TRACE_INPUT | LayerTracing::TRACE_BUFFERS);
- // 10MB buffer size (large enough to hold a single entry)
- layerTracing.setBufferSize(10 * 1024 * 1024);
- layerTracing.enable();
- layerTracing.writeToFile(outputLayersTracePath);
- std::ofstream out(outputLayersTracePath, std::ios::binary | std::ios::app);
-
ALOGD("Generating %d transactions...", traceFile.entry_size());
for (int i = 0; i < traceFile.entry_size(); i++) {
// parse proto
- proto::TransactionTraceEntry entry = traceFile.entry(i);
+ perfetto::protos::TransactionTraceEntry entry = traceFile.entry(i);
ALOGV(" Entry %04d/%04d for time=%" PRId64 " vsyncid=%" PRId64
" layers +%d -%d handles -%d transactions=%d",
i, traceFile.entry_size(), entry.elapsed_realtime_nanos(), entry.vsync_id(),
@@ -154,19 +153,26 @@
lifecycleManager.commitChanges();
- LayersProto layersProto = LayerProtoFromSnapshotGenerator(snapshotBuilder, displayInfos, {},
- layerTracing.getFlags())
- .generate(hierarchyBuilder.getHierarchy());
+ auto layersProto =
+ LayerProtoFromSnapshotGenerator(snapshotBuilder, displayInfos, {}, traceFlags)
+ .generate(hierarchyBuilder.getHierarchy());
auto displayProtos = LayerProtoHelper::writeDisplayInfoToProto(displayInfos);
if (!onlyLastEntry || (i == traceFile.entry_size() - 1)) {
- layerTracing.notify(visibleRegionsDirty, entry.elapsed_realtime_nanos(),
- entry.vsync_id(), &layersProto, {}, &displayProtos);
- layerTracing.appendToStream(out);
+ perfetto::protos::LayersSnapshotProto snapshotProto{};
+ snapshotProto.set_vsync_id(entry.vsync_id());
+ snapshotProto.set_elapsed_realtime_nanos(entry.elapsed_realtime_nanos());
+ snapshotProto.set_where(visibleRegionsDirty ? "visibleRegionsDirty" : "bufferLatched");
+ *snapshotProto.mutable_layers() = std::move(layersProto);
+ if ((traceFlags & LayerTracing::TRACE_COMPOSITION) == 0) {
+ snapshotProto.set_excludes_composition_state(true);
+ }
+ *snapshotProto.mutable_displays() = std::move(displayProtos);
+
+ layerTracing.addProtoSnapshotToOstream(std::move(snapshotProto),
+ LayerTracing::Mode::MODE_GENERATED);
}
}
- layerTracing.disable("", /*writeToFile=*/false);
- out.close();
- ALOGD("End of generating trace file. File written to %s", outputLayersTracePath);
+ ALOGD("End of generating trace file");
return true;
}
diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h
index e41d1e6..2bb6f51 100644
--- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h
+++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.h
@@ -18,10 +18,19 @@
#include <Tracing/TransactionTracing.h>
+#include <functional>
+#include <optional>
+#include <ostream>
+#include <string>
+
namespace android {
+
+class LayerTracing;
+
class LayerTraceGenerator {
public:
- bool generate(const proto::TransactionTraceFile&, const char* outputLayersTracePath,
- bool onlyLastEntry);
+ bool generate(const perfetto::protos::TransactionTraceFile&, std::uint32_t traceFlags,
+ std::optional<std::reference_wrapper<std::ostream>> outStream = std::nullopt,
+ bool onlyLastEntry = false);
};
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/Tracing/tools/main.cpp b/services/surfaceflinger/Tracing/tools/main.cpp
index 5ca87e4..a8ac36a 100644
--- a/services/surfaceflinger/Tracing/tools/main.cpp
+++ b/services/surfaceflinger/Tracing/tools/main.cpp
@@ -21,6 +21,7 @@
#include <iostream>
#include <string>
+#include <Tracing/LayerTracing.h>
#include "LayerTraceGenerator.h"
using namespace android;
@@ -41,25 +42,28 @@
return -1;
}
- proto::TransactionTraceFile transactionTraceFile;
+ perfetto::protos::TransactionTraceFile transactionTraceFile;
if (!transactionTraceFile.ParseFromIstream(&input)) {
std::cout << "Error: Failed to parse " << transactionTracePath;
return -1;
}
- const char* outputLayersTracePath =
- (argc >= 3) ? argv[2] : "/data/misc/wmtrace/layers_trace.winscope";
+ const auto* outputLayersTracePath =
+ (argc == 3) ? argv[2] : "/data/misc/wmtrace/layers_trace.winscope";
+ auto outStream = std::ofstream{outputLayersTracePath, std::ios::binary | std::ios::app};
const bool generateLastEntryOnly =
argc >= 4 && std::string_view(argv[3]) == "--last-entry-only";
+ auto traceFlags = LayerTracing::Flag::TRACE_INPUT | LayerTracing::Flag::TRACE_BUFFERS;
+
ALOGD("Generating %s...", outputLayersTracePath);
std::cout << "Generating " << outputLayersTracePath << "\n";
- if (!LayerTraceGenerator().generate(transactionTraceFile, outputLayersTracePath,
+ if (!LayerTraceGenerator().generate(transactionTraceFile, traceFlags, outStream,
generateLastEntryOnly)) {
std::cout << "Error: Failed to generate layers trace " << outputLayersTracePath;
return -1;
}
return 0;
-}
\ No newline at end of file
+}
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index 8a050fd..437fd35 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -455,7 +455,8 @@
result = fdp->ConsumeRandomLengthString().c_str();
mFlinger->dumpRawDisplayIdentificationData(dumpArgs, result);
- LayersProto layersProto = mFlinger->dumpDrawingStateProto(fdp->ConsumeIntegral<uint32_t>());
+ perfetto::protos::LayersProto layersProto =
+ mFlinger->dumpDrawingStateProto(fdp->ConsumeIntegral<uint32_t>());
mFlinger->dumpOffscreenLayersProto(layersProto);
mFlinger->dumpDisplayProto();
diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp
index 7287dd0..a4dc8a0 100644
--- a/services/surfaceflinger/layerproto/Android.bp
+++ b/services/surfaceflinger/layerproto/Android.bp
@@ -13,7 +13,20 @@
srcs: [
"LayerProtoParser.cpp",
- "*.proto",
+ ],
+
+ static_libs: [
+ "libperfetto_client_experimental",
+ ],
+
+ whole_static_libs: [
+ // TODO(b/169779783): move into "static_libs" when the soong issue is fixed
+ "perfetto_trace_protos",
+ ],
+
+ export_static_lib_headers: [
+ "libperfetto_client_experimental",
+ "perfetto_trace_protos",
],
shared_libs: [
@@ -24,10 +37,6 @@
"libbase",
],
- proto: {
- export_proto_headers: true,
- },
-
cppflags: [
"-Werror",
"-Wno-unused-parameter",
@@ -42,22 +51,3 @@
"-Wno-undef",
],
}
-
-java_library_static {
- name: "layersprotoslite",
- host_supported: true,
- proto: {
- type: "lite",
- include_dirs: ["external/protobuf/src"],
- },
- srcs: ["*.proto"],
- sdk_version: "core_platform",
- target: {
- android: {
- jarjar_rules: "jarjar-rules.txt",
- },
- host: {
- static_libs: ["libprotobuf-java-lite"],
- },
- },
-}
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
index 854084e..c3d0a40 100644
--- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -37,7 +37,8 @@
return lhs->id < rhs->id;
}
-LayerProtoParser::LayerTree LayerProtoParser::generateLayerTree(const LayersProto& layersProto) {
+LayerProtoParser::LayerTree LayerProtoParser::generateLayerTree(
+ const perfetto::protos::LayersProto& layersProto) {
LayerTree layerTree;
layerTree.allLayers = generateLayerList(layersProto);
@@ -53,7 +54,7 @@
}
std::vector<LayerProtoParser::Layer> LayerProtoParser::generateLayerList(
- const LayersProto& layersProto) {
+ const perfetto::protos::LayersProto& layersProto) {
std::vector<Layer> layerList;
std::unordered_map<int32_t, Layer*> layerMap;
@@ -74,7 +75,8 @@
return layerList;
}
-LayerProtoParser::Layer LayerProtoParser::generateLayer(const LayerProto& layerProto) {
+LayerProtoParser::Layer LayerProtoParser::generateLayer(
+ const perfetto::protos::LayerProto& layerProto) {
Layer layer;
layer.id = layerProto.id();
layer.name = layerProto.name();
@@ -120,17 +122,19 @@
return layer;
}
-LayerProtoParser::Region LayerProtoParser::generateRegion(const RegionProto& regionProto) {
+LayerProtoParser::Region LayerProtoParser::generateRegion(
+ const perfetto::protos::RegionProto& regionProto) {
LayerProtoParser::Region region;
for (int i = 0; i < regionProto.rect_size(); i++) {
- const RectProto& rectProto = regionProto.rect(i);
+ const perfetto::protos::RectProto& rectProto = regionProto.rect(i);
region.rects.push_back(generateRect(rectProto));
}
return region;
}
-LayerProtoParser::Rect LayerProtoParser::generateRect(const RectProto& rectProto) {
+LayerProtoParser::Rect LayerProtoParser::generateRect(
+ const perfetto::protos::RectProto& rectProto) {
LayerProtoParser::Rect rect;
rect.left = rectProto.left();
rect.top = rectProto.top();
@@ -140,7 +144,8 @@
return rect;
}
-LayerProtoParser::FloatRect LayerProtoParser::generateFloatRect(const FloatRectProto& rectProto) {
+LayerProtoParser::FloatRect LayerProtoParser::generateFloatRect(
+ const perfetto::protos::FloatRectProto& rectProto) {
LayerProtoParser::FloatRect rect;
rect.left = rectProto.left();
rect.top = rectProto.top();
@@ -151,7 +156,7 @@
}
LayerProtoParser::Transform LayerProtoParser::generateTransform(
- const TransformProto& transformProto) {
+ const perfetto::protos::TransformProto& transformProto) {
LayerProtoParser::Transform transform;
transform.dsdx = transformProto.dsdx();
transform.dtdx = transformProto.dtdx();
@@ -162,7 +167,7 @@
}
LayerProtoParser::ActiveBuffer LayerProtoParser::generateActiveBuffer(
- const ActiveBufferProto& activeBufferProto) {
+ const perfetto::protos::ActiveBufferProto& activeBufferProto) {
LayerProtoParser::ActiveBuffer activeBuffer;
activeBuffer.width = activeBufferProto.width();
activeBuffer.height = activeBufferProto.height();
@@ -172,7 +177,7 @@
return activeBuffer;
}
-void LayerProtoParser::updateChildrenAndRelative(const LayerProto& layerProto,
+void LayerProtoParser::updateChildrenAndRelative(const perfetto::protos::LayerProto& layerProto,
std::unordered_map<int32_t, Layer*>& layerMap) {
auto currLayer = layerMap[layerProto.id()];
@@ -188,13 +193,13 @@
}
}
- if (layerProto.parent() != -1) {
+ if (layerProto.has_parent()) {
if (layerMap.count(layerProto.parent()) > 0) {
currLayer->parent = layerMap[layerProto.parent()];
}
}
- if (layerProto.z_order_relative_of() != -1) {
+ if (layerProto.has_z_order_relative_of()) {
if (layerMap.count(layerProto.z_order_relative_of()) > 0) {
currLayer->zOrderRelativeOf = layerMap[layerProto.z_order_relative_of()];
}
diff --git a/services/surfaceflinger/layerproto/common.proto b/services/surfaceflinger/layerproto/common.proto
deleted file mode 100644
index 5e20d4d..0000000
--- a/services/surfaceflinger/layerproto/common.proto
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- */
-
-syntax = "proto3";
-option optimize_for = LITE_RUNTIME;
-package android.surfaceflinger;
-
-message RegionProto {
- reserved 1; // Previously: uint64 id
- repeated RectProto rect = 2;
-}
-
-message RectProto {
- int32 left = 1;
- int32 top = 2;
- int32 right = 3;
- int32 bottom = 4;
-}
-
-message SizeProto {
- int32 w = 1;
- int32 h = 2;
-}
-
-message TransformProto {
- float dsdx = 1;
- float dtdx = 2;
- float dsdy = 3;
- float dtdy = 4;
- int32 type = 5;
-}
-
-message ColorProto {
- float r = 1;
- float g = 2;
- float b = 3;
- float a = 4;
-}
-
-message InputWindowInfoProto {
- uint32 layout_params_flags = 1;
- int32 layout_params_type = 2;
- RectProto frame = 3;
- RegionProto touchable_region = 4;
-
- int32 surface_inset = 5;
- bool visible = 6;
- bool can_receive_keys = 7 [deprecated = true];
- bool focusable = 8;
- bool has_wallpaper = 9;
-
- float global_scale_factor = 10;
- float window_x_scale = 11 [deprecated = true];
- float window_y_scale = 12 [deprecated = true];
-
- int32 crop_layer_id = 13;
- bool replace_touchable_region_with_crop = 14;
- RectProto touchable_region_crop = 15;
- TransformProto transform = 16;
- uint32 input_config = 17;
-}
-
-message BlurRegion {
- uint32 blur_radius = 1;
- uint32 corner_radius_tl = 2;
- uint32 corner_radius_tr = 3;
- uint32 corner_radius_bl = 4;
- float corner_radius_br = 5;
- float alpha = 6;
- int32 left = 7;
- int32 top = 8;
- int32 right = 9;
- int32 bottom = 10;
-}
-
-message ColorTransformProto {
- // This will be a 4x4 matrix of float values
- repeated float val = 1;
-}
diff --git a/services/surfaceflinger/layerproto/display.proto b/services/surfaceflinger/layerproto/display.proto
deleted file mode 100644
index 64de775..0000000
--- a/services/surfaceflinger/layerproto/display.proto
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- */
-
-syntax = "proto3";
-option optimize_for = LITE_RUNTIME;
-
-import "frameworks/native/services/surfaceflinger/layerproto/common.proto";
-
-package android.surfaceflinger;
-
-message DisplayProto {
- uint64 id = 1;
-
- string name = 2;
-
- uint32 layer_stack = 3;
-
- SizeProto size = 4;
-
- RectProto layer_stack_space_rect = 5;
-
- TransformProto transform = 6;
-
- bool is_virtual = 7;
-
- double dpi_x = 8;
-
- double dpi_y = 9;
-}
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h
index f560562..4a2ef3d 100644
--- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoHeader.h
@@ -14,11 +14,14 @@
* limitations under the License.
*/
+#pragma once
+
// 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>
-#include <layerstrace.pb.h>
+#include <perfetto/config/android/surfaceflinger_layers_config.pbzero.h>
+#include <perfetto/trace/android/surfaceflinger_layers.pb.h>
+#include <perfetto/trace/android/surfaceflinger_layers.pbzero.h>
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
index cdc2706..79c3982 100644
--- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -131,19 +131,22 @@
std::vector<Layer*> topLevelLayers;
};
- static LayerTree generateLayerTree(const LayersProto& layersProto);
+ static LayerTree generateLayerTree(const perfetto::protos::LayersProto& layersProto);
static std::string layerTreeToString(const LayerTree& layerTree);
private:
- static std::vector<Layer> generateLayerList(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::FloatRect generateFloatRect(const FloatRectProto& rectProto);
- static LayerProtoParser::Transform generateTransform(const TransformProto& transformProto);
+ static std::vector<Layer> generateLayerList(const perfetto::protos::LayersProto& layersProto);
+ static LayerProtoParser::Layer generateLayer(const perfetto::protos::LayerProto& layerProto);
+ static LayerProtoParser::Region generateRegion(
+ const perfetto::protos::RegionProto& regionProto);
+ static LayerProtoParser::Rect generateRect(const perfetto::protos::RectProto& rectProto);
+ static LayerProtoParser::FloatRect generateFloatRect(
+ const perfetto::protos::FloatRectProto& rectProto);
+ static LayerProtoParser::Transform generateTransform(
+ const perfetto::protos::TransformProto& transformProto);
static LayerProtoParser::ActiveBuffer generateActiveBuffer(
- const ActiveBufferProto& activeBufferProto);
- static void updateChildrenAndRelative(const LayerProto& layerProto,
+ const perfetto::protos::ActiveBufferProto& activeBufferProto);
+ static void updateChildrenAndRelative(const perfetto::protos::LayerProto& layerProto,
std::unordered_map<int32_t, Layer*>& layerMap);
static std::string layerToString(const LayerProtoParser::Layer* layer);
diff --git a/services/surfaceflinger/layerproto/include/layerproto/TransactionProto.h b/services/surfaceflinger/layerproto/include/layerproto/TransactionProto.h
index 3e9ca52..ea80ad8 100644
--- a/services/surfaceflinger/layerproto/include/layerproto/TransactionProto.h
+++ b/services/surfaceflinger/layerproto/include/layerproto/TransactionProto.h
@@ -14,7 +14,11 @@
* limitations under the License.
*/
+#pragma once
+
// disable the warnings emitted from the protobuf headers. This file should be included instead of
// directly including the generated header file
#pragma GCC system_header
-#include <transactions.pb.h>
+#include <perfetto/config/android/surfaceflinger_transactions_config.pbzero.h>
+#include <perfetto/trace/android/surfaceflinger_transactions.pb.h>
+#include <perfetto/trace/android/surfaceflinger_transactions.pbzero.h>
diff --git a/services/surfaceflinger/layerproto/jarjar-rules.txt b/services/surfaceflinger/layerproto/jarjar-rules.txt
deleted file mode 100644
index 40043a8..0000000
--- a/services/surfaceflinger/layerproto/jarjar-rules.txt
+++ /dev/null
@@ -1 +0,0 @@
-rule com.google.protobuf.nano.** com.android.framework.protobuf.nano.@1
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
deleted file mode 100644
index e9add2e..0000000
--- a/services/surfaceflinger/layerproto/layers.proto
+++ /dev/null
@@ -1,171 +0,0 @@
-// Definitions for SurfaceFlinger layers.
-
-syntax = "proto3";
-option optimize_for = LITE_RUNTIME;
-
-import "frameworks/native/services/surfaceflinger/layerproto/common.proto";
-
-package android.surfaceflinger;
-
-// Contains a list of all layers.
-message LayersProto {
- repeated LayerProto layers = 1;
-}
-
-// Must match definition in the IComposerClient HAL
-enum HwcCompositionType {
- // Invalid composition type
- INVALID = 0;
- // Layer was composited by the client into the client target buffer
- CLIENT = 1;
- // Layer was composited by the device through hardware overlays
- DEVICE = 2;
- // Layer was composited by the device using a color
- SOLID_COLOR = 3;
- // Similar to DEVICE, but the layer position may have been asynchronously set
- // through setCursorPosition
- CURSOR = 4;
- // Layer was composited by the device via a sideband stream.
- SIDEBAND = 5;
-}
-
-// Information about each layer.
-message LayerProto {
- // unique id per layer.
- int32 id = 1;
- // unique name per layer.
- 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
- string type = 5;
- RegionProto transparent_region = 6;
- RegionProto visible_region = 7;
- RegionProto damage_region = 8;
- 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.
- int32 z = 10;
- // The layer's position on the display.
- PositionProto position = 11;
- // The layer's requested position.
- PositionProto requested_position = 12;
- // The layer's size.
- SizeProto size = 13;
- // The layer's crop in it's own bounds.
- RectProto crop = 14;
- // The layer's crop in it's parent's bounds.
- RectProto final_crop = 15 [deprecated=true];
- bool is_opaque = 16;
- bool invalidate = 17;
- string dataspace = 18;
- string pixel_format = 19;
- // The layer's actual color.
- ColorProto color = 20;
- // The layer's requested color.
- ColorProto requested_color = 21;
- // Can be any combination of
- // hidden = 0x01
- // opaque = 0x02,
- // secure = 0x80,
- uint32 flags = 22;
- // The layer's actual transform
- TransformProto transform = 23;
- // The layer's requested transform.
- TransformProto requested_transform = 24;
- // The parent layer. This value can be null if there is no parent.
- int32 parent = 25;
- // The layer that this layer has a z order relative to. This value can be null.
- int32 z_order_relative_of = 26;
- // This value can be null if there's nothing to draw.
- ActiveBufferProto active_buffer = 27;
- // The number of frames available.
- int32 queued_frames = 28;
- bool refresh_pending = 29;
- // The layer's composer backend destination frame
- RectProto hwc_frame = 30;
- // The layer's composer backend source crop
- FloatRectProto hwc_crop = 31;
- // The layer's composer backend transform
- int32 hwc_transform = 32;
- int32 window_type = 33 [deprecated=true];
- int32 app_id = 34 [deprecated=true];
- // The layer's composition type
- HwcCompositionType hwc_composition_type = 35;
- // If it's a buffer layer, indicate if the content is protected
- bool is_protected = 36;
- // Current frame number being rendered.
- uint64 curr_frame = 37;
- // A list of barriers that the layer is waiting to update state.
- repeated BarrierLayerProto barrier_layer = 38;
- // If active_buffer is not null, record its transform.
- TransformProto buffer_transform = 39;
- int32 effective_scaling_mode = 40;
- // Layer's corner radius.
- float corner_radius = 41;
- // Metadata map. May be empty.
- map<int32, bytes> metadata = 42;
-
- TransformProto effective_transform = 43;
- FloatRectProto source_bounds = 44;
- FloatRectProto bounds = 45;
- FloatRectProto screen_bounds = 46;
-
- InputWindowInfoProto input_window_info = 47;
-
- // Crop used to draw the rounded corner.
- FloatRectProto corner_radius_crop = 48;
-
- // length of the shadow to draw around the layer, it may be set on the
- // layer or set by a parent layer.
- float shadow_radius = 49;
- ColorTransformProto color_transform = 50;
-
- bool is_relative_of = 51;
- // Layer's background blur radius in pixels.
- int32 background_blur_radius = 52;
-
- uint32 owner_uid = 53;
-
- // Regions of a layer, where blur should be applied.
- repeated BlurRegion blur_regions = 54;
-
- bool is_trusted_overlay = 55;
-
- // Corner radius explicitly set on layer rather than inherited
- float requested_corner_radius = 56;
-
- RectProto destination_frame = 57;
-
- uint32 original_id = 58;
-}
-
-message PositionProto {
- float x = 1;
- float y = 2;
-}
-
-message FloatRectProto {
- float left = 1;
- float top = 2;
- float right = 3;
- float bottom = 4;
-}
-
-message ActiveBufferProto {
- uint32 width = 1;
- uint32 height = 2;
- uint32 stride = 3;
- int32 format = 4;
- uint64 usage = 5;
-}
-
-message BarrierLayerProto {
- // layer id the barrier is waiting on.
- int32 id = 1;
- // frame number the barrier is waiting on.
- uint64 frame_number = 2;
-}
-
diff --git a/services/surfaceflinger/layerproto/layerstrace.proto b/services/surfaceflinger/layerproto/layerstrace.proto
deleted file mode 100644
index 804a499..0000000
--- a/services/surfaceflinger/layerproto/layerstrace.proto
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.
- */
-
-syntax = "proto2";
-option optimize_for = LITE_RUNTIME;
-
-import "frameworks/native/services/surfaceflinger/layerproto/layers.proto";
-import "frameworks/native/services/surfaceflinger/layerproto/display.proto";
-
-package android.surfaceflinger;
-
-/* represents a file full of surface flinger trace entries.
- Encoded, it should start with 0x4c 0x59 0x52 0x54 0x52 0x41 0x43 0x45 (.LYRTRACE), such
- that they can be easily identified. */
-message LayersTraceFileProto {
-
- /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L
- (this is needed because enums have to be 32 bits and there's no nice way to put 64bit
- constants into .proto files. */
- enum MagicNumber {
- INVALID = 0;
- MAGIC_NUMBER_L = 0x5452594c; /* LYRT (little-endian ASCII) */
- MAGIC_NUMBER_H = 0x45434152; /* RACE (little-endian ASCII) */
- }
-
- optional fixed64 magic_number = 1; /* Must be the first field, set to value in MagicNumber */
- repeated LayersTraceProto entry = 2;
-
- /* offset between real-time clock and elapsed time clock in nanoseconds.
- Calculated as: systemTime(SYSTEM_TIME_REALTIME) - systemTime(SYSTEM_TIME_MONOTONIC) */
- optional fixed64 real_to_elapsed_time_offset_nanos = 3;
-}
-
-/* one layers trace entry. */
-message LayersTraceProto {
- /* required: elapsed realtime in nanos since boot of when this entry was logged */
- optional sfixed64 elapsed_realtime_nanos = 1;
-
- /* where the trace originated */
- optional string where = 2;
-
- optional LayersProto layers = 3;
-
- // Blob for the current HWC information for all layers, reported by dumpsys.
- optional string hwc_blob = 4;
-
- /* Includes state sent during composition like visible region and composition type. */
- optional bool excludes_composition_state = 5;
-
- /* Number of missed entries since the last entry was recorded. */
- optional uint32 missed_entries = 6;
-
- repeated DisplayProto displays = 7;
-
- optional int64 vsync_id = 8;
-}
diff --git a/services/surfaceflinger/layerproto/transactions.proto b/services/surfaceflinger/layerproto/transactions.proto
deleted file mode 100644
index d03afa0..0000000
--- a/services/surfaceflinger/layerproto/transactions.proto
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright (C) 2021 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.
- */
-
-syntax = "proto3";
-option optimize_for = LITE_RUNTIME;
-
-import "frameworks/native/services/surfaceflinger/layerproto/common.proto";
-
-package android.surfaceflinger.proto;
-
-/* Represents a file full of surface flinger transactions.
- Encoded, it should start with 0x54 0x4E 0x58 0x54 0x52 0x41 0x43 0x45 (.TNXTRACE), such
- that they can be easily identified. */
-message TransactionTraceFile {
- /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L
- (this is needed because enums have to be 32 bits and there's no nice way to put 64bit
- constants into .proto files. */
- enum MagicNumber {
- INVALID = 0;
- MAGIC_NUMBER_L = 0x54584E54; /* TNXT (little-endian ASCII) */
- MAGIC_NUMBER_H = 0x45434152; /* RACE (little-endian ASCII) */
- }
-
- fixed64 magic_number = 1; /* Must be the first field, set to value in MagicNumber */
- repeated TransactionTraceEntry entry = 2;
-
- /* offset between real-time clock and elapsed time clock in nanoseconds.
- Calculated as: systemTime(SYSTEM_TIME_REALTIME) - systemTime(SYSTEM_TIME_MONOTONIC) */
- fixed64 real_to_elapsed_time_offset_nanos = 3;
- uint32 version = 4;
-}
-
-message TransactionTraceEntry {
- int64 elapsed_realtime_nanos = 1;
- int64 vsync_id = 2;
- repeated TransactionState transactions = 3;
- repeated LayerCreationArgs added_layers = 4;
- repeated uint32 destroyed_layers = 5;
- repeated DisplayState added_displays = 6;
- repeated int32 removed_displays = 7;
- repeated uint32 destroyed_layer_handles = 8;
- bool displays_changed = 9;
- repeated DisplayInfo displays = 10;
-}
-
-message DisplayInfo {
- uint32 layer_stack = 1;
- int32 display_id = 2;
- int32 logical_width = 3;
- int32 logical_height = 4;
- Transform transform_inverse = 5;
- Transform transform = 6;
- bool receives_input = 7;
- bool is_secure = 8;
- bool is_primary = 9;
- bool is_virtual = 10;
- int32 rotation_flags = 11;
- int32 transform_hint = 12;
-
-}
-
-message LayerCreationArgs {
- uint32 layer_id = 1;
- string name = 2;
- uint32 flags = 3;
- uint32 parent_id = 4;
- uint32 mirror_from_id = 5;
- bool add_to_root = 6;
- uint32 layer_stack_to_mirror = 7;
-}
-
-message Transform {
- float dsdx = 1;
- float dtdx = 2;
- float dtdy = 3;
- float dsdy = 4;
- float tx = 5;
- float ty = 6;
-}
-
-message TransactionState {
- int32 pid = 1;
- int32 uid = 2;
- int64 vsync_id = 3;
- int32 input_event_id = 4;
- int64 post_time = 5;
- uint64 transaction_id = 6;
- repeated LayerState layer_changes = 7;
- repeated DisplayState display_changes = 8;
- repeated uint64 merged_transaction_ids = 9;
-}
-
-// Keep insync with layer_state_t
-message LayerState {
- uint32 layer_id = 1;
- // Changes are split into ChangesLsb and ChangesMsb. First 32 bits are in ChangesLsb
- // and the next 32 bits are in ChangesMsb. This is needed because enums have to be
- // 32 bits and there's no nice way to put 64bit constants into .proto files.
- enum ChangesLsb {
- eChangesLsbNone = 0;
- ePositionChanged = 0x00000001;
- eLayerChanged = 0x00000002;
- // unused = 0x00000004;
- eAlphaChanged = 0x00000008;
-
- eMatrixChanged = 0x00000010;
- eTransparentRegionChanged = 0x00000020;
- eFlagsChanged = 0x00000040;
- eLayerStackChanged = 0x00000080;
-
- eReleaseBufferListenerChanged = 0x00000400;
- eShadowRadiusChanged = 0x00000800;
-
- eBufferCropChanged = 0x00002000;
- eRelativeLayerChanged = 0x00004000;
- eReparent = 0x00008000;
-
- eColorChanged = 0x00010000;
- eBufferTransformChanged = 0x00040000;
- eTransformToDisplayInverseChanged = 0x00080000;
-
- eCropChanged = 0x00100000;
- eBufferChanged = 0x00200000;
- eAcquireFenceChanged = 0x00400000;
- eDataspaceChanged = 0x00800000;
-
- eHdrMetadataChanged = 0x01000000;
- eSurfaceDamageRegionChanged = 0x02000000;
- eApiChanged = 0x04000000;
- eSidebandStreamChanged = 0x08000000;
-
- eColorTransformChanged = 0x10000000;
- eHasListenerCallbacksChanged = 0x20000000;
- eInputInfoChanged = 0x40000000;
- eCornerRadiusChanged = -2147483648; // 0x80000000; (proto stores enums as signed int)
- };
- enum ChangesMsb {
- eChangesMsbNone = 0;
- eDestinationFrameChanged = 0x1;
- eCachedBufferChanged = 0x2;
- eBackgroundColorChanged = 0x4;
- eMetadataChanged = 0x8;
- eColorSpaceAgnosticChanged = 0x10;
- eFrameRateSelectionPriority = 0x20;
- eFrameRateChanged = 0x40;
- eBackgroundBlurRadiusChanged = 0x80;
- eProducerDisconnect = 0x100;
- eFixedTransformHintChanged = 0x200;
- eFrameNumberChanged = 0x400;
- eBlurRegionsChanged = 0x800;
- eAutoRefreshChanged = 0x1000;
- eStretchChanged = 0x2000;
- eTrustedOverlayChanged = 0x4000;
- eDropInputModeChanged = 0x8000;
- };
- uint64 what = 2;
- float x = 3;
- float y = 4;
- int32 z = 5;
- uint32 w = 6;
- uint32 h = 7;
- uint32 layer_stack = 8;
-
- enum Flags {
- eFlagsNone = 0;
- eLayerHidden = 0x01;
- eLayerOpaque = 0x02;
- eLayerSkipScreenshot = 0x40;
- eLayerSecure = 0x80;
- eEnableBackpressure = 0x100;
- eLayerIsDisplayDecoration = 0x200;
- };
- uint32 flags = 9;
- uint32 mask = 10;
-
- message Matrix22 {
- float dsdx = 1;
- float dtdx = 2;
- float dtdy = 3;
- float dsdy = 4;
- };
- Matrix22 matrix = 11;
- float corner_radius = 12;
- uint32 background_blur_radius = 13;
- uint32 parent_id = 14;
- uint32 relative_parent_id = 15;
-
- float alpha = 16;
- message Color3 {
- float r = 1;
- float g = 2;
- float b = 3;
- }
- Color3 color = 17;
- RegionProto transparent_region = 18;
- uint32 transform = 19;
- bool transform_to_display_inverse = 20;
- RectProto crop = 21;
-
- message BufferData {
- uint64 buffer_id = 1;
- uint32 width = 2;
- uint32 height = 3;
- uint64 frame_number = 4;
-
- enum BufferDataChange {
- BufferDataChangeNone = 0;
- fenceChanged = 0x01;
- frameNumberChanged = 0x02;
- cachedBufferChanged = 0x04;
- }
- uint32 flags = 5;
- uint64 cached_buffer_id = 6;
-
- enum PixelFormat {
- PIXEL_FORMAT_UNKNOWN = 0;
- PIXEL_FORMAT_CUSTOM = -4;
- PIXEL_FORMAT_TRANSLUCENT = -3;
- PIXEL_FORMAT_TRANSPARENT = -2;
- PIXEL_FORMAT_OPAQUE = -1;
- PIXEL_FORMAT_RGBA_8888 = 1;
- PIXEL_FORMAT_RGBX_8888 = 2;
- PIXEL_FORMAT_RGB_888 = 3;
- PIXEL_FORMAT_RGB_565 = 4;
- PIXEL_FORMAT_BGRA_8888 = 5;
- PIXEL_FORMAT_RGBA_5551 = 6;
- PIXEL_FORMAT_RGBA_4444 = 7;
- PIXEL_FORMAT_RGBA_FP16 = 22;
- PIXEL_FORMAT_RGBA_1010102 = 43;
- PIXEL_FORMAT_R_8 = 0x38;
- }
- PixelFormat pixel_format = 7;
- uint64 usage = 8;
- }
- BufferData buffer_data = 22;
- int32 api = 23;
- bool has_sideband_stream = 24;
- ColorTransformProto color_transform = 25;
- repeated BlurRegion blur_regions = 26;
-
- message WindowInfo {
- uint32 layout_params_flags = 1;
- int32 layout_params_type = 2;
- RegionProto touchable_region = 3;
- int32 surface_inset = 4;
- bool focusable = 5; // unused
- bool has_wallpaper = 6; // unused
- float global_scale_factor = 7;
- uint32 crop_layer_id = 8;
- bool replace_touchable_region_with_crop = 9;
- RectProto touchable_region_crop = 10;
- Transform transform = 11;
- uint32 input_config = 12;
- }
- WindowInfo window_info_handle = 27;
- float bg_color_alpha = 28;
- int32 bg_color_dataspace = 29;
- bool color_space_agnostic = 30;
- float shadow_radius = 31;
- int32 frame_rate_selection_priority = 32;
- float frame_rate = 33;
- int32 frame_rate_compatibility = 34;
- int32 change_frame_rate_strategy = 35;
- uint32 fixed_transform_hint = 36;
- uint64 frame_number = 37;
- bool auto_refresh = 38;
- bool is_trusted_overlay = 39;
- RectProto buffer_crop = 40;
- RectProto destination_frame = 41;
-
- enum DropInputMode {
- NONE = 0;
- ALL = 1;
- OBSCURED = 2;
- };
- DropInputMode drop_input_mode = 42;
-}
-
-message DisplayState {
- enum Changes {
- eChangesNone = 0;
- eSurfaceChanged = 0x01;
- eLayerStackChanged = 0x02;
- eDisplayProjectionChanged = 0x04;
- eDisplaySizeChanged = 0x08;
- eFlagsChanged = 0x10;
- };
- int32 id = 1;
- uint32 what = 2;
- uint32 flags = 3;
- uint32 layer_stack = 4;
- uint32 orientation = 5;
- RectProto layer_stack_space_rect = 6;
- RectProto oriented_display_space_rect = 7;
- uint32 width = 8;
- uint32 height = 9;
-}
diff --git a/services/surfaceflinger/tests/Stress_test.cpp b/services/surfaceflinger/tests/Stress_test.cpp
index 03201f7..b30df5e 100644
--- a/services/surfaceflinger/tests/Stress_test.cpp
+++ b/services/surfaceflinger/tests/Stress_test.cpp
@@ -51,9 +51,9 @@
}
}
-surfaceflinger::LayersProto generateLayerProto() {
- surfaceflinger::LayersProto layersProto;
- std::array<surfaceflinger::LayerProto*, 10> layers = {};
+perfetto::protos::LayersProto generateLayerProto() {
+ perfetto::protos::LayersProto layersProto;
+ std::array<perfetto::protos::LayerProto*, 10> layers = {};
for (size_t i = 0; i < layers.size(); ++i) {
layers[i] = layersProto.add_layers();
layers[i]->set_id(i);
@@ -103,7 +103,7 @@
cmd += std::to_string(getpid());
system(cmd.c_str());
for (int i = 0; i < 100000; i++) {
- surfaceflinger::LayersProto layersProto = generateLayerProto();
+ perfetto::protos::LayersProto layersProto = generateLayerProto();
auto layerTree = surfaceflinger::LayerProtoParser::generateLayerTree(layersProto);
surfaceflinger::LayerProtoParser::layerTreeToString(layerTree);
}
diff --git a/services/surfaceflinger/tests/tracing/Android.bp b/services/surfaceflinger/tests/tracing/Android.bp
index 21ebaea..b6cd7b8 100644
--- a/services/surfaceflinger/tests/tracing/Android.bp
+++ b/services/surfaceflinger/tests/tracing/Android.bp
@@ -35,7 +35,6 @@
srcs: [
":libsurfaceflinger_sources",
":libsurfaceflinger_mock_sources",
- ":layertracegenerator_sources",
"TransactionTraceTestSuite.cpp",
],
static_libs: [
@@ -43,7 +42,6 @@
],
header_libs: [
"libsurfaceflinger_mocks_headers",
- "layertracegenerator_headers",
],
data: ["testdata/*"],
}
diff --git a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
index b8a5e79..7a07634 100644
--- a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
+++ b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
@@ -23,8 +23,8 @@
#include <unordered_map>
#include <LayerProtoHelper.h>
-#include <LayerTraceGenerator.h>
#include <Tracing/TransactionProtoParser.h>
+#include <Tracing/tools/LayerTraceGenerator.h>
#include <layerproto/LayerProtoHeader.h>
#include <log/log.h>
@@ -40,9 +40,9 @@
static constexpr std::string_view sLayersTracePrefix = "layers_trace_";
static constexpr std::string_view sTracePostfix = ".winscope";
- proto::TransactionTraceFile mTransactionTrace;
- LayersTraceFileProto mExpectedLayersTraceProto;
- LayersTraceFileProto mActualLayersTraceProto;
+ perfetto::protos::TransactionTraceFile mTransactionTrace;
+ perfetto::protos::LayersTraceFileProto mExpectedLayersTraceProto;
+ perfetto::protos::LayersTraceFileProto mActualLayersTraceProto;
protected:
void SetUp() override {
@@ -56,18 +56,23 @@
EXPECT_TRUE(std::filesystem::exists(std::filesystem::path(expectedLayersTracePath)));
parseLayersTraceFromFile(expectedLayersTracePath.c_str(), mExpectedLayersTraceProto);
TemporaryDir temp_dir;
+
std::string actualLayersTracePath =
std::string(temp_dir.path) + "/" + expectedLayersFilename + "_actual";
+ {
+ auto traceFlags = LayerTracing::TRACE_INPUT | LayerTracing::TRACE_BUFFERS;
+ std::ofstream outStream{actualLayersTracePath, std::ios::binary | std::ios::app};
+ EXPECT_TRUE(LayerTraceGenerator().generate(mTransactionTrace, traceFlags, outStream,
+ /*onlyLastEntry=*/true))
+ << "Failed to generate layers trace from " << transactionTracePath;
+ }
- EXPECT_TRUE(LayerTraceGenerator().generate(mTransactionTrace, actualLayersTracePath.c_str(),
- /*onlyLastEntry=*/true))
- << "Failed to generate layers trace from " << transactionTracePath;
EXPECT_TRUE(std::filesystem::exists(std::filesystem::path(actualLayersTracePath)));
parseLayersTraceFromFile(actualLayersTracePath.c_str(), mActualLayersTraceProto);
}
void parseTransactionTraceFromFile(const char* transactionTracePath,
- proto::TransactionTraceFile& outProto) {
+ perfetto::protos::TransactionTraceFile& outProto) {
ALOGD("Parsing file %s...", transactionTracePath);
std::fstream input(transactionTracePath, std::ios::in | std::ios::binary);
EXPECT_TRUE(input) << "Error could not open " << transactionTracePath;
@@ -75,7 +80,8 @@
<< "Failed to parse " << transactionTracePath;
}
- void parseLayersTraceFromFile(const char* layersTracePath, LayersTraceFileProto& outProto) {
+ void parseLayersTraceFromFile(const char* layersTracePath,
+ perfetto::protos::LayersTraceFileProto& outProto) {
ALOGD("Parsing file %s...", layersTracePath);
std::fstream input(layersTracePath, std::ios::in | std::ios::binary);
EXPECT_TRUE(input) << "Error could not open " << layersTracePath;
@@ -124,7 +130,7 @@
bool operator()(LayerInfo const& m) const { return m.id == id; }
};
-static LayerInfo getLayerInfoFromProto(::android::surfaceflinger::LayerProto& proto) {
+static LayerInfo getLayerInfoFromProto(perfetto::protos::LayerProto& proto) {
Rect touchableRegionBounds = Rect::INVALID_RECT;
// ignore touchable region for layers without buffers, the new fe aggressively avoids
// calculating state for layers that are not visible which could lead to mismatches
@@ -148,8 +154,7 @@
touchableRegionBounds};
}
-static std::vector<LayerInfo> getLayerInfosFromProto(
- android::surfaceflinger::LayersTraceProto& entry) {
+static std::vector<LayerInfo> getLayerInfosFromProto(perfetto::protos::LayersSnapshotProto& entry) {
std::unordered_map<uint64_t /* snapshotId*/, uint64_t /*layerId*/> snapshotIdToLayerId;
std::vector<LayerInfo> layers;
layers.reserve(static_cast<size_t>(entry.layers().layers_size()));
@@ -267,4 +272,4 @@
}
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
-}
\ No newline at end of file
+}
diff --git a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
index a95a645..cbb597a 100644
--- a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
@@ -85,7 +85,7 @@
TransactionProtoParser parser(std::make_unique<TestMapper>(displayHandle));
- proto::TransactionState proto = parser.toProto(t1);
+ perfetto::protos::TransactionState proto = parser.toProto(t1);
TransactionState t2 = parser.fromProto(proto);
ASSERT_EQ(t1.originPid, t2.originPid);
@@ -119,7 +119,7 @@
d1.transformHint = ui::Transform::ROT_90;
const uint32_t layerStack = 2;
- google::protobuf::RepeatedPtrField<proto::DisplayInfo> displayProtos;
+ google::protobuf::RepeatedPtrField<perfetto::protos::DisplayInfo> displayProtos;
auto displayInfoProto = displayProtos.Add();
*displayInfoProto = TransactionProtoParser::toProto(d1, layerStack);
frontend::DisplayInfos displayInfos;
diff --git a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
index 71a2d2b..7981224 100644
--- a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
@@ -37,11 +37,11 @@
TransactionTracing mTracing;
void flush() { mTracing.flush(); }
- proto::TransactionTraceFile writeToProto() { return mTracing.writeToProto(); }
+ perfetto::protos::TransactionTraceFile writeToProto() { return mTracing.writeToProto(); }
- proto::TransactionTraceEntry bufferFront() {
+ perfetto::protos::TransactionTraceEntry bufferFront() {
std::scoped_lock<std::mutex> lock(mTracing.mTraceLock);
- proto::TransactionTraceEntry entry;
+ perfetto::protos::TransactionTraceEntry entry;
entry.ParseFromString(mTracing.mBuffer.front());
return entry;
}
@@ -59,7 +59,7 @@
flush();
}
- void verifyEntry(const proto::TransactionTraceEntry& actualProto,
+ void verifyEntry(const perfetto::protos::TransactionTraceEntry& actualProto,
const std::vector<TransactionState>& expectedTransactions,
int64_t expectedVsyncId) {
EXPECT_EQ(actualProto.vsync_id(), expectedVsyncId);
@@ -117,7 +117,7 @@
mTracing.addCommittedTransactions(secondTransactionSetVsyncId, 0, secondUpdate, {}, false);
flush();
- proto::TransactionTraceFile proto = writeToProto();
+ perfetto::protos::TransactionTraceFile proto = writeToProto();
ASSERT_EQ(proto.entry().size(), 2);
verifyEntry(proto.entry(0), firstUpdate.transactions, firstTransactionSetVsyncId);
verifyEntry(proto.entry(1), secondUpdate.transactions, secondTransactionSetVsyncId);
@@ -203,7 +203,7 @@
while (bufferFront().vsync_id() <= VSYNC_ID_FIRST_LAYER_CHANGE) {
queueAndCommitTransaction(++mVsyncId);
}
- proto::TransactionTraceFile proto = writeToProto();
+ perfetto::protos::TransactionTraceFile proto = writeToProto();
// verify we can still retrieve the layer change from the first entry containing starting
// states.
EXPECT_GT(proto.entry().size(), 0);
@@ -221,7 +221,7 @@
while (bufferFront().vsync_id() <= VSYNC_ID_SECOND_LAYER_CHANGE) {
queueAndCommitTransaction(++mVsyncId);
}
- proto::TransactionTraceFile proto = writeToProto();
+ perfetto::protos::TransactionTraceFile proto = writeToProto();
// verify starting states are updated correctly
EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).z(), 41);
}
@@ -231,7 +231,7 @@
while (bufferFront().vsync_id() <= VSYNC_ID_CHILD_LAYER_REMOVED) {
queueAndCommitTransaction(++mVsyncId);
}
- proto::TransactionTraceFile proto = writeToProto();
+ perfetto::protos::TransactionTraceFile proto = writeToProto();
// verify the child layer has been removed from the trace
EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 1);
EXPECT_EQ(proto.entry(0).transactions(0).layer_changes(0).layer_id(), mParentLayerId);
@@ -242,7 +242,7 @@
while (bufferFront().vsync_id() <= VSYNC_ID_SECOND_LAYER_CHANGE) {
queueAndCommitTransaction(++mVsyncId);
}
- proto::TransactionTraceFile proto = writeToProto();
+ perfetto::protos::TransactionTraceFile proto = writeToProto();
// verify we have two starting states
EXPECT_EQ(proto.entry(0).transactions(0).layer_changes().size(), 2);
@@ -302,7 +302,7 @@
};
TEST_F(TransactionTracingMirrorLayerTest, canAddMirrorLayers) {
- proto::TransactionTraceFile proto = writeToProto();
+ perfetto::protos::TransactionTraceFile proto = writeToProto();
// We don't have any starting states since no layer was removed from.
EXPECT_EQ(proto.entry().size(), 1);
@@ -317,18 +317,18 @@
// Verify we can write the layers traces by entry to reduce mem pressure
// on the system when generating large traces.
TEST(LayerTraceTest, canStreamLayersTrace) {
- LayersTraceFileProto inProto = LayerTracing::createTraceFileProto();
+ perfetto::protos::LayersTraceFileProto inProto = LayerTracing::createTraceFileProto();
inProto.add_entry();
inProto.add_entry();
std::string output;
inProto.SerializeToString(&output);
- LayersTraceFileProto inProto2 = LayerTracing::createTraceFileProto();
+ perfetto::protos::LayersTraceFileProto inProto2 = LayerTracing::createTraceFileProto();
inProto2.add_entry();
std::string output2;
inProto2.SerializeToString(&output2);
- LayersTraceFileProto outProto;
+ perfetto::protos::LayersTraceFileProto outProto;
outProto.ParseFromString(output + output2);
// magic?
EXPECT_EQ(outProto.entry().size(), 3);