surfaceflinger: replace early suspend with binder call from PowerManager

SurfaceFlinger will no longer directly synchronize with early suspend.
Instead, PowerManagerService will synchronize with SurfaceFlinger to
ensure that a black frame has been drawn on the display, and then
trigger all early suspend handlers.

Change-Id: I07acdd628440d23fdb69db94319ec5d65d3f4919
This commit is contained in:
Colin Cross 2012-06-07 13:17:52 -07:00
parent 1e339878c1
commit 8e533069e5
5 changed files with 38 additions and 84 deletions

View File

@ -139,6 +139,12 @@ public:
/* return an IDisplayEventConnection */
virtual sp<IDisplayEventConnection> createDisplayEventConnection() = 0;
/* triggers screen off and waits for it to complete */
virtual void blank() = 0;
/* triggers screen on and waits for it to complete */
virtual void unblank() = 0;
};
// ----------------------------------------------------------------------------
@ -160,6 +166,8 @@ public:
TURN_ELECTRON_BEAM_ON,
AUTHENTICATE_SURFACE,
CREATE_DISPLAY_EVENT_CONNECTION,
BLANK,
UNBLANK,
};
virtual status_t onTransact( uint32_t code,

View File

@ -193,6 +193,20 @@ public:
result = interface_cast<IDisplayEventConnection>(reply.readStrongBinder());
return result;
}
virtual void blank()
{
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::BLANK, data, &reply);
}
virtual void unblank()
{
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::UNBLANK, data, &reply);
}
};
IMPLEMENT_META_INTERFACE(SurfaceComposer, "android.ui.ISurfaceComposer");
@ -279,6 +293,14 @@ status_t BnSurfaceComposer::onTransact(
reply->writeStrongBinder(connection->asBinder());
return NO_ERROR;
} break;
case BLANK: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
blank();
} break;
case UNBLANK: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
unblank();
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}

View File

@ -30,91 +30,13 @@
// ----------------------------------------------------------------------------
namespace android {
static char const * const kSleepFileName = "/sys/power/wait_for_fb_sleep";
static char const * const kWakeFileName = "/sys/power/wait_for_fb_wake";
// ----------------------------------------------------------------------------
DisplayHardwareBase::DisplayEventThread::DisplayEventThread(
const sp<SurfaceFlinger>& flinger)
: Thread(false), mFlinger(flinger) {
}
DisplayHardwareBase::DisplayEventThread::~DisplayEventThread() {
}
status_t DisplayHardwareBase::DisplayEventThread::initCheck() const {
return ((access(kSleepFileName, R_OK) == 0 &&
access(kWakeFileName, R_OK) == 0)) ? NO_ERROR : NO_INIT;
}
bool DisplayHardwareBase::DisplayEventThread::threadLoop() {
if (waitForFbSleep() == NO_ERROR) {
sp<SurfaceFlinger> flinger = mFlinger.promote();
ALOGD("About to give-up screen, flinger = %p", flinger.get());
if (flinger != 0) {
flinger->screenReleased();
}
if (waitForFbWake() == NO_ERROR) {
ALOGD("Screen about to return, flinger = %p", flinger.get());
if (flinger != 0) {
flinger->screenAcquired();
}
return true;
}
}
// error, exit the thread
return false;
}
status_t DisplayHardwareBase::DisplayEventThread::waitForFbSleep() {
int err = 0;
char buf;
int fd = open(kSleepFileName, O_RDONLY, 0);
// if the file doesn't exist, the error will be caught in read() below
do {
err = read(fd, &buf, 1);
} while (err < 0 && errno == EINTR);
close(fd);
ALOGE_IF(err<0, "*** ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno));
return err < 0 ? -errno : int(NO_ERROR);
}
status_t DisplayHardwareBase::DisplayEventThread::waitForFbWake() {
int err = 0;
char buf;
int fd = open(kWakeFileName, O_RDONLY, 0);
// if the file doesn't exist, the error will be caught in read() below
do {
err = read(fd, &buf, 1);
} while (err < 0 && errno == EINTR);
close(fd);
ALOGE_IF(err<0, "*** ANDROID_WAIT_FOR_FB_WAKE failed (%s)", strerror(errno));
return err < 0 ? -errno : int(NO_ERROR);
}
// ----------------------------------------------------------------------------
DisplayHardwareBase::DisplayHardwareBase(const sp<SurfaceFlinger>& flinger,
uint32_t displayIndex)
{
mScreenAcquired = true;
mDisplayEventThread = new DisplayEventThread(flinger);
}
void DisplayHardwareBase::startSleepManagement() const {
if (mDisplayEventThread->initCheck() == NO_ERROR) {
mDisplayEventThread->run("DisplayEventThread", PRIORITY_URGENT_DISPLAY);
} else {
ALOGW("/sys/power/wait_for_fb_{wake|sleep} don't exist");
}
}
DisplayHardwareBase::~DisplayHardwareBase() {
// request exit
mDisplayEventThread->requestExitAndWait();
}
bool DisplayHardwareBase::canDraw() const {

View File

@ -297,7 +297,6 @@ status_t SurfaceFlinger::readyToRun()
// start the EventThread
mEventThread = new EventThread(this);
mEventQueue.setEventThread(mEventThread);
hw.startSleepManagement();
/*
* We're now ready to accept clients...
@ -1363,6 +1362,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(
// ---------------------------------------------------------------------------
void SurfaceFlinger::onScreenAcquired() {
ALOGD("Screen about to return, flinger = %p", this);
const DisplayHardware& hw(graphicPlane(0).displayHardware());
hw.acquireScreen();
mEventThread->onScreenAcquired();
@ -1374,6 +1374,7 @@ void SurfaceFlinger::onScreenAcquired() {
}
void SurfaceFlinger::onScreenReleased() {
ALOGD("About to give-up screen, flinger = %p", this);
const DisplayHardware& hw(graphicPlane(0).displayHardware());
if (hw.isScreenAcquired()) {
mEventThread->onScreenReleased();
@ -1382,7 +1383,7 @@ void SurfaceFlinger::onScreenReleased() {
}
}
void SurfaceFlinger::screenAcquired() {
void SurfaceFlinger::unblank() {
class MessageScreenAcquired : public MessageBase {
SurfaceFlinger* flinger;
public:
@ -1396,7 +1397,7 @@ void SurfaceFlinger::screenAcquired() {
postMessageSync(msg);
}
void SurfaceFlinger::screenReleased() {
void SurfaceFlinger::blank() {
class MessageScreenReleased : public MessageBase {
SurfaceFlinger* flinger;
public:
@ -1654,6 +1655,8 @@ status_t SurfaceFlinger::onTransact(
case BOOT_FINISHED:
case TURN_ELECTRON_BEAM_OFF:
case TURN_ELECTRON_BEAM_ON:
case BLANK:
case UNBLANK:
{
// codes that require permission check
IPCThreadState* ipc = IPCThreadState::self();

View File

@ -182,11 +182,10 @@ public:
virtual status_t turnElectronBeamOff(int32_t mode);
virtual status_t turnElectronBeamOn(int32_t mode);
// called when screen needs to turn off
void screenReleased();
virtual void blank();
// called when screen is turning back on
void screenAcquired();
virtual void unblank();
// called on the main thread in response to screenReleased()
void onScreenReleased();