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:
parent
80d9c1cfb0
commit
9efaaa4359
|
@ -114,8 +114,10 @@ private:
|
|||
};
|
||||
|
||||
Mutex mLock;
|
||||
Condition mAwake;
|
||||
bool mPolling;
|
||||
uint32_t mWaiters;
|
||||
Condition mAwake;
|
||||
Condition mResume;
|
||||
|
||||
int mWakeReadPipeFd;
|
||||
int mWakeWritePipeFd;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue