Support streaming fps updates for a layer subtree to sysui via listener.
The supported flow is:
* A binder listener is registered with SurfaceFlinger that is associated
with a task's SurfaceControl.
* Every frame, for every listener that is registered, the fps for each
layer subtree is computed and reported back to each listener via
onFpsUpdated.
* Fps for the layer subtree is computed via FrameTimeline: the layer IDs
for the subtree are gathered into a set, and FrameTimeline internally
finds all DisplayFrames containing at least one layer, then obtains the
present time for each of those frames, then computes the aggregated fps
from those frames. Pragmatically, this should correspond with the last
half second of activity for high refresh rate devices.
No heuristics are used to select the "correct" layer from the layer
subtree. If a game is rendering to two layers at a cadence of 30fps but
offset by one 60hz vsync, then the reported fps will be 60fps because
both layers will be counted on the same linear timeline.
No rate limiting is applied in this patch either. The caller is able to
hack in rate-limiting by immediately unregistering the listener after a
FPS callback is dispatched, and then reregistered. Architecturally, it
is not hard to add in rate-limiting at the SurfaceFlinger level, but
that can be added in a follow-up patch since this patch is already
large.
Bug: 174956756
Test: libsurfaceflinger_unittest
Test: E2E verification with custom listener outputting to logcat
Change-Id: I792bc19cad18b6aee6c6e644bca9da40a0f15099
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 1a643c2..b97eeec 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1994,6 +1994,15 @@
return ComposerService::getComposerService()->removeRegionSamplingListener(listener);
}
+status_t SurfaceComposerClient::addFpsListener(const sp<IBinder>& layerHandle,
+ const sp<gui::IFpsListener>& listener) {
+ return ComposerService::getComposerService()->addFpsListener(layerHandle, listener);
+}
+
+status_t SurfaceComposerClient::removeFpsListener(const sp<gui::IFpsListener>& listener) {
+ return ComposerService::getComposerService()->removeFpsListener(listener);
+}
+
bool SurfaceComposerClient::getDisplayBrightnessSupport(const sp<IBinder>& displayToken) {
bool support = false;
ComposerService::getComposerService()->getDisplayBrightnessSupport(displayToken, &support);