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