diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp index 602f20a46..a00ccdbd6 100644 --- a/services/surfaceflinger/DispSync.cpp +++ b/services/surfaceflinger/DispSync.cpp @@ -61,7 +61,10 @@ class DispSyncThread: public Thread { public: DispSyncThread(): + mLowPowerMode(false), mStop(false), + mLastVsyncSent(false), + mLastBufferFull(false), mPeriod(0), mPhase(0), mWakeupLatency(0) { @@ -145,7 +148,18 @@ public: } if (callbackInvocations.size() > 0) { - fireCallbackInvocations(callbackInvocations); + if (mLowPowerMode) { + if (!mLastVsyncSent || !mLastBufferFull) { + fireCallbackInvocations(callbackInvocations); + mLastVsyncSent = true; + } else + mLastVsyncSent = false; + } else { + fireCallbackInvocations(callbackInvocations); + } + mLastBufferFull = true; + } else { + mLastBufferFull = false; } } @@ -200,6 +214,7 @@ public: return !mEventListeners.empty(); } + bool mLowPowerMode; private: struct EventListener { @@ -272,6 +287,8 @@ private: } bool mStop; + bool mLastVsyncSent; + bool mLastBufferFull; nsecs_t mPeriod; nsecs_t mPhase; @@ -395,6 +412,10 @@ status_t DispSync::addEventListener(nsecs_t phase, return mThread->addEventListener(phase, callback); } +void DispSync::setLowPowerMode(bool enabled) { + mThread->mLowPowerMode = enabled; +} + status_t DispSync::removeEventListener(const sp& callback) { Mutex::Autolock lock(mMutex); return mThread->removeEventListener(callback); diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h index c4280aa0e..c2ae135b0 100644 --- a/services/surfaceflinger/DispSync.h +++ b/services/surfaceflinger/DispSync.h @@ -88,6 +88,9 @@ public: // turned on. It should NOT be used after that. void setPeriod(nsecs_t period); + // Setting the low power mode reduces the frame rate to half of the default + void setLowPowerMode(bool enabled); + // addEventListener registers a callback to be called repeatedly at the // given phase offset from the hardware vsync events. The callback is // called from a separate thread and it should return reasonably quickly diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a3465200b..0142992a8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2643,6 +2643,16 @@ status_t SurfaceFlinger::onTransact( repaintEverything(); return NO_ERROR; } + // This is an experimental interface + // Needs to be shifted to proper binder interface when we productize + case 1016: { + mPrimaryDispSync.setLowPowerMode(true); + return NO_ERROR; + } + case 1017: { + mPrimaryDispSync.setLowPowerMode(false); + return NO_ERROR; + } } } return err;