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

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

am 74bf59b4: Merge "Add new glue code for writing native apps." into gingerbread

Merge commit '74bf59b450daf9e7e6bf234f01db164099edbfd5' into gingerbread-plus-aosp

* commit '74bf59b450daf9e7e6bf234f01db164099edbfd5':
  Add new glue code for writing native apps.
parents ceef3d19 5234c75f
Loading
Loading
Loading
Loading
+34 −8
Original line number Original line Diff line number Diff line
@@ -42,7 +42,7 @@ protected:
    virtual ~PollLoop();
    virtual ~PollLoop();


public:
public:
    PollLoop();
    PollLoop(bool allowNonCallbacks);


    /**
    /**
     * A callback that it to be invoked when an event occurs on a file descriptor.
     * A callback that it to be invoked when an event occurs on a file descriptor.
@@ -54,6 +54,12 @@ public:
     */
     */
    typedef bool (*Callback)(int fd, int events, void* data);
    typedef bool (*Callback)(int fd, int events, void* data);


    enum {
        POLL_CALLBACK = ALOOPER_POLL_CALLBACK,
        POLL_TIMEOUT = ALOOPER_POLL_TIMEOUT,
        POLL_ERROR = ALOOPER_POLL_ERROR,
    };
    
    /**
    /**
     * Performs a single call to poll() with optional timeout in milliseconds.
     * Performs a single call to poll() with optional timeout in milliseconds.
     * Invokes callbacks for all file descriptors on which an event occurred.
     * Invokes callbacks for all file descriptors on which an event occurred.
@@ -61,16 +67,25 @@ public:
     * If the timeout is zero, returns immediately without blocking.
     * If the timeout is zero, returns immediately without blocking.
     * If the timeout is negative, waits indefinitely until awoken.
     * If the timeout is negative, waits indefinitely until awoken.
     *
     *
     * Returns true if a callback was invoked or if the loop was awoken by wake().
     * Returns ALOOPER_POLL_CALLBACK if a callback was invoked.
     * Returns false if a timeout or error occurred.
     *
     * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given
     * timeout expired.
     *
     * Returns ALOPER_POLL_ERROR if an error occurred.
     *
     * Returns a value >= 0 containing a file descriptor if it has data
     * and it has no callback function (requiring the caller here to handle it).
     * In this (and only this) case outEvents and outData will contain the poll
     * events and data associated with the fd.
     *
     *
     * This method must only be called on the main thread.
     * This method must only be called on the thread owning the PollLoop.
     * This method blocks until either a file descriptor is signalled, a timeout occurs,
     * This method blocks until either a file descriptor is signalled, a timeout occurs,
     * or wake() is called.
     * or wake() is called.
     * This method does not return until it has finished invoking the appropriate callbacks
     * This method does not return until it has finished invoking the appropriate callbacks
     * for all file descriptors that were signalled.
     * for all file descriptors that were signalled.
     */
     */
    bool pollOnce(int timeoutMillis);
    int32_t pollOnce(int timeoutMillis, int* outEvents = NULL, void** outData = NULL);


    /**
    /**
     * Wakes the loop asynchronously.
     * Wakes the loop asynchronously.
@@ -80,6 +95,12 @@ public:
     */
     */
    void wake();
    void wake();


    /**
     * Control whether this PollLoop instance allows using IDs instead
     * of callbacks.
     */
    bool getAllowNonCallbacks() const;
    
    /**
    /**
     * Sets the callback for a file descriptor, replacing the existing one, if any.
     * Sets the callback for a file descriptor, replacing the existing one, if any.
     * It is an error to call this method with events == 0 or callback == NULL.
     * It is an error to call this method with events == 0 or callback == NULL.
@@ -95,7 +116,8 @@ public:
    /**
    /**
     * Like setCallback(), but for the NDK callback function.
     * Like setCallback(), but for the NDK callback function.
     */
     */
    void setLooperCallback(int fd, int events, ALooper_callbackFunc* callback, void* data);
    void setLooperCallback(int fd, int events, ALooper_callbackFunc* callback,
            void* data);
    
    
    /**
    /**
     * Removes the callback for a file descriptor, if one exists.
     * Removes the callback for a file descriptor, if one exists.
@@ -142,6 +164,8 @@ private:
        void* data;
        void* data;
    };
    };
    
    
    const bool mAllowNonCallbacks;
    
    Mutex mLock;
    Mutex mLock;
    bool mPolling;
    bool mPolling;
    uint32_t mWaiters;
    uint32_t mWaiters;
@@ -155,6 +179,8 @@ private:
    Vector<RequestedCallback> mRequestedCallbacks;
    Vector<RequestedCallback> mRequestedCallbacks;


    Vector<PendingCallback> mPendingCallbacks; // used privately by pollOnce
    Vector<PendingCallback> mPendingCallbacks; // used privately by pollOnce
    Vector<PendingCallback> mPendingFds;       // used privately by pollOnce
    size_t mPendingFdsPos;
    
    
    void openWakePipe();
    void openWakePipe();
    void closeWakePipe();
    void closeWakePipe();
+1 −1
Original line number Original line Diff line number Diff line
@@ -54,7 +54,7 @@ static inline nsecs_t now() {


InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
    mPolicy(policy) {
    mPolicy(policy) {
    mPollLoop = new PollLoop();
    mPollLoop = new PollLoop(false);


    mInboundQueue.head.refCount = -1;
    mInboundQueue.head.refCount = -1;
    mInboundQueue.head.type = EventEntry::TYPE_SENTINEL;
    mInboundQueue.head.type = EventEntry::TYPE_SENTINEL;
+60 −33
Original line number Original line Diff line number Diff line
@@ -25,8 +25,9 @@ static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
static bool gHaveTLS = false;
static bool gHaveTLS = false;
static pthread_key_t gTLS = 0;
static pthread_key_t gTLS = 0;


PollLoop::PollLoop() :
PollLoop::PollLoop(bool allowNonCallbacks) :
        mPolling(false), mWaiters(0) {
        mAllowNonCallbacks(allowNonCallbacks), mPolling(false),
        mWaiters(0), mPendingFdsPos(0) {
    openWakePipe();
    openWakePipe();
}
}


@@ -106,7 +107,18 @@ void PollLoop::closeWakePipe() {
    //       method is currently only called by the destructor.
    //       method is currently only called by the destructor.
}
}


bool PollLoop::pollOnce(int timeoutMillis) {
int32_t PollLoop::pollOnce(int timeoutMillis, int* outEvents, void** outData) {
    // If there are still pending fds from the last call, dispatch those
    // first, to avoid an earlier fd from starving later ones.
    const size_t pendingFdsCount = mPendingFds.size();
    if (mPendingFdsPos < pendingFdsCount) {
        const PendingCallback& pending = mPendingFds.itemAt(mPendingFdsPos);
        mPendingFdsPos++;
        if (outEvents != NULL) *outEvents = pending.events;
        if (outData != NULL) *outData = pending.data;
        return pending.fd;
    }
    
    mLock.lock();
    mLock.lock();
    while (mWaiters != 0) {
    while (mWaiters != 0) {
        mResume.wait(mLock);
        mResume.wait(mLock);
@@ -114,7 +126,7 @@ bool PollLoop::pollOnce(int timeoutMillis) {
    mPolling = true;
    mPolling = true;
    mLock.unlock();
    mLock.unlock();


    bool result;
    int32_t result;
    size_t requestedCount = mRequestedFds.size();
    size_t requestedCount = mRequestedFds.size();


#if DEBUG_POLL_AND_WAKE
#if DEBUG_POLL_AND_WAKE
@@ -131,7 +143,7 @@ bool PollLoop::pollOnce(int timeoutMillis) {
#if DEBUG_POLL_AND_WAKE
#if DEBUG_POLL_AND_WAKE
        LOGD("%p ~ pollOnce - timeout", this);
        LOGD("%p ~ pollOnce - timeout", this);
#endif
#endif
        result = false;
        result = POLL_TIMEOUT;
        goto Done;
        goto Done;
    }
    }


@@ -143,7 +155,7 @@ bool PollLoop::pollOnce(int timeoutMillis) {
        if (errno != EINTR) {
        if (errno != EINTR) {
            LOGW("Poll failed with an unexpected error, errno=%d", errno);
            LOGW("Poll failed with an unexpected error, errno=%d", errno);
        }
        }
        result = false;
        result = POLL_ERROR;
        goto Done;
        goto Done;
    }
    }


@@ -156,25 +168,36 @@ bool PollLoop::pollOnce(int timeoutMillis) {
#endif
#endif


    mPendingCallbacks.clear();
    mPendingCallbacks.clear();
    mPendingFds.clear();
    mPendingFdsPos = 0;
    if (outEvents != NULL) *outEvents = 0;
    if (outData != NULL) *outData = NULL;
    
    result = POLL_CALLBACK;
    for (size_t i = 0; i < requestedCount; i++) {
    for (size_t i = 0; i < requestedCount; i++) {
        const struct pollfd& requestedFd = mRequestedFds.itemAt(i);
        const struct pollfd& requestedFd = mRequestedFds.itemAt(i);


        short revents = requestedFd.revents;
        short revents = requestedFd.revents;
        if (revents) {
        if (revents) {
            const RequestedCallback& requestedCallback = mRequestedCallbacks.itemAt(i);
            const RequestedCallback& requestedCallback = mRequestedCallbacks.itemAt(i);
            Callback callback = requestedCallback.callback;
            PendingCallback pending;
            ALooper_callbackFunc* looperCallback = requestedCallback.looperCallback;
            pending.fd = requestedFd.fd;

            pending.events = revents;
            if (callback || looperCallback) {
            pending.callback = requestedCallback.callback;
                PendingCallback pendingCallback;
            pending.looperCallback = requestedCallback.looperCallback;
                pendingCallback.fd = requestedFd.fd;
            pending.data = requestedCallback.data;
                pendingCallback.events = requestedFd.revents;

                pendingCallback.callback = callback;
            if (pending.callback || pending.looperCallback) {
                pendingCallback.looperCallback = looperCallback;
                mPendingCallbacks.push(pending);
                pendingCallback.data = requestedCallback.data;
            } else if (pending.fd != mWakeReadPipeFd) {
                mPendingCallbacks.push(pendingCallback);
                if (result == POLL_CALLBACK) {
                    result = pending.fd;
                    if (outEvents != NULL) *outEvents = pending.events;
                    if (outData != NULL) *outData = pending.data;
                } else {
                    mPendingFds.push(pending);
                }
            } else {
            } else {
                if (requestedFd.fd == mWakeReadPipeFd) {
#if DEBUG_POLL_AND_WAKE
#if DEBUG_POLL_AND_WAKE
                LOGD("%p ~ pollOnce - awoken", this);
                LOGD("%p ~ pollOnce - awoken", this);
#endif
#endif
@@ -183,11 +206,6 @@ bool PollLoop::pollOnce(int timeoutMillis) {
                do {
                do {
                    nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
                    nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
                } while (nRead == sizeof(buffer));
                } while (nRead == sizeof(buffer));
                } else {
#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
                    LOGD("%p ~ pollOnce - fd %d has no callback!", this, requestedFd.fd);
#endif
                }
            }
            }


            respondedCount -= 1;
            respondedCount -= 1;
@@ -196,7 +214,6 @@ bool PollLoop::pollOnce(int timeoutMillis) {
            }
            }
        }
        }
    }
    }
    result = true;


Done:
Done:
    mLock.lock();
    mLock.lock();
@@ -206,7 +223,7 @@ Done:
    }
    }
    mLock.unlock();
    mLock.unlock();


    if (result) {
    if (result == POLL_CALLBACK || result >= 0) {
        size_t pendingCount = mPendingCallbacks.size();
        size_t pendingCount = mPendingCallbacks.size();
        for (size_t i = 0; i < pendingCount; i++) {
        for (size_t i = 0; i < pendingCount; i++) {
            const PendingCallback& pendingCallback = mPendingCallbacks.itemAt(i);
            const PendingCallback& pendingCallback = mPendingCallbacks.itemAt(i);
@@ -247,6 +264,10 @@ void PollLoop::wake() {
    }
    }
}
}


bool PollLoop::getAllowNonCallbacks() const {
    return mAllowNonCallbacks;
}

void PollLoop::setCallback(int fd, int events, Callback callback, void* data) {
void PollLoop::setCallback(int fd, int events, Callback callback, void* data) {
    setCallbackCommon(fd, events, callback, NULL, data);
    setCallbackCommon(fd, events, callback, NULL, data);
}
}
@@ -263,8 +284,14 @@ void PollLoop::setCallbackCommon(int fd, int events, Callback callback,
    LOGD("%p ~ setCallback - fd=%d, events=%d", this, fd, events);
    LOGD("%p ~ setCallback - fd=%d, events=%d", this, fd, events);
#endif
#endif


    if (! events || (! callback && ! looperCallback)) {
    if (! events) {
        LOGE("Invalid attempt to set a callback with no selected poll events or no callback.");
        LOGE("Invalid attempt to set a callback with no selected poll events.");
        removeCallback(fd);
        return;
    }

    if (! callback && ! looperCallback && ! mAllowNonCallbacks) {
        LOGE("Invalid attempt to set NULL callback but not allowed.");
        removeCallback(fd);
        removeCallback(fd);
        return;
        return;
    }
    }
+39 −39
Original line number Original line Diff line number Diff line
@@ -87,7 +87,7 @@ protected:
    sp<PollLoop> mPollLoop;
    sp<PollLoop> mPollLoop;


    virtual void SetUp() {
    virtual void SetUp() {
        mPollLoop = new PollLoop();
        mPollLoop = new PollLoop(false);
    }
    }


    virtual void TearDown() {
    virtual void TearDown() {
@@ -98,26 +98,26 @@ protected:


TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndNotAwoken_WaitsForTimeoutAndReturnsFalse) {
TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndNotAwoken_WaitsForTimeoutAndReturnsFalse) {
    StopWatch stopWatch("pollOnce");
    StopWatch stopWatch("pollOnce");
    bool result = mPollLoop->pollOnce(100);
    int32_t result = mPollLoop->pollOnce(100);
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());


    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
            << "elapsed time should approx. equal timeout";
            << "elapsed time should approx. equal timeout";
    EXPECT_FALSE(result)
    EXPECT_EQ(result, PollLoop::POLL_TIMEOUT)
            << "pollOnce result should be false because timeout occurred";
            << "pollOnce result should be POLL_TIMEOUT";
}
}


TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndAwokenBeforeWaiting_ImmediatelyReturnsTrue) {
TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndAwokenBeforeWaiting_ImmediatelyReturnsTrue) {
    mPollLoop->wake();
    mPollLoop->wake();


    StopWatch stopWatch("pollOnce");
    StopWatch stopWatch("pollOnce");
    bool result = mPollLoop->pollOnce(1000);
    int32_t result = mPollLoop->pollOnce(1000);
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());


    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
            << "elapsed time should approx. zero because wake() was called before waiting";
            << "elapsed time should approx. zero because wake() was called before waiting";
    EXPECT_TRUE(result)
    EXPECT_EQ(result, PollLoop::POLL_CALLBACK)
            << "pollOnce result should be true because loop was awoken";
            << "pollOnce result should be POLL_CALLBACK because loop was awoken";
}
}


TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndAwokenWhileWaiting_PromptlyReturnsTrue) {
TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndAwokenWhileWaiting_PromptlyReturnsTrue) {
@@ -125,24 +125,24 @@ TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndAwokenWhileWaiting_PromptlyRe
    delayedWake->run();
    delayedWake->run();


    StopWatch stopWatch("pollOnce");
    StopWatch stopWatch("pollOnce");
    bool result = mPollLoop->pollOnce(1000);
    int32_t result = mPollLoop->pollOnce(1000);
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());


    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
            << "elapsed time should approx. equal wake delay";
            << "elapsed time should approx. equal wake delay";
    EXPECT_TRUE(result)
    EXPECT_EQ(result, PollLoop::POLL_CALLBACK)
            << "pollOnce result should be true because loop was awoken";
            << "pollOnce result should be POLL_CALLBACK because loop was awoken";
}
}


TEST_F(PollLoopTest, PollOnce_WhenZeroTimeoutAndNoRegisteredFDs_ImmediatelyReturnsFalse) {
TEST_F(PollLoopTest, PollOnce_WhenZeroTimeoutAndNoRegisteredFDs_ImmediatelyReturnsFalse) {
    StopWatch stopWatch("pollOnce");
    StopWatch stopWatch("pollOnce");
    bool result = mPollLoop->pollOnce(0);
    int32_t result = mPollLoop->pollOnce(0);
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());


    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
            << "elapsed time should be approx. zero";
            << "elapsed time should be approx. zero";
    EXPECT_FALSE(result)
    EXPECT_EQ(result, PollLoop::POLL_TIMEOUT)
            << "pollOnce result should be false because timeout occurred";
            << "pollOnce result should be POLL_TIMEOUT";
}
}


TEST_F(PollLoopTest, PollOnce_WhenZeroTimeoutAndNoSignalledFDs_ImmediatelyReturnsFalse) {
TEST_F(PollLoopTest, PollOnce_WhenZeroTimeoutAndNoSignalledFDs_ImmediatelyReturnsFalse) {
@@ -152,13 +152,13 @@ TEST_F(PollLoopTest, PollOnce_WhenZeroTimeoutAndNoSignalledFDs_ImmediatelyReturn
    handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);
    handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);


    StopWatch stopWatch("pollOnce");
    StopWatch stopWatch("pollOnce");
    bool result = mPollLoop->pollOnce(0);
    int32_t result = mPollLoop->pollOnce(0);
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());


    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
            << "elapsed time should be approx. zero";
            << "elapsed time should be approx. zero";
    EXPECT_FALSE(result)
    EXPECT_EQ(result, PollLoop::POLL_TIMEOUT)
            << "pollOnce result should be false because timeout occurred";
            << "pollOnce result should be POLL_TIMEOUT";
    EXPECT_EQ(0, handler.callbackCount)
    EXPECT_EQ(0, handler.callbackCount)
            << "callback should not have been invoked because FD was not signalled";
            << "callback should not have been invoked because FD was not signalled";
}
}
@@ -171,13 +171,13 @@ TEST_F(PollLoopTest, PollOnce_WhenZeroTimeoutAndSignalledFD_ImmediatelyInvokesCa
    handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);
    handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);


    StopWatch stopWatch("pollOnce");
    StopWatch stopWatch("pollOnce");
    bool result = mPollLoop->pollOnce(0);
    int32_t result = mPollLoop->pollOnce(0);
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());


    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
            << "elapsed time should be approx. zero";
            << "elapsed time should be approx. zero";
    EXPECT_TRUE(result)
    EXPECT_EQ(result, PollLoop::POLL_CALLBACK)
            << "pollOnce result should be true because FD was signalled";
            << "pollOnce result should be POLL_CALLBACK because FD was signalled";
    EXPECT_EQ(1, handler.callbackCount)
    EXPECT_EQ(1, handler.callbackCount)
            << "callback should be invoked exactly once";
            << "callback should be invoked exactly once";
    EXPECT_EQ(pipe.receiveFd, handler.fd)
    EXPECT_EQ(pipe.receiveFd, handler.fd)
@@ -193,13 +193,13 @@ TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndNoSignalledFDs_WaitsForTimeou
    handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);
    handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);


    StopWatch stopWatch("pollOnce");
    StopWatch stopWatch("pollOnce");
    bool result = mPollLoop->pollOnce(100);
    int32_t result = mPollLoop->pollOnce(100);
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());


    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
            << "elapsed time should approx. equal timeout";
            << "elapsed time should approx. equal timeout";
    EXPECT_FALSE(result)
    EXPECT_EQ(result, PollLoop::POLL_TIMEOUT)
            << "pollOnce result should be false because timeout occurred";
            << "pollOnce result should be POLL_TIMEOUT";
    EXPECT_EQ(0, handler.callbackCount)
    EXPECT_EQ(0, handler.callbackCount)
            << "callback should not have been invoked because FD was not signalled";
            << "callback should not have been invoked because FD was not signalled";
}
}
@@ -212,15 +212,15 @@ TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndSignalledFDBeforeWaiting_Imme
    handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);
    handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);


    StopWatch stopWatch("pollOnce");
    StopWatch stopWatch("pollOnce");
    bool result = mPollLoop->pollOnce(100);
    int32_t result = mPollLoop->pollOnce(100);
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());


    ASSERT_EQ(OK, pipe.readSignal())
    ASSERT_EQ(OK, pipe.readSignal())
            << "signal should actually have been written";
            << "signal should actually have been written";
    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
            << "elapsed time should be approx. zero";
            << "elapsed time should be approx. zero";
    EXPECT_TRUE(result)
    EXPECT_EQ(result, PollLoop::POLL_CALLBACK)
            << "pollOnce result should be true because FD was signalled";
            << "pollOnce result should be POLL_CALLBACK because FD was signalled";
    EXPECT_EQ(1, handler.callbackCount)
    EXPECT_EQ(1, handler.callbackCount)
            << "callback should be invoked exactly once";
            << "callback should be invoked exactly once";
    EXPECT_EQ(pipe.receiveFd, handler.fd)
    EXPECT_EQ(pipe.receiveFd, handler.fd)
@@ -238,15 +238,15 @@ TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndSignalledFDWhileWaiting_Promp
    delayedWriteSignal->run();
    delayedWriteSignal->run();


    StopWatch stopWatch("pollOnce");
    StopWatch stopWatch("pollOnce");
    bool result = mPollLoop->pollOnce(1000);
    int32_t result = mPollLoop->pollOnce(1000);
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());


    ASSERT_EQ(OK, pipe.readSignal())
    ASSERT_EQ(OK, pipe.readSignal())
            << "signal should actually have been written";
            << "signal should actually have been written";
    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
            << "elapsed time should approx. equal signal delay";
            << "elapsed time should approx. equal signal delay";
    EXPECT_TRUE(result)
    EXPECT_EQ(result, PollLoop::POLL_CALLBACK)
            << "pollOnce result should be true because FD was signalled";
            << "pollOnce result should be POLL_CALLBACK because FD was signalled";
    EXPECT_EQ(1, handler.callbackCount)
    EXPECT_EQ(1, handler.callbackCount)
            << "callback should be invoked exactly once";
            << "callback should be invoked exactly once";
    EXPECT_EQ(pipe.receiveFd, handler.fd)
    EXPECT_EQ(pipe.receiveFd, handler.fd)
@@ -264,15 +264,15 @@ TEST_F(PollLoopTest, PollOnce_WhenCallbackAddedThenRemoved_CallbackShouldNotBeIn
    mPollLoop->removeCallback(pipe.receiveFd);
    mPollLoop->removeCallback(pipe.receiveFd);


    StopWatch stopWatch("pollOnce");
    StopWatch stopWatch("pollOnce");
    bool result = mPollLoop->pollOnce(100);
    int32_t result = mPollLoop->pollOnce(100);
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());


    ASSERT_EQ(OK, pipe.readSignal())
    ASSERT_EQ(OK, pipe.readSignal())
            << "signal should actually have been written";
            << "signal should actually have been written";
    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
    EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
            << "elapsed time should approx. equal timeout because FD was no longer registered";
            << "elapsed time should approx. equal timeout because FD was no longer registered";
    EXPECT_FALSE(result)
    EXPECT_EQ(result, PollLoop::POLL_TIMEOUT)
            << "pollOnce result should be false because timeout occurred";
            << "pollOnce result should be POLL_TIMEOUT";
    EXPECT_EQ(0, handler.callbackCount)
    EXPECT_EQ(0, handler.callbackCount)
            << "callback should not be invoked";
            << "callback should not be invoked";
}
}
@@ -287,15 +287,15 @@ TEST_F(PollLoopTest, PollOnce_WhenCallbackReturnsFalse_CallbackShouldNotBeInvoke
    pipe.writeSignal();
    pipe.writeSignal();


    StopWatch stopWatch("pollOnce");
    StopWatch stopWatch("pollOnce");
    bool result = mPollLoop->pollOnce(0);
    int32_t result = mPollLoop->pollOnce(0);
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());


    ASSERT_EQ(OK, pipe.readSignal())
    ASSERT_EQ(OK, pipe.readSignal())
            << "signal should actually have been written";
            << "signal should actually have been written";
    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
            << "elapsed time should approx. equal zero because FD was already signalled";
            << "elapsed time should approx. equal zero because FD was already signalled";
    EXPECT_TRUE(result)
    EXPECT_EQ(result, PollLoop::POLL_CALLBACK)
            << "pollOnce result should be true because FD was signalled";
            << "pollOnce result should be POLL_CALLBACK because FD was signalled";
    EXPECT_EQ(1, handler.callbackCount)
    EXPECT_EQ(1, handler.callbackCount)
            << "callback should be invoked";
            << "callback should be invoked";


@@ -310,8 +310,8 @@ TEST_F(PollLoopTest, PollOnce_WhenCallbackReturnsFalse_CallbackShouldNotBeInvoke
            << "signal should actually have been written";
            << "signal should actually have been written";
    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
            << "elapsed time should approx. equal zero because timeout was zero";
            << "elapsed time should approx. equal zero because timeout was zero";
    EXPECT_FALSE(result)
    EXPECT_EQ(result, PollLoop::POLL_TIMEOUT)
            << "pollOnce result should be false because timeout occurred";
            << "pollOnce result should be POLL_TIMEOUT";
    EXPECT_EQ(1, handler.callbackCount)
    EXPECT_EQ(1, handler.callbackCount)
            << "callback should not be invoked this time";
            << "callback should not be invoked this time";
}
}
@@ -351,15 +351,15 @@ TEST_F(PollLoopTest, PollOnce_WhenCallbackAddedTwice_OnlySecondCallbackShouldBeI
    pipe.writeSignal(); // would cause FD to be considered signalled
    pipe.writeSignal(); // would cause FD to be considered signalled


    StopWatch stopWatch("pollOnce");
    StopWatch stopWatch("pollOnce");
    bool result = mPollLoop->pollOnce(100);
    int32_t result = mPollLoop->pollOnce(100);
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
    int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());


    ASSERT_EQ(OK, pipe.readSignal())
    ASSERT_EQ(OK, pipe.readSignal())
            << "signal should actually have been written";
            << "signal should actually have been written";
    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
    EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
            << "elapsed time should approx. zero because FD was already signalled";
            << "elapsed time should approx. zero because FD was already signalled";
    EXPECT_TRUE(result)
    EXPECT_EQ(result, PollLoop::POLL_CALLBACK)
            << "pollOnce result should be true because FD was signalled";
            << "pollOnce result should be POLL_CALLBACK because FD was signalled";
    EXPECT_EQ(0, handler1.callbackCount)
    EXPECT_EQ(0, handler1.callbackCount)
            << "original handler callback should not be invoked because it was replaced";
            << "original handler callback should not be invoked because it was replaced";
    EXPECT_EQ(1, handler2.callbackCount)
    EXPECT_EQ(1, handler2.callbackCount)