EventThread.cpp revision 3cf199aef6250552555344944c3e3a6e4ab05f92
1/* 2 * Copyright (C) 2011 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 <stdint.h> 18#include <sys/types.h> 19 20#include <gui/IDisplayEventConnection.h> 21#include <gui/DisplayEventReceiver.h> 22 23#include <utils/Errors.h> 24 25#include "DisplayHardware/DisplayHardware.h" 26#include "DisplayEventConnection.h" 27#include "EventThread.h" 28#include "SurfaceFlinger.h" 29 30// --------------------------------------------------------------------------- 31 32namespace android { 33 34// --------------------------------------------------------------------------- 35 36EventThread::EventThread(const sp<SurfaceFlinger>& flinger) 37 : mFlinger(flinger), 38 mHw(flinger->graphicPlane(0).displayHardware()), 39 mLastVSyncTimestamp(0), 40 mDeliveredEvents(0) 41{ 42} 43 44void EventThread::onFirstRef() { 45 run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); 46} 47 48sp<DisplayEventConnection> EventThread::createEventConnection() const { 49 return new DisplayEventConnection(const_cast<EventThread*>(this)); 50} 51 52nsecs_t EventThread::getLastVSyncTimestamp() const { 53 Mutex::Autolock _l(mLock); 54 return mLastVSyncTimestamp; 55} 56 57nsecs_t EventThread::getVSyncPeriod() const { 58 return mHw.getRefreshPeriod(); 59 60} 61 62status_t EventThread::registerDisplayEventConnection( 63 const sp<DisplayEventConnection>& connection) { 64 Mutex::Autolock _l(mLock); 65 ConnectionInfo info; 66 mDisplayEventConnections.add(connection, info); 67 mCondition.signal(); 68 return NO_ERROR; 69} 70 71status_t EventThread::unregisterDisplayEventConnection( 72 const wp<DisplayEventConnection>& connection) { 73 Mutex::Autolock _l(mLock); 74 mDisplayEventConnections.removeItem(connection); 75 mCondition.signal(); 76 return NO_ERROR; 77} 78 79void EventThread::removeDisplayEventConnection( 80 const wp<DisplayEventConnection>& connection) { 81 Mutex::Autolock _l(mLock); 82 mDisplayEventConnections.removeItem(connection); 83} 84 85EventThread::ConnectionInfo* EventThread::getConnectionInfoLocked( 86 const wp<DisplayEventConnection>& connection) { 87 ssize_t index = mDisplayEventConnections.indexOfKey(connection); 88 if (index < 0) return NULL; 89 return &mDisplayEventConnections.editValueAt(index); 90} 91 92void EventThread::setVsyncRate(uint32_t count, 93 const wp<DisplayEventConnection>& connection) { 94 if (int32_t(count) >= 0) { // server must protect against bad params 95 Mutex::Autolock _l(mLock); 96 ConnectionInfo* info = getConnectionInfoLocked(connection); 97 if (info) { 98 const int32_t new_count = (count == 0) ? -1 : count; 99 if (info->count != new_count) { 100 info->count = new_count; 101 mCondition.signal(); 102 } 103 } 104 } 105} 106 107void EventThread::requestNextVsync( 108 const wp<DisplayEventConnection>& connection) { 109 Mutex::Autolock _l(mLock); 110 ConnectionInfo* info = getConnectionInfoLocked(connection); 111 if (info && info->count < 0) { 112 info->count = 0; 113 mCondition.signal(); 114 } 115} 116 117bool EventThread::threadLoop() { 118 119 nsecs_t timestamp; 120 DisplayEventReceiver::Event vsync; 121 Vector< wp<DisplayEventConnection> > displayEventConnections; 122 123 { // scope for the lock 124 Mutex::Autolock _l(mLock); 125 do { 126 // see if we need to wait for the VSYNC at all 127 do { 128 bool waitForNextVsync = false; 129 size_t count = mDisplayEventConnections.size(); 130 for (size_t i=0 ; i<count ; i++) { 131 const ConnectionInfo& info( 132 mDisplayEventConnections.valueAt(i)); 133 if (info.count >= 0) { 134 // at least one continuous mode or active one-shot event 135 waitForNextVsync = true; 136 break; 137 } 138 } 139 140 if (waitForNextVsync) 141 break; 142 143 mCondition.wait(mLock); 144 } while(true); 145 146 // at least one listener requested VSYNC 147 mLock.unlock(); 148 timestamp = mHw.waitForRefresh(); 149 mLock.lock(); 150 mDeliveredEvents++; 151 mLastVSyncTimestamp = timestamp; 152 153 // now see if we still need to report this VSYNC event 154 const size_t count = mDisplayEventConnections.size(); 155 for (size_t i=0 ; i<count ; i++) { 156 bool reportVsync = false; 157 const ConnectionInfo& info( 158 mDisplayEventConnections.valueAt(i)); 159 if (info.count >= 1) { 160 if (info.count==1 || (mDeliveredEvents % info.count) == 0) { 161 // continuous event, and time to report it 162 reportVsync = true; 163 } 164 } else if (info.count >= -1) { 165 ConnectionInfo& info( 166 mDisplayEventConnections.editValueAt(i)); 167 if (info.count == 0) { 168 // fired this time around 169 reportVsync = true; 170 } 171 info.count--; 172 } 173 if (reportVsync) { 174 displayEventConnections.add(mDisplayEventConnections.keyAt(i)); 175 } 176 } 177 } while (!displayEventConnections.size()); 178 179 // dispatch vsync events to listeners... 180 vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; 181 vsync.header.timestamp = timestamp; 182 vsync.vsync.count = mDeliveredEvents; 183 } 184 185 const size_t count = displayEventConnections.size(); 186 for (size_t i=0 ; i<count ; i++) { 187 sp<DisplayEventConnection> conn(displayEventConnections[i].promote()); 188 // make sure the connection didn't die 189 if (conn != NULL) { 190 status_t err = conn->postEvent(vsync); 191 if (err == -EAGAIN || err == -EWOULDBLOCK) { 192 // The destination doesn't accept events anymore, it's probably 193 // full. For now, we just drop the events on the floor. 194 // Note that some events cannot be dropped and would have to be 195 // re-sent later. Right-now we don't have the ability to do 196 // this, but it doesn't matter for VSYNC. 197 } else if (err < 0) { 198 // handle any other error on the pipe as fatal. the only 199 // reasonable thing to do is to clean-up this connection. 200 // The most common error we'll get here is -EPIPE. 201 removeDisplayEventConnection(displayEventConnections[i]); 202 } 203 } else { 204 // somehow the connection is dead, but we still have it in our list 205 // just clean the list. 206 removeDisplayEventConnection(displayEventConnections[i]); 207 } 208 } 209 210 // clear all our references without holding mLock 211 displayEventConnections.clear(); 212 213 return true; 214} 215 216status_t EventThread::readyToRun() { 217 ALOGI("EventThread ready to run."); 218 return NO_ERROR; 219} 220 221void EventThread::dump(String8& result, char* buffer, size_t SIZE) const { 222 Mutex::Autolock _l(mLock); 223 result.append("VSYNC state:\n"); 224 snprintf(buffer, SIZE, " numListeners=%u, events-delivered: %u\n", 225 mDisplayEventConnections.size(), mDeliveredEvents); 226 result.append(buffer); 227} 228 229// --------------------------------------------------------------------------- 230 231}; // namespace android 232