Ensure objects remain valid after calling policy
The function afterKeyEventLockedInterruptable releases the lock and calls into policy. During this time, the call to "removeInputChannel" might come in. This call would cause the waitQueue to be drained. Therefore, the dispatchEntry that's stored in this queue would be deleted. Before this CL, we obtained a reference to the EventEntry object before calling policy. If there aren't any more strong pointers remaining to the EventEntry, the object would become deleted, and the reference would end up pointing to freed memory. Previous flow of events: - KeyEntry is allocated during setFocusedWindow call, as part of "synthesizeCancelationEvents". - App calls "finish" on an event, and dispatcher notifies policy about the unhandled key event. But dispatcher must release lock before calling policy. - After dispatcher has released the lock, but before it called policy, there is a binder call to "removeInputChannel" that comes in. That causes the waitQueue to be drained, and deletes the DispatchEntry. If the dispatch entry is the last remaining reference to the KeyEntry, then the KeyEntry gets deleted, as well. - The dispatcher calls policy, and uses the reference to the KeyEntry that it was provided. But that reference points to freed memory. This causes a crash. To deal with this, make a few changes in this CL: - Since the "doDispatchCycleFinishedCommand" is stored in queue, it should have a strong pointer to the connection object, and not just a reference. That means the Connection object will be valid when the command actually runs (otherwise, someone might delete it) - Inside afterKeyEventLockedInterruptable, assume that the dispatchEntry will be deleted after the lock is released. Make copies of the data that we need after the lock is regained: 1) Add refcount for EventEntry 2) Store the "hasForegroundTarget" into a separate variable (technically, it's not necessary, but it allows us to remove all usages of "dispatchEntry" in the rest of the function. As an alternative, we could re-look up the DispatchEntry in the waitQueue after we regain the lock, but that seems more complex in terms of implementation / readability. Bug: 343129193 Test: atest --host inputflinger_tests (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:299fd8ed96d30b5a83f0f8476c591b457cff4acb) Merged-In: Ibea7117e4c85cd1e98bbd01872ce249cbb2d54bd Change-Id: Ibea7117e4c85cd1e98bbd01872ce249cbb2d54bd
Loading
Please register or sign in to comment