Skip to content

Commit 78b8252

Browse files
committed
Move RingBuffer from SF utils into libui
Stuff in libui or libgui or elsewhere upstack might want to use this. Also remove PowerAdvisor's RingBuffer implementation, since it's basically the same thing. Change-Id: I9d8d94fa0d7b8327b320ceed0d507b83979d033d Bug: 360932099 Flag: EXEMPT refactor Test: builds
1 parent 78a579c commit 78b8252

7 files changed

Lines changed: 98 additions & 37 deletions

File tree

services/surfaceflinger/Utils/RingBuffer.h renamed to libs/ui/include/ui/RingBuffer.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include <stddef.h>
2020
#include <array>
2121

22-
namespace android::utils {
22+
namespace android::ui {
2323

2424
template <class T, size_t SIZE>
2525
class RingBuffer {
@@ -31,8 +31,8 @@ class RingBuffer {
3131
~RingBuffer() = default;
3232

3333
constexpr size_t capacity() const { return SIZE; }
34-
3534
size_t size() const { return mCount; }
35+
bool isFull() const { return size() == capacity(); }
3636

3737
T& next() {
3838
mHead = static_cast<size_t>(mHead + 1) % SIZE;
@@ -67,4 +67,4 @@ class RingBuffer {
6767
size_t mCount = 0;
6868
};
6969

70-
} // namespace android::utils
70+
} // namespace android::ui

libs/ui/tests/Android.bp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,17 @@ cc_test {
143143
],
144144
}
145145

146+
cc_test {
147+
name: "RingBuffer_test",
148+
test_suites: ["device-tests"],
149+
shared_libs: ["libui"],
150+
srcs: ["RingBuffer_test.cpp"],
151+
cflags: [
152+
"-Wall",
153+
"-Werror",
154+
],
155+
}
156+
146157
cc_test {
147158
name: "Size_test",
148159
test_suites: ["device-tests"],

libs/ui/tests/RingBuffer_test.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <gtest/gtest.h>
18+
#include <ui/RingBuffer.h>
19+
20+
namespace android::ui {
21+
22+
TEST(RingBuffer, basic) {
23+
RingBuffer<int, 5> rb;
24+
25+
rb.next() = 1;
26+
ASSERT_EQ(1, rb.size());
27+
ASSERT_EQ(1, rb.back());
28+
ASSERT_EQ(1, rb.front());
29+
30+
rb.next() = 2;
31+
ASSERT_EQ(2, rb.size());
32+
ASSERT_EQ(2, rb.back());
33+
ASSERT_EQ(1, rb.front());
34+
ASSERT_EQ(1, rb[-1]);
35+
36+
rb.next() = 3;
37+
ASSERT_EQ(3, rb.size());
38+
ASSERT_EQ(3, rb.back());
39+
ASSERT_EQ(1, rb.front());
40+
ASSERT_EQ(2, rb[-1]);
41+
ASSERT_EQ(1, rb[-2]);
42+
43+
rb.next() = 4;
44+
ASSERT_EQ(4, rb.size());
45+
ASSERT_EQ(4, rb.back());
46+
ASSERT_EQ(1, rb.front());
47+
ASSERT_EQ(3, rb[-1]);
48+
ASSERT_EQ(2, rb[-2]);
49+
ASSERT_EQ(1, rb[-3]);
50+
51+
rb.next() = 5;
52+
ASSERT_EQ(5, rb.size());
53+
ASSERT_EQ(5, rb.back());
54+
ASSERT_EQ(1, rb.front());
55+
ASSERT_EQ(4, rb[-1]);
56+
ASSERT_EQ(3, rb[-2]);
57+
ASSERT_EQ(2, rb[-3]);
58+
ASSERT_EQ(1, rb[-4]);
59+
60+
rb.next() = 6;
61+
ASSERT_EQ(5, rb.size());
62+
ASSERT_EQ(6, rb.back());
63+
ASSERT_EQ(2, rb.front());
64+
ASSERT_EQ(5, rb[-1]);
65+
ASSERT_EQ(4, rb[-2]);
66+
ASSERT_EQ(3, rb[-3]);
67+
ASSERT_EQ(2, rb[-4]);
68+
}
69+
70+
} // namespace android::ui

services/surfaceflinger/HdrLayerInfoReporter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919
#include <android-base/thread_annotations.h>
2020
#include <android/gui/IHdrLayerInfoListener.h>
2121
#include <binder/IBinder.h>
22+
#include <ui/RingBuffer.h>
2223
#include <utils/Timers.h>
2324

2425
#include <unordered_map>
2526

26-
#include "Utils/RingBuffer.h"
2727
#include "WpHash.h"
2828

2929
namespace android {
@@ -102,7 +102,7 @@ class HdrLayerInfoReporter final : public IBinder::DeathRecipient {
102102
EventHistoryEntry(const HdrLayerInfo& info) : info(info) { timestamp = systemTime(); }
103103
};
104104

105-
utils::RingBuffer<EventHistoryEntry, 32> mHdrInfoHistory;
105+
ui::RingBuffer<EventHistoryEntry, 32> mHdrInfoHistory;
106106
};
107107

108108
} // namespace android

services/surfaceflinger/PowerAdvisor/PowerAdvisor.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ void PowerAdvisor::setRequiresRenderEngine(DisplayId displayId, bool requiresRen
515515
}
516516

517517
void PowerAdvisor::setExpectedPresentTime(TimePoint expectedPresentTime) {
518-
mExpectedPresentTimes.append(expectedPresentTime);
518+
mExpectedPresentTimes.next() = expectedPresentTime;
519519
}
520520

521521
void PowerAdvisor::setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) {
@@ -532,7 +532,7 @@ void PowerAdvisor::setHwcPresentDelayedTime(DisplayId displayId, TimePoint earli
532532
}
533533

534534
void PowerAdvisor::setCommitStart(TimePoint commitStartTime) {
535-
mCommitStartTimes.append(commitStartTime);
535+
mCommitStartTimes.next() = commitStartTime;
536536
}
537537

538538
void PowerAdvisor::setCompositeEnd(TimePoint compositeEndTime) {
@@ -579,7 +579,7 @@ std::optional<hal::WorkDuration> PowerAdvisor::estimateWorkDuration() {
579579
}
580580

581581
// Tracks when we finish presenting to hwc
582-
TimePoint estimatedHwcEndTime = mCommitStartTimes[0];
582+
TimePoint estimatedHwcEndTime = mCommitStartTimes.back();
583583

584584
// How long we spent this frame not doing anything, waiting for fences or vsync
585585
Duration idleDuration = 0ns;
@@ -643,13 +643,13 @@ std::optional<hal::WorkDuration> PowerAdvisor::estimateWorkDuration() {
643643
// Also add the frame delay duration since the target did not move while we were delayed
644644
Duration totalDuration = mFrameDelayDuration +
645645
std::max(estimatedHwcEndTime, estimatedGpuEndTime.value_or(TimePoint{0ns})) -
646-
mCommitStartTimes[0];
646+
mCommitStartTimes.back();
647647
Duration totalDurationWithoutGpu =
648-
mFrameDelayDuration + estimatedHwcEndTime - mCommitStartTimes[0];
648+
mFrameDelayDuration + estimatedHwcEndTime - mCommitStartTimes.back();
649649

650650
// We finish SurfaceFlinger when post-composition finishes, so add that in here
651651
Duration flingerDuration =
652-
estimatedFlingerEndTime + mLastPostcompDuration - mCommitStartTimes[0];
652+
estimatedFlingerEndTime + mLastPostcompDuration - mCommitStartTimes.back();
653653
Duration estimatedGpuDuration = firstGpuTimeline.has_value()
654654
? estimatedGpuEndTime.value_or(TimePoint{0ns}) - firstGpuTimeline->startTime
655655
: Duration::fromNs(0);
@@ -661,7 +661,7 @@ std::optional<hal::WorkDuration> PowerAdvisor::estimateWorkDuration() {
661661
hal::WorkDuration duration{
662662
.timeStampNanos = TimePoint::now().ns(),
663663
.durationNanos = combinedDuration.ns(),
664-
.workPeriodStartTimestampNanos = mCommitStartTimes[0].ns(),
664+
.workPeriodStartTimestampNanos = mCommitStartTimes.back().ns(),
665665
.cpuDurationNanos = supportsGpuReporting() ? cpuDuration.ns() : 0,
666666
.gpuDurationNanos = supportsGpuReporting() ? estimatedGpuDuration.ns() : 0,
667667
};

services/surfaceflinger/PowerAdvisor/PowerAdvisor.h

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include <ui/DisplayId.h>
2525
#include <ui/FenceTime.h>
26+
#include <ui/RingBuffer.h>
2627
#include <utils/Mutex.h>
2728

2829
// FMQ library in IPower does questionable conversions
@@ -247,27 +248,6 @@ class PowerAdvisor final : public adpf::PowerAdvisor {
247248
std::optional<GpuTimeline> estimateGpuTiming(std::optional<TimePoint> previousEndTime);
248249
};
249250

250-
template <class T, size_t N>
251-
class RingBuffer {
252-
std::array<T, N> elements = {};
253-
size_t mIndex = 0;
254-
size_t numElements = 0;
255-
256-
public:
257-
void append(T item) {
258-
mIndex = (mIndex + 1) % N;
259-
numElements = std::min(N, numElements + 1);
260-
elements[mIndex] = item;
261-
}
262-
bool isFull() const { return numElements == N; }
263-
// Allows access like [0] == current, [-1] = previous, etc..
264-
T& operator[](int offset) {
265-
size_t positiveOffset =
266-
static_cast<size_t>((offset % static_cast<int>(N)) + static_cast<int>(N));
267-
return elements[(mIndex + positiveOffset) % N];
268-
}
269-
};
270-
271251
// Filter and sort the display ids by a given property
272252
std::vector<DisplayId> getOrderedDisplayIds(
273253
std::optional<TimePoint> DisplayTimingData::*sortBy);
@@ -287,9 +267,9 @@ class PowerAdvisor final : public adpf::PowerAdvisor {
287267
// Last frame's post-composition duration
288268
Duration mLastPostcompDuration{0ns};
289269
// Buffer of recent commit start times
290-
RingBuffer<TimePoint, 2> mCommitStartTimes;
270+
ui::RingBuffer<TimePoint, 2> mCommitStartTimes;
291271
// Buffer of recent expected present times
292-
RingBuffer<TimePoint, 2> mExpectedPresentTimes;
272+
ui::RingBuffer<TimePoint, 2> mExpectedPresentTimes;
293273
// Most recent present fence time, provided by SF after composition engine finishes presenting
294274
TimePoint mLastPresentFenceTime;
295275
// Most recent composition engine present end time, returned with the present fence from SF

services/surfaceflinger/Scheduler/include/scheduler/FrameTargeter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <ui/DisplayId.h>
2525
#include <ui/Fence.h>
2626
#include <ui/FenceTime.h>
27+
#include <ui/RingBuffer.h>
2728

2829
#include <scheduler/Features.h>
2930
#include <scheduler/FrameTime.h>
@@ -34,7 +35,6 @@
3435
// TODO(b/185536303): Pull to FTL.
3536
#include "../../../TracedOrdinal.h"
3637
#include "../../../Utils/Dumper.h"
37-
#include "../../../Utils/RingBuffer.h"
3838

3939
namespace android::scheduler {
4040

@@ -108,7 +108,7 @@ class FrameTarget {
108108
std::pair<bool /* wouldBackpressure */, PresentFence> expectedSignaledPresentFence(
109109
Period vsyncPeriod, Period minFramePeriod) const;
110110
std::array<PresentFence, 2> mPresentFencesLegacy;
111-
utils::RingBuffer<PresentFence, 5> mPresentFences;
111+
ui::RingBuffer<PresentFence, 5> mPresentFences;
112112

113113
FrameTime mLastSignaledFrameTime;
114114

0 commit comments

Comments
 (0)