SurfaceFlinger: expose vsync id extra buffers
Expose a function for clients to call and query the number
of extra buffers needed when vsync id is passed with the buffer.
Test: launch an app and observe systrace
Test: SF unit tests
Bug: 178148035
Change-Id: Icbeec66073feeae9768f0dcc45831b26144ab6f6
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index f68f3e1..e3aaf6d 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -1232,6 +1232,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
@@ -2101,6 +2113,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/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 81ff6b0..e56670d 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -508,6 +508,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;
};
// ----------------------------------------------------------------------------
@@ -570,6 +588,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 3f7a5b1..bbf0906 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