Fix WM input limitations on secondary displays (1/N)
- One DisplayContent include one InputMonitor.
- For customized inputconsumers, they can be handled by DisplayContent.
- Extract InputManagerCallback to communicated InputManagerService.
- All windows need pass displayId to InputWindowHandle.
Bug: 111363643
Test: atest WindowManagerSmokeTest
Test: atest DisplayContentTests
Change-Id: Iaaca7d135a11c55a78bcf1f81918599b3d160106
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b6222bb..8ef1196 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4669,7 +4669,8 @@
} else if (mInputConsumer == null && mStatusBar != null && canHideNavigationBar()) {
mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(),
INPUT_CONSUMER_NAVIGATION,
- (channel, looper) -> new HideNavInputEventReceiver(channel, looper));
+ (channel, looper) -> new HideNavInputEventReceiver(channel, looper),
+ displayFrames.mDisplayId);
// As long as mInputConsumer is active, hover events are not dispatched to the app
// and the pointer icon is likely to become stale. Hide it to avoid confusion.
InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_NULL);
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 45ce36b..0060328 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -525,7 +525,7 @@
* Add a input consumer which will consume all input events going to any window below it.
*/
public InputConsumer createInputConsumer(Looper looper, String name,
- InputEventReceiver.Factory inputEventReceiverFactory);
+ InputEventReceiver.Factory inputEventReceiverFactory, int displayId);
/**
* Returns a code that describes the current state of the lid switch.
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 4f15c5d..36280dd 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -648,7 +648,7 @@
public void pauseKeyDispatching() {
synchronized (mWindowMap) {
if (mContainer != null) {
- mService.mInputMonitor.pauseDispatchingLw(mContainer);
+ mContainer.getDisplayContent().getInputMonitor().pauseDispatchingLw(mContainer);
}
}
}
@@ -656,7 +656,7 @@
public void resumeKeyDispatching() {
synchronized (mWindowMap) {
if (mContainer != null) {
- mService.mInputMonitor.resumeDispatchingLw(mContainer);
+ mContainer.getDisplayContent().getInputMonitor().resumeDispatchingLw(mContainer);
}
}
}
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index d9ddf9f..4b8b6074 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -449,13 +449,13 @@
+ ": hidden=" + isHidden() + " hiddenRequested=" + hiddenRequested);
if (changed) {
- mService.mInputMonitor.setUpdateInputWindowsNeededLw();
+ getDisplayContent().getInputMonitor().setUpdateInputWindowsNeededLw();
if (performLayout) {
mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
false /*updateInputWindows*/);
mService.mWindowPlacerLocked.performSurfacePlacement();
}
- mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
+ getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
}
}
@@ -677,7 +677,7 @@
if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this);
mService.mFocusedApp = null;
mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
- mService.mInputMonitor.setFocusedAppLw(null);
+ getDisplayContent().getInputMonitor().setFocusedAppLw(null);
}
if (!delayed) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 31c0bdd..aa52b44 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -401,6 +401,8 @@
private MagnificationSpec mMagnificationSpec;
+ private InputMonitor mInputMonitor;
+
private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
WindowStateAnimator winAnimator = w.mWinAnimator;
final AppWindowToken atoken = w.mAppToken;
@@ -798,6 +800,8 @@
// TODO(b/62541591): evaluate whether this is the best spot to declare the
// {@link DisplayContent} ready for use.
mDisplayReady = true;
+
+ mInputMonitor = new InputMonitor(service, mDisplayId);
}
boolean isReady() {
@@ -2362,6 +2366,8 @@
pw.println();
mDisplayFrames.dump(prefix, pw);
+ pw.println();
+ mInputMonitor.dump(pw, " ");
}
@Override
@@ -2472,9 +2478,9 @@
assignWindowLayers(false /* setLayoutNeeded */);
}
- mService.mInputMonitor.setUpdateInputWindowsNeededLw();
+ mInputMonitor.setUpdateInputWindowsNeededLw();
mService.mWindowPlacerLocked.performSurfacePlacement();
- mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
+ mInputMonitor.updateInputWindowsLw(false /*force*/);
}
/** Returns true if a leaked surface was destroyed */
@@ -3057,10 +3063,10 @@
forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */);
// Window frames may have changed. Tell the input dispatcher about it.
- mService.mInputMonitor.layoutInputConsumers(dw, dh);
- mService.mInputMonitor.setUpdateInputWindowsNeededLw();
+ mInputMonitor.layoutInputConsumers(dw, dh);
+ mInputMonitor.setUpdateInputWindowsNeededLw();
if (updateInputWindows) {
- mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
+ mInputMonitor.updateInputWindowsLw(false /*force*/);
}
mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER);
@@ -4107,4 +4113,8 @@
private boolean canUpdateImeTarget() {
return mDeferUpdateImeTargetCount == 0;
}
+
+ InputMonitor getInputMonitor() {
+ return mInputMonitor;
+ }
}
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index d4046e9..5483602 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -143,7 +143,7 @@
mDragDropController.sendHandlerMessage(
MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT, mInputInterceptor);
mInputInterceptor = null;
- mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+ mDisplayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
}
// Send drag end broadcast if drag start has been sent.
@@ -296,7 +296,7 @@
Slog.e(TAG_WM, "Duplicate register of drag input channel");
} else {
mInputInterceptor = new InputInterceptor(display);
- mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+ mDisplayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
}
}
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index d40db8c..6a08f4d 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -40,7 +40,7 @@
final UserHandle mClientUser;
InputConsumerImpl(WindowManagerService service, IBinder token, String name,
- InputChannel inputChannel, int clientPid, UserHandle clientUser) {
+ InputChannel inputChannel, int clientPid, UserHandle clientUser, int displayId) {
mService = service;
mToken = token;
mName = name;
@@ -63,8 +63,7 @@
mApplicationHandle.dispatchingTimeoutNanos =
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
- mWindowHandle = new InputWindowHandle(mApplicationHandle, null, null,
- Display.DEFAULT_DISPLAY);
+ mWindowHandle = new InputWindowHandle(mApplicationHandle, null, null, displayId);
mWindowHandle.name = name;
mWindowHandle.inputChannel = mServerChannel;
mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
@@ -128,7 +127,9 @@
public void binderDied() {
synchronized (mService.getWindowManagerLock()) {
// Clean up the input consumer
- mService.mInputMonitor.destroyInputConsumer(mName);
+ final InputMonitor inputMonitor =
+ mService.mRoot.getDisplayContent(mWindowHandle.displayId).getInputMonitor();
+ inputMonitor.destroyInputConsumer(mName);
unlinkFromDeathRecipient();
}
}
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
new file mode 100644
index 0000000..016921d
--- /dev/null
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -0,0 +1,278 @@
+package com.android.server.wm;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.app.ActivityManager;
+import android.os.Debug;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.KeyEvent;
+import android.view.WindowManager;
+
+import com.android.server.input.InputApplicationHandle;
+import com.android.server.input.InputManagerService;
+import com.android.server.input.InputWindowHandle;
+
+import java.io.PrintWriter;
+
+final class InputManagerCallback implements InputManagerService.WindowManagerCallbacks {
+ private final WindowManagerService mService;
+
+ // Set to true when the first input device configuration change notification
+ // is received to indicate that the input devices are ready.
+ private final Object mInputDevicesReadyMonitor = new Object();
+ private boolean mInputDevicesReady;
+
+ // When true, prevents input dispatch from proceeding until set to false again.
+ private boolean mInputDispatchFrozen;
+
+ // The reason the input is currently frozen or null if the input isn't frozen.
+ private String mInputFreezeReason = null;
+
+ // When true, input dispatch proceeds normally. Otherwise all events are dropped.
+ // Initially false, so that input does not get dispatched until boot is finished at
+ // which point the ActivityManager will enable dispatching.
+ private boolean mInputDispatchEnabled;
+
+ public InputManagerCallback(WindowManagerService service) {
+ mService = service;
+ }
+
+ /**
+ * Notifies the window manager about a broken input channel.
+ *
+ * Called by the InputManager.
+ */
+ @Override
+ public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
+ if (inputWindowHandle == null) {
+ return;
+ }
+
+ synchronized (mService.mWindowMap) {
+ WindowState windowState = (WindowState) inputWindowHandle.windowState;
+ if (windowState != null) {
+ Slog.i(TAG_WM, "WINDOW DIED " + windowState);
+ windowState.removeIfPossible();
+ }
+ }
+ }
+
+ /**
+ * Notifies the window manager about an application that is not responding.
+ * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch.
+ *
+ * Called by the InputManager.
+ */
+ @Override
+ public long notifyANR(InputApplicationHandle inputApplicationHandle,
+ InputWindowHandle inputWindowHandle, String reason) {
+ AppWindowToken appWindowToken = null;
+ WindowState windowState = null;
+ boolean aboveSystem = false;
+ synchronized (mService.mWindowMap) {
+ if (inputWindowHandle != null) {
+ windowState = (WindowState) inputWindowHandle.windowState;
+ if (windowState != null) {
+ appWindowToken = windowState.mAppToken;
+ }
+ }
+ if (appWindowToken == null && inputApplicationHandle != null) {
+ appWindowToken = (AppWindowToken)inputApplicationHandle.appWindowToken;
+ }
+
+ if (windowState != null) {
+ Slog.i(TAG_WM, "Input event dispatching timed out "
+ + "sending to " + windowState.mAttrs.getTitle()
+ + ". Reason: " + reason);
+ // Figure out whether this window is layered above system windows.
+ // We need to do this here to help the activity manager know how to
+ // layer its ANR dialog.
+ int systemAlertLayer = mService.mPolicy.getWindowLayerFromTypeLw(
+ TYPE_APPLICATION_OVERLAY, windowState.mOwnerCanAddInternalSystemWindow);
+ aboveSystem = windowState.mBaseLayer > systemAlertLayer;
+ } else if (appWindowToken != null) {
+ Slog.i(TAG_WM, "Input event dispatching timed out "
+ + "sending to application " + appWindowToken.stringName
+ + ". Reason: " + reason);
+ } else {
+ Slog.i(TAG_WM, "Input event dispatching timed out "
+ + ". Reason: " + reason);
+ }
+
+ mService.saveANRStateLocked(appWindowToken, windowState, reason);
+ }
+
+ // All the calls below need to happen without the WM lock held since they call into AM.
+ mService.mAmInternal.saveANRState(reason);
+
+ if (appWindowToken != null && appWindowToken.appToken != null) {
+ // Notify the activity manager about the timeout and let it decide whether
+ // to abort dispatching or keep waiting.
+ final AppWindowContainerController controller = appWindowToken.getController();
+ final boolean abort = controller != null
+ && controller.keyDispatchingTimedOut(reason,
+ (windowState != null) ? windowState.mSession.mPid : -1);
+ if (!abort) {
+ // The activity manager declined to abort dispatching.
+ // Wait a bit longer and timeout again later.
+ return appWindowToken.mInputDispatchingTimeoutNanos;
+ }
+ } else if (windowState != null) {
+ try {
+ // Notify the activity manager about the timeout and let it decide whether
+ // to abort dispatching or keep waiting.
+ long timeout = ActivityManager.getService().inputDispatchingTimedOut(
+ windowState.mSession.mPid, aboveSystem, reason);
+ if (timeout >= 0) {
+ // The activity manager declined to abort dispatching.
+ // Wait a bit longer and timeout again later.
+ return timeout * 1000000L; // nanoseconds
+ }
+ } catch (RemoteException ex) {
+ }
+ }
+ return 0; // abort dispatching
+ }
+
+ /** Notifies that the input device configuration has changed. */
+ @Override
+ public void notifyConfigurationChanged() {
+ // TODO(multi-display): Notify proper displays that are associated with this input device.
+ mService.sendNewConfiguration(DEFAULT_DISPLAY);
+
+ synchronized (mInputDevicesReadyMonitor) {
+ if (!mInputDevicesReady) {
+ mInputDevicesReady = true;
+ mInputDevicesReadyMonitor.notifyAll();
+ }
+ }
+ }
+
+ /** Notifies that the lid switch changed state. */
+ @Override
+ public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
+ mService.mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
+ }
+
+ /** Notifies that the camera lens cover state has changed. */
+ @Override
+ public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
+ mService.mPolicy.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
+ }
+
+ /**
+ * Provides an opportunity for the window manager policy to intercept early key
+ * processing as soon as the key has been read from the device.
+ */
+ @Override
+ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
+ return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
+ }
+
+ /**
+ * Provides an opportunity for the window manager policy to intercept early motion event
+ * processing when the device is in a non-interactive state since these events are normally
+ * dropped.
+ */
+ @Override
+ public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
+ return mService.mPolicy.interceptMotionBeforeQueueingNonInteractive(
+ whenNanos, policyFlags);
+ }
+
+ /**
+ * Provides an opportunity for the window manager policy to process a key before
+ * ordinary dispatch.
+ */
+ @Override
+ public long interceptKeyBeforeDispatching(
+ InputWindowHandle focus, KeyEvent event, int policyFlags) {
+ WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
+ return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
+ }
+
+ /**
+ * Provides an opportunity for the window manager policy to process a key that
+ * the application did not handle.
+ */
+ @Override
+ public KeyEvent dispatchUnhandledKey(
+ InputWindowHandle focus, KeyEvent event, int policyFlags) {
+ WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
+ return mService.mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
+ }
+
+ /** Callback to get pointer layer. */
+ @Override
+ public int getPointerLayer() {
+ return mService.mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_POINTER)
+ * WindowManagerService.TYPE_LAYER_MULTIPLIER
+ + WindowManagerService.TYPE_LAYER_OFFSET;
+ }
+
+ /** Waits until the built-in input devices have been configured. */
+ public boolean waitForInputDevicesReady(long timeoutMillis) {
+ synchronized (mInputDevicesReadyMonitor) {
+ if (!mInputDevicesReady) {
+ try {
+ mInputDevicesReadyMonitor.wait(timeoutMillis);
+ } catch (InterruptedException ex) {
+ }
+ }
+ return mInputDevicesReady;
+ }
+ }
+
+ public void freezeInputDispatchingLw() {
+ if (!mInputDispatchFrozen) {
+ if (DEBUG_INPUT) {
+ Slog.v(TAG_WM, "Freezing input dispatching");
+ }
+
+ mInputDispatchFrozen = true;
+
+ if (DEBUG_INPUT) {
+ mInputFreezeReason = Debug.getCallers(6);
+ }
+ updateInputDispatchModeLw();
+ }
+ }
+
+ public void thawInputDispatchingLw() {
+ if (mInputDispatchFrozen) {
+ if (DEBUG_INPUT) {
+ Slog.v(TAG_WM, "Thawing input dispatching");
+ }
+
+ mInputDispatchFrozen = false;
+ mInputFreezeReason = null;
+ updateInputDispatchModeLw();
+ }
+ }
+
+ public void setEventDispatchingLw(boolean enabled) {
+ if (mInputDispatchEnabled != enabled) {
+ if (DEBUG_INPUT) {
+ Slog.v(TAG_WM, "Setting event dispatching to " + enabled);
+ }
+
+ mInputDispatchEnabled = enabled;
+ updateInputDispatchModeLw();
+ }
+ }
+
+ private void updateInputDispatchModeLw() {
+ mService.mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen);
+ }
+
+ void dump(PrintWriter pw, String prefix) {
+ if (mInputFreezeReason != null) {
+ pw.println(prefix + "mInputFreezeReason=" + mInputFreezeReason);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 8ab4651..d53a21b 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
import static android.view.WindowManager.INPUT_CONSUMER_PIP;
import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
@@ -24,7 +23,6 @@
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
@@ -33,13 +31,10 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import android.app.ActivityManager;
import android.graphics.Rect;
-import android.os.Debug;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
-import android.os.RemoteException;
import android.os.Trace;
import android.os.UserHandle;
import android.util.ArrayMap;
@@ -47,11 +42,8 @@
import android.util.Slog;
import android.view.InputChannel;
import android.view.InputEventReceiver;
-import android.view.KeyEvent;
-import android.view.WindowManager;
import com.android.server.input.InputApplicationHandle;
-import com.android.server.input.InputManagerService;
import com.android.server.input.InputWindowHandle;
import com.android.server.policy.WindowManagerPolicy;
@@ -60,23 +52,12 @@
import java.util.Set;
import java.util.function.Consumer;
-final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
+final class InputMonitor {
private final WindowManagerService mService;
// Current window with input focus for keys and other non-touch events. May be null.
private WindowState mInputFocus;
- // When true, prevents input dispatch from proceeding until set to false again.
- private boolean mInputDispatchFrozen;
-
- // The reason the input is currently frozen or null if the input isn't frozen.
- private String mInputFreezeReason = null;
-
- // When true, input dispatch proceeds normally. Otherwise all events are dropped.
- // Initially false, so that input does not get dispatched until boot is finished at
- // which point the ActivityManager will enable dispatching.
- private boolean mInputDispatchEnabled;
-
// When true, need to call updateInputWindowsLw().
private boolean mUpdateInputWindowsNeeded = true;
@@ -85,19 +66,12 @@
private int mInputWindowHandleCount;
private InputWindowHandle mFocusedInputWindowHandle;
- private boolean mAddInputConsumerHandle;
- private boolean mAddPipInputConsumerHandle;
- private boolean mAddWallpaperInputConsumerHandle;
- private boolean mAddRecentsAnimationInputConsumerHandle;
private boolean mDisableWallpaperTouchEvents;
private final Rect mTmpRect = new Rect();
private final UpdateInputForAllWindowsConsumer mUpdateInputForAllWindowsConsumer =
new UpdateInputForAllWindowsConsumer();
- // Set to true when the first input device configuration change notification
- // is received to indicate that the input devices are ready.
- private final Object mInputDevicesReadyMonitor = new Object();
- private boolean mInputDevicesReady;
+ private int mDisplayId;
/**
* The set of input consumer added to the window manager by name, which consumes input events
@@ -113,8 +87,9 @@
EventReceiverInputConsumer(WindowManagerService service, InputMonitor monitor,
Looper looper, String name,
InputEventReceiver.Factory inputEventReceiverFactory,
- int clientPid, UserHandle clientUser) {
- super(service, null /* token */, name, null /* inputChannel */, clientPid, clientUser);
+ int clientPid, UserHandle clientUser, int displayId) {
+ super(service, null /* token */, name, null /* inputChannel */, clientPid, clientUser,
+ displayId);
mInputMonitor = monitor;
mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver(
mClientChannel, looper);
@@ -130,8 +105,9 @@
}
}
- public InputMonitor(WindowManagerService service) {
+ public InputMonitor(WindowManagerService service, int displayId) {
mService = service;
+ mDisplayId = displayId;
}
private void addInputConsumer(String name, InputConsumerImpl consumer) {
@@ -156,9 +132,8 @@
return false;
}
- InputConsumerImpl getInputConsumer(String name, int displayId) {
- // TODO(multi-display): Allow input consumers on non-default displays?
- return (displayId == DEFAULT_DISPLAY) ? mInputConsumers.get(name) : null;
+ InputConsumerImpl getInputConsumer(String name) {
+ return mInputConsumers.get(name);
}
void layoutInputConsumers(int dw, int dh) {
@@ -170,12 +145,12 @@
WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name,
InputEventReceiver.Factory inputEventReceiverFactory) {
if (mInputConsumers.containsKey(name)) {
- throw new IllegalStateException("Existing input consumer found with name: " + name);
+ throw new IllegalStateException("Existing input consumer found with name: " + name
+ + ", display: " + mDisplayId);
}
-
final EventReceiverInputConsumer consumer = new EventReceiverInputConsumer(mService,
this, looper, name, inputEventReceiverFactory, Process.myPid(),
- UserHandle.SYSTEM);
+ UserHandle.SYSTEM, mDisplayId);
addInputConsumer(name, consumer);
return consumer;
}
@@ -183,11 +158,12 @@
void createInputConsumer(IBinder token, String name, InputChannel inputChannel, int clientPid,
UserHandle clientUser) {
if (mInputConsumers.containsKey(name)) {
- throw new IllegalStateException("Existing input consumer found with name: " + name);
+ throw new IllegalStateException("Existing input consumer found with name: " + name
+ + ", display: " + mDisplayId);
}
final InputConsumerImpl consumer = new InputConsumerImpl(mService, token, name,
- inputChannel, clientPid, clientUser);
+ inputChannel, clientPid, clientUser, mDisplayId);
switch (name) {
case INPUT_CONSUMER_WALLPAPER:
consumer.mWindowHandle.hasWallpaper = true;
@@ -201,100 +177,6 @@
addInputConsumer(name, consumer);
}
- /* Notifies the window manager about a broken input channel.
- *
- * Called by the InputManager.
- */
- @Override
- public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
- if (inputWindowHandle == null) {
- return;
- }
-
- synchronized (mService.mWindowMap) {
- WindowState windowState = (WindowState) inputWindowHandle.windowState;
- if (windowState != null) {
- Slog.i(TAG_WM, "WINDOW DIED " + windowState);
- windowState.removeIfPossible();
- }
- }
- }
-
- /* Notifies the window manager about an application that is not responding.
- * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch.
- *
- * Called by the InputManager.
- */
- @Override
- public long notifyANR(InputApplicationHandle inputApplicationHandle,
- InputWindowHandle inputWindowHandle, String reason) {
- AppWindowToken appWindowToken = null;
- WindowState windowState = null;
- boolean aboveSystem = false;
- synchronized (mService.mWindowMap) {
- if (inputWindowHandle != null) {
- windowState = (WindowState) inputWindowHandle.windowState;
- if (windowState != null) {
- appWindowToken = windowState.mAppToken;
- }
- }
- if (appWindowToken == null && inputApplicationHandle != null) {
- appWindowToken = (AppWindowToken)inputApplicationHandle.appWindowToken;
- }
-
- if (windowState != null) {
- Slog.i(TAG_WM, "Input event dispatching timed out "
- + "sending to " + windowState.mAttrs.getTitle()
- + ". Reason: " + reason);
- // Figure out whether this window is layered above system windows.
- // We need to do this here to help the activity manager know how to
- // layer its ANR dialog.
- int systemAlertLayer = mService.mPolicy.getWindowLayerFromTypeLw(
- TYPE_APPLICATION_OVERLAY, windowState.mOwnerCanAddInternalSystemWindow);
- aboveSystem = windowState.mBaseLayer > systemAlertLayer;
- } else if (appWindowToken != null) {
- Slog.i(TAG_WM, "Input event dispatching timed out "
- + "sending to application " + appWindowToken.stringName
- + ". Reason: " + reason);
- } else {
- Slog.i(TAG_WM, "Input event dispatching timed out "
- + ". Reason: " + reason);
- }
-
- mService.saveANRStateLocked(appWindowToken, windowState, reason);
- }
-
- // All the calls below need to happen without the WM lock held since they call into AM.
- mService.mAmInternal.saveANRState(reason);
-
- if (appWindowToken != null && appWindowToken.appToken != null) {
- // Notify the activity manager about the timeout and let it decide whether
- // to abort dispatching or keep waiting.
- final AppWindowContainerController controller = appWindowToken.getController();
- final boolean abort = controller != null
- && controller.keyDispatchingTimedOut(reason,
- (windowState != null) ? windowState.mSession.mPid : -1);
- if (!abort) {
- // The activity manager declined to abort dispatching.
- // Wait a bit longer and timeout again later.
- return appWindowToken.mInputDispatchingTimeoutNanos;
- }
- } else if (windowState != null) {
- try {
- // Notify the activity manager about the timeout and let it decide whether
- // to abort dispatching or keep waiting.
- long timeout = ActivityManager.getService().inputDispatchingTimedOut(
- windowState.mSession.mPid, aboveSystem, reason);
- if (timeout >= 0) {
- // The activity manager declined to abort dispatching.
- // Wait a bit longer and timeout again later.
- return timeout * 1000000L; // nanoseconds
- }
- } catch (RemoteException ex) {
- }
- }
- return 0; // abort dispatching
- }
private void addInputWindowHandle(final InputWindowHandle windowHandle) {
if (mInputWindowHandles == null) {
@@ -325,6 +207,7 @@
inputWindowHandle.ownerPid = child.mSession.mPid;
inputWindowHandle.ownerUid = child.mSession.mUid;
inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures;
+ inputWindowHandle.displayId = child.getDisplayId();
final Rect frame = child.getFrameLw();
inputWindowHandle.frameLeft = frame.left;
@@ -414,87 +297,6 @@
if (false) Slog.d(TAG_WM, "<<<<<<< EXITED updateInputWindowsLw");
}
- /* Notifies that the input device configuration has changed. */
- @Override
- public void notifyConfigurationChanged() {
- // TODO(multi-display): Notify proper displays that are associated with this input device.
- mService.sendNewConfiguration(DEFAULT_DISPLAY);
-
- synchronized (mInputDevicesReadyMonitor) {
- if (!mInputDevicesReady) {
- mInputDevicesReady = true;
- mInputDevicesReadyMonitor.notifyAll();
- }
- }
- }
-
- /* Waits until the built-in input devices have been configured. */
- public boolean waitForInputDevicesReady(long timeoutMillis) {
- synchronized (mInputDevicesReadyMonitor) {
- if (!mInputDevicesReady) {
- try {
- mInputDevicesReadyMonitor.wait(timeoutMillis);
- } catch (InterruptedException ex) {
- }
- }
- return mInputDevicesReady;
- }
- }
-
- /* Notifies that the lid switch changed state. */
- @Override
- public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
- mService.mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
- }
-
- /* Notifies that the camera lens cover state has changed. */
- @Override
- public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
- mService.mPolicy.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
- }
-
- /* Provides an opportunity for the window manager policy to intercept early key
- * processing as soon as the key has been read from the device. */
- @Override
- public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
- return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
- }
-
- /* Provides an opportunity for the window manager policy to intercept early motion event
- * processing when the device is in a non-interactive state since these events are normally
- * dropped. */
- @Override
- public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
- return mService.mPolicy.interceptMotionBeforeQueueingNonInteractive(
- whenNanos, policyFlags);
- }
-
- /* Provides an opportunity for the window manager policy to process a key before
- * ordinary dispatch. */
- @Override
- public long interceptKeyBeforeDispatching(
- InputWindowHandle focus, KeyEvent event, int policyFlags) {
- WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
- return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
- }
-
- /* Provides an opportunity for the window manager policy to process a key that
- * the application did not handle. */
- @Override
- public KeyEvent dispatchUnhandledKey(
- InputWindowHandle focus, KeyEvent event, int policyFlags) {
- WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
- return mService.mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
- }
-
- /* Callback to get pointer layer. */
- @Override
- public int getPointerLayer() {
- return mService.mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_POINTER)
- * WindowManagerService.TYPE_LAYER_MULTIPLIER
- + WindowManagerService.TYPE_LAYER_OFFSET;
- }
-
/* Called when the current input focus changes.
* Layer assignment is assumed to be complete by the time this is called.
*/
@@ -555,52 +357,7 @@
}
}
- public void freezeInputDispatchingLw() {
- if (!mInputDispatchFrozen) {
- if (DEBUG_INPUT) {
- Slog.v(TAG_WM, "Freezing input dispatching");
- }
-
- mInputDispatchFrozen = true;
-
- if (DEBUG_INPUT || true) {
- mInputFreezeReason = Debug.getCallers(6);
- }
- updateInputDispatchModeLw();
- }
- }
-
- public void thawInputDispatchingLw() {
- if (mInputDispatchFrozen) {
- if (DEBUG_INPUT) {
- Slog.v(TAG_WM, "Thawing input dispatching");
- }
-
- mInputDispatchFrozen = false;
- mInputFreezeReason = null;
- updateInputDispatchModeLw();
- }
- }
-
- public void setEventDispatchingLw(boolean enabled) {
- if (mInputDispatchEnabled != enabled) {
- if (DEBUG_INPUT) {
- Slog.v(TAG_WM, "Setting event dispatching to " + enabled);
- }
-
- mInputDispatchEnabled = enabled;
- updateInputDispatchModeLw();
- }
- }
-
- private void updateInputDispatchModeLw() {
- mService.mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen);
- }
-
void dump(PrintWriter pw, String prefix) {
- if (mInputFreezeReason != null) {
- pw.println(prefix + "mInputFreezeReason=" + mInputFreezeReason);
- }
final Set<String> inputConsumerKeys = mInputConsumers.keySet();
if (!inputConsumerKeys.isEmpty()) {
pw.println(prefix + "InputConsumers:");
@@ -611,40 +368,46 @@
}
private final class UpdateInputForAllWindowsConsumer implements Consumer<WindowState> {
-
InputConsumerImpl navInputConsumer;
InputConsumerImpl pipInputConsumer;
InputConsumerImpl wallpaperInputConsumer;
InputConsumerImpl recentsAnimationInputConsumer;
+
+ private boolean mAddInputConsumerHandle;
+ private boolean mAddPipInputConsumerHandle;
+ private boolean mAddWallpaperInputConsumerHandle;
+ private boolean mAddRecentsAnimationInputConsumerHandle;
+
boolean inDrag;
WallpaperController wallpaperController;
private void updateInputWindows(boolean inDrag) {
-
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "updateInputWindows");
- // TODO: multi-display
- navInputConsumer = getInputConsumer(INPUT_CONSUMER_NAVIGATION, DEFAULT_DISPLAY);
- pipInputConsumer = getInputConsumer(INPUT_CONSUMER_PIP, DEFAULT_DISPLAY);
- wallpaperInputConsumer = getInputConsumer(INPUT_CONSUMER_WALLPAPER, DEFAULT_DISPLAY);
- recentsAnimationInputConsumer = getInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION,
- DEFAULT_DISPLAY);
+ navInputConsumer = getInputConsumer(INPUT_CONSUMER_NAVIGATION);
+ pipInputConsumer = getInputConsumer(INPUT_CONSUMER_PIP);
+ wallpaperInputConsumer = getInputConsumer(INPUT_CONSUMER_WALLPAPER);
+ recentsAnimationInputConsumer = getInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION);
+
mAddInputConsumerHandle = navInputConsumer != null;
mAddPipInputConsumerHandle = pipInputConsumer != null;
mAddWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
mAddRecentsAnimationInputConsumerHandle = recentsAnimationInputConsumer != null;
+
mTmpRect.setEmpty();
mDisableWallpaperTouchEvents = false;
this.inDrag = inDrag;
wallpaperController = mService.mRoot.mWallpaperController;
- mService.mRoot.forAllWindows(this, true /* traverseTopToBottom */);
+ mService.mRoot.getDisplayContent(mDisplayId).forAllWindows(this,
+ true /* traverseTopToBottom */);
if (mAddWallpaperInputConsumerHandle) {
// No visible wallpaper found, add the wallpaper input consumer at the end.
addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
}
// Send windows to native code.
+ // TODO: Update Input windows and focus by display?
mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle);
clearInputWindowHandlesLw();
@@ -674,7 +437,7 @@
if (recentsAnimationController != null
&& recentsAnimationController.hasInputConsumerForApp(w.mAppToken)) {
if (recentsAnimationController.updateInputConsumerForApp(
- recentsAnimationInputConsumer, hasFocus)) {
+ recentsAnimationInputConsumer.mWindowHandle, hasFocus)) {
addInputWindowHandle(recentsAnimationInputConsumer.mWindowHandle);
mAddRecentsAnimationInputConsumerHandle = false;
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 6f5fea9..3a0cc28 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -53,6 +53,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
+import com.android.server.input.InputWindowHandle;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
import com.android.server.wm.utils.InsetUtils;
@@ -201,7 +202,9 @@
}
mInputConsumerEnabled = enabled;
- mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+ final InputMonitor inputMonitor =
+ mService.mRoot.getDisplayContent(mDisplayId).getInputMonitor();
+ inputMonitor.updateInputWindowsLw(true /*force*/);
mService.scheduleAnimationLocked();
}
} finally {
@@ -438,8 +441,10 @@
mCanceled = true;
// Clear associated input consumers
- mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
- mService.destroyInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION);
+ final InputMonitor inputMonitor =
+ mService.mRoot.getDisplayContent(mDisplayId).getInputMonitor();
+ inputMonitor.destroyInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION);
+ inputMonitor.updateInputWindowsLw(true /*force*/);
// We have deferred all notifications to the target app as a part of the recents animation,
// so if we are actually transitioning there, notify again here
@@ -497,7 +502,7 @@
return mInputConsumerEnabled && isAnimatingApp(appToken);
}
- boolean updateInputConsumerForApp(InputConsumerImpl recentsAnimationInputConsumer,
+ boolean updateInputConsumerForApp(InputWindowHandle inputWindowHandle,
boolean hasFocus) {
// Update the input consumer touchable region to match the target app main window
final WindowState targetAppMainWindow = mTargetAppToken != null
@@ -505,8 +510,8 @@
: null;
if (targetAppMainWindow != null) {
targetAppMainWindow.getBounds(mTmpRect);
- recentsAnimationInputConsumer.mWindowHandle.hasFocus = hasFocus;
- recentsAnimationInputConsumer.mWindowHandle.touchableRegion.set(mTmpRect);
+ inputWindowHandle.hasFocus = hasFocus;
+ inputWindowHandle.touchableRegion.set(mTmpRect);
return true;
}
return false;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 2be4001..3df4eb7 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -724,7 +724,9 @@
}
// Finally update all input windows now that the window changes have stabilized.
- mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+ forAllDisplays(dc -> {
+ dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
+ });
mService.setHoldScreenLocked(mHoldScreen);
if (!mService.mDisplayFrozen) {
@@ -784,7 +786,9 @@
}
if (updateInputWindowsNeeded) {
- mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
+ forAllDisplays(dc -> {
+ dc.getInputMonitor().updateInputWindowsLw(false /*force*/);
+ });
}
mService.setFocusTaskRegionLocked(null);
if (touchExcludeRegionUpdateDisplays != null) {
@@ -1091,4 +1095,15 @@
void scheduleAnimation() {
mService.scheduleAnimationLocked();
}
+
+ /**
+ * For all display at or below this call the callback.
+ *
+ * @param callback Callback to be called for every display.
+ */
+ void forAllDisplays(Consumer<DisplayContent> callback) {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ callback.accept(mChildren.get(i));
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index bd7e61c..8effc6b 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -209,6 +209,7 @@
// Post back to WM to handle clean-ups. We still need the input
// event handler for the last finishInputEvent()!
mService.mTaskPositioningController.finishTaskPositioning();
+ mTask.getDisplayContent().getInputMonitor().updateInputWindowsLw(true /*force*/);
}
handled = true;
} catch (Exception e) {
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index 7d36650..9cdc6b7 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -38,7 +38,6 @@
class TaskPositioningController {
private final WindowManagerService mService;
private final InputManagerService mInputManager;
- private final InputMonitor mInputMonitor;
private final IActivityTaskManager mActivityManager;
private final Handler mHandler;
@@ -54,9 +53,8 @@
}
TaskPositioningController(WindowManagerService service, InputManagerService inputManager,
- InputMonitor inputMonitor, IActivityTaskManager activityManager, Looper looper) {
+ IActivityTaskManager activityManager, Looper looper) {
mService = service;
- mInputMonitor = inputMonitor;
mInputManager = inputManager;
mActivityManager = activityManager;
mHandler = new Handler(looper);
@@ -129,7 +127,7 @@
Display display = displayContent.getDisplay();
mTaskPositioner = TaskPositioner.create(mService);
mTaskPositioner.register(displayContent);
- mInputMonitor.updateInputWindowsLw(true /*force*/);
+ displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
// We need to grab the touch focus so that the touch events during the
// resizing/scrolling are not sent to the app. 'win' is the main window
@@ -145,7 +143,7 @@
Slog.e(TAG_WM, "startPositioningLocked: Unable to transfer touch focus");
mTaskPositioner.unregister();
mTaskPositioner = null;
- mInputMonitor.updateInputWindowsLw(true /*force*/);
+ displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
return false;
}
@@ -161,7 +159,6 @@
if (mTaskPositioner != null) {
mTaskPositioner.unregister();
mTaskPositioner = null;
- mInputMonitor.updateInputWindowsLw(true /*force*/);
}
}
});
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 06a1968..9b792e3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -269,6 +269,8 @@
import java.util.Arrays;
import java.util.Date;
import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
/** {@hide} */
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
@@ -1073,7 +1075,7 @@
com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
mTaskPositioningController = new TaskPositioningController(
- this, mInputManager, mInputMonitor, mActivityTaskManager, mH.getLooper());
+ this, mInputManager, mActivityTaskManager, mH.getLooper());
mDragDropController = new DragDropController(this, mH.getLooper());
LocalServices.addService(WindowManagerInternal.class, new LocalService());
@@ -1099,9 +1101,8 @@
showEmulatorDisplayOverlayIfNeeded();
}
-
- public InputMonitor getInputMonitor() {
- return mInputMonitor;
+ public InputManagerCallback getInputManagerCallback() {
+ return mInputManagerCallback;
}
@Override
@@ -1489,7 +1490,7 @@
res |= WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
}
- mInputMonitor.setUpdateInputWindowsNeededLw();
+ displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
boolean focusChanged = false;
if (win.canReceiveKeys()) {
@@ -1509,9 +1510,10 @@
win.getParent().assignChildLayers();
if (focusChanged) {
- mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
+ displayContent.getInputMonitor().setInputFocusLw(mCurrentFocus,
+ false /*updateInputWindows*/);
}
- mInputMonitor.updateInputWindowsLw(false /*force*/);
+ displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "addWindow: New client "
+ client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5));
@@ -1724,7 +1726,7 @@
}
}
- mInputMonitor.updateInputWindowsLw(true /*force*/);
+ dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
}
void setInputMethodWindowLocked(WindowState win) {
@@ -2043,7 +2045,7 @@
try {
result = createSurfaceControl(outSurface, result, win, winAnimator);
} catch (Exception e) {
- mInputMonitor.updateInputWindowsLw(true /*force*/);
+ win.getDisplayContent().getInputMonitor().updateInputWindowsLw(true /*force*/);
Slog.w(TAG_WM, "Exception thrown when creating surface for client "
+ client + " (" + win.mAttrs.getTitle() + ")",
@@ -2377,7 +2379,7 @@
return;
}
- mInputMonitor.updateInputWindowsLw(true /*force*/);
+ dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -2566,7 +2568,7 @@
if (changed) {
AppWindowToken prev = mFocusedApp;
mFocusedApp = newFocus;
- mInputMonitor.setFocusedAppLw(newFocus);
+ mFocusedApp.getDisplayContent().getInputMonitor().setFocusedAppLw(newFocus);
setFocusTaskRegionLocked(prev);
}
@@ -3474,7 +3476,7 @@
if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM, "******************** ENABLING SCREEN!");
// Enable input dispatch.
- mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);
+ mInputManagerCallback.setEventDispatchingLw(mEventDispatchingEnabled);
}
try {
@@ -4421,7 +4423,7 @@
// Input Events and Focus Management
// -------------------------------------------------------------
- final InputMonitor mInputMonitor = new InputMonitor(this);
+ final InputManagerCallback mInputManagerCallback = new InputManagerCallback(this);
private boolean mEventDispatchingEnabled;
@Override
@@ -4433,7 +4435,7 @@
synchronized (mWindowMap) {
mEventDispatchingEnabled = enabled;
if (mDisplayEnabled) {
- mInputMonitor.setEventDispatchingLw(enabled);
+ mInputManagerCallback.setEventDispatchingLw(enabled);
}
}
}
@@ -4458,7 +4460,7 @@
}
public boolean detectSafeMode() {
- if (!mInputMonitor.waitForInputDevicesReady(
+ if (!mInputManagerCallback.waitForInputDevicesReady(
INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
Slog.w(TAG_WM, "Devices still not ready after waiting "
+ INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
@@ -5712,7 +5714,7 @@
if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
// If we defer assigning layers, then the caller is responsible for
// doing this part.
- mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
+ displayContent.getInputMonitor().setInputFocusLw(mCurrentFocus, updateInputWindows);
}
displayContent.adjustForImeIfNeeded();
@@ -5759,7 +5761,7 @@
// As a result, we only track the display that has initially froze the screen.
mFrozenDisplayId = displayContent.getDisplayId();
- mInputMonitor.freezeInputDispatchingLw();
+ mInputManagerCallback.freezeInputDispatchingLw();
// Clear the last input window -- that is just used for
// clean transitions between IMEs, and if we are freezing
@@ -5825,7 +5827,7 @@
final int displayId = mFrozenDisplayId;
mFrozenDisplayId = INVALID_DISPLAY;
mDisplayFrozen = false;
- mInputMonitor.thawInputDispatchingLw();
+ mInputManagerCallback.thawInputDispatchingLw();
mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
StringBuilder sb = new StringBuilder(128);
sb.append("Screen frozen for ");
@@ -6065,24 +6067,38 @@
@Override
public WindowManagerPolicy.InputConsumer createInputConsumer(Looper looper, String name,
- InputEventReceiver.Factory inputEventReceiverFactory) {
+ InputEventReceiver.Factory inputEventReceiverFactory, int displayId) {
synchronized (mWindowMap) {
- return mInputMonitor.createInputConsumer(looper, name, inputEventReceiverFactory);
+ DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+ if (displayContent != null) {
+ return displayContent.getInputMonitor().createInputConsumer(looper, name,
+ inputEventReceiverFactory);
+ } else {
+ return null;
+ }
}
}
@Override
public void createInputConsumer(IBinder token, String name, InputChannel inputChannel) {
synchronized (mWindowMap) {
- mInputMonitor.createInputConsumer(token, name, inputChannel, Binder.getCallingPid(),
- Binder.getCallingUserHandle());
+ mRoot.forAllDisplays(dc -> {
+ dc.getInputMonitor().createInputConsumer(token, name, inputChannel,
+ Binder.getCallingPid(), Binder.getCallingUserHandle());
+ });
}
}
@Override
public boolean destroyInputConsumer(String name) {
synchronized (mWindowMap) {
- return mInputMonitor.destroyInputConsumer(name);
+ AtomicBoolean retValue = new AtomicBoolean(true);
+ mRoot.forAllDisplays(dc -> {
+ if (!dc.getInputMonitor().destroyInputConsumer(name)) {
+ retValue.set(false);
+ }
+ });
+ return retValue.get();
}
}
@@ -6426,7 +6442,7 @@
pw.print(" mLastWakeLockObscuringWindow="); pw.print(mLastWakeLockObscuringWindow);
pw.println();
- mInputMonitor.dump(pw, " ");
+ mInputManagerCallback.dump(pw, " ");
mUnknownAppVisibilityController.dump(pw, " ");
mTaskSnapshotController.dump(pw, " ");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 06ffd5e..6385229 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2025,7 +2025,7 @@
// Set up a replacement input channel since the app is now dead.
// We need to catch tapping on the dead window to restart the app.
openInputChannel(null);
- mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
+ getDisplayContent().getInputMonitor().updateInputWindowsLw(true /*force*/);
return;
}
@@ -2092,7 +2092,7 @@
UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
mService.mWindowPlacerLocked.performSurfacePlacement();
if (focusChanged) {
- mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
+ getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 86c5175..4017b70 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -903,7 +903,7 @@
}
traceBeginAndSlog("StartInputManager");
- inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
+ inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
inputManager.start();
traceEnd();