EventThread.cpp revision 23748668d33ac850e64d87e25ac4cc78679c9384
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      mDeliveredEvents(0)
40{
41}
42
43void EventThread::onFirstRef() {
44    run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
45}
46
47status_t EventThread::registerDisplayEventConnection(
48        const sp<DisplayEventConnection>& connection) {
49    Mutex::Autolock _l(mLock);
50    mDisplayEventConnections.add(connection);
51    mCondition.signal();
52    return NO_ERROR;
53}
54
55status_t EventThread::unregisterDisplayEventConnection(
56        const wp<DisplayEventConnection>& connection) {
57    Mutex::Autolock _l(mLock);
58    mDisplayEventConnections.remove(connection);
59    mCondition.signal();
60    return NO_ERROR;
61}
62
63status_t EventThread::removeDisplayEventConnection(
64        const wp<DisplayEventConnection>& connection) {
65    Mutex::Autolock _l(mLock);
66    mDisplayEventConnections.remove(connection);
67    return NO_ERROR;
68}
69
70bool EventThread::threadLoop() {
71
72    nsecs_t timestamp;
73    DisplayEventReceiver::Event vsync;
74    SortedVector<wp<DisplayEventConnection> > displayEventConnections;
75
76    { // scope for the lock
77        Mutex::Autolock _l(mLock);
78        do {
79            // wait for listeners
80            while (!mDisplayEventConnections.size()) {
81                mCondition.wait(mLock);
82            }
83
84            // wait for vsync
85            mLock.unlock();
86            timestamp = mHw.waitForVSync();
87            mLock.lock();
88
89            // make sure we still have some listeners
90        } while (!mDisplayEventConnections.size());
91
92
93        // dispatch vsync events to listeners...
94        mDeliveredEvents++;
95
96        vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
97        vsync.header.timestamp = timestamp;
98        vsync.vsync.count = mDeliveredEvents;
99
100        // make a copy of our connection list, so we can
101        // dispatch events without holding mLock
102        displayEventConnections = mDisplayEventConnections;
103    }
104
105    const size_t count = displayEventConnections.size();
106    for (size_t i=0 ; i<count ; i++) {
107        sp<DisplayEventConnection> conn(displayEventConnections.itemAt(i).promote());
108        // make sure the connection didn't die
109        if (conn != NULL) {
110            status_t err = conn->postEvent(vsync);
111            if (err == -EAGAIN || err == -EWOULDBLOCK) {
112                // The destination doesn't accept events anymore, it's probably
113                // full. For now, we just drop the events on the floor.
114                // Note that some events cannot be dropped and would have to be
115                // re-sent later. Right-now we don't have the ability to do
116                // this, but it doesn't matter for VSYNC.
117            } else if (err < 0) {
118                // handle any other error on the pipe as fatal. the only
119                // reasonable thing to do is to clean-up this connection.
120                // The most common error we'll get here is -EPIPE.
121                removeDisplayEventConnection(displayEventConnections.itemAt(i));
122            }
123        } else {
124            // somehow the connection is dead, but we still have it in our list
125            // just clean the list.
126            removeDisplayEventConnection(displayEventConnections.itemAt(i));
127        }
128    }
129
130    // clear all our references without holding mLock
131    displayEventConnections.clear();
132
133    return true;
134}
135
136status_t EventThread::readyToRun() {
137    LOGI("EventThread ready to run.");
138    return NO_ERROR;
139}
140
141void EventThread::dump(String8& result, char* buffer, size_t SIZE) const {
142    Mutex::Autolock _l(mLock);
143    result.append("VSYNC state:\n");
144    snprintf(buffer, SIZE, "  numListeners=%u, events-delivered: %u\n",
145            mDisplayEventConnections.size(), mDeliveredEvents);
146    result.append(buffer);
147}
148
149// ---------------------------------------------------------------------------
150
151}; // namespace android
152