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

Commit 44fbdf5b authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Fixed issue with IME displaying on-top of nav bar.

Caused by some recent refactoring. We now make sure the IME
has the higher animation layer in its base layer of the window
it is targeting.
Also, consolidated some of our test functions.

Bug: 32916670
Test: bit FrameworksServicesTests:com.android.server.wm.WindowLayersControllerTests
Change-Id: I0b1abd6fead981cfc810488cc785261abba5341d
parent 0378c186
Loading
Loading
Loading
Loading
+30 −17
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import java.util.ArrayDeque;

import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -63,17 +64,19 @@ class WindowLayersController {
    private int mCurBaseLayer;
    private int mCurLayer;
    private boolean mAnyLayerChanged;
    private int mHighestLayerInImeTargetBaseLayer;
    private WindowState mImeTarget;

    final void assignWindowLayers(DisplayContent dc) {
        if (DEBUG_LAYERS) Slog.v(TAG_WM, "Assigning layers based",
                new RuntimeException("here").fillInStackTrace());

        clear();
        reset();
        dc.forAllWindows((w) -> {
            boolean layerChanged = false;

            int oldLayer = w.mLayer;
            if (w.mBaseLayer == mCurBaseLayer || w.mIsImWindow) {
            if (w.mBaseLayer == mCurBaseLayer) {
                mCurLayer += WINDOW_LAYER_MULTIPLIER;
            } else {
                mCurBaseLayer = mCurLayer = w.mBaseLayer;
@@ -92,6 +95,11 @@ class WindowLayersController {
                mHighestApplicationLayer = Math.max(mHighestApplicationLayer,
                        w.mWinAnimator.mAnimLayer);
            }
            if (mImeTarget != null && w.mBaseLayer == mImeTarget.mBaseLayer) {
                mHighestLayerInImeTargetBaseLayer = Math.max(mHighestLayerInImeTargetBaseLayer,
                        w.mWinAnimator.mAnimLayer);
            }

            collectSpecialWindows(w);

            if (layerChanged) {
@@ -103,7 +111,7 @@ class WindowLayersController {

        //TODO (multidisplay): Magnification is supported only for the default display.
        if (mService.mAccessibilityController != null && mAnyLayerChanged
                && dc.getDisplayId() == Display.DEFAULT_DISPLAY) {
                && dc.getDisplayId() == DEFAULT_DISPLAY) {
            mService.mAccessibilityController.onWindowLayersChangedLocked();
        }

@@ -120,7 +128,7 @@ class WindowLayersController {
        }, false /* traverseTopToBottom */);
    }

    private void clear() {
    private void reset() {
        mHighestApplicationLayer = 0;
        mPinnedWindows.clear();
        mInputMethodWindows.clear();
@@ -132,6 +140,9 @@ class WindowLayersController {
        mCurBaseLayer = 0;
        mCurLayer = 0;
        mAnyLayerChanged = false;

        mImeTarget = mService.mInputMethodTarget;
        mHighestLayerInImeTargetBaseLayer = (mImeTarget != null) ? mImeTarget.mBaseLayer : 0;
    }

    private void collectSpecialWindows(WindowState w) {
@@ -174,22 +185,10 @@ class WindowLayersController {

        layer = assignAndIncreaseLayerIfNeeded(mDockDivider, layer);

        boolean onTopLauncherVisible = !mOnTopLauncherWindows.isEmpty();
        while (!mOnTopLauncherWindows.isEmpty()) {
            layer = assignAndIncreaseLayerIfNeeded(mOnTopLauncherWindows.remove(), layer);
        }

        // Make sure IME windows are showing above the dock divider and on-top launcher windows.
        if ((mDockDivider != null && mDockDivider.isVisibleLw()) || onTopLauncherVisible) {
            while (!mInputMethodWindows.isEmpty()) {
                final WindowState w = mInputMethodWindows.remove();
                // Only ever move IME windows up, else we brake IME for windows above the divider.
                if (layer > w.mLayer) {
                    layer = assignAndIncreaseLayerIfNeeded(w, layer);
                }
            }
        }

        // We know that we will be animating a relaunching window in the near future, which will
        // receive a z-order increase. We want the replaced window to immediately receive the same
        // treatment, e.g. to be above the dock divider.
@@ -200,12 +199,26 @@ class WindowLayersController {
        while (!mPinnedWindows.isEmpty()) {
            layer = assignAndIncreaseLayerIfNeeded(mPinnedWindows.remove(), layer);
        }

        // Make sure IME is the highest window in the base layer of it's target.
        if (mImeTarget != null) {
            if (mImeTarget.mAppToken == null) {
                // For non-app ime targets adjust the layer we start from to match what we found
                // when assigning layers. Otherwise, just use the highest app layer we have some far.
                layer = mHighestLayerInImeTargetBaseLayer + WINDOW_LAYER_MULTIPLIER;
            }

            while (!mInputMethodWindows.isEmpty()) {
                layer = assignAndIncreaseLayerIfNeeded(mInputMethodWindows.remove(), layer);
            }
        }

    }

    private int assignAndIncreaseLayerIfNeeded(WindowState win, int layer) {
        if (win != null) {
            assignAnimLayer(win, layer);
            // Make sure we leave space inbetween normal windows for dims and such.
            // Make sure we leave space in-between normal windows for dims and such.
            layer += WINDOW_LAYER_MULTIPLIER;
        }
        return layer;
+1 −3
Original line number Diff line number Diff line
@@ -1905,9 +1905,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    }

    int getAnimLayerAdjustment() {
        final boolean isImeType =
                mAttrs.type == TYPE_INPUT_METHOD || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
        if (isImeType && mService.mInputMethodTarget != null) {
        if (mIsImWindow && mService.mInputMethodTarget != null) {
            final AppWindowToken appToken = mService.mInputMethodTarget.mAppToken;
            if (appToken != null) {
                return appToken.mAppAnimator.animLayerAdjustment;
+0 −15
Original line number Diff line number Diff line
@@ -175,21 +175,6 @@ class WindowToken extends WindowContainer<WindowState> {
        return (WindowState) mChildren.get(mChildren.size() - 1).getTop();
    }

    /**
     * Recursive search through a WindowList and all of its windows' children.
     * @param target The window to search for.
     * @return The index of win in windows or of the window that is an ancestor of win.
     */
    int getWindowIndex(WindowState target) {
        for (int i = mChildren.size() - 1; i >= 0; --i) {
            final WindowState w = mChildren.get(i);
            if (w == target || w.hasChild(target)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Returns true if the new window is considered greater than the existing window in terms of
     * z-order.
+10 −24
Original line number Diff line number Diff line
@@ -45,16 +45,7 @@ import static org.junit.Assert.assertTrue;
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
public class AppWindowTokenTests {

    private static WindowManagerService sWm = null;
    private final IWindow mIWindow = new TestIWindow();

    @Before
    public void setUp() throws Exception {
        final Context context = InstrumentationRegistry.getTargetContext();
        sWm = TestWindowManagerPolicy.getWindowManagerService(context);
    }
public class AppWindowTokenTests extends WindowTestsBase {

    @Test
    public void testAddWindow_Order() throws Exception {
@@ -62,10 +53,11 @@ public class AppWindowTokenTests {

        assertEquals(0, token.getWindowsCount());

        final WindowState win1 = createWindow(null, TYPE_APPLICATION, token);
        final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, token);
        final WindowState baseWin = createWindow(null, TYPE_BASE_APPLICATION, token);
        final WindowState win4 = createWindow(null, TYPE_APPLICATION, token);
        final WindowState win1 = createWindow(null, TYPE_APPLICATION, token, "win1");
        final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, token,
                "startingWin");
        final WindowState baseWin = createWindow(null, TYPE_BASE_APPLICATION, token, "baseWin");
        final WindowState win4 = createWindow(null, TYPE_APPLICATION, token, "win4");

        token.addWindow(win1);
        token.addWindow(startingWin);
@@ -92,24 +84,18 @@ public class AppWindowTokenTests {

        assertNull(token.findMainWindow());

        final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, token);
        final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token);
        final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token);
        final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, token, "window1");
        final WindowState window11 = createWindow(window1, FIRST_SUB_WINDOW, token, "window11");
        final WindowState window12 = createWindow(window1, FIRST_SUB_WINDOW, token, "window12");
        token.addWindow(window1);
        assertEquals(window1, token.findMainWindow());
        window1.mAnimatingExit = true;
        assertEquals(window1, token.findMainWindow());
        final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, token);
        final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, token, "window2");
        token.addWindow(window2);
        assertEquals(window2, token.findMainWindow());
    }

    private WindowState createWindow(WindowState parent, int type, WindowToken token) {
        final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);

        return new WindowState(sWm, null, mIWindow, token, parent, 0, 0, attrs, 0, 0);
    }

    /* Used so we can gain access to some protected members of the {@link AppWindowToken} class */
    private class TestAppWindowToken extends AppWindowToken {

+1 −61
Original line number Diff line number Diff line
@@ -16,28 +16,15 @@

package com.android.server.wm;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import android.content.Context;
import android.content.res.Configuration;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.Display;
import android.view.IWindow;
import android.view.WindowManager;

import java.util.ArrayList;

import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
import static android.app.AppOpsManager.OP_NONE;
import static android.content.res.Configuration.EMPTY;
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_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
@@ -47,7 +34,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;

/**
 * Tests for the {@link DisplayContent} class.
@@ -58,21 +44,7 @@ import static org.mockito.Mockito.mock;
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
public class DisplayContentTests {

    private static WindowManagerService sWm = null;
    private final IWindow mIWindow = new TestIWindow();
    private final Session mMockSession = mock(Session.class);
    private Display mDisplay;
    private int mNextStackId = FIRST_DYNAMIC_STACK_ID;
    private int mNextTaskId = 0;

    @Before
    public void setUp() throws Exception {
        final Context context = InstrumentationRegistry.getTargetContext();
        sWm = TestWindowManagerPolicy.getWindowManagerService(context);
        mDisplay = context.getDisplay();
    }
public class DisplayContentTests extends WindowTestsBase {

    @Test
    public void testForAllWindows() throws Exception {
@@ -124,36 +96,4 @@ public class DisplayContentTests {
        assertEquals(imeWindow, windows.get(1));
        assertEquals(imeDialogWindow, windows.get(0));
    }

    private WindowToken createWindowToken(DisplayContent dc, int type) {
        if (type < FIRST_APPLICATION_WINDOW || type > LAST_APPLICATION_WINDOW) {
            return new WindowToken(sWm, mock(IBinder.class), type, false, dc);
        }

        final int stackId = mNextStackId++;
        dc.addStackToDisplay(stackId, true);
        final TaskStack stack = sWm.mStackIdToStack.get(stackId);
        final Task task = new Task(mNextTaskId++, stack, 0, sWm, null, EMPTY, false);
        stack.addTask(task, true);
        final AppWindowToken token = new AppWindowToken(sWm, null, false, dc);
        task.addAppToken(0, token, 0, false);
        return token;
    }

    private WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name) {
        final WindowToken token = createWindowToken(dc, type);
        return createWindow(parent, type, token, name);
    }

    private WindowState createWindow(WindowState parent, int type, WindowToken token, String name) {
        final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type);
        attrs.setTitle(name);

        final WindowState w = new WindowState(sWm, mMockSession, mIWindow, token, parent, OP_NONE,
                0, attrs, 0, 0);
        // TODO: Probably better to make this call in the WindowState ctor to avoid errors with
        // adding it to the token...
        token.addWindow(w);
        return w;
    }
}
Loading