diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 7af4a1fea441d..5bcf1027f3848 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -400,4 +400,14 @@ interface IWindowManager * @hide */ void registerShortcutKey(in long shortcutCode, IShortcutService keySubscriber); + + /** + * Create the input consumer for wallpaper events. + */ + void createWallpaperInputConsumer(out InputChannel inputChannel); + + /** + * Remove the input consumer for wallpaper events. + */ + void removeWallpaperInputConsumer(); } diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java index 0581a165a3743..24783bccf3d5b 100644 --- a/services/core/java/com/android/server/wm/InputConsumerImpl.java +++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java @@ -16,38 +16,33 @@ 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 { +class InputConsumerImpl { 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"; + InputConsumerImpl(WindowManagerService service, String name, InputChannel inputChannel) { mService = service; InputChannel[] channels = InputChannel.openInputChannelPair(name); mServerChannel = channels[0]; - mClientChannel = channels[1]; + if (inputChannel != null) { + channels[1].transferTo(inputChannel); + channels[1].dispose(); + mClientChannel = inputChannel; + } else { + mClientChannel = channels[1]; + } mService.mInputManager.registerInputChannel(mServerChannel, null); - mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver( - mClientChannel, looper); - mApplicationHandle = new InputApplicationHandle(null); mApplicationHandle.name = name; mApplicationHandle.dispatchingTimeoutNanos = @@ -57,8 +52,7 @@ public final class InputConsumerImpl implements WindowManagerPolicy.InputConsume mWindowHandle.name = name; mWindowHandle.inputChannel = mServerChannel; mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; - mWindowLayer = getLayerLw(mWindowHandle.layoutParamsType); - mWindowHandle.layer = mWindowLayer; + mWindowHandle.layer = getLayerLw(mWindowHandle.layoutParamsType); mWindowHandle.layoutParamsFlags = 0; mWindowHandle.dispatchingTimeoutNanos = WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; @@ -81,21 +75,15 @@ public final class InputConsumerImpl implements WindowManagerPolicy.InputConsume 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; } + + void disposeChannelsLw() { + mService.mInputManager.unregisterInputChannel(mServerChannel); + mClientChannel.dispose(); + mServerChannel.dispose(); + } } diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index b70218059b74b..eea0e73c1b0ba 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -282,6 +282,8 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { boolean addInputConsumerHandle = mService.mInputConsumer != null; + boolean addWallpaperInputConsumerHandle = mService.mWallpaperInputConsumer != null; + // Add all windows on the default display. final int numDisplays = mService.mDisplayContents.size(); final WallpaperController wallpaperController = mService.mWallpaperControllerLocked; @@ -302,6 +304,14 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { addInputConsumerHandle = false; } + if (addWallpaperInputConsumerHandle) { + if (child.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER) { + // Add the wallpaper input consumer above the first wallpaper window. + addInputWindowHandleLw(mService.mWallpaperInputConsumer.mWindowHandle); + addWallpaperInputConsumerHandle = false; + } + } + final int flags = child.mAttrs.flags; final int privateFlags = child.mAttrs.privateFlags; final int type = child.mAttrs.type; @@ -329,6 +339,11 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { } } + if (addWallpaperInputConsumerHandle) { + // No wallpaper found, add the wallpaper input consumer at the end. + addInputWindowHandleLw(mService.mWallpaperInputConsumer.mWindowHandle); + } + // Send windows to native code. mService.mInputManager.setInputWindows(mInputWindowHandles); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 97c4c42dfd5d3..dcb4a63a560ae 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -406,6 +406,11 @@ public class WindowManagerService extends IWindowManager.Stub */ InputConsumerImpl mInputConsumer; + /** + * The input consumer added to the window manager before all wallpaper windows. + */ + InputConsumerImpl mWallpaperInputConsumer; + /** * Windows that are being resized. Used so we can tell the client about * the resize after closing the transaction in which we resized the @@ -9624,13 +9629,37 @@ public class WindowManagerService extends IWindowManager.Stub } } + private static final class HideNavInputConsumer extends InputConsumerImpl + implements WindowManagerPolicy.InputConsumer { + private final InputEventReceiver mInputEventReceiver; + + HideNavInputConsumer(WindowManagerService service, Looper looper, + InputEventReceiver.Factory inputEventReceiverFactory) { + super(service, "input consumer", null); + mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver( + mClientChannel, looper); + } + + @Override + public void dismiss() { + if (mService.removeInputConsumer()) { + synchronized (mService.mWindowMap) { + mInputEventReceiver.dispose(); + disposeChannelsLw(); + } + } + } + } + @Override - public InputConsumerImpl addInputConsumer(Looper looper, + public WindowManagerPolicy.InputConsumer addInputConsumer(Looper looper, InputEventReceiver.Factory inputEventReceiverFactory) { synchronized (mWindowMap) { - mInputConsumer = new InputConsumerImpl(this, looper, inputEventReceiverFactory); + HideNavInputConsumer inputConsumerImpl = new HideNavInputConsumer( + this, looper, inputEventReceiverFactory); + mInputConsumer = inputConsumerImpl; mInputMonitor.updateInputWindowsLw(true); - return mInputConsumer; + return inputConsumerImpl; } } @@ -9645,6 +9674,24 @@ public class WindowManagerService extends IWindowManager.Stub } } + public void createWallpaperInputConsumer(InputChannel inputChannel) { + synchronized (mWindowMap) { + mWallpaperInputConsumer = new InputConsumerImpl(this, "wallpaper input", inputChannel); + mWallpaperInputConsumer.mWindowHandle.hasWallpaper = true; + mInputMonitor.updateInputWindowsLw(true); + } + } + + public void removeWallpaperInputConsumer() { + synchronized (mWindowMap) { + if (mWallpaperInputConsumer != null) { + mWallpaperInputConsumer.disposeChannelsLw(); + mWallpaperInputConsumer = null; + mInputMonitor.updateInputWindowsLw(true); + } + } + } + @Override public boolean hasNavigationBar() { return mPolicy.hasNavigationBar(); diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index 3e5ddbce5a7b3..eda2f39480a8d 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -860,6 +860,10 @@ class WindowSurfacePlacer { mService.mInputConsumer.layout(dw, dh); } + if (mService.mWallpaperInputConsumer != null) { + mService.mWallpaperInputConsumer.layout(dw, dh); + } + final int N = windows.size(); int i;