diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index 0834c804a..8141b9910 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -96,7 +96,8 @@ LOCAL_SHARED_LIBRARIES := \ libGLESv2 \ libbinder \ libui \ - libgui + libgui \ + libpowermanager LOCAL_MODULE:= libsurfaceflinger diff --git a/services/surfaceflinger/DisplayHardware/PowerHAL.cpp b/services/surfaceflinger/DisplayHardware/PowerHAL.cpp index e41fbbc31..bd50b4a07 100644 --- a/services/surfaceflinger/DisplayHardware/PowerHAL.cpp +++ b/services/surfaceflinger/DisplayHardware/PowerHAL.cpp @@ -20,38 +20,30 @@ #include #include +#include +#include +#include + #include "PowerHAL.h" namespace android { // --------------------------------------------------------------------------- -PowerHAL::PowerHAL() : mPowerModule(0), mVSyncHintEnabled(false) { - int err = hw_get_module(POWER_HARDWARE_MODULE_ID, - (const hw_module_t **)&mPowerModule); - ALOGW_IF(err, "%s module not found", POWER_HARDWARE_MODULE_ID); -} - -PowerHAL::~PowerHAL() { -} - -status_t PowerHAL::initCheck() const { - return mPowerModule ? NO_ERROR : NO_INIT; -} - status_t PowerHAL::vsyncHint(bool enabled) { - if (!mPowerModule) { - return NO_INIT; - } - if (mPowerModule->common.module_api_version >= POWER_MODULE_API_VERSION_0_2) { - if (mPowerModule->powerHint) { - if (mVSyncHintEnabled != bool(enabled)) { - mPowerModule->powerHint(mPowerModule, - POWER_HINT_VSYNC, (void*)enabled); - mVSyncHintEnabled = bool(enabled); - } + Mutex::Autolock _l(mlock); + if (mPowerManager == NULL) { + const String16 serviceName("power"); + sp bs = defaultServiceManager()->checkService(serviceName); + if (bs == NULL) { + return NAME_NOT_FOUND; } + mPowerManager = interface_cast(bs); } - return NO_ERROR; + status_t status = mPowerManager->powerHint(POWER_HINT_VSYNC, enabled ? 1 : 0); + if(status == DEAD_OBJECT) { + mPowerManager = NULL; + } + return status; } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/PowerHAL.h b/services/surfaceflinger/DisplayHardware/PowerHAL.h index ef67b8f19..e5f82a97f 100644 --- a/services/surfaceflinger/DisplayHardware/PowerHAL.h +++ b/services/surfaceflinger/DisplayHardware/PowerHAL.h @@ -19,7 +19,9 @@ #include #include +#include +#include #include namespace android { @@ -28,15 +30,11 @@ namespace android { class PowerHAL { public: - PowerHAL(); - ~PowerHAL(); - - status_t initCheck() const; status_t vsyncHint(bool enabled); private: - power_module_t* mPowerModule; - bool mVSyncHintEnabled; + sp mPowerManager; + Mutex mlock; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index d868f3235..9b6360ef7 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -35,12 +35,21 @@ // --------------------------------------------------------------------------- namespace android { // --------------------------------------------------------------------------- +// time to wait between VSYNC requests before sending a VSYNC OFF power hint: 40msec. +const long vsyncHintOffDelay = 40000000; + +static void vsyncOffCallback(union sigval val) { + EventThread *ev = (EventThread *)val.sival_ptr; + ev->sendVsyncHintOff(); + return; +} EventThread::EventThread(const sp& src) : mVSyncSource(src), mUseSoftwareVSync(false), mVsyncEnabled(false), - mDebugVsyncEnabled(false) { + mDebugVsyncEnabled(false), + mVsyncHintSent(false) { for (int32_t i=0 ; i& src) mVSyncEvent[i].header.timestamp = 0; mVSyncEvent[i].vsync.count = 0; } + struct sigevent se; + se.sigev_notify = SIGEV_THREAD; + se.sigev_value.sival_ptr = this; + se.sigev_notify_function = vsyncOffCallback; + se.sigev_notify_attributes = NULL; + timer_create(CLOCK_MONOTONIC, &se, &mTimerId); +} + +void EventThread::sendVsyncHintOff() { + Mutex::Autolock _l(mLock); + mPowerHAL.vsyncHint(false); + mVsyncHintSent = false; +} + +void EventThread::sendVsyncHintOnLocked() { + struct itimerspec ts; + if(!mVsyncHintSent) { + mPowerHAL.vsyncHint(true); + mVsyncHintSent = true; + } + ts.it_value.tv_sec = 0; + ts.it_value.tv_nsec = vsyncHintOffDelay; + ts.it_interval.tv_sec = 0; + ts.it_interval.tv_nsec = 0; + timer_settime(mTimerId, 0, &ts, NULL); } void EventThread::onFirstRef() { @@ -307,17 +341,16 @@ void EventThread::enableVSyncLocked() { mVsyncEnabled = true; mVSyncSource->setCallback(static_cast(this)); mVSyncSource->setVSyncEnabled(true); - mPowerHAL.vsyncHint(true); } } mDebugVsyncEnabled = true; + sendVsyncHintOnLocked(); } void EventThread::disableVSyncLocked() { if (mVsyncEnabled) { mVsyncEnabled = false; mVSyncSource->setVSyncEnabled(false); - mPowerHAL.vsyncHint(false); mDebugVsyncEnabled = false; } } diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h index f6ab4a787..d1c4fcd98 100644 --- a/services/surfaceflinger/EventThread.h +++ b/services/surfaceflinger/EventThread.h @@ -97,6 +97,7 @@ public: DisplayEventReceiver::Event* event); void dump(String8& result) const; + void sendVsyncHintOff(); private: virtual bool threadLoop(); @@ -107,6 +108,7 @@ private: void removeDisplayEventConnection(const wp& connection); void enableVSyncLocked(); void disableVSyncLocked(); + void sendVsyncHintOnLocked(); // constants sp mVSyncSource; @@ -124,6 +126,9 @@ private: // for debugging bool mDebugVsyncEnabled; + + bool mVsyncHintSent; + timer_t mTimerId; }; // ---------------------------------------------------------------------------