Skip to content

Commit ebdbead

Browse files
author
Ben Widawsky
committed
SF: Implement FrameStats directly in FrameTimeline
Bug: 241394120 Test: builds, atest CtsUiAutomationTestCases:android.app.uiautomation.cts.UiAutomationTest#testWindowContentFrameStats$ Flag: com.android.graphics.surfaceflinger.flags.deprecate_frame_tracker Change-Id: I3f12d504e821a6ba15a26604eb56f317c9d59a18
1 parent 12b5112 commit ebdbead

5 files changed

Lines changed: 101 additions & 19 deletions

File tree

services/surfaceflinger/FrameTimeline/FrameTimeline.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,11 @@ void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) {
378378
}
379379
}
380380

381+
void SurfaceFrame::setDesiredPresentTime(nsecs_t desiredPresentTime) {
382+
std::scoped_lock lock(mMutex);
383+
mActuals.desiredPresentTime = desiredPresentTime;
384+
}
385+
381386
void SurfaceFrame::setDropTime(nsecs_t dropTime) {
382387
std::scoped_lock lock(mMutex);
383388
mDropTime = dropTime;
@@ -1456,6 +1461,30 @@ float FrameTimeline::computeFps(const std::unordered_set<int32_t>& layerIds) {
14561461
static_cast<float>(totalPresentToPresentWalls);
14571462
}
14581463

1464+
void FrameTimeline::generateFrameStats(int32_t layer, size_t count, FrameStats* outStats) const {
1465+
std::scoped_lock lock(mMutex);
1466+
1467+
// TODO: Include FPS calculation here
1468+
for (auto displayFrame : mDisplayFrames) {
1469+
if (!count--) {
1470+
break;
1471+
}
1472+
1473+
if (displayFrame->getActuals().presentTime <= 0) {
1474+
continue;
1475+
}
1476+
1477+
for (const auto& surfaceFrame : displayFrame->getSurfaceFrames()) {
1478+
if (surfaceFrame->getLayerId() == layer) {
1479+
outStats->actualPresentTimesNano.push_back(surfaceFrame->getActuals().presentTime);
1480+
outStats->desiredPresentTimesNano.push_back(
1481+
surfaceFrame->getActuals().desiredPresentTime);
1482+
outStats->frameReadyTimesNano.push_back(surfaceFrame->getActuals().endTime);
1483+
}
1484+
}
1485+
}
1486+
}
1487+
14591488
std::optional<size_t> FrameTimeline::getFirstSignalFenceIndex() const {
14601489
for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
14611490
const auto& [fence, _] = mPendingPresentFences[i];

services/surfaceflinger/FrameTimeline/FrameTimeline.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,20 @@ enum class FrameStartMetadata : int8_t {
8585
*/
8686
struct TimelineItem {
8787
TimelineItem(const nsecs_t startTime = 0, const nsecs_t endTime = 0,
88-
const nsecs_t presentTime = 0)
89-
: startTime(startTime), endTime(endTime), presentTime(presentTime) {}
88+
const nsecs_t presentTime = 0, const nsecs_t desiredPresentTime = 0)
89+
: startTime(startTime),
90+
endTime(endTime),
91+
presentTime(presentTime),
92+
desiredPresentTime(desiredPresentTime) {}
9093

9194
nsecs_t startTime;
9295
nsecs_t endTime;
9396
nsecs_t presentTime;
97+
nsecs_t desiredPresentTime;
9498

9599
bool operator==(const TimelineItem& other) const {
96100
return startTime == other.startTime && endTime == other.endTime &&
97-
presentTime == other.presentTime;
101+
presentTime == other.presentTime && desiredPresentTime != other.desiredPresentTime;
98102
}
99103

100104
bool operator!=(const TimelineItem& other) const { return !(*this == other); }
@@ -183,6 +187,7 @@ class SurfaceFrame {
183187
void setActualStartTime(nsecs_t actualStartTime);
184188
void setActualQueueTime(nsecs_t actualQueueTime);
185189
void setAcquireFenceTime(nsecs_t acquireFenceTime);
190+
void setDesiredPresentTime(nsecs_t desiredPresentTime);
186191
void setDropTime(nsecs_t dropTime);
187192
void setPresentState(PresentState presentState, nsecs_t lastLatchTime = 0);
188193
void setRenderRate(Fps renderRate);
@@ -341,6 +346,9 @@ class FrameTimeline {
341346
// containing at least one layer ID.
342347
virtual float computeFps(const std::unordered_set<int32_t>& layerIds) = 0;
343348

349+
// Supports the legacy FrameStats interface
350+
virtual void generateFrameStats(int32_t layer, size_t count, FrameStats* outStats) const = 0;
351+
344352
// Restores the max number of display frames to default. Called by SF backdoor.
345353
virtual void reset() = 0;
346354
};
@@ -501,6 +509,7 @@ class FrameTimeline : public android::frametimeline::FrameTimeline {
501509
void parseArgs(const Vector<String16>& args, std::string& result) override;
502510
void setMaxDisplayFrames(uint32_t size) override;
503511
float computeFps(const std::unordered_set<int32_t>& layerIds) override;
512+
void generateFrameStats(int32_t layer, size_t count, FrameStats* outStats) const override;
504513
void reset() override;
505514

506515
// Sets up the perfetto tracing backend and data source.

services/surfaceflinger/Layer.cpp

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ Layer::Layer(const surfaceflinger::LayerCreationArgs& args)
154154
mDrawingState.metadata = args.metadata;
155155
mDrawingState.frameTimelineInfo = {};
156156
mDrawingState.postTime = -1;
157-
mFrameTracker.setDisplayRefreshPeriod(
157+
mDeprecatedFrameTracker.setDisplayRefreshPeriod(
158158
args.flinger->mScheduler->getPacesetterVsyncPeriod().ns());
159159

160160
mOwnerUid = args.ownerUid;
@@ -472,6 +472,9 @@ std::shared_ptr<frametimeline::SurfaceFrame> Layer::createSurfaceFrameForTransac
472472
getSequence(), mName,
473473
mTransactionName,
474474
/*isBuffer*/ false, gameMode);
475+
// Buffer hasn't yet been latched, so use mDrawingState
476+
surfaceFrame->setDesiredPresentTime(mDrawingState.desiredPresentTime);
477+
475478
surfaceFrame->setActualStartTime(info.startTimeNanos);
476479
// For Transactions, the post time is considered to be both queue and acquire fence time.
477480
surfaceFrame->setActualQueueTime(postTime);
@@ -490,6 +493,8 @@ std::shared_ptr<frametimeline::SurfaceFrame> Layer::createSurfaceFrameForBuffer(
490493
mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid,
491494
getSequence(), mName, debugName,
492495
/*isBuffer*/ true, gameMode);
496+
// Buffer hasn't yet been latched, so use mDrawingState
497+
surfaceFrame->setDesiredPresentTime(mDrawingState.desiredPresentTime);
493498
surfaceFrame->setActualStartTime(info.startTimeNanos);
494499
// For buffers, acquire fence time will set during latch.
495500
surfaceFrame->setActualQueueTime(queueTime);
@@ -514,6 +519,8 @@ void Layer::setFrameTimelineVsyncForSkippedFrames(const FrameTimelineInfo& info,
514519
mOwnerPid, mOwnerUid,
515520
getSequence(), mName, debugName,
516521
/*isBuffer*/ false, gameMode);
522+
// Buffer hasn't yet been latched, so use mDrawingState
523+
surfaceFrame->setDesiredPresentTime(mDrawingState.desiredPresentTime);
517524
surfaceFrame->setActualStartTime(skippedFrameTimelineInfo.skippedFrameStartTimeNanos);
518525
// For Transactions, the post time is considered to be both queue and acquire fence time.
519526
surfaceFrame->setActualQueueTime(postTime);
@@ -605,15 +612,42 @@ void Layer::miniDump(std::string& result, const frontend::LayerSnapshot& snapsho
605612
}
606613

607614
void Layer::dumpFrameStats(std::string& result) const {
608-
mFrameTracker.dumpStats(result);
615+
if (FlagManager::getInstance().deprecate_frame_tracker()) {
616+
FrameStats fs = FrameStats();
617+
getFrameStats(&fs);
618+
for (auto desired = fs.desiredPresentTimesNano.begin(),
619+
actual = fs.actualPresentTimesNano.begin(),
620+
ready = fs.frameReadyTimesNano.begin();
621+
desired != fs.desiredPresentTimesNano.end() &&
622+
actual != fs.actualPresentTimesNano.end() && ready != fs.frameReadyTimesNano.end();
623+
++desired, ++actual, ++ready) {
624+
result.append(std::format("{}\t{}\t{}\n", *desired, *actual, *ready));
625+
}
626+
627+
result.push_back('\n');
628+
} else {
629+
mDeprecatedFrameTracker.dumpStats(result);
630+
}
609631
}
610632

611633
void Layer::clearFrameStats() {
612-
mFrameTracker.clearStats();
634+
if (FlagManager::getInstance().deprecate_frame_tracker()) {
635+
mFrameStatsHistorySize = 0;
636+
} else {
637+
mDeprecatedFrameTracker.clearStats();
638+
}
613639
}
614640

615641
void Layer::getFrameStats(FrameStats* outStats) const {
616-
mFrameTracker.getStats(outStats);
642+
if (FlagManager::getInstance().deprecate_frame_tracker()) {
643+
if (auto ftl = getTimeline()) {
644+
float fps = ftl->get().computeFps({getSequence()});
645+
ftl->get().generateFrameStats(getSequence(), mFrameStatsHistorySize, outStats);
646+
outStats->refreshPeriodNano = Fps::fromValue(fps).getPeriodNsecs();
647+
}
648+
} else {
649+
mDeprecatedFrameTracker.getStats(outStats);
650+
}
617651
}
618652

619653
void Layer::onDisconnect() {
@@ -1348,9 +1382,9 @@ void Layer::onCompositionPresented(const DisplayDevice* display,
13481382
handle->compositorTiming = compositorTiming;
13491383
}
13501384

1351-
// Update mFrameTracker.
1385+
// Update mDeprecatedFrameTracker.
13521386
nsecs_t desiredPresentTime = mBufferInfo.mDesiredPresentTime;
1353-
mFrameTracker.setDesiredPresentTime(desiredPresentTime);
1387+
mDeprecatedFrameTracker.setDesiredPresentTime(desiredPresentTime);
13541388

13551389
const int32_t layerId = getSequence();
13561390
mFlinger->mTimeStats->setDesiredTime(layerId, mCurrentFrameNumber, desiredPresentTime);
@@ -1370,15 +1404,15 @@ void Layer::onCompositionPresented(const DisplayDevice* display,
13701404
}
13711405
}
13721406

1407+
// The SurfaceFrame's AcquireFence is the same as this.
13731408
std::shared_ptr<FenceTime> frameReadyFence = mBufferInfo.mFenceTime;
13741409
if (frameReadyFence->isValid()) {
1375-
mFrameTracker.setFrameReadyFence(std::move(frameReadyFence));
1410+
mDeprecatedFrameTracker.setFrameReadyFence(std::move(frameReadyFence));
13761411
} else {
13771412
// There was no fence for this frame, so assume that it was ready
13781413
// to be presented at the desired present time.
1379-
mFrameTracker.setFrameReadyTime(desiredPresentTime);
1414+
mDeprecatedFrameTracker.setFrameReadyTime(desiredPresentTime);
13801415
}
1381-
13821416
if (display) {
13831417
const auto activeMode = display->refreshRateSelector().getActiveMode();
13841418
const Fps refreshRate = activeMode.fps;
@@ -1393,7 +1427,7 @@ void Layer::onCompositionPresented(const DisplayDevice* display,
13931427
mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber,
13941428
presentFence,
13951429
FrameTracer::FrameEvent::PRESENT_FENCE);
1396-
mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
1430+
mDeprecatedFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
13971431
} else if (const auto displayId = PhysicalDisplayId::tryCast(display->getId());
13981432
displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
13991433
// The HWC doesn't support present fences, so use the present timestamp instead.
@@ -1414,11 +1448,12 @@ void Layer::onCompositionPresented(const DisplayDevice* display,
14141448
mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(),
14151449
mCurrentFrameNumber, actualPresentTime,
14161450
FrameTracer::FrameEvent::PRESENT_FENCE);
1417-
mFrameTracker.setActualPresentTime(actualPresentTime);
1451+
mDeprecatedFrameTracker.setActualPresentTime(actualPresentTime);
14181452
}
14191453
}
14201454

1421-
mFrameTracker.advanceFrame();
1455+
mFrameStatsHistorySize++;
1456+
mDeprecatedFrameTracker.advanceFrame();
14221457
mBufferInfo.mFrameLatencyNeeded = false;
14231458
}
14241459

services/surfaceflinger/Layer.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include <android/gui/DropInputMode.h>
2020
#include <android/gui/ISurfaceComposerClient.h>
21+
#include <com_android_graphics_surfaceflinger_flags.h>
2122
#include <ftl/small_map.h>
2223
#include <gui/BufferQueue.h>
2324
#include <gui/LayerState.h>
@@ -44,6 +45,7 @@
4445
#include <scheduler/Seamlessness.h>
4546

4647
#include <cstdint>
48+
#include <functional>
4749
#include <optional>
4850
#include <vector>
4951

@@ -433,8 +435,12 @@ class Layer : public virtual RefBase {
433435

434436
uint32_t mTransactionFlags{0};
435437

438+
// Leverages FrameTimeline to generate FrameStats. Since FrameTimeline already has the data,
439+
// statistical history needs to only be tracked by count of frames.
440+
// TODO: Deprecate the '--latency-clear' and get rid of this.
441+
std::atomic<uint16_t> mFrameStatsHistorySize;
436442
// Timestamp history for UIAutomation. Thread safe.
437-
FrameTracker mFrameTracker;
443+
FrameTracker mDeprecatedFrameTracker;
438444

439445
// main thread
440446
sp<NativeHandle> mSidebandStream;
@@ -556,6 +562,9 @@ class Layer : public virtual RefBase {
556562

557563
std::vector<std::pair<frontend::LayerHierarchy::TraversalPath, sp<LayerFE>>> mLayerFEs;
558564
bool mHandleAlive = false;
565+
std::optional<std::reference_wrapper<frametimeline::FrameTimeline>> getTimeline() const {
566+
return *mFlinger->mFrameTimeline;
567+
}
559568
};
560569

561570
std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate);

services/surfaceflinger/tests/unittests/MessageQueueTest.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,9 @@ TEST_F(MessageQueueTest, commitTwiceWithCallback) {
159159
constexpr VsyncId vsyncId{42};
160160

161161
EXPECT_CALL(mTokenManager,
162-
generateTokenForPredictions(frametimeline::TimelineItem(kStartTime.ns(),
163-
kEndTime.ns(),
164-
kPresentTime.ns())))
162+
generateTokenForPredictions(
163+
frametimeline::TimelineItem(kStartTime.ns(), kEndTime.ns(),
164+
kPresentTime.ns(), kPresentTime.ns())))
165165
.WillOnce(Return(ftl::to_underlying(vsyncId)));
166166
EXPECT_CALL(*mEventQueue.mHandler, dispatchFrame(vsyncId, kPresentTime)).Times(1);
167167
EXPECT_NO_FATAL_FAILURE(

0 commit comments

Comments
 (0)