Merge "Only dump active display mode when it exists." into sc-dev
diff --git a/include/android/bitmap.h b/include/android/bitmap.h
index 2362c9e..a70dffd 100644
--- a/include/android/bitmap.h
+++ b/include/android/bitmap.h
@@ -31,18 +31,8 @@
#include <stddef.h>
#include <jni.h>
-#ifndef __ANDROID__
- // Value copied from 'bionic/libc/include/android/api-level.h' which is not available on
- // non Android systems. It is set to 10000 which is same as __ANDROID_API_FUTURE__ value.
- #ifndef __ANDROID_API__
- #define __ANDROID_API__ 10000
- #endif
-
- // Value copied from 'bionic/libc/include/android/versioning.h' which is not available on
- // non Android systems
- #ifndef __INTRODUCED_IN
- #define __INTRODUCED_IN(api_level)
- #endif
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
#endif
#ifdef __cplusplus
diff --git a/include/android/imagedecoder.h b/include/android/imagedecoder.h
index 819a6a4..cac67d4 100644
--- a/include/android/imagedecoder.h
+++ b/include/android/imagedecoder.h
@@ -51,18 +51,8 @@
#include <android/rect.h>
#include <stdint.h>
-#ifndef __ANDROID__
- // Value copied from 'bionic/libc/include/android/api-level.h' which is not available on
- // non Android systems. It is set to 10000 which is same as __ANDROID_API_FUTURE__ value.
- #ifndef __ANDROID_API__
- #define __ANDROID_API__ 10000
- #endif
-
- // Value copied from 'bionic/libc/include/android/versioning.h' which is not available on
- // non Android systems
- #ifndef __INTRODUCED_IN
- #define __INTRODUCED_IN(api_level)
- #endif
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
#endif
#ifdef __cplusplus
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index c2ec0fe..1e6fc2b 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -133,8 +133,10 @@
if (enableTripleBuffering) {
mProducer->setMaxDequeuedBufferCount(2);
}
- mBufferItemConsumer =
- new BLASTBufferItemConsumer(mConsumer, GraphicBuffer::USAGE_HW_COMPOSER, 1, false);
+ mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
+ GraphicBuffer::USAGE_HW_COMPOSER |
+ GraphicBuffer::USAGE_HW_TEXTURE,
+ 1, false);
static int32_t id = 0;
auto consumerName = mName + "(BLAST Consumer)" + std::to_string(id);
id++;
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index 5c9949b..9cd3f63 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -36,9 +36,7 @@
DisplayEventDispatcher::DisplayEventDispatcher(
const sp<Looper>& looper, ISurfaceComposer::VsyncSource vsyncSource,
ISurfaceComposer::EventRegistrationFlags eventRegistration)
- : mLooper(looper),
- mReceiver(vsyncSource, eventRegistration),
- mVsyncState(VsyncState::Unregistered) {
+ : mLooper(looper), mReceiver(vsyncSource, eventRegistration), mWaitingForVsync(false) {
ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}
@@ -68,37 +66,26 @@
}
status_t DisplayEventDispatcher::scheduleVsync() {
- switch (mVsyncState) {
- case VsyncState::Unregistered: {
- ALOGV("dispatcher %p ~ Scheduling vsync.", this);
+ if (!mWaitingForVsync) {
+ ALOGV("dispatcher %p ~ Scheduling vsync.", this);
- // Drain all pending events.
- nsecs_t vsyncTimestamp;
- PhysicalDisplayId vsyncDisplayId;
- uint32_t vsyncCount;
- VsyncEventData vsyncEventData;
- if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount,
- &vsyncEventData)) {
- ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "",
- this, ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
- }
+ // Drain all pending events.
+ nsecs_t vsyncTimestamp;
+ PhysicalDisplayId vsyncDisplayId;
+ uint32_t vsyncCount;
+ VsyncEventData vsyncEventData;
+ if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) {
+ ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this,
+ ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
+ }
- status_t status = mReceiver.setVsyncRate(1);
- if (status) {
- ALOGW("Failed to set vsync rate, status=%d", status);
- return status;
- }
+ status_t status = mReceiver.requestNextVsync();
+ if (status) {
+ ALOGW("Failed to request next vsync, status=%d", status);
+ return status;
+ }
- mVsyncState = VsyncState::RegisteredAndWaitingForVsync;
- break;
- }
- case VsyncState::Registered: {
- mVsyncState = VsyncState::RegisteredAndWaitingForVsync;
- break;
- }
- case VsyncState::RegisteredAndWaitingForVsync: {
- break;
- }
+ mWaitingForVsync = true;
}
return OK;
}
@@ -136,23 +123,8 @@
", displayId=%s, count=%d, vsyncId=%" PRId64,
this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount,
vsyncEventData.id);
- switch (mVsyncState) {
- case VsyncState::Unregistered:
- ALOGW("Received unexpected VSYNC event");
- break;
- case VsyncState::RegisteredAndWaitingForVsync:
- mVsyncState = VsyncState::Registered;
- dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
- break;
- case VsyncState::Registered:
- status_t status = mReceiver.setVsyncRate(0);
- if (status) {
- ALOGW("Failed to reset vsync rate, status=%d", status);
- return status;
- }
- mVsyncState = VsyncState::Unregistered;
- break;
- }
+ mWaitingForVsync = false;
+ dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
}
return 1; // keep the callback
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 10d48a3..762746c 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -1235,6 +1235,18 @@
}
return reply.readInt32();
}
+
+ status_t getExtraBufferCount(int* extraBuffers) const override {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ status_t err = remote()->transact(BnSurfaceComposer::GET_EXTRA_BUFFER_COUNT, data, &reply);
+ if (err != NO_ERROR) {
+ ALOGE("getExtraBufferCount failed to read data: %s (%d)", strerror(-err), err);
+ return err;
+ }
+
+ return reply.readInt32(extraBuffers);
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -2107,6 +2119,16 @@
SAFE_PARCEL(reply->writeInt32, priority);
return NO_ERROR;
}
+ case GET_EXTRA_BUFFER_COUNT: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ int extraBuffers = 0;
+ int err = getExtraBufferCount(&extraBuffers);
+ if (err != NO_ERROR) {
+ return err;
+ }
+ SAFE_PARCEL(reply->writeInt32, extraBuffers);
+ return NO_ERROR;
+ }
default: {
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 59ad8d2..07fc069 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1499,6 +1499,9 @@
case NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO:
res = dispatchSetFrameTimelineInfo(args);
break;
+ case NATIVE_WINDOW_GET_EXTRA_BUFFER_COUNT:
+ res = dispatchGetExtraBufferCount(args);
+ break;
default:
res = NAME_NOT_FOUND;
break;
@@ -1815,6 +1818,14 @@
return setFrameTimelineInfo({frameTimelineVsyncId, inputEventId});
}
+int Surface::dispatchGetExtraBufferCount(va_list args) {
+ ATRACE_CALL();
+ auto extraBuffers = static_cast<int*>(va_arg(args, int*));
+
+ ALOGV("Surface::dispatchGetExtraBufferCount");
+ return getExtraBufferCount(extraBuffers);
+}
+
bool Surface::transformToDisplayInverse() {
return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) ==
NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
@@ -2584,4 +2595,8 @@
return composerService()->setFrameTimelineInfo(mGraphicBufferProducer, frameTimelineInfo);
}
+status_t Surface::getExtraBufferCount(int* extraBuffers) const {
+ return composerService()->getExtraBufferCount(extraBuffers);
+}
+
}; // namespace android
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index 43b9feb..d74c2ba 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -52,20 +52,7 @@
private:
sp<Looper> mLooper;
DisplayEventReceiver mReceiver;
- // The state of vsync event registration and whether the client is expecting
- // an event or not.
- enum class VsyncState {
- // The dispatcher is not registered for vsync events.
- Unregistered,
- // The dispatcher is registered to receive vsync events but should not dispatch it to the
- // client as the client is not expecting a vsync event.
- Registered,
-
- // The dispatcher is registered to receive vsync events and supposed to dispatch it to
- // the client.
- RegisteredAndWaitingForVsync,
- };
- VsyncState mVsyncState;
+ bool mWaitingForVsync;
std::vector<FrameRateOverride> mFrameRateOverrides;
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 6d1a3ab..292838e 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -505,6 +505,24 @@
* Gets priority of the RenderEngine in SurfaceFlinger.
*/
virtual int getGPUContextPriority() = 0;
+
+ /**
+ * Gets the extra buffers a client would need to allocate if it passes
+ * the Choreographer#getVsyncId with its buffers.
+ *
+ * When Choreographer#getVsyncId is passed to SurfaceFlinger, it is used
+ * as an indication of when to latch the buffer. SurfaceFlinger will make
+ * sure that it will give the app at least the time configured as the
+ * 'appDuration' before trying to latch the buffer.
+ *
+ * The total buffers needed for a given configuration is basically the
+ * numbers of vsyncs a single buffer is used across the stack. For the default
+ * configuration a buffer is held ~1 vsync by the app, ~1 vsync by SurfaceFlinger
+ * and 1 vsync by the display. The extra buffers are calculated as the
+ * number of additional buffers on top of the 3 buffers already allocated
+ * by the app.
+ */
+ virtual status_t getExtraBufferCount(int* extraBuffers) const = 0;
};
// ----------------------------------------------------------------------------
@@ -567,6 +585,7 @@
SET_FRAME_TIMELINE_INFO,
ADD_TRANSACTION_TRACE_LISTENER,
GET_GPU_CONTEXT_PRIORITY,
+ GET_EXTRA_BUFFER_COUNT,
// Always append new enum to the end.
};
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index b6b5c7c..5881221 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -189,6 +189,7 @@
virtual status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless);
virtual status_t setFrameTimelineInfo(const FrameTimelineInfo& info);
+ virtual status_t getExtraBufferCount(int* extraBuffers) const;
protected:
virtual ~Surface();
@@ -275,6 +276,7 @@
int dispatchAddQueryInterceptor(va_list args);
int dispatchGetLastQueuedBuffer(va_list args);
int dispatchSetFrameTimelineInfo(va_list args);
+ int dispatchGetExtraBufferCount(va_list args);
bool transformToDisplayInverse();
protected:
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 80e4c77..43909ac 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -889,6 +889,8 @@
int getGPUContextPriority() override { return 0; };
+ status_t getExtraBufferCount(int* /*extraBuffers*/) const override { return NO_ERROR; }
+
protected:
IBinder* onAsBinder() override { return nullptr; }
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index ffe4412..7aa2cf4 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -256,6 +256,7 @@
NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER = 46, /* private */
NATIVE_WINDOW_SET_QUERY_INTERCEPTOR = 47, /* private */
NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO = 48, /* private */
+ NATIVE_WINDOW_GET_EXTRA_BUFFER_COUNT = 49, /* private */
// clang-format on
};
@@ -1030,6 +1031,11 @@
frameTimelineVsyncId, inputEventId);
}
+static inline int native_window_get_extra_buffer_count(
+ struct ANativeWindow* window, int* extraBuffers) {
+ return window->perform(window, NATIVE_WINDOW_GET_EXTRA_BUFFER_COUNT, extraBuffers);
+}
+
// ------------------------------------------------------------------------------------------------
// Candidates for APEX visibility
// These functions are planned to be made stable for APEX modules, but have not
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index bea9932..409c62a 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -409,7 +409,7 @@
KeyedVector<int32_t, Device*> mDevices;
std::vector<std::string> mExcludedDevices;
- List<RawEvent> mEvents GUARDED_BY(mLock);
+ std::vector<RawEvent> mEvents GUARDED_BY(mLock);
std::unordered_map<int32_t /*deviceId*/, std::vector<TouchVideoFrame>> mVideoFrames;
std::vector<int32_t> mVibrators = {0, 1};
@@ -722,16 +722,15 @@
mExcludedDevices = devices;
}
- size_t getEvents(int, RawEvent* buffer, size_t) override {
- std::scoped_lock<std::mutex> lock(mLock);
- if (mEvents.empty()) {
- return 0;
- }
+ size_t getEvents(int, RawEvent* buffer, size_t bufferSize) override {
+ std::scoped_lock lock(mLock);
- *buffer = *mEvents.begin();
- mEvents.erase(mEvents.begin());
+ const size_t filledSize = std::min(mEvents.size(), bufferSize);
+ std::copy(mEvents.begin(), mEvents.begin() + filledSize, buffer);
+
+ mEvents.erase(mEvents.begin(), mEvents.begin() + filledSize);
mEventsCondition.notify_all();
- return 1;
+ return filledSize;
}
std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override {
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 4f99495..3907ac5 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -989,9 +989,16 @@
});
const nsecs_t renderEngineStart = systemTime();
+ // Only use the framebuffer cache when rendering to an internal display
+ // TODO(b/173560331): This is only to help mitigate memory leaks from virtual displays because
+ // right now we don't have a concrete eviction policy for output buffers: GLESRenderEngine
+ // bounds its framebuffer cache but Skia RenderEngine has no current policy. The best fix is
+ // probably to encapsulate the output buffer into a structure that dispatches resource cleanup
+ // over to RenderEngine, in which case this flag can be removed from the drawLayers interface.
+ const bool useFramebufferCache = outputState.layerStackInternal;
status_t status =
renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buf,
- /*useFramebufferCache=*/true, std::move(fd), &readyFence);
+ useFramebufferCache, std::move(fd), &readyFence);
if (status != NO_ERROR && mClientCompositionRequestCache) {
// If rendering was not successful, remove the request from the cache.
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 376bac8..c4ae3a7 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -3003,7 +3003,7 @@
.WillRepeatedly(Return());
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
- EXPECT_CALL(mRenderEngine, drawLayers(_, IsEmpty(), _, true, _, _))
+ EXPECT_CALL(mRenderEngine, drawLayers(_, IsEmpty(), _, false, _, _))
.WillRepeatedly(Return(NO_ERROR));
verify().execute().expectAFenceWasReturned();
@@ -3030,6 +3030,36 @@
}));
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
+ EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _, _))
+ .WillRepeatedly(Return(NO_ERROR));
+
+ verify().execute().expectAFenceWasReturned();
+}
+
+TEST_F(OutputComposeSurfacesTest,
+ buildsAndRendersRequestListAndCachesFramebufferForInternalLayers) {
+ LayerFE::LayerSettings r1;
+ LayerFE::LayerSettings r2;
+
+ r1.geometry.boundaries = FloatRect{1, 2, 3, 4};
+ r2.geometry.boundaries = FloatRect{5, 6, 7, 8};
+ const constexpr uint32_t kInternalLayerStack = 1234;
+ mOutput.setLayerStackFilter(kInternalLayerStack, true);
+
+ EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
+ EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+ EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
+ EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
+ .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1}));
+ EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
+ .WillRepeatedly(
+ Invoke([&](const Region&,
+ std::vector<LayerFE::LayerSettings>& clientCompositionLayers) {
+ clientCompositionLayers.emplace_back(r2);
+ }));
+
+ EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
.WillRepeatedly(Return(NO_ERROR));
@@ -3054,7 +3084,7 @@
.WillRepeatedly(Return());
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
- EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
+ EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _, _))
.Times(2)
.WillOnce(Return(NO_ERROR));
@@ -3083,7 +3113,7 @@
.WillRepeatedly(Return());
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
- EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
+ EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _, _))
.WillOnce(Return(NO_ERROR));
EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
@@ -3115,7 +3145,7 @@
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_))
.WillOnce(Return(mOutputBuffer))
.WillOnce(Return(otherOutputBuffer));
- EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
+ EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _, _))
.WillRepeatedly(Return(NO_ERROR));
verify().execute().expectAFenceWasReturned();
@@ -3145,9 +3175,9 @@
.WillRepeatedly(Return());
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
- EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
+ EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _, _))
.WillOnce(Return(NO_ERROR));
- EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r3)), _, true, _, _))
+ EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r3)), _, false, _, _))
.WillOnce(Return(NO_ERROR));
verify().execute().expectAFenceWasReturned();
@@ -3197,7 +3227,7 @@
struct ExpectDisplaySettingsState
: public CallOrderStateMachineHelper<TestType, ExpectDisplaySettingsState> {
auto thenExpectDisplaySettingsUsed(renderengine::DisplaySettings settings) {
- EXPECT_CALL(getInstance()->mRenderEngine, drawLayers(settings, _, _, true, _, _))
+ EXPECT_CALL(getInstance()->mRenderEngine, drawLayers(settings, _, _, false, _, _))
.WillOnce(Return(NO_ERROR));
return nextState<ExecuteState>();
}
@@ -3296,7 +3326,7 @@
EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
.WillRepeatedly(Return());
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
- EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _))
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _, _))
.WillRepeatedly(Return(NO_ERROR));
}
@@ -3349,7 +3379,7 @@
EXPECT_CALL(*mRenderSurface, setProtected(true));
// Must happen after setting the protected content state.
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
- EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _, _)).WillOnce(Return(NO_ERROR));
mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
@@ -3419,7 +3449,7 @@
InSequence seq;
EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true));
- EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _, _)).WillOnce(Return(NO_ERROR));
mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
@@ -3434,7 +3464,7 @@
EXPECT_CALL(mLayer.outputLayer, writeStateToHWC(false));
EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
.WillOnce(Return(std::vector<LayerFE::LayerSettings>{}));
- EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _, _)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
.WillRepeatedly(Return(&mLayer.outputLayer));
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index df14003..87ca9c7 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -867,9 +867,7 @@
void Layer::popPendingState(State* stateToCommit) {
ATRACE_CALL();
- if (stateToCommit != nullptr) {
- mergeSurfaceFrames(*stateToCommit, mPendingStates[0]);
- }
+ mergeSurfaceFrames(*stateToCommit, mPendingStates[0]);
*stateToCommit = mPendingStates[0];
mPendingStates.pop_front();
ATRACE_INT(mTransactionName.c_str(), mPendingStates.size());
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index bfe9b4a..ba43e70 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -303,10 +303,6 @@
std::lock_guard<std::mutex> lock(mMutex);
const auto request = rate == 0 ? VSyncRequest::None : static_cast<VSyncRequest>(rate);
- if (request != VSyncRequest::None && connection->resyncCallback) {
- connection->resyncCallback();
- }
-
if (connection->vsyncRequest != request) {
connection->vsyncRequest = request;
mCondition.notify_all();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index f785cae..04e9a6d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5030,8 +5030,9 @@
case CAPTURE_DISPLAY:
case SET_DISPLAY_BRIGHTNESS:
case SET_FRAME_TIMELINE_INFO:
- // This is not sensitive information, so should not require permission control.
- case GET_GPU_CONTEXT_PRIORITY: {
+ case GET_GPU_CONTEXT_PRIORITY:
+ case GET_EXTRA_BUFFER_COUNT: {
+ // This is not sensitive information, so should not require permission control.
return OK;
}
case ADD_REGION_SAMPLING_LISTENER:
@@ -6456,6 +6457,25 @@
return getRenderEngine().getContextPriority();
}
+int SurfaceFlinger::calculateExtraBufferCount(Fps maxSupportedRefreshRate,
+ std::chrono::nanoseconds presentLatency) {
+ auto pipelineDepth = presentLatency.count() / maxSupportedRefreshRate.getPeriodNsecs();
+ if (presentLatency.count() % maxSupportedRefreshRate.getPeriodNsecs()) {
+ pipelineDepth++;
+ }
+ return std::max(0ll, pipelineDepth - 2);
+}
+
+status_t SurfaceFlinger::getExtraBufferCount(int* extraBuffers) const {
+ const auto maxSupportedRefreshRate = mRefreshRateConfigs->getSupportedRefreshRateRange().max;
+ const auto vsyncConfig =
+ mVsyncConfiguration->getConfigsForRefreshRate(maxSupportedRefreshRate).late;
+ const auto presentLatency = vsyncConfig.appWorkDuration + vsyncConfig.sfWorkDuration;
+
+ *extraBuffers = calculateExtraBufferCount(maxSupportedRefreshRate, presentLatency);
+ return NO_ERROR;
+}
+
} // namespace android
#if defined(__gl_h_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index ed5b098..a62d0b9 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -622,6 +622,8 @@
int getGPUContextPriority() override;
+ status_t getExtraBufferCount(int* extraBuffers) const override;
+
// Implements IBinder::DeathRecipient.
void binderDied(const wp<IBinder>& who) override;
@@ -1052,6 +1054,9 @@
return std::nullopt;
}
+ static int calculateExtraBufferCount(Fps maxSupportedRefreshRate,
+ std::chrono::nanoseconds presentLatency);
+
sp<StartPropertySetThread> mStartPropertySetThread;
surfaceflinger::Factory& mFactory;
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 694790f..e46a270 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -69,6 +69,8 @@
Scheduler::ConnectionHandle mConnectionHandle;
mock::EventThread* mEventThread;
sp<MockEventThreadConnection> mEventThreadConnection;
+
+ TestableSurfaceFlinger mFlinger;
};
SchedulerTest::SchedulerTest() {
@@ -187,4 +189,14 @@
EXPECT_CALL(*mEventThread, onModeChanged(_, _, _)).Times(0);
}
+TEST_F(SchedulerTest, calculateExtraBufferCount) {
+ EXPECT_EQ(0, mFlinger.calculateExtraBufferCount(Fps(60), 30ms));
+ EXPECT_EQ(1, mFlinger.calculateExtraBufferCount(Fps(90), 30ms));
+ EXPECT_EQ(2, mFlinger.calculateExtraBufferCount(Fps(120), 30ms));
+
+ EXPECT_EQ(1, mFlinger.calculateExtraBufferCount(Fps(60), 40ms));
+
+ EXPECT_EQ(0, mFlinger.calculateExtraBufferCount(Fps(60), 10ms));
+}
+
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 6aa6d31..ce2bfef 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -391,6 +391,11 @@
auto getGPUContextPriority() { return mFlinger->getGPUContextPriority(); }
+ auto calculateExtraBufferCount(Fps maxSupportedRefreshRate,
+ std::chrono::nanoseconds presentLatency) const {
+ return SurfaceFlinger::calculateExtraBufferCount(maxSupportedRefreshRate, presentLatency);
+ }
+
/* ------------------------------------------------------------------------
* Read-only access to private data to assert post-conditions.
*/