1054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin/* 2054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * Copyright (c) 2012, The Linux Foundation. All rights reserved. 3054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 4054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * Redistribution and use in source and binary forms, with or without 5054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * modification, are permitted provided that the following conditions are 6054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * met: 7054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * * Redistributions of source code must retain the above copyright 8054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * notice, this list of conditions and the following disclaimer. 9054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * * Redistributions in binary form must reproduce the above 10054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * copyright notice, this list of conditions and the following 11054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * disclaimer in the documentation and/or other materials provided 12054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * with the distribution. 13054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * * Neither the name of The Linux Foundation nor the names of its 14054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * contributors may be used to endorse or promote products derived 15054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * from this software without specific prior written permission. 16054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * 17054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin */ 29054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 30054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin#include "idle_invalidator.h" 31054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin#include <unistd.h> 32054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin#include <poll.h> 33054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin#include <string.h> 34054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin#include <fcntl.h> 35054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin#include <cutils/properties.h> 36054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 37054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin#define II_DEBUG 0 38054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin#define IDLE_NOTIFY_PATH "/sys/devices/virtual/graphics/fb0/idle_notify" 39054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin#define IDLE_TIME_PATH "/sys/devices/virtual/graphics/fb0/idle_time" 40054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 41054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 42054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjinstatic const char *threadName = "IdleInvalidator"; 43054df959aef7dce630a7f41d4aba6626c130756bPatrick TjinInvalidatorHandler IdleInvalidator::mHandler = NULL; 44054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjinandroid::sp<IdleInvalidator> IdleInvalidator::sInstance(0); 45054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 46054df959aef7dce630a7f41d4aba6626c130756bPatrick TjinIdleInvalidator::IdleInvalidator(): Thread(false), mHwcContext(0), 47054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin mTimeoutEventFd(-1) { 48054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__); 49054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin} 50054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 51054df959aef7dce630a7f41d4aba6626c130756bPatrick TjinIdleInvalidator::~IdleInvalidator() { 52054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin if(mTimeoutEventFd >= 0) { 53054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin close(mTimeoutEventFd); 54054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin } 55054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin} 56054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 57054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjinint IdleInvalidator::init(InvalidatorHandler reg_handler, void* user_data) { 58054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin mHandler = reg_handler; 59054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin mHwcContext = user_data; 60054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 61054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin // Open a sysfs node to receive the timeout notification from driver. 62054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin mTimeoutEventFd = open(IDLE_NOTIFY_PATH, O_RDONLY); 63054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin if (mTimeoutEventFd < 0) { 64054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin ALOGE ("%s:not able to open %s node %s", 65054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin __FUNCTION__, IDLE_NOTIFY_PATH, strerror(errno)); 66054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin return -1; 67054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin } 68054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 69054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin int defaultIdleTime = 70; //ms 70054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin char property[PROPERTY_VALUE_MAX] = {0}; 71054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin if((property_get("debug.mdpcomp.idletime", property, NULL) > 0)) { 72054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin defaultIdleTime = atoi(property); 73054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin } 74054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin if(not setIdleTimeout(defaultIdleTime)) { 75054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin close(mTimeoutEventFd); 76054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin mTimeoutEventFd = -1; 77054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin return -1; 78054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin } 79054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 80054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin //Triggers the threadLoop to run, if not already running. 81054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin run(threadName, android::PRIORITY_LOWEST); 82054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin return 0; 83054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin} 84054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 85054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjinbool IdleInvalidator::setIdleTimeout(const uint32_t& timeout) { 86054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin ALOGD_IF(II_DEBUG, "IdleInvalidator::%s timeout %d", 87054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin __FUNCTION__, timeout); 88054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 89054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin // Open a sysfs node to send the timeout value to driver. 90054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin int fd = open(IDLE_TIME_PATH, O_WRONLY); 91054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 92054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin if (fd < 0) { 93054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin ALOGE ("%s:Unable to open %s node %s", 94054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin __FUNCTION__, IDLE_TIME_PATH, strerror(errno)); 95054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin return false; 96054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin } 97054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 98054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin char strSleepTime[64]; 99054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin snprintf(strSleepTime, sizeof(strSleepTime), "%d", timeout); 100054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 101054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin // Notify driver about the timeout value 102054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin ssize_t len = pwrite(fd, strSleepTime, strlen(strSleepTime), 0); 103054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin if(len < -1) { 104054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin ALOGE ("%s:Unable to write into %s node %s", 105054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin __FUNCTION__, IDLE_TIME_PATH, strerror(errno)); 106054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin close(fd); 107054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin return false; 108054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin } 109054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 110054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin close(fd); 111054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin return true; 112054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin} 113054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 114054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjinbool IdleInvalidator::threadLoop() { 115054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__); 116054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin struct pollfd pFd; 117054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin pFd.fd = mTimeoutEventFd; 118054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin if (pFd.fd >= 0) 119054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin pFd.events = POLLPRI | POLLERR; 120054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin // Poll for an timeout event from driver 121054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin int err = poll(&pFd, 1, -1); 122054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin if(err > 0) { 123054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin if (pFd.revents & POLLPRI) { 124054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin char data[64]; 125054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin // Consume the node by reading it 126054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin ssize_t len = pread(pFd.fd, data, 64, 0); 127054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin ALOGD_IF(II_DEBUG, "IdleInvalidator::%s Idle Timeout fired len %zd", 128054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin __FUNCTION__, len); 129054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin mHandler((void*)mHwcContext); 130054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin } 131054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin } 132054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin return true; 133054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin} 134054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 135054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjinint IdleInvalidator::readyToRun() { 136054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__); 137054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin return 0; /*NO_ERROR*/ 138054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin} 139054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 140054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjinvoid IdleInvalidator::onFirstRef() { 141054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__); 142054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin} 143054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin 144054df959aef7dce630a7f41d4aba6626c130756bPatrick TjinIdleInvalidator *IdleInvalidator::getInstance() { 145054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin ALOGD_IF(II_DEBUG, "IdleInvalidator::%s", __FUNCTION__); 146054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin if(sInstance.get() == NULL) 147054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin sInstance = new IdleInvalidator(); 148054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin return sInstance.get(); 149054df959aef7dce630a7f41d4aba6626c130756bPatrick Tjin} 150