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:
parent
9ae71b0060
commit
d469a1c328
|
@ -96,7 +96,8 @@ LOCAL_SHARED_LIBRARIES := \
|
||||||
libGLESv2 \
|
libGLESv2 \
|
||||||
libbinder \
|
libbinder \
|
||||||
libui \
|
libui \
|
||||||
libgui
|
libgui \
|
||||||
|
libpowermanager
|
||||||
|
|
||||||
LOCAL_MODULE:= libsurfaceflinger
|
LOCAL_MODULE:= libsurfaceflinger
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue