1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <errno.h> 18 #include <stdlib.h> 19 #include <stdio.h> 20 #include <string.h> 21 22 #include <unistd.h> 23 #include <fcntl.h> 24 25 #include <utils/Log.h> 26 27 #include "DisplayHardware/DisplayHardwareBase.h" 28 #include "SurfaceFlinger.h" 29 30 // ---------------------------------------------------------------------------- 31 namespace android { 32 33 static char const * const kSleepFileName = "/sys/power/wait_for_fb_sleep"; 34 static char const * const kWakeFileName = "/sys/power/wait_for_fb_wake"; 35 36 // ---------------------------------------------------------------------------- 37 38 DisplayHardwareBase::DisplayEventThread::DisplayEventThread( 39 const sp<SurfaceFlinger>& flinger) 40 : Thread(false), mFlinger(flinger) { 41 } 42 43 DisplayHardwareBase::DisplayEventThread::~DisplayEventThread() { 44 } 45 46 status_t DisplayHardwareBase::DisplayEventThread::initCheck() const { 47 return ((access(kSleepFileName, R_OK) == 0 && 48 access(kWakeFileName, R_OK) == 0)) ? NO_ERROR : NO_INIT; 49 } 50 51 bool DisplayHardwareBase::DisplayEventThread::threadLoop() { 52 53 if (waitForFbSleep() == NO_ERROR) { 54 sp<SurfaceFlinger> flinger = mFlinger.promote(); 55 ALOGD("About to give-up screen, flinger = %p", flinger.get()); 56 if (flinger != 0) { 57 flinger->screenReleased(); 58 } 59 if (waitForFbWake() == NO_ERROR) { 60 ALOGD("Screen about to return, flinger = %p", flinger.get()); 61 if (flinger != 0) { 62 flinger->screenAcquired(); 63 } 64 return true; 65 } 66 } 67 68 // error, exit the thread 69 return false; 70 } 71 72 status_t DisplayHardwareBase::DisplayEventThread::waitForFbSleep() { 73 int err = 0; 74 char buf; 75 int fd = open(kSleepFileName, O_RDONLY, 0); 76 // if the file doesn't exist, the error will be caught in read() below 77 do { 78 err = read(fd, &buf, 1); 79 } while (err < 0 && errno == EINTR); 80 close(fd); 81 ALOGE_IF(err<0, "*** ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno)); 82 return err < 0 ? -errno : int(NO_ERROR); 83 } 84 85 status_t DisplayHardwareBase::DisplayEventThread::waitForFbWake() { 86 int err = 0; 87 char buf; 88 int fd = open(kWakeFileName, O_RDONLY, 0); 89 // if the file doesn't exist, the error will be caught in read() below 90 do { 91 err = read(fd, &buf, 1); 92 } while (err < 0 && errno == EINTR); 93 close(fd); 94 ALOGE_IF(err<0, "*** ANDROID_WAIT_FOR_FB_WAKE failed (%s)", strerror(errno)); 95 return err < 0 ? -errno : int(NO_ERROR); 96 } 97 98 // ---------------------------------------------------------------------------- 99 100 DisplayHardwareBase::DisplayHardwareBase(const sp<SurfaceFlinger>& flinger, 101 uint32_t displayIndex) 102 { 103 mScreenAcquired = true; 104 mDisplayEventThread = new DisplayEventThread(flinger); 105 } 106 107 void DisplayHardwareBase::startSleepManagement() const { 108 if (mDisplayEventThread->initCheck() == NO_ERROR) { 109 mDisplayEventThread->run("DisplayEventThread", PRIORITY_URGENT_DISPLAY); 110 } else { 111 ALOGW("/sys/power/wait_for_fb_{wake|sleep} don't exist"); 112 } 113 } 114 115 DisplayHardwareBase::~DisplayHardwareBase() { 116 // request exit 117 mDisplayEventThread->requestExitAndWait(); 118 } 119 120 bool DisplayHardwareBase::canDraw() const { 121 return mScreenAcquired; 122 } 123 124 void DisplayHardwareBase::releaseScreen() const { 125 mScreenAcquired = false; 126 } 127 128 void DisplayHardwareBase::acquireScreen() const { 129 mScreenAcquired = true; 130 } 131 132 bool DisplayHardwareBase::isScreenAcquired() const { 133 return mScreenAcquired; 134 } 135 136 }; // namespace android 137