Fix keyboard focus in VR

Consider this VirtualDisplay (VD) scenario:
HostActivity creates a VD which holds SettingsActivity. When EditText
on SettingsActivity is tapped, it gains focus.
On eventual taps, it loses focus i.e. the Window in VD loses focus and
the host activity in primary display gets the focus instead. This
happens because WM's TaskTapPointerEventListener.onPointerEvent()
is called on the default display only.

Root cause:
1. Tap detector isn't registered for non-default display.
2. Tap detector has no info on which displayId touch was received.
3. InputFlinger doesn't deliver InputMonitor events for
non-default displays (fixed in a separate CL)

Fixing above results in onPointerEvent(MotionEvent) to deliver the
Touch events successfully to VD. We restrict these changes to physical
multi-displays and VR VirtualDisplays (which uses virtual touch device).
[VrManagerService calls WMInternal.setVr2dDisplayId(int)]

In future, displayId should be part of InputEvent. Bug: 64258305

Bug: 62033391
Test: bit FrameworksServicesTests:com.android.server.wm.DisplayContentTests
Change-Id: I3626f4de5aa9bcf905da9abd39f3ab1baefc4c48
This commit is contained in:
Tarandeep Singh
2017-07-10 18:50:00 -07:00
parent 06802167e5
commit e1cfcf4c4d
21 changed files with 185 additions and 37 deletions

View File

@@ -16,10 +16,6 @@
package android.inputmethodservice;
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.SomeArgs;
import com.android.internal.view.IInputMethodSession;
import android.content.Context;
import android.graphics.Rect;
import android.os.Bundle;
@@ -34,9 +30,13 @@ import android.view.InputEventReceiver;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CursorAnchorInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.InputMethodSession;
import android.view.inputmethod.CursorAnchorInfo;
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.SomeArgs;
import com.android.internal.view.IInputMethodSession;
class IInputMethodSessionWrapper extends IInputMethodSession.Stub
implements HandlerCaller.Callback {
@@ -218,7 +218,7 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub
}
@Override
public void onInputEvent(InputEvent event) {
public void onInputEvent(InputEvent event, int displayId) {
if (mInputMethodSession == null) {
// The session has been finished.
finishInputEvent(event, false);

View File

@@ -268,7 +268,7 @@ public abstract class WallpaperService extends Service {
}
@Override
public void onInputEvent(InputEvent event) {
public void onInputEvent(InputEvent event, int displayId) {
boolean handled = false;
try {
if (event instanceof MotionEvent

View File

@@ -111,9 +111,10 @@ public abstract class InputEventReceiver {
* to indicate whether the event was handled. No new input events will be received
* until {@link #finishInputEvent} is called.
*
* @param displayId The display id on which input event triggered.
* @param event The input event that was received.
*/
public void onInputEvent(InputEvent event) {
public void onInputEvent(InputEvent event, int displayId) {
finishInputEvent(event, false);
}
@@ -180,9 +181,9 @@ public abstract class InputEventReceiver {
// Called from native code.
@SuppressWarnings("unused")
private void dispatchInputEvent(int seq, InputEvent event) {
private void dispatchInputEvent(int seq, InputEvent event, int displayId) {
mSeqMap.put(event.getSequenceNumber(), seq);
onInputEvent(event);
onInputEvent(event, displayId);
}
// Called from native code.

View File

@@ -6756,7 +6756,7 @@ public final class ViewRootImpl implements ViewParent,
}
@Override
public void onInputEvent(InputEvent event) {
public void onInputEvent(InputEvent event, int displayId) {
enqueueInputEvent(event, this, 0, true);
}

View File

@@ -347,4 +347,11 @@ public abstract class WindowManagerInternal {
* Requests the window manager to recompute the windows for accessibility.
*/
public abstract void computeWindowsForAccessibility();
/**
* Called after virtual display Id is updated by
* {@link com.android.server.vr.Vr2dDisplay} with a specific
* {@param vr2dDisplayId}.
*/
public abstract void setVr2dDisplayId(int vr2dDisplayId);
}

View File

@@ -16,6 +16,7 @@
package android.view;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
@@ -616,7 +617,16 @@ public interface WindowManagerPolicy {
* 2. motionEvent will be recycled after onPointerEvent returns so if it is needed later a
* copy() must be made and the copy must be recycled.
**/
public void onPointerEvent(MotionEvent motionEvent);
void onPointerEvent(MotionEvent motionEvent);
/**
* @see #onPointerEvent(MotionEvent)
**/
default void onPointerEvent(MotionEvent motionEvent, int displayId) {
if (displayId == DEFAULT_DISPLAY) {
onPointerEvent(motionEvent);
}
}
}
/** Window has been added to the screen. */