Merge "Fix keyboard focus in VR" into oc-dr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
986995d481
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -233,8 +233,9 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
|
||||
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 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
|
||||
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 @@ int register_android_view_InputEventReceiver(JNIEnv* env) {
|
||||
|
||||
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");
|
||||
|
||||
|
||||
@@ -39,6 +39,8 @@ namespace android {
|
||||
|
||||
// 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 @@ status_t NativeInputEventSender::sendMotionEvent(uint32_t seq, const MotionEvent
|
||||
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(),
|
||||
|
||||
@@ -367,7 +367,7 @@ public class ITvInputSessionWrapper extends ITvInputSession.Stub implements Hand
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputEvent(InputEvent event) {
|
||||
public void onInputEvent(InputEvent event, int displayId) {
|
||||
if (mTvInputSessionImpl == null) {
|
||||
// The session has been finished.
|
||||
finishInputEvent(event, false);
|
||||
|
||||
@@ -65,7 +65,7 @@ public class InputConsumerController {
|
||||
}
|
||||
|
||||
@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
|
||||
|
||||
@@ -4184,7 +4184,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputEvent(InputEvent event) {
|
||||
public void onInputEvent(InputEvent event, int displayId) {
|
||||
boolean handled = false;
|
||||
try {
|
||||
if (event instanceof MotionEvent
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.service.vr.IPersistentVrStateCallbacks;
|
||||
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 @@ class Vr2dDisplay {
|
||||
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 @@ class Vr2dDisplay {
|
||||
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 @@ class Vr2dDisplay {
|
||||
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 @@ class Vr2dDisplay {
|
||||
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 @@ class Vr2dDisplay {
|
||||
} 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();
|
||||
|
||||
@@ -56,6 +56,7 @@ import android.util.ArrayMap;
|
||||
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;
|
||||
@@ -627,8 +628,11 @@ public class VrManagerService extends SystemService implements EnabledComponentC
|
||||
|
||||
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();
|
||||
|
||||
@@ -36,11 +36,11 @@ public class PointerEventDispatcher extends InputEventReceiver {
|
||||
}
|
||||
|
||||
@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 @@ public class PointerEventDispatcher extends InputEventReceiver {
|
||||
listeners = mListenersArray;
|
||||
}
|
||||
for (int i = 0; i < listeners.length; ++i) {
|
||||
listeners[i].onPointerEvent(motionEvent);
|
||||
listeners[i].onPointerEvent(motionEvent, displayId);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.server.wm;
|
||||
|
||||
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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ class TaskPositioner implements DimLayer.DimLayerUser {
|
||||
}
|
||||
|
||||
@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;
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.view.WindowManagerPolicy.PointerEventListener;
|
||||
|
||||
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;
|
||||
@@ -44,6 +45,13 @@ public class TaskTapPointerEventListener implements PointerEventListener {
|
||||
mDisplayContent = displayContent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointerEvent(MotionEvent motionEvent, int displayId) {
|
||||
if (displayId == getDisplayId()) {
|
||||
onPointerEvent(motionEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPointerEvent(MotionEvent motionEvent) {
|
||||
final int action = motionEvent.getAction();
|
||||
@@ -104,4 +112,8 @@ public class TaskTapPointerEventListener implements PointerEventListener {
|
||||
mTouchExcludeRegion.set(newRegion);
|
||||
}
|
||||
}
|
||||
|
||||
private int getDisplayId() {
|
||||
return mDisplayContent.getDisplayId();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
|
||||
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 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
|
||||
final private KeyguardDisableHandler mKeyguardDisableHandler;
|
||||
boolean mKeyguardGoingAway;
|
||||
// VR Vr2d Display Id.
|
||||
int mVr2dDisplayId = INVALID_DISPLAY;
|
||||
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
@@ -764,7 +767,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInputEvent(InputEvent event) {
|
||||
public void onInputEvent(InputEvent event, int displayId) {
|
||||
boolean handled = false;
|
||||
try {
|
||||
if (mDragState == null) {
|
||||
@@ -7542,6 +7545,16 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
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) {
|
||||
|
||||
@@ -2038,7 +2038,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
super(inputChannel, mService.mH.getLooper());
|
||||
}
|
||||
@Override
|
||||
public void onInputEvent(InputEvent event) {
|
||||
public void onInputEvent(InputEvent event, int displayId) {
|
||||
finishInputEvent(event, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,10 +31,13 @@ import org.junit.Test;
|
||||
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 @@ public class DisplayContentTests extends WindowTestsBase {
|
||||
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 @@ public class DisplayContentTests extends WindowTestsBase {
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ package com.android.server.wm;
|
||||
|
||||
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.IBinder;
|
||||
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 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
|
||||
}).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;
|
||||
|
||||
Reference in New Issue
Block a user