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

Commit 391b568c authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Merge cherrypicks of ['googleplex-android-review.googlesource.com/35743035',...

Merge cherrypicks of ['googleplex-android-review.googlesource.com/35743035', 'googleplex-android-review.googlesource.com/35743299', 'googleplex-android-review.googlesource.com/35782396', 'googleplex-android-review.googlesource.com/35802532', 'googleplex-android-review.googlesource.com/35807552', 'googleplex-android-review.googlesource.com/35666383'] into 25Q4-release.

Change-Id: Ib872a5be8163ba0a5dced19ab418cce742466cf7
parents 3228688a 972646ff
Loading
Loading
Loading
Loading
+7 −10
Original line number Diff line number Diff line
@@ -392,11 +392,10 @@ public final class WindowManagerGlobal {
        if (display == null) {
            throw new IllegalArgumentException("display must not be null");
        }
        if (!(params instanceof WindowManager.LayoutParams)) {
        if (!(params instanceof WindowManager.LayoutParams wparams)) {
            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
        }

        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
        final Context context = view.getContext();
        if (parentWindow != null) {
            parentWindow.adjustLayoutParamsForSubWindow(wparams);
@@ -507,12 +506,10 @@ public final class WindowManagerGlobal {
        if (view == null) {
            throw new IllegalArgumentException("view must not be null");
        }
        if (!(params instanceof WindowManager.LayoutParams)) {
        if (!(params instanceof WindowManager.LayoutParams wparams)) {
            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
        }

        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;

        view.setLayoutParams(wparams);

        synchronized (mLock) {
@@ -1115,14 +1112,14 @@ public final class WindowManagerGlobal {
    }

    /**
     * Checks whether {@link WindowContext#getWindowTypeOverride()} can be applied when
     * Checks whether {@link WindowContext#getFallbackWindowType()} can be applied when
     * {@link WindowManager#addView} or {@link WindowManager#updateViewLayout}.
     *
     * @param windowTypeToOverride the window type to override
     * @param fallbackWindowType the fallback window type
     * @param view the view that applies the window type
     */
    public boolean canApplyWindowTypeOverride(
            @WindowManager.LayoutParams.WindowType int windowTypeToOverride,
    public boolean canApplyFallbackWindowType(
            @WindowManager.LayoutParams.WindowType int fallbackWindowType,
            @NonNull View view) {
        synchronized (mLock) {
            final int index = findViewLocked(view, false /* required */);
@@ -1133,7 +1130,7 @@ public final class WindowManagerGlobal {
            final WindowManager.LayoutParams params = mParams.get(index);
            // If the view has been attached, we should make sure the override type matches the
            // existing one. The window type can't be changed after the view was added.
            return windowTypeToOverride == params.type;
            return fallbackWindowType == params.type;
        }
    }
}
+17 −6
Original line number Diff line number Diff line
@@ -162,7 +162,7 @@ public final class WindowManagerImpl implements WindowManager {

    @Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyWindowTypeOverrideIfNeeded(params, view);
        fallbackWindowTypeIfNeeded(params, view);
        applyTokens(params);
        mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
                mContext.getUserId());
@@ -170,7 +170,7 @@ public final class WindowManagerImpl implements WindowManager {

    @Override
    public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyWindowTypeOverrideIfNeeded(params, view);
        fallbackWindowTypeIfNeeded(params, view);
        applyTokens(params);
        mGlobal.updateViewLayout(view, params);
    }
@@ -191,7 +191,7 @@ public final class WindowManagerImpl implements WindowManager {
        if (!(mContext instanceof WindowProvider windowProvider)) {
            return;
        }
        if (windowProvider.isValidWindowType(windowType)) {
        if (windowProvider.isSelfOrSubWindowType(windowType)) {
            return;
        }
        IllegalArgumentException exception = new IllegalArgumentException("Window type mismatch."
@@ -209,7 +209,14 @@ public final class WindowManagerImpl implements WindowManager {
                + " match type in WindowManager.LayoutParams", exception);
    }

    private void applyWindowTypeOverrideIfNeeded(
    /**
     * Fallbacks to {@link WindowContext#getFallbackWindowType()} if the type of the window context
     * associated window is not {@link WindowContext#isSelfOrSubWindowType}.
     *
     * @param params the passed {@link android.view.WindowManager.LayoutParams}
     * @param view   the window that are going to be attached or relayout
     */
    private void fallbackWindowTypeIfNeeded(
            @NonNull ViewGroup.LayoutParams params,
            @NonNull View view) {
        if (!(params instanceof WindowManager.LayoutParams wparams)) {
@@ -218,11 +225,15 @@ public final class WindowManagerImpl implements WindowManager {
        if (!(mContext instanceof WindowProvider windowProvider)) {
            return;
        }
        final int windowTypeOverride = windowProvider.getWindowTypeOverride();
        final int windowTypeOverride = windowProvider.getFallbackWindowType();
        if (windowTypeOverride == INVALID_WINDOW_TYPE) {
            return;
        }
        if (!mGlobal.canApplyWindowTypeOverride(windowTypeOverride, view)) {
        if (windowProvider.isSelfOrSubWindowType(wparams.type)) {
            // Don't need to override the type if the type is valid for this WindowContext.
            return;
        }
        if (!mGlobal.canApplyFallbackWindowType(windowTypeOverride, view)) {
            return;
        }
        if (isSubWindowType(windowTypeOverride) && mParentWindow == null) {
+37 −36
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ public class WindowContext extends ContextWrapper implements WindowProvider,
    @Nullable
    private final Bundle mOptions;
    @WindowType
    private int mWindowTypeOverride = INVALID_WINDOW_TYPE;
    private int mFallbackWindowType = INVALID_WINDOW_TYPE;
    private final ComponentCallbacksController mCallbacksController =
            new ComponentCallbacksController();
    private final WindowContextController mController;
@@ -176,37 +176,10 @@ public class WindowContext extends ContextWrapper implements WindowProvider,
        mCallbacksController.unregisterCallbacks(callback);
    }

    /**
     * If set, this {@code WindowContext} will override the window type when
     * {@link WindowManager#addView} or {@link WindowManager#updateViewLayout}.
     * <p>
     * Allowed window types are {@link #getWindowType()} and
     * any sub-window types. If set to {@link WindowManager.LayoutParams#INVALID_WINDOW_TYPE},
     * this {@code WindowContext} won't override the type.
     * <p>
     * Note:
     * <ol>
     *   <li>If a view is attached, the window type won't be overridden to another window type.</li>
     *   <li>If a sub-window override is requested, a parent window must be prepared. It can
     *   be either by using {@link WindowManager} from a {@link Window} or calling
     *   {@link #attachWindow(View)} before adding any sub-windows, or
     *   {@link IllegalArgumentException} throws when {@link WindowManager#addView}.
     *   </li>
     * </ol>
     *
     * @throws IllegalArgumentException if the passed {@code windowTypeOverride} is not an allowed
     *     window type mentioned above.
     */
    public void setWindowTypeOverride(@WindowType int windowTypeOverride) {
        if (!isValidWindowType(windowTypeOverride) && windowTypeOverride != INVALID_WINDOW_TYPE) {
            throw new IllegalArgumentException(
                    "The window type override must be either "
                    + mType
                    + " or a sub window type, but it's "
                    + windowTypeOverride
            );
        }
        mWindowTypeOverride = windowTypeOverride;
    @WindowType
    @Override
    public int getFallbackWindowType() {
        return mFallbackWindowType;
    }

    /**
@@ -263,10 +236,38 @@ public class WindowContext extends ContextWrapper implements WindowProvider,
        return mOptions;
    }

    @WindowType
    @Override
    public int getWindowTypeOverride() {
        return mWindowTypeOverride;
    /**
     * If set, this {@code WindowContext} will override the window type when
     * {@link WindowManager#addView} or {@link WindowManager#updateViewLayout} if the window does
     * not use {@link #isSelfOrSubWindowType(int)}.
     * <p>
     * The default is {@link WindowManager.LayoutParams#INVALID_WINDOW_TYPE},
     * which won't override the type.
     * <p>
     * Note:
     * <ol>
     *   <li>If a view is attached, the window type won't be overridden to another window type.</li>
     *   <li>If a sub-window override is requested, a parent window must be prepared. It can
     *   be either by using {@link WindowManager} from a {@link Window} or calling
     *   {@link #attachWindow(View)} before adding any sub-windows, or
     *   {@link IllegalArgumentException} throws when {@link WindowManager#addView}.
     *   </li>
     * </ol>
     *
     * @throws IllegalArgumentException if the passed {@code fallbackWindowType} is not
     * {@link #isSelfOrSubWindowType(int)}.
     */
    public void setFallbackWindowType(@WindowType int fallbackWindowType) {
        if (!isSelfOrSubWindowType(fallbackWindowType)
                && fallbackWindowType != INVALID_WINDOW_TYPE) {
            throw new IllegalArgumentException(
                    "The window type override must be either "
                    + mType
                    + " or a sub window type, but it's "
                            + fallbackWindowType
            );
        }
        mFallbackWindowType = fallbackWindowType;
    }

/* === ConfigurationDispatcher APIs === */
+6 −11
Original line number Diff line number Diff line
@@ -66,25 +66,20 @@ public interface WindowProvider {

    /**
     * Gets the window type to be overridden when {@link android.view.WindowManager#addView}
     * and {@link android.view.WindowManager#updateViewLayout} if the added window is not
     * {@link #isSelfOrSubWindowType(int)}.
     */
    @WindowType
    default int getWindowTypeOverride() {
    default int getFallbackWindowType() {
        return INVALID_WINDOW_TYPE;
    }

    /**
     * Returns {@code true} if the given type is a valid window type for this
     * {@link WindowProvider}.
     * Returns {@code true} if the given type is {@link #getWindowType()} or a sub-window type.
     *
     * @param type the requested window type
     */
    default boolean isValidWindowType(@WindowType int type) {
        if (type == getWindowType()) {
            // Valid. The requested window type is the type of WindowContext.
            return true;
        }
        // Don't need to check sub-window type because sub window should be allowed to be attached
        // to the parent window.
        return isSubWindowType(type);
    default boolean isSelfOrSubWindowType(@WindowType int type) {
        return getWindowType() == type || isSubWindowType(type);
    }
}
+63 −18
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ 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_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.window.WindowProvider.KEY_REPARENT_TO_DEFAULT_DISPLAY_WITH_DISPLAY_REMOVAL;

@@ -441,29 +442,29 @@ public class WindowContextTest {
    }

    @Test
    public void testSetWindowTypeOverride() {
    public void testSetFallbackWindowType() {
        int windowType = INVALID_WINDOW_TYPE;
        mWindowContext.setWindowTypeOverride(windowType);
        assertThat(mWindowContext.getWindowTypeOverride()).isEqualTo(windowType);
        mWindowContext.setFallbackWindowType(windowType);
        assertThat(mWindowContext.getFallbackWindowType()).isEqualTo(windowType);

        windowType = mWindowContext.getWindowType();
        mWindowContext.setWindowTypeOverride(windowType);
        assertThat(mWindowContext.getWindowTypeOverride()).isEqualTo(windowType);
        mWindowContext.setFallbackWindowType(windowType);
        assertThat(mWindowContext.getFallbackWindowType()).isEqualTo(windowType);

        windowType = TYPE_APPLICATION_ATTACHED_DIALOG;
        mWindowContext.setWindowTypeOverride(windowType);
        assertThat(mWindowContext.getWindowTypeOverride()).isEqualTo(windowType);
        mWindowContext.setFallbackWindowType(windowType);
        assertThat(mWindowContext.getFallbackWindowType()).isEqualTo(windowType);

        final int invalidType = TYPE_APPLICATION;
        assertThrows(IllegalArgumentException.class,
                () -> mWindowContext.setWindowTypeOverride(invalidType));
                () -> mWindowContext.setFallbackWindowType(invalidType));
    }

    @Test
    public void testSetWindowTypeOverrideAndAddView_invalidWindowType_noOverride() {
    public void testSetFallbackWindowTypeAndAddView_invalidFallbackWindowType_noOverride() {
        WindowManager.LayoutParams params =
                new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
        mWindowContext.setWindowTypeOverride(INVALID_WINDOW_TYPE);
        mWindowContext.setFallbackWindowType(INVALID_WINDOW_TYPE);
        final WindowManager wm = mWindowContext.getSystemService(WindowManager.class);
        mInstrumentation.runOnMainSync(() -> wm.addView(new View(mWindowContext), params));

@@ -471,10 +472,10 @@ public class WindowContextTest {
    }

    @Test
    public void testSetWindowTypeOverrideAndAddView_windowContextType_override() {
    public void testSetFallbackWindowTypeAndAddView_Fallback_windowContextType_override() {
        int windowType = mWindowContext.getWindowType();
        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        mWindowContext.setWindowTypeOverride(windowType);
        mWindowContext.setFallbackWindowType(windowType);
        final WindowManager wm = mWindowContext.getSystemService(WindowManager.class);
        mInstrumentation.runOnMainSync(() -> wm.addView(new View(mWindowContext), params));

@@ -482,9 +483,9 @@ public class WindowContextTest {
    }

    @Test
    public void testSetWindowTypeOverrideAndAddView_subWindowWithoutParentWindow_throwException() {
    public void testSetFallbackWindowTypeAndAddView_subWindowWithoutParent_throwException() {
        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        mWindowContext.setWindowTypeOverride(TYPE_APPLICATION_ATTACHED_DIALOG);
        mWindowContext.setFallbackWindowType(TYPE_APPLICATION_ATTACHED_DIALOG);
        final WindowManager wm = mWindowContext.getSystemService(WindowManager.class);

        assertThrows(IllegalArgumentException.class,
@@ -493,7 +494,7 @@ public class WindowContextTest {
    }

    @Test
    public void testSetWindowTypeOverrideAndAddView_subWindowWithParentWindow_override()
    public void testSetFallbackWindowTypeAndAddView_subWindowWithParent_override()
            throws InterruptedException {
        final View parentWindow = new View(mWindowContext);
        final AttachStateListener listener = new AttachStateListener();
@@ -505,7 +506,7 @@ public class WindowContextTest {

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

        mWindowContext.setWindowTypeOverride(TYPE_APPLICATION_ATTACHED_DIALOG);
        mWindowContext.setFallbackWindowType(TYPE_APPLICATION_ATTACHED_DIALOG);

        WindowManager.LayoutParams params = new WindowManager.LayoutParams();
        mInstrumentation.runOnMainSync(() -> wm.addView(new View(mWindowContext), params));
@@ -514,7 +515,51 @@ public class WindowContextTest {
    }

    @Test
    public void testSetWindowTypeOverrideAndUpdateLayout_diffType_noOverride() {
    public void testSetFallbackWindowTypeAndAddView_isSubWindow_noOverride()
            throws InterruptedException {
        final View parentWindow = new View(mWindowContext);
        final AttachStateListener listener = new AttachStateListener();
        parentWindow.addOnAttachStateChangeListener(listener);
        mWindowContext.attachWindow(parentWindow);
        final WindowManager wm = mWindowContext.getSystemService(WindowManager.class);
        mInstrumentation.runOnMainSync(() -> wm.addView(
                parentWindow, new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY)));

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

        mWindowContext.setFallbackWindowType(TYPE_APPLICATION_ATTACHED_DIALOG);

        WindowManager.LayoutParams params =
                new WindowManager.LayoutParams(TYPE_APPLICATION_SUB_PANEL);
        mInstrumentation.runOnMainSync(() -> wm.addView(new View(mWindowContext), params));

        assertThat(params.type).isEqualTo(TYPE_APPLICATION_SUB_PANEL);
    }

    @Test
    public void testSetFallbackWindowTypeAndAddView_typeMatch_noOverride()
            throws InterruptedException {
        final View parentWindow = new View(mWindowContext);
        final AttachStateListener listener = new AttachStateListener();
        parentWindow.addOnAttachStateChangeListener(listener);
        mWindowContext.attachWindow(parentWindow);
        final WindowManager wm = mWindowContext.getSystemService(WindowManager.class);
        mInstrumentation.runOnMainSync(() -> wm.addView(
                parentWindow, new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY)));

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

        mWindowContext.setFallbackWindowType(TYPE_APPLICATION_ATTACHED_DIALOG);

        WindowManager.LayoutParams params =
                new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
        mInstrumentation.runOnMainSync(() -> wm.addView(new View(mWindowContext), params));

        assertThat(params.type).isEqualTo(TYPE_APPLICATION_OVERLAY);
    }

    @Test
    public void testSetFallbackWindowTypeAndUpdateLayout_diffType_noOverride() {
        final View view = new View(mWindowContext);
        mWindowContext.attachWindow(view);
        final WindowManager wm = mWindowContext.getSystemService(WindowManager.class);
@@ -523,7 +568,7 @@ public class WindowContextTest {

        mInstrumentation.runOnMainSync(() -> wm.addView(view, params));

        mWindowContext.setWindowTypeOverride(TYPE_APPLICATION_ATTACHED_DIALOG);
        mWindowContext.setFallbackWindowType(TYPE_APPLICATION_ATTACHED_DIALOG);

        mInstrumentation.runOnMainSync(() -> wm.updateViewLayout(view, params));

Loading