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

Commit 805d9ecc authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Don't allow IME windows to be IME targets

IME targets are required to be below the IME windows and that wouldn't
be possible if the IME window is its own target which leads to issues
elsewhere in the code where that is expected to be the case.

Change-Id: I34a723ff4ce2519cd80e0eea0eaea04712b6cf8f
Fixes: 33336368
Test: bit FrameworksServicesTests:com.android.server.wm.WindowStateTests
parent 929a81b8
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -1925,9 +1925,17 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    }

    boolean canBeImeTarget() {
        if (mIsImWindow) {
            // IME windows can't be IME targets. IME targets are required to be below the IME
            // windows and that wouldn't be possible if the IME window is its own target...silly.
            return false;
        }

        final int fl = mAttrs.flags & (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM);
        final int type = mAttrs.type;

        // Can only be an IME target if both FLAG_NOT_FOCUSABLE and FLAG_ALT_FOCUSABLE_IM are set or
        // both are cleared...and not a starting window.
        if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM)
                && type != TYPE_APPLICATION_STARTING) {
            return false;
+61 −49
Original line number Diff line number Diff line
@@ -16,23 +16,18 @@

package com.android.server.wm;

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

import android.content.Context;
import android.os.Binder;
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.IWindow;
import android.view.WindowManager;

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_MEDIA_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@@ -41,30 +36,19 @@ import static org.junit.Assert.assertTrue;
/**
 * Tests for the {@link WindowState} class.
 *
 * runtest frameworks-services -c com.android.server.wm.WindowStateTests
 * Build/Install/Run:
 *  bit FrameworksServicesTests:com.android.server.wm.WindowStateTests
 */
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
public class WindowStateTests extends WindowTestsBase {

    private WindowToken mWindowToken;

    @Before
    public void setUp() throws Exception {
        super.setUp();
        mWindowToken = new WindowToken(sWm, new Binder(), 0, false,
                sWm.getDefaultDisplayContentLocked());
    }

    @Test
    public void testIsParentWindowHidden() throws Exception {
        final WindowState parentWindow =
                createWindow(null, TYPE_APPLICATION, mWindowToken, "parentWindow");
        final WindowState child1 =
                createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child1");
        final WindowState child2 =
                createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child2");
        final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
        final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1");
        final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2");

        assertFalse(parentWindow.mHidden);
        assertFalse(parentWindow.isParentWindowHidden());
@@ -79,14 +63,10 @@ public class WindowStateTests extends WindowTestsBase {

    @Test
    public void testIsChildWindow() throws Exception {
        final WindowState parentWindow =
                createWindow(null, TYPE_APPLICATION, mWindowToken, "parentWindow");
        final WindowState child1 =
                createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child1");
        final WindowState child2 =
                createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child2");
        final WindowState randomWindow =
                createWindow(null, TYPE_APPLICATION, mWindowToken, "randomWindow");
        final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
        final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1");
        final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2");
        final WindowState randomWindow = createWindow(null, TYPE_APPLICATION, "randomWindow");

        assertFalse(parentWindow.isChildWindow());
        assertTrue(child1.isChildWindow());
@@ -96,13 +76,12 @@ public class WindowStateTests extends WindowTestsBase {

    @Test
    public void testHasChild() throws Exception {
        final WindowState win1 = createWindow(null, TYPE_APPLICATION, mWindowToken, "win1");
        final WindowState win11 = createWindow(win1, FIRST_SUB_WINDOW, mWindowToken, "win11");
        final WindowState win12 = createWindow(win1, FIRST_SUB_WINDOW, mWindowToken, "win12");
        final WindowState win2 = createWindow(null, TYPE_APPLICATION, mWindowToken, "win2");
        final WindowState win21 = createWindow(win2, FIRST_SUB_WINDOW, mWindowToken, "win21");
        final WindowState randomWindow =
                createWindow(null, TYPE_APPLICATION, mWindowToken, "randomWindow");
        final WindowState win1 = createWindow(null, TYPE_APPLICATION, "win1");
        final WindowState win11 = createWindow(win1, FIRST_SUB_WINDOW, "win11");
        final WindowState win12 = createWindow(win1, FIRST_SUB_WINDOW, "win12");
        final WindowState win2 = createWindow(null, TYPE_APPLICATION, "win2");
        final WindowState win21 = createWindow(win2, FIRST_SUB_WINDOW, "win21");
        final WindowState randomWindow = createWindow(null, TYPE_APPLICATION, "randomWindow");

        assertTrue(win1.hasChild(win11));
        assertTrue(win1.hasChild(win12));
@@ -118,12 +97,9 @@ public class WindowStateTests extends WindowTestsBase {

    @Test
    public void testGetParentWindow() throws Exception {
        final WindowState parentWindow =
                createWindow(null, TYPE_APPLICATION, mWindowToken, "parentWindow");
        final WindowState child1 =
                createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child1");
        final WindowState child2 =
                createWindow(parentWindow, FIRST_SUB_WINDOW, mWindowToken, "child2");
        final WindowState parentWindow = createWindow(null, TYPE_APPLICATION, "parentWindow");
        final WindowState child1 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child1");
        final WindowState child2 = createWindow(parentWindow, FIRST_SUB_WINDOW, "child2");

        assertNull(parentWindow.getParentWindow());
        assertEquals(parentWindow, child1.getParentWindow());
@@ -132,9 +108,9 @@ public class WindowStateTests extends WindowTestsBase {

    @Test
    public void testGetTopParentWindow() throws Exception {
        final WindowState root = createWindow(null, TYPE_APPLICATION, mWindowToken, "root");
        final WindowState child1 = createWindow(root, FIRST_SUB_WINDOW, mWindowToken, "child1");
        final WindowState child2 = createWindow(child1, FIRST_SUB_WINDOW, mWindowToken, "child2");
        final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
        final WindowState child1 = createWindow(root, FIRST_SUB_WINDOW, "child1");
        final WindowState child2 = createWindow(child1, FIRST_SUB_WINDOW, "child2");

        assertEquals(root, root.getTopParentWindow());
        assertEquals(root, child1.getTopParentWindow());
@@ -144,10 +120,46 @@ public class WindowStateTests extends WindowTestsBase {

    @Test
    public void testIsOnScreen_hiddenByPolicy() {
        final WindowState window = createWindow(null, TYPE_APPLICATION, mWindowToken, "window");
        final WindowState window = createWindow(null, TYPE_APPLICATION, "window");
        window.setHasSurface(true);
        assertTrue(window.isOnScreen());
        window.hideLw(false /* doAnimation */);
        assertFalse(window.isOnScreen());
    }

    @Test
    public void testCanBeImeTarget() throws Exception {
        final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
        final WindowState imeWindow = createWindow(null, TYPE_INPUT_METHOD, "imeWindow");

        // Setting FLAG_NOT_FOCUSABLE without FLAG_ALT_FOCUSABLE_IM prevents the window from being
        // an IME target.
        appWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
        imeWindow.mAttrs.flags |= FLAG_NOT_FOCUSABLE;

        // Make windows visible
        appWindow.setHasSurface(true);
        imeWindow.setHasSurface(true);

        // Windows without flags (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM) can't be IME targets
        assertFalse(appWindow.canBeImeTarget());
        assertFalse(imeWindow.canBeImeTarget());

        // Add IME target flags
        appWindow.mAttrs.flags |= (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM);
        imeWindow.mAttrs.flags |= (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM);

        // Visible app window with flags can be IME target while an IME window can never be an IME
        // target regardless of its visibility or flags.
        assertTrue(appWindow.canBeImeTarget());
        assertFalse(imeWindow.canBeImeTarget());

        // Make windows invisible
        appWindow.hideLw(false /* doAnimation */);
        imeWindow.hideLw(false /* doAnimation */);

        // Invisible window can't be IME targets even if they have the right flags.
        assertFalse(appWindow.canBeImeTarget());
        assertFalse(imeWindow.canBeImeTarget());
    }
}
+6 −0
Original line number Diff line number Diff line
@@ -113,6 +113,12 @@ public class WindowTestsBase {
        return token;
    }

    WindowState createWindow(WindowState parent, int type, String name) {
        return (parent == null)
                ? createWindow(parent, type, sDisplayContent, name)
                : createWindow(parent, type, parent.mToken, name);
    }

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