Merge "libbinder: reverse connections"
diff --git a/libs/binder/include/binder/BinderService.h b/libs/binder/include/binder/BinderService.h
index 5776f3c..e58d489 100644
--- a/libs/binder/include/binder/BinderService.h
+++ b/libs/binder/include/binder/BinderService.h
@@ -26,6 +26,24 @@
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
 
+// WARNING: deprecated - DO NOT USE - prefer to setup service directly.
+//
+// This class embellishes a class with a few static methods which can be used in
+// limited circumstances (when one service needs to be registered and
+// published). However, this is an anti-pattern:
+// - these methods are aliases of existing methods, and as such, represent an
+//   incremental amount of information required to understand the system but
+//   which does not actually save in terms of lines of code. For instance, users
+//   of this class should be surprised to know that this will start up to 16
+//   threads in the binder threadpool.
+// - the template instantiation costs need to be paid, even though everything
+//   done here is generic.
+// - the getServiceName API here is undocumented and non-local (for instance,
+//   this unnecessarily assumes a single service type will only be instantiated
+//   once with no arguments).
+//
+// So, DO NOT USE.
+
 // ---------------------------------------------------------------------------
 namespace android {
 
diff --git a/libs/binder/tests/rpc_fuzzer/main.cpp b/libs/binder/tests/rpc_fuzzer/main.cpp
index 072f8dd..9fc496f 100644
--- a/libs/binder/tests/rpc_fuzzer/main.cpp
+++ b/libs/binder/tests/rpc_fuzzer/main.cpp
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
 #include <binder/Binder.h>
@@ -90,8 +89,10 @@
             if (provider.ConsumeBool()) {
                 std::vector<uint8_t> writeData = provider.ConsumeBytes<uint8_t>(
                         provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes()));
-                CHECK(base::WriteFully(connections.at(idx).get(), writeData.data(),
-                                       writeData.size()));
+                ssize_t size = TEMP_FAILURE_RETRY(send(connections.at(idx).get(), writeData.data(),
+                                                       writeData.size(), MSG_NOSIGNAL));
+                CHECK(errno == EPIPE || size == writeData.size())
+                        << size << " " << writeData.size() << " " << strerror(errno);
             } else {
                 connections.erase(connections.begin() + idx); // hang up
             }
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 6ea64b4..674d6de 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -1098,6 +1098,11 @@
           entry->deviceId);
 #endif
 
+    // Reset key repeating in case a keyboard device was disabled or enabled.
+    if (mKeyRepeatState.lastKeyEntry && mKeyRepeatState.lastKeyEntry->deviceId == entry->deviceId) {
+        resetKeyRepeatLocked();
+    }
+
     CancelationOptions options(CancelationOptions::CANCEL_ALL_EVENTS, "device was reset");
     options.deviceId = entry->deviceId;
     synthesizeCancelationEventsForAllConnectionsLocked(options);
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 668a7ab..8d80f2a 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -1799,6 +1799,16 @@
     mWindow->assertNoEvents();
 }
 
+TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterDisableInputDevice) {
+    sendAndConsumeKeyDown();
+    expectKeyRepeatOnce(1 /*repeatCount*/);
+    NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
+    mDispatcher->notifyDeviceReset(&args);
+    mWindow->consumeKeyUp(ADISPLAY_ID_DEFAULT,
+                          AKEY_EVENT_FLAG_CANCELED | AKEY_EVENT_FLAG_LONG_PRESS);
+    mWindow->assertNoEvents();
+}
+
 TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
     sendAndConsumeKeyDown();
     for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {