SF: Simplify layer tracing
As preparation to support transaction tracing, do the
following:
1. refactor the ring buffer code so it can be reused
2. remove layer async tracing since we will use
transaction tracing for always on tracing
Test: presubmit
Test: capture sf trace via bugreport
Bug: 200284593
Change-Id: I28388c6db27a420c078e1cc33b0b378c55c6c5d6
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 56b8374..4e29172 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -200,7 +200,7 @@
"SurfaceFlinger.cpp",
"SurfaceFlingerDefaultFactory.cpp",
"SurfaceInterceptor.cpp",
- "SurfaceTracing.cpp",
+ "Tracing/LayerTracing.cpp",
"Tracing/TransactionProtoParser.cpp",
"TransactionCallbackInvoker.cpp",
"TunnelModeEnabledReporter.cpp",
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3d189d6..f5c5b4a 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2005,7 +2005,7 @@
writeToProtoDrawingState(layerProto, traceFlags, display);
writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags);
- if (traceFlags & SurfaceTracing::TRACE_COMPOSITION) {
+ if (traceFlags & LayerTracing::TRACE_COMPOSITION) {
// Only populate for the primary display.
if (display) {
const Hwc2::IComposerClient::Composition compositionType = getCompositionType(*display);
@@ -2023,43 +2023,38 @@
void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags,
const DisplayDevice* display) {
const ui::Transform transform = getTransform();
+ auto buffer = getBuffer();
+ if (buffer != nullptr) {
+ LayerProtoHelper::writeToProto(buffer,
+ [&]() { return layerInfo->mutable_active_buffer(); });
+ LayerProtoHelper::writeToProtoDeprecated(ui::Transform(getBufferTransform()),
+ layerInfo->mutable_buffer_transform());
+ }
+ layerInfo->set_invalidate(contentDirty);
+ layerInfo->set_is_protected(isProtected());
+ layerInfo->set_dataspace(dataspaceDetails(static_cast<android_dataspace>(getDataSpace())));
+ layerInfo->set_queued_frames(getQueuedFrameCount());
+ layerInfo->set_refresh_pending(isBufferLatched());
+ layerInfo->set_curr_frame(mCurrentFrameNumber);
+ layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
- if (traceFlags & SurfaceTracing::TRACE_CRITICAL) {
+ layerInfo->set_requested_corner_radius(getDrawingState().cornerRadius);
+ layerInfo->set_corner_radius(getRoundedCornerState().radius);
+ layerInfo->set_background_blur_radius(getBackgroundBlurRadius());
+ layerInfo->set_is_trusted_overlay(isTrustedOverlay());
+ LayerProtoHelper::writeToProtoDeprecated(transform, layerInfo->mutable_transform());
+ LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
+ [&]() { return layerInfo->mutable_position(); });
+ LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
+ if (traceFlags & LayerTracing::TRACE_COMPOSITION) {
+ LayerProtoHelper::writeToProto(getVisibleRegion(display),
+ [&]() { return layerInfo->mutable_visible_region(); });
+ }
+ LayerProtoHelper::writeToProto(surfaceDamageRegion,
+ [&]() { return layerInfo->mutable_damage_region(); });
- auto buffer = getBuffer();
- if (buffer != nullptr) {
- LayerProtoHelper::writeToProto(buffer,
- [&]() { return layerInfo->mutable_active_buffer(); });
- LayerProtoHelper::writeToProtoDeprecated(ui::Transform(getBufferTransform()),
- layerInfo->mutable_buffer_transform());
- }
- layerInfo->set_invalidate(contentDirty);
- layerInfo->set_is_protected(isProtected());
- layerInfo->set_dataspace(dataspaceDetails(static_cast<android_dataspace>(getDataSpace())));
- layerInfo->set_queued_frames(getQueuedFrameCount());
- layerInfo->set_refresh_pending(isBufferLatched());
- layerInfo->set_curr_frame(mCurrentFrameNumber);
- layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
-
- layerInfo->set_requested_corner_radius(getDrawingState().cornerRadius);
- layerInfo->set_corner_radius(getRoundedCornerState().radius);
- layerInfo->set_background_blur_radius(getBackgroundBlurRadius());
- layerInfo->set_is_trusted_overlay(isTrustedOverlay());
- LayerProtoHelper::writeToProtoDeprecated(transform, layerInfo->mutable_transform());
- LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
- [&]() { return layerInfo->mutable_position(); });
- LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); });
- if (traceFlags & SurfaceTracing::TRACE_COMPOSITION) {
- LayerProtoHelper::writeToProto(getVisibleRegion(display),
- [&]() { return layerInfo->mutable_visible_region(); });
- }
- LayerProtoHelper::writeToProto(surfaceDamageRegion,
- [&]() { return layerInfo->mutable_damage_region(); });
-
- if (hasColorTransform()) {
- LayerProtoHelper::writeToProto(getColorTransform(),
- layerInfo->mutable_color_transform());
- }
+ if (hasColorTransform()) {
+ LayerProtoHelper::writeToProto(getColorTransform(), layerInfo->mutable_color_transform());
}
LayerProtoHelper::writeToProto(mSourceBounds,
@@ -2079,70 +2074,66 @@
ui::Transform requestedTransform = state.transform;
- if (traceFlags & SurfaceTracing::TRACE_CRITICAL) {
- layerInfo->set_id(sequence);
- layerInfo->set_name(getName().c_str());
- layerInfo->set_type(getType());
+ layerInfo->set_id(sequence);
+ layerInfo->set_name(getName().c_str());
+ layerInfo->set_type(getType());
- for (const auto& child : children) {
- layerInfo->add_children(child->sequence);
- }
-
- for (const wp<Layer>& weakRelative : state.zOrderRelatives) {
- sp<Layer> strongRelative = weakRelative.promote();
- if (strongRelative != nullptr) {
- layerInfo->add_relatives(strongRelative->sequence);
- }
- }
-
- LayerProtoHelper::writeToProto(state.activeTransparentRegion_legacy,
- [&]() { return layerInfo->mutable_transparent_region(); });
-
- layerInfo->set_layer_stack(getLayerStack().id);
- layerInfo->set_z(state.z);
-
- LayerProtoHelper::writePositionToProto(requestedTransform.tx(), requestedTransform.ty(),
- [&]() {
- return layerInfo->mutable_requested_position();
- });
-
- LayerProtoHelper::writeSizeToProto(state.width, state.height,
- [&]() { return layerInfo->mutable_size(); });
-
- LayerProtoHelper::writeToProto(state.crop, [&]() { return layerInfo->mutable_crop(); });
-
- layerInfo->set_is_opaque(isOpaque(state));
-
-
- layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat()));
- LayerProtoHelper::writeToProto(getColor(), [&]() { return layerInfo->mutable_color(); });
- LayerProtoHelper::writeToProto(state.color,
- [&]() { return layerInfo->mutable_requested_color(); });
- layerInfo->set_flags(state.flags);
-
- LayerProtoHelper::writeToProtoDeprecated(requestedTransform,
- layerInfo->mutable_requested_transform());
-
- 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);
-
- layerInfo->set_owner_uid(mOwnerUid);
+ for (const auto& child : children) {
+ layerInfo->add_children(child->sequence);
}
- if (traceFlags & SurfaceTracing::TRACE_INPUT) {
+ for (const wp<Layer>& weakRelative : state.zOrderRelatives) {
+ sp<Layer> strongRelative = weakRelative.promote();
+ if (strongRelative != nullptr) {
+ layerInfo->add_relatives(strongRelative->sequence);
+ }
+ }
+
+ LayerProtoHelper::writeToProto(state.activeTransparentRegion_legacy,
+ [&]() { return layerInfo->mutable_transparent_region(); });
+
+ layerInfo->set_layer_stack(getLayerStack().id);
+ layerInfo->set_z(state.z);
+
+ LayerProtoHelper::writePositionToProto(requestedTransform.tx(), requestedTransform.ty(), [&]() {
+ return layerInfo->mutable_requested_position();
+ });
+
+ LayerProtoHelper::writeSizeToProto(state.width, state.height,
+ [&]() { return layerInfo->mutable_size(); });
+
+ LayerProtoHelper::writeToProto(state.crop, [&]() { return layerInfo->mutable_crop(); });
+
+ layerInfo->set_is_opaque(isOpaque(state));
+
+ layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat()));
+ LayerProtoHelper::writeToProto(getColor(), [&]() { return layerInfo->mutable_color(); });
+ LayerProtoHelper::writeToProto(state.color,
+ [&]() { return layerInfo->mutable_requested_color(); });
+ layerInfo->set_flags(state.flags);
+
+ LayerProtoHelper::writeToProtoDeprecated(requestedTransform,
+ layerInfo->mutable_requested_transform());
+
+ 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);
+
+ layerInfo->set_owner_uid(mOwnerUid);
+
+ if (traceFlags & LayerTracing::TRACE_INPUT) {
WindowInfo info;
if (useDrawing) {
info = fillInputInfo(ui::Transform(), /* displayIsSecure */ true);
@@ -2154,7 +2145,7 @@
[&]() { return layerInfo->mutable_input_window_info(); });
}
- if (traceFlags & SurfaceTracing::TRACE_EXTRA) {
+ if (traceFlags & LayerTracing::TRACE_EXTRA) {
auto protoMap = layerInfo->mutable_metadata();
for (const auto& entry : state.metadata.mMap) {
(*protoMap)[entry.first] = std::string(entry.second.cbegin(), entry.second.cend());
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3da07e8..5af8dda 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -57,7 +57,7 @@
#include "Scheduler/LayerInfo.h"
#include "Scheduler/Seamlessness.h"
#include "SurfaceFlinger.h"
-#include "SurfaceTracing.h"
+#include "Tracing/LayerTracing.h"
#include "TransactionCallbackInvoker.h"
using namespace android::surfaceflinger;
@@ -691,7 +691,7 @@
// external mStateLock. If writing drawing state, this function should be called on the
// main or tracing thread.
void writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet,
- uint32_t traceFlags = SurfaceTracing::TRACE_ALL);
+ uint32_t traceFlags = LayerTracing::TRACE_ALL);
gui::WindowInfo::Type getWindowType() const { return mWindowType; }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5a6a8ce..a990e6b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1948,7 +1948,7 @@
}
if (mTracingEnabledChanged) {
- mTracingEnabled = mTracing.isEnabled();
+ mTracingEnabled = mLayerTracing.isEnabled();
mTracingEnabledChanged = false;
}
@@ -1962,24 +1962,12 @@
// Composite if transactions were committed, or if requested by HWC.
bool mustComposite = mMustComposite.exchange(false);
{
- mTracePostComposition = mTracing.flagIsSet(SurfaceTracing::TRACE_COMPOSITION) ||
- mTracing.flagIsSet(SurfaceTracing::TRACE_SYNC) ||
- mTracing.flagIsSet(SurfaceTracing::TRACE_BUFFERS);
- const bool tracePreComposition = mTracingEnabled && !mTracePostComposition;
- ConditionalLockGuard<std::mutex> lock(mTracingLock, tracePreComposition);
-
mFrameTimeline->setSfWakeUp(vsyncId, frameTime, Fps::fromPeriodNsecs(stats.vsyncPeriod));
mustComposite |= flushAndCommitTransactions();
mustComposite |= latchBuffers();
updateLayerGeometry();
-
- if (tracePreComposition) {
- if (mVisibleRegionsDirty) {
- mTracing.notifyLocked("visibleRegionsDirty");
- }
- }
}
// Layers need to get updated (in the previous line) before we can use them for
@@ -2112,12 +2100,12 @@
modulateVsync(&VsyncModulator::onDisplayRefresh, usedGpuComposition);
mLayersWithQueuedFrames.clear();
- if (mTracingEnabled && mTracePostComposition) {
- // This may block if SurfaceTracing is running in sync mode.
+ if (mTracingEnabled) {
+ // This will block and should only be used for debugging.
if (mVisibleRegionsDirty) {
- mTracing.notify("visibleRegionsDirty");
- } else if (mTracing.flagIsSet(SurfaceTracing::TRACE_BUFFERS)) {
- mTracing.notify("bufferLatched");
+ mLayerTracing.notify("visibleRegionsDirty");
+ } else if (mLayerTracing.flagIsSet(LayerTracing::TRACE_BUFFERS)) {
+ mLayerTracing.notify("bufferLatched");
}
}
@@ -4647,7 +4635,7 @@
}
if (dumpLayers) {
- LayersTraceFileProto traceFileProto = SurfaceTracing::createLayersTraceFileProto();
+ LayersTraceFileProto traceFileProto = mLayerTracing.createTraceFileProto();
LayersTraceProto* layersTrace = traceFileProto.add_entry();
LayersProto layersProto = dumpProtoFromMainThread();
layersTrace->mutable_layers()->Swap(&layersProto);
@@ -4669,8 +4657,8 @@
}
status_t SurfaceFlinger::dumpCritical(int fd, const DumpArgs&, bool asProto) {
- if (asProto && mTracing.isEnabled()) {
- mTracing.writeToFile();
+ if (asProto && mLayerTracing.isEnabled()) {
+ mLayerTracing.writeToFile();
}
return doDump(fd, DumpArgs(), asProto);
@@ -5066,7 +5054,7 @@
/*
* Tracing state
*/
- mTracing.dump(result);
+ mLayerTracing.dump(result);
result.append("\n");
/*
@@ -5493,20 +5481,20 @@
bool tracingEnabledChanged;
if (n) {
ALOGD("LayerTracing enabled");
- tracingEnabledChanged = mTracing.enable();
+ tracingEnabledChanged = mLayerTracing.enable();
if (tracingEnabledChanged) {
- schedule([&]() MAIN_THREAD { mTracing.notify("start"); }).wait();
+ schedule([&]() MAIN_THREAD { mLayerTracing.notify("start"); }).wait();
}
} else {
ALOGD("LayerTracing disabled");
- tracingEnabledChanged = mTracing.disable();
+ tracingEnabledChanged = mLayerTracing.disable();
}
mTracingEnabledChanged = tracingEnabledChanged;
reply->writeInt32(NO_ERROR);
return NO_ERROR;
}
case 1026: { // Get layer tracing status
- reply->writeBool(mTracing.isEnabled());
+ reply->writeBool(mLayerTracing.isEnabled());
return NO_ERROR;
}
// Is a DisplayColorSetting supported?
@@ -5547,7 +5535,7 @@
}
ALOGD("Updating trace buffer to %d KB", n);
- mTracing.setBufferSize(n * 1024);
+ mLayerTracing.setBufferSize(n * 1024);
reply->writeInt32(NO_ERROR);
return NO_ERROR;
}
@@ -5592,7 +5580,7 @@
case 1033: {
n = data.readUint32();
ALOGD("Updating trace flags to 0x%x", n);
- mTracing.setTraceFlags(n);
+ mLayerTracing.setTraceFlags(n);
reply->writeInt32(NO_ERROR);
return NO_ERROR;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index b432f24..e3bcde2 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -62,8 +62,8 @@
#include "Scheduler/Scheduler.h"
#include "Scheduler/VsyncModulator.h"
#include "SurfaceFlingerFactory.h"
-#include "SurfaceTracing.h"
#include "TracedOrdinal.h"
+#include "Tracing/LayerTracing.h"
#include "TransactionCallbackInvoker.h"
#include "TransactionState.h"
@@ -353,7 +353,7 @@
friend class MonitoredProducer;
friend class RefreshRateOverlay;
friend class RegionSamplingThread;
- friend class SurfaceTracing;
+ friend class LayerTracing;
// For unit tests
friend class TestableSurfaceFlinger;
@@ -1042,12 +1042,12 @@
void dumpWideColorInfo(std::string& result) const REQUIRES(mStateLock);
LayersProto dumpDrawingStateProto(uint32_t traceFlags) const;
void dumpOffscreenLayersProto(LayersProto& layersProto,
- uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const;
+ uint32_t traceFlags = LayerTracing::TRACE_ALL) const;
void dumpDisplayProto(LayersTraceProto& layersTraceProto) const;
// Dumps state from HW Composer
void dumpHwc(std::string& result) const;
- LayersProto dumpProtoFromMainThread(uint32_t traceFlags = SurfaceTracing::TRACE_ALL)
+ 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);
@@ -1190,10 +1190,9 @@
bool mPropagateBackpressureClientComposition = false;
sp<SurfaceInterceptor> mInterceptor;
- SurfaceTracing mTracing{*this};
+ LayerTracing mLayerTracing{*this};
std::mutex mTracingLock;
bool mTracingEnabled = false;
- bool mTracePostComposition = false;
std::atomic<bool> mTracingEnabledChanged = false;
const std::shared_ptr<TimeStats> mTimeStats;
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
deleted file mode 100644
index 5963737..0000000
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#undef LOG_TAG
-#define LOG_TAG "SurfaceTracing"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include "SurfaceTracing.h"
-#include <SurfaceFlinger.h>
-
-#include <android-base/file.h>
-#include <android-base/stringprintf.h>
-#include <log/log.h>
-#include <utils/SystemClock.h>
-#include <utils/Trace.h>
-
-namespace android {
-
-SurfaceTracing::SurfaceTracing(SurfaceFlinger& flinger) : mFlinger(flinger) {}
-
-bool SurfaceTracing::enable() {
- std::scoped_lock lock(mTraceLock);
- if (mEnabled) {
- return false;
- }
-
- if (flagIsSet(TRACE_SYNC)) {
- runner = std::make_unique<SurfaceTracing::Runner>(mFlinger, mConfig);
- } else {
- runner = std::make_unique<SurfaceTracing::AsyncRunner>(mFlinger, mConfig,
- mFlinger.mTracingLock);
- }
- mEnabled = true;
- return true;
-}
-
-bool SurfaceTracing::disable() {
- std::scoped_lock lock(mTraceLock);
- if (!mEnabled) {
- return false;
- }
- mEnabled = false;
- runner->stop();
- return true;
-}
-
-bool SurfaceTracing::isEnabled() const {
- std::scoped_lock lock(mTraceLock);
- return mEnabled;
-}
-
-status_t SurfaceTracing::writeToFile() {
- std::scoped_lock lock(mTraceLock);
- if (!mEnabled) {
- return STATUS_OK;
- }
- return runner->writeToFile();
-}
-
-void SurfaceTracing::notify(const char* where) {
- std::scoped_lock lock(mTraceLock);
- if (mEnabled) {
- runner->notify(where);
- }
-}
-
-void SurfaceTracing::notifyLocked(const char* where) {
- std::scoped_lock lock(mTraceLock);
- if (mEnabled) {
- runner->notifyLocked(where);
- }
-}
-
-void SurfaceTracing::dump(std::string& result) const {
- std::scoped_lock lock(mTraceLock);
- base::StringAppendF(&result, "Tracing state: %s\n", mEnabled ? "enabled" : "disabled");
- if (mEnabled) {
- runner->dump(result);
- }
-}
-
-void SurfaceTracing::LayersTraceBuffer::reset(size_t newSize) {
- // use the swap trick to make sure memory is released
- std::queue<LayersTraceProto>().swap(mStorage);
- mSizeInBytes = newSize;
- mUsedInBytes = 0U;
-}
-
-void SurfaceTracing::LayersTraceBuffer::emplace(LayersTraceProto&& proto) {
- size_t protoSize = static_cast<size_t>(proto.ByteSize());
- while (mUsedInBytes + protoSize > mSizeInBytes) {
- if (mStorage.empty()) {
- return;
- }
- mUsedInBytes -= static_cast<size_t>(mStorage.front().ByteSize());
- mStorage.pop();
- }
- mUsedInBytes += protoSize;
- mStorage.emplace();
- mStorage.back().Swap(&proto);
-}
-
-void SurfaceTracing::LayersTraceBuffer::flush(LayersTraceFileProto* fileProto) {
- fileProto->mutable_entry()->Reserve(static_cast<int>(mStorage.size()));
-
- while (!mStorage.empty()) {
- auto entry = fileProto->add_entry();
- entry->Swap(&mStorage.front());
- mStorage.pop();
- }
-}
-
-SurfaceTracing::Runner::Runner(SurfaceFlinger& flinger, SurfaceTracing::Config& config)
- : mFlinger(flinger), mConfig(config) {
- mBuffer.setSize(mConfig.bufferSize);
-}
-
-void SurfaceTracing::Runner::notify(const char* where) {
- LayersTraceProto entry = traceLayers(where);
- mBuffer.emplace(std::move(entry));
-}
-
-status_t SurfaceTracing::Runner::stop() {
- return writeToFile();
-}
-
-LayersTraceFileProto SurfaceTracing::createLayersTraceFileProto() {
- LayersTraceFileProto fileProto;
- fileProto.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
- LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
- return fileProto;
-}
-
-status_t SurfaceTracing::Runner::writeToFile() {
- ATRACE_CALL();
-
- LayersTraceFileProto fileProto = createLayersTraceFileProto();
- std::string output;
-
- mBuffer.flush(&fileProto);
- mBuffer.reset(mConfig.bufferSize);
-
- if (!fileProto.SerializeToString(&output)) {
- ALOGE("Could not save the proto file! Permission denied");
- return PERMISSION_DENIED;
- }
-
- // -rw-r--r--
- const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
- if (!android::base::WriteStringToFile(output, DEFAULT_FILE_NAME, mode, getuid(), getgid(),
- true)) {
- ALOGE("Could not save the proto file! There are missing fields");
- return PERMISSION_DENIED;
- }
-
- return NO_ERROR;
-}
-
-LayersTraceProto SurfaceTracing::Runner::traceLayers(const char* where) {
- ATRACE_CALL();
-
- LayersTraceProto entry;
- entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
- entry.set_where(where);
- LayersProto layers(mFlinger.dumpDrawingStateProto(mConfig.flags));
-
- if (flagIsSet(SurfaceTracing::TRACE_EXTRA)) {
- mFlinger.dumpOffscreenLayersProto(layers);
- }
- entry.mutable_layers()->Swap(&layers);
-
- if (flagIsSet(SurfaceTracing::TRACE_HWC)) {
- std::string hwcDump;
- mFlinger.dumpHwc(hwcDump);
- entry.set_hwc_blob(hwcDump);
- }
- if (!flagIsSet(SurfaceTracing::TRACE_COMPOSITION)) {
- entry.set_excludes_composition_state(true);
- }
- entry.set_missed_entries(mMissedTraceEntries);
- mFlinger.dumpDisplayProto(entry);
- return entry;
-}
-
-void SurfaceTracing::Runner::dump(std::string& result) const {
- base::StringAppendF(&result, " number of entries: %zu (%.2fMB / %.2fMB)\n",
- mBuffer.frameCount(), float(mBuffer.used()) / float(1_MB),
- float(mBuffer.size()) / float(1_MB));
-}
-
-SurfaceTracing::AsyncRunner::AsyncRunner(SurfaceFlinger& flinger, SurfaceTracing::Config& config,
- std::mutex& sfLock)
- : SurfaceTracing::Runner(flinger, config), mSfLock(sfLock) {
- mEnabled = true;
- mThread = std::thread(&AsyncRunner::loop, this);
-}
-
-void SurfaceTracing::AsyncRunner::loop() {
- while (mEnabled) {
- LayersTraceProto entry;
- bool entryAdded = traceWhenNotified(&entry);
- if (entryAdded) {
- mBuffer.emplace(std::move(entry));
- }
- if (mWriteToFile) {
- Runner::writeToFile();
- mWriteToFile = false;
- }
- }
-}
-
-bool SurfaceTracing::AsyncRunner::traceWhenNotified(LayersTraceProto* outProto) {
- std::unique_lock<std::mutex> lock(mSfLock);
- mCanStartTrace.wait(lock);
- if (!mAddEntry) {
- return false;
- }
- *outProto = traceLayers(mWhere);
- mAddEntry = false;
- mMissedTraceEntries = 0;
- return true;
-}
-
-void SurfaceTracing::AsyncRunner::notify(const char* where) {
- std::scoped_lock lock(mSfLock);
- notifyLocked(where);
-}
-
-void SurfaceTracing::AsyncRunner::notifyLocked(const char* where) {
- mWhere = where;
- if (mAddEntry) {
- mMissedTraceEntries++;
- }
- mAddEntry = true;
- mCanStartTrace.notify_one();
-}
-
-status_t SurfaceTracing::AsyncRunner::writeToFile() {
- mWriteToFile = true;
- mCanStartTrace.notify_one();
- return STATUS_OK;
-}
-
-status_t SurfaceTracing::AsyncRunner::stop() {
- mEnabled = false;
- mCanStartTrace.notify_one();
- mThread.join();
- return Runner::writeToFile();
-}
-
-} // namespace android
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
deleted file mode 100644
index 97adb20..0000000
--- a/services/surfaceflinger/SurfaceTracing.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright 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.
- */
-
-#pragma once
-
-#include <android-base/thread_annotations.h>
-#include <layerproto/LayerProtoHeader.h>
-#include <utils/Errors.h>
-#include <utils/StrongPointer.h>
-
-#include <condition_variable>
-#include <memory>
-#include <mutex>
-#include <queue>
-#include <thread>
-
-using namespace android::surfaceflinger;
-
-namespace android {
-
-class SurfaceFlinger;
-constexpr auto operator""_MB(unsigned long long const num) {
- return num * 1024 * 1024;
-}
-/*
- * SurfaceTracing records layer states during surface flinging. Manages tracing state and
- * configuration.
- */
-class SurfaceTracing {
-public:
- SurfaceTracing(SurfaceFlinger& flinger);
- bool enable();
- bool disable();
- status_t writeToFile();
- bool isEnabled() const;
- /*
- * Adds a trace entry, must be called from the drawing thread or while holding the
- * SurfaceFlinger tracing lock.
- */
- void notify(const char* where);
- /*
- * Adds a trace entry, called while holding the SurfaceFlinger tracing lock.
- */
- void notifyLocked(const char* where) /* REQUIRES(mSfLock) */;
-
- void setBufferSize(size_t bufferSizeInBytes) { mConfig.bufferSize = bufferSizeInBytes; }
- void dump(std::string& result) const;
-
- enum : uint32_t {
- TRACE_CRITICAL = 1 << 0,
- TRACE_INPUT = 1 << 1,
- TRACE_COMPOSITION = 1 << 2,
- TRACE_EXTRA = 1 << 3,
- TRACE_HWC = 1 << 4,
- // Add non-geometry composition changes to the trace.
- TRACE_BUFFERS = 1 << 5,
- // Add entries from the drawing thread post composition.
- TRACE_SYNC = 1 << 6,
- TRACE_ALL = TRACE_CRITICAL | TRACE_INPUT | TRACE_COMPOSITION | TRACE_EXTRA,
- };
- void setTraceFlags(uint32_t flags) { mConfig.flags = flags; }
- bool flagIsSet(uint32_t flags) { return (mConfig.flags & flags) == flags; }
- static LayersTraceFileProto createLayersTraceFileProto();
-
-private:
- class Runner;
- static constexpr auto DEFAULT_BUFFER_SIZE = 20_MB;
- static constexpr auto DEFAULT_FILE_NAME = "/data/misc/wmtrace/layers_trace.winscope";
-
- SurfaceFlinger& mFlinger;
- mutable std::mutex mTraceLock;
- bool mEnabled GUARDED_BY(mTraceLock) = false;
- std::unique_ptr<Runner> runner GUARDED_BY(mTraceLock);
-
- struct Config {
- uint32_t flags = TRACE_CRITICAL | TRACE_INPUT | TRACE_SYNC;
- size_t bufferSize = DEFAULT_BUFFER_SIZE;
- } mConfig;
-
- /*
- * ring buffer.
- */
- class LayersTraceBuffer {
- public:
- size_t size() const { return mSizeInBytes; }
- size_t used() const { return mUsedInBytes; }
- size_t frameCount() const { return mStorage.size(); }
-
- void setSize(size_t newSize) { mSizeInBytes = newSize; }
- void reset(size_t newSize);
- void emplace(LayersTraceProto&& proto);
- void flush(LayersTraceFileProto* fileProto);
-
- private:
- size_t mUsedInBytes = 0U;
- size_t mSizeInBytes = DEFAULT_BUFFER_SIZE;
- std::queue<LayersTraceProto> mStorage;
- };
-
- /*
- * Implements a synchronous way of adding trace entries. This must be called
- * from the drawing thread.
- */
- class Runner {
- public:
- Runner(SurfaceFlinger& flinger, SurfaceTracing::Config& config);
- virtual ~Runner() = default;
- virtual status_t stop();
- virtual status_t writeToFile();
- virtual void notify(const char* where);
- /* Cannot be called with a synchronous runner. */
- virtual void notifyLocked(const char* /* where */) {}
- void dump(std::string& result) const;
-
- protected:
- bool flagIsSet(uint32_t flags) { return (mConfig.flags & flags) == flags; }
- SurfaceFlinger& mFlinger;
- SurfaceTracing::Config mConfig;
- SurfaceTracing::LayersTraceBuffer mBuffer;
- uint32_t mMissedTraceEntries = 0;
- LayersTraceProto traceLayers(const char* where);
- };
-
- /*
- * Implements asynchronous way to add trace entries called from a separate thread while holding
- * the SurfaceFlinger tracing lock. Trace entries may be missed if the tracing thread is not
- * scheduled in time.
- */
- class AsyncRunner : public Runner {
- public:
- AsyncRunner(SurfaceFlinger& flinger, SurfaceTracing::Config& config, std::mutex& sfLock);
- virtual ~AsyncRunner() = default;
- status_t stop() override;
- status_t writeToFile() override;
- void notify(const char* where) override;
- void notifyLocked(const char* where);
-
- private:
- std::mutex& mSfLock;
- std::condition_variable mCanStartTrace;
- std::thread mThread;
- const char* mWhere = "";
- bool mWriteToFile = false;
- bool mEnabled = false;
- bool mAddEntry = false;
- void loop();
- bool traceWhenNotified(LayersTraceProto* outProto);
- };
-};
-
-} // namespace android
diff --git a/services/surfaceflinger/Tracing/LayerTracing.cpp b/services/surfaceflinger/Tracing/LayerTracing.cpp
new file mode 100644
index 0000000..84890ee
--- /dev/null
+++ b/services/surfaceflinger/Tracing/LayerTracing.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "LayerTracing"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <SurfaceFlinger.h>
+#include <android-base/stringprintf.h>
+#include <log/log.h>
+#include <utils/SystemClock.h>
+#include <utils/Trace.h>
+
+#include "LayerTracing.h"
+#include "RingBuffer.h"
+
+namespace android {
+
+LayerTracing::LayerTracing(SurfaceFlinger& flinger) : mFlinger(flinger) {
+ mBuffer = std::make_unique<RingBuffer<LayersTraceFileProto, LayersTraceProto>>();
+}
+
+LayerTracing::~LayerTracing() = default;
+
+bool LayerTracing::enable() {
+ std::scoped_lock lock(mTraceLock);
+ if (mEnabled) {
+ return false;
+ }
+ mBuffer->setSize(mBufferSizeInBytes);
+ mEnabled = true;
+ return true;
+}
+
+bool LayerTracing::disable() {
+ std::scoped_lock lock(mTraceLock);
+ if (!mEnabled) {
+ return false;
+ }
+ mEnabled = false;
+ LayersTraceFileProto fileProto = createTraceFileProto();
+ mBuffer->writeToFile(fileProto, FILE_NAME);
+ return true;
+}
+
+bool LayerTracing::isEnabled() const {
+ std::scoped_lock lock(mTraceLock);
+ return mEnabled;
+}
+
+status_t LayerTracing::writeToFile() {
+ std::scoped_lock lock(mTraceLock);
+ if (!mEnabled) {
+ return STATUS_OK;
+ }
+ LayersTraceFileProto fileProto = createTraceFileProto();
+ return mBuffer->writeToFile(fileProto, FILE_NAME);
+}
+
+void LayerTracing::setTraceFlags(uint32_t flags) {
+ std::scoped_lock lock(mTraceLock);
+ mFlags = flags;
+}
+
+void LayerTracing::setBufferSize(size_t bufferSizeInBytes) {
+ std::scoped_lock lock(mTraceLock);
+ mBufferSizeInBytes = bufferSizeInBytes;
+}
+
+bool LayerTracing::flagIsSet(uint32_t flags) const {
+ return (mFlags & flags) == flags;
+}
+
+LayersTraceFileProto LayerTracing::createTraceFileProto() const {
+ LayersTraceFileProto fileProto;
+ fileProto.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
+ LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
+ 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::notify(const char* where) {
+ ATRACE_CALL();
+ std::scoped_lock lock(mTraceLock);
+ if (!mEnabled) {
+ return;
+ }
+
+ ATRACE_CALL();
+ LayersTraceProto entry;
+ entry.set_elapsed_realtime_nanos(elapsedRealtimeNano());
+ entry.set_where(where);
+ LayersProto layers(mFlinger.dumpDrawingStateProto(mFlags));
+
+ if (flagIsSet(LayerTracing::TRACE_EXTRA)) {
+ mFlinger.dumpOffscreenLayersProto(layers);
+ }
+ entry.mutable_layers()->Swap(&layers);
+
+ if (flagIsSet(LayerTracing::TRACE_HWC)) {
+ std::string hwcDump;
+ mFlinger.dumpHwc(hwcDump);
+ entry.set_hwc_blob(hwcDump);
+ }
+ if (!flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
+ entry.set_excludes_composition_state(true);
+ }
+ mFlinger.dumpDisplayProto(entry);
+ mBuffer->emplace(std::move(entry));
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/Tracing/LayerTracing.h b/services/surfaceflinger/Tracing/LayerTracing.h
new file mode 100644
index 0000000..8ca3587
--- /dev/null
+++ b/services/surfaceflinger/Tracing/LayerTracing.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 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.
+ */
+
+#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;
+
+namespace android {
+
+template <typename FileProto, typename EntryProto>
+class RingBuffer;
+
+class SurfaceFlinger;
+
+/*
+ * LayerTracing records layer states during surface flinging. Manages tracing state and
+ * configuration.
+ */
+class LayerTracing {
+public:
+ LayerTracing(SurfaceFlinger& flinger);
+ ~LayerTracing();
+ bool enable();
+ bool disable();
+ bool isEnabled() const;
+ status_t writeToFile();
+ LayersTraceFileProto createTraceFileProto() const;
+ void notify(const char* where);
+
+ enum : uint32_t {
+ TRACE_INPUT = 1 << 1,
+ TRACE_COMPOSITION = 1 << 2,
+ TRACE_EXTRA = 1 << 3,
+ TRACE_HWC = 1 << 4,
+ TRACE_BUFFERS = 1 << 5,
+ TRACE_ALL = TRACE_INPUT | TRACE_COMPOSITION | TRACE_EXTRA,
+ };
+ void setTraceFlags(uint32_t flags);
+ bool flagIsSet(uint32_t flags) const;
+ void setBufferSize(size_t bufferSizeInBytes);
+ void dump(std::string&) const;
+
+private:
+ static constexpr auto FILE_NAME = "/data/misc/wmtrace/layers_trace.winscope";
+
+ SurfaceFlinger& mFlinger;
+ uint32_t mFlags = TRACE_INPUT;
+ mutable std::mutex mTraceLock;
+ bool mEnabled GUARDED_BY(mTraceLock) = false;
+ std::unique_ptr<RingBuffer<LayersTraceFileProto, LayersTraceProto>> mBuffer
+ GUARDED_BY(mTraceLock);
+ size_t mBufferSizeInBytes GUARDED_BY(mTraceLock) = 20 * 1024 * 1024;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/Tracing/RingBuffer.h b/services/surfaceflinger/Tracing/RingBuffer.h
new file mode 100644
index 0000000..d0fb3f2
--- /dev/null
+++ b/services/surfaceflinger/Tracing/RingBuffer.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+
+#include <log/log.h>
+#include <utils/Errors.h>
+#include <utils/SystemClock.h>
+#include <utils/Trace.h>
+#include <queue>
+
+namespace android {
+
+class SurfaceFlinger;
+
+template <typename FileProto, typename EntryProto>
+class RingBuffer {
+public:
+ size_t size() const { return mSizeInBytes; }
+ size_t used() const { return mUsedInBytes; }
+ size_t frameCount() const { return mStorage.size(); }
+ void setSize(size_t newSize) { mSizeInBytes = newSize; }
+ EntryProto& front() { return mStorage.front(); }
+ const EntryProto& front() const { return mStorage.front(); }
+
+ void reset(size_t newSize) {
+ // use the swap trick to make sure memory is released
+ std::queue<EntryProto>().swap(mStorage);
+ mSizeInBytes = newSize;
+ mUsedInBytes = 0U;
+ }
+ void flush(FileProto& fileProto) {
+ fileProto.mutable_entry()->Reserve(static_cast<int>(mStorage.size()));
+ while (!mStorage.empty()) {
+ auto entry = fileProto.add_entry();
+ entry->Swap(&mStorage.front());
+ mStorage.pop();
+ }
+ }
+
+ status_t writeToFile(FileProto& fileProto, std::string filename) {
+ ATRACE_CALL();
+ std::string output;
+ flush(fileProto);
+ reset(mSizeInBytes);
+ 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.");
+ return PERMISSION_DENIED;
+ }
+ return NO_ERROR;
+ }
+
+ std::vector<EntryProto> emplace(EntryProto&& proto) {
+ std::vector<EntryProto> replacedEntries;
+ size_t protoSize = static_cast<size_t>(proto.ByteSize());
+ while (mUsedInBytes + protoSize > mSizeInBytes) {
+ if (mStorage.empty()) {
+ return {};
+ }
+ mUsedInBytes -= static_cast<size_t>(mStorage.front().ByteSize());
+ replacedEntries.emplace_back(mStorage.front());
+ mStorage.pop();
+ }
+ mUsedInBytes += protoSize;
+ mStorage.emplace();
+ mStorage.back().Swap(&proto);
+ return replacedEntries;
+ }
+
+ void dump(std::string& result) const {
+ std::chrono::milliseconds duration(0);
+ if (frameCount() > 0) {
+ duration = std::chrono::duration_cast<std::chrono::milliseconds>(
+ std::chrono::nanoseconds(systemTime() - front().elapsed_realtime_nanos()));
+ }
+ const int64_t durationCount = duration.count();
+ base::StringAppendF(&result,
+ " number of entries: %zu (%.2fMB / %.2fMB) duration: %" PRIi64 "ms\n",
+ frameCount(), float(used()) / 1024.f * 1024.f,
+ float(size()) / 1024.f * 1024.f, durationCount);
+ }
+
+private:
+ size_t mUsedInBytes = 0U;
+ size_t mSizeInBytes = 0U;
+ std::queue<EntryProto> mStorage;
+};
+
+} // namespace android