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