SurfaceFlinger: send VSYNC power hints to IPowerManager

VSYNC power hints are now sent via binder to IPowerManager.
SurfaceFlinger no longer loads a second copy of the PowerHAL.
VSYNC power hints are sent in batches and not on per frame basis.

Change-Id: Icc2eee5df56135bd24dc244a84e7c12dd5511fec
This commit is contained in:
Ruchi Kandoi 2014-04-02 12:50:06 -07:00
parent 9ae71b0060
commit d469a1c328
5 changed files with 63 additions and 34 deletions

View File

@ -96,7 +96,8 @@ LOCAL_SHARED_LIBRARIES := \
libGLESv2 \ libGLESv2 \
libbinder \ libbinder \
libui \ libui \
libgui libgui \
libpowermanager
LOCAL_MODULE:= libsurfaceflinger LOCAL_MODULE:= libsurfaceflinger

View File

@ -20,38 +20,30 @@
#include <cutils/log.h> #include <cutils/log.h>
#include <utils/Errors.h> #include <utils/Errors.h>
#include <binder/IServiceManager.h>
#include <powermanager/IPowerManager.h>
#include <powermanager/PowerManager.h>
#include "PowerHAL.h" #include "PowerHAL.h"
namespace android { 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) { status_t PowerHAL::vsyncHint(bool enabled) {
if (!mPowerModule) { Mutex::Autolock _l(mlock);
return NO_INIT; if (mPowerManager == NULL) {
} const String16 serviceName("power");
if (mPowerModule->common.module_api_version >= POWER_MODULE_API_VERSION_0_2) { sp<IBinder> bs = defaultServiceManager()->checkService(serviceName);
if (mPowerModule->powerHint) { if (bs == NULL) {
if (mVSyncHintEnabled != bool(enabled)) { return NAME_NOT_FOUND;
mPowerModule->powerHint(mPowerModule,
POWER_HINT_VSYNC, (void*)enabled);
mVSyncHintEnabled = bool(enabled);
}
} }
mPowerManager = interface_cast<IPowerManager>(bs);
} }
return NO_ERROR; status_t status = mPowerManager->powerHint(POWER_HINT_VSYNC, enabled ? 1 : 0);
if(status == DEAD_OBJECT) {
mPowerManager = NULL;
}
return status;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -19,7 +19,9 @@
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include <utils/Mutex.h>
#include <powermanager/IPowerManager.h>
#include <hardware/power.h> #include <hardware/power.h>
namespace android { namespace android {
@ -28,15 +30,11 @@ namespace android {
class PowerHAL class PowerHAL
{ {
public: public:
PowerHAL();
~PowerHAL();
status_t initCheck() const;
status_t vsyncHint(bool enabled); status_t vsyncHint(bool enabled);
private: private:
power_module_t* mPowerModule; sp<IPowerManager> mPowerManager;
bool mVSyncHintEnabled; Mutex mlock;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -35,12 +35,21 @@
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
namespace android { 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<VSyncSource>& src) EventThread::EventThread(const sp<VSyncSource>& src)
: mVSyncSource(src), : mVSyncSource(src),
mUseSoftwareVSync(false), mUseSoftwareVSync(false),
mVsyncEnabled(false), mVsyncEnabled(false),
mDebugVsyncEnabled(false) { mDebugVsyncEnabled(false),
mVsyncHintSent(false) {
for (int32_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) { for (int32_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
mVSyncEvent[i].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; mVSyncEvent[i].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
@ -48,6 +57,31 @@ EventThread::EventThread(const sp<VSyncSource>& src)
mVSyncEvent[i].header.timestamp = 0; mVSyncEvent[i].header.timestamp = 0;
mVSyncEvent[i].vsync.count = 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() { void EventThread::onFirstRef() {
@ -307,17 +341,16 @@ void EventThread::enableVSyncLocked() {
mVsyncEnabled = true; mVsyncEnabled = true;
mVSyncSource->setCallback(static_cast<VSyncSource::Callback*>(this)); mVSyncSource->setCallback(static_cast<VSyncSource::Callback*>(this));
mVSyncSource->setVSyncEnabled(true); mVSyncSource->setVSyncEnabled(true);
mPowerHAL.vsyncHint(true);
} }
} }
mDebugVsyncEnabled = true; mDebugVsyncEnabled = true;
sendVsyncHintOnLocked();
} }
void EventThread::disableVSyncLocked() { void EventThread::disableVSyncLocked() {
if (mVsyncEnabled) { if (mVsyncEnabled) {
mVsyncEnabled = false; mVsyncEnabled = false;
mVSyncSource->setVSyncEnabled(false); mVSyncSource->setVSyncEnabled(false);
mPowerHAL.vsyncHint(false);
mDebugVsyncEnabled = false; mDebugVsyncEnabled = false;
} }
} }

View File

@ -97,6 +97,7 @@ public:
DisplayEventReceiver::Event* event); DisplayEventReceiver::Event* event);
void dump(String8& result) const; void dump(String8& result) const;
void sendVsyncHintOff();
private: private:
virtual bool threadLoop(); virtual bool threadLoop();
@ -107,6 +108,7 @@ private:
void removeDisplayEventConnection(const wp<Connection>& connection); void removeDisplayEventConnection(const wp<Connection>& connection);
void enableVSyncLocked(); void enableVSyncLocked();
void disableVSyncLocked(); void disableVSyncLocked();
void sendVsyncHintOnLocked();
// constants // constants
sp<VSyncSource> mVSyncSource; sp<VSyncSource> mVSyncSource;
@ -124,6 +126,9 @@ private:
// for debugging // for debugging
bool mDebugVsyncEnabled; bool mDebugVsyncEnabled;
bool mVsyncHintSent;
timer_t mTimerId;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------