Merge "Merge "Fix keyboard focus in VR" into oc-dr1-dev am: 986995d481" into oc-mr1-dev
diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
index ed223d1..d2e3510 100644
--- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
@@ -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.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 @@
}
@Override
- public void onInputEvent(InputEvent event) {
+ public void onInputEvent(InputEvent event, int displayId) {
if (mInputMethodSession == null) {
// The session has been finished.
finishInputEvent(event, false);
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 424967f..1457adf 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -268,7 +268,7 @@
}
@Override
- public void onInputEvent(InputEvent event) {
+ public void onInputEvent(InputEvent event, int displayId) {
boolean handled = false;
try {
if (event instanceof MotionEvent
diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java
index 20ab539..c566a65 100644
--- a/core/java/android/view/InputEventReceiver.java
+++ b/core/java/android/view/InputEventReceiver.java
@@ -111,9 +111,10 @@
* 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 @@
// 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.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 05f9da5..6bf4845 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -6752,7 +6752,7 @@
}
@Override
- public void onInputEvent(InputEvent event) {
+ public void onInputEvent(InputEvent event, int displayId) {
enqueueInputEvent(event, this, 0, true);
}
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index 4c9cf40..98f8dc8 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -347,4 +347,11 @@
* 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);
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 668d25e..49b7ed8 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -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 @@
* 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. */
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index 31e954b..c457ab0 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -233,8 +233,9 @@
for (;;) {
uint32_t seq;
InputEvent* inputEvent;
+ int32_t displayId;
status_t status = mInputConsumer.consume(&mInputEventFactory,
- consumeBatches, frameTime, &seq, &inputEvent);
+ consumeBatches, frameTime, &seq, &inputEvent, &displayId);
if (status) {
if (status == WOULD_BLOCK) {
if (!skipCallbacks && !mBatchedInputEventPending
@@ -311,7 +312,8 @@
ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName());
}
env->CallVoidMethod(receiverObj.get(),
- gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
+ gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj,
+ displayId);
if (env->ExceptionCheck()) {
ALOGE("Exception dispatching input event.");
skipCallbacks = true;
@@ -417,7 +419,7 @@
gInputEventReceiverClassInfo.dispatchInputEvent = GetMethodIDOrDie(env,
gInputEventReceiverClassInfo.clazz,
- "dispatchInputEvent", "(ILandroid/view/InputEvent;)V");
+ "dispatchInputEvent", "(ILandroid/view/InputEvent;I)V");
gInputEventReceiverClassInfo.dispatchBatchedInputEventPending = GetMethodIDOrDie(env,
gInputEventReceiverClassInfo.clazz, "dispatchBatchedInputEventPending", "()V");
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index 420ff2a..58ccef18 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -39,6 +39,8 @@
// Log debug messages about the dispatch cycle.
static const bool kDebugDispatchCycle = false;
+// Display id for default(primary) display.
+static const int32_t kDefaultDisplayId = 0;
static struct {
jclass clazz;
@@ -136,6 +138,7 @@
publishedSeq = mNextPublishedSeq++;
status_t status = mInputPublisher.publishMotionEvent(publishedSeq,
event->getDeviceId(), event->getSource(),
+ kDefaultDisplayId /* TODO(multi-display): propagate display id */,
event->getAction(), event->getActionButton(), event->getFlags(),
event->getEdgeFlags(), event->getMetaState(), event->getButtonState(),
event->getXOffset(), event->getYOffset(),
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index 07cfbda..df87e0f 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -367,7 +367,7 @@
}
@Override
- public void onInputEvent(InputEvent event) {
+ public void onInputEvent(InputEvent event, int displayId) {
if (mTvInputSessionImpl == null) {
// The session has been finished.
finishInputEvent(event, false);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java
index 6733421..abc5667 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/InputConsumerController.java
@@ -65,7 +65,7 @@
}
@Override
- public void onInputEvent(InputEvent event) {
+ public void onInputEvent(InputEvent event, int displayId) {
boolean handled = true;
try {
// To be implemented for input handling over Pip windows
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index e3cf459..61ecee3 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4184,7 +4184,7 @@
}
@Override
- public void onInputEvent(InputEvent event) {
+ public void onInputEvent(InputEvent event, int displayId) {
boolean handled = false;
try {
if (event instanceof MotionEvent
diff --git a/services/core/java/com/android/server/vr/Vr2dDisplay.java b/services/core/java/com/android/server/vr/Vr2dDisplay.java
index 69d8ca6..8f50a39 100644
--- a/services/core/java/com/android/server/vr/Vr2dDisplay.java
+++ b/services/core/java/com/android/server/vr/Vr2dDisplay.java
@@ -24,6 +24,7 @@
import android.service.vr.IVrManager;
import android.util.Log;
import android.view.Surface;
+import android.view.WindowManagerInternal;
import com.android.server.vr.VrManagerService;
@@ -74,6 +75,7 @@
public static final int MIN_VR_DISPLAY_DPI = 1;
private final ActivityManagerInternal mActivityManagerInternal;
+ private final WindowManagerInternal mWindowManagerInternal;
private final DisplayManager mDisplayManager;
private final IVrManager mVrManager;
private final Object mVdLock = new Object();
@@ -103,9 +105,11 @@
private boolean mBootsToVr = false; // The device boots into VR (standalone VR device)
public Vr2dDisplay(DisplayManager displayManager,
- ActivityManagerInternal activityManagerInternal, IVrManager vrManager) {
+ ActivityManagerInternal activityManagerInternal,
+ WindowManagerInternal windowManagerInternal, IVrManager vrManager) {
mDisplayManager = displayManager;
mActivityManagerInternal = activityManagerInternal;
+ mWindowManagerInternal = windowManagerInternal;
mVrManager = vrManager;
mVirtualDisplayWidth = DEFAULT_VIRTUAL_DISPLAY_WIDTH;
mVirtualDisplayHeight = DEFAULT_VIRTUAL_DISPLAY_HEIGHT;
@@ -296,13 +300,12 @@
UNIQUE_DISPLAY_ID);
if (mVirtualDisplay != null) {
- mActivityManagerInternal.setVr2dDisplayId(
- mVirtualDisplay.getDisplay().getDisplayId());
+ updateDisplayId(mVirtualDisplay.getDisplay().getDisplayId());
// Now create the ImageReader to supply a Surface to the new virtual display.
startImageReader();
} else {
Log.w(TAG, "Virtual display id is null after createVirtualDisplay");
- mActivityManagerInternal.setVr2dDisplayId(INVALID_DISPLAY);
+ updateDisplayId(INVALID_DISPLAY);
return;
}
}
@@ -310,6 +313,11 @@
Log.i(TAG, "VD created: " + mVirtualDisplay);
}
+ private void updateDisplayId(int displayId) {
+ mActivityManagerInternal.setVr2dDisplayId(displayId);
+ mWindowManagerInternal.setVr2dDisplayId(displayId);
+ }
+
/**
* Stops the virtual display with a {@link #STOP_VIRTUAL_DISPLAY_DELAY_MILLIS} timeout.
* The timeout prevents the virtual display from bouncing in cases where VrMode goes in and out
@@ -325,7 +333,7 @@
} else {
Log.i(TAG, "Stopping Virtual Display");
synchronized (mVdLock) {
- mActivityManagerInternal.setVr2dDisplayId(INVALID_DISPLAY);
+ updateDisplayId(INVALID_DISPLAY);
setSurfaceLocked(null); // clean up and release the surface first.
if (mVirtualDisplay != null) {
mVirtualDisplay.release();
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 425b23f..b6b964b 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -58,6 +58,7 @@
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
+import android.view.WindowManagerInternal;
import com.android.internal.R;
import com.android.internal.util.DumpUtils;
@@ -633,8 +634,11 @@
DisplayManager dm =
(DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE);
- ActivityManagerInternal ami = LocalServices.getService(ActivityManagerInternal.class);
- mVr2dDisplay = new Vr2dDisplay(dm, ami, mVrManager);
+ mVr2dDisplay = new Vr2dDisplay(
+ dm,
+ LocalServices.getService(ActivityManagerInternal.class),
+ LocalServices.getService(WindowManagerInternal.class),
+ mVrManager);
mVr2dDisplay.init(getContext(), mBootsToVr);
IntentFilter intentFilter = new IntentFilter();
diff --git a/services/core/java/com/android/server/wm/PointerEventDispatcher.java b/services/core/java/com/android/server/wm/PointerEventDispatcher.java
index 6b0e4c9..484987e 100644
--- a/services/core/java/com/android/server/wm/PointerEventDispatcher.java
+++ b/services/core/java/com/android/server/wm/PointerEventDispatcher.java
@@ -36,11 +36,11 @@
}
@Override
- public void onInputEvent(InputEvent event) {
+ public void onInputEvent(InputEvent event, int displayId) {
try {
if (event instanceof MotionEvent
&& (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
- final MotionEvent motionEvent = (MotionEvent)event;
+ final MotionEvent motionEvent = (MotionEvent) event;
PointerEventListener[] listeners;
synchronized (mListeners) {
if (mListenersArray == null) {
@@ -50,7 +50,7 @@
listeners = mListenersArray;
}
for (int i = 0; i < listeners.length; ++i) {
- listeners[i].onPointerEvent(motionEvent);
+ listeners[i].onPointerEvent(motionEvent, displayId);
}
}
} finally {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 36fa3a7..40528d0 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -18,6 +18,7 @@
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
import android.hardware.power.V1_0.PowerHint;
import android.os.Binder;
import android.os.Debug;
@@ -243,12 +244,24 @@
displayId, displayInfo);
mService.configureDisplayPolicyLocked(dc);
- // TODO(multi-display): Create an input channel for each display with touch capability.
- if (displayId == DEFAULT_DISPLAY && mService.canDispatchPointerEvents()) {
- dc.mTapDetector = new TaskTapPointerEventListener(
- mService, dc);
+ // Tap Listeners are supported for:
+ // 1. All physical displays (multi-display).
+ // 2. VirtualDisplays that support virtual touch input. (Only VR for now)
+ // TODO(multi-display): Support VirtualDisplays with no virtual touch input.
+ if ((display.getType() != Display.TYPE_VIRTUAL
+ || (display.getType() == Display.TYPE_VIRTUAL
+ // Only VR VirtualDisplays
+ && displayId == mService.mVr2dDisplayId))
+ && mService.canDispatchPointerEvents()) {
+ if (DEBUG_DISPLAY) {
+ Slog.d(TAG,
+ "Registering PointerEventListener for DisplayId: " + displayId);
+ }
+ dc.mTapDetector = new TaskTapPointerEventListener(mService, dc);
mService.registerPointerEventListener(dc.mTapDetector);
- mService.registerPointerEventListener(mService.mMousePositionTracker);
+ if (displayId == DEFAULT_DISPLAY) {
+ mService.registerPointerEventListener(mService.mMousePositionTracker);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 0c68e2c..c58212c 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -133,7 +133,7 @@
}
@Override
- public void onInputEvent(InputEvent event) {
+ public void onInputEvent(InputEvent event, int displayId) {
if (!(event instanceof MotionEvent)
|| (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
return;
diff --git a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
index dd9ba73..42a2d9d 100644
--- a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
@@ -24,6 +24,7 @@
import com.android.server.wm.WindowManagerService.H;
+import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.PointerIcon.TYPE_NOT_SPECIFIED;
import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;
import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
@@ -45,6 +46,13 @@
}
@Override
+ public void onPointerEvent(MotionEvent motionEvent, int displayId) {
+ if (displayId == getDisplayId()) {
+ onPointerEvent(motionEvent);
+ }
+ }
+
+ @Override
public void onPointerEvent(MotionEvent motionEvent) {
final int action = motionEvent.getAction();
switch (action & MotionEvent.ACTION_MASK) {
@@ -104,4 +112,8 @@
mTouchExcludeRegion.set(newRegion);
}
}
+
+ private int getDisplayId() {
+ return mDisplayContent.getDisplayId();
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 5db691e..83926af 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -79,6 +79,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
@@ -357,6 +358,8 @@
final private KeyguardDisableHandler mKeyguardDisableHandler;
boolean mKeyguardGoingAway;
+ // VR Vr2d Display Id.
+ int mVr2dDisplayId = INVALID_DISPLAY;
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -767,7 +770,7 @@
}
@Override
- public void onInputEvent(InputEvent event) {
+ public void onInputEvent(InputEvent event, int displayId) {
boolean handled = false;
try {
if (mDragState == null) {
@@ -7565,6 +7568,16 @@
accessibilityController.performComputeChangedWindowsNotLocked();
}
}
+
+ @Override
+ public void setVr2dDisplayId(int vr2dDisplayId) {
+ if (DEBUG_DISPLAY) {
+ Slog.d(TAG, "setVr2dDisplayId called for: " + vr2dDisplayId);
+ }
+ synchronized (WindowManagerService.this) {
+ mVr2dDisplayId = vr2dDisplayId;
+ }
+ }
}
void registerAppFreezeListener(AppFreezeListener listener) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 7decb11..7ec21a8 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2043,7 +2043,7 @@
super(inputChannel, mService.mH.getLooper());
}
@Override
- public void onInputEvent(InputEvent event) {
+ public void onInputEvent(InputEvent event, int displayId) {
finishInputEvent(event, true);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index 856e940..91eb55b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -31,10 +31,13 @@
import org.junit.runner.RunWith;
import android.content.res.Configuration;
+import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import android.util.DisplayMetrics;
import android.util.SparseIntArray;
+import android.view.MotionEvent;
import java.util.Arrays;
import java.util.LinkedList;
@@ -237,6 +240,52 @@
assertEquals(currentConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
}
+ /**
+ * Tests tapping on a stack in different display results in window gaining focus.
+ */
+ @Test
+ public void testInputEventBringsCorrectDisplayInFocus() throws Exception {
+ DisplayContent dc0 = sWm.getDefaultDisplayContentLocked();
+ // Create a second display
+ final DisplayContent dc1 = createNewDisplay();
+
+ // Add stack with activity.
+ final TaskStack stack0 = createTaskStackOnDisplay(dc0);
+ final Task task0 = createTaskInStack(stack0, 0 /* userId */);
+ final WindowTestUtils.TestAppWindowToken token =
+ new WindowTestUtils.TestAppWindowToken(dc0);
+ task0.addChild(token, 0);
+ dc0.mTapDetector = new TaskTapPointerEventListener(sWm, dc0);
+ sWm.registerPointerEventListener(dc0.mTapDetector);
+ final TaskStack stack1 = createTaskStackOnDisplay(dc1);
+ final Task task1 = createTaskInStack(stack1, 0 /* userId */);
+ final WindowTestUtils.TestAppWindowToken token1 =
+ new WindowTestUtils.TestAppWindowToken(dc0);
+ task1.addChild(token1, 0);
+ dc1.mTapDetector = new TaskTapPointerEventListener(sWm, dc0);
+ sWm.registerPointerEventListener(dc1.mTapDetector);
+
+ // tap on primary display (by sending ACTION_DOWN followed by ACTION_UP)
+ DisplayMetrics dm0 = dc0.getDisplayMetrics();
+ dc0.mTapDetector.onPointerEvent(
+ createTapEvent(dm0.widthPixels / 2, dm0.heightPixels / 2, true));
+ dc0.mTapDetector.onPointerEvent(
+ createTapEvent(dm0.widthPixels / 2, dm0.heightPixels / 2, false));
+
+ // Check focus is on primary display.
+ assertEquals(sWm.mCurrentFocus, dc0.findFocusedWindow());
+
+ // Tap on secondary display
+ DisplayMetrics dm1 = dc1.getDisplayMetrics();
+ dc1.mTapDetector.onPointerEvent(
+ createTapEvent(dm1.widthPixels / 2, dm1.heightPixels / 2, true));
+ dc1.mTapDetector.onPointerEvent(
+ createTapEvent(dm1.widthPixels / 2, dm1.heightPixels / 2, false));
+
+ // Check focus is on secondary.
+ assertEquals(sWm.mCurrentFocus, dc1.findFocusedWindow());
+ }
+
@Test
@Ignore
public void testFocusedWindowMultipleDisplays() throws Exception {
@@ -355,4 +404,18 @@
}
assertTrue(actualWindows.isEmpty());
}
+
+ private MotionEvent createTapEvent(float x, float y, boolean isDownEvent) {
+ final long downTime = SystemClock.uptimeMillis();
+ final long eventTime = SystemClock.uptimeMillis() + 100;
+ final int metaState = 0;
+
+ return MotionEvent.obtain(
+ downTime,
+ eventTime,
+ isDownEvent ? MotionEvent.ACTION_DOWN : MotionEvent.ACTION_UP,
+ x,
+ y,
+ metaState);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 828d405..95adc9c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -18,6 +18,10 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManagerPolicy.NAV_BAR_BOTTOM;
+
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -39,6 +43,7 @@
import android.os.RemoteException;
import android.view.Display;
import android.view.IWindowManager;
+import android.view.InputChannel;
import android.view.KeyEvent;
import android.view.WindowManager;
import android.view.WindowManagerPolicy;
@@ -91,7 +96,14 @@
}).when(am).notifyKeyguardFlagsChanged(any());
}
- sWm = WindowManagerService.main(context, mock(InputManagerService.class), true, false,
+ InputManagerService ims = mock(InputManagerService.class);
+ // InputChannel is final and can't be mocked.
+ InputChannel[] input = InputChannel.openInputChannelPair(TAG_WM);
+ if (input != null && input.length > 1) {
+ doReturn(input[1]).when(ims).monitorInput(anyString());
+ }
+
+ sWm = WindowManagerService.main(context, ims, true, false,
false, new TestWindowManagerPolicy());
}
return sWm;