From f83e824216435e45f36a3587e269888f791b2a01 Mon Sep 17 00:00:00 2001 From: Selim Cinek Date: Tue, 19 May 2015 18:08:14 -0700 Subject: Fixed that touches where incorrectly consumed when fullscreen The fake window that was added when View.SYSTEM_UI_FULL_SCREEN was set consumed all touches, even those going to the SystemUI and not just those of windows below. The input consumer is now correctly positioned in the window order to only capture the right touches. Clicks to the volume panel and the heads up now correctly go to the right place instead of just unhiding the SystemUI bars. Bug: 21089476 Change-Id: Ib53dfc0b33b70084ca607d0f044db30b6e6c91d6 --- .../android/server/wm/AccessibilityController.java | 2 +- .../java/com/android/server/wm/FakeWindowImpl.java | 109 --------------------- .../com/android/server/wm/InputConsumerImpl.java | 101 +++++++++++++++++++ .../java/com/android/server/wm/InputMonitor.java | 24 ++--- .../android/server/wm/WindowManagerService.java | 35 +++---- 5 files changed, 127 insertions(+), 144 deletions(-) delete mode 100644 services/core/java/com/android/server/wm/FakeWindowImpl.java create mode 100644 services/core/java/com/android/server/wm/InputConsumerImpl.java (limited to 'services/core/java/com/android/server/wm') diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index 482ae24..66ae9ef 100644 --- a/services/core/java/com/android/server/wm/AccessibilityController.java +++ b/services/core/java/com/android/server/wm/AccessibilityController.java @@ -1248,7 +1248,7 @@ final class AccessibilityController { && windowType != WindowManager.LayoutParams.TYPE_BOOT_PROGRESS && windowType != WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY && windowType != WindowManager.LayoutParams.TYPE_DRAG - && windowType != WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER + && windowType != WindowManager.LayoutParams.TYPE_INPUT_CONSUMER && windowType != WindowManager.LayoutParams.TYPE_POINTER && windowType != WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY && windowType != WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY diff --git a/services/core/java/com/android/server/wm/FakeWindowImpl.java b/services/core/java/com/android/server/wm/FakeWindowImpl.java deleted file mode 100644 index 1136ced..0000000 --- a/services/core/java/com/android/server/wm/FakeWindowImpl.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -import com.android.server.input.InputApplicationHandle; -import com.android.server.input.InputWindowHandle; - -import android.os.Looper; -import android.os.Process; -import android.view.Display; -import android.view.InputChannel; -import android.view.InputEventReceiver; -import android.view.WindowManagerPolicy; - -public final class FakeWindowImpl implements WindowManagerPolicy.FakeWindow { - final WindowManagerService mService; - final InputChannel mServerChannel, mClientChannel; - final InputApplicationHandle mApplicationHandle; - final InputWindowHandle mWindowHandle; - final InputEventReceiver mInputEventReceiver; - final int mWindowLayer; - - boolean mTouchFullscreen; - - public FakeWindowImpl(WindowManagerService service, - Looper looper, InputEventReceiver.Factory inputEventReceiverFactory, - String name, int windowType, int layoutParamsFlags, - boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) { - mService = service; - - InputChannel[] channels = InputChannel.openInputChannelPair(name); - mServerChannel = channels[0]; - mClientChannel = channels[1]; - mService.mInputManager.registerInputChannel(mServerChannel, null); - - mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver( - mClientChannel, looper); - - mApplicationHandle = new InputApplicationHandle(null); - mApplicationHandle.name = name; - mApplicationHandle.dispatchingTimeoutNanos = - WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; - - mWindowHandle = new InputWindowHandle(mApplicationHandle, null, Display.DEFAULT_DISPLAY); - mWindowHandle.name = name; - mWindowHandle.inputChannel = mServerChannel; - mWindowLayer = getLayerLw(windowType); - mWindowHandle.layer = mWindowLayer; - mWindowHandle.layoutParamsFlags = layoutParamsFlags; - mWindowHandle.layoutParamsType = windowType; - mWindowHandle.dispatchingTimeoutNanos = - WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; - mWindowHandle.visible = true; - mWindowHandle.canReceiveKeys = canReceiveKeys; - mWindowHandle.hasFocus = hasFocus; - mWindowHandle.hasWallpaper = false; - mWindowHandle.paused = false; - mWindowHandle.ownerPid = Process.myPid(); - mWindowHandle.ownerUid = Process.myUid(); - mWindowHandle.inputFeatures = 0; - mWindowHandle.scaleFactor = 1.0f; - - mTouchFullscreen = touchFullscreen; - } - - void layout(int dw, int dh) { - if (mTouchFullscreen) { - mWindowHandle.touchableRegion.set(0, 0, dw, dh); - } else { - mWindowHandle.touchableRegion.setEmpty(); - } - mWindowHandle.frameLeft = 0; - mWindowHandle.frameTop = 0; - mWindowHandle.frameRight = dw; - mWindowHandle.frameBottom = dh; - } - - @Override - public void dismiss() { - synchronized (mService.mWindowMap) { - if (mService.removeFakeWindowLocked(this)) { - mInputEventReceiver.dispose(); - mService.mInputManager.unregisterInputChannel(mServerChannel); - mClientChannel.dispose(); - mServerChannel.dispose(); - } - } - } - - private int getLayerLw(int windowType) { - return mService.mPolicy.windowTypeToLayerLw(windowType) - * WindowManagerService.TYPE_LAYER_MULTIPLIER - + WindowManagerService.TYPE_LAYER_OFFSET; - } -} diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java new file mode 100644 index 0000000..0581a16 --- /dev/null +++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import android.os.Looper; +import android.os.Process; +import android.view.Display; +import android.view.InputChannel; +import android.view.InputEventReceiver; +import android.view.WindowManager; +import android.view.WindowManagerPolicy; + +import com.android.server.input.InputApplicationHandle; +import com.android.server.input.InputWindowHandle; + +public final class InputConsumerImpl implements WindowManagerPolicy.InputConsumer { + final WindowManagerService mService; + final InputChannel mServerChannel, mClientChannel; + final InputApplicationHandle mApplicationHandle; + final InputWindowHandle mWindowHandle; + final InputEventReceiver mInputEventReceiver; + final int mWindowLayer; + + public InputConsumerImpl(WindowManagerService service, Looper looper, + InputEventReceiver.Factory inputEventReceiverFactory) { + String name = "input consumer"; + mService = service; + + InputChannel[] channels = InputChannel.openInputChannelPair(name); + mServerChannel = channels[0]; + mClientChannel = channels[1]; + mService.mInputManager.registerInputChannel(mServerChannel, null); + + mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver( + mClientChannel, looper); + + mApplicationHandle = new InputApplicationHandle(null); + mApplicationHandle.name = name; + mApplicationHandle.dispatchingTimeoutNanos = + WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; + + mWindowHandle = new InputWindowHandle(mApplicationHandle, null, Display.DEFAULT_DISPLAY); + mWindowHandle.name = name; + mWindowHandle.inputChannel = mServerChannel; + mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; + mWindowLayer = getLayerLw(mWindowHandle.layoutParamsType); + mWindowHandle.layer = mWindowLayer; + mWindowHandle.layoutParamsFlags = 0; + mWindowHandle.dispatchingTimeoutNanos = + WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; + mWindowHandle.visible = true; + mWindowHandle.canReceiveKeys = false; + mWindowHandle.hasFocus = false; + mWindowHandle.hasWallpaper = false; + mWindowHandle.paused = false; + mWindowHandle.ownerPid = Process.myPid(); + mWindowHandle.ownerUid = Process.myUid(); + mWindowHandle.inputFeatures = 0; + mWindowHandle.scaleFactor = 1.0f; + } + + void layout(int dw, int dh) { + mWindowHandle.touchableRegion.set(0, 0, dw, dh); + mWindowHandle.frameLeft = 0; + mWindowHandle.frameTop = 0; + mWindowHandle.frameRight = dw; + mWindowHandle.frameBottom = dh; + } + + @Override + public void dismiss() { + synchronized (mService.mWindowMap) { + if (mService.removeInputConsumer()) { + mInputEventReceiver.dispose(); + mService.mInputManager.unregisterInputChannel(mServerChannel); + mClientChannel.dispose(); + mServerChannel.dispose(); + } + } + } + + private int getLayerLw(int windowType) { + return mService.mPolicy.windowTypeToLayerLw(windowType) + * WindowManagerService.TYPE_LAYER_MULTIPLIER + + WindowManagerService.TYPE_LAYER_OFFSET; + } +} diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index c24fcb3..ae442e5 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -16,10 +16,6 @@ package com.android.server.wm; -import com.android.server.input.InputManagerService; -import com.android.server.input.InputApplicationHandle; -import com.android.server.input.InputWindowHandle; - import android.app.ActivityManagerNative; import android.graphics.Rect; import android.os.RemoteException; @@ -30,17 +26,21 @@ import android.view.InputChannel; 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.util.Arrays; final class InputMonitor implements InputManagerService.WindowManagerCallbacks { 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; - + // 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. @@ -256,10 +256,7 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { } } - final int NFW = mService.mFakeWindows.size(); - for (int i = 0; i < NFW; i++) { - addInputWindowHandleLw(mService.mFakeWindows.get(i).mWindowHandle); - } + boolean addInputConsumerHandle = mService.mInputConsumer != null; // Add all windows on the default display. final int numDisplays = mService.mDisplayContents.size(); @@ -273,6 +270,11 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { // Skip this window because it cannot possibly receive input. continue; } + if (addInputConsumerHandle + && inputWindowHandle.layer <= mService.mInputConsumer.mWindowHandle.layer) { + addInputWindowHandleLw(mService.mInputConsumer.mWindowHandle); + addInputConsumerHandle = false; + } final int flags = child.mAttrs.flags; final int privateFlags = child.mAttrs.privateFlags; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index d956d76..cebb909 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -108,7 +108,6 @@ import android.view.WindowManager.LayoutParams; import android.view.WindowManagerGlobal; import android.view.WindowManagerInternal; import android.view.WindowManagerPolicy; -import android.view.WindowManagerPolicy.FakeWindow; import android.view.WindowManagerPolicy.PointerEventListener; import android.view.animation.Animation; import android.view.animation.AnimationUtils; @@ -382,10 +381,10 @@ public class WindowManagerService extends IWindowManager.Stub final ArrayList mFinishedStarting = new ArrayList<>(); /** - * Fake windows added to the window manager. Note: ordered from top to - * bottom, opposite of mWindows. + * The input consumer added to the window manager which consumes input events to windows below + * it. */ - final ArrayList mFakeWindows = new ArrayList<>(); + InputConsumerImpl mInputConsumer; /** * Windows that are being resized. Used so we can tell the client about @@ -8966,9 +8965,8 @@ public class WindowManagerService extends IWindowManager.Stub final int dw = displayInfo.logicalWidth; final int dh = displayInfo.logicalHeight; - final int NFW = mFakeWindows.size(); - for (int i=0; i