EventThread.cpp revision 3eb38cb33e41ce40dd1094bdec850f0fca9f8a53
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 // check if we have received a VSYNC event 127 if (mVSyncTimestamp) { 128 // we have a VSYNC event pending 129 timestamp = mVSyncTimestamp; 130 mVSyncTimestamp = 0; 131 break; 132 } 133 134 // check if we should be waiting for VSYNC events 135 bool waitForNextVsync = false; 136 size_t count = mDisplayEventConnections.size(); 137 for (size_t i=0 ; i<count ; i++) { 138 sp<Connection> connection = 139 mDisplayEventConnections.itemAt(i).promote(); 140 if (connection!=0 && connection->count >= 0) { 141 // at least one continuous mode or active one-shot event 142 waitForNextVsync = true; 143 break; 144 } 145 } 146 147 // enable or disable VSYNC events 148 mHw.getHwComposer().eventControl( 149 HWComposer::EVENT_VSYNC, waitForNextVsync); 150 151 // wait for something to happen 152 mCondition.wait(mLock); 153 } while(true); 154 155 // process vsync event 156 157 ATRACE_INT("VSYNC", mDeliveredEvents&1); 158 mDeliveredEvents++; 159 mLastVSyncTimestamp = timestamp; 160 161 // now see if we still need to report this VSYNC event 162 const size_t count = mDisplayEventConnections.size(); 163 for (size_t i=0 ; i<count ; i++) { 164 bool reportVsync = false; 165 sp<Connection> connection = 166 mDisplayEventConnections.itemAt(i).promote(); 167 if (connection == 0) 168 continue; 169 170 const int32_t count = connection->count; 171 if (count >= 1) { 172 if (count==1 || (mDeliveredEvents % count) == 0) { 173 // continuous event, and time to report it 174 reportVsync = true; 175 } 176 } else if (count >= -1) { 177 if (count == 0) { 178 // fired this time around 179 reportVsync = true; 180 } 181 connection->count--; 182 } 183 if (reportVsync) { 184 displayEventConnections.add(connection); 185 } 186 } 187 } while (!displayEventConnections.size()); 188 189 // dispatch vsync events to listeners... 190 vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; 191 vsync.header.timestamp = timestamp; 192 vsync.vsync.count = mDeliveredEvents; 193 194 const size_t count = displayEventConnections.size(); 195 for (size_t i=0 ; i<count ; i++) { 196 sp<Connection> conn(displayEventConnections[i].promote()); 197 // make sure the connection didn't die 198 if (conn != NULL) { 199 status_t err = conn->postEvent(vsync); 200 if (err == -EAGAIN || err == -EWOULDBLOCK) { 201 // The destination doesn't accept events anymore, it's probably 202 // full. For now, we just drop the events on the floor. 203 // Note that some events cannot be dropped and would have to be 204 // re-sent later. Right-now we don't have the ability to do 205 // this, but it doesn't matter for VSYNC. 206 } else if (err < 0) { 207 // handle any other error on the pipe as fatal. the only 208 // reasonable thing to do is to clean-up this connection. 209 // The most common error we'll get here is -EPIPE. 210 removeDisplayEventConnection(displayEventConnections[i]); 211 } 212 } else { 213 // somehow the connection is dead, but we still have it in our list 214 // just clean the list. 215 removeDisplayEventConnection(displayEventConnections[i]); 216 } 217 } 218 219 // clear all our references without holding mLock 220 displayEventConnections.clear(); 221 222 return true; 223} 224 225status_t EventThread::readyToRun() { 226 ALOGI("EventThread ready to run."); 227 return NO_ERROR; 228} 229 230void EventThread::dump(String8& result, char* buffer, size_t SIZE) const { 231 Mutex::Autolock _l(mLock); 232 result.append("VSYNC state:\n"); 233 snprintf(buffer, SIZE, " numListeners=%u, events-delivered: %u\n", 234 mDisplayEventConnections.size(), mDeliveredEvents); 235 result.append(buffer); 236} 237 238// --------------------------------------------------------------------------- 239 240EventThread::Connection::Connection( 241 const sp<EventThread>& eventThread) 242 : count(-1), mEventThread(eventThread), mChannel(new BitTube()) 243{ 244} 245 246EventThread::Connection::~Connection() { 247 mEventThread->unregisterDisplayEventConnection(this); 248} 249 250void EventThread::Connection::onFirstRef() { 251 // NOTE: mEventThread doesn't hold a strong reference on us 252 mEventThread->registerDisplayEventConnection(this); 253} 254 255sp<BitTube> EventThread::Connection::getDataChannel() const { 256 return mChannel; 257} 258 259void EventThread::Connection::setVsyncRate(uint32_t count) { 260 mEventThread->setVsyncRate(count, this); 261} 262 263void EventThread::Connection::requestNextVsync() { 264 mEventThread->requestNextVsync(this); 265} 266 267status_t EventThread::Connection::postEvent( 268 const DisplayEventReceiver::Event& event) { 269 ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1); 270 return size < 0 ? status_t(size) : status_t(NO_ERROR); 271} 272 273// --------------------------------------------------------------------------- 274 275}; // namespace android 276