diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 7976ca424506d..f0c86e52d4a30 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -218,7 +218,7 @@ public interface WindowManager extends ViewManager { @ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR, to = "TYPE_NAVIGATION_BAR"), @ViewDebug.IntToString(from = TYPE_VOLUME_OVERLAY, to = "TYPE_VOLUME_OVERLAY"), @ViewDebug.IntToString(from = TYPE_BOOT_PROGRESS, to = "TYPE_BOOT_PROGRESS"), - @ViewDebug.IntToString(from = TYPE_HIDDEN_NAV_CONSUMER, to = "TYPE_HIDDEN_NAV_CONSUMER"), + @ViewDebug.IntToString(from = TYPE_INPUT_CONSUMER, to = "TYPE_INPUT_CONSUMER"), @ViewDebug.IntToString(from = TYPE_DREAM, to = "TYPE_DREAM"), @ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR_PANEL, to = "TYPE_NAVIGATION_BAR_PANEL"), @ViewDebug.IntToString(from = TYPE_DISPLAY_OVERLAY, to = "TYPE_DISPLAY_OVERLAY"), @@ -490,12 +490,11 @@ public interface WindowManager extends ViewManager { public static final int TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21; /** - * Window type: Fake window to consume touch events when the navigation - * bar is hidden. + * Window type to consume input events when the systemUI bars are hidden. * In multiuser systems shows on all users' windows. * @hide */ - public static final int TYPE_HIDDEN_NAV_CONSUMER = FIRST_SYSTEM_WINDOW+22; + public static final int TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW+22; /** * Window type: Dreams (screen saver) window, just above keyguard. diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 9199af1041be8..1b759a33de561 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -373,12 +373,12 @@ public interface WindowManagerPolicy { } /** - * Representation of a "fake window" that the policy has added to the - * window manager to consume events. + * Representation of a input consumer that the policy has added to the + * window manager to consume input events going to windows below it. */ - public interface FakeWindow { + public interface InputConsumer { /** - * Remove the fake window from the window manager. + * Remove the input consumer from the window manager. */ void dismiss(); } @@ -402,13 +402,10 @@ public interface WindowManagerPolicy { public void reevaluateStatusBarVisibility(); /** - * Add a fake window to the window manager. This window sits - * at the top of the other windows and consumes events. + * Add a input consumer which will consume all input events going to any window below it. */ - public FakeWindow addFakeWindow(Looper looper, - InputEventReceiver.Factory inputEventReceiverFactory, - String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags, - boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen); + public InputConsumer addInputConsumer(Looper looper, + InputEventReceiver.Factory inputEventReceiverFactory); /** * Returns a code that describes the current state of the lid switch. diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index a4e9c6808899a..9bb5e404a9071 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -51,7 +51,6 @@ import android.media.IAudioService; import android.media.Ringtone; import android.media.RingtoneManager; import android.media.session.MediaSessionLegacyHelper; -import android.os.Build; import android.os.Bundle; import android.os.Debug; import android.os.FactoryTest; @@ -97,7 +96,6 @@ import com.android.internal.policy.PhoneWindow; import android.view.Surface; import android.view.View; import android.view.ViewConfiguration; -import android.view.ViewRootImpl; import android.view.Window; import android.view.WindowManager; import android.view.WindowManagerGlobal; @@ -458,7 +456,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // menu needs to be displayed. boolean mLastFocusNeedsMenu = false; - FakeWindow mHideNavFakeWindow = null; + InputConsumer mInputConsumer = null; static final Rect mTmpParentFrame = new Rect(); static final Rect mTmpDisplayFrame = new Rect(); @@ -1817,7 +1815,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { case TYPE_APPLICATION_STARTING: case TYPE_BOOT_PROGRESS: case TYPE_DISPLAY_OVERLAY: - case TYPE_HIDDEN_NAV_CONSUMER: + case TYPE_INPUT_CONSUMER: case TYPE_KEYGUARD_SCRIM: case TYPE_KEYGUARD_DIALOG: case TYPE_MAGNIFICATION_OVERLAY: @@ -1942,75 +1940,75 @@ public class PhoneWindowManager implements WindowManagerPolicy { case TYPE_VOICE_INTERACTION: // voice interaction layer is almost immediately above apps. return 5; - case TYPE_SYSTEM_DIALOG: + case TYPE_INPUT_CONSUMER: return 6; + case TYPE_SYSTEM_DIALOG: + return 7; case TYPE_TOAST: // toasts and the plugged-in battery thing - return 7; + return 8; case TYPE_PRIORITY_PHONE: // SIM errors and unlock. Not sure if this really should be in a high layer. - return 8; + return 9; case TYPE_DREAM: // used for Dreams (screensavers with TYPE_DREAM windows) - return 9; + return 10; case TYPE_SYSTEM_ALERT: // like the ANR / app crashed dialogs - return 10; + return 11; case TYPE_INPUT_METHOD: // on-screen keyboards and other such input method user interfaces go here. - return 11; + return 12; case TYPE_INPUT_METHOD_DIALOG: // on-screen keyboards and other such input method user interfaces go here. - return 12; + return 13; case TYPE_KEYGUARD_SCRIM: // the safety window that shows behind keyguard while keyguard is starting - return 13; - case TYPE_STATUS_BAR_SUB_PANEL: return 14; - case TYPE_STATUS_BAR: + case TYPE_STATUS_BAR_SUB_PANEL: return 15; - case TYPE_STATUS_BAR_PANEL: + case TYPE_STATUS_BAR: return 16; - case TYPE_KEYGUARD_DIALOG: + case TYPE_STATUS_BAR_PANEL: return 17; + case TYPE_KEYGUARD_DIALOG: + return 18; case TYPE_VOLUME_OVERLAY: // the on-screen volume indicator and controller shown when the user // changes the device volume - return 18; + return 19; case TYPE_SYSTEM_OVERLAY: // the on-screen volume indicator and controller shown when the user // changes the device volume - return 19; + return 20; case TYPE_NAVIGATION_BAR: // the navigation bar, if available, shows atop most things - return 20; + return 21; case TYPE_NAVIGATION_BAR_PANEL: // some panels (e.g. search) need to show on top of the navigation bar - return 21; + return 22; case TYPE_SYSTEM_ERROR: // system-level error dialogs - return 22; + return 23; case TYPE_MAGNIFICATION_OVERLAY: // used to highlight the magnified portion of a display - return 23; + return 24; case TYPE_DISPLAY_OVERLAY: // used to simulate secondary display devices - return 24; + return 25; case TYPE_DRAG: // the drag layer: input for drag-and-drop is associated with this window, // which sits above all other focusable windows - return 25; + return 26; case TYPE_ACCESSIBILITY_OVERLAY: // overlay put by accessibility services to intercept user interaction - return 26; - case TYPE_SECURE_SYSTEM_OVERLAY: return 27; - case TYPE_BOOT_PROGRESS: + case TYPE_SECURE_SYSTEM_OVERLAY: return 28; + case TYPE_BOOT_PROGRESS: + return 29; case TYPE_POINTER: // the (mouse) pointer layer - return 29; - case TYPE_HIDDEN_NAV_CONSUMER: return 30; } Log.e(TAG, "Unknown window type: " + type); @@ -3385,15 +3383,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { // detect when the user presses anywhere to bring back the nav // bar and ensure the application doesn't see the event. if (navVisible || navAllowedHidden) { - if (mHideNavFakeWindow != null) { - mHideNavFakeWindow.dismiss(); - mHideNavFakeWindow = null; + if (mInputConsumer != null) { + mInputConsumer.dismiss(); + mInputConsumer = null; } - } else if (mHideNavFakeWindow == null) { - mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow( - mHandler.getLooper(), mHideNavInputEventReceiverFactory, - "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER, 0, - 0, false, false, true); + } else if (mInputConsumer == null) { + mInputConsumer = mWindowManagerFuncs.addInputConsumer(mHandler.getLooper(), + mHideNavInputEventReceiverFactory); } // For purposes of positioning and showing the nav bar, if we have @@ -6311,7 +6307,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { vis = mNavigationBarController.applyTranslucentFlagLw(transWin, vis, oldVis); // prevent status bar interaction from clearing certain flags - boolean statusBarHasFocus = win.getAttrs().type == TYPE_STATUS_BAR; + int type = win.getAttrs().type; + boolean statusBarHasFocus = type == TYPE_STATUS_BAR; if (statusBarHasFocus && !isStatusBarKeyguard()) { int flags = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION @@ -6323,6 +6320,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { } vis = (vis & ~flags) | (oldVis & flags); } + if (windowTypeToLayerLw(type) > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) { + // We can't get into fullscreen from this window otherwise the consumer would not get + // the input events. + vis = (vis & ~View.SYSTEM_UI_FLAG_FULLSCREEN); + } if (!areTranslucentBarsAllowed() && transWin != mStatusBar) { vis &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSLUCENT diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java index 482ae2420729c..66ae9ef82f3e8 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/InputConsumerImpl.java similarity index 77% rename from services/core/java/com/android/server/wm/FakeWindowImpl.java rename to services/core/java/com/android/server/wm/InputConsumerImpl.java index 1136cedcc0a59..0581a165a3743 100644 --- a/services/core/java/com/android/server/wm/FakeWindowImpl.java +++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java @@ -16,17 +16,18 @@ 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.WindowManager; import android.view.WindowManagerPolicy; -public final class FakeWindowImpl implements WindowManagerPolicy.FakeWindow { +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; @@ -34,12 +35,9 @@ public final class FakeWindowImpl implements WindowManagerPolicy.FakeWindow { 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) { + public InputConsumerImpl(WindowManagerService service, Looper looper, + InputEventReceiver.Factory inputEventReceiverFactory) { + String name = "input consumer"; mService = service; InputChannel[] channels = InputChannel.openInputChannelPair(name); @@ -58,31 +56,25 @@ public final class FakeWindowImpl implements WindowManagerPolicy.FakeWindow { mWindowHandle = new InputWindowHandle(mApplicationHandle, null, Display.DEFAULT_DISPLAY); mWindowHandle.name = name; mWindowHandle.inputChannel = mServerChannel; - mWindowLayer = getLayerLw(windowType); + mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; + mWindowLayer = getLayerLw(mWindowHandle.layoutParamsType); mWindowHandle.layer = mWindowLayer; - mWindowHandle.layoutParamsFlags = layoutParamsFlags; - mWindowHandle.layoutParamsType = windowType; + mWindowHandle.layoutParamsFlags = 0; mWindowHandle.dispatchingTimeoutNanos = WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS; mWindowHandle.visible = true; - mWindowHandle.canReceiveKeys = canReceiveKeys; - mWindowHandle.hasFocus = hasFocus; + 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; - - mTouchFullscreen = touchFullscreen; } void layout(int dw, int dh) { - if (mTouchFullscreen) { - mWindowHandle.touchableRegion.set(0, 0, dw, dh); - } else { - mWindowHandle.touchableRegion.setEmpty(); - } + mWindowHandle.touchableRegion.set(0, 0, dw, dh); mWindowHandle.frameLeft = 0; mWindowHandle.frameTop = 0; mWindowHandle.frameRight = dw; @@ -92,7 +84,7 @@ public final class FakeWindowImpl implements WindowManagerPolicy.FakeWindow { @Override public void dismiss() { synchronized (mService.mWindowMap) { - if (mService.removeFakeWindowLocked(this)) { + if (mService.removeInputConsumer()) { mInputEventReceiver.dispose(); mService.mInputManager.unregisterInputChannel(mServerChannel); mClientChannel.dispose(); diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index c24fcb3e7501f..ae442e5f8610a 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 d956d76fc4816..cebb909e5678d 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