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

Commit 58eab5f3 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android Git Automerger
Browse files

am 68267415: Add new native Looper API.

Merge commit '682674154e3fe88f6061245145f934f25f1a2eb8' into gingerbread-plus-aosp

* commit '682674154e3fe88f6061245145f934f25f1a2eb8':
  Add new native Looper API.
parents 7c1c974d efa10850
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include <semaphore.h>
#include <ui/Input.h>
#include <utils/Errors.h>
#include <utils/PollLoop.h>
#include <utils/Timers.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
@@ -345,11 +346,15 @@ public:
    
    android::status_t consume(android::InputEvent** event);
    
    void setPollLoop(const android::sp<android::PollLoop>& pollLoop) { mPollLoop = pollLoop; }
    const android::sp<android::PollLoop> getPollLoop() const { return mPollLoop; }
    
    virtual void doDefaultKey(android::KeyEvent* keyEvent) = 0;
    
private:
    android::InputConsumer mConsumer;
    android::PreallocatedInputEventFactory mInputEventFactory;
    android::sp<android::PollLoop> mPollLoop;
};

#endif // _UI_INPUT_TRANSPORT_H
+33 −1
Original line number Diff line number Diff line
@@ -22,12 +22,22 @@

#include <sys/poll.h>

#include <android/looper.h>

struct ALooper : public android::RefBase {
protected:
    virtual ~ALooper() { }

public:
    ALooper() { }
};

namespace android {

/**
 * A basic file descriptor polling loop based on poll() with callbacks.
 */
class PollLoop : public RefBase {
class PollLoop : public ALooper {
protected:
    virtual ~PollLoop();

@@ -82,6 +92,11 @@ public:
     */
    void setCallback(int fd, int events, Callback callback, void* data = NULL);

    /**
     * Like setCallback(), but for the NDK callback function.
     */
    void setLooperCallback(int fd, int events, ALooper_callbackFunc* callback, void* data);
    
    /**
     * Removes the callback for a file descriptor, if one exists.
     *
@@ -100,9 +115,22 @@ public:
     */
    bool removeCallback(int fd);

    /**
     * Set the given PollLoop to be associated with the
     * calling thread.  There must be a 1:1 relationship between
     * PollLoop and thread.
     */
    static void setForThread(const sp<PollLoop>& pollLoop);
    
    /**
     * Return the PollLoop associated with the calling thread.
     */
    static sp<PollLoop> getForThread();
    
private:
    struct RequestedCallback {
        Callback callback;
        ALooper_callbackFunc* looperCallback;
        void* data;
    };

@@ -110,6 +138,7 @@ private:
        int fd;
        int events;
        Callback callback;
        ALooper_callbackFunc* looperCallback;
        void* data;
    };

@@ -130,8 +159,11 @@ private:
    void openWakePipe();
    void closeWakePipe();

    void setCallbackCommon(int fd, int events, Callback callback,
            ALooper_callbackFunc* looperCallback, void* data);
    ssize_t getRequestIndexLocked(int fd);
    void wakeAndLock();
    static void threadDestructor(void *st);
};

} // namespace android
+64 −4
Original line number Diff line number Diff line
@@ -21,6 +21,10 @@

namespace android {

static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
static bool gHaveTLS = false;
static pthread_key_t gTLS = 0;

PollLoop::PollLoop() :
        mPolling(false), mWaiters(0) {
    openWakePipe();
@@ -30,6 +34,41 @@ PollLoop::~PollLoop() {
    closeWakePipe();
}

void PollLoop::threadDestructor(void *st) {
    PollLoop* const self = static_cast<PollLoop*>(st);
    if (self != NULL) {
        self->decStrong((void*)threadDestructor);
    }
}

void PollLoop::setForThread(const sp<PollLoop>& pollLoop) {
    sp<PollLoop> old = getForThread();
    
    if (pollLoop != NULL) {
        pollLoop->incStrong((void*)threadDestructor);
    }
    
    pthread_setspecific(gTLS, pollLoop.get());
    
    if (old != NULL) {
        old->decStrong((void*)threadDestructor);
    }
}
    
sp<PollLoop> PollLoop::getForThread() {
    if (!gHaveTLS) {
        pthread_mutex_lock(&gTLSMutex);
        if (pthread_key_create(&gTLS, threadDestructor) != 0) {
            pthread_mutex_unlock(&gTLSMutex);
            return NULL;
        }
        gHaveTLS = true;
        pthread_mutex_unlock(&gTLSMutex);
    }
    
    return (PollLoop*)pthread_getspecific(gTLS);
}

void PollLoop::openWakePipe() {
    int wakeFds[2];
    int result = pipe(wakeFds);
@@ -54,6 +93,7 @@ void PollLoop::openWakePipe() {

    RequestedCallback requestedCallback;
    requestedCallback.callback = NULL;
    requestedCallback.looperCallback = NULL;
    requestedCallback.data = NULL;
    mRequestedCallbacks.insertAt(requestedCallback, 0);
}
@@ -123,12 +163,14 @@ bool PollLoop::pollOnce(int timeoutMillis) {
        if (revents) {
            const RequestedCallback& requestedCallback = mRequestedCallbacks.itemAt(i);
            Callback callback = requestedCallback.callback;
            ALooper_callbackFunc* looperCallback = requestedCallback.looperCallback;

            if (callback) {
            if (callback || looperCallback) {
                PendingCallback pendingCallback;
                pendingCallback.fd = requestedFd.fd;
                pendingCallback.events = requestedFd.revents;
                pendingCallback.callback = callback;
                pendingCallback.looperCallback = looperCallback;
                pendingCallback.data = requestedCallback.data;
                mPendingCallbacks.push(pendingCallback);
            } else {
@@ -172,8 +214,14 @@ Done:
            LOGD("%p ~ pollOnce - invoking callback for fd %d", this, pendingCallback.fd);
#endif

            bool keep = pendingCallback.callback(pendingCallback.fd, pendingCallback.events,
            bool keep = true;
            if (pendingCallback.callback != NULL) {
                keep = pendingCallback.callback(pendingCallback.fd, pendingCallback.events,
                        pendingCallback.data);
            } else {
                keep = pendingCallback.looperCallback(pendingCallback.fd, pendingCallback.events,
                        pendingCallback.data) != 0;
            }
            if (! keep) {
                removeCallback(pendingCallback.fd);
            }
@@ -200,11 +248,22 @@ void PollLoop::wake() {
}

void PollLoop::setCallback(int fd, int events, Callback callback, void* data) {
    setCallbackCommon(fd, events, callback, NULL, data);
}

void PollLoop::setLooperCallback(int fd, int events, ALooper_callbackFunc* callback,
        void* data) {
    setCallbackCommon(fd, events, NULL, callback, data);
}

void PollLoop::setCallbackCommon(int fd, int events, Callback callback,
        ALooper_callbackFunc* looperCallback, void* data) {

#if DEBUG_CALLBACKS
    LOGD("%p ~ setCallback - fd=%d, events=%d", this, fd, events);
#endif

    if (! events || ! callback) {
    if (! events || (! callback && ! looperCallback)) {
        LOGE("Invalid attempt to set a callback with no selected poll events or no callback.");
        removeCallback(fd);
        return;
@@ -218,6 +277,7 @@ void PollLoop::setCallback(int fd, int events, Callback callback, void* data) {

    RequestedCallback requestedCallback;
    requestedCallback.callback = callback;
    requestedCallback.looperCallback = looperCallback;
    requestedCallback.data = data;

    ssize_t index = getRequestIndexLocked(fd);