DO NOT MERGE: Fix input event injection ANRs on UI thread.
Added a new asynchronous injection mode and made the existing synchronization mechanism more robust. Change-Id: Ia4aa04fd9b75ea2461a844c5b7933c831c1027e6
This commit is contained in:
@ -103,6 +103,7 @@ import android.view.IWindowManager;
|
||||
import android.view.IWindowSession;
|
||||
import android.view.InputChannel;
|
||||
import android.view.InputDevice;
|
||||
import android.view.InputEvent;
|
||||
import android.view.InputQueue;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
@ -5382,6 +5383,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
|
||||
/**
|
||||
* Injects a keystroke event into the UI.
|
||||
* Even when sync is false, this method may block while waiting for current
|
||||
* input events to be dispatched.
|
||||
*
|
||||
* @param ev A motion event describing the keystroke action. (Be sure to use
|
||||
* {@link SystemClock#uptimeMillis()} as the timebase.)
|
||||
@ -5414,8 +5417,10 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
final int uid = Binder.getCallingUid();
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
|
||||
final int result = mInputManager.injectKeyEvent(newEvent,
|
||||
pid, uid, sync, INJECTION_TIMEOUT_MILLIS);
|
||||
final int result = mInputManager.injectInputEvent(newEvent, pid, uid,
|
||||
sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH
|
||||
: InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
|
||||
INJECTION_TIMEOUT_MILLIS);
|
||||
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
return reportInjectionResult(result);
|
||||
@ -5423,6 +5428,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
|
||||
/**
|
||||
* Inject a pointer (touch) event into the UI.
|
||||
* Even when sync is false, this method may block while waiting for current
|
||||
* input events to be dispatched.
|
||||
*
|
||||
* @param ev A motion event describing the pointer (touch) action. (As noted in
|
||||
* {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
|
||||
@ -5440,8 +5447,10 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
newEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
|
||||
}
|
||||
|
||||
final int result = mInputManager.injectMotionEvent(newEvent,
|
||||
pid, uid, sync, INJECTION_TIMEOUT_MILLIS);
|
||||
final int result = mInputManager.injectInputEvent(newEvent, pid, uid,
|
||||
sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH
|
||||
: InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
|
||||
INJECTION_TIMEOUT_MILLIS);
|
||||
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
return reportInjectionResult(result);
|
||||
@ -5449,6 +5458,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
|
||||
/**
|
||||
* Inject a trackball (navigation device) event into the UI.
|
||||
* Even when sync is false, this method may block while waiting for current
|
||||
* input events to be dispatched.
|
||||
*
|
||||
* @param ev A motion event describing the trackball action. (As noted in
|
||||
* {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
|
||||
@ -5466,8 +5477,31 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
newEvent.setSource(InputDevice.SOURCE_TRACKBALL);
|
||||
}
|
||||
|
||||
final int result = mInputManager.injectMotionEvent(newEvent,
|
||||
pid, uid, sync, INJECTION_TIMEOUT_MILLIS);
|
||||
final int result = mInputManager.injectInputEvent(newEvent, pid, uid,
|
||||
sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH
|
||||
: InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
|
||||
INJECTION_TIMEOUT_MILLIS);
|
||||
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
return reportInjectionResult(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject an input event into the UI without waiting for dispatch to commence.
|
||||
* This variant is useful for fire-and-forget input event injection. It does not
|
||||
* block any longer than it takes to enqueue the input event.
|
||||
*
|
||||
* @param ev An input event. (Be sure to set the input source correctly.)
|
||||
* @return Returns true if event was dispatched, false if it was dropped for any reason
|
||||
*/
|
||||
public boolean injectInputEventNoWait(InputEvent ev) {
|
||||
final int pid = Binder.getCallingPid();
|
||||
final int uid = Binder.getCallingUid();
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
|
||||
final int result = mInputManager.injectInputEvent(ev, pid, uid,
|
||||
InputManager.INPUT_EVENT_INJECTION_SYNC_NONE,
|
||||
INJECTION_TIMEOUT_MILLIS);
|
||||
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
return reportInjectionResult(result);
|
||||
|
Reference in New Issue
Block a user