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*/,
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index 9e515cd..6d91916 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -141,6 +141,8 @@
void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId,
nsecs_t vsyncPeriod) override;
void dispatchNullEvent(nsecs_t, PhysicalDisplayId) override;
+ void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId,
+ std::vector<FrameRateOverride> overrides) override;
void scheduleCallbacks();
@@ -175,8 +177,7 @@
}
Choreographer::Choreographer(const sp<Looper>& looper)
- : DisplayEventDispatcher(looper, ISurfaceComposer::VsyncSource::eVsyncSourceApp,
- ISurfaceComposer::ConfigChanged::eConfigChangedSuppress),
+ : DisplayEventDispatcher(looper, ISurfaceComposer::VsyncSource::eVsyncSourceApp),
mLooper(looper),
mThreadId(std::this_thread::get_id()) {
std::lock_guard<std::mutex> _l(gChoreographers.lock);
@@ -381,15 +382,13 @@
this, to_string(displayId).c_str(), toString(connected));
}
-// TODO(b/74619554): The PhysicalDisplayId is ignored because currently
-// Choreographer only supports dispatching VSYNC events for the internal
-// display, so as such Choreographer does not support the notion of multiple
-// displays. When multi-display choreographer is properly supported, then
-// PhysicalDisplayId should no longer be ignored.
-void Choreographer::dispatchConfigChanged(nsecs_t, PhysicalDisplayId displayId, int32_t configId,
- nsecs_t) {
- ALOGV("choreographer %p ~ received config change event (displayId=%s, configId=%d).",
- this, to_string(displayId).c_str(), configId);
+void Choreographer::dispatchConfigChanged(nsecs_t, PhysicalDisplayId, int32_t, nsecs_t) {
+ LOG_ALWAYS_FATAL("dispatchConfigChanged was called but was never registered");
+}
+
+void Choreographer::dispatchFrameRateOverrides(nsecs_t, PhysicalDisplayId,
+ std::vector<FrameRateOverride>) {
+ LOG_ALWAYS_FATAL("dispatchFrameRateOverrides was called but was never registered");
}
void Choreographer::dispatchNullEvent(nsecs_t, PhysicalDisplayId) {