17d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber/*
27d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber * Copyright (C) 2010 The Android Open Source Project
37d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber *
47d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
57d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber * you may not use this file except in compliance with the License.
67d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber * You may obtain a copy of the License at
77d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber *
87d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
97d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber *
107d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber * Unless required by applicable law or agreed to in writing, software
117d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
127d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber * See the License for the specific language governing permissions and
147d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber * limitations under the License.
157d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber */
167d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
177d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber//#define LOG_NDEBUG 0
187d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber#define LOG_TAG "ALooper"
197d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber#include <utils/Log.h>
207d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
217d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber#include <sys/time.h>
227d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
237d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber#include "ALooper.h"
247d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
257d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber#include "AHandler.h"
267d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber#include "ALooperRoster.h"
277d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber#include "AMessage.h"
287d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
297d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Hubernamespace android {
307d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
317d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas HuberALooperRoster gLooperRoster;
327d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
337d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huberstruct ALooper::LooperThread : public Thread {
344f104d99d8657fd3fef675eb2a3e84ba9f5870e4Andreas Huber    LooperThread(ALooper *looper, bool canCallJava)
354f104d99d8657fd3fef675eb2a3e84ba9f5870e4Andreas Huber        : Thread(canCallJava),
364f104d99d8657fd3fef675eb2a3e84ba9f5870e4Andreas Huber          mLooper(looper) {
377d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    }
387d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
397d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    virtual bool threadLoop() {
407d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        return mLooper->loop();
417d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    }
427d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
437d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huberprotected:
447d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    virtual ~LooperThread() {}
457d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
467d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huberprivate:
477d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    ALooper *mLooper;
487d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
497d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(LooperThread);
507d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber};
517d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
527d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber// static
537d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huberint64_t ALooper::GetNowUs() {
547d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    struct timeval tv;
557d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    gettimeofday(&tv, NULL);
567d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
577d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    return (int64_t)tv.tv_sec * 1000000ll + tv.tv_usec;
587d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber}
597d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
607d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas HuberALooper::ALooper()
617d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    : mRunningLocally(false) {
627d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber}
637d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
647d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas HuberALooper::~ALooper() {
657d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    stop();
667d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber}
677d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
68c4e0b70a21fadb47d70955c71fc31ce1473da925Andreas Hubervoid ALooper::setName(const char *name) {
69c4e0b70a21fadb47d70955c71fc31ce1473da925Andreas Huber    mName = name;
70c4e0b70a21fadb47d70955c71fc31ce1473da925Andreas Huber}
71c4e0b70a21fadb47d70955c71fc31ce1473da925Andreas Huber
727d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas HuberALooper::handler_id ALooper::registerHandler(const sp<AHandler> &handler) {
737d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    return gLooperRoster.registerHandler(this, handler);
747d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber}
757d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
767d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Hubervoid ALooper::unregisterHandler(handler_id handlerID) {
777d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    gLooperRoster.unregisterHandler(handlerID);
787d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber}
797d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
804e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huberstatus_t ALooper::start(
814e4173b0af52bdf2b5730a5837476e400c5b2040Andreas Huber        bool runOnCallingThread, bool canCallJava, int32_t priority) {
827d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    if (runOnCallingThread) {
837d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        {
847d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber            Mutex::Autolock autoLock(mLock);
857d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
867d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber            if (mThread != NULL || mRunningLocally) {
877d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber                return INVALID_OPERATION;
887d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber            }
897d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
907d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber            mRunningLocally = true;
917d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        }
927d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
937d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        do {
947d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        } while (loop());
957d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
967d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        return OK;
977d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    }
987d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
997d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    Mutex::Autolock autoLock(mLock);
1007d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1017d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    if (mThread != NULL || mRunningLocally) {
1027d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        return INVALID_OPERATION;
1037d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    }
1047d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1054f104d99d8657fd3fef675eb2a3e84ba9f5870e4Andreas Huber    mThread = new LooperThread(this, canCallJava);
1067d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
107c4e0b70a21fadb47d70955c71fc31ce1473da925Andreas Huber    status_t err = mThread->run(
108c4e0b70a21fadb47d70955c71fc31ce1473da925Andreas Huber            mName.empty() ? "ALooper" : mName.c_str(), priority);
1097d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    if (err != OK) {
1107d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        mThread.clear();
1117d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    }
1127d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1137d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    return err;
1147d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber}
1157d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1167d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huberstatus_t ALooper::stop() {
1177d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    sp<LooperThread> thread;
1187d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    bool runningLocally;
1197d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1207d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    {
1217d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        Mutex::Autolock autoLock(mLock);
1227d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1237d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        thread = mThread;
1247d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        runningLocally = mRunningLocally;
1257d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        mThread.clear();
1267d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        mRunningLocally = false;
1277d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    }
1287d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1297d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    if (thread == NULL && !runningLocally) {
1307d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        return INVALID_OPERATION;
1317d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    }
1327d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1337d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    if (thread != NULL) {
1347d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        thread->requestExit();
1357d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    }
1367d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1377d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    mQueueChangedCondition.signal();
1387d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1397d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    if (!runningLocally) {
1407d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        thread->requestExitAndWait();
1417d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    }
1427d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1437d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    return OK;
1447d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber}
1457d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1467d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Hubervoid ALooper::post(const sp<AMessage> &msg, int64_t delayUs) {
1477d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    Mutex::Autolock autoLock(mLock);
1487d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1497d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    int64_t whenUs;
1507d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    if (delayUs > 0) {
1517d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        whenUs = GetNowUs() + delayUs;
1527d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    } else {
1537d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        whenUs = GetNowUs();
1547d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    }
1557d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1567d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    List<Event>::iterator it = mEventQueue.begin();
1577d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    while (it != mEventQueue.end() && (*it).mWhenUs <= whenUs) {
1587d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        ++it;
1597d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    }
1607d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1617d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    Event event;
1627d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    event.mWhenUs = whenUs;
1637d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    event.mMessage = msg;
1647d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1657d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    if (it == mEventQueue.begin()) {
1667d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        mQueueChangedCondition.signal();
1677d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    }
1687d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1697d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    mEventQueue.insert(it, event);
1707d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber}
1717d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1727d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huberbool ALooper::loop() {
1737d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    Event event;
1747d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1757d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    {
1767d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        Mutex::Autolock autoLock(mLock);
1777d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        if (mThread == NULL && !mRunningLocally) {
1787d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber            return false;
1797d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        }
1807d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        if (mEventQueue.empty()) {
1817d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber            mQueueChangedCondition.wait(mLock);
1827d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber            return true;
1837d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        }
1847d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        int64_t whenUs = (*mEventQueue.begin()).mWhenUs;
1857d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        int64_t nowUs = GetNowUs();
1867d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1877d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        if (whenUs > nowUs) {
1887d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber            int64_t delayUs = whenUs - nowUs;
1897d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber            mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll);
1907d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1917d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber            return true;
1927d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        }
1937d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1947d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        event = *mEventQueue.begin();
1957d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber        mEventQueue.erase(mEventQueue.begin());
1967d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    }
1977d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
1987d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    gLooperRoster.deliverMessage(event.mMessage);
1997d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
2007d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber    return true;
2017d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber}
2027d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber
2037d2f703649e270b635018f8b7219bb0e1d62a2e5Andreas Huber}  // namespace android
204