Merge "SF: Move/Refactor doComposition and doDisplayComposition to CompositionEngine"
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 438f8f3..51bf78a 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -139,6 +139,7 @@
"DisplayHardware/VirtualDisplaySurface.cpp",
"Effects/Daltonizer.cpp",
"EventLog/EventLog.cpp",
+ "FrameTracer/FrameTracer.cpp",
"FrameTracker.cpp",
"Layer.cpp",
"LayerProtoHelper.cpp",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index a8bdb79..90a02b3 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -51,6 +51,7 @@
#include "Colorizer.h"
#include "DisplayDevice.h"
+#include "FrameTracer/FrameTracer.h"
#include "LayerRejecter.h"
#include "TimeStats/TimeStats.h"
@@ -71,7 +72,9 @@
BufferLayer::~BufferLayer() {
mFlinger->deleteTextureAsync(mTextureName);
- mFlinger->mTimeStats->onDestroy(getSequence());
+ const int32_t layerID = getSequence();
+ mFlinger->mTimeStats->onDestroy(layerID);
+ mFlinger->mFrameTracer->onDestroy(layerID);
}
void BufferLayer::useSurfaceDamage() {
@@ -314,17 +317,17 @@
if (presentFence->isValid()) {
mFlinger->mTimeStats->setPresentFence(layerID, mCurrentFrameNumber, presentFence);
- mFlinger->mTimeStats->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber,
- presentFence, TimeStats::FrameEvent::PRESENT_FENCE);
+ mFlinger->mFrameTracer->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber,
+ presentFence, FrameTracer::FrameEvent::PRESENT_FENCE);
mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
} else if (displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
// The HWC doesn't support present fences, so use the refresh
// timestamp instead.
const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId);
mFlinger->mTimeStats->setPresentTime(layerID, mCurrentFrameNumber, actualPresentTime);
- mFlinger->mTimeStats->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber,
- actualPresentTime,
- TimeStats::FrameEvent::PRESENT_FENCE);
+ mFlinger->mFrameTracer->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber,
+ actualPresentTime,
+ FrameTracer::FrameEvent::PRESENT_FENCE);
mFrameTracker.setActualPresentTime(actualPresentTime);
}
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 6cad3c7..4da39e4 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -29,6 +29,7 @@
#include "LayerRejecter.h"
#include "SurfaceInterceptor.h"
+#include "FrameTracer/FrameTracer.h"
#include "TimeStats/TimeStats.h"
namespace android {
@@ -48,9 +49,9 @@
// Prevent tracing the same release multiple times.
if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) {
- mFlinger->mTimeStats->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber,
- std::make_shared<FenceTime>(releaseFence),
- TimeStats::FrameEvent::RELEASE_FENCE);
+ mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber,
+ std::make_shared<FenceTime>(releaseFence),
+ FrameTracer::FrameEvent::RELEASE_FENCE);
mPreviousReleasedFrameNumber = mPreviousFrameNumber;
}
}
@@ -337,6 +338,7 @@
mQueueItems.clear();
mQueuedFrames = 0;
mFlinger->mTimeStats->onDestroy(layerID);
+ mFlinger->mFrameTracer->onDestroy(layerID);
}
// Once we have hit this state, the shadow queue may no longer
@@ -366,12 +368,12 @@
uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId();
mFlinger->mTimeStats->setAcquireFence(layerID, currentFrameNumber,
mQueueItems[0].mFenceTime);
- mFlinger->mTimeStats->traceFence(layerID, bufferID, currentFrameNumber,
- mQueueItems[0].mFenceTime,
- TimeStats::FrameEvent::ACQUIRE_FENCE);
+ mFlinger->mFrameTracer->traceFence(layerID, bufferID, currentFrameNumber,
+ mQueueItems[0].mFenceTime,
+ FrameTracer::FrameEvent::ACQUIRE_FENCE);
mFlinger->mTimeStats->setLatchTime(layerID, currentFrameNumber, latchTime);
- mFlinger->mTimeStats->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime,
- TimeStats::FrameEvent::LATCH);
+ mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime,
+ FrameTracer::FrameEvent::LATCH);
mQueueItems.removeAt(0);
}
@@ -429,9 +431,9 @@
void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
const int32_t layerID = getSequence();
- mFlinger->mTimeStats->traceNewLayer(layerID, getName().c_str());
- mFlinger->mTimeStats->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber,
- systemTime(), TimeStats::FrameEvent::POST);
+ mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str());
+ mFlinger->mFrameTracer->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber,
+ systemTime(), FrameTracer::FrameEvent::POST);
ATRACE_CALL();
// Add this buffer from our internal queue tracker
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 4a8261d..e7d1b63 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -32,6 +32,7 @@
#include "BufferStateLayer.h"
#include "ColorLayer.h"
+#include "FrameTracer/FrameTracer.h"
#include "TimeStats/TimeStats.h"
namespace android {
@@ -90,9 +91,9 @@
// Prevent tracing the same release multiple times.
if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) {
- mFlinger->mTimeStats->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber,
- std::make_shared<FenceTime>(releaseFence),
- TimeStats::FrameEvent::RELEASE_FENCE);
+ mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber,
+ std::make_shared<FenceTime>(releaseFence),
+ FrameTracer::FrameEvent::RELEASE_FENCE);
mPreviousReleasedFrameNumber = mPreviousFrameNumber;
}
}
@@ -236,9 +237,9 @@
const int32_t layerID = getSequence();
mFlinger->mTimeStats->setPostTime(layerID, mFrameNumber, getName().c_str(), postTime);
- mFlinger->mTimeStats->traceNewLayer(layerID, getName().c_str());
- mFlinger->mTimeStats->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime,
- TimeStats::FrameEvent::POST);
+ mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str());
+ mFlinger->mFrameTracer->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime,
+ FrameTracer::FrameEvent::POST);
mCurrentState.desiredPresentTime = desiredPresentTime;
if (mFlinger->mUseSmart90ForVideo) {
@@ -569,17 +570,18 @@
status_t err = bindTextureImage();
if (err != NO_ERROR) {
mFlinger->mTimeStats->onDestroy(layerID);
+ mFlinger->mFrameTracer->onDestroy(layerID);
return BAD_VALUE;
}
}
const uint64_t bufferID = getCurrentBufferId();
mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, getCurrentFenceTime());
- mFlinger->mTimeStats->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(),
- TimeStats::FrameEvent::ACQUIRE_FENCE);
+ mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(),
+ FrameTracer::FrameEvent::ACQUIRE_FENCE);
mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime);
- mFlinger->mTimeStats->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime,
- TimeStats::FrameEvent::LATCH);
+ mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime,
+ FrameTracer::FrameEvent::LATCH);
mCurrentStateModified = false;
diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.cpp b/services/surfaceflinger/FrameTracer/FrameTracer.cpp
new file mode 100644
index 0000000..7cbb8d8
--- /dev/null
+++ b/services/surfaceflinger/FrameTracer/FrameTracer.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2019 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 "FrameTracer"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "FrameTracer.h"
+
+#include <android-base/stringprintf.h>
+
+#include <algorithm>
+
+PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::FrameTracer::FrameTracerDataSource);
+
+namespace android {
+
+void FrameTracer::initialize() {
+ perfetto::TracingInitArgs args;
+ args.backends = perfetto::kSystemBackend;
+ perfetto::Tracing::Initialize(args);
+ registerDataSource();
+}
+
+void FrameTracer::registerDataSource() {
+ perfetto::DataSourceDescriptor dsd;
+ dsd.set_name(kFrameTracerDataSource);
+ FrameTracerDataSource::Register(dsd);
+}
+
+void FrameTracer::traceNewLayer(int32_t layerID, const std::string& layerName) {
+ FrameTracerDataSource::Trace([this, layerID, &layerName](FrameTracerDataSource::TraceContext) {
+ if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
+ std::lock_guard<std::mutex> lock(mTraceMutex);
+ mTraceTracker[layerID].layerName = layerName;
+ }
+ });
+}
+
+void FrameTracer::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
+ nsecs_t timestamp, FrameEvent::BufferEventType type,
+ nsecs_t duration) {
+ FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type,
+ duration](FrameTracerDataSource::TraceContext ctx) {
+ std::lock_guard<std::mutex> lock(mTraceMutex);
+ if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
+ return;
+ }
+
+ // Handle any pending fences for this buffer.
+ tracePendingFencesLocked(ctx, layerID, bufferID);
+
+ // Complete current trace.
+ traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration);
+ });
+}
+
+void FrameTracer::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
+ const std::shared_ptr<FenceTime>& fence,
+ FrameEvent::BufferEventType type, nsecs_t startTime) {
+ FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type,
+ startTime](FrameTracerDataSource::TraceContext ctx) {
+ const nsecs_t signalTime = fence->getSignalTime();
+ if (signalTime != Fence::SIGNAL_TIME_INVALID) {
+ std::lock_guard<std::mutex> lock(mTraceMutex);
+ if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
+ return;
+ }
+
+ // Handle any pending fences for this buffer.
+ tracePendingFencesLocked(ctx, layerID, bufferID);
+
+ if (signalTime != Fence::SIGNAL_TIME_PENDING) {
+ traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime);
+ } else {
+ mTraceTracker[layerID].pendingFences[bufferID].push_back(
+ {.frameNumber = frameNumber,
+ .type = type,
+ .fence = fence,
+ .startTime = startTime});
+ }
+ }
+ });
+}
+
+void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx,
+ int32_t layerID, uint64_t bufferID) {
+ if (mTraceTracker[layerID].pendingFences.count(bufferID)) {
+ auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID];
+ for (size_t i = 0; i < pendingFences.size(); ++i) {
+ auto& pendingFence = pendingFences[i];
+
+ nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
+ if (pendingFence.fence && pendingFence.fence->isValid()) {
+ signalTime = pendingFence.fence->getSignalTime();
+ if (signalTime == Fence::SIGNAL_TIME_PENDING) {
+ continue;
+ }
+ }
+
+ if (signalTime != Fence::SIGNAL_TIME_INVALID &&
+ systemTime() - signalTime < kFenceSignallingDeadline) {
+ traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type,
+ pendingFence.startTime, signalTime);
+ }
+
+ pendingFences.erase(pendingFences.begin() + i);
+ --i;
+ }
+ }
+}
+
+void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID,
+ uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
+ FrameEvent::BufferEventType type, nsecs_t duration) {
+ auto packet = ctx.NewTracePacket();
+ packet->set_timestamp(timestamp);
+ auto* event = packet->set_graphics_frame_event()->set_buffer_event();
+ event->set_buffer_id(static_cast<uint32_t>(bufferID));
+ event->set_frame_number(frameNumber);
+ event->set_type(type);
+
+ if (mTraceTracker.find(layerID) != mTraceTracker.end() &&
+ !mTraceTracker[layerID].layerName.empty()) {
+ const std::string& layerName = mTraceTracker[layerID].layerName;
+ event->set_layer_name(layerName.c_str(), layerName.size());
+ }
+
+ if (duration > 0) {
+ event->set_duration_ns(duration);
+ }
+}
+
+void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID,
+ uint64_t bufferID, uint64_t frameNumber,
+ FrameEvent::BufferEventType type, nsecs_t startTime,
+ nsecs_t endTime) {
+ nsecs_t timestamp = endTime;
+ nsecs_t duration = 0;
+ if (startTime > 0 && startTime < endTime) {
+ timestamp = startTime;
+ duration = endTime - startTime;
+ }
+ traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration);
+}
+
+void FrameTracer::onDestroy(int32_t layerID) {
+ std::lock_guard<std::mutex> traceLock(mTraceMutex);
+ mTraceTracker.erase(layerID);
+}
+
+std::string FrameTracer::miniDump() {
+ std::string result = "FrameTracer miniDump:\n";
+ std::lock_guard<std::mutex> lock(mTraceMutex);
+ android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n",
+ mTraceTracker.size());
+ return result;
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.h b/services/surfaceflinger/FrameTracer/FrameTracer.h
new file mode 100644
index 0000000..d34ad81
--- /dev/null
+++ b/services/surfaceflinger/FrameTracer/FrameTracer.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2019 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 <perfetto/trace/android/graphics_frame_event.pbzero.h>
+#include <perfetto/tracing.h>
+#include <ui/FenceTime.h>
+
+#include <mutex>
+#include <unordered_map>
+
+namespace android {
+
+class FrameTracer {
+public:
+ class FrameTracerDataSource : public perfetto::DataSource<FrameTracerDataSource> {
+ virtual void OnSetup(const SetupArgs&) override{};
+ virtual void OnStart(const StartArgs&) override{};
+ virtual void OnStop(const StopArgs&) override{};
+ };
+
+ using FrameEvent = perfetto::protos::pbzero::GraphicsFrameEvent;
+
+ ~FrameTracer() = default;
+
+ // Sets up the perfetto tracing backend and data source.
+ void initialize();
+ // Registers the data source with the perfetto backend. Called as part of initialize()
+ // and should not be called manually outside of tests. Public to allow for substituting a
+ // perfetto::kInProcessBackend in tests.
+ void registerDataSource();
+ // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or
+ // traceFence() for each layer.
+ void traceNewLayer(int32_t layerID, const std::string& layerName);
+ // Creates a trace point at the timestamp provided.
+ void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
+ FrameEvent::BufferEventType type, nsecs_t duration = 0);
+ // Creates a trace point after the provided fence has been signalled. If a startTime is provided
+ // the trace will have be timestamped from startTime until fence signalling time. If no
+ // startTime is provided, a durationless trace point will be created timestamped at fence
+ // signalling time. If the fence hasn't signalled yet, the trace point will be created the next
+ // time after signalling a trace call for this buffer occurs.
+ void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
+ const std::shared_ptr<FenceTime>& fence, FrameEvent::BufferEventType type,
+ nsecs_t startTime = 0);
+
+ // Takes care of cleanup when a layer is destroyed.
+ void onDestroy(int32_t layerID);
+
+ std::string miniDump();
+
+ static constexpr char kFrameTracerDataSource[] = "android.surfaceflinger.frame";
+
+ // The maximum amount of time a fence has to signal before it is discarded.
+ // Used to avoid fences from previous traces generating new trace points in later ones.
+ // Public for testing.
+ static constexpr nsecs_t kFenceSignallingDeadline = 60'000'000'000; // 60 seconds
+
+private:
+ struct PendingFence {
+ uint64_t frameNumber;
+ FrameEvent::BufferEventType type;
+ std::shared_ptr<FenceTime> fence;
+ nsecs_t startTime;
+ };
+
+ struct TraceRecord {
+ std::string layerName;
+ using BufferID = uint64_t;
+ std::unordered_map<BufferID, std::vector<PendingFence>> pendingFences;
+ };
+
+ // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates
+ // trace points for them.
+ void tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID,
+ uint64_t bufferID);
+ // Creates a trace point by translating a start time and an end time to a timestamp and
+ // duration. If startTime is later than end time it sets end time as the timestamp and the
+ // duration to 0. Used by traceFence().
+ void traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID,
+ uint64_t bufferID, uint64_t frameNumber, FrameEvent::BufferEventType type,
+ nsecs_t startTime, nsecs_t endTime);
+ void traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID,
+ uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type,
+ nsecs_t duration = 0);
+
+ std::mutex mTraceMutex;
+ std::unordered_map<int32_t, TraceRecord> mTraceTracker;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 5121835..106d505 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -57,6 +57,7 @@
#include "Colorizer.h"
#include "DisplayDevice.h"
#include "DisplayHardware/HWComposer.h"
+#include "FrameTracer/FrameTracer.h"
#include "LayerProtoHelper.h"
#include "LayerRejecter.h"
#include "MonitoredProducer.h"
@@ -1343,7 +1344,9 @@
void Layer::onDisconnect() {
Mutex::Autolock lock(mFrameEventHistoryMutex);
mFrameEventHistory.onDisconnect();
- mFlinger->mTimeStats->onDestroy(getSequence());
+ const int32_t layerID = getSequence();
+ mFlinger->mTimeStats->onDestroy(layerID);
+ mFlinger->mFrameTracer->onDestroy(layerID);
}
void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1875151..0eac1a7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -98,6 +98,7 @@
#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/VirtualDisplaySurface.h"
#include "Effects/Daltonizer.h"
+#include "FrameTracer/FrameTracer.h"
#include "RegionSamplingThread.h"
#include "Scheduler/DispSync.h"
#include "Scheduler/DispSyncSource.h"
@@ -257,6 +258,7 @@
: mFactory(factory),
mInterceptor(mFactory.createSurfaceInterceptor(this)),
mTimeStats(mFactory.createTimeStats()),
+ mFrameTracer(std::make_unique<FrameTracer>()),
mEventQueue(mFactory.createMessageQueue()),
mCompositionEngine(mFactory.createCompositionEngine()),
mPhaseOffsets(mFactory.createPhaseOffsets()) {}
@@ -513,7 +515,7 @@
const nsecs_t duration = now - mBootTime;
ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
- mTimeStats->initializeTracing();
+ mFrameTracer->initialize();
// wait patiently for the window manager death
const String16 name("window");
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 9acd975..3c1fc82 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -94,6 +94,7 @@
class RefreshRateOverlay;
class RegionSamplingThread;
class TimeStats;
+class FrameTracer;
namespace compositionengine {
class DisplaySurface;
@@ -993,6 +994,7 @@
bool mTracingEnabled = false;
bool mTracingEnabledChanged GUARDED_BY(mStateLock) = false;
const std::shared_ptr<TimeStats> mTimeStats;
+ const std::unique_ptr<FrameTracer> mFrameTracer;
bool mUseHwcVirtualDisplays = false;
std::atomic<uint32_t> mFrameMissedCount = 0;
std::atomic<uint32_t> mHwcFrameMissedCount = 0;
diff --git a/services/surfaceflinger/TimeStats/Android.bp b/services/surfaceflinger/TimeStats/Android.bp
index 9e1d503..2080a38 100644
--- a/services/surfaceflinger/TimeStats/Android.bp
+++ b/services/surfaceflinger/TimeStats/Android.bp
@@ -2,12 +2,9 @@
name: "libtimestats",
defaults: ["surfaceflinger_defaults"],
srcs: [
- "TimeStats.cpp"
+ "TimeStats.cpp",
],
export_include_dirs: ["."],
- static_libs: [
- "libperfetto_client_experimental",
- ],
shared_libs: [
"libtimestats_proto",
"libui",
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index b66e4cf..b01fa81 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -30,141 +30,10 @@
#include <algorithm>
#include <regex>
-PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::impl::TimeStats::TimeStatsDataSource);
-
namespace android {
namespace impl {
-void TimeStats::initializeTracing() {
- perfetto::TracingInitArgs args;
- args.backends = perfetto::kSystemBackend;
- perfetto::Tracing::Initialize(args);
- registerTracingDataSource();
-}
-
-void TimeStats::registerTracingDataSource() {
- perfetto::DataSourceDescriptor dsd;
- dsd.set_name(kTimeStatsDataSource);
- TimeStatsDataSource::Register(dsd);
-}
-
-void TimeStats::traceNewLayer(int32_t layerID, const std::string& layerName) {
- TimeStatsDataSource::Trace([this, layerID, &layerName](TimeStatsDataSource::TraceContext) {
- if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
- std::lock_guard<std::mutex> lock(mTraceMutex);
- mTraceTracker[layerID].layerName = layerName;
- }
- });
-}
-
-void TimeStats::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
- nsecs_t timestamp, FrameEvent::BufferEventType type,
- nsecs_t duration) {
- TimeStatsDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type,
- duration](TimeStatsDataSource::TraceContext ctx) {
- std::lock_guard<std::mutex> lock(mTraceMutex);
- if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
- return;
- }
-
- // Handle any pending fences for this buffer.
- tracePendingFencesLocked(ctx, layerID, bufferID);
-
- // Complete current trace.
- traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration);
- });
-}
-
-void TimeStats::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
- const std::shared_ptr<FenceTime>& fence,
- FrameEvent::BufferEventType type, nsecs_t startTime) {
- TimeStatsDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type,
- startTime](TimeStatsDataSource::TraceContext ctx) {
- const nsecs_t signalTime = fence->getSignalTime();
- if (signalTime != Fence::SIGNAL_TIME_INVALID) {
- std::lock_guard<std::mutex> lock(mTraceMutex);
- if (mTraceTracker.find(layerID) == mTraceTracker.end()) {
- return;
- }
-
- // Handle any pending fences for this buffer.
- tracePendingFencesLocked(ctx, layerID, bufferID);
-
- if (signalTime != Fence::SIGNAL_TIME_PENDING) {
- traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime);
- } else {
- mTraceTracker[layerID].pendingFences[bufferID].push_back(
- {.frameNumber = frameNumber,
- .type = type,
- .fence = fence,
- .startTime = startTime});
- }
- }
- });
-}
-
-void TimeStats::tracePendingFencesLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID,
- uint64_t bufferID) {
- if (mTraceTracker[layerID].pendingFences.count(bufferID)) {
- auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID];
- for (size_t i = 0; i < pendingFences.size(); ++i) {
- auto& pendingFence = pendingFences[i];
-
- nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
- if (pendingFence.fence && pendingFence.fence->isValid()) {
- signalTime = pendingFence.fence->getSignalTime();
- if (signalTime == Fence::SIGNAL_TIME_PENDING) {
- continue;
- }
- }
-
- if (signalTime != Fence::SIGNAL_TIME_INVALID &&
- systemTime() - signalTime < kFenceSignallingDeadline) {
- traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type,
- pendingFence.startTime, signalTime);
- }
-
- pendingFences.erase(pendingFences.begin() + i);
- --i;
- }
- }
-}
-
-void TimeStats::traceLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID,
- uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
- FrameEvent::BufferEventType type, nsecs_t duration) {
- auto packet = ctx.NewTracePacket();
- packet->set_timestamp(timestamp);
- auto* event = packet->set_graphics_frame_event()->set_buffer_event();
- event->set_buffer_id(static_cast<uint32_t>(bufferID));
- event->set_frame_number(frameNumber);
- event->set_type(type);
-
- if (mTraceTracker.find(layerID) != mTraceTracker.end() &&
- !mTraceTracker[layerID].layerName.empty()) {
- const std::string& layerName = mTraceTracker[layerID].layerName;
- event->set_layer_name(layerName.c_str(), layerName.size());
- }
-
- if (duration > 0) {
- event->set_duration_ns(duration);
- }
-}
-
-void TimeStats::traceSpanLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID,
- uint64_t bufferID, uint64_t frameNumber,
- FrameEvent::BufferEventType type, nsecs_t startTime,
- nsecs_t endTime) {
- nsecs_t timestamp = endTime;
- nsecs_t duration = 0;
- if (startTime > 0 && startTime < endTime) {
- timestamp = startTime;
- duration = endTime - startTime;
- }
- traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration);
-}
-
void TimeStats::parseArgs(bool asProto, const Vector<String16>& args, std::string& result) {
ATRACE_CALL();
@@ -207,8 +76,6 @@
mTimeStatsTracker.size());
android::base::StringAppendF(&result, "Number of layers in the stats pool is %zu\n",
mTimeStats.stats.size());
- android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n",
- mTraceTracker.size());
return result;
}
@@ -542,15 +409,8 @@
void TimeStats::onDestroy(int32_t layerID) {
ATRACE_CALL();
ALOGV("[%d]-onDestroy", layerID);
- {
- std::lock_guard<std::mutex> lock(mMutex);
- mTimeStatsTracker.erase(layerID);
- }
-
- {
- std::lock_guard<std::mutex> traceLock(mTraceMutex);
- mTraceTracker.erase(layerID);
- }
+ std::lock_guard<std::mutex> lock(mMutex);
+ mTimeStatsTracker.erase(layerID);
}
void TimeStats::removeTimeRecord(int32_t layerID, uint64_t frameNumber) {
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index 470137a..9ebc1ad 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -17,8 +17,6 @@
#pragma once
#include <hardware/hwcomposer_defs.h>
-#include <perfetto/trace/android/graphics_frame_event.pbzero.h>
-#include <perfetto/tracing.h>
#include <timestatsproto/TimeStatsHelper.h>
#include <timestatsproto/TimeStatsProtoHeader.h>
#include <ui/FenceTime.h>
@@ -36,32 +34,8 @@
class TimeStats {
public:
- using FrameEvent = perfetto::protos::pbzero::GraphicsFrameEvent;
-
virtual ~TimeStats() = default;
- // Sets up the perfetto tracing backend and data source.
- virtual void initializeTracing() = 0;
- // Registers the data source with the perfetto backend. Called as part of initializeTracing()
- // and should not be called manually outside of tests. Public to allow for substituting a
- // perfetto::kInProcessBackend in tests.
- virtual void registerTracingDataSource() = 0;
- // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or
- // traceFence() for each layer.
- virtual void traceNewLayer(int32_t layerID, const std::string& layerName) = 0;
- // Creates a trace point at the timestamp provided.
- virtual void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
- nsecs_t timestamp, FrameEvent::BufferEventType type,
- nsecs_t duration = 0) = 0;
- // Creates a trace point after the provided fence has been signalled. If a startTime is provided
- // the trace will have be timestamped from startTime until fence signalling time. If no
- // startTime is provided, a durationless trace point will be created timestamped at fence
- // signalling time. If the fence hasn't signalled yet, the trace point will be created the next
- // time after signalling a trace call for this buffer occurs.
- virtual void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
- const std::shared_ptr<FenceTime>& fence,
- FrameEvent::BufferEventType type, nsecs_t startTime = 0) = 0;
-
virtual void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) = 0;
virtual bool isEnabled() = 0;
virtual std::string miniDump() = 0;
@@ -89,13 +63,6 @@
// Source of truth is RefrehRateStats.
virtual void recordRefreshRate(uint32_t fps, nsecs_t duration) = 0;
virtual void setPresentFenceGlobal(const std::shared_ptr<FenceTime>& presentFence) = 0;
-
- static constexpr char kTimeStatsDataSource[] = "android.surfaceflinger.timestats";
-
- // The maximum amount of time a fence has to signal before it is discarded.
- // Used to avoid fence's from previous traces generating new trace points in later ones.
- // Public for testing.
- static constexpr nsecs_t kFenceSignallingDeadline = 60'000'000'000; // 60 seconds
};
namespace impl {
@@ -117,13 +84,6 @@
std::shared_ptr<FenceTime> presentFence;
};
- struct PendingFence {
- uint64_t frameNumber;
- FrameEvent::BufferEventType type;
- std::shared_ptr<FenceTime> fence;
- nsecs_t startTime;
- };
-
struct LayerRecord {
std::string layerName;
// This is the index in timeRecords, at which the timestamps for that
@@ -135,12 +95,6 @@
std::deque<TimeRecord> timeRecords;
};
- struct TraceRecord {
- std::string layerName;
- using BufferID = uint64_t;
- std::unordered_map<BufferID, std::vector<PendingFence>> pendingFences;
- };
-
struct PowerTime {
int32_t powerMode = HWC_POWER_MODE_OFF;
nsecs_t prevTime = 0;
@@ -152,23 +106,8 @@
};
public:
- class TimeStatsDataSource : public perfetto::DataSource<TimeStatsDataSource> {
- virtual void OnSetup(const SetupArgs&) override{};
- virtual void OnStart(const StartArgs&) override { ALOGV("TimeStats trace started"); };
- virtual void OnStop(const StopArgs&) override { ALOGV("TimeStats trace stopped"); };
- };
-
TimeStats() = default;
- void initializeTracing() override;
- void registerTracingDataSource() override;
- void traceNewLayer(int32_t layerID, const std::string& layerName) override;
- void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp,
- FrameEvent::BufferEventType type, nsecs_t duration = 0) override;
- void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber,
- const std::shared_ptr<FenceTime>& fence, FrameEvent::BufferEventType type,
- nsecs_t startTime = 0) override;
-
void parseArgs(bool asProto, const Vector<String16>& args, std::string& result) override;
bool isEnabled() override;
std::string miniDump() override;
@@ -200,20 +139,6 @@
static const size_t MAX_NUM_TIME_RECORDS = 64;
private:
- // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates
- // trace points for them.
- void tracePendingFencesLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID,
- uint64_t bufferID);
- // Creates a trace point by translating a start time and an end time to a timestamp and
- // duration. If startTime is later than end time it sets end time as the timestamp and the
- // duration to 0. Used by traceFence().
- void traceSpanLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID,
- uint64_t frameNumber, FrameEvent::BufferEventType type, nsecs_t startTime,
- nsecs_t endTime);
- void traceLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID,
- uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type,
- nsecs_t duration = 0);
-
bool recordReadyLocked(int32_t layerID, TimeRecord* timeRecord);
void flushAvailableRecordsToStatsLocked(int32_t layerID);
void flushPowerTimeLocked();
@@ -232,9 +157,6 @@
PowerTime mPowerTime;
GlobalRecord mGlobalRecord;
- std::mutex mTraceMutex;
- std::unordered_map<int32_t, TraceRecord> mTraceTracker;
-
static const size_t MAX_NUM_LAYER_RECORDS = 200;
static const size_t MAX_NUM_LAYER_STATS = 200;
};
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 0eedf9b..8d98af6 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -51,6 +51,7 @@
"RefreshRateStatsTest.cpp",
"RegionSamplingTest.cpp",
"TimeStatsTest.cpp",
+ "FrameTracerTest.cpp",
"mock/DisplayHardware/MockComposer.cpp",
"mock/DisplayHardware/MockDisplay.cpp",
"mock/DisplayHardware/MockPowerAdvisor.cpp",
@@ -63,6 +64,7 @@
"mock/MockNativeWindowSurface.cpp",
"mock/MockSurfaceInterceptor.cpp",
"mock/MockTimeStats.cpp",
+ "mock/MockFrameTracer.cpp",
"mock/system/window/MockNativeWindow.cpp",
],
static_libs: [
diff --git a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp
new file mode 100644
index 0000000..b5af591
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp
@@ -0,0 +1,396 @@
+/*
+ * Copyright 2019 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 "LibSurfaceFlingerUnittests"
+
+#include <FrameTracer/FrameTracer.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <perfetto/trace/trace.pb.h>
+
+#include "libsurfaceflinger_unittest_main.h"
+
+using namespace google::protobuf;
+
+namespace android {
+namespace {
+
+class FrameTracerTest : public testing::Test {
+public:
+ FrameTracerTest() {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+
+ // Need to initialize tracing in process for testing, and only once per test suite.
+ static bool wasInitialized = false;
+ if (!wasInitialized) {
+ perfetto::TracingInitArgs args;
+ args.backends = perfetto::kInProcessBackend;
+ perfetto::Tracing::Initialize(args);
+ wasInitialized = true;
+ }
+ }
+
+ ~FrameTracerTest() {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
+ }
+
+ void SetUp() override {
+ mFrameTracer = std::make_unique<FrameTracer>();
+ mFrameTracer->registerDataSource();
+ }
+
+ void TearDown() override { mFrameTracer.reset(); }
+
+ // Each tracing session can be used for a single block of Start -> Stop.
+ static std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest() {
+ perfetto::TraceConfig cfg;
+ cfg.set_duration_ms(500);
+ cfg.add_buffers()->set_size_kb(1024);
+ auto* ds_cfg = cfg.add_data_sources()->mutable_config();
+ ds_cfg->set_name(FrameTracer::kFrameTracerDataSource);
+
+ auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend);
+ tracingSession->Setup(cfg);
+ return tracingSession;
+ }
+
+ std::unique_ptr<FrameTracer> mFrameTracer;
+ FenceToFenceTimeMap fenceFactory;
+};
+
+TEST_F(FrameTracerTest, traceNewLayerStartsTrackingLayerWhenTracing) {
+ EXPECT_EQ(mFrameTracer->miniDump(),
+ "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n");
+
+ const std::string layerName = "co.layername#0";
+ const int32_t layerID = 5;
+ mFrameTracer->traceNewLayer(layerID, layerName);
+
+ EXPECT_EQ(mFrameTracer->miniDump(),
+ "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n");
+
+ auto tracingSession = getTracingSessionForTest();
+ tracingSession->StartBlocking();
+ EXPECT_EQ(mFrameTracer->miniDump(),
+ "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n");
+ mFrameTracer->traceNewLayer(layerID, layerName);
+ EXPECT_EQ(mFrameTracer->miniDump(),
+ "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n");
+ tracingSession->StopBlocking();
+}
+
+TEST_F(FrameTracerTest, onDestroyRemovesTheTrackedLayer) {
+ EXPECT_EQ(mFrameTracer->miniDump(),
+ "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n");
+
+ const std::string layerName = "co.layername#0";
+ const int32_t layerID = 5;
+ const int32_t secondLayerID = 6;
+
+ auto tracingSession = getTracingSessionForTest();
+ tracingSession->StartBlocking();
+ mFrameTracer->traceNewLayer(layerID, layerName);
+ mFrameTracer->traceNewLayer(secondLayerID, layerName);
+ EXPECT_EQ(mFrameTracer->miniDump(),
+ "FrameTracer miniDump:\nNumber of layers currently being traced is 2\n");
+ tracingSession->StopBlocking();
+
+ mFrameTracer->onDestroy(layerID);
+ EXPECT_EQ(mFrameTracer->miniDump(),
+ "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n");
+ mFrameTracer->onDestroy(layerID);
+ EXPECT_EQ(mFrameTracer->miniDump(),
+ "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n");
+ mFrameTracer->onDestroy(secondLayerID);
+ EXPECT_EQ(mFrameTracer->miniDump(),
+ "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n");
+}
+
+TEST_F(FrameTracerTest, canTraceAfterAddingLayer) {
+ const std::string layerName = "co.layername#0";
+ const int32_t layerID = 1;
+ const uint32_t bufferID = 2;
+ const uint64_t frameNumber = 3;
+ const nsecs_t timestamp = 4;
+ const nsecs_t duration = 5;
+ const auto type = FrameTracer::FrameEvent::POST;
+
+ {
+ auto tracingSession = getTracingSessionForTest();
+
+ tracingSession->StartBlocking();
+ // Clean up irrelevant traces.
+ tracingSession->ReadTraceBlocking();
+
+ mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration);
+ // Create second trace packet to finalize the previous one.
+ mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+ tracingSession->StopBlocking();
+
+ std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+ EXPECT_EQ(raw_trace.size(), 0);
+ }
+
+ {
+ auto tracingSession = getTracingSessionForTest();
+
+ tracingSession->StartBlocking();
+ // Clean up irrelevant traces.
+ tracingSession->ReadTraceBlocking();
+
+ mFrameTracer->traceNewLayer(layerID, layerName);
+ mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration);
+ // Create second trace packet to finalize the previous one.
+ mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+ tracingSession->StopBlocking();
+
+ std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+ ASSERT_GT(raw_trace.size(), 0);
+
+ perfetto::protos::Trace trace;
+ ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+ ASSERT_FALSE(trace.packet().empty());
+ EXPECT_EQ(trace.packet().size(), 1);
+
+ const auto& packet = trace.packet().Get(0);
+ ASSERT_TRUE(packet.has_timestamp());
+ EXPECT_EQ(packet.timestamp(), timestamp);
+ ASSERT_TRUE(packet.has_graphics_frame_event());
+ const auto& frame_event = packet.graphics_frame_event();
+ ASSERT_TRUE(frame_event.has_buffer_event());
+ const auto& buffer_event = frame_event.buffer_event();
+ ASSERT_TRUE(buffer_event.has_buffer_id());
+ EXPECT_EQ(buffer_event.buffer_id(), bufferID);
+ ASSERT_TRUE(buffer_event.has_frame_number());
+ EXPECT_EQ(buffer_event.frame_number(), frameNumber);
+ ASSERT_TRUE(buffer_event.has_type());
+ EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type));
+ ASSERT_TRUE(buffer_event.has_duration_ns());
+ EXPECT_EQ(buffer_event.duration_ns(), duration);
+ }
+}
+
+TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) {
+ const std::string layerName = "co.layername#0";
+ const int32_t layerID = 5;
+ const uint32_t bufferID = 4;
+ const uint64_t frameNumber = 3;
+ const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE;
+
+ {
+ auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ fenceFactory.signalAllForTest(Fence::NO_FENCE, Fence::SIGNAL_TIME_PENDING);
+ auto tracingSession = getTracingSessionForTest();
+ tracingSession->StartBlocking();
+ // Clean up irrelevant traces.
+ tracingSession->ReadTraceBlocking();
+ // Trace.
+ mFrameTracer->traceNewLayer(layerID, layerName);
+ mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type);
+ // Create extra trace packet to (hopefully not) trigger and finalize the fence packet.
+ mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+ tracingSession->StopBlocking();
+ std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+ EXPECT_EQ(raw_trace.size(), 0);
+ }
+
+ {
+ auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ auto tracingSession = getTracingSessionForTest();
+ tracingSession->StartBlocking();
+ // Clean up irrelevant traces.
+ tracingSession->ReadTraceBlocking();
+ mFrameTracer->traceNewLayer(layerID, layerName);
+ mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type);
+ const nsecs_t timestamp = systemTime();
+ fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp);
+ // Create extra trace packet to trigger and finalize fence trace packets.
+ mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+ tracingSession->StopBlocking();
+
+ std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+ ASSERT_GT(raw_trace.size(), 0);
+
+ perfetto::protos::Trace trace;
+ ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+ ASSERT_FALSE(trace.packet().empty());
+ EXPECT_EQ(trace.packet().size(), 2); // Two packets because of the extra trace made above.
+
+ const auto& packet = trace.packet().Get(1);
+ ASSERT_TRUE(packet.has_timestamp());
+ EXPECT_EQ(packet.timestamp(), timestamp);
+ ASSERT_TRUE(packet.has_graphics_frame_event());
+ const auto& frame_event = packet.graphics_frame_event();
+ ASSERT_TRUE(frame_event.has_buffer_event());
+ const auto& buffer_event = frame_event.buffer_event();
+ ASSERT_TRUE(buffer_event.has_buffer_id());
+ EXPECT_EQ(buffer_event.buffer_id(), bufferID);
+ ASSERT_TRUE(buffer_event.has_frame_number());
+ EXPECT_EQ(buffer_event.frame_number(), frameNumber);
+ ASSERT_TRUE(buffer_event.has_type());
+ EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type));
+ EXPECT_FALSE(buffer_event.has_duration_ns());
+ }
+}
+
+TEST_F(FrameTracerTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) {
+ const std::string layerName = "co.layername#0";
+ const int32_t layerID = 5;
+ const uint32_t bufferID = 4;
+ const uint64_t frameNumber = 3;
+ const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE;
+
+ auto tracingSession = getTracingSessionForTest();
+
+ tracingSession->StartBlocking();
+ // Clean up irrelevant traces.
+ tracingSession->ReadTraceBlocking();
+ mFrameTracer->traceNewLayer(layerID, layerName);
+
+ // traceFence called after fence signalled.
+ const nsecs_t signalTime1 = systemTime();
+ const nsecs_t startTime1 = signalTime1 + 100000;
+ auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1);
+ mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1);
+
+ // traceFence called before fence signalled.
+ const nsecs_t signalTime2 = systemTime();
+ const nsecs_t startTime2 = signalTime2 + 100000;
+ auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2);
+ fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2);
+
+ // Create extra trace packet to trigger and finalize fence trace packets.
+ mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+ tracingSession->StopBlocking();
+
+ std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+ ASSERT_GT(raw_trace.size(), 0);
+
+ perfetto::protos::Trace trace;
+ ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+ ASSERT_FALSE(trace.packet().empty());
+ EXPECT_EQ(trace.packet().size(), 2);
+
+ const auto& packet1 = trace.packet().Get(0);
+ ASSERT_TRUE(packet1.has_timestamp());
+ EXPECT_EQ(packet1.timestamp(), signalTime1);
+ ASSERT_TRUE(packet1.has_graphics_frame_event());
+ ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event());
+ ASSERT_FALSE(packet1.graphics_frame_event().buffer_event().has_duration_ns());
+
+ const auto& packet2 = trace.packet().Get(1);
+ ASSERT_TRUE(packet2.has_timestamp());
+ EXPECT_EQ(packet2.timestamp(), signalTime2);
+ ASSERT_TRUE(packet2.has_graphics_frame_event());
+ ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event());
+ ASSERT_FALSE(packet2.graphics_frame_event().buffer_event().has_duration_ns());
+}
+
+TEST_F(FrameTracerTest, traceFenceOlderThanDeadline_ShouldBeIgnored) {
+ const std::string layerName = "co.layername#0";
+ const int32_t layerID = 5;
+ const uint32_t bufferID = 4;
+ const uint64_t frameNumber = 3;
+ const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE;
+ const nsecs_t signalTime = systemTime() - FrameTracer::kFenceSignallingDeadline;
+
+ auto tracingSession = getTracingSessionForTest();
+ auto fence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+
+ tracingSession->StartBlocking();
+ // Clean up irrelevant traces.
+ tracingSession->ReadTraceBlocking();
+ mFrameTracer->traceNewLayer(layerID, layerName);
+ mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence, type);
+ fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime);
+ // Create extra trace packet to trigger and finalize any previous fence packets.
+ mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+ tracingSession->StopBlocking();
+
+ std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+ EXPECT_EQ(raw_trace.size(), 0);
+}
+
+TEST_F(FrameTracerTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) {
+ const std::string layerName = "co.layername#0";
+ const int32_t layerID = 5;
+ const uint32_t bufferID = 4;
+ const uint64_t frameNumber = 3;
+ const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE;
+ const nsecs_t duration = 1234;
+
+ auto tracingSession = getTracingSessionForTest();
+
+ tracingSession->StartBlocking();
+ // Clean up irrelevant traces.
+ tracingSession->ReadTraceBlocking();
+ mFrameTracer->traceNewLayer(layerID, layerName);
+
+ // traceFence called after fence signalled.
+ const nsecs_t signalTime1 = systemTime();
+ const nsecs_t startTime1 = signalTime1 - duration;
+ auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1);
+ mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1);
+
+ // traceFence called before fence signalled.
+ const nsecs_t signalTime2 = systemTime();
+ const nsecs_t startTime2 = signalTime2 - duration;
+ auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2);
+ fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2);
+
+ // Create extra trace packet to trigger and finalize fence trace packets.
+ mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED);
+ tracingSession->StopBlocking();
+
+ std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
+ ASSERT_GT(raw_trace.size(), 0);
+
+ perfetto::protos::Trace trace;
+ ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
+ ASSERT_FALSE(trace.packet().empty());
+ EXPECT_EQ(trace.packet().size(), 2);
+
+ const auto& packet1 = trace.packet().Get(0);
+ ASSERT_TRUE(packet1.has_timestamp());
+ EXPECT_EQ(packet1.timestamp(), startTime1);
+ ASSERT_TRUE(packet1.has_graphics_frame_event());
+ ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event());
+ ASSERT_TRUE(packet1.graphics_frame_event().buffer_event().has_duration_ns());
+ const auto& buffer_event1 = packet1.graphics_frame_event().buffer_event();
+ EXPECT_EQ(buffer_event1.duration_ns(), duration);
+
+ const auto& packet2 = trace.packet().Get(1);
+ ASSERT_TRUE(packet2.has_timestamp());
+ EXPECT_EQ(packet2.timestamp(), startTime2);
+ ASSERT_TRUE(packet2.has_graphics_frame_event());
+ ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event());
+ ASSERT_TRUE(packet2.graphics_frame_event().buffer_event().has_duration_ns());
+ const auto& buffer_event2 = packet2.graphics_frame_event().buffer_event();
+ EXPECT_EQ(buffer_event2.duration_ns(), duration);
+}
+
+} // namespace
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
index f01e603..ffacbfe 100644
--- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
@@ -20,8 +20,8 @@
#include <TimeStats/TimeStats.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+
#include <log/log.h>
-#include <perfetto/trace/trace.pb.h>
#include <utils/String16.h>
#include <utils/Vector.h>
@@ -109,15 +109,6 @@
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
-
- // Need to initialize tracing in process for testing, and only once per test suite.
- static bool wasInitialized = false;
- if (!wasInitialized) {
- perfetto::TracingInitArgs args;
- args.backends = perfetto::kInProcessBackend;
- perfetto::Tracing::Initialize(args);
- wasInitialized = true;
- }
}
~TimeStatsTest() {
@@ -126,13 +117,6 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
- void SetUp() override {
- mTimeStats = std::make_unique<impl::TimeStats>();
- mTimeStats->registerTracingDataSource();
- }
-
- void TearDown() override { mTimeStats.reset(); }
-
std::string inputCommand(InputCommand cmd, bool useProto);
void setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts);
@@ -147,22 +131,8 @@
}
}
- // Each tracing session can be used for a single block of Start -> Stop.
- static std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest() {
- perfetto::TraceConfig cfg;
- cfg.set_duration_ms(500);
- cfg.add_buffers()->set_size_kb(1024);
- auto* ds_cfg = cfg.add_data_sources()->mutable_config();
- ds_cfg->set_name(TimeStats::kTimeStatsDataSource);
-
- auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend);
- tracingSession->Setup(cfg);
- return tracingSession;
- }
-
std::mt19937 mRandomEngine = std::mt19937(std::random_device()());
- std::unique_ptr<TimeStats> mTimeStats;
- FenceToFenceTimeMap fenceFactory;
+ std::unique_ptr<TimeStats> mTimeStats = std::make_unique<impl::TimeStats>();
};
std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) {
@@ -239,330 +209,6 @@
return distr(mRandomEngine);
}
-TEST_F(TimeStatsTest, traceNewLayerStartsTrackingLayerWhenTracing) {
- EXPECT_EQ(mTimeStats->miniDump(),
- "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
- "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
-
- const std::string layerName = "co.layername#0";
- const int32_t layerID = 5;
- mTimeStats->traceNewLayer(layerID, layerName);
-
- EXPECT_EQ(mTimeStats->miniDump(),
- "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
- "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
-
- auto tracingSession = getTracingSessionForTest();
- tracingSession->StartBlocking();
- EXPECT_EQ(mTimeStats->miniDump(),
- "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
- "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
- mTimeStats->traceNewLayer(layerID, layerName);
- EXPECT_EQ(mTimeStats->miniDump(),
- "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
- "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n");
- tracingSession->StopBlocking();
-}
-
-TEST_F(TimeStatsTest, onDestroyRemovesTheTrackedLayer) {
- EXPECT_EQ(mTimeStats->miniDump(),
- "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
- "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
-
- const std::string layerName = "co.layername#0";
- const int32_t layerID = 5;
- const int32_t secondLayerID = 6;
-
- auto tracingSession = getTracingSessionForTest();
- tracingSession->StartBlocking();
- mTimeStats->traceNewLayer(layerID, layerName);
- mTimeStats->traceNewLayer(secondLayerID, layerName);
- EXPECT_EQ(mTimeStats->miniDump(),
- "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
- "layers in the stats pool is 0\nNumber of layers currently being traced is 2\n");
- tracingSession->StopBlocking();
-
- mTimeStats->onDestroy(layerID);
- EXPECT_EQ(mTimeStats->miniDump(),
- "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
- "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n");
- mTimeStats->onDestroy(layerID);
- EXPECT_EQ(mTimeStats->miniDump(),
- "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
- "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n");
- mTimeStats->onDestroy(secondLayerID);
- EXPECT_EQ(mTimeStats->miniDump(),
- "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of "
- "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n");
-}
-
-TEST_F(TimeStatsTest, canTraceAfterAddingLayer) {
- const std::string layerName = "co.layername#0";
- const int32_t layerID = 1;
- const uint32_t bufferID = 2;
- const uint64_t frameNumber = 3;
- const nsecs_t timestamp = 4;
- const nsecs_t duration = 5;
- const auto type = TimeStats::FrameEvent::POST;
-
- {
- auto tracingSession = getTracingSessionForTest();
-
- tracingSession->StartBlocking();
- // Clean up irrelevant traces.
- tracingSession->ReadTraceBlocking();
-
- mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration);
- // Create second trace packet to finalize the previous one.
- mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
- tracingSession->StopBlocking();
-
- std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
- EXPECT_EQ(raw_trace.size(), 0);
- }
-
- {
- auto tracingSession = getTracingSessionForTest();
-
- tracingSession->StartBlocking();
- // Clean up irrelevant traces.
- tracingSession->ReadTraceBlocking();
-
- mTimeStats->traceNewLayer(layerID, layerName);
- mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration);
- // Create second trace packet to finalize the previous one.
- mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
- tracingSession->StopBlocking();
-
- std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
- ASSERT_GT(raw_trace.size(), 0);
-
- perfetto::protos::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
- ASSERT_FALSE(trace.packet().empty());
- EXPECT_EQ(trace.packet().size(), 1);
-
- const auto& packet = trace.packet().Get(0);
- ASSERT_TRUE(packet.has_timestamp());
- EXPECT_EQ(packet.timestamp(), timestamp);
- ASSERT_TRUE(packet.has_graphics_frame_event());
- const auto& frame_event = packet.graphics_frame_event();
- ASSERT_TRUE(frame_event.has_buffer_event());
- const auto& buffer_event = frame_event.buffer_event();
- ASSERT_TRUE(buffer_event.has_buffer_id());
- EXPECT_EQ(buffer_event.buffer_id(), bufferID);
- ASSERT_TRUE(buffer_event.has_frame_number());
- EXPECT_EQ(buffer_event.frame_number(), frameNumber);
- ASSERT_TRUE(buffer_event.has_type());
- EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type));
- ASSERT_TRUE(buffer_event.has_duration_ns());
- EXPECT_EQ(buffer_event.duration_ns(), duration);
- }
-}
-
-TEST_F(TimeStatsTest, traceFenceTriggersOnNextTraceAfterFenceFired) {
- const std::string layerName = "co.layername#0";
- const int32_t layerID = 5;
- const uint32_t bufferID = 4;
- const uint64_t frameNumber = 3;
- const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE;
-
- {
- auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
- fenceFactory.signalAllForTest(Fence::NO_FENCE, Fence::SIGNAL_TIME_PENDING);
- auto tracingSession = getTracingSessionForTest();
- tracingSession->StartBlocking();
- // Clean up irrelevant traces.
- tracingSession->ReadTraceBlocking();
- // Trace.
- mTimeStats->traceNewLayer(layerID, layerName);
- mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type);
- // Create extra trace packet to (hopefully not) trigger and finalize the fence packet.
- mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
- tracingSession->StopBlocking();
- std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
- EXPECT_EQ(raw_trace.size(), 0);
- }
-
- {
- auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
- auto tracingSession = getTracingSessionForTest();
- tracingSession->StartBlocking();
- // Clean up irrelevant traces.
- tracingSession->ReadTraceBlocking();
- mTimeStats->traceNewLayer(layerID, layerName);
- mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type);
- const nsecs_t timestamp = systemTime();
- fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp);
- // Create extra trace packet to trigger and finalize fence trace packets.
- mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
- tracingSession->StopBlocking();
-
- std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
- ASSERT_GT(raw_trace.size(), 0);
-
- perfetto::protos::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
- ASSERT_FALSE(trace.packet().empty());
- EXPECT_EQ(trace.packet().size(), 2); // Two packets because of the extra trace made above.
-
- const auto& packet = trace.packet().Get(1);
- ASSERT_TRUE(packet.has_timestamp());
- EXPECT_EQ(packet.timestamp(), timestamp);
- ASSERT_TRUE(packet.has_graphics_frame_event());
- const auto& frame_event = packet.graphics_frame_event();
- ASSERT_TRUE(frame_event.has_buffer_event());
- const auto& buffer_event = frame_event.buffer_event();
- ASSERT_TRUE(buffer_event.has_buffer_id());
- EXPECT_EQ(buffer_event.buffer_id(), bufferID);
- ASSERT_TRUE(buffer_event.has_frame_number());
- EXPECT_EQ(buffer_event.frame_number(), frameNumber);
- ASSERT_TRUE(buffer_event.has_type());
- EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type));
- EXPECT_FALSE(buffer_event.has_duration_ns());
- }
-}
-
-TEST_F(TimeStatsTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) {
- const std::string layerName = "co.layername#0";
- const int32_t layerID = 5;
- const uint32_t bufferID = 4;
- const uint64_t frameNumber = 3;
- const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE;
-
- auto tracingSession = getTracingSessionForTest();
-
- tracingSession->StartBlocking();
- // Clean up irrelevant traces.
- tracingSession->ReadTraceBlocking();
- mTimeStats->traceNewLayer(layerID, layerName);
-
- // traceFence called after fence signalled.
- const nsecs_t signalTime1 = systemTime();
- const nsecs_t startTime1 = signalTime1 + 100000;
- auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
- fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1);
- mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1);
-
- // traceFence called before fence signalled.
- const nsecs_t signalTime2 = systemTime();
- const nsecs_t startTime2 = signalTime2 + 100000;
- auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
- mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2);
- fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2);
-
- // Create extra trace packet to trigger and finalize fence trace packets.
- mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
- tracingSession->StopBlocking();
-
- std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
- ASSERT_GT(raw_trace.size(), 0);
-
- perfetto::protos::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
- ASSERT_FALSE(trace.packet().empty());
- EXPECT_EQ(trace.packet().size(), 2);
-
- const auto& packet1 = trace.packet().Get(0);
- ASSERT_TRUE(packet1.has_timestamp());
- EXPECT_EQ(packet1.timestamp(), signalTime1);
- ASSERT_TRUE(packet1.has_graphics_frame_event());
- ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event());
- ASSERT_FALSE(packet1.graphics_frame_event().buffer_event().has_duration_ns());
-
- const auto& packet2 = trace.packet().Get(1);
- ASSERT_TRUE(packet2.has_timestamp());
- EXPECT_EQ(packet2.timestamp(), signalTime2);
- ASSERT_TRUE(packet2.has_graphics_frame_event());
- ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event());
- ASSERT_FALSE(packet2.graphics_frame_event().buffer_event().has_duration_ns());
-}
-
-TEST_F(TimeStatsTest, traceFenceOlderThanDeadline_ShouldBeIgnored) {
- const std::string layerName = "co.layername#0";
- const int32_t layerID = 5;
- const uint32_t bufferID = 4;
- const uint64_t frameNumber = 3;
- const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE;
- const nsecs_t signalTime = systemTime() - TimeStats::kFenceSignallingDeadline;
-
- auto tracingSession = getTracingSessionForTest();
- auto fence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
-
- tracingSession->StartBlocking();
- // Clean up irrelevant traces.
- tracingSession->ReadTraceBlocking();
- mTimeStats->traceNewLayer(layerID, layerName);
- mTimeStats->traceFence(layerID, bufferID, frameNumber, fence, type);
- fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime);
- // Create extra trace packet to trigger and finalize any previous fence packets.
- mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
- tracingSession->StopBlocking();
-
- std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
- EXPECT_EQ(raw_trace.size(), 0);
-}
-
-TEST_F(TimeStatsTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) {
- const std::string layerName = "co.layername#0";
- const int32_t layerID = 5;
- const uint32_t bufferID = 4;
- const uint64_t frameNumber = 3;
- const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE;
- const nsecs_t duration = 1234;
-
- auto tracingSession = getTracingSessionForTest();
-
- tracingSession->StartBlocking();
- // Clean up irrelevant traces.
- tracingSession->ReadTraceBlocking();
- mTimeStats->traceNewLayer(layerID, layerName);
-
- // traceFence called after fence signalled.
- const nsecs_t signalTime1 = systemTime();
- const nsecs_t startTime1 = signalTime1 - duration;
- auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
- fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1);
- mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1);
-
- // traceFence called before fence signalled.
- const nsecs_t signalTime2 = systemTime();
- const nsecs_t startTime2 = signalTime2 - duration;
- auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
- mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2);
- fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2);
-
- // Create extra trace packet to trigger and finalize fence trace packets.
- mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED);
- tracingSession->StopBlocking();
-
- std::vector<char> raw_trace = tracingSession->ReadTraceBlocking();
- ASSERT_GT(raw_trace.size(), 0);
-
- perfetto::protos::Trace trace;
- ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size())));
- ASSERT_FALSE(trace.packet().empty());
- EXPECT_EQ(trace.packet().size(), 2);
-
- const auto& packet1 = trace.packet().Get(0);
- ASSERT_TRUE(packet1.has_timestamp());
- EXPECT_EQ(packet1.timestamp(), startTime1);
- ASSERT_TRUE(packet1.has_graphics_frame_event());
- ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event());
- ASSERT_TRUE(packet1.graphics_frame_event().buffer_event().has_duration_ns());
- const auto& buffer_event1 = packet1.graphics_frame_event().buffer_event();
- EXPECT_EQ(buffer_event1.duration_ns(), duration);
-
- const auto& packet2 = trace.packet().Get(1);
- ASSERT_TRUE(packet2.has_timestamp());
- EXPECT_EQ(packet2.timestamp(), startTime2);
- ASSERT_TRUE(packet2.has_graphics_frame_event());
- ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event());
- ASSERT_TRUE(packet2.graphics_frame_event().buffer_event().has_duration_ns());
- const auto& buffer_event2 = packet2.graphics_frame_event().buffer_event();
- EXPECT_EQ(buffer_event2.duration_ns(), duration);
-}
-
TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) {
EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
ASSERT_TRUE(mTimeStats->isEnabled());
diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp
new file mode 100644
index 0000000..358dfdb
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2019 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 "mock/MockFrameTracer.h"
+
+namespace android {
+namespace mock {
+
+// Explicit default instantiation is recommended.
+FrameTracer::FrameTracer() = default;
+FrameTracer::~FrameTracer() = default;
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h
new file mode 100644
index 0000000..f768b81
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019 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 <gmock/gmock.h>
+
+#include "FrameTracer/FrameTracer.h"
+
+namespace android {
+namespace mock {
+
+class FrameTracer : public android::FrameTracer {
+public:
+ FrameTracer();
+ ~FrameTracer();
+
+ MOCK_METHOD0(initialize, void());
+ MOCK_METHOD0(registerDataSource, void());
+ MOCK_METHOD2(traceNewLayer, void(int32_t, const std::string&));
+ MOCK_METHOD6(traceTimestamp,
+ void(int32_t, uint64_t, uint64_t, nsecs_t, FrameEvent::BufferEventType, nsecs_t));
+ MOCK_METHOD6(traceFence,
+ void(int32_t, uint64_t, uint64_t, const std::shared_ptr<FenceTime>&,
+ FrameEvent::BufferEventType, nsecs_t));
+ MOCK_METHOD0(miniDump, std::string());
+};
+
+} // namespace mock
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
index 542c70a..b1634a8 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
@@ -28,14 +28,6 @@
TimeStats();
~TimeStats() override;
- MOCK_METHOD0(initializeTracing, void());
- MOCK_METHOD0(registerTracingDataSource, void());
- MOCK_METHOD2(traceNewLayer, void(int32_t, const std::string&));
- MOCK_METHOD6(traceTimestamp,
- void(int32_t, uint64_t, uint64_t, nsecs_t, FrameEvent::BufferEventType, nsecs_t));
- MOCK_METHOD6(traceFence,
- void(int32_t, uint64_t, uint64_t, const std::shared_ptr<FenceTime>&,
- FrameEvent::BufferEventType, nsecs_t));
MOCK_METHOD3(parseArgs, void(bool, const Vector<String16>&, std::string&));
MOCK_METHOD0(isEnabled, bool());
MOCK_METHOD0(miniDump, std::string());