Add plumbing for upcoming setFrameRate() api
Add plumbing from the app to surface flinger for the
ANativeWindow_setFrameRate() and ASurfaceTransaction_setFrameRate() api
calls we'll be adding soon.
We don't do anything in surface flinger with this data yet.
Bug: 143912624
Test: Added a new test, SetFrameRateTest.
Change-Id: I1cab87f3ce5afca4591a39d8e7a42cb1e86a368f
diff --git a/libs/gui/BufferHubConsumer.cpp b/libs/gui/BufferHubConsumer.cpp
index b5cdeb2..0ddb87e 100644
--- a/libs/gui/BufferHubConsumer.cpp
+++ b/libs/gui/BufferHubConsumer.cpp
@@ -147,6 +147,16 @@
return INVALID_OPERATION;
}
+status_t BufferHubConsumer::setFrameRate(float /*frameRate*/) {
+ ALOGE("BufferHubConsumer::setFrameRate: not implemented.");
+ return INVALID_OPERATION;
+}
+
+status_t BufferHubConsumer::getFrameRate(float* /*frameRate*/) const {
+ ALOGE("BufferHubConsumer::getFrameRate: not implemented.");
+ return INVALID_OPERATION;
+}
+
status_t BufferHubConsumer::dumpState(const String8& /*prefix*/, String8* /*outResult*/) const {
ALOGE("BufferHubConsumer::dumpState: not implemented.");
return INVALID_OPERATION;
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 6418e8c..9b74fef 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -775,6 +775,18 @@
return NO_ERROR;
}
+status_t BufferQueueConsumer::setFrameRate(float frameRate) {
+ std::lock_guard<std::mutex> lock(mCore->mMutex);
+ mCore->mFrameRate = frameRate;
+ return NO_ERROR;
+}
+
+status_t BufferQueueConsumer::getFrameRate(float* frameRate) const {
+ std::lock_guard<std::mutex> lock(mCore->mMutex);
+ *frameRate = mCore->mFrameRate;
+ return NO_ERROR;
+}
+
status_t BufferQueueConsumer::dumpState(const String8& prefix, String8* outResult) const {
struct passwd* pwd = getpwnam("shell");
uid_t shellUid = pwd ? pwd->pw_uid : 0;
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index e6df757..6b11a54 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -1670,4 +1670,14 @@
return NO_ERROR;
}
+status_t BufferQueueProducer::setFrameRate(float frameRate) {
+ ATRACE_CALL();
+ BQ_LOGV("setFrameRate: %.0f", frameRate);
+
+ std::lock_guard<std::mutex> lock(mCore->mMutex);
+
+ mCore->mFrameRate = frameRate;
+ return NO_ERROR;
+}
+
} // namespace android
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 9f91d9d..515f45c 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -363,6 +363,24 @@
return OK;
}
+status_t ConsumerBase::setFrameRate(float frameRate) {
+ Mutex::Autolock _l(mMutex);
+ if (mAbandoned) {
+ CB_LOGE("setFrameRate: ConsumerBase is abandoned!");
+ return NO_INIT;
+ }
+ return mConsumer->setFrameRate(frameRate);
+}
+
+status_t ConsumerBase::getFrameRate(float* frameRate) {
+ Mutex::Autolock _l(mMutex);
+ if (mAbandoned) {
+ CB_LOGE("getFrameRate: ConsumerBase is abandoned!");
+ return NO_INIT;
+ }
+ return mConsumer->getFrameRate(frameRate);
+}
+
void ConsumerBase::dumpState(String8& result) const {
dumpState(result, "");
}
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index c705d39..2521a7c 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -51,6 +51,8 @@
GET_SIDEBAND_STREAM,
GET_OCCUPANCY_HISTORY,
DISCARD_FREE_BUFFERS,
+ SET_FRAME_RATE,
+ GET_FRAME_RATE,
DUMP_STATE,
LAST = DUMP_STATE,
};
@@ -163,6 +165,16 @@
Tag::DISCARD_FREE_BUFFERS);
}
+ status_t setFrameRate(float frameRate) override {
+ using Signature = decltype(&IGraphicBufferConsumer::setFrameRate);
+ return callRemote<Signature>(Tag::SET_FRAME_RATE, frameRate);
+ }
+
+ status_t getFrameRate(float* frameRate) const override {
+ using Signature = decltype(&IGraphicBufferConsumer::getFrameRate);
+ return callRemote<Signature>(Tag::GET_FRAME_RATE, frameRate);
+ }
+
status_t dumpState(const String8& prefix, String8* outResult) const override {
using Signature = status_t (IGraphicBufferConsumer::*)(const String8&, String8*) const;
return callRemote<Signature>(Tag::DUMP_STATE, prefix, outResult);
@@ -220,6 +232,10 @@
return callLocal(data, reply, &IGraphicBufferConsumer::getOccupancyHistory);
case Tag::DISCARD_FREE_BUFFERS:
return callLocal(data, reply, &IGraphicBufferConsumer::discardFreeBuffers);
+ case Tag::SET_FRAME_RATE:
+ return callLocal(data, reply, &IGraphicBufferConsumer::setFrameRate);
+ case Tag::GET_FRAME_RATE:
+ return callLocal(data, reply, &IGraphicBufferConsumer::getFrameRate);
case Tag::DUMP_STATE: {
using Signature = status_t (IGraphicBufferConsumer::*)(const String8&, String8*) const;
return callLocal<Signature>(data, reply, &IGraphicBufferConsumer::dumpState);
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 0009a57..75876f2 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -74,6 +74,7 @@
GET_CONSUMER_USAGE,
SET_LEGACY_BUFFER_DROP,
SET_AUTO_PREROTATION,
+ SET_FRAME_RATE,
};
class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -559,6 +560,14 @@
}
return result;
}
+
+ virtual status_t setFrameRate(float frameRate) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+ data.writeFloat(frameRate);
+ status_t result = remote()->transact(SET_FRAME_RATE, data, &reply, IBinder::FLAG_ONEWAY);
+ return result;
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -691,6 +700,8 @@
status_t setAutoPrerotation(bool autoPrerotation) override {
return mBase->setAutoPrerotation(autoPrerotation);
}
+
+ status_t setFrameRate(float frameRate) override { return mBase->setFrameRate(frameRate); }
};
IMPLEMENT_HYBRID_META_INTERFACE(GraphicBufferProducer,
@@ -710,6 +721,12 @@
return INVALID_OPERATION;
}
+status_t IGraphicBufferProducer::setFrameRate(float frameRate) {
+ // No-op for IGBP other than BufferQueue.
+ (void)frameRate;
+ return INVALID_OPERATION;
+}
+
status_t IGraphicBufferProducer::exportToParcel(Parcel* parcel) {
status_t res = OK;
res = parcel->writeUint32(USE_BUFFER_QUEUE);
@@ -1079,6 +1096,13 @@
reply->writeInt32(result);
return NO_ERROR;
}
+ case SET_FRAME_RATE: {
+ CHECK_INTERFACE(IGraphicBuffer, data, reply);
+ float frameRate = data.readFloat();
+ status_t result = setFrameRate(frameRate);
+ reply->writeInt32(result);
+ return NO_ERROR;
+ }
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 8b448ff..39b4d4b 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -110,9 +110,8 @@
}
}
output.writeFloat(shadowRadius);
-
output.writeInt32(frameRateSelectionPriority);
-
+ output.writeFloat(frameRate);
return NO_ERROR;
}
@@ -191,9 +190,8 @@
listeners.emplace_back(listener, callbackIds);
}
shadowRadius = input.readFloat();
-
frameRateSelectionPriority = input.readInt32();
-
+ frameRate = input.readFloat();
return NO_ERROR;
}
@@ -420,6 +418,10 @@
what |= eFrameRateSelectionPriority;
frameRateSelectionPriority = other.frameRateSelectionPriority;
}
+ if (other.what & eFrameRateChanged) {
+ what |= eFrameRateChanged;
+ frameRate = other.frameRate;
+ }
if ((other.what & what) != other.what) {
ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
"other.what=0x%" PRIu64 " what=0x%" PRIu64,
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index e490d6d..d5cf11d 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1093,6 +1093,9 @@
case NATIVE_WINDOW_GET_LAST_QUEUE_DURATION:
res = dispatchGetLastQueueDuration(args);
break;
+ case NATIVE_WINDOW_SET_FRAME_RATE:
+ res = dispatchSetFrameRate(args);
+ break;
default:
res = NAME_NOT_FOUND;
break;
@@ -1321,6 +1324,11 @@
return NO_ERROR;
}
+int Surface::dispatchSetFrameRate(va_list args) {
+ float frameRate = static_cast<float>(va_arg(args, double));
+ return setFrameRate(frameRate);
+}
+
bool Surface::transformToDisplayInverse() {
return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) ==
NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
@@ -2064,4 +2072,11 @@
mSurfaceListener->onBuffersDiscarded(discardedBufs);
}
+status_t Surface::setFrameRate(float frameRate) {
+ ATRACE_CALL();
+ ALOGV("Surface::setTargetFrameRate");
+ Mutex::Autolock lock(mMutex);
+ return mGraphicBufferProducer->setFrameRate(frameRate);
+}
+
}; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 2ef33cf..20614f8 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1376,6 +1376,18 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameRate(
+ const sp<SurfaceControl>& sc, float frameRate) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+ s->what |= layer_state_t::eFrameRateChanged;
+ s->frameRate = frameRate;
+ return *this;
+}
+
// ---------------------------------------------------------------------------
DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp<IBinder>& token) {
diff --git a/libs/gui/include/gui/BufferHubConsumer.h b/libs/gui/include/gui/BufferHubConsumer.h
index d380770..d756203 100644
--- a/libs/gui/include/gui/BufferHubConsumer.h
+++ b/libs/gui/include/gui/BufferHubConsumer.h
@@ -93,6 +93,12 @@
// See |IGraphicBufferConsumer::discardFreeBuffers|
status_t discardFreeBuffers() override;
+ // See |IGraphicBufferConsumer::setFrameRate|
+ status_t setFrameRate(float frameRate) override;
+
+ // See |IGraphicBufferConsumer::getFrameRate|
+ status_t getFrameRate(float* frameRate) const override;
+
// See |IGraphicBufferConsumer::dumpState|
status_t dumpState(const String8& prefix, String8* outResult) const override;
diff --git a/libs/gui/include/gui/BufferQueueConsumer.h b/libs/gui/include/gui/BufferQueueConsumer.h
index 7db69ec..e9f0449 100644
--- a/libs/gui/include/gui/BufferQueueConsumer.h
+++ b/libs/gui/include/gui/BufferQueueConsumer.h
@@ -149,6 +149,12 @@
// See IGraphicBufferConsumer::discardFreeBuffers
virtual status_t discardFreeBuffers() override;
+ // See IGraphicBufferConsumer::setFrameRate.
+ virtual status_t setFrameRate(float frameRate) override;
+
+ // See IGraphicBufferConsumer::getFrameRate.
+ virtual status_t getFrameRate(float* frameRate) const override;
+
// dump our state in a String
status_t dumpState(const String8& prefix, String8* outResult) const override;
diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h
index 557c28b..05c2074 100644
--- a/libs/gui/include/gui/BufferQueueCore.h
+++ b/libs/gui/include/gui/BufferQueueCore.h
@@ -354,6 +354,9 @@
// mTransformHintInUse is to cache the mTransformHint used by the producer.
uint32_t mTransformHintInUse;
+ // The frame rate the app intends to run at.
+ float mFrameRate;
+
}; // class BufferQueueCore
} // namespace android
diff --git a/libs/gui/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h
index 9ad92a6..2dec663 100644
--- a/libs/gui/include/gui/BufferQueueProducer.h
+++ b/libs/gui/include/gui/BufferQueueProducer.h
@@ -193,6 +193,9 @@
// See IGraphicBufferProducer::setAutoPrerotation
virtual status_t setAutoPrerotation(bool autoPrerotation);
+ // See IGraphicBufferProducer::setFrameRate
+ virtual status_t setFrameRate(float frameRate) override;
+
private:
// This is required by the IBinder::DeathRecipient interface
virtual void binderDied(const wp<IBinder>& who);
diff --git a/libs/gui/include/gui/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h
index 8ff0cd0..cfed9aa 100644
--- a/libs/gui/include/gui/ConsumerBase.h
+++ b/libs/gui/include/gui/ConsumerBase.h
@@ -111,6 +111,12 @@
// See IGraphicBufferConsumer::discardFreeBuffers
status_t discardFreeBuffers();
+ // See IGraphicBufferConsumer::setFrameRate
+ status_t setFrameRate(float frameRate);
+
+ // See IGraphicBufferConsumer::getFrameRate
+ status_t getFrameRate(float* frameRate);
+
private:
ConsumerBase(const ConsumerBase&);
void operator=(const ConsumerBase&);
diff --git a/libs/gui/include/gui/IGraphicBufferConsumer.h b/libs/gui/include/gui/IGraphicBufferConsumer.h
index 9fb7580..54f77b4 100644
--- a/libs/gui/include/gui/IGraphicBufferConsumer.h
+++ b/libs/gui/include/gui/IGraphicBufferConsumer.h
@@ -271,6 +271,16 @@
// call to free up any of its locally cached buffers.
virtual status_t discardFreeBuffers() = 0;
+ // Set the frame rate the producer will run at.
+ //
+ // Return of a value other than NO_ERROR means an unknown error has occurred.
+ virtual status_t setFrameRate(float frameRate) = 0;
+
+ // Get the frame rate the producer will run at.
+ //
+ // Return of a value other than NO_ERROR means an unknown error has occurred.
+ virtual status_t getFrameRate(float* frameRate) const = 0;
+
// dump state into a string
virtual status_t dumpState(const String8& prefix, String8* outResult) const = 0;
diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h
index 25ce1ca..680d64e 100644
--- a/libs/gui/include/gui/IGraphicBufferProducer.h
+++ b/libs/gui/include/gui/IGraphicBufferProducer.h
@@ -637,6 +637,9 @@
// the width and height used for dequeueBuffer will be additionally swapped.
virtual status_t setAutoPrerotation(bool autoPrerotation);
+ // Sets the apps intended frame rate.
+ virtual status_t setFrameRate(float frameRate);
+
// Static method exports any IGraphicBufferProducer object to a parcel. It
// handles null producer as well.
static status_t exportToParcel(const sp<IGraphicBufferProducer>& producer,
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 03e91c4..cf64193 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -100,6 +100,7 @@
eMetadataChanged = 0x8'00000000,
eColorSpaceAgnosticChanged = 0x10'00000000,
eFrameRateSelectionPriority = 0x20'00000000,
+ eFrameRateChanged = 0x40'00000000,
};
layer_state_t()
@@ -130,7 +131,8 @@
bgColorDataspace(ui::Dataspace::UNKNOWN),
colorSpaceAgnostic(false),
shadowRadius(0.0f),
- frameRateSelectionPriority(-1) {
+ frameRateSelectionPriority(-1),
+ frameRate(0.0f) {
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
hdrMetadata.validTypes = 0;
@@ -214,6 +216,8 @@
// Priority of the layer assigned by Window Manager.
int32_t frameRateSelectionPriority;
+
+ float frameRate;
};
struct ComposerState {
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index e582509..86cc61f 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -179,6 +179,9 @@
status_t getUniqueId(uint64_t* outId) const;
status_t getConsumerUsage(uint64_t* outUsage) const;
+ // See IGraphicBufferProducer::setFrameRate
+ status_t setFrameRate(float frameRate);
+
protected:
virtual ~Surface();
@@ -248,6 +251,7 @@
int dispatchSetDequeueTimeout(va_list args);
int dispatchGetLastDequeueDuration(va_list args);
int dispatchGetLastQueueDuration(va_list args);
+ int dispatchSetFrameRate(va_list args);
bool transformToDisplayInverse();
protected:
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 6a3f452..71ee82a 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -520,6 +520,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);
+
status_t setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
diff --git a/libs/gui/include/gui/mock/GraphicBufferConsumer.h b/libs/gui/include/gui/mock/GraphicBufferConsumer.h
index 98f24c2..e940cf3 100644
--- a/libs/gui/include/gui/mock/GraphicBufferConsumer.h
+++ b/libs/gui/include/gui/mock/GraphicBufferConsumer.h
@@ -49,6 +49,8 @@
MOCK_CONST_METHOD1(getSidebandStream, status_t(sp<NativeHandle>*));
MOCK_METHOD2(getOccupancyHistory, status_t(bool, std::vector<OccupancyTracker::Segment>*));
MOCK_METHOD0(discardFreeBuffers, status_t());
+ MOCK_METHOD1(setFrameRate, status_t(float));
+ MOCK_CONST_METHOD1(getFrameRate, status_t(float*));
MOCK_CONST_METHOD2(dumpState, status_t(const String8&, String8*));
};
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 1814ab5..14f7214 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -34,12 +34,12 @@
#include <cutils/native_handle.h>
#include <errno.h>
#include <limits.h>
+#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <sys/cdefs.h>
#include <system/graphics.h>
#include <unistd.h>
-#include <stdbool.h>
// system/window.h is a superset of the vndk and apex apis
#include <apex/window.h>
@@ -247,6 +247,7 @@
NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT = 37, /* private */
NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION = 38, /* private */
NATIVE_WINDOW_GET_LAST_QUEUE_DURATION = 39, /* private */
+ NATIVE_WINDOW_SET_FRAME_RATE = 40,
// clang-format on
};
@@ -1008,4 +1009,8 @@
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);
+}
+
__END_DECLS