Bundle correlated switch changes atomically.

This is a prerequisite for headset jack detection on Manta.

Bug: 6548391
Change-Id: I549a194344511c0cee578b00f6a9ab5fdbdfb99c
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 87a6c1b..be0cec9 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -2485,15 +2485,15 @@
 
 void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) {
 #if DEBUG_INBOUND_EVENT_DETAILS
-    ALOGD("notifySwitch - eventTime=%lld, policyFlags=0x%x, switchCode=%d, switchValue=%d",
+    ALOGD("notifySwitch - eventTime=%lld, policyFlags=0x%x, switchValues=0x%08x, switchMask=0x%08x",
             args->eventTime, args->policyFlags,
-            args->switchCode, args->switchValue);
+            args->switchValues, args->switchMask);
 #endif
 
     uint32_t policyFlags = args->policyFlags;
     policyFlags |= POLICY_FLAG_TRUSTED;
     mPolicy->notifySwitch(args->eventTime,
-            args->switchCode, args->switchValue, policyFlags);
+            args->switchValues, args->switchMask, policyFlags);
 }
 
 void InputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index af7ff5e..6099c43 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -248,7 +248,7 @@
     /* Notifies the policy about switch events.
      */
     virtual void notifySwitch(nsecs_t when,
-            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) = 0;
+            uint32_t switchValues, uint32_t switchMask, uint32_t policyFlags) = 0;
 
     /* Poke user activity for an event dispatched to a window. */
     virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) = 0;
diff --git a/services/input/InputListener.cpp b/services/input/InputListener.cpp
index c2705b0..85bb0ed 100644
--- a/services/input/InputListener.cpp
+++ b/services/input/InputListener.cpp
@@ -104,14 +104,14 @@
 // --- NotifySwitchArgs ---
 
 NotifySwitchArgs::NotifySwitchArgs(nsecs_t eventTime, uint32_t policyFlags,
-        int32_t switchCode, int32_t switchValue) :
+        uint32_t switchValues, uint32_t switchMask) :
         eventTime(eventTime), policyFlags(policyFlags),
-        switchCode(switchCode), switchValue(switchValue) {
+        switchValues(switchValues), switchMask(switchMask) {
 }
 
 NotifySwitchArgs::NotifySwitchArgs(const NotifySwitchArgs& other) :
         eventTime(other.eventTime), policyFlags(other.policyFlags),
-        switchCode(other.switchCode), switchValue(other.switchValue) {
+        switchValues(other.switchValues), switchMask(other.switchMask) {
 }
 
 void NotifySwitchArgs::notify(const sp<InputListenerInterface>& listener) const {
diff --git a/services/input/InputListener.h b/services/input/InputListener.h
index 486852b..cd7c25a 100644
--- a/services/input/InputListener.h
+++ b/services/input/InputListener.h
@@ -116,13 +116,13 @@
 struct NotifySwitchArgs : public NotifyArgs {
     nsecs_t eventTime;
     uint32_t policyFlags;
-    int32_t switchCode;
-    int32_t switchValue;
+    uint32_t switchValues;
+    uint32_t switchMask;
 
     inline NotifySwitchArgs() { }
 
     NotifySwitchArgs(nsecs_t eventTime, uint32_t policyFlags,
-            int32_t switchCode, int32_t switchValue);
+            uint32_t switchValues, uint32_t switchMask);
 
     NotifySwitchArgs(const NotifySwitchArgs& other);
 
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index d56b9a9..cebfeb4 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -1800,7 +1800,7 @@
 // --- SwitchInputMapper ---
 
 SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
-        InputMapper(device) {
+        InputMapper(device), mUpdatedSwitchValues(0), mUpdatedSwitchMask(0) {
 }
 
 SwitchInputMapper::~SwitchInputMapper() {
@@ -1813,14 +1813,33 @@
 void SwitchInputMapper::process(const RawEvent* rawEvent) {
     switch (rawEvent->type) {
     case EV_SW:
-        processSwitch(rawEvent->when, rawEvent->code, rawEvent->value);
+        processSwitch(rawEvent->code, rawEvent->value);
         break;
+
+    case EV_SYN:
+        if (rawEvent->code == SYN_REPORT) {
+            sync(rawEvent->when);
+        }
     }
 }
 
-void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
-    NotifySwitchArgs args(when, 0, switchCode, switchValue);
-    getListener()->notifySwitch(&args);
+void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
+    if (switchCode >= 0 && switchCode < 32) {
+        if (switchValue) {
+            mUpdatedSwitchValues |= 1 << switchCode;
+        }
+        mUpdatedSwitchMask |= 1 << switchCode;
+    }
+}
+
+void SwitchInputMapper::sync(nsecs_t when) {
+    if (mUpdatedSwitchMask) {
+        NotifySwitchArgs args(when, 0, mUpdatedSwitchValues, mUpdatedSwitchMask);
+        getListener()->notifySwitch(&args);
+
+        mUpdatedSwitchValues = 0;
+        mUpdatedSwitchMask = 0;
+    }
 }
 
 int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index e1a8dd8..61b21e2 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -962,7 +962,11 @@
     virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
 
 private:
-    void processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue);
+    uint32_t mUpdatedSwitchValues;
+    uint32_t mUpdatedSwitchMask;
+
+    void processSwitch(int32_t switchCode, int32_t switchValue);
+    void sync(nsecs_t when);
 };
 
 
diff --git a/services/input/tests/InputDispatcher_test.cpp b/services/input/tests/InputDispatcher_test.cpp
index 961566f..ed2b4a5 100644
--- a/services/input/tests/InputDispatcher_test.cpp
+++ b/services/input/tests/InputDispatcher_test.cpp
@@ -86,7 +86,7 @@
     }
 
     virtual void notifySwitch(nsecs_t when,
-            int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
+            uint32_t switchValues, uint32_t switchMask, uint32_t policyFlags) {
     }
 
     virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index c6dbbf3..14065d2 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -1493,12 +1493,16 @@
     addMapperAndConfigure(mapper);
 
     process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_LID, 1);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_JACK_PHYSICAL_INSERT, 1);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_HEADPHONE_INSERT, 0);
+    process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0);
 
     NotifySwitchArgs args;
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySwitchWasCalled(&args));
     ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-    ASSERT_EQ(SW_LID, args.switchCode);
-    ASSERT_EQ(1, args.switchValue);
+    ASSERT_EQ((1 << SW_LID) | (1 << SW_JACK_PHYSICAL_INSERT), args.switchValues);
+    ASSERT_EQ((1 << SW_LID) | (1 << SW_JACK_PHYSICAL_INSERT) | (1 << SW_HEADPHONE_INSERT),
+            args.switchMask);
     ASSERT_EQ(uint32_t(0), args.policyFlags);
 }