1/* 2 * Copyright (c) 2012, The Linux Foundation. All rights reserved. 3 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above 10 * copyright notice, this list of conditions and the following 11 * disclaimer in the documentation and/or other materials provided 12 * with the distribution. 13 * * Neither the name of The Linux Foundation nor the names of its 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#include "idle_invalidator.h" 31#include <unistd.h> 32#include <poll.h> 33#include <string.h> 34#include <fcntl.h> 35 36#define II_DEBUG 0 37#define IDLE_NOTIFY_PATH "/sys/devices/virtual/graphics/fb0/idle_notify" 38#define IDLE_TIME_PATH "/sys/devices/virtual/graphics/fb0/idle_time" 39 40 41static const char *threadName = "IdleInvalidator"; 42InvalidatorHandler IdleInvalidator::mHandler = NULL; 43android::sp<IdleInvalidator> IdleInvalidator::sInstance(0); 44 45IdleInvalidator::IdleInvalidator(): Thread(false), mHwcContext(0), 46 mTimeoutEventFd(-1) { 47 ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__); 48} 49 50int IdleInvalidator::init(InvalidatorHandler reg_handler, void* user_data, 51 unsigned int idleSleepTime) { 52 ALOGD_IF(II_DEBUG, "IdleInvalidator::%s idleSleepTime %d", 53 __FUNCTION__, idleSleepTime); 54 mHandler = reg_handler; 55 mHwcContext = user_data; 56 57 // Open a sysfs node to receive the timeout notification from driver. 58 mTimeoutEventFd = open(IDLE_NOTIFY_PATH, O_RDONLY); 59 if (mTimeoutEventFd < 0) { 60 ALOGE ("%s:not able to open %s node %s", 61 __FUNCTION__, IDLE_NOTIFY_PATH, strerror(errno)); 62 return -1; 63 } 64 65 // Open a sysfs node to send the timeout value to driver. 66 int fd = open(IDLE_TIME_PATH, O_WRONLY); 67 if (fd < 0) { 68 ALOGE ("%s:not able to open %s node %s", 69 __FUNCTION__, IDLE_TIME_PATH, strerror(errno)); 70 close(mTimeoutEventFd); 71 mTimeoutEventFd = -1; 72 return -1; 73 } 74 char strSleepTime[64]; 75 snprintf(strSleepTime, sizeof(strSleepTime), "%d", idleSleepTime); 76 // Notify driver about the timeout value 77 ssize_t len = pwrite(fd, strSleepTime, strlen(strSleepTime), 0); 78 if(len < -1) { 79 ALOGE ("%s:not able to write into %s node %s", 80 __FUNCTION__, IDLE_TIME_PATH, strerror(errno)); 81 close(mTimeoutEventFd); 82 mTimeoutEventFd = -1; 83 close(fd); 84 return -1; 85 } 86 close(fd); 87 88 //Triggers the threadLoop to run, if not already running. 89 run(threadName, android::PRIORITY_LOWEST); 90 return 0; 91} 92 93bool IdleInvalidator::threadLoop() { 94 ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__); 95 struct pollfd pFd; 96 pFd.fd = mTimeoutEventFd; 97 if (pFd.fd >= 0) 98 pFd.events = POLLPRI | POLLERR; 99 // Poll for an timeout event from driver 100 int err = poll(&pFd, 1, -1); 101 if(err > 0) { 102 if (pFd.revents & POLLPRI) { 103 char data[64]; 104 // Consume the node by reading it 105 ssize_t len = pread(pFd.fd, data, 64, 0); 106 ALOGD_IF(II_DEBUG, "IdleInvalidator::%s Idle Timeout fired len %zu", 107 __FUNCTION__, len); 108 mHandler((void*)mHwcContext); 109 } 110 } 111 return true; 112} 113 114int IdleInvalidator::readyToRun() { 115 ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__); 116 return 0; /*NO_ERROR*/ 117} 118 119void IdleInvalidator::onFirstRef() { 120 ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__); 121} 122 123IdleInvalidator *IdleInvalidator::getInstance() { 124 ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__); 125 if(sInstance.get() == NULL) 126 sInstance = new IdleInvalidator(); 127 return sInstance.get(); 128} 129