e4623041f9
Previously, when the touched window was unresponsive, we skipped adding the gesture monitors to the touch targets. That means, when an app has ANR, gesture nav stops working, and the phone feels frozen, until the ANR dialog comes up. Another failure mode was a stuck pending event. If there is no focused window, and we have a pending key event (or any focused event), we will be waiting for a focused window to appear. That would still prevent gesture monitors from receiving further touch events. In this solution, we do not add unresponsive windows to the list of targets, but we still proceed with handling the event, meaning that the app won't get a new DOWN when it is unresponsive, but the event would still go to the gesture monitors. That change, in isolation, would also break ANR for the case when the app loses focus. To maintain the ANR functionality, we extend the ANR detection mechanism to all connections. Now, every connection is eligible to receive an ANR, even if it's a gesture monitor. We expect everything in the system to be responsive within reasonable timeouts. We also change the handling of extended ANR timeouts coming from policy. Today, the behaviour is as follows: 1. If the policy says "wait longer", then we do nothing and just keep waiting 2. If the policy says "abort", then we send the cancel events and remove the window from the window list. The "abort" approach seems incorrect, because the policy will probably not register the existing inputchannel/connection with a new window. If the user does click "close app" when the ANR dialog appears, we will anyways receive "window removed" event via setInputWindows, and will clean up the connection that way. So we don't really need to do anything other than sending "cancel events" to the window. The policy now for sending events to unresponsive windows becomes: 1. If the unresponsive window is touched, the new touch stream does not go to the window. It will go to all other places, though. 2. If the unresponsive window receives a focused event, the event still gets queued for the unresponsive window to handle. For improved ANR performance, the ANR detection is now done by introducing a helper data structure, a multiset of the timeout times. Whenever we send an event to a connection, we will calculate the time that this event will cause a timeout. We will then add this time to the multiset of times. When we check for ANR inside dispatchOnce, we will only access the smallest (soonest) timeout inside the multiset. If the current time is before this smallest timeout time, then everything is normal, and we move on. This would cost O(1). If the time is past the timeout time, it means a connection is unresponsive. In this case, we take the closest in time unresponsive entry. That entry already has the connection token, for convenience. We then raise an ANR on that connection. The entries are removed from the multiset in several cases: 1. When we receive a 'finished' signal on an entry for a specific connection 2. When the connection becomes unresponsive and we raise ANR. In that case, no need to keep checking on the same connection. Once case 1. applies to that connection, entries from that connection will again become eligible for being added to the multiset. 3. When we reset and drop everything. 4. When we cannot find a connection for an entry in the multiset, we will drop all entries from that connection. If we report ANR for an app, we do not report the second ANR until the waitQueue becomes healthy first and then becomes clogged again. If we have a focused application, but no window has focus, then nothing will happen for pointer events. They will keep going to the touched window as normal. When we receive the first focused event, however, we will start a timer. If there is no focused window added by that time, we will send an ANR for that application. This logic should be moved into WM later, because from the input perspective, it is legitimate to have an application without a focused window. This would also allow WM to remove the "setFocusedApplication" call. Bug: 143459140 Test: use the test app from the bug. The app sleeps for 10 seconds when the button is clicked. Click the button, and try to use gesture nav several times. Observe that gesture nav continues to work even after app has ANR. Observe that ANR is reported even after interacting with gesture nav. Test: Click on the app multiple times (to clog up the queue), and then wait for a long time, even after the ANR dialog shows up. Then click "wait" to not close the app. Then click again on the app. Observe that the anr dialog appears after a while. This indicates that at some point, the app processed all events, and then became eligible for anr again. Test: adb shell -t /data/nativetest64/inputflinger_tests/inputflinger_tests Test: create an app that sets "FLAG_NOT_FOCUSABLE" on its only window. Launch the app and interact with it by touch. Notice that the app does not ANR. Then, send the back key to the app (using the back gesture). Notice that in 5 seconds, we receive an ANR for this app. While the BACK key is queued up for this app, the gesture nav continues to work and the notification shade can still be pulled down. Change-Id: I2c0fd1957cda833f5fbe26368cfcaa6fea6eddaf Merged-In: I2c0fd1957cda833f5fbe26368cfcaa6fea6eddaf |
||
---|---|---|
.. | ||
android | ||
audiomanager | ||
binder | ||
diskusage | ||
gfx | ||
input | ||
powermanager | ||
private | ||
ui | ||
vr/vr_manager | ||
gui | ||
layerproto | ||
media | ||
OWNERS |