EventThread.cpp revision d94d3b890ac3d5731bd0397874d32aa4bc74bd61
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 171 ATRACE_INT("VSYNC", mDeliveredEvents&1); 172 mDeliveredEvents++; 173 mLastVSyncTimestamp = timestamp; 174 175 // now see if we still need to report this VSYNC event 176 const size_t count = mDisplayEventConnections.size(); 177 for (size_t i=0 ; i<count ; i++) { 178 bool reportVsync = false; 179 sp<Connection> connection = 180 mDisplayEventConnections.itemAt(i).promote(); 181 if (connection == 0) 182 continue; 183 184 const int32_t count = connection->count; 185 if (count >= 1) { 186 if (count==1 || (mDeliveredEvents % count) == 0) { 187 // continuous event, and time to report it 188 reportVsync = true; 189 } 190 } else if (count >= -1) { 191 if (count == 0) { 192 // fired this time around 193 reportVsync = true; 194 } 195 connection->count--; 196 } 197 if (reportVsync) { 198 displayEventConnections.add(connection); 199 } 200 } 201 } while (!displayEventConnections.size()); 202 203 // dispatch vsync events to listeners... 204 vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; 205 vsync.header.timestamp = timestamp; 206 vsync.vsync.count = mDeliveredEvents; 207 208 const size_t count = displayEventConnections.size(); 209 for (size_t i=0 ; i<count ; i++) { 210 sp<Connection> conn(displayEventConnections[i].promote()); 211 // make sure the connection didn't die 212 if (conn != NULL) { 213 status_t err = conn->postEvent(vsync); 214 if (err == -EAGAIN || err == -EWOULDBLOCK) { 215 // The destination doesn't accept events anymore, it's probably 216 // full. For now, we just drop the events on the floor. 217 // Note that some events cannot be dropped and would have to be 218 // re-sent later. Right-now we don't have the ability to do 219 // this, but it doesn't matter for VSYNC. 220 } else if (err < 0) { 221 // handle any other error on the pipe as fatal. the only 222 // reasonable thing to do is to clean-up this connection. 223 // The most common error we'll get here is -EPIPE. 224 removeDisplayEventConnection(displayEventConnections[i]); 225 } 226 } else { 227 // somehow the connection is dead, but we still have it in our list 228 // just clean the list. 229 removeDisplayEventConnection(displayEventConnections[i]); 230 } 231 } 232 233 // clear all our references without holding mLock 234 displayEventConnections.clear(); 235 236 return true; 237} 238 239status_t EventThread::readyToRun() { 240 ALOGI("EventThread ready to run."); 241 return NO_ERROR; 242} 243 244void EventThread::dump(String8& result, char* buffer, size_t SIZE) const { 245 Mutex::Autolock _l(mLock); 246 result.append("VSYNC state:\n"); 247 snprintf(buffer, SIZE, " numListeners=%u, events-delivered: %u\n", 248 mDisplayEventConnections.size(), mDeliveredEvents); 249 result.append(buffer); 250} 251 252// --------------------------------------------------------------------------- 253 254EventThread::Connection::Connection( 255 const sp<EventThread>& eventThread) 256 : count(-1), mEventThread(eventThread), mChannel(new BitTube()) 257{ 258} 259 260EventThread::Connection::~Connection() { 261 mEventThread->unregisterDisplayEventConnection(this); 262} 263 264void EventThread::Connection::onFirstRef() { 265 // NOTE: mEventThread doesn't hold a strong reference on us 266 mEventThread->registerDisplayEventConnection(this); 267} 268 269sp<BitTube> EventThread::Connection::getDataChannel() const { 270 return mChannel; 271} 272 273void EventThread::Connection::setVsyncRate(uint32_t count) { 274 mEventThread->setVsyncRate(count, this); 275} 276 277void EventThread::Connection::requestNextVsync() { 278 mEventThread->requestNextVsync(this); 279} 280 281status_t EventThread::Connection::postEvent( 282 const DisplayEventReceiver::Event& event) { 283 ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1); 284 return size < 0 ? status_t(size) : status_t(NO_ERROR); 285} 286 287// --------------------------------------------------------------------------- 288 289}; // namespace android 290