Even more native input dispatch work in progress.

Added more tests.
Fixed a regression in Vector.
Fixed bugs in pointer tracking.
Fixed a starvation issue in PollLoop when setting or removing callbacks.
Fixed a couple of policy nits.

Modified the internal representation of MotionEvent to be more
efficient and more consistent.

Added code to skip/cancel virtual key processing when there are multiple
pointers down.  This helps to better disambiguate virtual key presses
from stray touches (such as cheek presses).

Change-Id: I2a7d2cce0195afb9125b23378baa94fd2fc6671c
This commit is contained in:
Jeff Brown 2010-06-16 01:53:36 -07:00 committed by Alex Ray
parent 80d9c1cfb0
commit 9efaaa4359
7 changed files with 90 additions and 53 deletions

View File

@ -114,8 +114,10 @@ private:
};
Mutex mLock;
Condition mAwake;
bool mPolling;
uint32_t mWaiters;
Condition mAwake;
Condition mResume;
int mWakeReadPipeFd;
int mWakeWritePipeFd;

View File

@ -115,10 +115,10 @@ public:
//! insert an array at a given index
ssize_t insertArrayAt(const TYPE* array, size_t index, size_t numItems);
ssize_t insertArrayAt(const TYPE* array, size_t index, size_t length);
//! append an array at the end of this vector
ssize_t appendArray(const TYPE* array, size_t numItems);
ssize_t appendArray(const TYPE* array, size_t length);
/*!
* add/insert/replace items
@ -126,7 +126,7 @@ public:
//! insert one or several items initialized with their default constructor
inline ssize_t insertAt(size_t index, size_t numItems = 1);
//! insert on onr several items initialized from a prototype item
//! insert one or several items initialized from a prototype item
ssize_t insertAt(const TYPE& prototype_item, size_t index, size_t numItems = 1);
//! pop the top of the stack (removes the last element). No-op if the stack's empty
inline void pop();
@ -265,13 +265,13 @@ ssize_t Vector<TYPE>::appendVector(const Vector<TYPE>& vector) {
}
template<class TYPE> inline
ssize_t Vector<TYPE>::insertArrayAt(const TYPE* array, size_t index, size_t numItems) {
return VectorImpl::insertAt(array, index, numItems);
ssize_t Vector<TYPE>::insertArrayAt(const TYPE* array, size_t index, size_t length) {
return VectorImpl::insertArrayAt(array, index, length);
}
template<class TYPE> inline
ssize_t Vector<TYPE>::appendArray(const TYPE* array, size_t numItems) {
return VectorImpl::add(array, numItems);
ssize_t Vector<TYPE>::appendArray(const TYPE* array, size_t length) {
return VectorImpl::appendArray(array, length);
}
template<class TYPE> inline

View File

@ -65,9 +65,11 @@ public:
size_t capacity() const;
ssize_t setCapacity(size_t size);
/*! append/insert another vector */
/*! append/insert another vector or array */
ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
ssize_t appendVector(const VectorImpl& vector);
ssize_t insertArrayAt(const void* array, size_t index, size_t length);
ssize_t appendArray(const void* array, size_t length);
/*! add/insert/replace items */
ssize_t insertAt(size_t where, size_t numItems = 1);
@ -76,7 +78,7 @@ public:
void push();
void push(const void* item);
ssize_t add();
ssize_t add(const void* item, size_t numItems = 1);
ssize_t add(const void* item);
ssize_t replaceAt(size_t index);
ssize_t replaceAt(const void* item, size_t index);
@ -184,8 +186,8 @@ private:
void push(const void* item);
ssize_t insertVectorAt(const VectorImpl& vector, size_t index);
ssize_t appendVector(const VectorImpl& vector);
ssize_t insertArrayAt(const void* array, size_t index, size_t numItems);
ssize_t appendArray(const void* array, size_t numItems);
ssize_t insertArrayAt(const void* array, size_t index, size_t length);
ssize_t appendArray(const void* array, size_t length);
ssize_t insertAt(size_t where, size_t numItems = 1);
ssize_t insertAt(const void* item, size_t where, size_t numItems = 1);
ssize_t replaceAt(size_t index);

View File

@ -11,7 +11,7 @@
#define DEBUG_POLL_AND_WAKE 0
// Debugs callback registration and invocation.
#define DEBUG_CALLBACKS 1
#define DEBUG_CALLBACKS 0
#include <cutils/log.h>
#include <utils/PollLoop.h>
@ -22,7 +22,7 @@
namespace android {
PollLoop::PollLoop() :
mPolling(false) {
mPolling(false), mWaiters(0) {
openWakePipe();
}
@ -68,6 +68,9 @@ void PollLoop::closeWakePipe() {
bool PollLoop::pollOnce(int timeoutMillis) {
mLock.lock();
while (mWaiters != 0) {
mResume.wait(mLock);
}
mPolling = true;
mLock.unlock();
@ -156,7 +159,9 @@ bool PollLoop::pollOnce(int timeoutMillis) {
Done:
mLock.lock();
mPolling = false;
mAwake.broadcast();
if (mWaiters != 0) {
mAwake.broadcast();
}
mLock.unlock();
if (result) {
@ -258,10 +263,15 @@ ssize_t PollLoop::getRequestIndexLocked(int fd) {
void PollLoop::wakeAndLock() {
mLock.lock();
mWaiters += 1;
while (mPolling) {
wake();
mAwake.wait(mLock);
}
mWaiters -= 1;
if (mWaiters == 0) {
mResume.signal();
}
}
} // namespace android

View File

@ -108,7 +108,7 @@ size_t VectorImpl::capacity() const
ssize_t VectorImpl::insertVectorAt(const VectorImpl& vector, size_t index)
{
return insertAt(vector.arrayImpl(), index, vector.size());
return insertArrayAt(vector.arrayImpl(), index, vector.size());
}
ssize_t VectorImpl::appendVector(const VectorImpl& vector)
@ -116,6 +116,22 @@ ssize_t VectorImpl::appendVector(const VectorImpl& vector)
return insertVectorAt(vector, size());
}
ssize_t VectorImpl::insertArrayAt(const void* array, size_t index, size_t length)
{
if (index > size())
return BAD_INDEX;
void* where = _grow(index, length);
if (where) {
_do_copy(where, array, length);
}
return where ? index : (ssize_t)NO_MEMORY;
}
ssize_t VectorImpl::appendArray(const void* array, size_t length)
{
return insertArrayAt(array, size(), length);
}
ssize_t VectorImpl::insertAt(size_t index, size_t numItems)
{
return insertAt(0, index, numItems);
@ -220,9 +236,9 @@ ssize_t VectorImpl::add()
return add(0);
}
ssize_t VectorImpl::add(const void* item, size_t numItems)
ssize_t VectorImpl::add(const void* item)
{
return insertAt(item, size(), numItems);
return insertAt(item, size());
}
ssize_t VectorImpl::replaceAt(size_t index)

View File

@ -16,34 +16,6 @@
namespace android {
class Pipe {
public:
int sendFd;
int receiveFd;
Pipe() {
int fds[2];
::pipe(fds);
receiveFd = fds[0];
sendFd = fds[1];
}
~Pipe() {
::close(sendFd);
::close(receiveFd);
}
bool writeSignal() {
return ::write(sendFd, "*", 1) == 1;
}
bool readSignal() {
char buf[1];
return ::read(receiveFd, buf, 1) == 1;
}
};
class DelayedWake : public DelayedTask {
sp<PollLoop> mPollLoop;
@ -195,7 +167,7 @@ TEST_F(PollLoopTest, PollOnce_WhenZeroTimeoutAndSignalledFD_ImmediatelyInvokesCa
Pipe pipe;
StubCallbackHandler handler(true);
ASSERT_TRUE(pipe.writeSignal());
ASSERT_EQ(OK, pipe.writeSignal());
handler.setCallback(mPollLoop, pipe.receiveFd, POLL_IN);
StopWatch stopWatch("pollOnce");
@ -243,7 +215,7 @@ TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndSignalledFDBeforeWaiting_Imme
bool result = mPollLoop->pollOnce(100);
int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
ASSERT_TRUE(pipe.readSignal())
ASSERT_EQ(OK, pipe.readSignal())
<< "signal should actually have been written";
EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
<< "elapsed time should be approx. zero";
@ -269,7 +241,7 @@ TEST_F(PollLoopTest, PollOnce_WhenNonZeroTimeoutAndSignalledFDWhileWaiting_Promp
bool result = mPollLoop->pollOnce(1000);
int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
ASSERT_TRUE(pipe.readSignal())
ASSERT_EQ(OK, pipe.readSignal())
<< "signal should actually have been written";
EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
<< "elapsed time should approx. equal signal delay";
@ -295,7 +267,7 @@ TEST_F(PollLoopTest, PollOnce_WhenCallbackAddedThenRemoved_CallbackShouldNotBeIn
bool result = mPollLoop->pollOnce(100);
int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
ASSERT_TRUE(pipe.readSignal())
ASSERT_EQ(OK, pipe.readSignal())
<< "signal should actually have been written";
EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS)
<< "elapsed time should approx. equal timeout because FD was no longer registered";
@ -318,7 +290,7 @@ TEST_F(PollLoopTest, PollOnce_WhenCallbackReturnsFalse_CallbackShouldNotBeInvoke
bool result = mPollLoop->pollOnce(0);
int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
ASSERT_TRUE(pipe.readSignal())
ASSERT_EQ(OK, pipe.readSignal())
<< "signal should actually have been written";
EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
<< "elapsed time should approx. equal zero because FD was already signalled";
@ -334,7 +306,7 @@ TEST_F(PollLoopTest, PollOnce_WhenCallbackReturnsFalse_CallbackShouldNotBeInvoke
result = mPollLoop->pollOnce(0);
elapsedMillis = ns2ms(stopWatch.elapsedTime());
ASSERT_TRUE(pipe.readSignal())
ASSERT_EQ(OK, pipe.readSignal())
<< "signal should actually have been written";
EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
<< "elapsed time should approx. equal zero because timeout was zero";
@ -382,7 +354,7 @@ TEST_F(PollLoopTest, PollOnce_WhenCallbackAddedTwice_OnlySecondCallbackShouldBeI
bool result = mPollLoop->pollOnce(100);
int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime());
ASSERT_TRUE(pipe.readSignal())
ASSERT_EQ(OK, pipe.readSignal())
<< "signal should actually have been written";
EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS)
<< "elapsed time should approx. zero because FD was already signalled";

View File

@ -21,6 +21,41 @@
namespace android {
class Pipe {
public:
int sendFd;
int receiveFd;
Pipe() {
int fds[2];
::pipe(fds);
receiveFd = fds[0];
sendFd = fds[1];
}
~Pipe() {
if (sendFd != -1) {
::close(sendFd);
}
if (receiveFd != -1) {
::close(receiveFd);
}
}
status_t writeSignal() {
ssize_t nWritten = ::write(sendFd, "*", 1);
return nWritten == 1 ? 0 : -errno;
}
status_t readSignal() {
char buf[1];
ssize_t nRead = ::read(receiveFd, buf, 1);
return nRead == 1 ? 0 : nRead == 0 ? -EPIPE : -errno;
}
};
class DelayedTask : public Thread {
int mDelayMillis;