Merge "Fix regression in default zoom setting"
diff --git a/cmds/keystore/keystore.cpp b/cmds/keystore/keystore.cpp
index 05f77e5..2c9cb35 100644
--- a/cmds/keystore/keystore.cpp
+++ b/cmds/keystore/keystore.cpp
@@ -581,7 +581,7 @@
 static ResponseCode insert(KeyStore* keyStore, int sock, uid_t uid, Value* keyName, Value* val) {
     char filename[NAME_MAX];
     encode_key(filename, uid, keyName);
-    Blob keyBlob(val->value, val->length, 0, NULL);
+    Blob keyBlob(val->value, val->length, NULL, 0);
     return keyStore->put(filename, &keyBlob);
 }
 
diff --git a/include/ui/InputTransport.h b/include/ui/InputTransport.h
index bdd2fb9..1f738cd 100644
--- a/include/ui/InputTransport.h
+++ b/include/ui/InputTransport.h
@@ -297,19 +297,32 @@
 private:
     sp<InputChannel> mChannel;
 
-    // State about an event that consume would have returned except that it had to
-    // return a completed batch first.  Sequence number is non-zero if an event was deferred.
-    uint32_t mDeferredEventSeq;
-    MotionEvent mDeferredEvent;
+    // The current input message.
+    InputMessage mMsg;
+
+    // True if mMsg contains a valid input message that was deferred from the previous
+    // call to consume and that still needs to be handled.
+    bool mMsgDeferred;
 
     // 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 98c4bdd..ecb3fb5 100644
--- a/libs/ui/InputTransport.cpp
+++ b/libs/ui/InputTransport.cpp
@@ -334,7 +334,7 @@
 // --- InputConsumer ---
 
 InputConsumer::InputConsumer(const sp<InputChannel>& channel) :
-        mChannel(channel), mDeferredEventSeq(0) {
+        mChannel(channel), mMsgDeferred(false) {
 }
 
 InputConsumer::~InputConsumer() {
@@ -350,55 +350,44 @@
     *outSeq = 0;
     *outEvent = NULL;
 
-    // Report deferred event first, if we had to end a batch earlier than we expected
-    // during the previous time consume was called.
-    if (mDeferredEventSeq) {
-        MotionEvent* motionEvent = factory->createMotionEvent();
-        if (! motionEvent) return NO_MEMORY;
-
-        motionEvent->copyFrom(&mDeferredEvent, true /*keepHistory*/);
-        *outSeq = mDeferredEventSeq;
-        *outEvent = motionEvent;
-        mDeferredEventSeq = 0;
-#if DEBUG_TRANSPORT_ACTIONS
-        ALOGD("channel '%s' consumer ~ consumed deferred event, seq=%u",
-                mChannel->getName().string(), *outSeq);
-#endif
-        return OK;
-    }
-
     // Fetch the next input message.
     // Loop until an event can be returned or no additional events are received.
     while (!*outEvent) {
-        InputMessage msg;
-        status_t result = mChannel->receiveMessage(&msg);
-        if (result) {
-            // Consume the next batched event unless batches are being held for later.
-            if (!mBatches.isEmpty() && (consumeBatches || result != WOULD_BLOCK)) {
-                MotionEvent* motionEvent = factory->createMotionEvent();
-                if (! motionEvent) return NO_MEMORY;
+        if (mMsgDeferred) {
+            // mMsg contains a valid input message from the previous call to consume
+            // that has not yet been processed.
+            mMsgDeferred = false;
+        } else {
+            // Receive a fresh message.
+            status_t result = mChannel->receiveMessage(&mMsg);
+            if (result) {
+                // Consume the next batched event unless batches are being held for later.
+                if (!mBatches.isEmpty() && (consumeBatches || result != WOULD_BLOCK)) {
+                    MotionEvent* motionEvent = factory->createMotionEvent();
+                    if (! motionEvent) return NO_MEMORY;
 
-                const Batch& batch = mBatches.top();
-                motionEvent->copyFrom(&batch.event, true /*keepHistory*/);
-                *outSeq = batch.seq;
-                *outEvent = motionEvent;
-                mBatches.pop();
+                    const Batch& batch = mBatches.top();
+                    motionEvent->copyFrom(&batch.event, true /*keepHistory*/);
+                    *outSeq = batch.seq;
+                    *outEvent = motionEvent;
+                    mBatches.pop();
 #if DEBUG_TRANSPORT_ACTIONS
-                ALOGD("channel '%s' consumer ~ consumed batch event, seq=%u",
-                        mChannel->getName().string(), *outSeq);
+                    ALOGD("channel '%s' consumer ~ consumed batch event, seq=%u",
+                            mChannel->getName().string(), *outSeq);
 #endif
-                break;
+                    break;
+                }
+                return result;
             }
-            return result;
         }
 
-        switch (msg.header.type) {
+        switch (mMsg.header.type) {
         case InputMessage::TYPE_KEY: {
             KeyEvent* keyEvent = factory->createKeyEvent();
             if (!keyEvent) return NO_MEMORY;
 
-            initializeKeyEvent(keyEvent, &msg);
-            *outSeq = msg.body.key.seq;
+            initializeKeyEvent(keyEvent, &mMsg);
+            *outSeq = mMsg.body.key.seq;
             *outEvent = keyEvent;
 #if DEBUG_TRANSPORT_ACTIONS
             ALOGD("channel '%s' consumer ~ consumed key event, seq=%u",
@@ -408,21 +397,20 @@
         }
 
         case AINPUT_EVENT_TYPE_MOTION: {
-            ssize_t batchIndex = findBatch(msg.body.motion.deviceId, msg.body.motion.source);
+            ssize_t batchIndex = findBatch(mMsg.body.motion.deviceId, mMsg.body.motion.source);
             if (batchIndex >= 0) {
                 Batch& batch = mBatches.editItemAt(batchIndex);
-                if (canAppendSamples(&batch.event, &msg)) {
-                    // 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;
-                    }
-
+                if (canAppendSamples(&batch.event, &mMsg)) {
                     // Append to the batch and save the new sequence number for the tail end.
-                    appendSamples(&batch.event, &msg);
-                    batch.seq = msg.body.motion.seq;
+                    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());
@@ -433,9 +421,8 @@
                     if (! motionEvent) return NO_MEMORY;
 
                     // We cannot append to the batch in progress, so we need to consume
-                    // the previous batch right now and defer the new event until later.
-                    mDeferredEventSeq = msg.body.motion.seq;
-                    initializeMotionEvent(&mDeferredEvent, &msg);
+                    // the previous batch right now and defer the new message until later.
+                    mMsgDeferred = true;
 
                     // Return the end of the previous batch.
                     motionEvent->copyFrom(&batch.event, true /*keepHistory*/);
@@ -452,12 +439,12 @@
             }
 
             // Start a new batch if needed.
-            if (msg.body.motion.action == AMOTION_EVENT_ACTION_MOVE
-                    || msg.body.motion.action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
+            if (mMsg.body.motion.action == AMOTION_EVENT_ACTION_MOVE
+                    || mMsg.body.motion.action == AMOTION_EVENT_ACTION_HOVER_MOVE) {
                 mBatches.push();
                 Batch& batch = mBatches.editTop();
-                batch.seq = msg.body.motion.seq;
-                initializeMotionEvent(&batch.event, &msg);
+                batch.seq = mMsg.body.motion.seq;
+                initializeMotionEvent(&batch.event, &mMsg);
 #if DEBUG_TRANSPORT_ACTIONS
                 ALOGD("channel '%s' consumer ~ started batch event",
                         mChannel->getName().string());
@@ -468,8 +455,8 @@
             MotionEvent* motionEvent = factory->createMotionEvent();
             if (! motionEvent) return NO_MEMORY;
 
-            initializeMotionEvent(motionEvent, &msg);
-            *outSeq = msg.body.motion.seq;
+            initializeMotionEvent(motionEvent, &mMsg);
+            *outSeq = mMsg.body.motion.seq;
             *outEvent = motionEvent;
 #if DEBUG_TRANSPORT_ACTIONS
             ALOGD("channel '%s' consumer ~ consumed motion event, seq=%u",
@@ -480,7 +467,7 @@
 
         default:
             ALOGE("channel '%s' consumer ~ Received unexpected message of type %d",
-                    mChannel->getName().string(), msg.header.type);
+                    mChannel->getName().string(), mMsg.header.type);
             return UNKNOWN_ERROR;
         }
     }
@@ -498,6 +485,41 @@
         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;