diff options
| author | 2023-09-04 07:50:34 +0000 | |
|---|---|---|
| committer | 2023-09-04 07:50:34 +0000 | |
| commit | 2f96ee9cf247a81304caa45c11069dce43f1aa1b (patch) | |
| tree | fdfee73e902fcd254e58927b79ccd2876020c213 | |
| parent | 5855f5a09b444cddccd6bcaa7e38737b4e92a4e4 (diff) | |
| parent | 3e68a20316a7d9d6be55bb71adad643a0eb7f856 (diff) | |
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
39 files changed, 1184 insertions, 1255 deletions
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index eda52bfcb5..1718e0b10f 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -198,9 +198,12 @@ filegroup { "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 cdf7cff76d..9a5173ba9b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -139,7 +139,7 @@ using gui::WindowInfo; 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 @@ bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace da 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 @@ void Layer::setInputInfo(const WindowInfo& info) { 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 @@ LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags) { 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 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo) { 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 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet 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 @@ Rect Layer::computeBufferCrop(const State& s) { } 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 7b6c56b6a8..dc4ceb0bfa 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -235,7 +235,7 @@ public: 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 @@ public: 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 341f041086..144e1f5abf 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -29,28 +29,30 @@ using gui::WindowInfo; 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 @@ void LayerProtoHelper::writeToProto(const Region& region, 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::writeToProto(const Region& region, RegionProto* regionPro } } -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::readFromProto(const RegionProto& regionProto, Region& out } } -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 FloatRect& rect, } } -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::writeToProto(const half4 color, std::function<ColorProto* } 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::writeToProtoDeprecated(const ui::Transform& transform, } 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::writeTransformToProto(const ui::Transform& transform, } } -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 renderengine::ExternalTexture& buffer, 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( } } -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::writeToProto(const mat4 matrix, ColorTransformProto* colo } } -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::readFromProto(const ColorTransformProto& colorTransformPr } } -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 @@ void LayerProtoHelper::writeToProto(const android::BlurRegion region, BlurRegion 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 @@ void LayerProtoHelper::readFromProto(const BlurRegion& proto, android::BlurRegio 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 @@ frontend::LayerSnapshot* LayerProtoFromSnapshotGenerator::getSnapshot( 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 LayerProtoFromSnapshotGenerator::writeHierarchyToProto( } } -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 @@ void LayerProtoHelper::writeSnapshotToProto(LayerProto* layerInfo, [&]() { 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 346685f259..20c226006c 100644 --- a/services/surfaceflinger/LayerProtoHelper.h +++ b/services/surfaceflinger/LayerProtoHelper.h @@ -35,39 +35,47 @@ namespace android { 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 @@ public: 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 @@ private: 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 bc626f3030..38188c05b5 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -320,8 +320,6 @@ const String16 sWakeupSurfaceFlinger("android.permission.WAKEUP_SURFACE_FLINGER" 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 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI 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 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { 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 @@ bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId, 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 @@ bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId, 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 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( 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 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { } 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 @@ void SurfaceFlinger::dumpHdrInfo(std::string& result) const { } } -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 @@ LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { } 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 @@ LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { .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 @@ void SurfaceFlinger::dumpHwc(std::string& result) const { 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 @@ void SurfaceFlinger::dumpOffscreenLayersProto(LayersProto& layersProto, uint32_t 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 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, const std::string& comp 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 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r 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 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r 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 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r } 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 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r // 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 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r 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 @@ frontend::Update SurfaceFlinger::flushLifecycleUpdates() { 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 79dcd0d1b2..dc4e7cf2fe 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -368,7 +368,6 @@ private: friend class RefreshRateOverlay; friend class RegionSamplingThread; friend class LayerRenderArea; - friend class LayerTracing; friend class SurfaceComposerAIDL; friend class DisplayRenderArea; @@ -1092,17 +1091,20 @@ private: 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 @@ private: 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 0000000000..474fef89a0 --- /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 0000000000..7944092993 --- /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 b92d50b423..e55b4c2ce8 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 "LayerTracing.h" + +#include "LayerDataSource.h" +#include "Tracing/tools/LayerTraceGenerator.h" +#include "TransactionTracing.h" -#include <SurfaceFlinger.h> -#include <android-base/stringprintf.h> #include <log/log.h> -#include <utils/SystemClock.h> +#include <perfetto/tracing.h> +#include <utils/Timers.h> #include <utils/Trace.h> -#include "LayerTracing.h" -#include "TransactionRingBuffer.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(); +} + +void LayerTracing::setTakeLayersSnapshotProtoFunction( + const std::function<perfetto::protos::LayersSnapshotProto(uint32_t)>& callback) { + mTakeLayersSnapshotProto = callback; +} -bool LayerTracing::enable() { - std::scoped_lock lock(mTraceLock); - if (mEnabled) { - return false; +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; -} -void LayerTracing::appendToStream(std::ofstream& out) { - std::scoped_lock lock(mTraceLock); - LayersTraceFileProto fileProto = createTraceFileProto(); - mBuffer->appendToStream(fileProto, out); - mBuffer->reset(); + auto transactionTrace = mTransactionTracing->writeToProto(); + LayerTraceGenerator{}.generate(transactionTrace, flags); + ALOGV("Flushed generated tracing"); } -bool LayerTracing::isEnabled() const { - std::scoped_lock lock(mTraceLock); - return mEnabled; +void LayerTracing::onStop(Mode mode) { + if (mode == Mode::MODE_ACTIVE) { + mIsActiveTracingStarted.store(false); + ALOGV("Stopped active tracing"); + } } -status_t LayerTracing::writeToFile(std::string filename) { - std::scoped_lock lock(mTraceLock); - if (!mEnabled) { - return STATUS_OK; +void LayerTracing::addProtoSnapshotToOstream(perfetto::protos::LayersSnapshotProto&& snapshot, + Mode mode) { + ATRACE_CALL(); + if (mOutStream) { + writeSnapshotToStream(std::move(snapshot)); + } else { + writeSnapshotToPerfetto(snapshot, mode); } - LayersTraceFileProto fileProto = createTraceFileProto(); - return mBuffer->writeToFile(fileProto, filename); } -void LayerTracing::setTraceFlags(uint32_t flags) { - std::scoped_lock lock(mTraceLock); - mFlags = flags; +bool LayerTracing::isActiveTracingStarted() const { + return mIsActiveTracingStarted.load(); } -void LayerTracing::setBufferSize(size_t bufferSizeInBytes) { - std::scoped_lock lock(mTraceLock); - mBufferSizeInBytes = bufferSizeInBytes; +uint32_t LayerTracing::getActiveTracingFlags() const { + return mActiveTracingFlags.load(); } -bool LayerTracing::flagIsSet(uint32_t flags) const { - return (mFlags & flags) == flags; -} -uint32_t LayerTracing::getFlags() const { - return mFlags; +bool LayerTracing::isActiveTracingFlagSet(Flag flag) const { + return (mActiveTracingFlags.load() & flag) != 0; } -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)); +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(); + } + }); +} - if (!visibleRegionDirty && !flagIsSet(LayerTracing::TRACE_BUFFERS)) { - return; +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; } - 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); + auto lastVsyncId = mLastVsyncIdWrittenToPerfetto.load(); + while (lastVsyncId < vsyncId) { + if (mLastVsyncIdWrittenToPerfetto.compare_exchange_strong(lastVsyncId, vsyncId)) { + return 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 7c0d23d5b6..349cc40073 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 @@ public: 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 0000000000..05b89b84ad --- /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 0000000000..be8373b4ac --- /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 b1e3d6378a..2dc89b55ba 100644 --- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp +++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp @@ -51,8 +51,8 @@ public: ~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 @@ proto::TransactionState TransactionProtoParser::toProto(const TransactionState& 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::LayerState TransactionProtoParser::toProto( 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 @@ proto::LayerState TransactionProtoParser::toProto( } 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 @@ proto::LayerState TransactionProtoParser::toProto( 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 @@ proto::LayerState TransactionProtoParser::toProto( 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 @@ proto::LayerState TransactionProtoParser::toProto( 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 @@ proto::LayerState TransactionProtoParser::toProto( 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 @@ proto::LayerState TransactionProtoParser::toProto( } 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 @@ proto::DisplayState TransactionProtoParser::toProto(const DisplayState& display) 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 @@ proto::LayerCreationArgs TransactionProtoParser::toProto(const LayerCreationArgs 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 @@ TransactionState TransactionProtoParser::fromProto(const proto::TransactionState 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 @@ void TransactionProtoParser::fromProto(const proto::LayerCreationArgs& proto, 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::mergeFromProto(const proto::LayerState& proto, } } -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 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, 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 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, } 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 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, 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 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, 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 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, 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 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, 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 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, } } -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 @@ DisplayState TransactionProtoParser::fromProto(const proto::DisplayState& proto) 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 @@ void asProto(proto::Transform* proto, const ui::Transform& transform) { 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 @@ proto::DisplayInfo TransactionProtoParser::toProto(const frontend::DisplayInfo& 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 @@ frontend::DisplayInfo TransactionProtoParser::fromProto(const proto::DisplayInfo } 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 457c3bec40..b3ab71cfb5 100644 --- a/services/surfaceflinger/Tracing/TransactionProtoParser.h +++ b/services/surfaceflinger/Tracing/TransactionProtoParser.h @@ -44,25 +44,25 @@ public: 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 e6f85ca4a5..7d1d3fd7f2 100644 --- a/services/surfaceflinger/Tracing/TransactionRingBuffer.h +++ b/services/surfaceflinger/Tracing/TransactionRingBuffer.h @@ -47,7 +47,7 @@ public: 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 @@ public: } } - 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 bc69191cc1..0517984dab 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 @@ TransactionTracing::TransactionTracing() : 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 @@ TransactionTracing::~TransactionTracing() { if (thread.joinable()) { thread.join(); } +} + +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)"); +} - writeToFile(); +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::dump(std::string& result) const { } 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 @@ void TransactionTracing::addEntry(const std::vector<CommittedUpdates>& committed 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 @@ void TransactionTracing::addEntry(const std::vector<CommittedUpdates>& committed 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 @@ void TransactionTracing::flush() { 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::tryPushToTracingThread() { } 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::updateStartingStateLocked( } } -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 422b5f3689..ddbf3e4873 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 SurfaceFlinger; 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 @@ class TransactionTracingTest; * 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 @@ private: } mutable std::mutex mTraceLock; - TransactionRingBuffer<proto::TransactionTraceFile, proto::TransactionTraceEntry> mBuffer - GUARDED_BY(mTraceLock); - size_t mBufferSizeInBytes GUARDED_BY(mTraceLock) = CONTINUOUS_TRACING_BUFFER_SIZE; - std::unordered_map<uint64_t, proto::TransactionState> mQueuedTransactions + TransactionRingBuffer<perfetto::protos::TransactionTraceFile, + perfetto::protos::TransactionTraceEntry> + mBuffer GUARDED_BY(mTraceLock); + std::unordered_map<uint64_t, perfetto::protos::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 @@ private: 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 b6435a8a13..2ff09c3f4c 100644 --- a/services/surfaceflinger/Tracing/tools/Android.bp +++ b/services/surfaceflinger/Tracing/tools/Android.bp @@ -31,7 +31,6 @@ cc_binary { srcs: [ ":libsurfaceflinger_sources", ":libsurfaceflinger_mock_sources", - ":layertracegenerator_sources", "main.cpp", ], static_libs: [ @@ -41,15 +40,3 @@ cc_binary { "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 321b8baccc..62c362eb2d 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 @@ bool LayerTraceGenerator::generate(const proto::TransactionTraceFile& traceFile, 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 @@ bool LayerTraceGenerator::generate(const proto::TransactionTraceFile& traceFile, 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 @@ bool LayerTraceGenerator::generate(const proto::TransactionTraceFile& traceFile, 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 e41d1e6e0b..2bb6f5129c 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 5ca87e4cb3..a8ac36a422 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 @@ int main(int argc, char** argv) { 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 8a050fdab5..437fd35c15 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -455,7 +455,8 @@ public: 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 7287dd0103..a4dc8a058e 100644 --- a/services/surfaceflinger/layerproto/Android.bp +++ b/services/surfaceflinger/layerproto/Android.bp @@ -13,7 +13,20 @@ cc_library { 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 @@ cc_library { "libbase", ], - proto: { - export_proto_headers: true, - }, - cppflags: [ "-Werror", "-Wno-unused-parameter", @@ -42,22 +51,3 @@ cc_library { "-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 854084e7f9..c3d0a40261 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -37,7 +37,8 @@ bool sortLayers(LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs 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 @@ LayerProtoParser::LayerTree LayerProtoParser::generateLayerTree(const LayersProt } 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 @@ std::vector<LayerProtoParser::Layer> LayerProtoParser::generateLayerList( 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 @@ LayerProtoParser::Layer LayerProtoParser::generateLayer(const LayerProto& layerP 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 @@ LayerProtoParser::Rect LayerProtoParser::generateRect(const RectProto& rectProto 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::FloatRect LayerProtoParser::generateFloatRect(const FloatRectP } 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::Transform LayerProtoParser::generateTransform( } 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 @@ LayerProtoParser::ActiveBuffer LayerProtoParser::generateActiveBuffer( 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 @@ void LayerProtoParser::updateChildrenAndRelative(const LayerProto& layerProto, } } - 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 5e20d4d0f5..0000000000 --- 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 64de775b8b..0000000000 --- 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 f560562c94..4a2ef3ddf8 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 cdc2706ee2..79c3982dbd 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -131,19 +131,22 @@ public: 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 3e9ca52fff..ea80ad8f33 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 40043a861c..0000000000 --- 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 e9add2e1a4..0000000000 --- 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 804a4994ee..0000000000 --- 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 d03afa05ab..0000000000 --- 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 03201f7937..b30df5ef15 100644 --- a/services/surfaceflinger/tests/Stress_test.cpp +++ b/services/surfaceflinger/tests/Stress_test.cpp @@ -51,9 +51,9 @@ TEST(SurfaceFlingerStress, create_and_destroy) { } } -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 @@ TEST(LayerProtoStress, mem_info) { 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 21ebaea8ad..b6cd7b8b7f 100644 --- a/services/surfaceflinger/tests/tracing/Android.bp +++ b/services/surfaceflinger/tests/tracing/Android.bp @@ -35,7 +35,6 @@ cc_test { srcs: [ ":libsurfaceflinger_sources", ":libsurfaceflinger_mock_sources", - ":layertracegenerator_sources", "TransactionTraceTestSuite.cpp", ], static_libs: [ @@ -43,7 +42,6 @@ cc_test { ], 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 b8a5e79a38..7a076347bb 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 @@ public: 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 @@ protected: 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 @@ protected: << "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 @@ struct find_id : std::unary_function<LayerInfo, bool> { 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 @@ static LayerInfo getLayerInfoFromProto(::android::surfaceflinger::LayerProto& pr 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 @@ int main(int argc, char** argv) { } ::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 a95a6453d5..cbb597af69 100644 --- a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp @@ -85,7 +85,7 @@ TEST(TransactionProtoParserTest, parse) { 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 @@ TEST(TransactionProtoParserTest, parseDisplayInfo) { 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 71a2d2b9a6..7981224b5c 100644 --- a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp @@ -37,11 +37,11 @@ protected: 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 @@ protected: 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 @@ TEST_F(TransactionTracingTest, addTransactions) { 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 @@ TEST_F(TransactionTracingLayerHandlingTest, addStartingState) { 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 @@ TEST_F(TransactionTracingLayerHandlingTest, updateStartingState) { 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 @@ TEST_F(TransactionTracingLayerHandlingTest, removeStartingState) { 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 @@ TEST_F(TransactionTracingLayerHandlingTest, startingStateSurvivesBufferFlush) { 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 @@ protected: }; 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 @@ TEST_F(TransactionTracingMirrorLayerTest, canAddMirrorLayers) { // 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); |