EventThread.cpp revision 2965b26022f95051f65b09d7eac47cbe923855c9
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#define ATRACE_TAG ATRACE_TAG_GRAPHICS 18 19#include <stdint.h> 20#include <sys/types.h> 21 22#include <gui/BitTube.h> 23#include <gui/IDisplayEventConnection.h> 24#include <gui/DisplayEventReceiver.h> 25 26#include <utils/Errors.h> 27#include <utils/Trace.h> 28 29#include "DisplayHardware/DisplayHardware.h" 30#include "EventThread.h" 31#include "SurfaceFlinger.h" 32 33// --------------------------------------------------------------------------- 34 35namespace android { 36 37// --------------------------------------------------------------------------- 38 39EventThread::EventThread(const sp<SurfaceFlinger>& flinger) 40 : mFlinger(flinger), 41 mHw(flinger->graphicPlane(0).editDisplayHardware()), 42 mLastVSyncTimestamp(0), 43 mVSyncTimestamp(0), 44 mDeliveredEvents(0) 45{ 46} 47 48void EventThread::onFirstRef() { 49 mHw.setVSyncHandler(this); 50 run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); 51} 52 53sp<EventThread::Connection> EventThread::createEventConnection() const { 54 return new Connection(const_cast<EventThread*>(this)); 55} 56 57nsecs_t EventThread::getLastVSyncTimestamp() const { 58 Mutex::Autolock _l(mLock); 59 return mLastVSyncTimestamp; 60} 61 62nsecs_t EventThread::getVSyncPeriod() const { 63 return mHw.getRefreshPeriod(); 64 65} 66 67status_t EventThread::registerDisplayEventConnection( 68 const sp<EventThread::Connection>& connection) { 69 Mutex::Autolock _l(mLock); 70 mDisplayEventConnections.add(connection); 71 mCondition.signal(); 72 return NO_ERROR; 73} 74 75status_t EventThread::unregisterDisplayEventConnection( 76 const wp<EventThread::Connection>& connection) { 77 Mutex::Autolock _l(mLock); 78 mDisplayEventConnections.remove(connection); 79 mCondition.signal(); 80 return NO_ERROR; 81} 82 83void EventThread::removeDisplayEventConnection( 84 const wp<EventThread::Connection>& connection) { 85 Mutex::Autolock _l(mLock); 86 mDisplayEventConnections.remove(connection); 87} 88 89void EventThread::setVsyncRate(uint32_t count, 90 const sp<EventThread::Connection>& connection) { 91 if (int32_t(count) >= 0) { // server must protect against bad params 92 Mutex::Autolock _l(mLock); 93 const int32_t new_count = (count == 0) ? -1 : count; 94 if (connection->count != new_count) { 95 connection->count = new_count; 96 mCondition.signal(); 97 } 98 } 99} 100 101void EventThread::requestNextVsync( 102 const sp<EventThread::Connection>& connection) { 103 Mutex::Autolock _l(mLock); 104 if (connection->count < 0) { 105 connection->count = 0; 106 mCondition.signal(); 107 } 108} 109 110void EventThread::onVSyncReceived(int, nsecs_t timestamp) { 111 Mutex::Autolock _l(mLock); 112 mVSyncTimestamp = timestamp; 113 mCondition.signal(); 114} 115 116bool EventThread::threadLoop() { 117 118 nsecs_t timestamp; 119 DisplayEventReceiver::Event vsync; 120 Vector< wp<EventThread::Connection> > displayEventConnections; 121 122 do { 123 124 Mutex::Autolock _l(mLock); 125 do { 126 // latch VSYNC event if any 127 timestamp = mVSyncTimestamp; 128 mVSyncTimestamp = 0; 129 130 // check if we should be waiting for VSYNC events 131 bool waitForNextVsync = false; 132 size_t count = mDisplayEventConnections.size(); 133 for (size_t i=0 ; i<count ; i++) { 134 sp<Connection> connection = 135 mDisplayEventConnections.itemAt(i).promote(); 136 if (connection!=0 && connection->count >= 0) { 137 // at least one continuous mode or active one-shot event 138 waitForNextVsync = true; 139 break; 140 } 141 } 142 143 if (timestamp) { 144 if (!waitForNextVsync) { 145 // we received a VSYNC but we have no clients 146 // don't report it, and disable VSYNC events 147 mHw.getHwComposer().eventControl( 148 HWComposer::EVENT_VSYNC, false); 149 } else { 150 // report VSYNC event 151 break; 152 } 153 } else { 154 // never disable VSYNC events immediately, instead 155 // we'll wait to receive the event and we'll 156 // reevaluate whether we need to dispatch it and/or 157 // disable VSYNC events then. 158 if (waitForNextVsync) { 159 // enable 160 mHw.getHwComposer().eventControl( 161 HWComposer::EVENT_VSYNC, true); 162 } 163 } 164 165 // wait for something to happen 166 mCondition.wait(mLock); 167 } while(true); 168 169 // process vsync event 170 mDeliveredEvents++; 171 mLastVSyncTimestamp = timestamp; 172 173 // now see if we still need to report this VSYNC event 174 const size_t count = mDisplayEventConnections.size(); 175 for (size_t i=0 ; i<count ; i++) { 176 bool reportVsync = false; 177 sp<Connection> connection = 178 mDisplayEventConnections.itemAt(i).promote(); 179 if (connection == 0) 180 continue; 181 182 const int32_t count = connection->count; 183 if (count >= 1) { 184 if (count==1 || (mDeliveredEvents % count) == 0) { 185 // continuous event, and time to report it 186 reportVsync = true; 187 } 188 } else if (count >= -1) { 189 if (count == 0) { 190 // fired this time around 191 reportVsync = true; 192 } 193 connection->count--; 194 } 195 if (reportVsync) { 196 displayEventConnections.add(connection); 197 } 198 } 199 } while (!displayEventConnections.size()); 200 201 // dispatch vsync events to listeners... 202 vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; 203 vsync.header.timestamp = timestamp; 204 vsync.vsync.count = mDeliveredEvents; 205 206 const size_t count = displayEventConnections.size(); 207 for (size_t i=0 ; i<count ; i++) { 208 sp<Connection> conn(displayEventConnections[i].promote()); 209 // make sure the connection didn't die 210 if (conn != NULL) { 211 status_t err = conn->postEvent(vsync); 212 if (err == -EAGAIN || err == -EWOULDBLOCK) { 213 // The destination doesn't accept events anymore, it's probably 214 // full. For now, we just drop the events on the floor. 215 // Note that some events cannot be dropped and would have to be 216 // re-sent later. Right-now we don't have the ability to do 217 // this, but it doesn't matter for VSYNC. 218 } else if (err < 0) { 219 // handle any other error on the pipe as fatal. the only 220 // reasonable thing to do is to clean-up this connection. 221 // The most common error we'll get here is -EPIPE. 222 removeDisplayEventConnection(displayEventConnections[i]); 223 } 224 } else { 225 // somehow the connection is dead, but we still have it in our list 226 // just clean the list. 227 removeDisplayEventConnection(displayEventConnections[i]); 228 } 229 } 230 231 // clear all our references without holding mLock 232 displayEventConnections.clear(); 233 234 return true; 235} 236 237status_t EventThread::readyToRun() { 238 ALOGI("EventThread ready to run."); 239 return NO_ERROR; 240} 241 242void EventThread::dump(String8& result, char* buffer, size_t SIZE) const { 243 Mutex::Autolock _l(mLock); 244 result.append("VSYNC state:\n"); 245 snprintf(buffer, SIZE, " numListeners=%u, events-delivered: %u\n", 246 mDisplayEventConnections.size(), mDeliveredEvents); 247 result.append(buffer); 248} 249 250// --------------------------------------------------------------------------- 251 252EventThread::Connection::Connection( 253 const sp<EventThread>& eventThread) 254 : count(-1), mEventThread(eventThread), mChannel(new BitTube()) 255{ 256} 257 258EventThread::Connection::~Connection() { 259 mEventThread->unregisterDisplayEventConnection(this); 260} 261 262void EventThread::Connection::onFirstRef() { 263 // NOTE: mEventThread doesn't hold a strong reference on us 264 mEventThread->registerDisplayEventConnection(this); 265} 266 267sp<BitTube> EventThread::Connection::getDataChannel() const { 268 return mChannel; 269} 270 271void EventThread::Connection::setVsyncRate(uint32_t count) { 272 mEventThread->setVsyncRate(count, this); 273} 274 275void EventThread::Connection::requestNextVsync() { 276 mEventThread->requestNextVsync(this); 277} 278 279status_t EventThread::Connection::postEvent( 280 const DisplayEventReceiver::Event& event) { 281 ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1); 282 return size < 0 ? status_t(size) : status_t(NO_ERROR); 283} 284 285// --------------------------------------------------------------------------- 286 287}; // namespace android 288