From a524a098e9280897a965bae16efd27469ff01ea4 Mon Sep 17 00:00:00 2001 From: Marin Shalamanov Date: Mon, 27 Jul 2020 21:39:55 +0200 Subject: Use type safe display IDs. Use a type safe wrapper around uint64_t for display ids. We also modify the format of the EDID generated physical display IDs by setting bit 62 to 1, which will indicate that the display id is stable across reboot. Bug: 160679868 Test: m && flash device Test: take screnshot on device Test: atest surfaceflinger_unittest Change-Id: Ie2c7c2b737e0882fa4208c059caa85b7ded922b2 --- libs/gui/DisplayEventDispatcher.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'libs/gui/DisplayEventDispatcher.cpp') diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp index b33bc9e556..51fbb9748b 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -121,9 +121,8 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) { PhysicalDisplayId vsyncDisplayId; uint32_t vsyncCount; if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) { - ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 - ", displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", count=%d", - this, ns2ms(vsyncTimestamp), vsyncDisplayId, vsyncCount); + ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", displayId=%s, count=%d", this, + ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount); mWaitingForVsync = false; dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount); } -- cgit v1.2.3-59-g8ed1b From 967d5d73fb9647846b14e3e442c374361cf99b68 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Wed, 5 Aug 2020 12:50:03 -0700 Subject: Fix refresh rate callback fan-out for choreographer * AChoreographer receives refresh rates from DisplayManager already, so there's no need to default-enable them - AChoreographer only needs to pump an event with the latest refresh rate to wake up looper. This also ensures that AChoreographer's callbacks are entirely in-sync with DisplayManager since there's no raciness. * Instead of re-requesting a config change from SF, instead inject it in AChoreographer correctly to save on binder. Bug: 154874011 Bug: 158680912 Bug: 161406626 Test: while [ true ]; do adb shell service call SurfaceFlinger 1035 i32 1; adb shell service call SurfaceFlinger 1035 i32 0; and repeatedly rotate the home screen with auto-rotate off. Change-Id: I66abc2e28e60f06987ce3a54be294c94b77524fc --- libs/gui/BitTube.cpp | 16 ++++++++++ libs/gui/DisplayEventDispatcher.cpp | 12 +++---- libs/gui/DisplayEventReceiver.cpp | 12 +++---- libs/gui/IDisplayEventConnection.cpp | 10 +----- libs/gui/include/gui/DisplayEventDispatcher.h | 5 ++- libs/gui/include/gui/DisplayEventReceiver.h | 8 ++--- libs/gui/include/gui/IDisplayEventConnection.h | 5 --- libs/gui/include/private/gui/BitTube.h | 5 ++- libs/nativedisplay/AChoreographer.cpp | 36 +++++++++------------ services/surfaceflinger/Scheduler/EventThread.cpp | 39 ++--------------------- services/surfaceflinger/Scheduler/EventThread.h | 14 +------- 11 files changed, 55 insertions(+), 107 deletions(-) (limited to 'libs/gui/DisplayEventDispatcher.cpp') diff --git a/libs/gui/BitTube.cpp b/libs/gui/BitTube.cpp index ef7a6f54d9..351af652e2 100644 --- a/libs/gui/BitTube.cpp +++ b/libs/gui/BitTube.cpp @@ -86,6 +86,10 @@ void BitTube::setReceiveFd(base::unique_fd&& receiveFd) { mReceiveFd = std::move(receiveFd); } +void BitTube::setSendFd(base::unique_fd&& sendFd) { + mSendFd = std::move(sendFd); +} + ssize_t BitTube::write(void const* vaddr, size_t size) { ssize_t err, len; do { @@ -115,6 +119,11 @@ status_t BitTube::writeToParcel(Parcel* reply) const { status_t result = reply->writeDupFileDescriptor(mReceiveFd); mReceiveFd.reset(); + if (result != NO_ERROR) { + return result; + } + result = reply->writeDupFileDescriptor(mSendFd); + mSendFd.reset(); return result; } @@ -126,6 +135,13 @@ status_t BitTube::readFromParcel(const Parcel* parcel) { ALOGE("BitTube::readFromParcel: can't dup file descriptor (%s)", strerror(error)); return -error; } + mSendFd.reset(dup(parcel->readFileDescriptor())); + if (mSendFd < 0) { + mSendFd.reset(); + int error = errno; + ALOGE("BitTube::readFromParcel: can't dup file descriptor (%s)", strerror(error)); + return -error; + } return NO_ERROR; } diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp index 51fbb9748b..2cc7c34c40 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -89,12 +89,8 @@ status_t DisplayEventDispatcher::scheduleVsync() { return OK; } -void DisplayEventDispatcher::requestLatestConfig() { - status_t status = mReceiver.requestLatestConfig(); - if (status) { - ALOGW("Failed enable config events, status=%d", status); - return; - } +void DisplayEventDispatcher::injectEvent(const DisplayEventReceiver::Event& event) { + mReceiver.sendEvents(&event, 1); } int DisplayEventDispatcher::getFd() const { @@ -156,6 +152,9 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, dispatchConfigChanged(ev.header.timestamp, ev.header.displayId, ev.config.configId, ev.config.vsyncPeriod); break; + case DisplayEventReceiver::DISPLAY_EVENT_NULL: + dispatchNullEvent(ev.header.timestamp, ev.header.displayId); + break; default: ALOGW("dispatcher %p ~ ignoring unknown event type %#x", this, ev.header.type); break; @@ -167,4 +166,5 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, } return gotVsync; } + } // namespace android diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp index 1fed509003..f2b0962eb7 100644 --- a/libs/gui/DisplayEventReceiver.cpp +++ b/libs/gui/DisplayEventReceiver.cpp @@ -79,14 +79,6 @@ status_t DisplayEventReceiver::requestNextVsync() { return NO_INIT; } -status_t DisplayEventReceiver::requestLatestConfig() { - if (mEventConnection != nullptr) { - mEventConnection->requestLatestConfig(); - return NO_ERROR; - } - return NO_INIT; -} - ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events, size_t count) { return DisplayEventReceiver::getEvents(mDataChannel.get(), events, count); @@ -98,6 +90,10 @@ ssize_t DisplayEventReceiver::getEvents(gui::BitTube* dataChannel, return gui::BitTube::recvObjects(dataChannel, events, count); } +ssize_t DisplayEventReceiver::sendEvents(Event const* events, size_t count) { + return DisplayEventReceiver::sendEvents(mDataChannel.get(), events, count); +} + ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel, Event const* events, size_t count) { diff --git a/libs/gui/IDisplayEventConnection.cpp b/libs/gui/IDisplayEventConnection.cpp index aa74bfd3f8..c0e246fa15 100644 --- a/libs/gui/IDisplayEventConnection.cpp +++ b/libs/gui/IDisplayEventConnection.cpp @@ -26,8 +26,7 @@ enum class Tag : uint32_t { STEAL_RECEIVE_CHANNEL = IBinder::FIRST_CALL_TRANSACTION, SET_VSYNC_RATE, REQUEST_NEXT_VSYNC, - REQUEST_LATEST_CONFIG, - LAST = REQUEST_LATEST_CONFIG, + LAST = REQUEST_NEXT_VSYNC, }; } // Anonymous namespace @@ -54,11 +53,6 @@ public: callRemoteAsync( Tag::REQUEST_NEXT_VSYNC); } - - void requestLatestConfig() override { - callRemoteAsync( - Tag::REQUEST_LATEST_CONFIG); - } }; // Out-of-line virtual method definition to trigger vtable emission in this translation unit (see @@ -80,8 +74,6 @@ status_t BnDisplayEventConnection::onTransact(uint32_t code, const Parcel& data, return callLocal(data, reply, &IDisplayEventConnection::setVsyncRate); case Tag::REQUEST_NEXT_VSYNC: return callLocalAsync(data, reply, &IDisplayEventConnection::requestNextVsync); - case Tag::REQUEST_LATEST_CONFIG: - return callLocalAsync(data, reply, &IDisplayEventConnection::requestLatestConfig); } } diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h index f210c34196..eb5b00418a 100644 --- a/libs/gui/include/gui/DisplayEventDispatcher.h +++ b/libs/gui/include/gui/DisplayEventDispatcher.h @@ -31,7 +31,7 @@ public: status_t initialize(); void dispose(); status_t scheduleVsync(); - void requestLatestConfig(); + void injectEvent(const DisplayEventReceiver::Event& event); int getFd() const; virtual int handleEvent(int receiveFd, int events, void* data); @@ -48,6 +48,9 @@ private: bool connected) = 0; virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId, nsecs_t vsyncPeriod) = 0; + // AChoreographer-specific hook for processing null-events so that looper + // can be properly poked. + virtual void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) = 0; bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, uint32_t* outCount); diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h index 8d49184caf..0e10d1ad8e 100644 --- a/libs/gui/include/gui/DisplayEventReceiver.h +++ b/libs/gui/include/gui/DisplayEventReceiver.h @@ -53,6 +53,7 @@ public: DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'), 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'), }; struct Event { @@ -130,6 +131,7 @@ public: * sendEvents write events to the queue and returns how many events were * written. */ + ssize_t sendEvents(Event const* events, size_t count); static ssize_t sendEvents(gui::BitTube* dataChannel, Event const* events, size_t count); /* @@ -146,12 +148,6 @@ public: */ status_t requestNextVsync(); - /* - * requestLatestConfig() force-requests the current config for the primary - * display. - */ - status_t requestLatestConfig(); - private: sp mEventConnection; std::unique_ptr mDataChannel; diff --git a/libs/gui/include/gui/IDisplayEventConnection.h b/libs/gui/include/gui/IDisplayEventConnection.h index 674aafd81c..cff22a368a 100644 --- a/libs/gui/include/gui/IDisplayEventConnection.h +++ b/libs/gui/include/gui/IDisplayEventConnection.h @@ -51,11 +51,6 @@ public: * requestNextVsync() schedules the next vsync event. It has no effect if the vsync rate is > 0. */ virtual void requestNextVsync() = 0; // Asynchronous - - /* - * requestLatestConfig() requests the config for the primary display. - */ - virtual void requestLatestConfig() = 0; // Asynchronous }; class BnDisplayEventConnection : public SafeBnInterface { diff --git a/libs/gui/include/private/gui/BitTube.h b/libs/gui/include/private/gui/BitTube.h index 13c01623b7..80485184bd 100644 --- a/libs/gui/include/private/gui/BitTube.h +++ b/libs/gui/include/private/gui/BitTube.h @@ -58,6 +58,9 @@ public: // resets this BitTube's receive file descriptor to receiveFd void setReceiveFd(base::unique_fd&& receiveFd); + // resets this BitTube's send file descriptor to sendFd + void setSendFd(base::unique_fd&& sendFd); + // send objects (sized blobs). All objects are guaranteed to be written or the call fails. template static ssize_t sendObjects(BitTube* tube, T const* events, size_t count) { @@ -85,7 +88,7 @@ private: // the message, excess data is silently discarded. ssize_t read(void* vaddr, size_t size); - base::unique_fd mSendFd; + mutable base::unique_fd mSendFd; mutable base::unique_fd mReceiveFd; static ssize_t sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize); diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp index ebc8909179..ff1b5e6d34 100644 --- a/libs/nativedisplay/AChoreographer.cpp +++ b/libs/nativedisplay/AChoreographer.cpp @@ -136,6 +136,7 @@ private: void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override; void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId, nsecs_t vsyncPeriod) override; + void dispatchNullEvent(nsecs_t, PhysicalDisplayId) override; void scheduleCallbacks(); @@ -170,7 +171,7 @@ Choreographer* Choreographer::getForThread() { Choreographer::Choreographer(const sp& looper) : DisplayEventDispatcher(looper, ISurfaceComposer::VsyncSource::eVsyncSourceApp, - ISurfaceComposer::ConfigChanged::eConfigChangedDispatch), + ISurfaceComposer::ConfigChanged::eConfigChangedSuppress), mLooper(looper), mThreadId(std::this_thread::get_id()) { std::lock_guard _l(gChoreographers.lock); @@ -294,8 +295,14 @@ void Choreographer::scheduleLatestConfigRequest() { } else { // If the looper thread is detached from Choreographer, then refresh rate // changes will be handled in AChoreographer_handlePendingEvents, so we - // need to redispatch a config from SF - requestLatestConfig(); + // need to wake up the looper thread by writing to the write-end of the + // socket the looper is listening on. + // Fortunately, these events are small so sending packets across the + // socket should be atomic across processes. + DisplayEventReceiver::Event event; + event.header = DisplayEventReceiver::Event::Header{DisplayEventReceiver::DISPLAY_EVENT_NULL, + PhysicalDisplayId(0), systemTime()}; + injectEvent(event); } } @@ -373,27 +380,14 @@ void Choreographer::dispatchHotplug(nsecs_t, PhysicalDisplayId displayId, bool c // 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 vsyncPeriod) { + nsecs_t) { ALOGV("choreographer %p ~ received config change event (displayId=%s, configId=%d).", this, to_string(displayId).c_str(), configId); +} - const nsecs_t lastPeriod = mLatestVsyncPeriod; - std::vector callbacks{}; - { - std::lock_guard _l{mLock}; - for (auto& cb : mRefreshRateCallbacks) { - callbacks.push_back(cb); - cb.firstCallbackFired = true; - } - } - - for (auto& cb : callbacks) { - if (!cb.firstCallbackFired || (vsyncPeriod > 0 && vsyncPeriod != lastPeriod)) { - cb.callback(vsyncPeriod, cb.data); - } - } - - mLatestVsyncPeriod = vsyncPeriod; +void Choreographer::dispatchNullEvent(nsecs_t, PhysicalDisplayId) { + ALOGV("choreographer %p ~ received null event.", this); + handleRefreshRateUpdates(); } void Choreographer::handleMessage(const Message& message) { diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index 2020e0cb29..846190c7eb 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -137,6 +137,7 @@ void EventThreadConnection::onFirstRef() { status_t EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) { outChannel->setReceiveFd(mChannel.moveReceiveFd()); + outChannel->setSendFd(base::unique_fd(dup(mChannel.getSendFd()))); return NO_ERROR; } @@ -150,11 +151,6 @@ void EventThreadConnection::requestNextVsync() { mEventThread->requestNextVsync(this); } -void EventThreadConnection::requestLatestConfig() { - ATRACE_NAME("requestLatestConfig"); - mEventThread->requestLatestConfig(this); -} - status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) { ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1); return size < 0 ? status_t(size) : status_t(NO_ERROR); @@ -267,28 +263,6 @@ void EventThread::requestNextVsync(const sp& connection) } } -void EventThread::requestLatestConfig(const sp& connection) { - std::lock_guard lock(mMutex); - if (connection->mForcedConfigChangeDispatch) { - return; - } - connection->mForcedConfigChangeDispatch = true; - auto pendingConfigChange = - std::find_if(std::begin(mPendingEvents), std::end(mPendingEvents), - [&](const DisplayEventReceiver::Event& event) { - return event.header.type == - DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED; - }); - - // If we didn't find a pending config change event, then push out the - // latest one we've ever seen. - if (pendingConfigChange == std::end(mPendingEvents)) { - mPendingEvents.push_back(mLastConfigChangeEvent); - } - - mCondition.notify_all(); -} - void EventThread::onScreenReleased() { std::lock_guard lock(mMutex); if (!mVSyncState || mVSyncState->synthetic) { @@ -364,9 +338,6 @@ void EventThread::threadMain(std::unique_lock& lock) { mInterceptVSyncsCallback(event->header.timestamp); } break; - case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: - mLastConfigChangeEvent = *event; - break; } } @@ -379,10 +350,6 @@ void EventThread::threadMain(std::unique_lock& lock) { vsyncRequested |= connection->vsyncRequest != VSyncRequest::None; if (event && shouldConsumeEvent(*event, connection)) { - if (event->header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED && - connection->mForcedConfigChangeDispatch) { - connection->mForcedConfigChangeDispatch = false; - } consumers.push_back(connection); } @@ -458,9 +425,7 @@ bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, return true; case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: { - const bool oneTimeDispatch = connection->mForcedConfigChangeDispatch; - return oneTimeDispatch || - connection->mConfigChanged == ISurfaceComposer::eConfigChangedDispatch; + return connection->mConfigChanged == ISurfaceComposer::eConfigChangedDispatch; } case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h index 64acbd72d0..49f624c35e 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -81,19 +81,13 @@ public: status_t stealReceiveChannel(gui::BitTube* outChannel) override; status_t setVsyncRate(uint32_t rate) override; void requestNextVsync() override; // asynchronous - void requestLatestConfig() override; // asynchronous // Called in response to requestNextVsync. const ResyncCallback resyncCallback; VSyncRequest vsyncRequest = VSyncRequest::None; - ISurfaceComposer::ConfigChanged mConfigChanged = + const ISurfaceComposer::ConfigChanged mConfigChanged = ISurfaceComposer::ConfigChanged::eConfigChangedSuppress; - // Store whether we need to force dispatching a config change separately - - // if mConfigChanged ever changes before the config change is dispatched - // then we still need to propagate an initial config to the app if we - // haven't already. - bool mForcedConfigChangeDispatch = false; private: virtual void onFirstRef(); @@ -129,10 +123,6 @@ public: virtual void setVsyncRate(uint32_t rate, const sp& connection) = 0; // Requests the next vsync. If resetIdleTimer is set to true, it resets the idle timer. virtual void requestNextVsync(const sp& connection) = 0; - // Dispatches the most recent configuration - // Usage of this method assumes that only the primary internal display - // supports multiple display configurations. - virtual void requestLatestConfig(const sp& connection) = 0; // Retrieves the number of event connections tracked by this EventThread. virtual size_t getEventThreadConnectionCount() = 0; @@ -153,7 +143,6 @@ public: status_t registerDisplayEventConnection(const sp& connection) override; void setVsyncRate(uint32_t rate, const sp& connection) override; void requestNextVsync(const sp& connection) override; - void requestLatestConfig(const sp& connection) override; // called before the screen is turned off from main thread void onScreenReleased() override; @@ -201,7 +190,6 @@ private: std::vector> mDisplayEventConnections GUARDED_BY(mMutex); std::deque mPendingEvents GUARDED_BY(mMutex); - DisplayEventReceiver::Event mLastConfigChangeEvent GUARDED_BY(mMutex); // VSYNC state of connected display. struct VSyncState { -- cgit v1.2.3-59-g8ed1b From 74e17562e4166e11c2e4f33126088c5ed35ea0e7 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Mon, 24 Aug 2020 18:18:19 -0700 Subject: SurfaceFlinger: Shared timeline plumbing Add plumbing to get shared timeline data from Surface Flinger to HWUI and back. Bug: 162890382 Bug: 162888881 Test: SF unit tests Change-Id: Ifb76e6bf28d43c051e6c8ff568437ec9a106b865 --- libs/gui/DisplayEventDispatcher.cpp | 17 ++++--- libs/gui/ISurfaceComposer.cpp | 59 ++++++++++++++++++++++ libs/gui/Surface.cpp | 11 ++++ libs/gui/include/gui/DisplayEventDispatcher.h | 5 +- libs/gui/include/gui/DisplayEventReceiver.h | 1 + libs/gui/include/gui/ISurfaceComposer.h | 8 +++ libs/gui/include/gui/Surface.h | 1 + libs/gui/tests/DisplayEventStructLayout_test.cpp | 2 + libs/gui/tests/Surface_test.cpp | 9 +++- libs/nativedisplay/AChoreographer.cpp | 27 +++++++--- .../private/android/choreographer.h | 6 +++ libs/nativedisplay/libnativedisplay.map.txt | 1 + libs/nativewindow/include/system/window.h | 7 +++ services/surfaceflinger/Layer.cpp | 4 ++ services/surfaceflinger/Layer.h | 4 ++ services/surfaceflinger/Scheduler/EventThread.cpp | 9 ++-- services/surfaceflinger/SurfaceFlinger.cpp | 16 +++++- services/surfaceflinger/SurfaceFlinger.h | 3 ++ 18 files changed, 170 insertions(+), 20 deletions(-) (limited to 'libs/gui/DisplayEventDispatcher.cpp') diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp index 2cc7c34c40..7e894b4b79 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -73,7 +73,8 @@ status_t DisplayEventDispatcher::scheduleVsync() { nsecs_t vsyncTimestamp; PhysicalDisplayId vsyncDisplayId; uint32_t vsyncCount; - if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) { + int64_t vsyncId; + if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncId)) { ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this, ns2ms(static_cast(vsyncTimestamp))); } @@ -116,11 +117,13 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) { nsecs_t vsyncTimestamp; PhysicalDisplayId vsyncDisplayId; uint32_t vsyncCount; - if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) { - ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", displayId=%s, count=%d", this, - ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount); + int64_t vsyncId; + if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncId)) { + ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 + ", displayId=%s, count=%d, vsyncId=%" PRId64, + this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount, vsyncId); mWaitingForVsync = false; - dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount); + dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncId); } return 1; // keep the callback @@ -128,10 +131,11 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) { bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, - uint32_t* outCount) { + uint32_t* outCount, int64_t* outVsyncId) { bool gotVsync = false; DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE]; ssize_t n; + *outVsyncId = 0; while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) { ALOGV("dispatcher %p ~ Read %d events.", this, int(n)); for (ssize_t i = 0; i < n; i++) { @@ -144,6 +148,7 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, *outTimestamp = ev.header.timestamp; *outDisplayId = ev.header.displayId; *outCount = ev.vsync.count; + *outVsyncId = ev.vsync.vsyncId; break; case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected); diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 0ac493dab1..8b65ea1cbe 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -1150,6 +1150,38 @@ public: return NO_ERROR; } + + virtual status_t setFrameTimelineVsync(const sp& surface, + int64_t frameTimelineVsyncId) { + Parcel data, reply; + status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (err != NO_ERROR) { + ALOGE("setFrameTimelineVsync: failed writing interface token: %s (%d)", strerror(-err), + -err); + return err; + } + + err = data.writeStrongBinder(IInterface::asBinder(surface)); + if (err != NO_ERROR) { + ALOGE("setFrameTimelineVsync: failed writing strong binder: %s (%d)", strerror(-err), + -err); + return err; + } + + err = data.writeInt64(frameTimelineVsyncId); + if (err != NO_ERROR) { + ALOGE("setFrameTimelineVsync: failed writing int64_t: %s (%d)", strerror(-err), -err); + return err; + } + + err = remote()->transact(BnSurfaceComposer::SET_FRAME_TIMELINE_VSYNC, data, &reply); + if (err != NO_ERROR) { + ALOGE("setFrameTimelineVsync: failed to transact: %s (%d)", strerror(-err), err); + return err; + } + + return reply.readInt32(); + } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -1950,6 +1982,33 @@ status_t BnSurfaceComposer::onTransact( } return NO_ERROR; } + case SET_FRAME_TIMELINE_VSYNC: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp binder; + status_t err = data.readStrongBinder(&binder); + if (err != NO_ERROR) { + ALOGE("setFrameTimelineVsync: failed to read strong binder: %s (%d)", + strerror(-err), -err); + return err; + } + sp surface = interface_cast(binder); + if (!surface) { + ALOGE("setFrameTimelineVsync: failed to cast to IGraphicBufferProducer: %s (%d)", + strerror(-err), -err); + return err; + } + int64_t frameTimelineVsyncId; + err = data.readInt64(&frameTimelineVsyncId); + if (err != NO_ERROR) { + ALOGE("setFrameTimelineVsync: failed to read int64_t: %s (%d)", strerror(-err), + -err); + return err; + } + + status_t result = setFrameTimelineVsync(surface, frameTimelineVsyncId); + reply->writeInt32(result); + return NO_ERROR; + } default: { return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index e45b3d1be4..9ce8442579 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1207,6 +1207,9 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER: res = dispatchGetLastQueuedBuffer(args); break; + case NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC: + res = dispatchSetFrameTimelineVsync(args); + break; default: res = NAME_NOT_FOUND; break; @@ -1513,6 +1516,14 @@ int Surface::dispatchGetLastQueuedBuffer(va_list args) { return result; } +int Surface::dispatchSetFrameTimelineVsync(va_list args) { + ATRACE_CALL(); + auto frameTimelineVsyncId = static_cast(va_arg(args, int64_t)); + + ALOGV("Surface::dispatchSetFrameTimelineVsync"); + return composerService()->setFrameTimelineVsync(mGraphicBufferProducer, frameTimelineVsyncId); +} + bool Surface::transformToDisplayInverse() { return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) == NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h index eb5b00418a..cf598ead14 100644 --- a/libs/gui/include/gui/DisplayEventDispatcher.h +++ b/libs/gui/include/gui/DisplayEventDispatcher.h @@ -43,7 +43,8 @@ private: DisplayEventReceiver mReceiver; bool mWaitingForVsync; - virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) = 0; + virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, + int64_t vsyncId) = 0; virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) = 0; virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, @@ -53,6 +54,6 @@ private: virtual void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) = 0; bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, - uint32_t* outCount); + uint32_t* outCount, int64_t* outVsyncId); }; } // namespace android diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h index 0d0d10289c..df3118ff6d 100644 --- a/libs/gui/include/gui/DisplayEventReceiver.h +++ b/libs/gui/include/gui/DisplayEventReceiver.h @@ -73,6 +73,7 @@ public: uint32_t count; nsecs_t expectedVSyncTimestamp __attribute__((aligned(8))); nsecs_t deadlineTimestamp __attribute__((aligned(8))); + int64_t vsyncId; }; struct Hotplug { diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index e057b68b60..7c25b974fe 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -479,6 +479,13 @@ public: * for tests. Release the token by releasing the returned IBinder reference. */ virtual status_t acquireFrameRateFlexibilityToken(sp* outToken) = 0; + + /* + * Sets the frame timeline vsync id received from choreographer that corresponds to next + * buffer submitted on that surface. + */ + virtual status_t setFrameTimelineVsync(const sp& surface, + int64_t frameTimelineVsyncId) = 0; }; // ---------------------------------------------------------------------------- @@ -538,6 +545,7 @@ public: SET_GAME_CONTENT_TYPE, SET_FRAME_RATE, ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN, + SET_FRAME_TIMELINE_VSYNC, // Always append new enum to the end. }; diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 55b4101908..a68f2e7ce8 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -265,6 +265,7 @@ private: int dispatchAddQueueInterceptor(va_list args); int dispatchAddQueryInterceptor(va_list args); int dispatchGetLastQueuedBuffer(va_list args); + int dispatchSetFrameTimelineVsync(va_list args); bool transformToDisplayInverse(); protected: diff --git a/libs/gui/tests/DisplayEventStructLayout_test.cpp b/libs/gui/tests/DisplayEventStructLayout_test.cpp index 4bcb7953c6..72109109c4 100644 --- a/libs/gui/tests/DisplayEventStructLayout_test.cpp +++ b/libs/gui/tests/DisplayEventStructLayout_test.cpp @@ -33,6 +33,8 @@ TEST(DisplayEventStructLayoutTest, TestEventAlignment) { CHECK_OFFSET(DisplayEventReceiver::Event::VSync, count, 0); CHECK_OFFSET(DisplayEventReceiver::Event::VSync, expectedVSyncTimestamp, 8); + CHECK_OFFSET(DisplayEventReceiver::Event::VSync, deadlineTimestamp, 16); + CHECK_OFFSET(DisplayEventReceiver::Event::VSync, vsyncId, 24); CHECK_OFFSET(DisplayEventReceiver::Event::Hotplug, connected, 0); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index aedba2aebd..8d699978c7 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -868,7 +868,14 @@ public: return NO_ERROR; } - status_t acquireFrameRateFlexibilityToken(sp* /*outToken*/) { return NO_ERROR; } + status_t acquireFrameRateFlexibilityToken(sp* /*outToken*/) override { + return NO_ERROR; + } + + status_t setFrameTimelineVsync(const sp& /*surface*/, + int64_t /*frameTimelineVsyncId*/) override { + return NO_ERROR; + } protected: IBinder* onAsBinder() override { return nullptr; } diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp index ff1b5e6d34..b7c5b2a3d4 100644 --- a/libs/nativedisplay/AChoreographer.cpp +++ b/libs/nativedisplay/AChoreographer.cpp @@ -128,11 +128,14 @@ public: static Choreographer* getForThread(); virtual ~Choreographer() override EXCLUDES(gChoreographers.lock); + int64_t getVsyncId() const; + private: Choreographer(const Choreographer&) = delete; - void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count) override; + void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, + int64_t vsyncId) override; void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override; void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId, nsecs_t vsyncPeriod) override; @@ -146,6 +149,7 @@ private: std::vector mRefreshRateCallbacks; nsecs_t mLatestVsyncPeriod = -1; + int64_t mLastVsyncId = -1; const sp mLooper; const std::thread::id mThreadId; @@ -350,7 +354,7 @@ void Choreographer::handleRefreshRateUpdates() { // TODO(b/74619554): The PhysicalDisplayId is ignored because SF only emits VSYNC events for the // internal display and DisplayEventReceiver::requestNextVsync only allows requesting VSYNC for // the internal display implicitly. -void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t) { +void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t, int64_t vsyncId) { std::vector callbacks{}; { std::lock_guard _l{mLock}; @@ -360,6 +364,7 @@ void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t mFrameCallbacks.pop(); } } + mLastVsyncId = vsyncId; for (const auto& cb : callbacks) { if (cb.callback64 != nullptr) { cb.callback64(timestamp, cb.data); @@ -404,6 +409,10 @@ void Choreographer::handleMessage(const Message& message) { } } +int64_t Choreographer::getVsyncId() const { + return mLastVsyncId; +} + } // namespace android using namespace android; @@ -411,6 +420,11 @@ static inline Choreographer* AChoreographer_to_Choreographer(AChoreographer* cho return reinterpret_cast(choreographer); } +static inline const Choreographer* AChoreographer_to_Choreographer( + const AChoreographer* choreographer) { + return reinterpret_cast(choreographer); +} + // Glue for private C api namespace android { void AChoreographer_signalRefreshRateCallbacks(nsecs_t vsyncPeriod) EXCLUDES(gChoreographers.lock) { @@ -468,15 +482,14 @@ void AChoreographer_routeUnregisterRefreshRateCallback(AChoreographer* choreogra return AChoreographer_unregisterRefreshRateCallback(choreographer, callback, data); } +int64_t AChoreographer_getVsyncId(const AChoreographer* choreographer) { + return AChoreographer_to_Choreographer(choreographer)->getVsyncId(); +} + } // namespace android /* Glue for the NDK interface */ -static inline const Choreographer* AChoreographer_to_Choreographer( - const AChoreographer* choreographer) { - return reinterpret_cast(choreographer); -} - static inline AChoreographer* Choreographer_to_AChoreographer(Choreographer* choreographer) { return reinterpret_cast(choreographer); } diff --git a/libs/nativedisplay/include-private/private/android/choreographer.h b/libs/nativedisplay/include-private/private/android/choreographer.h index 21649304bf..1d57c155ec 100644 --- a/libs/nativedisplay/include-private/private/android/choreographer.h +++ b/libs/nativedisplay/include-private/private/android/choreographer.h @@ -29,6 +29,12 @@ void AChoreographer_initJVM(JNIEnv* env); // for consumption by callbacks. void AChoreographer_signalRefreshRateCallbacks(int64_t vsyncPeriod); +// Returns the vsync id of the last frame callback. Client are expected to call +// this function from their frame callback function to get the vsyncId and pass +// it together with a buffer or transaction to the Surface Composer. Calling +// this function from anywhere else will return an undefined value. +int64_t AChoreographer_getVsyncId(const AChoreographer* choreographer); + // Trampoline functions allowing libandroid.so to define the NDK symbols without including // the entirety of libnativedisplay as a whole static lib. As libnativedisplay // maintains global state, libnativedisplay can never be directly statically diff --git a/libs/nativedisplay/libnativedisplay.map.txt b/libs/nativedisplay/libnativedisplay.map.txt index fc59431d08..5ed2e496d3 100644 --- a/libs/nativedisplay/libnativedisplay.map.txt +++ b/libs/nativedisplay/libnativedisplay.map.txt @@ -29,6 +29,7 @@ LIBNATIVEDISPLAY_PLATFORM { android::AChoreographer_routeRegisterRefreshRateCallback*; android::AChoreographer_routeUnregisterRefreshRateCallback*; android::AChoreographer_signalRefreshRateCallbacks*; + android::AChoreographer_getVsyncId*; android::ADisplay_acquirePhysicalDisplays*; android::ADisplay_release*; android::ADisplay_getMaxSupportedFps*; diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index b78fc5dbbc..138e08f490 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -255,6 +255,7 @@ enum { NATIVE_WINDOW_ALLOCATE_BUFFERS = 45, /* private */ NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER = 46, /* private */ NATIVE_WINDOW_SET_QUERY_INTERCEPTOR = 47, /* private */ + NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC = 48, /* private */ // clang-format on }; @@ -1022,6 +1023,12 @@ static inline int native_window_set_frame_rate(struct ANativeWindow* window, flo (int)compatibility); } +static inline int native_window_set_frame_timeline_vsync(struct ANativeWindow* window, + int64_t frameTimelineVsyncId) { + return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC, + frameTimelineVsyncId); +} + // ------------------------------------------------------------------------------------------------ // Candidates for APEX visibility // These functions are planned to be made stable for APEX modules, but have not diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index eced6bdbe2..152c044ceb 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1435,6 +1435,10 @@ bool Layer::setFrameRate(FrameRate frameRate) { return true; } +void Layer::setFrameTimelineVsync(int64_t frameTimelineVsyncId) { + mFrameTimelineVsyncId = frameTimelineVsyncId; +} + Layer::FrameRate Layer::getFrameRateForLayerTree() const { const auto frameRate = getDrawingState().frameRate; if (frameRate.rate > 0 || frameRate.type == FrameRateCompatibility::NoVote) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 913f13ad95..f77a828c09 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -822,6 +822,8 @@ public: bool setFrameRate(FrameRate); + void setFrameTimelineVsync(int64_t frameTimelineVsyncId); + // Creates a new handle each time, so we only expect // this to be called once. sp getHandle(); @@ -1022,6 +1024,8 @@ protected: // Can only be accessed with the SF state lock held. bool mChildrenChanged{false}; + std::optional mFrameTimelineVsyncId; + // Window types from WindowManager.LayoutParams const InputWindowInfo::Type mWindowType; diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index f513535658..77b2f4273e 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -99,12 +99,13 @@ DisplayEventReceiver::Event makeHotplug(PhysicalDisplayId displayId, nsecs_t tim DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t timestamp, uint32_t count, nsecs_t expectedVSyncTimestamp, - nsecs_t deadlineTimestamp) { + nsecs_t deadlineTimestamp, int64_t vsyncId) { DisplayEventReceiver::Event event; event.header = {DisplayEventReceiver::DISPLAY_EVENT_VSYNC, displayId, timestamp}; event.vsync.count = count; event.vsync.expectedVSyncTimestamp = expectedVSyncTimestamp; event.vsync.deadlineTimestamp = deadlineTimestamp; + event.vsync.vsyncId = vsyncId; return event; } @@ -291,8 +292,9 @@ void EventThread::onVSyncEvent(nsecs_t timestamp, nsecs_t expectedVSyncTimestamp std::lock_guard lock(mMutex); LOG_FATAL_IF(!mVSyncState); + // TODO(b/162890590): use TokenManager to populate vsyncId mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count, - expectedVSyncTimestamp, deadlineTimestamp)); + expectedVSyncTimestamp, deadlineTimestamp, /*vsyncId=*/0)); mCondition.notify_all(); } @@ -416,9 +418,10 @@ void EventThread::threadMain(std::unique_lock& lock) { const auto now = systemTime(SYSTEM_TIME_MONOTONIC); const auto deadlineTimestamp = now + timeout.count(); const auto expectedVSyncTime = deadlineTimestamp + timeout.count(); + // TODO(b/162890590): use TokenManager to populate vsyncId mPendingEvents.push_back(makeVSync(mVSyncState->displayId, now, ++mVSyncState->count, expectedVSyncTime, - deadlineTimestamp)); + deadlineTimestamp, /*vsyncId=*/0)); } } } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9d35a3fca6..51107d31da 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5001,7 +5001,8 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { // captureLayers and captureDisplay will handle the permission check in the function case CAPTURE_LAYERS: case CAPTURE_DISPLAY: - case SET_DISPLAY_BRIGHTNESS: { + case SET_DISPLAY_BRIGHTNESS: + case SET_FRAME_TIMELINE_VSYNC: { return OK; } @@ -6333,6 +6334,19 @@ void SurfaceFlinger::onFrameRateFlexibilityTokenReleased() { })); } +status_t SurfaceFlinger::setFrameTimelineVsync(const sp& surface, + int64_t frameTimelineVsyncId) { + Mutex::Autolock lock(mStateLock); + if (!authenticateSurfaceTextureLocked(surface)) { + ALOGE("Attempt to set frame timeline vsync on an unrecognized IGraphicBufferProducer"); + return BAD_VALUE; + } + + sp layer = (static_cast(surface.get()))->getLayer(); + layer->setFrameTimelineVsync(frameTimelineVsyncId); + return NO_ERROR; +} + void SurfaceFlinger::enableRefreshRateOverlay(bool enable) { static_cast(schedule([=] { std::unique_ptr overlay; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 28762c927c..faee775b02 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -597,6 +597,9 @@ private: int8_t compatibility) override; status_t acquireFrameRateFlexibilityToken(sp* outToken) override; + status_t setFrameTimelineVsync(const sp& surface, + int64_t frameTimelineVsyncId) override; + // Implements IBinder::DeathRecipient. void binderDied(const wp& who) override; -- cgit v1.2.3-59-g8ed1b From 0d28d76a34e82b3133b17854017698995c589cb1 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Mon, 5 Oct 2020 17:50:41 -0700 Subject: SurfaceFlinger: pass frame deadline to Choreographer Pass the frame deadline calculated by SF to AChoreographer so hwui would be able to improve its stats by knowing if a frame is likely to be late. Bug: 169858174 Test: manul Change-Id: I9433d990684b968cbe1cd3ce17717b616d01b9a2 --- libs/gui/DisplayEventDispatcher.cpp | 20 +++++++++++--------- libs/gui/include/gui/DisplayEventDispatcher.h | 15 +++++++++++++-- libs/nativedisplay/AChoreographer.cpp | 20 +++++++++++++++----- .../include-private/private/android/choreographer.h | 7 +++++++ libs/nativedisplay/libnativedisplay.map.txt | 1 + 5 files changed, 47 insertions(+), 16 deletions(-) (limited to 'libs/gui/DisplayEventDispatcher.cpp') diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp index 7e894b4b79..abfee61685 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -73,8 +73,8 @@ status_t DisplayEventDispatcher::scheduleVsync() { nsecs_t vsyncTimestamp; PhysicalDisplayId vsyncDisplayId; uint32_t vsyncCount; - int64_t vsyncId; - if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncId)) { + VsyncEventData vsyncEventData; + if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) { ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this, ns2ms(static_cast(vsyncTimestamp))); } @@ -117,13 +117,14 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) { nsecs_t vsyncTimestamp; PhysicalDisplayId vsyncDisplayId; uint32_t vsyncCount; - int64_t vsyncId; - if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncId)) { + VsyncEventData vsyncEventData; + if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) { ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", displayId=%s, count=%d, vsyncId=%" PRId64, - this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount, vsyncId); + this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount, + vsyncEventData.id); mWaitingForVsync = false; - dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncId); + dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData); } return 1; // keep the callback @@ -131,11 +132,11 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) { bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, - uint32_t* outCount, int64_t* outVsyncId) { + uint32_t* outCount, + VsyncEventData* outVsyncEventData) { bool gotVsync = false; DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE]; ssize_t n; - *outVsyncId = 0; while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) { ALOGV("dispatcher %p ~ Read %d events.", this, int(n)); for (ssize_t i = 0; i < n; i++) { @@ -148,7 +149,8 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, *outTimestamp = ev.header.timestamp; *outDisplayId = ev.header.displayId; *outCount = ev.vsync.count; - *outVsyncId = ev.vsync.vsyncId; + outVsyncEventData->id = ev.vsync.vsyncId; + outVsyncEventData->deadlineTimestamp = ev.vsync.deadlineTimestamp; break; case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected); diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h index cf598ead14..c65618b31f 100644 --- a/libs/gui/include/gui/DisplayEventDispatcher.h +++ b/libs/gui/include/gui/DisplayEventDispatcher.h @@ -20,6 +20,17 @@ namespace android { +struct VsyncEventData { + // The Vsync Id corresponsing to this vsync event. This will be used to + // populate ISurfaceComposer::setFrameTimelineVsync and + // SurfaceComposerClient::setFrameTimelineVsync + int64_t id = ISurfaceComposer::INVALID_VSYNC_ID; + + // The deadline in CLOCK_MONOTONIC that the app needs to complete its + // frame by (both on the CPU and the GPU) + int64_t deadlineTimestamp = std::numeric_limits::max(); +}; + class DisplayEventDispatcher : public LooperCallback { public: explicit DisplayEventDispatcher( @@ -44,7 +55,7 @@ private: bool mWaitingForVsync; virtual void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, - int64_t vsyncId) = 0; + VsyncEventData vsyncEventData) = 0; virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) = 0; virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, @@ -54,6 +65,6 @@ private: virtual void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) = 0; bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, - uint32_t* outCount, int64_t* outVsyncId); + uint32_t* outCount, VsyncEventData* outVsyncEventData); }; } // namespace android diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp index 470f28f947..9e515cdc80 100644 --- a/libs/nativedisplay/AChoreographer.cpp +++ b/libs/nativedisplay/AChoreographer.cpp @@ -129,13 +129,14 @@ public: static Choreographer* getForThread(); virtual ~Choreographer() override EXCLUDES(gChoreographers.lock); int64_t getVsyncId() const; + int64_t getFrameDeadline() const; private: Choreographer(const Choreographer&) = delete; void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, - int64_t vsyncId) override; + VsyncEventData vsyncEventData) override; void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override; void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId, nsecs_t vsyncPeriod) override; @@ -149,7 +150,7 @@ private: std::vector mRefreshRateCallbacks; nsecs_t mLatestVsyncPeriod = -1; - int64_t mLastVsyncId = -1; + VsyncEventData mLastVsyncEventData; const sp mLooper; const std::thread::id mThreadId; @@ -354,7 +355,8 @@ void Choreographer::handleRefreshRateUpdates() { // TODO(b/74619554): The PhysicalDisplayId is ignored because SF only emits VSYNC events for the // internal display and DisplayEventReceiver::requestNextVsync only allows requesting VSYNC for // the internal display implicitly. -void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t, int64_t vsyncId) { +void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t, + VsyncEventData vsyncEventData) { std::vector callbacks{}; { std::lock_guard _l{mLock}; @@ -364,7 +366,7 @@ void Choreographer::dispatchVsync(nsecs_t timestamp, PhysicalDisplayId, uint32_t mFrameCallbacks.pop(); } } - mLastVsyncId = vsyncId; + mLastVsyncEventData = vsyncEventData; for (const auto& cb : callbacks) { if (cb.callback64 != nullptr) { cb.callback64(timestamp, cb.data); @@ -410,7 +412,11 @@ void Choreographer::handleMessage(const Message& message) { } int64_t Choreographer::getVsyncId() const { - return mLastVsyncId; + return mLastVsyncEventData.id; +} + +int64_t Choreographer::getFrameDeadline() const { + return mLastVsyncEventData.deadlineTimestamp; } } // namespace android @@ -492,6 +498,10 @@ int64_t AChoreographer_getVsyncId(const AChoreographer* choreographer) { return AChoreographer_to_Choreographer(choreographer)->getVsyncId(); } +int64_t AChoreographer_getFrameDeadline(const AChoreographer* choreographer) { + return AChoreographer_to_Choreographer(choreographer)->getFrameDeadline(); +} + } // namespace android /* Glue for the NDK interface */ diff --git a/libs/nativedisplay/include-private/private/android/choreographer.h b/libs/nativedisplay/include-private/private/android/choreographer.h index 1d57c155ec..d3a4a66c18 100644 --- a/libs/nativedisplay/include-private/private/android/choreographer.h +++ b/libs/nativedisplay/include-private/private/android/choreographer.h @@ -35,6 +35,13 @@ void AChoreographer_signalRefreshRateCallbacks(int64_t vsyncPeriod); // this function from anywhere else will return an undefined value. int64_t AChoreographer_getVsyncId(const AChoreographer* choreographer); +// Returns the deadline timestamp (in CLOCK_MONOTONIC) of the last frame callback. +// Client are expected to call this function from their frame callback function +// to get the deadline and use it to know whether a frame is likely to miss +// presentation. Calling this function from anywhere else will return an undefined +// value. +int64_t AChoreographer_getFrameDeadline(const AChoreographer* choreographer); + // Trampoline functions allowing libandroid.so to define the NDK symbols without including // the entirety of libnativedisplay as a whole static lib. As libnativedisplay // maintains global state, libnativedisplay can never be directly statically diff --git a/libs/nativedisplay/libnativedisplay.map.txt b/libs/nativedisplay/libnativedisplay.map.txt index 5ed2e496d3..fda6a20a0b 100644 --- a/libs/nativedisplay/libnativedisplay.map.txt +++ b/libs/nativedisplay/libnativedisplay.map.txt @@ -30,6 +30,7 @@ LIBNATIVEDISPLAY_PLATFORM { android::AChoreographer_routeUnregisterRefreshRateCallback*; android::AChoreographer_signalRefreshRateCallbacks*; android::AChoreographer_getVsyncId*; + android::AChoreographer_getFrameDeadline*; android::ADisplay_acquirePhysicalDisplays*; android::ADisplay_release*; android::ADisplay_getMaxSupportedFps*; -- cgit v1.2.3-59-g8ed1b From 62f216c62edbe4c997e959cfb28c8609664978df Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Tue, 13 Oct 2020 19:07:23 -0700 Subject: 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 --- PREUPLOAD.cfg | 1 + libs/gui/Android.bp | 4 + libs/gui/DisplayEventDispatcher.cpp | 16 +++- libs/gui/DisplayEventReceiver.cpp | 7 +- libs/gui/ISurfaceComposer.cpp | 11 ++- libs/gui/include/gui/DisplayEventDispatcher.h | 9 +- libs/gui/include/gui/DisplayEventReceiver.h | 15 ++- libs/gui/include/gui/ISurfaceComposer.h | 11 ++- libs/gui/tests/DisplayEventStructLayout_test.cpp | 3 + libs/gui/tests/Surface_test.cpp | 2 +- libs/nativedisplay/AChoreographer.cpp | 21 ++--- services/surfaceflinger/Scheduler/EventThread.cpp | 80 ++++++++++++++-- services/surfaceflinger/Scheduler/EventThread.h | 22 +++-- .../Scheduler/RefreshRateConfigs.cpp | 28 ++++-- .../surfaceflinger/Scheduler/RefreshRateConfigs.h | 12 ++- services/surfaceflinger/Scheduler/Scheduler.cpp | 22 +++-- services/surfaceflinger/Scheduler/Scheduler.h | 11 ++- services/surfaceflinger/SurfaceFlinger.cpp | 21 +++-- services/surfaceflinger/SurfaceFlinger.h | 3 +- .../tests/fakehwc/SFFakeHwc_test.cpp | 5 +- .../tests/unittests/CompositionTest.cpp | 12 +-- .../tests/unittests/DisplayTransactionTest.cpp | 10 +- .../tests/unittests/EventThreadTest.cpp | 102 +++++++++++++++------ .../tests/unittests/RefreshRateConfigsTest.cpp | 8 +- .../tests/unittests/RefreshRateSelectionTest.cpp | 6 +- .../tests/unittests/SchedulerTest.cpp | 10 +- .../tests/unittests/SetFrameRateTest.cpp | 6 +- .../tests/unittests/TransactionApplicationTest.cpp | 12 +-- .../tests/unittests/mock/MockEventThread.h | 5 +- 29 files changed, 330 insertions(+), 145 deletions(-) (limited to 'libs/gui/DisplayEventDispatcher.cpp') diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index 560459be13..a8c0500683 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -14,6 +14,7 @@ clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp libs/graphicsenv/ libs/gui/ libs/input/ + libs/nativedisplay/ libs/renderengine/ libs/ui/ libs/vr/ diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index a0e9cbf2eb..af9ef06b86 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -237,6 +237,10 @@ cc_defaults { "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 abfee61685..c6c9a8f7a7 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -33,10 +33,10 @@ namespace android { // using just a few large reads. static const size_t EVENT_BUFFER_SIZE = 100; -DisplayEventDispatcher::DisplayEventDispatcher(const sp& looper, - ISurfaceComposer::VsyncSource vsyncSource, - ISurfaceComposer::ConfigChanged configChanged) - : mLooper(looper), mReceiver(vsyncSource, configChanged), mWaitingForVsync(false) { +DisplayEventDispatcher::DisplayEventDispatcher( + const sp& 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 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, 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 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, 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 f2b0962eb7..03b33c7330 100644 --- a/libs/gui/DisplayEventReceiver.cpp +++ b/libs/gui/DisplayEventReceiver.cpp @@ -32,11 +32,12 @@ namespace android { // --------------------------------------------------------------------------- -DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource, - ISurfaceComposer::ConfigChanged configChanged) { +DisplayEventReceiver::DisplayEventReceiver( + ISurfaceComposer::VsyncSource vsyncSource, + ISurfaceComposer::EventRegistrationFlags eventRegistration) { sp sf(ComposerService::getComposerService()); if (sf != nullptr) { - mEventConnection = sf->createDisplayEventConnection(vsyncSource, configChanged); + mEventConnection = sf->createDisplayEventConnection(vsyncSource, eventRegistration); if (mEventConnection != nullptr) { mDataChannel = std::make_unique(); mEventConnection->stealReceiveChannel(mDataChannel.get()); diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index a9fe5bf319..e46a415f8c 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -223,8 +223,8 @@ public: return NO_ERROR; } - virtual sp createDisplayEventConnection(VsyncSource vsyncSource, - ConfigChanged configChanged) { + virtual sp createDisplayEventConnection( + VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) { Parcel data, reply; sp result; int err = data.writeInterfaceToken( @@ -233,7 +233,7 @@ public: return result; } data.writeInt32(static_cast(vsyncSource)); - data.writeInt32(static_cast(configChanged)); + data.writeUint32(eventRegistration.get()); err = remote()->transact( BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION, data, &reply); @@ -1373,10 +1373,11 @@ status_t BnSurfaceComposer::onTransact( case CREATE_DISPLAY_EVENT_CONNECTION: { CHECK_INTERFACE(ISurfaceComposer, data, reply); auto vsyncSource = static_cast(data.readInt32()); - auto configChanged = static_cast(data.readInt32()); + EventRegistrationFlags eventRegistration = + static_cast(data.readUint32()); sp 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 c65618b31f..5587acf08f 100644 --- a/libs/gui/include/gui/DisplayEventDispatcher.h +++ b/libs/gui/include/gui/DisplayEventDispatcher.h @@ -19,6 +19,7 @@ #include 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 @@ public: explicit DisplayEventDispatcher( const sp& looper, ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp, - ISurfaceComposer::ConfigChanged configChanged = - ISurfaceComposer::eConfigChangedSuppress); + ISurfaceComposer::EventRegistrationFlags eventRegistration = {}); status_t initialize(); void dispose(); @@ -54,6 +54,8 @@ private: DisplayEventReceiver mReceiver; bool mWaitingForVsync; + std::vector 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 @@ private: // can be properly poked. virtual void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) = 0; + virtual void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId, + std::vector 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 df3118ff6d..3191fc9ab5 100644 --- a/libs/gui/include/gui/DisplayEventReceiver.h +++ b/libs/gui/include/gui/DisplayEventReceiver.h @@ -54,6 +54,8 @@ public: 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 @@ public: 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 @@ public: * 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 9e96b79b8c..86e3a25f5a 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -26,6 +26,8 @@ #include #include +#include + #include #include @@ -107,7 +109,12 @@ public: eVsyncSourceSurfaceFlinger = 1 }; - enum ConfigChanged { eConfigChangedSuppress = 0, eConfigChangedDispatch = 1 }; + enum class EventRegistration { + configChanged = 1 << 0, + frameRateOverride = 1 << 1, + }; + + using EventRegistrationFlags = Flags; // 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 @@ public: /* return an IDisplayEventConnection */ virtual sp 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 72109109c4..c5093e2d88 100644 --- a/libs/gui/tests/DisplayEventStructLayout_test.cpp +++ b/libs/gui/tests/DisplayEventStructLayout_test.cpp @@ -40,6 +40,9 @@ TEST(DisplayEventStructLayoutTest, TestEventAlignment) { 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 2392ae5ccd..ce3afa2710 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -687,7 +687,7 @@ public: sp createConnection() override { return nullptr; } sp createDisplayEventConnection( - ISurfaceComposer::VsyncSource, ISurfaceComposer::ConfigChanged) override { + ISurfaceComposer::VsyncSource, ISurfaceComposer::EventRegistrationFlags) override { return nullptr; } sp createDisplay(const String8& /*displayName*/, diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp index 9e515cdc80..6d91916978 100644 --- a/libs/nativedisplay/AChoreographer.cpp +++ b/libs/nativedisplay/AChoreographer.cpp @@ -141,6 +141,8 @@ private: 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 overrides) override; void scheduleCallbacks(); @@ -175,8 +177,7 @@ Choreographer* Choreographer::getForThread() { } Choreographer::Choreographer(const sp& 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 _l(gChoreographers.lock); @@ -381,15 +382,13 @@ void Choreographer::dispatchHotplug(nsecs_t, PhysicalDisplayId displayId, bool c 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) { + LOG_ALWAYS_FATAL("dispatchFrameRateOverrides was called but was never registered"); } void Choreographer::dispatchNullEvent(nsecs_t, PhysicalDisplayId) { diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index bf5be4790d..b63e8c835b 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -45,6 +45,9 @@ #include "FrameTimeline.h" #include "HwcStrongTypes.h" +#undef LOG_TAG +#define LOG_TAG "EventThread" + using namespace std::chrono_literals; namespace android { @@ -123,14 +126,36 @@ DisplayEventReceiver::Event makeConfigChanged(PhysicalDisplayId displayId, return event; } +DisplayEventReceiver::Event makeFrameRateOverrideEvent(PhysicalDisplayId displayId, + FrameRateOverride frameRateOverride) { + return DisplayEventReceiver::Event{ + .header = + DisplayEventReceiver::Event::Header{ + .type = DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE, + .displayId = displayId, + .timestamp = systemTime(), + }, + .frameRateOverride = frameRateOverride, + }; +} + +DisplayEventReceiver::Event makeFrameRateOverrideFlushEvent(PhysicalDisplayId displayId) { + return DisplayEventReceiver::Event{ + .header = DisplayEventReceiver::Event::Header{ + .type = DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH, + .displayId = displayId, + .timestamp = systemTime(), + }}; +} + } // namespace -EventThreadConnection::EventThreadConnection(EventThread* eventThread, uid_t callingUid, - ResyncCallback resyncCallback, - ISurfaceComposer::ConfigChanged configChanged) +EventThreadConnection::EventThreadConnection( + EventThread* eventThread, uid_t callingUid, ResyncCallback resyncCallback, + ISurfaceComposer::EventRegistrationFlags eventRegistration) : resyncCallback(std::move(resyncCallback)), - mConfigChanged(configChanged), mOwnerUid(callingUid), + mEventRegistration(eventRegistration), mEventThread(eventThread), mChannel(gui::BitTube::DefaultSize) {} @@ -161,8 +186,25 @@ void EventThreadConnection::requestNextVsync() { } status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) { - ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1); - return size < 0 ? status_t(size) : status_t(NO_ERROR); + constexpr auto toStatus = [](ssize_t size) { + return size < 0 ? status_t(size) : status_t(NO_ERROR); + }; + + if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE || + event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH) { + mPendingEvents.emplace_back(event); + if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE) { + return status_t(NO_ERROR); + } + + auto size = DisplayEventReceiver::sendEvents(&mChannel, mPendingEvents.data(), + mPendingEvents.size()); + mPendingEvents.clear(); + return toStatus(size); + } + + auto size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1); + return toStatus(size); } // --------------------------------------------------------------------------- @@ -220,10 +262,11 @@ void EventThread::setDuration(std::chrono::nanoseconds workDuration, } sp EventThread::createEventConnection( - ResyncCallback resyncCallback, ISurfaceComposer::ConfigChanged configChanged) const { + ResyncCallback resyncCallback, + ISurfaceComposer::EventRegistrationFlags eventRegistration) const { return new EventThreadConnection(const_cast(this), IPCThreadState::self()->getCallingUid(), - std::move(resyncCallback), configChanged); + std::move(resyncCallback), eventRegistration); } status_t EventThread::registerDisplayEventConnection(const sp& connection) { @@ -333,6 +376,18 @@ void EventThread::onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexTyp mCondition.notify_all(); } +void EventThread::onFrameRateOverridesChanged(PhysicalDisplayId displayId, + std::vector overrides) { + std::lock_guard lock(mMutex); + + for (auto frameRateOverride : overrides) { + mPendingEvents.push_back(makeFrameRateOverrideEvent(displayId, frameRateOverride)); + } + mPendingEvents.push_back(makeFrameRateOverrideFlushEvent(displayId)); + + mCondition.notify_all(); +} + size_t EventThread::getEventThreadConnectionCount() { std::lock_guard lock(mMutex); return mDisplayEventConnections.size(); @@ -459,7 +514,8 @@ bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, return true; case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: { - return connection->mConfigChanged == ISurfaceComposer::eConfigChangedDispatch; + return connection->mEventRegistration.test( + ISurfaceComposer::EventRegistration::configChanged); } case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: @@ -488,6 +544,12 @@ bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0; } + case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE: + [[fallthrough]]; + case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH: + return connection->mEventRegistration.test( + ISurfaceComposer::EventRegistration::frameRateOverride); + default: return false; } diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h index 2e2d98950e..e75b7189da 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -48,6 +48,7 @@ class TokenManager; // --------------------------------------------------------------------------- using ResyncCallback = std::function; +using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride; enum class VSyncRequest { None = -2, @@ -82,7 +83,7 @@ public: class EventThreadConnection : public BnDisplayEventConnection { public: EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback, - ISurfaceComposer::ConfigChanged configChanged); + ISurfaceComposer::EventRegistrationFlags eventRegistration = {}); virtual ~EventThreadConnection(); virtual status_t postEvent(const DisplayEventReceiver::Event& event); @@ -95,15 +96,15 @@ public: const ResyncCallback resyncCallback; VSyncRequest vsyncRequest = VSyncRequest::None; - const ISurfaceComposer::ConfigChanged mConfigChanged = - ISurfaceComposer::ConfigChanged::eConfigChangedSuppress; - const uid_t mOwnerUid; + const ISurfaceComposer::EventRegistrationFlags mEventRegistration; private: virtual void onFirstRef(); EventThread* const mEventThread; gui::BitTube mChannel; + + std::vector mPendingEvents; }; class EventThread { @@ -111,7 +112,8 @@ public: virtual ~EventThread(); virtual sp createEventConnection( - ResyncCallback, ISurfaceComposer::ConfigChanged configChanged) const = 0; + ResyncCallback, + ISurfaceComposer::EventRegistrationFlags eventRegistration = {}) const = 0; // called before the screen is turned off from main thread virtual void onScreenReleased() = 0; @@ -125,6 +127,10 @@ public: virtual void onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexType configId, nsecs_t vsyncPeriod) = 0; + // called when SF updates the Frame Rate Override list + virtual void onFrameRateOverridesChanged(PhysicalDisplayId displayId, + std::vector overrides) = 0; + virtual void dump(std::string& result) const = 0; virtual void setDuration(std::chrono::nanoseconds workDuration, @@ -152,7 +158,8 @@ public: ~EventThread(); sp createEventConnection( - ResyncCallback, ISurfaceComposer::ConfigChanged configChanged) const override; + ResyncCallback, + ISurfaceComposer::EventRegistrationFlags eventRegistration = {}) const override; status_t registerDisplayEventConnection(const sp& connection) override; void setVsyncRate(uint32_t rate, const sp& connection) override; @@ -169,6 +176,9 @@ public: void onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexType configId, nsecs_t vsyncPeriod) override; + void onFrameRateOverridesChanged(PhysicalDisplayId displayId, + std::vector overrides) override; + void dump(std::string& result) const override; void setDuration(std::chrono::nanoseconds workDuration, diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index b872d7a4dd..8b4283cd65 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -687,21 +687,20 @@ RefreshRateConfigs::KernelIdleTimerAction RefreshRateConfigs::getIdleTimerAction return RefreshRateConfigs::KernelIdleTimerAction::TurnOn; } -void RefreshRateConfigs::setPreferredRefreshRateForUid(uid_t uid, float refreshRateHz) { - if (refreshRateHz > 0 && refreshRateHz < 1) { +void RefreshRateConfigs::setPreferredRefreshRateForUid(FrameRateOverride frameRateOverride) { + if (frameRateOverride.frameRateHz > 0 && frameRateOverride.frameRateHz < 1) { return; } std::lock_guard lock(mLock); - if (refreshRateHz != 0) { - mPreferredRefreshRateForUid[uid] = refreshRateHz; + if (frameRateOverride.frameRateHz != 0) { + mPreferredRefreshRateForUid[frameRateOverride.uid] = frameRateOverride.frameRateHz; } else { - mPreferredRefreshRateForUid.erase(uid); + mPreferredRefreshRateForUid.erase(frameRateOverride.uid); } } int RefreshRateConfigs::getRefreshRateDividerForUid(uid_t uid) const { - constexpr float kThreshold = 0.1f; std::lock_guard lock(mLock); const auto iter = mPreferredRefreshRateForUid.find(uid); @@ -709,6 +708,9 @@ int RefreshRateConfigs::getRefreshRateDividerForUid(uid_t uid) const { return 1; } + // This calculation needs to be in sync with the java code + // in DisplayManagerService.getDisplayInfoForFrameRateOverride + constexpr float kThreshold = 0.1f; const auto refreshRateHz = iter->second; const auto numPeriods = mCurrentRefreshRate->getFps() / refreshRateHz; const auto numPeriodsRounded = std::round(numPeriods); @@ -716,7 +718,19 @@ int RefreshRateConfigs::getRefreshRateDividerForUid(uid_t uid) const { return 1; } - return static_cast(numPeriods); + return static_cast(numPeriodsRounded); +} + +std::vector RefreshRateConfigs::getFrameRateOverrides() { + std::lock_guard lock(mLock); + std::vector overrides; + overrides.reserve(mPreferredRefreshRateForUid.size()); + + for (const auto [uid, frameRate] : mPreferredRefreshRateForUid) { + overrides.emplace_back(FrameRateOverride{uid, frameRate}); + } + + return overrides; } void RefreshRateConfigs::dump(std::string& result) const { diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index 3159352db9..a8737778d3 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -17,6 +17,7 @@ #pragma once #include +#include #include #include @@ -39,6 +40,8 @@ inline RefreshRateConfigEvent operator|(RefreshRateConfigEvent lhs, RefreshRateC return static_cast(static_cast(lhs) | static_cast(rhs)); } +using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride; + /** * This class is used to encapsulate configuration for refresh rates. It holds information * about available refresh rates on the device, and the mapping between the numbers and human @@ -316,14 +319,17 @@ public: KernelIdleTimerAction getIdleTimerAction() const; // Stores the preferred refresh rate that an app should run at. - // refreshRate == 0 means no preference. - void setPreferredRefreshRateForUid(uid_t, float refreshRateHz) EXCLUDES(mLock); + // FrameRateOverride.refreshRateHz == 0 means no preference. + void setPreferredRefreshRateForUid(FrameRateOverride) EXCLUDES(mLock); // Returns a divider for the current refresh rate int getRefreshRateDividerForUid(uid_t) const EXCLUDES(mLock); void dump(std::string& result) const EXCLUDES(mLock); + // Returns the current frame rate overrides + std::vector getFrameRateOverrides() EXCLUDES(mLock); + private: friend class RefreshRateConfigsTest; @@ -381,6 +387,8 @@ private: Policy mDisplayManagerPolicy GUARDED_BY(mLock); std::optional mOverridePolicy GUARDED_BY(mLock); + // A mapping between a UID and a preferred refresh rate that this app would + // run at. std::unordered_map mPreferredRefreshRateForUid GUARDED_BY(mLock); // The min and max refresh rates supported by the device. diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index a14019eeb5..a93bf11301 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -239,8 +239,7 @@ Scheduler::ConnectionHandle Scheduler::createConnection(std::unique_ptr lock(mConnectionsLock); mConnections.emplace(handle, Connection{connection, std::move(eventThread)}); @@ -248,15 +247,15 @@ Scheduler::ConnectionHandle Scheduler::createConnection(std::unique_ptr Scheduler::createConnectionInternal( - EventThread* eventThread, ISurfaceComposer::ConfigChanged configChanged) { - return eventThread->createEventConnection([&] { resync(); }, configChanged); + EventThread* eventThread, ISurfaceComposer::EventRegistrationFlags eventRegistration) { + return eventThread->createEventConnection([&] { resync(); }, eventRegistration); } sp Scheduler::createDisplayEventConnection( - ConnectionHandle handle, ISurfaceComposer::ConfigChanged configChanged) { + ConnectionHandle handle, ISurfaceComposer::EventRegistrationFlags eventRegistration) { std::lock_guard lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle, nullptr); - return createConnectionInternal(mConnections[handle].thread.get(), configChanged); + return createConnectionInternal(mConnections[handle].thread.get(), eventRegistration); } sp Scheduler::getEventConnection(ConnectionHandle handle) { @@ -297,6 +296,17 @@ void Scheduler::onScreenReleased(ConnectionHandle handle) { thread->onScreenReleased(); } +void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId, + std::vector overrides) { + android::EventThread* thread; + { + std::lock_guard lock(mConnectionsLock); + RETURN_IF_INVALID_HANDLE(handle); + thread = mConnections[handle].thread.get(); + } + thread->onFrameRateOverridesChanged(displayId, std::move(overrides)); +} + void Scheduler::onPrimaryDisplayConfigChanged(ConnectionHandle handle, PhysicalDisplayId displayId, HwcConfigIndexType configId, nsecs_t vsyncPeriod) { std::lock_guard lock(mFeatureStateLock); diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 4c86d26a01..76e8f57adc 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -79,8 +79,8 @@ public: std::chrono::nanoseconds readyDuration, impl::EventThread::InterceptVSyncsCallback); - sp createDisplayEventConnection(ConnectionHandle, - ISurfaceComposer::ConfigChanged); + sp createDisplayEventConnection( + ConnectionHandle, ISurfaceComposer::EventRegistrationFlags eventRegistration = {}); sp getEventConnection(ConnectionHandle); @@ -93,6 +93,9 @@ public: void onScreenAcquired(ConnectionHandle); void onScreenReleased(ConnectionHandle); + void onFrameRateOverridesChanged(ConnectionHandle, PhysicalDisplayId, + std::vector); + // Modifies work duration in the event thread. void setDuration(ConnectionHandle, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration); @@ -203,8 +206,8 @@ private: // Create a connection on the given EventThread. ConnectionHandle createConnection(std::unique_ptr); - sp createConnectionInternal(EventThread*, - ISurfaceComposer::ConfigChanged); + sp createConnectionInternal( + EventThread*, ISurfaceComposer::EventRegistrationFlags eventRegistration = {}); // Update feature state machine to given state when corresponding timer resets or expires. void kernelIdleTimerCallback(TimerState); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 91f050c017..eed6aa4a07 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1527,11 +1527,12 @@ status_t SurfaceFlinger::notifyPowerBoost(int32_t boostId) { // ---------------------------------------------------------------------------- sp SurfaceFlinger::createDisplayEventConnection( - ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposer::ConfigChanged configChanged) { + ISurfaceComposer::VsyncSource vsyncSource, + ISurfaceComposer::EventRegistrationFlags eventRegistration) { const auto& handle = vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle; - return mScheduler->createDisplayEventConnection(handle, configChanged); + return mScheduler->createDisplayEventConnection(handle, eventRegistration); } void SurfaceFlinger::signalTransaction() { @@ -5274,10 +5275,18 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r return NO_ERROR; } case 1039: { - // The first parameter is the uid - n = data.readInt32(); - const float refreshRateHz = data.readFloat(); - mRefreshRateConfigs->setPreferredRefreshRateForUid(n, refreshRateHz); + PhysicalDisplayId displayId = [&]() { + Mutex::Autolock lock(mStateLock); + return getDefaultDisplayDeviceLocked()->getPhysicalId(); + }(); + + auto inUid = static_cast(data.readInt32()); + const auto refreshRate = data.readFloat(); + mRefreshRateConfigs->setPreferredRefreshRateForUid( + FrameRateOverride{inUid, refreshRate}); + const auto mappings = mRefreshRateConfigs->getFrameRateOverrides(); + mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId, + std::move(mappings)); } return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 9666f145b0..a909ad81c0 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -530,8 +530,7 @@ private: status_t getSupportedFrameTimestamps(std::vector* outSupported) const override; sp createDisplayEventConnection( ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp, - ISurfaceComposer::ConfigChanged configChanged = - ISurfaceComposer::eConfigChangedSuppress) override; + ISurfaceComposer::EventRegistrationFlags eventRegistration = {}) override; status_t captureDisplay(const DisplayCaptureArgs& args, const sp& captureListener) override; status_t captureDisplay(uint64_t displayOrLayerStack, diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 0a70f5c504..31a51268e6 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -240,8 +240,9 @@ protected: mComposerClient = new SurfaceComposerClient; ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); - mReceiver.reset(new DisplayEventReceiver(ISurfaceComposer::eVsyncSourceApp, - ISurfaceComposer::eConfigChangedDispatch)); + mReceiver.reset( + new DisplayEventReceiver(ISurfaceComposer::eVsyncSourceApp, + ISurfaceComposer::EventRegistration::configChanged)); mLooper = new Looper(false); mLooper->addFd(mReceiver->getFd(), 0, ALOOPER_EVENT_INPUT, processDisplayEvents, this); } diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 091171266f..be9d336137 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -133,17 +133,13 @@ public: EXPECT_CALL(*eventThread, registerDisplayEventConnection(_)); EXPECT_CALL(*eventThread, createEventConnection(_, _)) - .WillOnce(Return( - new EventThreadConnection(eventThread.get(), /*callingUid=*/0, - ResyncCallback(), - ISurfaceComposer::eConfigChangedSuppress))); + .WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0, + ResyncCallback()))); EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_)); EXPECT_CALL(*sfEventThread, createEventConnection(_, _)) - .WillOnce(Return( - new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0, - ResyncCallback(), - ISurfaceComposer::eConfigChangedSuppress))); + .WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0, + ResyncCallback()))); auto vsyncController = std::make_unique(); auto vsyncTracker = std::make_unique(); diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index f0311bdaab..90692003ef 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -70,15 +70,13 @@ DisplayTransactionTest::~DisplayTransactionTest() { void DisplayTransactionTest::injectMockScheduler() { EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)); EXPECT_CALL(*mEventThread, createEventConnection(_, _)) - .WillOnce(Return(new EventThreadConnection(mEventThread, /*callingUid=*/0, - ResyncCallback(), - ISurfaceComposer::eConfigChangedSuppress))); + .WillOnce(Return( + new EventThreadConnection(mEventThread, /*callingUid=*/0, ResyncCallback()))); EXPECT_CALL(*mSFEventThread, registerDisplayEventConnection(_)); EXPECT_CALL(*mSFEventThread, createEventConnection(_, _)) - .WillOnce(Return(new EventThreadConnection(mSFEventThread, /*callingUid=*/0, - ResyncCallback(), - ISurfaceComposer::eConfigChangedSuppress))); + .WillOnce(Return( + new EventThreadConnection(mSFEventThread, /*callingUid=*/0, ResyncCallback()))); mFlinger.setupScheduler(std::unique_ptr(mVsyncController), std::unique_ptr(mVSyncTracker), diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp index 3aafd456d9..ee56178169 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -29,6 +29,7 @@ using namespace std::chrono_literals; using namespace std::placeholders; +using namespace android::flag_operators; using testing::_; using testing::Invoke; @@ -61,9 +62,9 @@ protected: public: MockEventThreadConnection(impl::EventThread* eventThread, uid_t callingUid, ResyncCallback&& resyncCallback, - ISurfaceComposer::ConfigChanged configChanged) + ISurfaceComposer::EventRegistrationFlags eventRegistration) : EventThreadConnection(eventThread, callingUid, std::move(resyncCallback), - configChanged) {} + eventRegistration) {} MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event)); }; @@ -74,9 +75,10 @@ protected: ~EventThreadTest() override; void createThread(std::unique_ptr); - sp createConnection(ConnectionEventRecorder& recorder, - ISurfaceComposer::ConfigChanged configChanged, - uid_t ownerUid = mConnectionUid); + sp createConnection( + ConnectionEventRecorder& recorder, + ISurfaceComposer::EventRegistrationFlags eventRegistration = {}, + uid_t ownerUid = mConnectionUid); void expectVSyncSetEnabledCallReceived(bool expectedState); void expectVSyncSetDurationCallReceived(std::chrono::nanoseconds expectedDuration, @@ -93,6 +95,8 @@ protected: int32_t expectedConfigId, nsecs_t expectedVsyncPeriod); void expectThrottleVsyncReceived(nsecs_t expectedTimestamp, uid_t); + void expectUidFrameRateMappingEventReceivedByConnection(PhysicalDisplayId expectedDisplayId, + std::vector); AsyncCallRecorder mVSyncSetEnabledCallRecorder; AsyncCallRecorder mVSyncSetCallbackCallRecorder; @@ -133,10 +137,11 @@ EventThreadTest::EventThreadTest() { createThread(std::move(vsyncSource)); mConnection = createConnection(mConnectionEventCallRecorder, - ISurfaceComposer::eConfigChangedDispatch); - mThrottledConnection = - createConnection(mThrottledConnectionEventCallRecorder, - ISurfaceComposer::eConfigChangedDispatch, mThrottledConnectionUid); + ISurfaceComposer::EventRegistration::configChanged | + ISurfaceComposer::EventRegistration::frameRateOverride); + mThrottledConnection = createConnection(mThrottledConnectionEventCallRecorder, + ISurfaceComposer::EventRegistration::configChanged, + mThrottledConnectionUid); // A display must be connected for VSYNC events to be delivered. mThread->onHotplugReceived(INTERNAL_DISPLAY_ID, true); @@ -169,11 +174,11 @@ void EventThreadTest::createThread(std::unique_ptr source) { } sp EventThreadTest::createConnection( - ConnectionEventRecorder& recorder, ISurfaceComposer::ConfigChanged configChanged, - uid_t ownerUid) { + ConnectionEventRecorder& recorder, + ISurfaceComposer::EventRegistrationFlags eventRegistration, uid_t ownerUid) { sp connection = new MockEventThreadConnection(mThread.get(), ownerUid, - mResyncCallRecorder.getInvocable(), configChanged); + mResyncCallRecorder.getInvocable(), eventRegistration); EXPECT_CALL(*connection, postEvent(_)).WillRepeatedly(Invoke(recorder.getInvocable())); return connection; } @@ -254,6 +259,25 @@ void EventThreadTest::expectConfigChangedEventReceivedByConnection( EXPECT_EQ(expectedVsyncPeriod, event.config.vsyncPeriod); } +void EventThreadTest::expectUidFrameRateMappingEventReceivedByConnection( + PhysicalDisplayId expectedDisplayId, std::vector expectedOverrides) { + for (const auto [uid, frameRateHz] : expectedOverrides) { + auto args = mConnectionEventCallRecorder.waitForCall(); + ASSERT_TRUE(args.has_value()); + const auto& event = std::get<0>(args.value()); + EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE, event.header.type); + EXPECT_EQ(expectedDisplayId, event.header.displayId); + EXPECT_EQ(uid, event.frameRateOverride.uid); + EXPECT_EQ(frameRateHz, event.frameRateOverride.frameRateHz); + } + + auto args = mConnectionEventCallRecorder.waitForCall(); + ASSERT_TRUE(args.has_value()); + const auto& event = std::get<0>(args.value()); + EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH, event.header.type); + EXPECT_EQ(expectedDisplayId, event.header.displayId); +} + namespace { /* ------------------------------------------------------------------------ @@ -313,9 +337,7 @@ TEST_F(EventThreadTest, requestNextVsyncPostsASingleVSyncEventToTheConnection) { TEST_F(EventThreadTest, setVsyncRateZeroPostsNoVSyncEventsToThatConnection) { // Create a first connection, register it, and request a vsync rate of zero. ConnectionEventRecorder firstConnectionEventRecorder{0}; - sp firstConnection = - createConnection(firstConnectionEventRecorder, - ISurfaceComposer::eConfigChangedSuppress); + sp firstConnection = createConnection(firstConnectionEventRecorder); mThread->setVsyncRate(0, firstConnection); // By itself, this should not enable vsync events @@ -325,8 +347,7 @@ TEST_F(EventThreadTest, setVsyncRateZeroPostsNoVSyncEventsToThatConnection) { // However if there is another connection which wants events at a nonzero rate..... ConnectionEventRecorder secondConnectionEventRecorder{0}; sp secondConnection = - createConnection(secondConnectionEventRecorder, - ISurfaceComposer::eConfigChangedSuppress); + createConnection(secondConnectionEventRecorder); mThread->setVsyncRate(1, secondConnection); // EventThread should enable vsync callbacks. @@ -418,9 +439,7 @@ TEST_F(EventThreadTest, connectionsRemovedIfInstanceDestroyed) { TEST_F(EventThreadTest, connectionsRemovedIfEventDeliveryError) { ConnectionEventRecorder errorConnectionEventRecorder{NO_MEMORY}; - sp errorConnection = - createConnection(errorConnectionEventRecorder, - ISurfaceComposer::eConfigChangedSuppress); + sp errorConnection = createConnection(errorConnectionEventRecorder); mThread->setVsyncRate(1, errorConnection); // EventThread should enable vsync callbacks. @@ -445,15 +464,12 @@ TEST_F(EventThreadTest, connectionsRemovedIfEventDeliveryError) { TEST_F(EventThreadTest, tracksEventConnections) { EXPECT_EQ(2, mThread->getEventThreadConnectionCount()); ConnectionEventRecorder errorConnectionEventRecorder{NO_MEMORY}; - sp errorConnection = - createConnection(errorConnectionEventRecorder, - ISurfaceComposer::eConfigChangedSuppress); + sp errorConnection = createConnection(errorConnectionEventRecorder); mThread->setVsyncRate(1, errorConnection); EXPECT_EQ(3, mThread->getEventThreadConnectionCount()); ConnectionEventRecorder secondConnectionEventRecorder{0}; sp secondConnection = - createConnection(secondConnectionEventRecorder, - ISurfaceComposer::eConfigChangedSuppress); + createConnection(secondConnectionEventRecorder); mThread->setVsyncRate(1, secondConnection); EXPECT_EQ(4, mThread->getEventThreadConnectionCount()); @@ -472,9 +488,7 @@ TEST_F(EventThreadTest, tracksEventConnections) { TEST_F(EventThreadTest, eventsDroppedIfNonfatalEventDeliveryError) { ConnectionEventRecorder errorConnectionEventRecorder{WOULD_BLOCK}; - sp errorConnection = - createConnection(errorConnectionEventRecorder, - ISurfaceComposer::eConfigChangedSuppress); + sp errorConnection = createConnection(errorConnectionEventRecorder); mThread->setVsyncRate(1, errorConnection); // EventThread should enable vsync callbacks. @@ -539,8 +553,7 @@ TEST_F(EventThreadTest, postConfigChangedPrimary64bit) { TEST_F(EventThreadTest, suppressConfigChanged) { ConnectionEventRecorder suppressConnectionEventRecorder{0}; sp suppressConnection = - createConnection(suppressConnectionEventRecorder, - ISurfaceComposer::eConfigChangedSuppress); + createConnection(suppressConnectionEventRecorder); mThread->onConfigChanged(INTERNAL_DISPLAY_ID, HwcConfigIndexType(9), 16666666); expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9, 16666666); @@ -549,6 +562,35 @@ TEST_F(EventThreadTest, suppressConfigChanged) { ASSERT_FALSE(args.has_value()); } +TEST_F(EventThreadTest, postUidFrameRateMapping) { + const std::vector overrides = { + {.uid = 1, .frameRateHz = 20}, + {.uid = 3, .frameRateHz = 40}, + {.uid = 5, .frameRateHz = 60}, + }; + + mThread->onFrameRateOverridesChanged(INTERNAL_DISPLAY_ID, overrides); + expectUidFrameRateMappingEventReceivedByConnection(INTERNAL_DISPLAY_ID, overrides); +} + +TEST_F(EventThreadTest, suppressUidFrameRateMapping) { + const std::vector overrides = { + {.uid = 1, .frameRateHz = 20}, + {.uid = 3, .frameRateHz = 40}, + {.uid = 5, .frameRateHz = 60}, + }; + + ConnectionEventRecorder suppressConnectionEventRecorder{0}; + sp suppressConnection = + createConnection(suppressConnectionEventRecorder); + + mThread->onFrameRateOverridesChanged(INTERNAL_DISPLAY_ID, overrides); + expectUidFrameRateMappingEventReceivedByConnection(INTERNAL_DISPLAY_ID, overrides); + + auto args = suppressConnectionEventRecorder.waitForCall(); + ASSERT_FALSE(args.has_value()); +} + TEST_F(EventThreadTest, requestNextVsyncWithThrottleVsyncDoesntPostVSync) { // Signal that we want the next vsync event to be posted to the throttled connection mThread->requestNextVsync(mThrottledConnection); diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index df7611043a..2fbc72a01a 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -1601,7 +1601,7 @@ TEST_F(RefreshRateConfigsTest, RefreshRateDividerForUid) { std::make_unique(m30_60_72_90_120Device, /*currentConfigId=*/HWC_CONFIG_ID_30); const uid_t uid = 1234; - refreshRateConfigs->setPreferredRefreshRateForUid(uid, 30); + refreshRateConfigs->setPreferredRefreshRateForUid({uid, 30}); EXPECT_EQ(1, refreshRateConfigs->getRefreshRateDividerForUid(uid)); refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_60); @@ -1615,6 +1615,12 @@ TEST_F(RefreshRateConfigsTest, RefreshRateDividerForUid) { refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_120); EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDividerForUid(uid)); + + refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + refreshRateConfigs->setPreferredRefreshRateForUid({uid, 22.5}); + EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDividerForUid(uid)); + refreshRateConfigs->setPreferredRefreshRateForUid({uid, 22.6f}); + EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDividerForUid(uid)); } } // namespace diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp index 8cd8372626..c5deb7ca07 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp @@ -132,14 +132,12 @@ void RefreshRateSelectionTest::setupScheduler() { EXPECT_CALL(*eventThread, registerDisplayEventConnection(_)); EXPECT_CALL(*eventThread, createEventConnection(_, _)) .WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0, - ResyncCallback(), - ISurfaceComposer::eConfigChangedSuppress))); + ResyncCallback()))); EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_)); EXPECT_CALL(*sfEventThread, createEventConnection(_, _)) .WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0, - ResyncCallback(), - ISurfaceComposer::eConfigChangedSuppress))); + ResyncCallback()))); auto vsyncController = std::make_unique(); auto vsyncTracker = std::make_unique(); diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index 509858a4ab..647689b46c 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -42,8 +42,7 @@ protected: class MockEventThreadConnection : public android::EventThreadConnection { public: explicit MockEventThreadConnection(EventThread* eventThread) - : EventThreadConnection(eventThread, /*callingUid=*/0, ResyncCallback(), - ISurfaceComposer::eConfigChangedSuppress) {} + : EventThreadConnection(eventThread, /*callingUid=*/0, ResyncCallback()) {} ~MockEventThreadConnection() = default; MOCK_METHOD1(stealReceiveChannel, status_t(gui::BitTube* outChannel)); @@ -98,9 +97,7 @@ SchedulerTest::SchedulerTest() { TEST_F(SchedulerTest, invalidConnectionHandle) { Scheduler::ConnectionHandle handle; - const sp connection = - mScheduler.createDisplayEventConnection(handle, - ISurfaceComposer::eConfigChangedSuppress); + const sp connection = mScheduler.createDisplayEventConnection(handle); EXPECT_FALSE(connection); EXPECT_FALSE(mScheduler.getEventConnection(handle)); @@ -126,8 +123,7 @@ TEST_F(SchedulerTest, invalidConnectionHandle) { TEST_F(SchedulerTest, validConnectionHandle) { const sp connection = - mScheduler.createDisplayEventConnection(mConnectionHandle, - ISurfaceComposer::eConfigChangedSuppress); + mScheduler.createDisplayEventConnection(mConnectionHandle); ASSERT_EQ(mEventThreadConnection, connection); EXPECT_TRUE(mScheduler.getEventConnection(mConnectionHandle)); diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp index e25d501fe3..5278641e5b 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -172,14 +172,12 @@ void SetFrameRateTest::setupScheduler() { EXPECT_CALL(*eventThread, registerDisplayEventConnection(_)); EXPECT_CALL(*eventThread, createEventConnection(_, _)) .WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0, - ResyncCallback(), - ISurfaceComposer::eConfigChangedSuppress))); + ResyncCallback()))); EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_)); EXPECT_CALL(*sfEventThread, createEventConnection(_, _)) .WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0, - ResyncCallback(), - ISurfaceComposer::eConfigChangedSuppress))); + ResyncCallback()))); auto vsyncController = std::make_unique(); auto vsyncTracker = std::make_unique(); diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index 68cf330b9c..c36d9947b7 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -65,17 +65,13 @@ public: EXPECT_CALL(*eventThread, registerDisplayEventConnection(_)); EXPECT_CALL(*eventThread, createEventConnection(_, _)) - .WillOnce(Return( - new EventThreadConnection(eventThread.get(), /*callingUid=*/0, - ResyncCallback(), - ISurfaceComposer::eConfigChangedSuppress))); + .WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0, + ResyncCallback()))); EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_)); EXPECT_CALL(*sfEventThread, createEventConnection(_, _)) - .WillOnce(Return( - new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0, - ResyncCallback(), - ISurfaceComposer::eConfigChangedSuppress))); + .WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0, + ResyncCallback()))); EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); EXPECT_CALL(*mVSyncTracker, currentPeriod()) diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h index b4594c183d..650d52d88a 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h +++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h @@ -28,11 +28,14 @@ public: ~EventThread() override; MOCK_CONST_METHOD2(createEventConnection, - sp(ResyncCallback, ISurfaceComposer::ConfigChanged)); + sp(ResyncCallback, + ISurfaceComposer::EventRegistrationFlags)); MOCK_METHOD0(onScreenReleased, void()); MOCK_METHOD0(onScreenAcquired, void()); MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool)); MOCK_METHOD3(onConfigChanged, void(PhysicalDisplayId, HwcConfigIndexType, nsecs_t)); + MOCK_METHOD2(onFrameRateOverridesChanged, + void(PhysicalDisplayId, std::vector)); MOCK_CONST_METHOD1(dump, void(std::string&)); MOCK_METHOD2(setDuration, void(std::chrono::nanoseconds workDuration, -- cgit v1.2.3-59-g8ed1b From 981787535c543cf82ef6f92ad17e9d15b6dc032f Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Mon, 21 Dec 2020 19:14:30 -0800 Subject: DisplayEventDispatcher: optimize binder calls Use DisplayEventReciever::setVsyncRate instead of DisplayEventReciever::requestNextVsync to accommodate a one-time registration to vsync events when the app registers back to back callbacks. With this approach we can save all the binder calls during a running animation. Test: run TouchLatency test app and observe systrace Bug: 162096692 Change-Id: Ib415f2aade40a3d23a2b4c77e5746e5e13666d23 --- libs/gui/DisplayEventDispatcher.cpp | 70 ++++++++++++++++------- libs/gui/include/gui/DisplayEventDispatcher.h | 15 ++++- services/surfaceflinger/Scheduler/EventThread.cpp | 4 ++ 3 files changed, 67 insertions(+), 22 deletions(-) (limited to 'libs/gui/DisplayEventDispatcher.cpp') diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp index c6c9a8f7a7..2ad484add3 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -36,7 +36,9 @@ static const size_t EVENT_BUFFER_SIZE = 100; DisplayEventDispatcher::DisplayEventDispatcher( const sp& looper, ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposer::EventRegistrationFlags eventRegistration) - : mLooper(looper), mReceiver(vsyncSource, eventRegistration), mWaitingForVsync(false) { + : mLooper(looper), + mReceiver(vsyncSource, eventRegistration), + mVsyncState(VsyncState::Unregistered) { ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this); } @@ -66,26 +68,37 @@ void DisplayEventDispatcher::dispose() { } status_t DisplayEventDispatcher::scheduleVsync() { - if (!mWaitingForVsync) { - ALOGV("dispatcher %p ~ Scheduling vsync.", this); - - // Drain all pending events. - nsecs_t vsyncTimestamp; - PhysicalDisplayId vsyncDisplayId; - uint32_t vsyncCount; - VsyncEventData vsyncEventData; - if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) { - ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this, - ns2ms(static_cast(vsyncTimestamp))); - } + switch (mVsyncState) { + case VsyncState::Unregistered: { + ALOGV("dispatcher %p ~ Scheduling vsync.", this); + + // Drain all pending events. + nsecs_t vsyncTimestamp; + PhysicalDisplayId vsyncDisplayId; + uint32_t vsyncCount; + VsyncEventData vsyncEventData; + if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, + &vsyncEventData)) { + ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", + this, ns2ms(static_cast(vsyncTimestamp))); + } - status_t status = mReceiver.requestNextVsync(); - if (status) { - ALOGW("Failed to request next vsync, status=%d", status); - return status; - } + status_t status = mReceiver.setVsyncRate(1); + if (status) { + ALOGW("Failed to set vsync rate, status=%d", status); + return status; + } - mWaitingForVsync = true; + mVsyncState = VsyncState::RegisteredAndWaitingForVsync; + break; + } + case VsyncState::Registered: { + mVsyncState = VsyncState::RegisteredAndWaitingForVsync; + break; + } + case VsyncState::RegisteredAndWaitingForVsync: { + break; + } } return OK; } @@ -123,8 +136,23 @@ int DisplayEventDispatcher::handleEvent(int, int events, void*) { ", displayId=%s, count=%d, vsyncId=%" PRId64, this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount, vsyncEventData.id); - mWaitingForVsync = false; - dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData); + switch (mVsyncState) { + case VsyncState::Unregistered: + ALOGW("Received unexpected VSYNC event"); + break; + case VsyncState::RegisteredAndWaitingForVsync: + mVsyncState = VsyncState::Registered; + dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData); + break; + case VsyncState::Registered: + status_t status = mReceiver.setVsyncRate(0); + if (status) { + ALOGW("Failed to reset vsync rate, status=%d", status); + return status; + } + mVsyncState = VsyncState::Unregistered; + break; + } } return 1; // keep the callback diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h index 5587acf08f..4c2b08b2bb 100644 --- a/libs/gui/include/gui/DisplayEventDispatcher.h +++ b/libs/gui/include/gui/DisplayEventDispatcher.h @@ -52,7 +52,20 @@ protected: private: sp mLooper; DisplayEventReceiver mReceiver; - bool mWaitingForVsync; + // The state of vsync event registration and whether the client is expecting + // an event or not. + enum class VsyncState { + // The dispatcher is not registered for vsync events. + Unregistered, + // The dispatcher is registered to receive vsync events but should not dispatch it to the + // client as the client is not expecting a vsync event. + Registered, + + // The dispatcher is registered to receive vsync events and supposed to dispatch it to + // the client. + RegisteredAndWaitingForVsync, + }; + VsyncState mVsyncState; std::vector mFrameRateOverrides; diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index c12a7b106a..f90c130992 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -303,6 +303,10 @@ void EventThread::setVsyncRate(uint32_t rate, const sp& c std::lock_guard lock(mMutex); const auto request = rate == 0 ? VSyncRequest::None : static_cast(rate); + if (request != VSyncRequest::None && connection->resyncCallback) { + connection->resyncCallback(); + } + if (connection->vsyncRequest != request) { connection->vsyncRequest = request; mCondition.notify_all(); -- cgit v1.2.3-59-g8ed1b From a7fe3048aaaf8a45337c7355326f2c6b68b70fb0 Mon Sep 17 00:00:00 2001 From: Marin Shalamanov Date: Fri, 29 Jan 2021 21:02:08 +0100 Subject: Rename DisplayConfig to DisplayMode This CL continues the raneming of display "configs" to display "modes". The goal of this is to have the same names as in the java code and the public display APIs. Additionally in this CL we move DisplayConfig (from libui) to the namespace android::ui. This is to prevent conflict with the SurfaceFlinger's internal android::DisplayMode. This is consistent with the neighboring classes which are also in the ui namespace. Also the type of the parameter defaultMode of {s,g}etDesiredDisplayModeSpecs is changed to size_t for consistency with the rest of the code. Appropriate error handling is added for this. Bug: 159590486 Bug: 179158858 Test: presubmit Change-Id: I31e5be1f2223a9ec9340789ce3dc5738eceaf40f --- cmds/flatland/GLHelper.cpp | 12 +- libs/gui/DisplayEventDispatcher.cpp | 6 +- libs/gui/ISurfaceComposer.cpp | 182 ++++++----- libs/gui/SurfaceComposerClient.cpp | 47 ++- libs/gui/include/gui/DisplayEventDispatcher.h | 4 +- libs/gui/include/gui/DisplayEventReceiver.h | 10 +- libs/gui/include/gui/ISurfaceComposer.h | 61 ++-- libs/gui/include/gui/SurfaceComposerClient.h | 37 +-- libs/gui/tests/BLASTBufferQueue_test.cpp | 8 +- libs/gui/tests/DisplayEventStructLayout_test.cpp | 6 +- libs/gui/tests/EndToEndNativeInputTest.cpp | 8 +- libs/gui/tests/Surface_test.cpp | 30 +- libs/nativedisplay/AChoreographer.cpp | 8 +- libs/nativedisplay/ADisplay.cpp | 34 +- libs/ui/include/ui/DisplayConfig.h | 41 --- libs/ui/include/ui/DisplayMode.h | 41 +++ libs/ui/include_vndk/ui/DisplayConfig.h | 1 - libs/ui/include_vndk/ui/DisplayMode.h | 1 + opengl/tests/lib/WindowSurface.cpp | 10 +- .../display/AutomotiveDisplayProxyService.cpp | 18 +- .../include/AutomotiveDisplayProxyService.h | 2 +- .../surfaceflinger/DisplayHardware/DisplayMode.h | 15 +- services/surfaceflinger/Scheduler/EventThread.cpp | 26 +- services/surfaceflinger/Scheduler/EventThread.h | 10 +- services/surfaceflinger/Scheduler/LayerHistory.cpp | 2 +- services/surfaceflinger/Scheduler/LayerHistory.h | 8 +- services/surfaceflinger/Scheduler/LayerInfo.cpp | 12 +- services/surfaceflinger/Scheduler/LayerInfo.h | 4 +- .../Scheduler/RefreshRateConfigs.cpp | 198 ++++++----- .../surfaceflinger/Scheduler/RefreshRateConfigs.h | 78 +++-- services/surfaceflinger/Scheduler/Scheduler.cpp | 116 ++++--- services/surfaceflinger/Scheduler/Scheduler.h | 28 +- services/surfaceflinger/SurfaceFlinger.cpp | 363 ++++++++++----------- services/surfaceflinger/SurfaceFlinger.h | 93 +++--- services/surfaceflinger/tests/Credentials_test.cpp | 43 ++- .../surfaceflinger/tests/DisplayConfigs_test.cpp | 94 +++--- services/surfaceflinger/tests/IPC_test.cpp | 10 +- .../surfaceflinger/tests/LayerTransactionTest.h | 10 +- services/surfaceflinger/tests/LayerUpdate_test.cpp | 6 +- .../tests/MultiDisplayLayerBounds_test.cpp | 10 +- .../surfaceflinger/tests/ScreenCapture_test.cpp | 6 +- .../tests/SurfaceInterceptor_test.cpp | 8 +- .../tests/TransactionTestHarnesses.h | 6 +- .../tests/fakehwc/SFFakeHwc_test.cpp | 300 +++++++++-------- .../tests/unittests/EventThreadTest.cpp | 18 +- .../tests/unittests/LayerHistoryTest.cpp | 4 +- .../tests/unittests/LayerInfoTest.cpp | 18 +- .../tests/unittests/RefreshRateConfigsTest.cpp | 117 +++---- .../tests/unittests/RefreshRateStatsTest.cpp | 26 +- .../tests/unittests/SchedulerTest.cpp | 24 +- ...ceFlinger_SetupNewDisplayDeviceInternalTest.cpp | 2 +- .../tests/unittests/TestableScheduler.h | 13 +- .../tests/unittests/TestableSurfaceFlinger.h | 36 +- .../tests/unittests/mock/MockEventThread.h | 2 +- 54 files changed, 1127 insertions(+), 1146 deletions(-) delete mode 100644 libs/ui/include/ui/DisplayConfig.h create mode 100644 libs/ui/include/ui/DisplayMode.h delete mode 120000 libs/ui/include_vndk/ui/DisplayConfig.h create mode 120000 libs/ui/include_vndk/ui/DisplayMode.h (limited to 'libs/gui/DisplayEventDispatcher.cpp') diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp index 3a3df08534..01f7d30a42 100644 --- a/cmds/flatland/GLHelper.cpp +++ b/cmds/flatland/GLHelper.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include namespace android { @@ -227,15 +227,15 @@ bool GLHelper::computeWindowScale(uint32_t w, uint32_t h, float* scale) { return false; } - DisplayConfig config; - status_t err = mSurfaceComposerClient->getActiveDisplayConfig(dpy, &config); + ui::DisplayMode mode; + status_t err = mSurfaceComposerClient->getActiveDisplayMode(dpy, &mode); if (err != NO_ERROR) { - fprintf(stderr, "SurfaceComposer::getActiveDisplayConfig failed: %#x\n", err); + fprintf(stderr, "SurfaceComposer::getActiveDisplayMode failed: %#x\n", err); return false; } - float scaleX = static_cast(config.resolution.getWidth()) / w; - float scaleY = static_cast(config.resolution.getHeight()) / h; + float scaleX = static_cast(mode.resolution.getWidth()) / w; + float scaleY = static_cast(mode.resolution.getHeight()) / h; *scale = scaleX < scaleY ? scaleX : scaleY; return true; diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp index 2ad484add3..5c9949b549 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -184,9 +184,9 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected); break; - case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: - dispatchConfigChanged(ev.header.timestamp, ev.header.displayId, - ev.config.configId, ev.config.vsyncPeriod); + case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: + dispatchModeChanged(ev.header.timestamp, ev.header.displayId, + ev.modeChange.modeId, ev.modeChange.vsyncPeriod); break; case DisplayEventReceiver::DISPLAY_EVENT_NULL: dispatchNullEvent(ev.header.timestamp, ev.header.displayId); diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index f68f3e134e..10d48a35bf 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -36,8 +36,8 @@ #include -#include #include +#include #include #include #include @@ -333,20 +333,19 @@ public: return reply.read(*info); } - status_t getDisplayConfigs(const sp& display, - Vector* configs) override { + status_t getDisplayModes(const sp& display, Vector* modes) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); - remote()->transact(BnSurfaceComposer::GET_DISPLAY_CONFIGS, data, &reply); + remote()->transact(BnSurfaceComposer::GET_DISPLAY_MODES, data, &reply); const status_t result = reply.readInt32(); if (result == NO_ERROR) { - const size_t numConfigs = reply.readUint32(); - configs->clear(); - configs->resize(numConfigs); - for (size_t c = 0; c < numConfigs; ++c) { - memcpy(&(configs->editItemAt(c)), reply.readInplace(sizeof(DisplayConfig)), - sizeof(DisplayConfig)); + const size_t numModes = reply.readUint32(); + modes->clear(); + modes->resize(numModes); + for (size_t i = 0; i < numModes; i++) { + memcpy(&(modes->editItemAt(i)), reply.readInplace(sizeof(ui::DisplayMode)), + sizeof(ui::DisplayMode)); } } return result; @@ -366,11 +365,11 @@ public: return result; } - int getActiveConfig(const sp& display) override { + int getActiveDisplayModeId(const sp& display) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); - remote()->transact(BnSurfaceComposer::GET_ACTIVE_CONFIG, data, &reply); + remote()->transact(BnSurfaceComposer::GET_ACTIVE_DISPLAY_MODE, data, &reply); return reply.readInt32(); } @@ -882,71 +881,70 @@ public: return error; } - status_t setDesiredDisplayConfigSpecs(const sp& displayToken, int32_t defaultConfig, - bool allowGroupSwitching, float primaryRefreshRateMin, - float primaryRefreshRateMax, - float appRequestRefreshRateMin, - float appRequestRefreshRateMax) override { + status_t setDesiredDisplayModeSpecs(const sp& displayToken, size_t defaultMode, + bool allowGroupSwitching, float primaryRefreshRateMin, + float primaryRefreshRateMax, float appRequestRefreshRateMin, + float appRequestRefreshRateMax) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to writeInterfaceToken: %d", result); + ALOGE("setDesiredDisplayModeSpecs: failed to writeInterfaceToken: %d", result); return result; } result = data.writeStrongBinder(displayToken); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to write display token: %d", result); + ALOGE("setDesiredDisplayModeSpecs: failed to write display token: %d", result); return result; } - result = data.writeInt32(defaultConfig); + result = data.writeInt32(defaultMode); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs failed to write defaultConfig: %d", result); + ALOGE("setDesiredDisplayModeSpecs failed to write defaultMode: %d", result); return result; } result = data.writeBool(allowGroupSwitching); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs failed to write allowGroupSwitching: %d", result); + ALOGE("setDesiredDisplayModeSpecs failed to write allowGroupSwitching: %d", result); return result; } result = data.writeFloat(primaryRefreshRateMin); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs failed to write primaryRefreshRateMin: %d", result); + ALOGE("setDesiredDisplayModeSpecs failed to write primaryRefreshRateMin: %d", result); return result; } result = data.writeFloat(primaryRefreshRateMax); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs failed to write primaryRefreshRateMax: %d", result); + ALOGE("setDesiredDisplayModeSpecs failed to write primaryRefreshRateMax: %d", result); return result; } result = data.writeFloat(appRequestRefreshRateMin); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs failed to write appRequestRefreshRateMin: %d", + ALOGE("setDesiredDisplayModeSpecs failed to write appRequestRefreshRateMin: %d", result); return result; } result = data.writeFloat(appRequestRefreshRateMax); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs failed to write appRequestRefreshRateMax: %d", + ALOGE("setDesiredDisplayModeSpecs failed to write appRequestRefreshRateMax: %d", result); return result; } - result = remote()->transact(BnSurfaceComposer::SET_DESIRED_DISPLAY_CONFIG_SPECS, data, - &reply); + result = + remote()->transact(BnSurfaceComposer::SET_DESIRED_DISPLAY_MODE_SPECS, data, &reply); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs failed to transact: %d", result); + ALOGE("setDesiredDisplayModeSpecs failed to transact: %d", result); return result; } return reply.readInt32(); } - status_t getDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t* outDefaultConfig, bool* outAllowGroupSwitching, - float* outPrimaryRefreshRateMin, - float* outPrimaryRefreshRateMax, - float* outAppRequestRefreshRateMin, - float* outAppRequestRefreshRateMax) override { - if (!outDefaultConfig || !outAllowGroupSwitching || !outPrimaryRefreshRateMin || + status_t getDesiredDisplayModeSpecs(const sp& displayToken, size_t* outDefaultMode, + bool* outAllowGroupSwitching, + float* outPrimaryRefreshRateMin, + float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, + float* outAppRequestRefreshRateMax) override { + if (!outDefaultMode || !outAllowGroupSwitching || !outPrimaryRefreshRateMin || !outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin || !outAppRequestRefreshRateMax) { return BAD_VALUE; @@ -954,50 +952,55 @@ public: Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to writeInterfaceToken: %d", result); + ALOGE("getDesiredDisplayModeSpecs failed to writeInterfaceToken: %d", result); return result; } result = data.writeStrongBinder(displayToken); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to writeStrongBinder: %d", result); + ALOGE("getDesiredDisplayModeSpecs failed to writeStrongBinder: %d", result); return result; } - result = remote()->transact(BnSurfaceComposer::GET_DESIRED_DISPLAY_CONFIG_SPECS, data, - &reply); + result = + remote()->transact(BnSurfaceComposer::GET_DESIRED_DISPLAY_MODE_SPECS, data, &reply); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to transact: %d", result); + ALOGE("getDesiredDisplayModeSpecs failed to transact: %d", result); return result; } - result = reply.readInt32(outDefaultConfig); + int32_t defaultMode; + result = reply.readInt32(&defaultMode); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to read defaultConfig: %d", result); + ALOGE("getDesiredDisplayModeSpecs failed to read defaultMode: %d", result); return result; } + if (defaultMode < 0) { + ALOGE("%s: defaultMode must be non-negative but it was %d", __func__, defaultMode); + return BAD_VALUE; + } + *outDefaultMode = static_cast(defaultMode); + result = reply.readBool(outAllowGroupSwitching); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to read allowGroupSwitching: %d", result); + ALOGE("getDesiredDisplayModeSpecs failed to read allowGroupSwitching: %d", result); return result; } result = reply.readFloat(outPrimaryRefreshRateMin); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to read primaryRefreshRateMin: %d", result); + ALOGE("getDesiredDisplayModeSpecs failed to read primaryRefreshRateMin: %d", result); return result; } result = reply.readFloat(outPrimaryRefreshRateMax); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to read primaryRefreshRateMax: %d", result); + ALOGE("getDesiredDisplayModeSpecs failed to read primaryRefreshRateMax: %d", result); return result; } result = reply.readFloat(outAppRequestRefreshRateMin); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to read appRequestRefreshRateMin: %d", - result); + ALOGE("getDesiredDisplayModeSpecs failed to read appRequestRefreshRateMin: %d", result); return result; } result = reply.readFloat(outAppRequestRefreshRateMax); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to read appRequestRefreshRateMax: %d", - result); + ALOGE("getDesiredDisplayModeSpecs failed to read appRequestRefreshRateMax: %d", result); return result; } return reply.readInt32(); @@ -1430,17 +1433,17 @@ status_t BnSurfaceComposer::onTransact( if (result != NO_ERROR) return result; return reply->write(info); } - case GET_DISPLAY_CONFIGS: { + case GET_DISPLAY_MODES: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - Vector configs; + Vector modes; const sp display = data.readStrongBinder(); - const status_t result = getDisplayConfigs(display, &configs); + const status_t result = getDisplayModes(display, &modes); reply->writeInt32(result); if (result == NO_ERROR) { - reply->writeUint32(static_cast(configs.size())); - for (size_t c = 0; c < configs.size(); ++c) { - memcpy(reply->writeInplace(sizeof(DisplayConfig)), &configs[c], - sizeof(DisplayConfig)); + reply->writeUint32(static_cast(modes.size())); + for (size_t i = 0; i < modes.size(); i++) { + memcpy(reply->writeInplace(sizeof(ui::DisplayMode)), &modes[i], + sizeof(ui::DisplayMode)); } } return NO_ERROR; @@ -1457,10 +1460,10 @@ status_t BnSurfaceComposer::onTransact( } return NO_ERROR; } - case GET_ACTIVE_CONFIG: { + case GET_ACTIVE_DISPLAY_MODE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp display = data.readStrongBinder(); - int id = getActiveConfig(display); + int id = getActiveDisplayModeId(display); reply->writeInt32(id); return NO_ERROR; } @@ -1844,56 +1847,59 @@ status_t BnSurfaceComposer::onTransact( } return removeRegionSamplingListener(listener); } - case SET_DESIRED_DISPLAY_CONFIG_SPECS: { + case SET_DESIRED_DISPLAY_MODE_SPECS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp displayToken = data.readStrongBinder(); - int32_t defaultConfig; - status_t result = data.readInt32(&defaultConfig); + int32_t defaultMode; + status_t result = data.readInt32(&defaultMode); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to read defaultConfig: %d", result); + ALOGE("setDesiredDisplayModeSpecs: failed to read defaultMode: %d", result); return result; } + if (defaultMode < 0) { + ALOGE("%s: defaultMode must be non-negative but it was %d", __func__, defaultMode); + return BAD_VALUE; + } bool allowGroupSwitching; result = data.readBool(&allowGroupSwitching); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to read allowGroupSwitching: %d", - result); + ALOGE("setDesiredDisplayModeSpecs: failed to read allowGroupSwitching: %d", result); return result; } float primaryRefreshRateMin; result = data.readFloat(&primaryRefreshRateMin); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to read primaryRefreshRateMin: %d", + ALOGE("setDesiredDisplayModeSpecs: failed to read primaryRefreshRateMin: %d", result); return result; } float primaryRefreshRateMax; result = data.readFloat(&primaryRefreshRateMax); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to read primaryRefreshRateMax: %d", + ALOGE("setDesiredDisplayModeSpecs: failed to read primaryRefreshRateMax: %d", result); return result; } float appRequestRefreshRateMin; result = data.readFloat(&appRequestRefreshRateMin); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to read appRequestRefreshRateMin: %d", + ALOGE("setDesiredDisplayModeSpecs: failed to read appRequestRefreshRateMin: %d", result); return result; } float appRequestRefreshRateMax; result = data.readFloat(&appRequestRefreshRateMax); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to read appRequestRefreshRateMax: %d", + ALOGE("setDesiredDisplayModeSpecs: failed to read appRequestRefreshRateMax: %d", result); return result; } - result = setDesiredDisplayConfigSpecs(displayToken, defaultConfig, allowGroupSwitching, - primaryRefreshRateMin, primaryRefreshRateMax, - appRequestRefreshRateMin, - appRequestRefreshRateMax); + result = setDesiredDisplayModeSpecs(displayToken, static_cast(defaultMode), + allowGroupSwitching, primaryRefreshRateMin, + primaryRefreshRateMax, appRequestRefreshRateMin, + appRequestRefreshRateMax); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to call setDesiredDisplayConfigSpecs: " + ALOGE("setDesiredDisplayModeSpecs: failed to call setDesiredDisplayModeSpecs: " "%d", result); return result; @@ -1901,10 +1907,10 @@ status_t BnSurfaceComposer::onTransact( reply->writeInt32(result); return result; } - case GET_DESIRED_DISPLAY_CONFIG_SPECS: { + case GET_DESIRED_DISPLAY_MODE_SPECS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp displayToken = data.readStrongBinder(); - int32_t defaultConfig; + size_t defaultMode; bool allowGroupSwitching; float primaryRefreshRateMin; float primaryRefreshRateMax; @@ -1912,49 +1918,49 @@ status_t BnSurfaceComposer::onTransact( float appRequestRefreshRateMax; status_t result = - getDesiredDisplayConfigSpecs(displayToken, &defaultConfig, &allowGroupSwitching, - &primaryRefreshRateMin, &primaryRefreshRateMax, - &appRequestRefreshRateMin, - &appRequestRefreshRateMax); + getDesiredDisplayModeSpecs(displayToken, &defaultMode, &allowGroupSwitching, + &primaryRefreshRateMin, &primaryRefreshRateMax, + &appRequestRefreshRateMin, + &appRequestRefreshRateMax); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs: failed to get getDesiredDisplayConfigSpecs: " + ALOGE("getDesiredDisplayModeSpecs: failed to get getDesiredDisplayModeSpecs: " "%d", result); return result; } - result = reply->writeInt32(defaultConfig); + result = reply->writeInt32(static_cast(defaultMode)); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs: failed to write defaultConfig: %d", result); + ALOGE("getDesiredDisplayModeSpecs: failed to write defaultMode: %d", result); return result; } result = reply->writeBool(allowGroupSwitching); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs: failed to write allowGroupSwitching: %d", + ALOGE("getDesiredDisplayModeSpecs: failed to write allowGroupSwitching: %d", result); return result; } result = reply->writeFloat(primaryRefreshRateMin); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs: failed to write primaryRefreshRateMin: %d", + ALOGE("getDesiredDisplayModeSpecs: failed to write primaryRefreshRateMin: %d", result); return result; } result = reply->writeFloat(primaryRefreshRateMax); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs: failed to write primaryRefreshRateMax: %d", + ALOGE("getDesiredDisplayModeSpecs: failed to write primaryRefreshRateMax: %d", result); return result; } result = reply->writeFloat(appRequestRefreshRateMin); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs: failed to write appRequestRefreshRateMin: %d", + ALOGE("getDesiredDisplayModeSpecs: failed to write appRequestRefreshRateMin: %d", result); return result; } result = reply->writeFloat(appRequestRefreshRateMax); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs: failed to write appRequestRefreshRateMax: %d", + ALOGE("getDesiredDisplayModeSpecs: failed to write appRequestRefreshRateMax: %d", result); return result; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 550803d453..4493a21fc3 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -39,7 +39,7 @@ #include #include #include -#include +#include #ifndef NO_INPUT #include