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