SurfaceFlinger: Add DISPLAY_EVENT_FRAME_RATE_OVERRIDE

Add a new event to DisplayEventReceiver that conveys a list
of apps whose frame rates have been overriden.
This event is processed by the DisplayManager to advertise the
new frame rate to the overridden app.

Change-Id: I89fce8b5b4d9db65ec5db7dd2393c384c0fcfd82
Bug: 169271059
Bug: 169271062
Bug: 170503758
Test: manual test using SF backdoor
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index a0e9cbf..af9ef06 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -237,6 +237,10 @@
         "libnativebase_headers",
     ],
 
+    include_dirs: [
+        "frameworks/native/include",
+    ],
+
     export_shared_lib_headers: [
         "libEGL",
         "libnativewindow",
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index abfee61..c6c9a8f 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -33,10 +33,10 @@
 // using just a few large reads.
 static const size_t EVENT_BUFFER_SIZE = 100;
 
-DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,
-                                               ISurfaceComposer::VsyncSource vsyncSource,
-                                               ISurfaceComposer::ConfigChanged configChanged)
-      : mLooper(looper), mReceiver(vsyncSource, configChanged), mWaitingForVsync(false) {
+DisplayEventDispatcher::DisplayEventDispatcher(
+        const sp<Looper>& looper, ISurfaceComposer::VsyncSource vsyncSource,
+        ISurfaceComposer::EventRegistrationFlags eventRegistration)
+      : mLooper(looper), mReceiver(vsyncSource, eventRegistration), mWaitingForVsync(false) {
     ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
 }
 
@@ -139,6 +139,7 @@
     ssize_t n;
     while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
         ALOGV("dispatcher %p ~ Read %d events.", this, int(n));
+        mFrameRateOverrides.reserve(n);
         for (ssize_t i = 0; i < n; i++) {
             const DisplayEventReceiver::Event& ev = buf[i];
             switch (ev.header.type) {
@@ -162,6 +163,13 @@
                 case DisplayEventReceiver::DISPLAY_EVENT_NULL:
                     dispatchNullEvent(ev.header.timestamp, ev.header.displayId);
                     break;
+                case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE:
+                    mFrameRateOverrides.emplace_back(ev.frameRateOverride);
+                    break;
+                case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH:
+                    dispatchFrameRateOverrides(ev.header.timestamp, ev.header.displayId,
+                                               std::move(mFrameRateOverrides));
+                    break;
                 default:
                     ALOGW("dispatcher %p ~ ignoring unknown event type %#x", this, ev.header.type);
                     break;
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index f2b0962..03b33c7 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -32,11 +32,12 @@
 
 // ---------------------------------------------------------------------------
 
-DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource,
-                                           ISurfaceComposer::ConfigChanged configChanged) {
+DisplayEventReceiver::DisplayEventReceiver(
+        ISurfaceComposer::VsyncSource vsyncSource,
+        ISurfaceComposer::EventRegistrationFlags eventRegistration) {
     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
     if (sf != nullptr) {
-        mEventConnection = sf->createDisplayEventConnection(vsyncSource, configChanged);
+        mEventConnection = sf->createDisplayEventConnection(vsyncSource, eventRegistration);
         if (mEventConnection != nullptr) {
             mDataChannel = std::make_unique<gui::BitTube>();
             mEventConnection->stealReceiveChannel(mDataChannel.get());
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index a9fe5bf..e46a415 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -223,8 +223,8 @@
         return NO_ERROR;
     }
 
-    virtual sp<IDisplayEventConnection> createDisplayEventConnection(VsyncSource vsyncSource,
-                                                                     ConfigChanged configChanged) {
+    virtual sp<IDisplayEventConnection> createDisplayEventConnection(
+            VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) {
         Parcel data, reply;
         sp<IDisplayEventConnection> result;
         int err = data.writeInterfaceToken(
@@ -233,7 +233,7 @@
             return result;
         }
         data.writeInt32(static_cast<int32_t>(vsyncSource));
-        data.writeInt32(static_cast<int32_t>(configChanged));
+        data.writeUint32(eventRegistration.get());
         err = remote()->transact(
                 BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION,
                 data, &reply);
@@ -1373,10 +1373,11 @@
         case CREATE_DISPLAY_EVENT_CONNECTION: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             auto vsyncSource = static_cast<ISurfaceComposer::VsyncSource>(data.readInt32());
-            auto configChanged = static_cast<ISurfaceComposer::ConfigChanged>(data.readInt32());
+            EventRegistrationFlags eventRegistration =
+                    static_cast<EventRegistration>(data.readUint32());
 
             sp<IDisplayEventConnection> connection(
-                    createDisplayEventConnection(vsyncSource, configChanged));
+                    createDisplayEventConnection(vsyncSource, eventRegistration));
             reply->writeStrongBinder(IInterface::asBinder(connection));
             return NO_ERROR;
         }
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index c65618b..5587acf 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -19,6 +19,7 @@
 #include <utils/Looper.h>
 
 namespace android {
+using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
 
 struct VsyncEventData {
     // The Vsync Id corresponsing to this vsync event. This will be used to
@@ -36,8 +37,7 @@
     explicit DisplayEventDispatcher(
             const sp<Looper>& looper,
             ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp,
-            ISurfaceComposer::ConfigChanged configChanged =
-                    ISurfaceComposer::eConfigChangedSuppress);
+            ISurfaceComposer::EventRegistrationFlags eventRegistration = {});
 
     status_t initialize();
     void dispose();
@@ -54,6 +54,8 @@
     DisplayEventReceiver mReceiver;
     bool mWaitingForVsync;
 
+    std::vector<FrameRateOverride> mFrameRateOverrides;
+
     virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count,
                                VsyncEventData vsyncEventData) = 0;
     virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId,
@@ -64,6 +66,9 @@
     // can be properly poked.
     virtual void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) = 0;
 
+    virtual void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId,
+                                            std::vector<FrameRateOverride> overrides) = 0;
+
     bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId,
                               uint32_t* outCount, VsyncEventData* outVsyncEventData);
 };
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index df3118f..3191fc9 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -54,6 +54,8 @@
         DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'),
         DISPLAY_EVENT_CONFIG_CHANGED = fourcc('c', 'o', 'n', 'f'),
         DISPLAY_EVENT_NULL = fourcc('n', 'u', 'l', 'l'),
+        DISPLAY_EVENT_FRAME_RATE_OVERRIDE = fourcc('r', 'a', 't', 'e'),
+        DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH = fourcc('f', 'l', 's', 'h'),
     };
 
     struct Event {
@@ -85,11 +87,17 @@
             nsecs_t vsyncPeriod __attribute__((aligned(8)));
         };
 
+        struct FrameRateOverride {
+            uid_t uid __attribute__((aligned(8)));
+            float frameRateHz __attribute__((aligned(8)));
+        };
+
         Header header;
         union {
             VSync vsync;
             Hotplug hotplug;
             Config config;
+            FrameRateOverride frameRateOverride;
         };
     };
 
@@ -98,13 +106,12 @@
      * DisplayEventReceiver creates and registers an event connection with
      * SurfaceFlinger. VSync events are disabled by default. Call setVSyncRate
      * or requestNextVsync to receive them.
-     * To receive Config Changed events specify this in the constructor.
-     * Other events start being delivered immediately.
+     * To receive ConfigChanged and/or FrameRateOverrides events specify this in
+     * the constructor. Other events start being delivered immediately.
      */
     explicit DisplayEventReceiver(
             ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp,
-            ISurfaceComposer::ConfigChanged configChanged =
-                    ISurfaceComposer::eConfigChangedSuppress);
+            ISurfaceComposer::EventRegistrationFlags eventRegistration = {});
 
     /*
      * ~DisplayEventReceiver severs the connection with SurfaceFlinger, new events
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 9e96b79..86e3a25 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -26,6 +26,8 @@
 #include <gui/IScreenCaptureListener.h>
 #include <gui/ITransactionCompletedListener.h>
 
+#include <input/Flags.h>
+
 #include <math/vec4.h>
 
 #include <ui/ConfigStoreTypes.h>
@@ -107,7 +109,12 @@
         eVsyncSourceSurfaceFlinger = 1
     };
 
-    enum ConfigChanged { eConfigChangedSuppress = 0, eConfigChangedDispatch = 1 };
+    enum class EventRegistration {
+        configChanged = 1 << 0,
+        frameRateOverride = 1 << 1,
+    };
+
+    using EventRegistrationFlags = Flags<EventRegistration>;
 
     // Needs to be in sync with android.graphics.FrameInfo.INVALID_VSYNC_ID in java
     static constexpr int64_t INVALID_VSYNC_ID = -1;
@@ -120,7 +127,7 @@
     /* return an IDisplayEventConnection */
     virtual sp<IDisplayEventConnection> createDisplayEventConnection(
             VsyncSource vsyncSource = eVsyncSourceApp,
-            ConfigChanged configChanged = eConfigChangedSuppress) = 0;
+            EventRegistrationFlags eventRegistration = {}) = 0;
 
     /* create a virtual display
      * requires ACCESS_SURFACE_FLINGER permission.
diff --git a/libs/gui/tests/DisplayEventStructLayout_test.cpp b/libs/gui/tests/DisplayEventStructLayout_test.cpp
index 7210910..c5093e2 100644
--- a/libs/gui/tests/DisplayEventStructLayout_test.cpp
+++ b/libs/gui/tests/DisplayEventStructLayout_test.cpp
@@ -40,6 +40,9 @@
 
     CHECK_OFFSET(DisplayEventReceiver::Event::Config, configId, 0);
     CHECK_OFFSET(DisplayEventReceiver::Event::Config, vsyncPeriod, 8);
+
+    CHECK_OFFSET(DisplayEventReceiver::Event::FrameRateOverride, uid, 0);
+    CHECK_OFFSET(DisplayEventReceiver::Event::FrameRateOverride, frameRateHz, 8);
 }
 
 } // namespace android::test
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 2392ae5..ce3afa2 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -687,7 +687,7 @@
 
     sp<ISurfaceComposerClient> createConnection() override { return nullptr; }
     sp<IDisplayEventConnection> createDisplayEventConnection(
-            ISurfaceComposer::VsyncSource, ISurfaceComposer::ConfigChanged) override {
+            ISurfaceComposer::VsyncSource, ISurfaceComposer::EventRegistrationFlags) override {
         return nullptr;
     }
     sp<IBinder> createDisplay(const String8& /*displayName*/,