Add compatibility param to setFrameRate() api
Add a compatiblity param to the setFrameRate() api, so the system has
more info to decide the device frame rate when there are multiple
competing preferences.
I also changed the plumbing for setFrameRate() to go directly to surface
flinger, instead of through buffer queue. We're trying to avoid changes
to buffer queue code, to avoid disturbing the prebuilts.
Bug: 137287430
Test: Added new cts tests to verify behavior of the compatibility param.
cts-tradefed run commandAndExit cts-dev --module CtsGraphicsTestCases --test android.graphics.cts.SetFrameRateTest
Test: /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test --gtest_filter='SetFrameRateTest.*'
Change-Id: Ibe75a778fb459d4138a1446c1b38b44798b56a99
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a98ff4f..2701c3e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -34,6 +34,8 @@
#include <optional>
#include <unordered_map>
+#include <android/native_window.h>
+
#include <cutils/properties.h>
#include <log/log.h>
@@ -58,6 +60,7 @@
#include <gui/IProducerListener.h>
#include <gui/LayerDebugInfo.h>
#include <gui/LayerMetadata.h>
+#include <gui/LayerState.h>
#include <gui/Surface.h>
#include <input/IInputFlinger.h>
#include <renderengine/RenderEngine.h>
@@ -3574,9 +3577,13 @@
}
}
if (what & layer_state_t::eFrameRateChanged) {
- if (layer->setFrameRate(
- Layer::FrameRate(s.frameRate, Layer::FrameRateCompatibility::Default)))
+ if (ValidateFrameRate(s.frameRate, s.frameRateCompatibility,
+ "SurfaceFlinger::setClientStateLocked") &&
+ layer->setFrameRate(Layer::FrameRate(s.frameRate,
+ Layer::FrameRate::convertCompatibility(
+ s.frameRateCompatibility)))) {
flags |= eTraversalNeeded;
+ }
}
// This has to happen after we reparent children because when we reparent to null we remove
// child layers from current state and remove its relative z. If the children are reparented in
@@ -4674,6 +4681,9 @@
case GET_COMPOSITION_PREFERENCE:
case GET_PROTECTED_CONTENT_SUPPORT:
case IS_WIDE_COLOR_DISPLAY:
+ // setFrameRate() is deliberately available for apps to call without any
+ // special permissions.
+ case SET_FRAME_RATE:
case GET_DISPLAY_BRIGHTNESS_SUPPORT:
case SET_DISPLAY_BRIGHTNESS: {
return OK;
@@ -5887,6 +5897,27 @@
return genericLayerMetadataKeyMap;
}
+status_t SurfaceFlinger::setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
+ int8_t compatibility) {
+ if (!ValidateFrameRate(frameRate, compatibility, "SurfaceFlinger::setFrameRate")) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock lock(mStateLock);
+ if (authenticateSurfaceTextureLocked(surface)) {
+ sp<Layer> layer = (static_cast<MonitoredProducer*>(surface.get()))->getLayer();
+ if (layer->setFrameRate(
+ Layer::FrameRate(frameRate,
+ Layer::FrameRate::convertCompatibility(compatibility)))) {
+ setTransactionFlags(eTraversalNeeded);
+ }
+ } else {
+ ALOGE("Attempt to set frame rate on an unrecognized IGraphicBufferProducer");
+ return BAD_VALUE;
+ }
+ return NO_ERROR;
+}
+
} // namespace android
#if defined(__gl_h_)