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

Commit b987a56e authored by Charles Chen's avatar Charles Chen Committed by Automerger Merge Worker
Browse files

Fix WindowContext cannot add window with sub window type am: 4ca1b87f

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14111136

Change-Id: Ia9e919744423e51d735d872dbc006fc14ddafcaa
parents eba41ae4 4ca1b87f
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());
    }
}