Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cb9732a9 authored by Mathias Agopian's avatar Mathias Agopian
Browse files

refactor / simplify EventThread

Change-Id: I3981c6fba93b7b985174b2a7045e24db2c0b4428
parent 9b712211
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -11,7 +11,6 @@ LOCAL_SRC_FILES:= \
    DisplayHardware/DisplayHardwareBase.cpp \
    DisplayHardware/HWComposer.cpp          \
    DisplayHardware/VSyncBarrier.cpp        \
    DisplayEventConnection.cpp              \
    GLExtensions.cpp                        \
    MessageQueue.cpp                        \
    SurfaceFlinger.cpp                      \
+0 −71
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdint.h>
#include <sys/types.h>

#include <gui/IDisplayEventConnection.h>
#include <gui/BitTube.h>
#include <gui/DisplayEventReceiver.h>

#include <utils/Errors.h>

#include "SurfaceFlinger.h"
#include "DisplayEventConnection.h"
#include "EventThread.h"

// ---------------------------------------------------------------------------

namespace android {

// ---------------------------------------------------------------------------

DisplayEventConnection::DisplayEventConnection(
        const sp<EventThread>& eventThread)
    : mEventThread(eventThread), mChannel(new BitTube())
{
}

DisplayEventConnection::~DisplayEventConnection() {
    mEventThread->unregisterDisplayEventConnection(this);
}

void DisplayEventConnection::onFirstRef() {
    // NOTE: mEventThread doesn't hold a strong reference on us
    mEventThread->registerDisplayEventConnection(this);
}

sp<BitTube> DisplayEventConnection::getDataChannel() const {
    return mChannel;
}

void DisplayEventConnection::setVsyncRate(uint32_t count) {
    mEventThread->setVsyncRate(count, this);
}

void DisplayEventConnection::requestNextVsync() {
    mEventThread->requestNextVsync(this);
}

status_t DisplayEventConnection::postEvent(
        const DisplayEventReceiver::Event& event) {
    ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1);
    return size < 0 ? status_t(size) : status_t(NO_ERROR);
}

// ---------------------------------------------------------------------------

}; // namespace android
+0 −62
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_SURFACE_FLINGER_DISPLAY_EVENT_CONNECTION_H
#define ANDROID_SURFACE_FLINGER_DISPLAY_EVENT_CONNECTION_H

#include <stdint.h>
#include <sys/types.h>

#include <gui/IDisplayEventConnection.h>

#include <utils/Errors.h>
#include <gui/DisplayEventReceiver.h>

// ---------------------------------------------------------------------------

namespace android {

// ---------------------------------------------------------------------------

class BitTube;
class EventThread;

// ---------------------------------------------------------------------------

class DisplayEventConnection : public BnDisplayEventConnection {
public:
    DisplayEventConnection(const sp<EventThread>& flinger);

    status_t postEvent(const DisplayEventReceiver::Event& event);

private:
    virtual ~DisplayEventConnection();
    virtual void onFirstRef();
    virtual sp<BitTube> getDataChannel() const;
    virtual void setVsyncRate(uint32_t count);
    virtual void requestNextVsync();    // asynchronous

    sp<EventThread> const mEventThread;
    sp<BitTube> const mChannel;
};

// ---------------------------------------------------------------------------

}; // namespace android

// ---------------------------------------------------------------------------

#endif /* ANDROID_SURFACE_FLINGER_DISPLAY_EVENT_CONNECTION_H */
+69 −44
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <stdint.h>
#include <sys/types.h>

#include <gui/BitTube.h>
#include <gui/IDisplayEventConnection.h>
#include <gui/DisplayEventReceiver.h>

@@ -26,7 +27,6 @@
#include <utils/Trace.h>

#include "DisplayHardware/DisplayHardware.h"
#include "DisplayEventConnection.h"
#include "EventThread.h"
#include "SurfaceFlinger.h"

@@ -48,8 +48,8 @@ void EventThread::onFirstRef() {
    run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
}

sp<DisplayEventConnection> EventThread::createEventConnection() const {
    return new DisplayEventConnection(const_cast<EventThread*>(this));
sp<EventThread::Connection> EventThread::createEventConnection() const {
    return new Connection(const_cast<EventThread*>(this));
}

nsecs_t EventThread::getLastVSyncTimestamp() const {
@@ -63,56 +63,44 @@ nsecs_t EventThread::getVSyncPeriod() const {
}

status_t EventThread::registerDisplayEventConnection(
        const sp<DisplayEventConnection>& connection) {
        const sp<EventThread::Connection>& connection) {
    Mutex::Autolock _l(mLock);
    ConnectionInfo info;
    mDisplayEventConnections.add(connection, info);
    mDisplayEventConnections.add(connection);
    mCondition.signal();
    return NO_ERROR;
}

status_t EventThread::unregisterDisplayEventConnection(
        const wp<DisplayEventConnection>& connection) {
        const wp<EventThread::Connection>& connection) {
    Mutex::Autolock _l(mLock);
    mDisplayEventConnections.removeItem(connection);
    mDisplayEventConnections.remove(connection);
    mCondition.signal();
    return NO_ERROR;
}

void EventThread::removeDisplayEventConnection(
        const wp<DisplayEventConnection>& connection) {
        const wp<EventThread::Connection>& connection) {
    Mutex::Autolock _l(mLock);
    mDisplayEventConnections.removeItem(connection);
}

EventThread::ConnectionInfo* EventThread::getConnectionInfoLocked(
        const wp<DisplayEventConnection>& connection) {
    ssize_t index = mDisplayEventConnections.indexOfKey(connection);
    if (index < 0) return NULL;
    return &mDisplayEventConnections.editValueAt(index);
    mDisplayEventConnections.remove(connection);
}

void EventThread::setVsyncRate(uint32_t count,
        const wp<DisplayEventConnection>& connection) {
        const sp<EventThread::Connection>& connection) {
    if (int32_t(count) >= 0) { // server must protect against bad params
        Mutex::Autolock _l(mLock);
        ConnectionInfo* info = getConnectionInfoLocked(connection);
        if (info) {
        const int32_t new_count = (count == 0) ? -1 : count;
            if (info->count != new_count) {
                info->count = new_count;
        if (connection->count != new_count) {
            connection->count = new_count;
            mCondition.signal();
        }
    }
}
}

void EventThread::requestNextVsync(
        const wp<DisplayEventConnection>& connection) {
        const sp<EventThread::Connection>& connection) {
    Mutex::Autolock _l(mLock);
    ConnectionInfo* info = getConnectionInfoLocked(connection);
    if (info && info->count < 0) {
        info->count = 0;
    if (connection->count < 0) {
        connection->count = 0;
        mCondition.signal();
    }
}
@@ -121,7 +109,7 @@ bool EventThread::threadLoop() {

    nsecs_t timestamp;
    DisplayEventReceiver::Event vsync;
    Vector< wp<DisplayEventConnection> > displayEventConnections;
    Vector< wp<EventThread::Connection> > displayEventConnections;

    { // scope for the lock
        Mutex::Autolock _l(mLock);
@@ -131,9 +119,9 @@ bool EventThread::threadLoop() {
                bool waitForNextVsync = false;
                size_t count = mDisplayEventConnections.size();
                for (size_t i=0 ; i<count ; i++) {
                    const ConnectionInfo& info(
                            mDisplayEventConnections.valueAt(i));
                    if (info.count >= 0) {
                    sp<Connection> connection =
                            mDisplayEventConnections.itemAt(i).promote();
                    if (connection!=0 && connection->count >= 0) {
                        // at least one continuous mode or active one-shot event
                        waitForNextVsync = true;
                        break;
@@ -158,24 +146,26 @@ bool EventThread::threadLoop() {
            const size_t count = mDisplayEventConnections.size();
            for (size_t i=0 ; i<count ; i++) {
                bool reportVsync = false;
                const ConnectionInfo& info(
                        mDisplayEventConnections.valueAt(i));
                if (info.count >= 1) {
                    if (info.count==1 || (mDeliveredEvents % info.count) == 0) {
                sp<Connection> connection =
                        mDisplayEventConnections.itemAt(i).promote();
                if (connection == 0)
                    continue;

                const int32_t count = connection->count;
                if (count >= 1) {
                    if (count==1 || (mDeliveredEvents % count) == 0) {
                        // continuous event, and time to report it
                        reportVsync = true;
                    }
                } else if (info.count >= -1) {
                    ConnectionInfo& info(
                            mDisplayEventConnections.editValueAt(i));
                    if (info.count == 0) {
                } else if (count >= -1) {
                    if (count == 0) {
                        // fired this time around
                        reportVsync = true;
                    }
                    info.count--;
                    connection->count--;
                }
                if (reportVsync) {
                    displayEventConnections.add(mDisplayEventConnections.keyAt(i));
                    displayEventConnections.add(connection);
                }
            }
        } while (!displayEventConnections.size());
@@ -188,7 +178,7 @@ bool EventThread::threadLoop() {

    const size_t count = displayEventConnections.size();
    for (size_t i=0 ; i<count ; i++) {
        sp<DisplayEventConnection> conn(displayEventConnections[i].promote());
        sp<Connection> conn(displayEventConnections[i].promote());
        // make sure the connection didn't die
        if (conn != NULL) {
            status_t err = conn->postEvent(vsync);
@@ -232,4 +222,39 @@ void EventThread::dump(String8& result, char* buffer, size_t SIZE) const {

// ---------------------------------------------------------------------------

EventThread::Connection::Connection(
        const sp<EventThread>& eventThread)
    : count(-1), mEventThread(eventThread), mChannel(new BitTube())
{
}

EventThread::Connection::~Connection() {
    mEventThread->unregisterDisplayEventConnection(this);
}

void EventThread::Connection::onFirstRef() {
    // NOTE: mEventThread doesn't hold a strong reference on us
    mEventThread->registerDisplayEventConnection(this);
}

sp<BitTube> EventThread::Connection::getDataChannel() const {
    return mChannel;
}

void EventThread::Connection::setVsyncRate(uint32_t count) {
    mEventThread->setVsyncRate(count, this);
}

void EventThread::Connection::requestNextVsync() {
    mEventThread->requestNextVsync(this);
}

status_t EventThread::Connection::postEvent(
        const DisplayEventReceiver::Event& event) {
    ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1);
    return size < 0 ? status_t(size) : status_t(NO_ERROR);
}

// ---------------------------------------------------------------------------

}; // namespace android
+29 −32
Original line number Diff line number Diff line
@@ -20,13 +20,12 @@
#include <stdint.h>
#include <sys/types.h>

#include <gui/DisplayEventReceiver.h>
#include <gui/IDisplayEventConnection.h>

#include <utils/Errors.h>
#include <utils/threads.h>
#include <utils/KeyedVector.h>

#include "DisplayEventConnection.h"
#include <utils/SortedVector.h>

// ---------------------------------------------------------------------------

@@ -36,31 +35,43 @@ namespace android {

class SurfaceFlinger;
class DisplayHardware;
class DisplayEventConnection;

// ---------------------------------------------------------------------------

class EventThread : public Thread {
    friend class DisplayEventConnection;

    class Connection : public BnDisplayEventConnection {
    public:
    EventThread(const sp<SurfaceFlinger>& flinger);
        Connection(const sp<EventThread>& eventThread);
        status_t postEvent(const DisplayEventReceiver::Event& event);

        // count >= 1 : continuous event. count is the vsync rate
        // count == 0 : one-shot event that has not fired
        // count ==-1 : one-shot event that fired this round / disabled
        // count ==-2 : one-shot event that fired the round before
        int32_t count;

    sp<DisplayEventConnection> createEventConnection() const;
    private:
        virtual ~Connection();
        virtual void onFirstRef();
        virtual sp<BitTube> getDataChannel() const;
        virtual void setVsyncRate(uint32_t count);
        virtual void requestNextVsync();    // asynchronous
        sp<EventThread> const mEventThread;
        sp<BitTube> const mChannel;
    };

    status_t registerDisplayEventConnection(
            const sp<DisplayEventConnection>& connection);
public:

    status_t unregisterDisplayEventConnection(
            const wp<DisplayEventConnection>& connection);
    EventThread(const sp<SurfaceFlinger>& flinger);

    void setVsyncRate(uint32_t count,
            const wp<DisplayEventConnection>& connection);
    sp<Connection> createEventConnection() const;
    status_t registerDisplayEventConnection(const sp<Connection>& connection);
    status_t unregisterDisplayEventConnection(const wp<Connection>& connection);

    void requestNextVsync(const wp<DisplayEventConnection>& connection);
    void setVsyncRate(uint32_t count, const sp<Connection>& connection);
    void requestNextVsync(const sp<Connection>& connection);

    nsecs_t getLastVSyncTimestamp() const;

    nsecs_t getVSyncPeriod() const;

    void dump(String8& result, char* buffer, size_t SIZE) const;
@@ -70,21 +81,7 @@ private:
    virtual status_t    readyToRun();
    virtual void        onFirstRef();

    struct ConnectionInfo {
        ConnectionInfo() : count(-1) { }

        // count >= 1 : continuous event. count is the vsync rate
        // count == 0 : one-shot event that has not fired
        // count ==-1 : one-shot event that fired this round / disabled
        // count ==-2 : one-shot event that fired the round before
        int32_t count;
    };

    void removeDisplayEventConnection(
            const wp<DisplayEventConnection>& connection);

    ConnectionInfo* getConnectionInfoLocked(
            const wp<DisplayEventConnection>& connection);
    void removeDisplayEventConnection(const wp<Connection>& connection);

    // constants
    sp<SurfaceFlinger> mFlinger;
@@ -94,7 +91,7 @@ private:
    mutable Condition mCondition;

    // protected by mLock
    KeyedVector< wp<DisplayEventConnection>, ConnectionInfo > mDisplayEventConnections;
    SortedVector< wp<Connection> > mDisplayEventConnections;
    nsecs_t mLastVSyncTimestamp;

    // main thread only
Loading