Merge "Add compatibility param to setFrameRate() api"
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index eeb8330..c30dcfe 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -425,12 +425,15 @@
* valid refresh rate for this device's display - e.g., it's fine to pass 30fps to a device that can
* only run the display at 60fps.
*
+ * |compatibility| The frame rate compatibility of this surface. The compatibility value may
+ * influence the system's choice of display frame rate. To specify a compatibility use the
+ * ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* enum.
+ *
* Available since API level 30.
*/
void ASurfaceTransaction_setFrameRate(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control,
- float frameRate)
- __INTRODUCED_IN(30);
+ ASurfaceControl* surface_control, float frameRate,
+ int8_t compatibility) __INTRODUCED_IN(30);
#endif // __ANDROID_API__ >= 30
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 2f27fd2..ce41eab 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -1112,6 +1112,42 @@
}
return NO_ERROR;
}
+
+ virtual status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
+ int8_t compatibility) {
+ Parcel data, reply;
+ status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ if (err != NO_ERROR) {
+ ALOGE("setFrameRate: failed writing interface token: %s (%d)", strerror(-err), -err);
+ return err;
+ }
+
+ err = data.writeStrongBinder(IInterface::asBinder(surface));
+ if (err != NO_ERROR) {
+ ALOGE("setFrameRate: failed writing strong binder: %s (%d)", strerror(-err), -err);
+ return err;
+ }
+
+ err = data.writeFloat(frameRate);
+ if (err != NO_ERROR) {
+ ALOGE("setFrameRate: failed writing float: %s (%d)", strerror(-err), -err);
+ return err;
+ }
+
+ err = data.writeByte(compatibility);
+ if (err != NO_ERROR) {
+ ALOGE("setFrameRate: failed writing byte: %s (%d)", strerror(-err), -err);
+ return err;
+ }
+
+ err = remote()->transact(BnSurfaceComposer::SET_FRAME_RATE, data, &reply,
+ IBinder::FLAG_ONEWAY);
+ if (err != NO_ERROR) {
+ ALOGE("setFrameRate: failed to transact: %s (%d)", strerror(-err), err);
+ return err;
+ }
+ return NO_ERROR;
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -1877,6 +1913,36 @@
return setGlobalShadowSettings(ambientColor, spotColor, lightPosY, lightPosZ,
lightRadius);
}
+ case SET_FRAME_RATE: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> binder;
+ status_t err = data.readStrongBinder(&binder);
+ if (err != NO_ERROR) {
+ ALOGE("setFrameRate: failed to read strong binder: %s (%d)", strerror(-err), -err);
+ return err;
+ }
+ sp<IGraphicBufferProducer> surface = interface_cast<IGraphicBufferProducer>(binder);
+ if (!surface) {
+ ALOGE("setFrameRate: failed to cast to IGraphicBufferProducer: %s (%d)",
+ strerror(-err), -err);
+ return err;
+ }
+ float frameRate;
+ err = data.readFloat(&frameRate);
+ if (err != NO_ERROR) {
+ ALOGE("setFrameRate: failed to read float: %s (%d)", strerror(-err), -err);
+ return err;
+ }
+ int8_t compatibility;
+ err = data.readByte(&compatibility);
+ if (err != NO_ERROR) {
+ ALOGE("setFrameRate: failed to read byte: %s (%d)", strerror(-err), -err);
+ return err;
+ }
+ status_t result = setFrameRate(surface, frameRate, compatibility);
+ reply->writeInt32(result);
+ return NO_ERROR;
+ }
default: {
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 5547efc..a9c9b74 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -24,6 +24,8 @@
#include <gui/IGraphicBufferProducer.h>
#include <gui/LayerState.h>
+#include <cmath>
+
namespace android {
status_t layer_state_t::write(Parcel& output) const
@@ -113,6 +115,7 @@
output.writeFloat(shadowRadius);
output.writeInt32(frameRateSelectionPriority);
output.writeFloat(frameRate);
+ output.writeByte(frameRateCompatibility);
return NO_ERROR;
}
@@ -194,6 +197,7 @@
shadowRadius = input.readFloat();
frameRateSelectionPriority = input.readInt32();
frameRate = input.readFloat();
+ frameRateCompatibility = input.readByte();
return NO_ERROR;
}
@@ -427,6 +431,7 @@
if (other.what & eFrameRateChanged) {
what |= eFrameRateChanged;
frameRate = other.frameRate;
+ frameRateCompatibility = other.frameRateCompatibility;
}
if ((other.what & what) != other.what) {
ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
@@ -474,4 +479,21 @@
syncInputWindows = input.readBool();
}
+bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunctionName) {
+ const char* functionName = inFunctionName != nullptr ? inFunctionName : "call";
+ int floatClassification = std::fpclassify(frameRate);
+ if (frameRate < 0 || floatClassification == FP_INFINITE || floatClassification == FP_NAN) {
+ ALOGE("%s failed - invalid frame rate %f", functionName, frameRate);
+ return false;
+ }
+
+ if (compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT &&
+ compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE) {
+ ALOGE("%s failed - invalid compatibility value %d", functionName, compatibility);
+ return false;
+ }
+
+ return true;
+}
+
}; // namespace android
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 278cc59..f911e70 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -43,6 +43,7 @@
#include <gui/IProducerListener.h>
#include <gui/ISurfaceComposer.h>
+#include <gui/LayerState.h>
#include <private/gui/ComposerService.h>
namespace android {
@@ -1413,7 +1414,8 @@
int Surface::dispatchSetFrameRate(va_list args) {
float frameRate = static_cast<float>(va_arg(args, double));
- return setFrameRate(frameRate);
+ int8_t compatibility = static_cast<int8_t>(va_arg(args, int));
+ return setFrameRate(frameRate, compatibility);
}
int Surface::dispatchAddCancelInterceptor(va_list args) {
@@ -2222,11 +2224,15 @@
mSurfaceListener->onBuffersDiscarded(discardedBufs);
}
-status_t Surface::setFrameRate(float frameRate) {
+status_t Surface::setFrameRate(float frameRate, int8_t compatibility) {
ATRACE_CALL();
- ALOGV("Surface::setTargetFrameRate");
- Mutex::Autolock lock(mMutex);
- return mGraphicBufferProducer->setFrameRate(frameRate);
+ ALOGV("Surface::setFrameRate");
+
+ if (!ValidateFrameRate(frameRate, compatibility, "Surface::setFrameRate")) {
+ return BAD_VALUE;
+ }
+
+ return composerService()->setFrameRate(mGraphicBufferProducer, frameRate, compatibility);
}
}; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index ff8b719..dc4860a 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1387,14 +1387,19 @@
}
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameRate(
- const sp<SurfaceControl>& sc, float frameRate) {
+ const sp<SurfaceControl>& sc, float frameRate, int8_t compatibility) {
layer_state_t* s = getLayerState(sc);
if (!s) {
mStatus = BAD_INDEX;
return *this;
}
+ if (!ValidateFrameRate(frameRate, compatibility, "Transaction::setFrameRate")) {
+ mStatus = BAD_VALUE;
+ return *this;
+ }
s->what |= layer_state_t::eFrameRateChanged;
s->frameRate = frameRate;
+ s->frameRateCompatibility = compatibility;
return *this;
}
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index e860f61..0659f0d 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -500,6 +500,12 @@
virtual status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
float lightPosY, float lightPosZ,
float lightRadius) = 0;
+
+ /*
+ * Sets the intended frame rate for a surface. See ANativeWindow_setFrameRate() for more info.
+ */
+ virtual status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
+ int8_t compatibility) = 0;
};
// ----------------------------------------------------------------------------
@@ -557,6 +563,7 @@
SET_AUTO_LOW_LATENCY_MODE,
GET_GAME_CONTENT_TYPE_SUPPORT,
SET_GAME_CONTENT_TYPE,
+ SET_FRAME_RATE,
// Always append new enum to the end.
};
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 2d53b48..7e3d5d5 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -20,8 +20,7 @@
#include <stdint.h>
#include <sys/types.h>
-#include <utils/Errors.h>
-
+#include <android/native_window.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/ITransactionCompletedListener.h>
#include <math/mat4.h>
@@ -36,6 +35,7 @@
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/Rotation.h>
+#include <utils/Errors.h>
namespace android {
@@ -135,7 +135,8 @@
colorSpaceAgnostic(false),
shadowRadius(0.0f),
frameRateSelectionPriority(-1),
- frameRate(0.0f) {
+ frameRate(0.0f),
+ frameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT) {
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
hdrMetadata.validTypes = 0;
@@ -221,7 +222,9 @@
// Priority of the layer assigned by Window Manager.
int32_t frameRateSelectionPriority;
+ // Layer frame rate and compatibility. See ANativeWindow_setFrameRate().
float frameRate;
+ int8_t frameRateCompatibility;
};
struct ComposerState {
@@ -292,6 +295,12 @@
return compare_type(lhs.token, rhs.token);
}
+// Returns true if the frameRate and compatibility are valid values, false
+// othwerise. If either of the params are invalid, an error log is printed, and
+// functionName is added to the log to indicate which function call failed.
+// functionName can be null.
+bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* functionName);
+
}; // namespace android
#endif // ANDROID_SF_LAYER_STATE_H
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 4a353fc..ad7cbfe 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -179,7 +179,7 @@
status_t getConsumerUsage(uint64_t* outUsage) const;
// See IGraphicBufferProducer::setFrameRate
- status_t setFrameRate(float frameRate);
+ status_t setFrameRate(float frameRate, int8_t compatibility);
protected:
virtual ~Surface();
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 27877bb..0cf141d 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -519,7 +519,8 @@
const Rect& source, const Rect& dst, int transform);
Transaction& setShadowRadius(const sp<SurfaceControl>& sc, float cornerRadius);
- Transaction& setFrameRate(const sp<SurfaceControl>& sc, float frameRate);
+ Transaction& setFrameRate(const sp<SurfaceControl>& sc, float frameRate,
+ int8_t compatibility);
status_t setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 70fd888..8c0f8f8 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -854,6 +854,11 @@
return NO_ERROR;
}
+ status_t setFrameRate(const sp<IGraphicBufferProducer>& /*surface*/, float /*frameRate*/,
+ int8_t /*compatibility*/) override {
+ return NO_ERROR;
+ }
+
protected:
IBinder* onAsBinder() override { return nullptr; }
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index 98b76fd..f09decf 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -158,11 +158,11 @@
return query(window, NATIVE_WINDOW_DATASPACE);
}
-int32_t ANativeWindow_setFrameRate(ANativeWindow* window, float frameRate) {
- if (!window || !query(window, NATIVE_WINDOW_IS_VALID) || frameRate < 0) {
+int32_t ANativeWindow_setFrameRate(ANativeWindow* window, float frameRate, int8_t compatibility) {
+ if (!window || !query(window, NATIVE_WINDOW_IS_VALID)) {
return -EINVAL;
}
- return native_window_set_frame_rate(window, frameRate);
+ return native_window_set_frame_rate(window, frameRate, compatibility);
}
void ANativeWindow_tryAllocateBuffers(ANativeWindow* window) {
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index 4b426c5..59aa665 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -33,6 +33,7 @@
#ifndef ANDROID_NATIVE_WINDOW_H
#define ANDROID_NATIVE_WINDOW_H
+#include <stdint.h>
#include <sys/cdefs.h>
#include <android/data_space.h>
@@ -232,6 +233,24 @@
#if __ANDROID_API__ >= 30
+/* Parameter for ANativeWindow_setFrameRate */
+enum {
+ /**
+ * There are no inherent restrictions on the frame rate of this window.
+ */
+ ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT = 0,
+ /**
+ * This window is being used to display content with an inherently fixed
+ * frame rate, e.g. a video that has a specific frame rate. When the system
+ * selects a frame rate other than what the app requested, the app will need
+ * to do pull down or use some other technique to adapt to the system's
+ * frame rate. The user experience is likely to be worse (e.g. more frame
+ * stuttering) than it would be if the system had chosen the app's requested
+ * frame rate.
+ */
+ ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE = 1
+};
+
/**
* Sets the intended frame rate for this window.
*
@@ -257,9 +276,15 @@
* refresh rate for this device's display - e.g., it's fine to pass 30fps to a
* device that can only run the display at 60fps.
*
- * \return 0 for success, -EINVAL if the window or frame rate are invalid.
+ * \param compatibility The frame rate compatibility of this window. The
+ * compatibility value may influence the system's choice of display refresh
+ * rate. See the ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* values for more info.
+ *
+ * \return 0 for success, -EINVAL if the window, frame rate, or compatibility
+ * value are invalid.
*/
-int32_t ANativeWindow_setFrameRate(ANativeWindow* window, float frameRate) __INTRODUCED_IN(30);
+int32_t ANativeWindow_setFrameRate(ANativeWindow* window, float frameRate, int8_t compatibility)
+ __INTRODUCED_IN(30);
/**
* Provides a hint to the window that buffers should be preallocated ahead of
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index f686147..0e28fb8 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -1015,8 +1015,10 @@
return window->perform(window, NATIVE_WINDOW_SET_AUTO_PREROTATION, autoPrerotation);
}
-static inline int native_window_set_frame_rate(struct ANativeWindow* window, float frameRate) {
- return window->perform(window, NATIVE_WINDOW_SET_FRAME_RATE, (double)frameRate);
+static inline int native_window_set_frame_rate(struct ANativeWindow* window, float frameRate,
+ int8_t compatibility) {
+ return window->perform(window, NATIVE_WINDOW_SET_FRAME_RATE, (double)frameRate,
+ (int)compatibility);
}
// ------------------------------------------------------------------------------------------------
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index 154eb8e..e072e11 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -46,9 +46,9 @@
ANativeWindow_setBuffersTimestamp; # llndk
ANativeWindow_setBuffersTransform;
ANativeWindow_setDequeueTimeout; # apex # introduced=30
+ ANativeWindow_setFrameRate; # introduced=30
ANativeWindow_setSharedBufferMode; # llndk
ANativeWindow_setSwapInterval; # llndk
- ANativeWindow_setFrameRate; # introduced=30
ANativeWindow_setUsage; # llndk
ANativeWindow_tryAllocateBuffers; # introduced=30
ANativeWindow_unlockAndPost;
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index e65064b..f5a99ca 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -124,18 +124,6 @@
return isDue || !isPlausible;
}
-bool BufferQueueLayer::setFrameRate(FrameRate frameRate) {
- float oldFrameRate = 0.f;
- status_t result = mConsumer->getFrameRate(&oldFrameRate);
- bool frameRateChanged = result < 0 || frameRate.rate != oldFrameRate;
- mConsumer->setFrameRate(frameRate.rate);
- return frameRateChanged;
-}
-
-Layer::FrameRate BufferQueueLayer::getFrameRate() const {
- return FrameRate(mLatchedFrameRate, Layer::FrameRateCompatibility::Default);
-}
-
// -----------------------------------------------------------------------
// Interface implementation for BufferLayer
// -----------------------------------------------------------------------
@@ -578,7 +566,6 @@
mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse();
float latchedFrameRate;
mConsumer->getFrameRate(&latchedFrameRate);
- mLatchedFrameRate = latchedFrameRate;
}
sp<Layer> BufferQueueLayer::createClone() {
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 626af4b..5f7587c 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -56,9 +56,6 @@
bool shouldPresentNow(nsecs_t expectedPresentTime) const override;
- bool setFrameRate(FrameRate frameRate) override;
- FrameRate getFrameRate() const override;
-
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
@@ -155,8 +152,6 @@
std::atomic<bool> mSidebandStreamChanged{false};
sp<ContentsChangedListener> mContentsChangedListener;
-
- std::atomic<float> mLatchedFrameRate = 0.f;
};
} // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index da26a37..d7647d7 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -26,6 +26,7 @@
#include "Layer.h"
#include <android-base/stringprintf.h>
+#include <android/native_window.h>
#include <binder/IPCThreadState.h>
#include <compositionengine/Display.h>
#include <compositionengine/LayerFECompositionState.h>
@@ -2446,6 +2447,18 @@
layer->mDrawingParent = this;
}
+Layer::FrameRateCompatibility Layer::FrameRate::convertCompatibility(int8_t compatibility) {
+ switch (compatibility) {
+ case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT:
+ return FrameRateCompatibility::Default;
+ case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE:
+ return FrameRateCompatibility::ExactOrMultiple;
+ default:
+ LOG_ALWAYS_FATAL("Invalid frame rate compatibility value %d", compatibility);
+ return FrameRateCompatibility::Default;
+ }
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 37ae340..5d2144a 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -161,6 +161,10 @@
}
bool operator!=(const FrameRate& other) const { return !(*this == other); }
+
+ // Convert an ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* value to a
+ // Layer::FrameRateCompatibility. Logs fatal if the compatibility value is invalid.
+ static FrameRateCompatibility convertCompatibility(int8_t compatibility);
};
struct State {
@@ -795,7 +799,7 @@
*/
Rect getCroppedBufferSize(const Layer::State& s) const;
- virtual bool setFrameRate(FrameRate frameRate);
+ bool setFrameRate(FrameRate frameRate);
virtual FrameRate getFrameRate() const;
protected:
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index bc0111b..a8e6756 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -180,4 +180,3 @@
mActiveLayersEnd = 0;
}
} // namespace android::scheduler::impl
-
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index dcbd934..fbebea0 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>
@@ -3599,9 +3602,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
@@ -4699,6 +4706,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;
@@ -5912,6 +5922,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_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6770c1c..dcbb150 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -493,6 +493,8 @@
status_t notifyPowerHint(int32_t hintId) override;
status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
float lightPosY, float lightPosZ, float lightRadius) override;
+ status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
+ int8_t compatibility) override;
/* ------------------------------------------------------------------------
* DeathRecipient interface
*/
diff --git a/services/surfaceflinger/tests/SetFrameRate_test.cpp b/services/surfaceflinger/tests/SetFrameRate_test.cpp
index fc65263..02ba9e2 100644
--- a/services/surfaceflinger/tests/SetFrameRate_test.cpp
+++ b/services/surfaceflinger/tests/SetFrameRate_test.cpp
@@ -58,17 +58,23 @@
TEST_F(SetFrameRateTest, BufferQueueLayerSetFrameRate) {
CreateLayer(ISurfaceComposerClient::eFXSurfaceBufferQueue);
- native_window_set_frame_rate(mLayer->getSurface().get(), 100.f);
+ native_window_set_frame_rate(mLayer->getSurface().get(), 100.f,
+ ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT);
ASSERT_NO_FATAL_FAILURE(PostBuffers(Color::RED));
- Transaction().setFrameRate(mLayer, 200.f).apply();
+ Transaction()
+ .setFrameRate(mLayer, 200.f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT)
+ .apply();
ASSERT_NO_FATAL_FAILURE(PostBuffers(Color::RED));
- native_window_set_frame_rate(mLayer->getSurface().get(), 300.f);
+ native_window_set_frame_rate(mLayer->getSurface().get(), 300.f,
+ ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT);
ASSERT_NO_FATAL_FAILURE(PostBuffers(Color::RED));
}
TEST_F(SetFrameRateTest, BufferStateLayerSetFrameRate) {
CreateLayer(ISurfaceComposerClient::eFXSurfaceBufferState);
- Transaction().setFrameRate(mLayer, 400.f).apply();
+ Transaction()
+ .setFrameRate(mLayer, 400.f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT)
+ .apply();
ASSERT_NO_FATAL_FAILURE(PostBuffers(Color::GREEN));
}