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

Commit 4ca1b87f authored by Charles Chen's avatar Charles Chen
Browse files

Fix WindowContext cannot add window with sub window type

Bug: 184717383
Test: atest WindowManagerServiceTests
Test: atest WindowContextTest

Change-Id: Ie523902a8ec1a1de96b961da1204bf7c923052be
parent ac8d924d
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.window;

import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;

@@ -209,6 +210,38 @@ public class WindowContextTest {
        mWms.removeWindowToken(existingToken, DEFAULT_DISPLAY);
    }

    @Test
    public void testWindowContextAddViewWithSubWindowType_NotCrash() throws Throwable {
        final WindowContext windowContext = createWindowContext(TYPE_INPUT_METHOD);
        final WindowManager wm = windowContext.getSystemService(WindowManager.class);

        // Create a WindowToken with system window type.
        final IBinder existingToken = new Binder();
        mWms.addWindowToken(existingToken, TYPE_INPUT_METHOD, windowContext.getDisplayId(),
                null /* options */);

        final WindowManager.LayoutParams params =
                new WindowManager.LayoutParams(TYPE_INPUT_METHOD);
        params.token = existingToken;
        final View parentWindow = new View(windowContext);

        final AttachStateListener listener = new AttachStateListener();
        parentWindow.addOnAttachStateChangeListener(listener);

        // Add the parent window
        mInstrumentation.runOnMainSync(() -> wm.addView(parentWindow, params));

        assertTrue(listener.mLatch.await(4, TimeUnit.SECONDS));

        final WindowManager.LayoutParams subWindowAttrs =
                new WindowManager.LayoutParams(TYPE_APPLICATION_ATTACHED_DIALOG);
        subWindowAttrs.token = parentWindow.getWindowToken();
        final View subWindow = new View(windowContext);

        // Add a window with sub-window type.
        mInstrumentation.runOnMainSync(() -> wm.addView(subWindow, subWindowAttrs));
    }

    private WindowContext createWindowContext() {
        return createWindowContext(TYPE_APPLICATION_OVERLAY);
    }
@@ -219,4 +252,16 @@ public class WindowContextTest {
                .getDisplay(DEFAULT_DISPLAY);
        return (WindowContext) instContext.createWindowContext(display, type,  null /* options */);
    }

    private static class AttachStateListener implements View.OnAttachStateChangeListener {
        final CountDownLatch mLatch = new CountDownLatch(1);

        @Override
        public void onViewAttachedToWindow(View v) {
            mLatch.countDown();
        }

        @Override
        public void onViewDetachedFromWindow(View v) {}
    }
}
+5 −2
Original line number Diff line number Diff line
@@ -1740,8 +1740,11 @@ public class WindowManagerService extends IWindowManager.Stub
            }

            // Switch to listen to the {@link WindowToken token}'s configuration changes when
            // adding a window to the window context.
            if (mWindowContextListenerController.hasListener(windowContextToken)) {
            // adding a window to the window context. Filter sub window type here because the sub
            // window must be attached to the parent window, which is attached to the window context
            // created window token.
            if (!win.isChildWindow()
                    && mWindowContextListenerController.hasListener(windowContextToken)) {
                final int windowContextType = mWindowContextListenerController
                        .getWindowType(windowContextToken);
                if (type != windowContextType) {
+34 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
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_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
@@ -50,7 +51,13 @@ import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
import android.view.IWindowSessionCallback;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.View;
import android.view.WindowManager;

import androidx.test.filters.SmallTest;

@@ -250,4 +257,31 @@ public class WindowManagerServiceTests extends WindowTestsBase {
                eq(clientToken), eq(windowToken), anyInt(), eq(TYPE_INPUT_METHOD),
                eq(windowToken.mOptions));
    }

    @Test
    public void testAddWindowWithSubWindowTypeByWindowContext() {
        spyOn(mWm.mWindowContextListenerController);

        final WindowToken windowToken = createTestWindowToken(TYPE_INPUT_METHOD, mDefaultDisplay);
        final Session session = new Session(mWm, new IWindowSessionCallback.Stub() {
            @Override
            public void onAnimatorScaleChanged(float v) throws RemoteException {}
        });
        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                TYPE_APPLICATION_ATTACHED_DIALOG);
        params.token = windowToken.token;
        final IBinder windowContextToken = new Binder();
        params.setWindowContextToken(windowContextToken);
        doReturn(true).when(mWm.mWindowContextListenerController)
                .hasListener(eq(windowContextToken));
        doReturn(TYPE_INPUT_METHOD).when(mWm.mWindowContextListenerController)
                .getWindowType(eq(windowContextToken));

        mWm.addWindow(session, new TestIWindow(), params, View.VISIBLE, DEFAULT_DISPLAY,
                UserHandle.USER_SYSTEM, new InsetsState(), null, new InsetsState(),
                new InsetsSourceControl[0]);

        verify(mWm.mWindowContextListenerController, never()).registerWindowContainerListener(any(),
                any(), anyInt(), anyInt(), any());
    }
}