Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f83e8242 authored by Selim Cinek's avatar Selim Cinek
Browse files

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
parent 0e2d3f2f
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -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.
+7 −10
Original line number Diff line number Diff line
@@ -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.
+40 −38
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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
+15 −23
Original line number Diff line number Diff line
@@ -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.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();
Loading