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:
Jeff Brown
2010-07-28 15:48:59 -07:00
parent 6dea6f4e71
commit 6ec402b5ae
13 changed files with 379 additions and 204 deletions

View File

@ -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);