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

Commit b327a4a3 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fixed issues with child windows been IME targets"

parents f9bd2944 34247958
Loading
Loading
Loading
Loading
+40 −7
Original line number Diff line number Diff line
@@ -3889,7 +3889,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    }

    private boolean forAllWindowBottomToTop(ToBooleanFunction<WindowState> callback) {
        // We want to consumer the negative sublayer children first because they need to appear
        // We want to consume the negative sublayer children first because they need to appear
        // below the parent, then this window (the parent), and then the positive sublayer children
        // because they need to appear above the parent.
        int i = 0;
@@ -3897,7 +3897,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        WindowState child = mChildren.get(i);

        while (i < count && child.mSubLayer < 0) {
            if (callback.apply(child)) {
            if (child.applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) {
                return true;
            }
            i++;
@@ -3912,7 +3912,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        }

        while (i < count) {
            if (callback.apply(child)) {
            if (child.applyInOrderWithImeWindows(callback, false /* traverseTopToBottom */)) {
                return true;
            }
            i++;
@@ -3926,14 +3926,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    }

    private boolean forAllWindowTopToBottom(ToBooleanFunction<WindowState> callback) {
        // We want to consumer the positive sublayer children first because they need to appear
        // We want to consume the positive sublayer children first because they need to appear
        // above the parent, then this window (the parent), and then the negative sublayer children
        // because they need to appear above the parent.
        int i = mChildren.size() - 1;
        WindowState child = mChildren.get(i);

        while (i >= 0 && child.mSubLayer >= 0) {
            if (callback.apply(child)) {
            if (child.applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) {
                return true;
            }
            --i;
@@ -3948,7 +3948,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        }

        while (i >= 0) {
            if (callback.apply(child)) {
            if (child.applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) {
                return true;
            }
            --i;
@@ -3991,10 +3991,43 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    }

    WindowState getWindow(Predicate<WindowState> callback) {
        if (mChildren.isEmpty()) {
            return callback.test(this) ? this : null;
        }

        // We want to consume the positive sublayer children first because they need to appear
        // above the parent, then this window (the parent), and then the negative sublayer children
        // because they need to appear above the parent.
        int i = mChildren.size() - 1;
        WindowState child = mChildren.get(i);

        while (i >= 0 && child.mSubLayer >= 0) {
            if (callback.test(child)) {
                return child;
            }
            --i;
            if (i < 0) {
                break;
            }
            child = mChildren.get(i);
        }

        if (callback.test(this)) {
            return this;
        }
        return super.getWindow(callback);

        while (i >= 0) {
            if (callback.test(child)) {
                return child;
            }
            --i;
            if (i < 0) {
                break;
            }
            child = mChildren.get(i);
        }

        return null;
    }

    boolean isWindowAnimationSet() {
+106 −138
Original line number Diff line number Diff line
@@ -16,24 +16,25 @@

package com.android.server.wm;

import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

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

import android.content.res.Configuration;
import android.hardware.display.DisplayManagerGlobal;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.Display;
import android.view.DisplayInfo;

import java.util.ArrayList;

import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

/**
 * Tests for the {@link DisplayContent} class.
@@ -54,38 +55,17 @@ public class DisplayContentTests extends WindowTestsBase {
        exitingAppToken.mIsExiting = true;
        exitingAppToken.mTask.mStack.mExitingAppTokens.add(exitingAppToken);

        final ArrayList<WindowState> windows = new ArrayList();

        // Test forward traversal.
        sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);

        assertEquals(sWallpaperWindow, windows.get(0));
        assertEquals(exitingAppWindow, windows.get(1));
        assertEquals(sChildAppWindowBelow, windows.get(2));
        assertEquals(sAppWindow, windows.get(3));
        assertEquals(sChildAppWindowAbove, windows.get(4));
        assertEquals(sDockedDividerWindow, windows.get(5));
        assertEquals(sStatusBarWindow, windows.get(6));
        assertEquals(sNavBarWindow, windows.get(7));
        assertEquals(sImeWindow, windows.get(8));
        assertEquals(sImeDialogWindow, windows.get(9));

        // Test backward traversal.
        windows.clear();
        sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);

        assertEquals(sWallpaperWindow, windows.get(9));
        assertEquals(exitingAppWindow, windows.get(8));
        assertEquals(sChildAppWindowBelow, windows.get(7));
        assertEquals(sAppWindow, windows.get(6));
        assertEquals(sChildAppWindowAbove, windows.get(5));
        assertEquals(sDockedDividerWindow, windows.get(4));
        assertEquals(sStatusBarWindow, windows.get(3));
        assertEquals(sNavBarWindow, windows.get(2));
        assertEquals(sImeWindow, windows.get(1));
        assertEquals(sImeDialogWindow, windows.get(0));

        exitingAppWindow.removeImmediately();
        assertForAllWindowsOrder(Arrays.asList(
                sWallpaperWindow,
                exitingAppWindow,
                sChildAppWindowBelow,
                sAppWindow,
                sChildAppWindowAbove,
                sDockedDividerWindow,
                sStatusBarWindow,
                sNavBarWindow,
                sImeWindow,
                sImeDialogWindow));
    }

    @Test
@@ -95,78 +75,49 @@ public class DisplayContentTests extends WindowTestsBase {

        sWm.mInputMethodTarget = imeAppTarget;

        final ArrayList<WindowState> windows = new ArrayList();

        // Test forward traversal.
        sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);

        assertEquals(sWallpaperWindow, windows.get(0));
        assertEquals(sChildAppWindowBelow, windows.get(1));
        assertEquals(sAppWindow, windows.get(2));
        assertEquals(sChildAppWindowAbove, windows.get(3));
        assertEquals(imeAppTarget, windows.get(4));
        assertEquals(sImeWindow, windows.get(5));
        assertEquals(sImeDialogWindow, windows.get(6));
        assertEquals(sDockedDividerWindow, windows.get(7));
        assertEquals(sStatusBarWindow, windows.get(8));
        assertEquals(sNavBarWindow, windows.get(9));
        assertForAllWindowsOrder(Arrays.asList(
                sWallpaperWindow,
                sChildAppWindowBelow,
                sAppWindow,
                sChildAppWindowAbove,
                imeAppTarget,
                sImeWindow,
                sImeDialogWindow,
                sDockedDividerWindow,
                sStatusBarWindow,
                sNavBarWindow));
    }

        // Test backward traversal.
        windows.clear();
        sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);

        assertEquals(sWallpaperWindow, windows.get(9));
        assertEquals(sChildAppWindowBelow, windows.get(8));
        assertEquals(sAppWindow, windows.get(7));
        assertEquals(sChildAppWindowAbove, windows.get(6));
        assertEquals(imeAppTarget, windows.get(5));
        assertEquals(sImeWindow, windows.get(4));
        assertEquals(sImeDialogWindow, windows.get(3));
        assertEquals(sDockedDividerWindow, windows.get(2));
        assertEquals(sStatusBarWindow, windows.get(1));
        assertEquals(sNavBarWindow, windows.get(0));

        // Clean-up
        sWm.mInputMethodTarget = null;
        imeAppTarget.removeImmediately();
    @Test
    public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
        sWm.mInputMethodTarget = sChildAppWindowAbove;

        assertForAllWindowsOrder(Arrays.asList(
                sWallpaperWindow,
                sChildAppWindowBelow,
                sAppWindow,
                sChildAppWindowAbove,
                sImeWindow,
                sImeDialogWindow,
                sDockedDividerWindow,
                sStatusBarWindow,
                sNavBarWindow));
    }

    @Test
    public void testForAllWindows_WithStatusBarImeTarget() throws Exception {

        sWm.mInputMethodTarget = sStatusBarWindow;

        final ArrayList<WindowState> windows = new ArrayList();

        // Test forward traversal.
        sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);

        assertEquals(sWallpaperWindow, windows.get(0));
        assertEquals(sChildAppWindowBelow, windows.get(1));
        assertEquals(sAppWindow, windows.get(2));
        assertEquals(sChildAppWindowAbove, windows.get(3));
        assertEquals(sDockedDividerWindow, windows.get(4));
        assertEquals(sStatusBarWindow, windows.get(5));
        assertEquals(sImeWindow, windows.get(6));
        assertEquals(sImeDialogWindow, windows.get(7));
        assertEquals(sNavBarWindow, windows.get(8));

        // Test backward traversal.
        windows.clear();
        sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);

        assertEquals(sWallpaperWindow, windows.get(8));
        assertEquals(sChildAppWindowBelow, windows.get(7));
        assertEquals(sAppWindow, windows.get(6));
        assertEquals(sChildAppWindowAbove, windows.get(5));
        assertEquals(sDockedDividerWindow, windows.get(4));
        assertEquals(sStatusBarWindow, windows.get(3));
        assertEquals(sImeWindow, windows.get(2));
        assertEquals(sImeDialogWindow, windows.get(1));
        assertEquals(sNavBarWindow, windows.get(0));

        // Clean-up
        sWm.mInputMethodTarget = null;
        assertForAllWindowsOrder(Arrays.asList(
                sWallpaperWindow,
                sChildAppWindowBelow,
                sAppWindow,
                sChildAppWindowAbove,
                sDockedDividerWindow,
                sStatusBarWindow,
                sImeWindow,
                sImeDialogWindow,
                sNavBarWindow));
    }

    @Test
@@ -176,38 +127,35 @@ public class DisplayContentTests extends WindowTestsBase {
        final WindowState voiceInteractionWindow = createWindow(null, TYPE_VOICE_INTERACTION,
                sDisplayContent, "voiceInteractionWindow");

        final ArrayList<WindowState> windows = new ArrayList();

        // Test forward traversal.
        sDisplayContent.forAllWindows(w -> {windows.add(w);}, false /* traverseTopToBottom */);

        assertEquals(sWallpaperWindow, windows.get(0));
        assertEquals(sChildAppWindowBelow, windows.get(1));
        assertEquals(sAppWindow, windows.get(2));
        assertEquals(sChildAppWindowAbove, windows.get(3));
        assertEquals(sDockedDividerWindow, windows.get(4));
        assertEquals(voiceInteractionWindow, windows.get(5));
        assertEquals(sStatusBarWindow, windows.get(6));
        assertEquals(sNavBarWindow, windows.get(7));
        assertEquals(sImeWindow, windows.get(8));
        assertEquals(sImeDialogWindow, windows.get(9));
        assertForAllWindowsOrder(Arrays.asList(
                sWallpaperWindow,
                sChildAppWindowBelow,
                sAppWindow,
                sChildAppWindowAbove,
                sDockedDividerWindow,
                voiceInteractionWindow,
                sStatusBarWindow,
                sNavBarWindow,
                sImeWindow,
                sImeDialogWindow));
    }

        // Test backward traversal.
        windows.clear();
        sDisplayContent.forAllWindows(w -> {windows.add(w);}, true /* traverseTopToBottom */);

        assertEquals(sWallpaperWindow, windows.get(9));
        assertEquals(sChildAppWindowBelow, windows.get(8));
        assertEquals(sAppWindow, windows.get(7));
        assertEquals(sChildAppWindowAbove, windows.get(6));
        assertEquals(sDockedDividerWindow, windows.get(5));
        assertEquals(voiceInteractionWindow, windows.get(4));
        assertEquals(sStatusBarWindow, windows.get(3));
        assertEquals(sNavBarWindow, windows.get(2));
        assertEquals(sImeWindow, windows.get(1));
        assertEquals(sImeDialogWindow, windows.get(0));

        voiceInteractionWindow.removeImmediately();
    @Test
    public void testComputeImeTarget() throws Exception {
        // Verify that an app window can be an ime target.
        final WindowState appWin = createWindow(null, TYPE_APPLICATION, sDisplayContent, "appWin");
        appWin.setHasSurface(true);
        assertTrue(appWin.canBeImeTarget());
        WindowState imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
        assertEquals(appWin, imeTarget);

        // Verify that an child window can be an ime target.
        final WindowState childWin = createWindow(appWin,
                TYPE_APPLICATION_ATTACHED_DIALOG, "childWin");
        childWin.setHasSurface(true);
        assertTrue(childWin.canBeImeTarget());
        imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */);
        assertEquals(childWin, imeTarget);
    }

    /**
@@ -284,4 +232,24 @@ public class DisplayContentTests extends WindowTestsBase {
        assertEquals(currentOverrideConfig.densityDpi, globalConfig.densityDpi);
        assertEquals(currentOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
    }

    private void assertForAllWindowsOrder(List<WindowState> expectedWindows) {
        final LinkedList<WindowState> actualWindows = new LinkedList();

        // Test forward traversal.
        sDisplayContent.forAllWindows(actualWindows::addLast, false /* traverseTopToBottom */);
        assertEquals(expectedWindows.size(), actualWindows.size());
        for (WindowState w : expectedWindows) {
            assertEquals(w, actualWindows.pollFirst());
        }
        assertTrue(actualWindows.isEmpty());

        // Test backward traversal.
        sDisplayContent.forAllWindows(actualWindows::addLast, true /* traverseTopToBottom */);
        assertEquals(expectedWindows.size(), actualWindows.size());
        for (WindowState w : expectedWindows) {
            assertEquals(w, actualWindows.pollLast());
        }
        assertTrue(actualWindows.isEmpty());
    }
}
+37 −0
Original line number Diff line number Diff line
@@ -23,10 +23,17 @@ import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;

import java.util.LinkedList;

import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
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_APPLICATION_MEDIA_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -167,4 +174,34 @@ public class WindowStateTests extends WindowTestsBase {
        assertFalse(appWindow.canBeImeTarget());
        assertFalse(imeWindow.canBeImeTarget());
    }

    @Test
    public void testGetWindow() throws Exception {
        final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
        final WindowState mediaChild = createWindow(root, TYPE_APPLICATION_MEDIA, "mediaChild");
        final WindowState mediaOverlayChild = createWindow(root,
                TYPE_APPLICATION_MEDIA_OVERLAY, "mediaOverlayChild");
        final WindowState attachedDialogChild = createWindow(root,
                TYPE_APPLICATION_ATTACHED_DIALOG, "attachedDialogChild");
        final WindowState subPanelChild = createWindow(root,
                TYPE_APPLICATION_SUB_PANEL, "subPanelChild");
        final WindowState aboveSubPanelChild = createWindow(root,
                TYPE_APPLICATION_ABOVE_SUB_PANEL, "aboveSubPanelChild");

        final LinkedList<WindowState> windows = new LinkedList();

        root.getWindow(w -> {
            windows.addLast(w);
            return false;
        });

        // getWindow should have returned candidate windows in z-order.
        assertEquals(aboveSubPanelChild, windows.pollFirst());
        assertEquals(subPanelChild, windows.pollFirst());
        assertEquals(attachedDialogChild, windows.pollFirst());
        assertEquals(root, windows.pollFirst());
        assertEquals(mediaOverlayChild, windows.pollFirst());
        assertEquals(mediaChild, windows.pollFirst());
        assertTrue(windows.isEmpty());
    }
}
+13 −1
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.EMPTY;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
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_OVERLAY;
@@ -60,6 +61,7 @@ import static org.mockito.Mockito.mock;
import com.android.server.AttributeCache;

import java.util.HashSet;
import java.util.LinkedList;

/**
 * Common base class for window manager unit test classes.
@@ -120,6 +122,7 @@ class WindowTestsBase {
        sCommonWindows = new HashSet();
        sWallpaperWindow = createCommonWindow(null, TYPE_WALLPAPER, "wallpaperWindow");
        sImeWindow = createCommonWindow(null, TYPE_INPUT_METHOD, "sImeWindow");
        sWm.mInputMethodWindow = sImeWindow;
        sImeDialogWindow = createCommonWindow(null, TYPE_INPUT_METHOD_DIALOG, "sImeDialogWindow");
        sStatusBarWindow = createCommonWindow(null, TYPE_STATUS_BAR, "sStatusBarWindow");
        sNavBarWindow = createCommonWindow(null, TYPE_NAVIGATION_BAR, "sNavBarWindow");
@@ -133,16 +136,25 @@ class WindowTestsBase {

    @After
    public void tearDown() throws Exception {
        final LinkedList<WindowState> nonCommonWindows = new LinkedList();
        sWm.mRoot.forAllWindows(w -> {
            if (!sCommonWindows.contains(w)) {
                w.removeImmediately();
                nonCommonWindows.addLast(w);
            }
        }, true /* traverseTopToBottom */);

        while (!nonCommonWindows.isEmpty()) {
            nonCommonWindows.pollLast().removeImmediately();
        }

        sWm.mInputMethodTarget = null;
    }

    private static WindowState createCommonWindow(WindowState parent, int type, String name) {
        final WindowState win = createWindow(parent, type, name);
        sCommonWindows.add(win);
        // Prevent common windows from been IMe targets
        win.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
        return win;
    }