/*
 * 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/DisplayEventReceiver.h>

#include <utils/Errors.h>

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

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

namespace android {

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

EventThread::EventThread(const sp<SurfaceFlinger>& flinger)
    : mFlinger(flinger),
      mHw(flinger->graphicPlane(0).displayHardware()),
      mDeliveredEvents(0)
{
}

void EventThread::onFirstRef() {
    run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
}

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

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

void EventThread::removeDisplayEventConnection(
        const wp<DisplayEventConnection>& 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);
}

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

void EventThread::requestNextVsync(
        const wp<DisplayEventConnection>& connection) {
    Mutex::Autolock _l(mLock);
    ConnectionInfo* info = getConnectionInfoLocked(connection);
    if (info) {
        if (info->count < 0) {
            info->count = 0;
        }
        mCondition.signal();
    }
}

bool EventThread::threadLoop() {

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

    { // scope for the lock
        Mutex::Autolock _l(mLock);
        do {
            // see if we need to wait for the VSYNC at all
            do {
                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) {
                        // at least one continuous mode or active one-shot event
                        waitForNextVsync = true;
                        break;
                    }
                }

                if (waitForNextVsync)
                    break;

                mCondition.wait(mLock);
            } while(true);

            // at least one listener requested VSYNC
            mLock.unlock();
            timestamp = mHw.waitForVSync();
            mLock.lock();
            mDeliveredEvents++;

            // now see if we still need to report this VSYNC event
            bool reportVsync = false;
            size_t count = mDisplayEventConnections.size();
            for (size_t i=0 ; i<count ; i++) {
                const ConnectionInfo& info(
                        mDisplayEventConnections.valueAt(i));
                if (info.count >= 1) {
                    if (info.count==1 || (mDeliveredEvents % info.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) {
                        // fired this time around
                        reportVsync = true;
                    }
                    info.count--;
                }
                if (reportVsync) {
                    displayEventConnections.add(mDisplayEventConnections.keyAt(i));
                }
            }

            if (reportVsync) {
                break;
            }
        } while (true);

        // dispatch vsync events to listeners...
        vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
        vsync.header.timestamp = timestamp;
        vsync.vsync.count = mDeliveredEvents;
    }

    const size_t count = displayEventConnections.size();
    for (size_t i=0 ; i<count ; i++) {
        sp<DisplayEventConnection> conn(displayEventConnections[i].promote());
        // make sure the connection didn't die
        if (conn != NULL) {
            status_t err = conn->postEvent(vsync);
            if (err == -EAGAIN || err == -EWOULDBLOCK) {
                // The destination doesn't accept events anymore, it's probably
                // full. For now, we just drop the events on the floor.
                // Note that some events cannot be dropped and would have to be
                // re-sent later. Right-now we don't have the ability to do
                // this, but it doesn't matter for VSYNC.
            } else if (err < 0) {
                // handle any other error on the pipe as fatal. the only
                // reasonable thing to do is to clean-up this connection.
                // The most common error we'll get here is -EPIPE.
                removeDisplayEventConnection(displayEventConnections[i]);
            }
        } else {
            // somehow the connection is dead, but we still have it in our list
            // just clean the list.
            removeDisplayEventConnection(displayEventConnections[i]);
        }
    }

    // clear all our references without holding mLock
    displayEventConnections.clear();

    return true;
}

status_t EventThread::readyToRun() {
    ALOGI("EventThread ready to run.");
    return NO_ERROR;
}

void EventThread::dump(String8& result, char* buffer, size_t SIZE) const {
    Mutex::Autolock _l(mLock);
    result.append("VSYNC state:\n");
    snprintf(buffer, SIZE, "  numListeners=%u, events-delivered: %u\n",
            mDisplayEventConnections.size(), mDeliveredEvents);
    result.append(buffer);
}

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

}; // namespace android
