Accumulate NotifyArgs inside the lock before notifying
Currently, mQueuedListener is used both with and without a lock inside
InputReader. This is problematic because things like 'vibrate' could
modify the collection inside QueuedInputListener while it's accessing
it.
This causes a crash.
To avoid this, explicitly accumulate the events inside a lock, and then
notify all args when the lock is released, but from a swapped variable.
Bug: 293260512
Test: atest inputflinger_tests
Change-Id: Ib9891b22e6c2632395ddfcec6af3aefe3151b4c4
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 01ec7c1..e21715e 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -174,7 +174,14 @@
// in parallel to passing it to the InputReader.
std::shared_ptr<EventHubInterface> mEventHub;
sp<InputReaderPolicyInterface> mPolicy;
- QueuedInputListener mQueuedListener;
+
+ // The next stage that should receive the events generated inside InputReader.
+ InputListenerInterface& mNextListener;
+ // As various events are generated inside InputReader, they are stored inside this list. The
+ // list can only be accessed with the lock, so the events inside it are well-ordered.
+ // Once the reader is done working, these events will be swapped into a temporary storage and
+ // sent to the 'mNextListener' without holding the lock.
+ std::list<NotifyArgs> mPendingArgs GUARDED_BY(mLock);
InputReaderConfiguration mConfig GUARDED_BY(mLock);
@@ -242,8 +249,6 @@
ConfigurationChanges mConfigurationChangesToRefresh GUARDED_BY(mLock);
void refreshConfigurationLocked(ConfigurationChanges changes) REQUIRES(mLock);
- void notifyAll(std::list<NotifyArgs>&& argsList);
-
PointerCaptureRequest mCurrentPointerCaptureRequest GUARDED_BY(mLock);
// state queries