summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2012-02-13 13:18:09 -0800
committerJeff Brown <jeffbrown@google.com>2012-02-13 13:59:32 -0800
commit2d34e0cfe7e2586b75a6f2c6646dd2e1e52c973f (patch)
treefbec10b21b79e9055f2deef4fbbb3ca4294c0334
parent90fde93c473aca5a33dc41c989bb2fdc5f2b1485 (diff)
downloadframeworks_base-2d34e0cfe7e2586b75a6f2c6646dd2e1e52c973f.zip
frameworks_base-2d34e0cfe7e2586b75a6f2c6646dd2e1e52c973f.tar.gz
frameworks_base-2d34e0cfe7e2586b75a6f2c6646dd2e1e52c973f.tar.bz2
Accurately track the sequence numbers of batched events.
Instead of sending finished signals immediately when appending to a batch, record the chain of sequence numbers that were part of the batch and then send finished signals all at once when done. This change helps the dispatcher keep track of the true state of the application and can improve ANR detection slightly. This is part of a series of changes to improve input system pipelining. Bug: 5963420 Change-Id: I463c2221e2aa8fdf1c3d670c18e39e59ab69b0db
-rw-r--r--include/ui/InputTransport.h13
-rw-r--r--libs/ui/InputTransport.cpp50
2 files changed, 54 insertions, 9 deletions
diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h
index 46b56ff..1f738cd 100644
--- a/include/ui/InputTransport.h
+++ b/include/ui/InputTransport.h
@@ -306,12 +306,23 @@ private:
// Batched motion events per device and source.
struct Batch {
- uint32_t seq;
+ uint32_t seq; // sequence number of last input message batched in the event
MotionEvent event;
};
Vector<Batch> mBatches;
+ // Chain of batched sequence numbers. When multiple input messages are combined into
+ // a batch, we append a record here that associates the last sequence number in the
+ // batch with the previous one. When the finished signal is sent, we traverse the
+ // chain to individually finish all input messages that were part of the batch.
+ struct SeqChain {
+ uint32_t seq; // sequence number of batched input message
+ uint32_t chain; // sequence number of previous batched input message
+ };
+ Vector<SeqChain> mSeqChains;
+
ssize_t findBatch(int32_t deviceId, int32_t source) const;
+ status_t sendUnchainedFinishedSignal(uint32_t seq, bool handled);
static void initializeKeyEvent(KeyEvent* event, const InputMessage* msg);
static void initializeMotionEvent(MotionEvent* event, const InputMessage* msg);
diff --git a/libs/ui/InputTransport.cpp b/libs/ui/InputTransport.cpp
index 44cb6db..ecb3fb5 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -401,17 +401,16 @@ status_t InputConsumer::consume(InputEventFactoryInterface* factory,
if (batchIndex >= 0) {
Batch& batch = mBatches.editItemAt(batchIndex);
if (canAppendSamples(&batch.event, &mMsg)) {
- // Send finished message for the earlier part of the batch.
- // Claim that we handled the event. (The dispatcher doesn't care either
- // way at the moment.)
- status_t status = sendFinishedSignal(batch.seq, true);
- if (status) {
- return status;
- }
-
// Append to the batch and save the new sequence number for the tail end.
+ uint32_t chain = batch.seq;
appendSamples(&batch.event, &mMsg);
batch.seq = mMsg.body.motion.seq;
+
+ // Update the sequence number chain.
+ SeqChain seqChain;
+ seqChain.seq = batch.seq;
+ seqChain.chain = chain;
+ mSeqChains.push(seqChain);
#if DEBUG_TRANSPORT_ACTIONS
ALOGD("channel '%s' consumer ~ appended to batch event",
mChannel->getName().string());
@@ -486,6 +485,41 @@ status_t InputConsumer::sendFinishedSignal(uint32_t seq, bool handled) {
return BAD_VALUE;
}
+ // Send finished signals for the batch sequence chain first.
+ size_t seqChainCount = mSeqChains.size();
+ if (seqChainCount) {
+ uint32_t currentSeq = seq;
+ uint32_t chainSeqs[seqChainCount];
+ size_t chainIndex = 0;
+ for (size_t i = seqChainCount; i-- > 0; ) {
+ const SeqChain& seqChain = mSeqChains.itemAt(i);
+ if (seqChain.seq == currentSeq) {
+ currentSeq = seqChain.chain;
+ chainSeqs[chainIndex++] = currentSeq;
+ mSeqChains.removeAt(i);
+ }
+ }
+ status_t status = OK;
+ while (!status && chainIndex-- > 0) {
+ status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled);
+ }
+ if (status) {
+ // An error occurred so at least one signal was not sent, reconstruct the chain.
+ do {
+ SeqChain seqChain;
+ seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;
+ seqChain.chain = chainSeqs[chainIndex];
+ mSeqChains.push(seqChain);
+ } while (chainIndex-- > 0);
+ return status;
+ }
+ }
+
+ // Send finished signal for the last message in the batch.
+ return sendUnchainedFinishedSignal(seq, handled);
+}
+
+status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled) {
InputMessage msg;
msg.header.type = InputMessage::TYPE_FINISHED;
msg.body.finished.seq = seq;