diff options
-rw-r--r-- | libs/gui/DisplayEventDispatcher.cpp | 17 | ||||
-rw-r--r-- | libs/gui/ISurfaceComposer.cpp | 59 | ||||
-rw-r--r-- | libs/gui/Surface.cpp | 11 | ||||
-rw-r--r-- | libs/gui/include/gui/DisplayEventDispatcher.h | 5 | ||||
-rw-r--r-- | libs/gui/include/gui/DisplayEventReceiver.h | 1 | ||||
-rw-r--r-- | libs/gui/include/gui/ISurfaceComposer.h | 8 | ||||
-rw-r--r-- | libs/gui/include/gui/Surface.h | 1 | ||||
-rw-r--r-- | libs/gui/tests/DisplayEventStructLayout_test.cpp | 2 | ||||
-rw-r--r-- | libs/gui/tests/Surface_test.cpp | 9 | ||||
-rw-r--r-- | libs/nativedisplay/AChoreographer.cpp | 27 | ||||
-rw-r--r-- | libs/nativedisplay/include-private/private/android/choreographer.h | 6 | ||||
-rw-r--r-- | libs/nativedisplay/libnativedisplay.map.txt | 1 | ||||
-rw-r--r-- | libs/nativewindow/include/system/window.h | 7 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 4 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 4 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/EventThread.cpp | 9 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 16 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 3 |
18 files changed, 170 insertions, 20 deletions
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<nsecs_t>(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<IGraphicBufferProducer>& 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<IBinder> 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<IGraphicBufferProducer> surface = interface_cast<IGraphicBufferProducer>(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<int64_t>(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<IBinder>* 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<IGraphicBufferProducer>& 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<IBinder>* /*outToken*/) { return NO_ERROR; } + status_t acquireFrameRateFlexibilityToken(sp<IBinder>* /*outToken*/) override { + return NO_ERROR; + } + + status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& /*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<RefreshRateCallback> mRefreshRateCallbacks; nsecs_t mLatestVsyncPeriod = -1; + int64_t mLastVsyncId = -1; const sp<Looper> 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<FrameCallback> callbacks{}; { std::lock_guard<std::mutex> _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*>(choreographer); } +static inline const Choreographer* AChoreographer_to_Choreographer( + const AChoreographer* choreographer) { + return reinterpret_cast<const Choreographer*>(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<const Choreographer*>(choreographer); -} - static inline AChoreographer* Choreographer_to_AChoreographer(Choreographer* choreographer) { return reinterpret_cast<AChoreographer*>(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<IBinder> getHandle(); @@ -1022,6 +1024,8 @@ protected: // Can only be accessed with the SF state lock held. bool mChildrenChanged{false}; + std::optional<int64_t> 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<std::mutex> 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<std::mutex>& 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<IGraphicBufferProducer>& 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> layer = (static_cast<MonitoredProducer*>(surface.get()))->getLayer(); + layer->setFrameTimelineVsync(frameTimelineVsyncId); + return NO_ERROR; +} + void SurfaceFlinger::enableRefreshRateOverlay(bool enable) { static_cast<void>(schedule([=] { std::unique_ptr<RefreshRateOverlay> 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<IBinder>* outToken) override; + status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& surface, + int64_t frameTimelineVsyncId) override; + // Implements IBinder::DeathRecipient. void binderDied(const wp<IBinder>& who) override; |