/*
 * Copyright (C) 2009 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 <errno.h>
#include <sys/types.h>

#include <binder/IPCThreadState.h>

#include <utils/threads.h>
#include <utils/Timers.h>
#include <utils/Log.h>

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

#include "MessageQueue.h"
#include "EventThread.h"

namespace android {

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

MessageBase::MessageBase()
    : MessageHandler() {
}

MessageBase::~MessageBase() {
}

void MessageBase::handleMessage(const Message&) {
    this->handler();
    barrier.open();
};

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

MessageQueue::MessageQueue()
    : mLooper(new Looper(true)), mWorkPending(0)
{
}

MessageQueue::~MessageQueue() {
}

void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
    mEventThread = eventThread;
    mEvents = eventThread->createEventConnection();
    mEventTube = mEvents->getDataChannel();
    mLooper->addFd(mEventTube->getFd(), 0, ALOOPER_EVENT_INPUT,
            MessageQueue::cb_eventReceiver, this);
}

void MessageQueue::waitMessage() {
    do {
        IPCThreadState::self()->flushCommands();

        int32_t ret = mLooper->pollOnce(-1);
        switch (ret) {
            case ALOOPER_POLL_WAKE:
            case ALOOPER_POLL_CALLBACK:
                // callback and/or wake
                if (android_atomic_and(0, &mWorkPending)) {
                    return;
                }
                continue;

            case ALOOPER_POLL_TIMEOUT:
                // timeout (should not happen)
                continue;

            case ALOOPER_POLL_ERROR:
                ALOGE("ALOOPER_POLL_ERROR");
                continue;

            default:
                // should not happen
                ALOGE("Looper::pollOnce() returned unknown status %d", ret);
                continue;
        }
    } while (true);
}

status_t MessageQueue::postMessage(
        const sp<MessageBase>& messageHandler, nsecs_t relTime)
{
    const Message dummyMessage;
    if (relTime > 0) {
        mLooper->sendMessageDelayed(relTime, messageHandler, dummyMessage);
    } else {
        mLooper->sendMessage(messageHandler, dummyMessage);
    }
    return NO_ERROR;
}

void MessageQueue::scheduleWorkASAP() {
    if (android_atomic_or(1, &mWorkPending) == 0) {
        mLooper->wake();
   }
}

status_t MessageQueue::invalidate() {
    mEvents->requestNextVsync();
    return NO_ERROR;
}

int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
    MessageQueue* queue = reinterpret_cast<MessageQueue *>(data);
    return queue->eventReceiver(fd, events);
}

int MessageQueue::eventReceiver(int fd, int events) {
    ssize_t n;
    DisplayEventReceiver::Event buffer[8];
    while ((n = getEvents(buffer, 8)) > 0) {
        for (int i=0 ; i<n ; i++) {
            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
                scheduleWorkASAP();
                break;
            }
        }
    }
    return 1;
}

ssize_t MessageQueue::getEvents(
        DisplayEventReceiver::Event* events, size_t count)
{
    ssize_t size = mEventTube->read(events, sizeof(events[0])*count);
    ALOGE_IF(size<0, "MessageQueue::getEvents error (%s)", strerror(-size));
    if (size >= 0) {
        // Note: if (size % sizeof(events[0])) != 0, we've got a
        // partial read. This can happen if the queue filed up (ie: if we
        // didn't pull from it fast enough).
        // We discard the partial event and rely on the sender to
        // re-send the event if appropriate (some events, like VSYNC
        // can be lost forever).
        // returns number of events read
        size /= sizeof(events[0]);
    }
    return size;
}

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

}; // namespace android
