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

Commit 8065f440 authored by chaviw's avatar chaviw
Browse files

Allow Windows in Display Overlays

Instead of display overlays being a SurfaceControl that can only have
child surfaces, it now is a WindowContainer that can have windows.
Specifically, windows with the type TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY
will be placed in the display overlays layer

This is the first step to allow window magnification to use real windows
on the display.

Test: go/wm-smoke
Bug: 136250281

Change-Id: Idad98db7a85f68ba49557c0efb83b9a1be089609
parent 0bfdf247
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -1105,6 +1105,13 @@ public interface WindowManager extends ViewManager {
         */
        public static final int TYPE_APPLICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 38;

        /**
         * Window type: Window for adding accessibility window magnification above other windows.
         * This will place the window in the overlay windows.
         * @hide
         */
        public static final int TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 39;

        /**
         * End of types of system windows.
         */
+1 −0
Original line number Diff line number Diff line
@@ -163,6 +163,7 @@ message DisplayContentProto {
    repeated IdentifierProto opening_apps = 17;
    repeated IdentifierProto closing_apps = 18;
    repeated IdentifierProto changing_apps = 19;
    repeated WindowTokenProto overlay_windows = 20;
}

/* represents DisplayFrames */
+6 −3
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.policy;

import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -876,13 +877,15 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
            case TYPE_ACCESSIBILITY_OVERLAY:
                // overlay put by accessibility services to intercept user interaction
                return  30;
            case TYPE_SECURE_SYSTEM_OVERLAY:
            case TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY:
                return 31;
            case TYPE_BOOT_PROGRESS:
            case TYPE_SECURE_SYSTEM_OVERLAY:
                return  32;
            case TYPE_BOOT_PROGRESS:
                return  33;
            case TYPE_POINTER:
                // the (mouse) pointer layer
                return  33;
                return  34;
            default:
                Slog.e("WindowManager", "Unknown window type: " + type);
                return APPLICATION_LAYER;
+208 −180
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
@@ -93,6 +94,7 @@ import static com.android.server.wm.DisplayContentProto.FOCUSED_APP;
import static com.android.server.wm.DisplayContentProto.ID;
import static com.android.server.wm.DisplayContentProto.IME_WINDOWS;
import static com.android.server.wm.DisplayContentProto.OPENING_APPS;
import static com.android.server.wm.DisplayContentProto.OVERLAY_WINDOWS;
import static com.android.server.wm.DisplayContentProto.PINNED_STACK_CONTROLLER;
import static com.android.server.wm.DisplayContentProto.ROTATION;
import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
@@ -240,7 +242,21 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    /** Unique identifier of this display. */
    private final int mDisplayId;

    /** The containers below are the only child containers the display can have. */
    /**
     * Most surfaces will be a child of this window. There are some special layers and windows
     * which are always on top of others and omitted from Screen-Magnification, for example the
     * strict mode flash or the magnification overlay itself. Those layers will be children of
     * {@link #mOverlayContainers} where mWindowContainers contains everything else.
     */
    private final WindowContainers mWindowContainers =
            new WindowContainers("mWindowContainers", mWmService);

    // Contains some special windows which are always on top of others and omitted from
    // Screen-Magnification, for example the WindowMagnification windows.
    private final NonAppWindowContainers mOverlayContainers =
            new NonAppWindowContainers("mOverlayContainers", mWmService);

    /** The containers below are the only child containers {@link #mWindowContainers} can have. */
    // Contains all window containers that are related to apps (Activities)
    private final TaskStackContainers mTaskStackContainers = new TaskStackContainers(mWmService);
    // Contains all non-app window containers that should be displayed above the app containers
@@ -260,7 +276,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo

    private WindowState mTmpWindow;
    private WindowState mTmpWindow2;
    private boolean mTmpRecoveringMemory;
    private boolean mUpdateImeTarget;
    private boolean mTmpInitial;
    private int mMaxUiWidth;
@@ -489,20 +504,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo

    private ScreenRotationAnimation mScreenRotationAnimation;

    /**
     * We organize all top-level Surfaces in to the following layers.
     * mOverlayLayer contains a few Surfaces which are always on top of others
     * and omitted from Screen-Magnification, for example the strict mode flash or
     * the magnification overlay itself.
     * {@link #mWindowingLayer} contains everything else.
     */
    private SurfaceControl mOverlayLayer;

    /**
     * See {@link #mOverlayLayer}
     */
    private SurfaceControl mWindowingLayer;

    /**
     * Sequence number for the current layout pass.
     */
@@ -910,24 +911,19 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                .setOpaque(true)
                .setContainerLayer();
        mSurfaceControl = b.setName("Root").setContainerLayer().build();
        mWindowingLayer = b.setName("Display Windows").setParent(mSurfaceControl).build();
        mOverlayLayer = b.setName("Display Overlays").setParent(mSurfaceControl).build();

        getPendingTransaction()
                .setLayer(mSurfaceControl, 0)
                .setLayerStack(mSurfaceControl, mDisplayId)
                .show(mSurfaceControl)
                .setLayer(mWindowingLayer, 0)
                .show(mWindowingLayer)
                .setLayer(mOverlayLayer, 1)
                .show(mOverlayLayer);
                .show(mSurfaceControl);
        getPendingTransaction().apply();

        // These are the only direct children we should ever have and they are permanent.
        super.addChild(mBelowAppWindowsContainers, null);
        super.addChild(mTaskStackContainers, null);
        super.addChild(mAboveAppWindowsContainers, null);
        super.addChild(mImeWindowsContainers, null);
        super.addChild(mWindowContainers, null);
        super.addChild(mOverlayContainers, null);

        mWindowContainers.addChildren();

        // Sets the display content for the children.
        onDisplayChanged(this);

@@ -1001,6 +997,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                case TYPE_INPUT_METHOD_DIALOG:
                    mImeWindowsContainers.addChild(token);
                    break;
                case TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY:
                    mOverlayContainers.addChild(token);
                    break;
                default:
                    mAboveAppWindowsContainers.addChild(token);
                    break;
@@ -1936,49 +1935,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        setWindowingMode(windowingMode);
    }

    /**
     * In split-screen mode we process the IME containers above the docked divider
     * rather than directly above their target.
     */
    private boolean skipTraverseChild(WindowContainer child) {
        if (child == mImeWindowsContainers && mInputMethodTarget != null
                && !hasSplitScreenPrimaryStack()) {
            return true;
        }
        return false;
    }

    @Override
    boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
        // Special handling so we can process IME windows with #forAllImeWindows above their IME
        // target, or here in order if there isn't an IME target.
        if (traverseTopToBottom) {
            for (int i = mChildren.size() - 1; i >= 0; --i) {
                final DisplayChildWindowContainer child = mChildren.get(i);
                if (skipTraverseChild(child)) {
                    continue;
                }

                if (child.forAllWindows(callback, traverseTopToBottom)) {
                    return true;
                }
            }
        } else {
            final int count = mChildren.size();
            for (int i = 0; i < count; i++) {
                final DisplayChildWindowContainer child = mChildren.get(i);
                if (skipTraverseChild(child)) {
                    continue;
                }

                if (child.forAllWindows(callback, traverseTopToBottom)) {
                    return true;
                }
            }
        }
        return false;
    }

    boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
        return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom);
    }
@@ -2383,8 +2339,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            mPointerEventDispatcher.dispose();
            setRotationAnimation(null);
            mWmService.mAnimator.removeDisplayLocked(mDisplayId);
            mWindowingLayer.release();
            mOverlayLayer.release();
            mInputMonitor.onDisplayRemoved();
            // TODO(display-merge): Remove cast
            mWmService.mDisplayNotificationController
@@ -2630,6 +2584,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            final WindowToken windowToken = mImeWindowsContainers.getChildAt(i);
            windowToken.dumpDebug(proto, IME_WINDOWS, logLevel);
        }
        for (int i = mOverlayContainers.getChildCount() - 1; i >= 0; --i) {
            final WindowToken windowToken = mOverlayContainers.getChildAt(i);
            windowToken.dumpDebug(proto, OVERLAY_WINDOWS, logLevel);
        }
        proto.write(DPI, mBaseDisplayDensity);
        mDisplayInfo.dumpDebug(proto, DISPLAY_INFO);
        proto.write(ROTATION, getRotation());
@@ -3223,7 +3181,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        // target app together.
        final boolean shouldAttachToDisplay = (mMagnificationSpec != null);
        final SurfaceControl newParent =
                shouldAttachToDisplay ? mWindowingLayer : computeImeParent();
                shouldAttachToDisplay ? mWindowContainers.getSurfaceControl() : computeImeParent();
        if (newParent != null) {
            getPendingTransaction().reparent(mImeWindowsContainers.mSurfaceControl, newParent);
            scheduleAnimation();
@@ -3248,7 +3206,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        }

        // Otherwise, we just attach it to the display.
        return mWindowingLayer;
        return mWindowContainers.getSurfaceControl();
    }

    boolean getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom) {
@@ -3591,8 +3549,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo

        mTmpApplySurfaceChangesTransactionState.reset();

        mTmpRecoveringMemory = recoveringMemory;

        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applyWindowSurfaceChanges");
        try {
            forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
@@ -4497,6 +4453,126 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        }
    }

    private class WindowContainers extends DisplayChildWindowContainer<WindowContainer> {
        private final String mName;

        WindowContainers(String name, WindowManagerService service) {
            super(service);
            mName = name;
        }

        @Override
        void assignChildLayers(SurfaceControl.Transaction t) {
            mBelowAppWindowsContainers.assignLayer(t, 0);
            mTaskStackContainers.assignLayer(t, 1);
            mAboveAppWindowsContainers.assignLayer(t, 2);

            final WindowState imeTarget = mInputMethodTarget;
            boolean needAssignIme = true;

            // In the case where we have an IME target that is not in split-screen mode IME
            // assignment is easy. We just need the IME to go directly above the target. This way
            // children of the target will naturally go above the IME and everyone is happy.
            //
            // In the case of split-screen windowing mode, we need to elevate the IME above the
            // docked divider while keeping the app itself below the docked divider, so instead
            // we use relative layering of the IME targets child windows, and place the IME in
            // the non-app layer (see {@link AboveAppWindowContainers#assignChildLayers}).
            //
            // In the case the IME target is animating, the animation Z order may be different
            // than the WindowContainer Z order, so it's difficult to be sure we have the correct
            // IME target. In this case we just layer the IME over all transitions by placing it
            // in the above applications layer.
            //
            // In the case where we have no IME target we assign it where its base layer would
            // place it in the AboveAppWindowContainers.
            //
            // Keep IME window in mAboveAppWindowsContainers as long as app's starting window
            // exists so it get's layered above the starting window.
            if (imeTarget != null && !(imeTarget.mActivityRecord != null
                    && imeTarget.mActivityRecord.hasStartingWindow()) && (
                    !(imeTarget.inSplitScreenWindowingMode()
                            || imeTarget.mToken.isAppTransitioning()) && (
                            imeTarget.getSurfaceControl() != null))) {
                mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
                        // TODO: We need to use an extra level on the app surface to ensure
                        // this is always above SurfaceView but always below attached window.
                        1);
                needAssignIme = false;
            }

            // Above we have assigned layers to our children, now we ask them to assign
            // layers to their children.
            mBelowAppWindowsContainers.assignChildLayers(t);
            mTaskStackContainers.assignChildLayers(t);
            mAboveAppWindowsContainers.assignChildLayers(t,
                    needAssignIme ? mImeWindowsContainers : null);
            mImeWindowsContainers.assignChildLayers(t);
        }

        @Override
        String getName() {
            return mName;
        }

        void addChildren() {
            addChild(mBelowAppWindowsContainers, null);
            addChild(mTaskStackContainers, null);
            addChild(mAboveAppWindowsContainers, null);
            addChild(mImeWindowsContainers, null);
        }

        /**
         * In split-screen mode we process the IME containers above the docked divider
         * rather than directly above their target.
         */
        private boolean skipTraverseChild(WindowContainer child) {
            return child == mImeWindowsContainers && mInputMethodTarget != null
                    && !hasSplitScreenPrimaryStack();
        }

        @Override
        boolean forAllWindows(ToBooleanFunction<WindowState> callback,
                boolean traverseTopToBottom) {
            // Special handling so we can process IME windows with #forAllImeWindows above their IME
            // target, or here in order if there isn't an IME target.
            if (traverseTopToBottom) {
                for (int i = mChildren.size() - 1; i >= 0; --i) {
                    final WindowContainer child = mChildren.get(i);
                    if (skipTraverseChild(child)) {
                        continue;
                    }

                    if (child.forAllWindows(callback, traverseTopToBottom)) {
                        return true;
                    }
                }
            } else {
                final int count = mChildren.size();
                for (int i = 0; i < count; i++) {
                    Slog.d(TAG, "child " + mChildren.get(i));
                    final WindowContainer child = mChildren.get(i);
                    if (skipTraverseChild(child)) {
                        Slog.d(TAG, "child skipped");
                        continue;
                    }

                    if (child.forAllWindows(callback, traverseTopToBottom)) {
                        return true;
                    }
                }
            }
            return false;
        }

        @Override
        void positionChildAt(int position, WindowContainer child, boolean includingParents) {
            // Children of the WindowContainers are statically ordered, so the real intention here
            // is to perform the operation on the display and not the static direct children.
            getParent().positionChildAt(position, this, includingParents);
        }
    }

    /**
     * Window container class that contains all containers on this display that are not related to
     * Apps. E.g. status bar.
@@ -4602,11 +4678,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        }
    }

    SurfaceControl.Builder makeSurface(SurfaceSession s) {
        return mWmService.makeSurfaceBuilder(s)
                .setParent(mWindowingLayer);
    }

    @Override
    SurfaceSession getSession() {
        return mSession;
@@ -4621,7 +4692,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        }

        return b.setName(child.getName())
                .setParent(mWindowingLayer);
                .setParent(mSurfaceControl);
    }

    /**
@@ -4632,14 +4703,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
     */
    SurfaceControl.Builder makeOverlay() {
        return mWmService.makeSurfaceBuilder(mSession)
            .setParent(mOverlayLayer);
                .setParent(mOverlayContainers.getSurfaceControl());
    }

    /**
     * Reparents the given surface to mOverlayLayer.
     * Reparents the given surface to {@link #mOverlayContainers}' SurfaceControl.
     */
    void reparentToOverlay(Transaction transaction, SurfaceControl surface) {
        transaction.reparent(surface, mOverlayLayer);
        transaction.reparent(surface, mOverlayContainers.getSurfaceControl());
    }

    void applyMagnificationSpec(MagnificationSpec spec) {
@@ -4671,54 +4742,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo

    @Override
    void assignChildLayers(SurfaceControl.Transaction t) {
        mWindowContainers.assignLayer(t, 0);
        mOverlayContainers.assignLayer(t, 1);

        // These are layers as children of "mWindowingLayer"
        mBelowAppWindowsContainers.assignLayer(t, 0);
        mTaskStackContainers.assignLayer(t, 1);
        mAboveAppWindowsContainers.assignLayer(t, 2);

        final WindowState imeTarget = mInputMethodTarget;
        boolean needAssignIme = true;

        // In the case where we have an IME target that is not in split-screen
        // mode IME assignment is easy. We just need the IME to go directly above
        // the target. This way children of the target will naturally go above the IME
        // and everyone is happy.
        //
        // In the case of split-screen windowing mode, we need to elevate the IME above the
        // docked divider while keeping the app itself below the docked divider, so instead
        // we use relative layering of the IME targets child windows, and place the
        // IME in the non-app layer (see {@link AboveAppWindowContainers#assignChildLayers}).
        //
        // In the case the IME target is animating, the animation Z order may be different
        // than the WindowContainer Z order, so it's difficult to be sure we have the correct
        // IME target. In this case we just layer the IME over all transitions by placing it in the
        // above applications layer.
        //
        // In the case where we have no IME target we assign it where it's base layer would
        // place it in the AboveAppWindowContainers.
        //
        // Keep IME window in mAboveAppWindowsContainers as long as app's starting window exists
        // so it get's layered above the starting window.
        if (imeTarget != null
                && !(imeTarget.mActivityRecord != null && imeTarget.mActivityRecord.hasStartingWindow())
                && (!(imeTarget.inSplitScreenWindowingMode()
                             || imeTarget.mToken.isAppTransitioning())
                && (imeTarget.getSurfaceControl() != null))) {
            mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
                    // TODO: We need to use an extra level on the app surface to ensure
                    // this is always above SurfaceView but always below attached window.
                    1);
            needAssignIme = false;
        }

        // Above we have assigned layers to our children, now we ask them to assign
        // layers to their children.
        mBelowAppWindowsContainers.assignChildLayers(t);
        mTaskStackContainers.assignChildLayers(t);
        mAboveAppWindowsContainers.assignChildLayers(t,
                needAssignIme == true ? mImeWindowsContainers : null);
        mImeWindowsContainers.assignChildLayers(t);
        mWindowContainers.assignChildLayers(t);
        mOverlayContainers.assignChildLayers(t);
    }

    /**
@@ -4885,8 +4913,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    }

    /**
     * Re-parent the DisplayContent's top surfaces, {@link #mWindowingLayer} and
     * {@link #mOverlayLayer} to the specified SurfaceControl.
     * Re-parent the DisplayContent's top surface, {@link #mSurfaceControl} to the specified
     * SurfaceControl.
     *
     * @param win The window which owns the SurfaceControl. This indicates the z-order of the
     *            windows of this display against the windows on the parent display.
@@ -4964,11 +4992,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo

    @VisibleForTesting
    SurfaceControl getWindowingLayer() {
        return mWindowingLayer;
        return mWindowContainers.getSurfaceControl();
    }

    SurfaceControl getOverlayLayer() {
        return mOverlayLayer;
        return mOverlayContainers.getSurfaceControl();
    }

    /**
+1 −1
Original line number Diff line number Diff line
@@ -172,7 +172,7 @@ class ScreenRotationAnimation {
                    .setContainerLayer()
                    .build();

            mSurfaceControl = displayContent.makeSurface(null)
            mSurfaceControl = mService.makeSurfaceBuilder(null)
                    .setName("ScreenshotSurface")
                    .setParent(mRotationLayer)
                    .setBufferSize(mWidth, mHeight)
Loading