From db4ac3ce63074f5602b46074ffeabfea4a14d032 Mon Sep 17 00:00:00 2001 From: Dan Stoza Date: Tue, 14 Apr 2015 11:34:01 -0700 Subject: [PATCH] SF: Permit changing DispSync offsets at runtime This modifies EventThread such that its phase offsets for both Choreographer and SurfaceFlinger may be modified at runtime. It also plumbs this functionality up to the SurfaceFlinger debug interface so that it is possible to rapidly test different offsets without restarting the framework. Change-Id: I426873f8553f931250dfebc9a8a4a78e9f1f4309 --- services/surfaceflinger/EventThread.cpp | 5 ++ services/surfaceflinger/EventThread.h | 3 + services/surfaceflinger/SurfaceFlinger.cpp | 69 +++++++++++++++++++--- 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index 9b6360ef7..f76020000 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -71,6 +71,11 @@ void EventThread::sendVsyncHintOff() { mVsyncHintSent = false; } +void EventThread::setPhaseOffset(nsecs_t phaseOffset) { + Mutex::Autolock _l(mLock); + mVSyncSource->setPhaseOffset(phaseOffset); +} + void EventThread::sendVsyncHintOnLocked() { struct itimerspec ts; if(!mVsyncHintSent) { diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h index d1c4fcd98..9ba179ad7 100644 --- a/services/surfaceflinger/EventThread.h +++ b/services/surfaceflinger/EventThread.h @@ -51,6 +51,7 @@ public: virtual ~VSyncSource() {} virtual void setVSyncEnabled(bool enable) = 0; virtual void setCallback(const sp& callback) = 0; + virtual void setPhaseOffset(nsecs_t phaseOffset) = 0; }; class EventThread : public Thread, private VSyncSource::Callback { @@ -99,6 +100,8 @@ public: void dump(String8& result) const; void sendVsyncHintOff(); + void setPhaseOffset(nsecs_t phaseOffset); + private: virtual bool threadLoop(); virtual void onFirstRef(); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f967c9d89..df4ac2e66 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -320,17 +320,20 @@ public: DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync, const char* label) : mValue(0), - mPhaseOffset(phaseOffset), mTraceVsync(traceVsync), mVsyncOnLabel(String8::format("VsyncOn-%s", label)), mVsyncEventLabel(String8::format("VSYNC-%s", label)), - mDispSync(dispSync) {} + mDispSync(dispSync), + mCallbackMutex(), + mCallback(), + mVsyncMutex(), + mPhaseOffset(phaseOffset), + mEnabled(false) {} virtual ~DispSyncSource() {} virtual void setVSyncEnabled(bool enable) { - // Do NOT lock the mutex here so as to avoid any mutex ordering issues - // with locking it in the onDispSyncEvent callback. + Mutex::Autolock lock(mVsyncMutex); if (enable) { status_t err = mDispSync->addEventListener(mPhaseOffset, static_cast(this)); @@ -348,18 +351,54 @@ public: } //ATRACE_INT(mVsyncOnLabel.string(), 0); } + mEnabled = enable; } virtual void setCallback(const sp& callback) { - Mutex::Autolock lock(mMutex); + Mutex::Autolock lock(mCallbackMutex); mCallback = callback; } + virtual void setPhaseOffset(nsecs_t phaseOffset) { + Mutex::Autolock lock(mVsyncMutex); + + // Normalize phaseOffset to [0, period) + auto period = mDispSync->getPeriod(); + phaseOffset %= period; + if (phaseOffset < 0) { + // If we're here, then phaseOffset is in (-period, 0). After this + // operation, it will be in (0, period) + phaseOffset += period; + } + mPhaseOffset = phaseOffset; + + // If we're not enabled, we don't need to mess with the listeners + if (!mEnabled) { + return; + } + + // Remove the listener with the old offset + status_t err = mDispSync->removeEventListener( + static_cast(this)); + if (err != NO_ERROR) { + ALOGE("error unregistering vsync callback: %s (%d)", + strerror(-err), err); + } + + // Add a listener with the new offset + err = mDispSync->addEventListener(mPhaseOffset, + static_cast(this)); + if (err != NO_ERROR) { + ALOGE("error registering vsync callback: %s (%d)", + strerror(-err), err); + } + } + private: virtual void onDispSyncEvent(nsecs_t when) { sp callback; { - Mutex::Autolock lock(mMutex); + Mutex::Autolock lock(mCallbackMutex); callback = mCallback; if (mTraceVsync) { @@ -375,14 +414,18 @@ private: int mValue; - const nsecs_t mPhaseOffset; const bool mTraceVsync; const String8 mVsyncOnLabel; const String8 mVsyncEventLabel; DispSync* mDispSync; + + Mutex mCallbackMutex; // Protects the following sp mCallback; - Mutex mMutex; + + Mutex mVsyncMutex; // Protects the following + nsecs_t mPhaseOffset; + bool mEnabled; }; void SurfaceFlinger::init() { @@ -2887,6 +2930,16 @@ status_t SurfaceFlinger::onTransact( mForceFullDamage = static_cast(n); return NO_ERROR; } + case 1018: { // Modify Choreographer's phase offset + n = data.readInt32(); + mEventThread->setPhaseOffset(static_cast(n)); + return NO_ERROR; + } + case 1019: { // Modify SurfaceFlinger's phase offset + n = data.readInt32(); + mSFEventThread->setPhaseOffset(static_cast(n)); + return NO_ERROR; + } } } return err;