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

Commit 7084a4d9 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Enable non-activity windows to be re-parented between displays" into main

parents 8761aabe 3e3b4221
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -932,6 +932,27 @@ interface IWindowManager
     */
    void detachWindowContext(IBinder clientToken);

    /**
     * Reparents the {@link android.window.WindowContext} to the
     * {@link com.android.server.wm.DisplayArea} on another display.
     * This method also reparent the WindowContext associated WindowToken to another display if
     * necessary.
     * <p>
     * {@code type} and {@code options} must be the same as the previous call of
     * {@link #attachWindowContextToDisplayArea} on the same Context otherwise this will fail
     * silently.
     *
     * @param appThread the process that the window context is on.
     * @param clientToken the window context's token
     * @param type The window type of the WindowContext
     * @param displayId The new display id this context windows should be parented to
     * @param options Bundle the context was created with
     *
     * @return True if the operation was successful, False otherwise.
     */
    boolean reparentWindowContextToDisplayArea(in IApplicationThread appThread,
                IBinder clientToken, int displayId);

    /**
     * Registers a listener, which is to be called whenever cross-window blur is enabled/disabled.
     *
+12 −11
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.view.Display;
import android.view.WindowManager;

import com.android.internal.annotations.VisibleForTesting;
import com.android.window.flags.Flags;

import java.lang.ref.Reference;

@@ -95,20 +96,20 @@ public class WindowContext extends ContextWrapper implements WindowProvider {
    }

    /**
     * Updates this context to a new displayId.
     * Moves this context to another display.
     * <p>
     * Note that this doesn't re-parent previously attached windows (they should be removed and
     * re-added manually after this is called). Resources associated with this context will have
     * the correct value and configuration for the new display after this is called.
     * Note that this re-parents all the previously attached windows. Resources associated with this
     * context will have the correct value and configuration for the new display after this is
     * called.
     */
    @Override
    public void updateDisplay(int displayId) {
    public void reparentToDisplay(int displayId) {
        if (Flags.reparentWindowTokenApi()) {
            if (displayId == getDisplayId()) {
                return;
            }
            super.updateDisplay(displayId);
        mController.detachIfNeeded();
        mController.attachToDisplayArea(mType, displayId, mOptions);
            mController.reparentToDisplayArea(mType, displayId, mOptions);
        }
    }

    @Override
+15 −0
Original line number Diff line number Diff line
@@ -158,6 +158,21 @@ public class WindowContextController {
        }
    }

    /**
     * Reparents the window context from the current attached display to another. {@code type} and
     * {@code options} must be the same as the previous attach call, otherwise this will fail
     * silently.
     */
    public void reparentToDisplayArea(
            @WindowType int type, int displayId, @Nullable Bundle options) {
        if (mAttachedToDisplayArea != AttachStatus.STATUS_ATTACHED) {
            attachToDisplayArea(type, displayId, options);
            return;
        }
        // No need to propagate type and options as this is already attached and they can't change.
        getWindowTokenClientController().reparentToDisplayArea(mToken, displayId);
    }

    /** Gets the {@link WindowTokenClientController}. */
    @VisibleForTesting
    @NonNull
+15 −0
Original line number Diff line number Diff line
@@ -197,6 +197,21 @@ public class WindowTokenClientController {
        }
    }

    /**
     * Reparents a {@link WindowTokenClient} and its associated WindowContainer if there's one.
     */
    public void reparentToDisplayArea(@NonNull WindowTokenClient client, int displayId) {
        try {
            if (!getWindowManagerService().reparentWindowContextToDisplayArea(mAppThread, client,
                    displayId)) {
                Log.e(TAG,
                        "Didn't succeed reparenting of " + client + " to displayId=" + displayId);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    private void onWindowContextTokenAttached(@NonNull WindowTokenClient client,
            @NonNull WindowContextInfo info, boolean shouldReportConfigChange) {
        recordWindowContextToken(client);
+31 −6
Original line number Diff line number Diff line
@@ -33,7 +33,9 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Activity;
import android.app.EmptyActivity;
@@ -48,7 +50,9 @@ import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.os.Binder;
import android.os.IBinder;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
import android.view.Display;
import android.view.IWindowManager;
import android.view.View;
@@ -64,6 +68,7 @@ import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;

import com.android.frameworks.coretests.R;
import com.android.window.flags.Flags;

import org.junit.After;
import org.junit.Before;
@@ -91,6 +96,8 @@ public class WindowContextTest {
    public ActivityTestRule<EmptyActivity> mActivityRule =
            new ActivityTestRule<>(EmptyActivity.class, false /* initialTouchMode */,
                    false /* launchActivity */);
    @Rule
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();

    private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
    private final WindowContext mWindowContext = createWindowContext();
@@ -340,17 +347,35 @@ public class WindowContextTest {
    }

    @Test
    public void updateDisplay_wasAttached_detachThenAttachedPropagatedToTokenController() {
    @EnableFlags(Flags.FLAG_REPARENT_WINDOW_TOKEN_API)
    public void reparentToDisplayId_wasAttached_reparentToDisplayAreaPropagatedToTokenController() {
        final WindowTokenClientController mockWindowTokenClientController =
                mock(WindowTokenClientController.class);
        when(mockWindowTokenClientController.attachToDisplayArea(any(), anyInt(), anyInt(),
                any())).thenReturn(true);
        WindowTokenClientController.overrideForTesting(mockWindowTokenClientController);

        mWindowContext.reparentToDisplay(DEFAULT_DISPLAY + 1);

        verify(mockWindowTokenClientController).reparentToDisplayArea(any(),
                /* displayId= */ eq(DEFAULT_DISPLAY + 1)
        );
    }

    @Test
    @EnableFlags(Flags.FLAG_REPARENT_WINDOW_TOKEN_API)
    public void reparentToDisplayId_sameDisplayId_noReparenting() {
        final WindowTokenClientController mockWindowTokenClientController =
                mock(WindowTokenClientController.class);
        when(mockWindowTokenClientController.attachToDisplayArea(any(), anyInt(), anyInt(),
                any())).thenReturn(true);
        WindowTokenClientController.overrideForTesting(mockWindowTokenClientController);

        mWindowContext.updateDisplay(DEFAULT_DISPLAY + 1);
        mWindowContext.reparentToDisplay(DEFAULT_DISPLAY);

        verify(mockWindowTokenClientController).detachIfNeeded(any());
        verify(mockWindowTokenClientController).attachToDisplayArea(any(),
                anyInt(), /* displayId= */ eq(DEFAULT_DISPLAY + 1),
                any());
        verify(mockWindowTokenClientController, never()).reparentToDisplayArea(any(),
                /* displayId= */ eq(DEFAULT_DISPLAY)
        );
    }

    private WindowContext createWindowContext() {
Loading