Fix WM input limitations on secondary displays (3/4)
One DisplayContent contains one InputMonitor now.
- Change setInputWindow of InputManagerService updated by displayId,
so Window Handles in InputDispather can be updated by each DisplayContent.
- Only exist one focus in current state, reset it if in removed DisplayContent,
will be updated by default display or focused display.
- Add displayId parameter for createInputConsumer and destroyInputConsumer,
so InputConsumer from PIP, RecentApp and Wallpaper can be supported in multi-display.
Bug: 111363643
Test: atest WindowManagerSmokeTest ActivityManagerMultiDisplayTests
Test: atest com.android.server.wm.DisplayContentTests
Test: atest libinput_tests inputflinger_tests
Change-Id: I999c355be1789af5759f00206475d004e10116e3
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ba46737..82c1808 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -814,9 +814,7 @@
// {@link DisplayContent} ready for use.
mDisplayReady = true;
- // TODO(b/112081256): Use independent InputMonitor.
- mInputMonitor = isDefaultDisplay ? new InputMonitor(service, mDisplayId)
- : mService.getDefaultDisplayContentLocked().mInputMonitor;
+ mInputMonitor = new InputMonitor(service, mDisplayId);
}
boolean isReady() {
@@ -2180,6 +2178,7 @@
mRemovingDisplay = false;
}
+ mInputMonitor.onRemoved();
mService.onDisplayRemoved(mDisplayId);
}
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index 6a08f4d..585a4f5 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -20,9 +20,9 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.view.Display;
import android.view.InputChannel;
import android.view.WindowManager;
+
import com.android.server.input.InputApplicationHandle;
import com.android.server.input.InputWindowHandle;
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index c4beb55..3309798 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -367,6 +367,13 @@
}
}
+ void onRemoved() {
+ // If DisplayContent removed, we need find a way to remove window handles of this display
+ // from InputDispatcher, so pass an empty InputWindowHandles to remove them.
+ mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle,
+ mDisplayId);
+ }
+
private final class UpdateInputForAllWindowsConsumer implements Consumer<WindowState> {
InputConsumerImpl navInputConsumer;
InputConsumerImpl pipInputConsumer;
@@ -399,8 +406,7 @@
this.inDrag = inDrag;
wallpaperController = mService.mRoot.mWallpaperController;
- // TODO(b/112081256): Use independent InputMonitor for each display.
- mService.mRoot/*.getDisplayContent(mDisplayId)*/.forAllWindows(this,
+ mService.mRoot.getDisplayContent(mDisplayId).forAllWindows(this,
true /* traverseTopToBottom */);
if (mAddWallpaperInputConsumerHandle) {
// No visible wallpaper found, add the wallpaper input consumer at the end.
@@ -408,8 +414,8 @@
}
// Send windows to native code.
- // TODO: Update Input windows and focus by display?
- mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle);
+ mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle,
+ mDisplayId);
clearInputWindowHandlesLw();
@@ -429,7 +435,8 @@
final int flags = w.mAttrs.flags;
final int privateFlags = w.mAttrs.privateFlags;
final int type = w.mAttrs.type;
- final boolean hasFocus = w == mInputFocus;
+ // TODO(b/111361570): multi-display focus, one focus window per display.
+ final boolean hasFocus = w.isFocused();
final boolean isVisible = w.isVisibleLw();
if (mAddRecentsAnimationInputConsumerHandle) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index da77edf..50fe7e3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -6036,11 +6036,10 @@
}
@Override
- public void createInputConsumer(IBinder token, String name, InputChannel inputChannel) {
+ public void createInputConsumer(IBinder token, String name, int displayId,
+ InputChannel inputChannel) {
synchronized (mWindowMap) {
- // TODO(b/112049699): Fix this for multiple displays. There is only one inputChannel
- // here to accept the return value.
- DisplayContent display = mRoot.getDisplayContent(Display.DEFAULT_DISPLAY);
+ DisplayContent display = mRoot.getDisplayContent(displayId);
if (display != null) {
display.getInputMonitor().createInputConsumer(token, name, inputChannel,
Binder.getCallingPid(), Binder.getCallingUserHandle());
@@ -6049,11 +6048,9 @@
}
@Override
- public boolean destroyInputConsumer(String name) {
+ public boolean destroyInputConsumer(String name, int displayId) {
synchronized (mWindowMap) {
- // TODO(b/112049699): Fix this for multiple displays. For consistency with
- // createInputConsumer above.
- DisplayContent display = mRoot.getDisplayContent(Display.DEFAULT_DISPLAY);
+ DisplayContent display = mRoot.getDisplayContent(displayId);
if (display != null) {
return display.getInputMonitor().destroyInputConsumer(name);
}