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

Commit 39fc317d authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Stop assuming the existence of displays when tasks appear" into...

Merge "Stop assuming the existence of displays when tasks appear" into tm-qpr-dev am: 54300c58 am: 4a008524

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



Change-Id: I0e8ff9f83f53dab12dad529c2904bc7c0ee0de6a
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents ca190513 4a008524
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
        mDragResizeCallback = dragResizeCallback;
    }

    @Override
    void relayout(ActivityManager.RunningTaskInfo taskInfo) {
        final int shadowRadiusDp = taskInfo.isFocused
                ? DECOR_SHADOW_FOCUSED_THICKNESS_IN_DIP : DECOR_SHADOW_UNFOCUSED_THICKNESS_IN_DIP;
@@ -119,8 +120,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
        });

        if (mResult.mRootView == null) {
            // This means the task is hidden. Nothing is set up in this case including the
            // decoration surface.
            // This means something blocks the window decor from showing, e.g. the task is hidden.
            // Nothing is set up in this case including the decoration surface.
            return;
        }
        if (oldRootView != mResult.mRootView) {
+81 −10
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ import android.window.WindowContainerTransaction;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;

import java.util.function.Supplier;

/**
 * Manages a container surface and a windowless window to show window decoration. Responsible to
 * update window decoration window state and layout parameters on task info changes and so that
@@ -53,7 +55,8 @@ import com.android.wm.shell.common.DisplayController;
 *
 * @param <T> The type of the root view
 */
public class WindowDecoration<T extends View & TaskFocusStateConsumer> implements AutoCloseable {
public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
        implements AutoCloseable {
    private static final int[] CAPTION_INSETS_TYPES = { InsetsState.ITYPE_CAPTION_BAR };

    /**
@@ -62,6 +65,20 @@ public class WindowDecoration<T extends View & TaskFocusStateConsumer> implement
    final Context mContext;
    final DisplayController mDisplayController;
    final ShellTaskOrganizer mTaskOrganizer;
    final Supplier<SurfaceControl.Builder> mSurfaceControlBuilderSupplier;
    final SurfaceControlViewHostFactory mSurfaceControlViewHostFactory;
    private final DisplayController.OnDisplaysChangedListener mOnDisplaysChangedListener =
            new DisplayController.OnDisplaysChangedListener() {
                @Override
                public void onDisplayAdded(int displayId) {
                    if (mTaskInfo.displayId != displayId) {
                        return;
                    }

                    mDisplayController.removeDisplayWindowListener(this);
                    relayout(mTaskInfo);
                }
            };

    RunningTaskInfo mTaskInfo;
    final SurfaceControl mTaskSurface;
@@ -71,7 +88,7 @@ public class WindowDecoration<T extends View & TaskFocusStateConsumer> implement
    SurfaceControl mDecorationContainerSurface;
    SurfaceControl mTaskBackgroundSurface;

    private CaptionWindowManager mCaptionWindowManager;
    private final CaptionWindowManager mCaptionWindowManager;
    private SurfaceControlViewHost mViewHost;

    private final Rect mCaptionInsetsRect = new Rect();
@@ -84,11 +101,25 @@ public class WindowDecoration<T extends View & TaskFocusStateConsumer> implement
            ShellTaskOrganizer taskOrganizer,
            RunningTaskInfo taskInfo,
            SurfaceControl taskSurface) {
        this(context, displayController, taskOrganizer, taskInfo, taskSurface,
                SurfaceControl.Builder::new, new SurfaceControlViewHostFactory() {});
    }

    WindowDecoration(
            Context context,
            DisplayController displayController,
            ShellTaskOrganizer taskOrganizer,
            RunningTaskInfo taskInfo,
            SurfaceControl taskSurface,
            Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
            SurfaceControlViewHostFactory surfaceControlViewHostFactory) {
        mContext = context;
        mDisplayController = displayController;
        mTaskOrganizer = taskOrganizer;
        mTaskInfo = taskInfo;
        mTaskSurface = taskSurface;
        mSurfaceControlBuilderSupplier = surfaceControlBuilderSupplier;
        mSurfaceControlViewHostFactory = surfaceControlViewHostFactory;

        mDisplay = mDisplayController.getDisplay(mTaskInfo.displayId);
        mDecorWindowContext = mContext.createConfigurationContext(mTaskInfo.getConfiguration());
@@ -99,6 +130,15 @@ public class WindowDecoration<T extends View & TaskFocusStateConsumer> implement
                new CaptionWindowManager(mTaskInfo.getConfiguration(), mTaskSurface);
    }

    /**
     * Used by {@link WindowDecoration} to trigger a new relayout because the requirements for a
     * relayout weren't satisfied are satisfied now.
     *
     * @param taskInfo The previous {@link RunningTaskInfo} passed into {@link #relayout} or the
     *                 constructor.
     */
    abstract void relayout(RunningTaskInfo taskInfo);

    void relayout(RunningTaskInfo taskInfo, int layoutResId, T rootView, float captionHeightDp,
            Rect outsetsDp, float shadowRadiusDp, SurfaceControl.Transaction t,
            WindowContainerTransaction wct, RelayoutResult<T> outResult) {
@@ -110,7 +150,7 @@ public class WindowDecoration<T extends View & TaskFocusStateConsumer> implement
        }

        if (!mTaskInfo.isVisible) {
            close();
            releaseViews();
            t.hide(mTaskSurface);
            return;
        }
@@ -123,10 +163,14 @@ public class WindowDecoration<T extends View & TaskFocusStateConsumer> implement
        rootView = null; // Clear it just in case we use it accidentally
        final Configuration taskConfig = mTaskInfo.getConfiguration();
        if (oldTaskConfig.densityDpi != taskConfig.densityDpi
                || mDisplay == null
                || mDisplay.getDisplayId() != mTaskInfo.displayId) {
            close();
            releaseViews();

            mDisplay = mDisplayController.getDisplay(mTaskInfo.displayId);
            if (!obtainDisplayOrRegisterListener()) {
                outResult.mRootView = null;
                return;
            }
            mDecorWindowContext = mContext.createConfigurationContext(taskConfig);
            if (layoutResId != 0) {
                outResult.mRootView =
@@ -141,7 +185,7 @@ public class WindowDecoration<T extends View & TaskFocusStateConsumer> implement

        // DecorationContainerSurface
        if (mDecorationContainerSurface == null) {
            final SurfaceControl.Builder builder = new SurfaceControl.Builder();
            final SurfaceControl.Builder builder = mSurfaceControlBuilderSupplier.get();
            mDecorationContainerSurface = builder
                    .setName("Decor container of Task=" + mTaskInfo.taskId)
                    .setContainerLayer()
@@ -168,7 +212,7 @@ public class WindowDecoration<T extends View & TaskFocusStateConsumer> implement

        // TaskBackgroundSurface
        if (mTaskBackgroundSurface == null) {
            final SurfaceControl.Builder builder = new SurfaceControl.Builder();
            final SurfaceControl.Builder builder = mSurfaceControlBuilderSupplier.get();
            mTaskBackgroundSurface = builder
                    .setName("Background of Task=" + mTaskInfo.taskId)
                    .setEffectLayer()
@@ -195,7 +239,7 @@ public class WindowDecoration<T extends View & TaskFocusStateConsumer> implement
        lp.setTitle("Caption of Task=" + mTaskInfo.taskId);
        lp.setTrustedOverlay();
        if (mViewHost == null) {
            mViewHost = new SurfaceControlViewHost(mDecorWindowContext, mDisplay,
            mViewHost = mSurfaceControlViewHostFactory.create(mDecorWindowContext, mDisplay,
                    mCaptionWindowManager, true);
            mViewHost.setView(outResult.mRootView, lp);
        } else {
@@ -225,8 +269,22 @@ public class WindowDecoration<T extends View & TaskFocusStateConsumer> implement
                .show(mTaskSurface);
    }

    @Override
    public void close() {
    /**
     * Obtains the {@link Display} instance for the display ID in {@link #mTaskInfo} if it exists or
     * registers {@link #mOnDisplaysChangedListener} if it doesn't.
     *
     * @return {@code true} if the {@link Display} instance exists; or {@code false} otherwise
     */
    private boolean obtainDisplayOrRegisterListener() {
        mDisplay = mDisplayController.getDisplay(mTaskInfo.displayId);
        if (mDisplay == null) {
            mDisplayController.addDisplayWindowListener(mOnDisplaysChangedListener);
            return false;
        }
        return true;
    }

    private void releaseViews() {
        if (mViewHost != null) {
            mViewHost.release();
            mViewHost = null;
@@ -243,6 +301,12 @@ public class WindowDecoration<T extends View & TaskFocusStateConsumer> implement
        }
    }

    @Override
    public void close() {
        mDisplayController.removeDisplayWindowListener(mOnDisplaysChangedListener);
        releaseViews();
    }

    static class RelayoutResult<T extends View & TaskFocusStateConsumer> {
        int mWidth;
        int mHeight;
@@ -267,4 +331,11 @@ public class WindowDecoration<T extends View & TaskFocusStateConsumer> implement
            super.setConfiguration(configuration);
        }
    }

    interface SurfaceControlViewHostFactory {
        default SurfaceControlViewHost create(
                Context c, Display d, WindowlessWindowManager wmm, boolean useSfChoreographer) {
            return new SurfaceControlViewHost(c, d, wmm, useSfChoreographer);
        }
    }
}
+56 −0
Original line number Diff line number Diff line
@@ -14,53 +14,43 @@
 * limitations under the License.
 */

package com.android.wm.shell.pip;
package com.android.wm.shell;

import static org.mockito.Mockito.RETURNS_SELF;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;

import android.graphics.Matrix;
import android.view.SurfaceControl;

/**
 * A dummy {@link SurfaceControl.Transaction} class for testing purpose and supports
 * method chaining.
 * Helper class to provide mocks for {@link SurfaceControl.Builder} and
 * {@link SurfaceControl.Transaction} with method chaining support.
 */
public class PipDummySurfaceControlTx extends SurfaceControl.Transaction {
    @Override
    public SurfaceControl.Transaction setAlpha(SurfaceControl leash, float alpha) {
        return this;
    }
public class MockSurfaceControlHelper {
    private MockSurfaceControlHelper() {}

    @Override
    public SurfaceControl.Transaction setPosition(SurfaceControl leash, float x, float y) {
        return this;
    }

    @Override
    public SurfaceControl.Transaction setWindowCrop(SurfaceControl leash, int w, int h) {
        return this;
    }

    @Override
    public SurfaceControl.Transaction setCornerRadius(SurfaceControl leash, float radius) {
        return this;
    }

    @Override
    public SurfaceControl.Transaction setShadowRadius(SurfaceControl leash, float radius) {
        return this;
    }

    @Override
    public SurfaceControl.Transaction setMatrix(SurfaceControl leash, Matrix matrix,
            float[] float9) {
        return this;
    /**
     * Creates a mock {@link SurfaceControl.Builder} that supports method chaining and return the
     * given {@link SurfaceControl} when calling {@link SurfaceControl.Builder#build()}.
     *
     * @param mockSurfaceControl the first {@link SurfaceControl} to return
     * @param mockSurfaceControls following {@link SurfaceControl} to return
     * @return the mock of {@link SurfaceControl.Builder}
     */
    public static SurfaceControl.Builder createMockSurfaceControlBuilder(
            SurfaceControl mockSurfaceControl, SurfaceControl... mockSurfaceControls) {
        final SurfaceControl.Builder mockBuilder = mock(SurfaceControl.Builder.class, RETURNS_SELF);
        doReturn(mockSurfaceControl, (Object[]) mockSurfaceControls)
                .when(mockBuilder)
                .build();
        return mockBuilder;
    }

    @Override
    public SurfaceControl.Transaction setFrameTimelineVsync(long frameTimelineVsyncId) {
        return this;
    /**
     * Creates a mock {@link SurfaceControl.Transaction} that supports method chaining.
     * @return the mock of {@link SurfaceControl.Transaction}
     */
    public static SurfaceControl.Transaction createMockSurfaceControlTransaction() {
        return mock(SurfaceControl.Transaction.class, RETURNS_SELF);
    }

    @Override
    public void apply() {}
}
+32 −1
Original line number Diff line number Diff line
@@ -25,8 +25,10 @@ import static org.mockito.Mockito.mock;

import android.app.ActivityManager;
import android.app.WindowConfiguration;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.IBinder;
import android.view.Display;
import android.window.IWindowContainerToken;
import android.window.WindowContainerToken;

@@ -38,6 +40,10 @@ public final class TestRunningTaskInfoBuilder {
    private int mParentTaskId = INVALID_TASK_ID;
    private @WindowConfiguration.ActivityType int mActivityType = ACTIVITY_TYPE_STANDARD;
    private @WindowConfiguration.WindowingMode int mWindowingMode = WINDOWING_MODE_UNDEFINED;
    private int mDisplayId = Display.DEFAULT_DISPLAY;
    private ActivityManager.TaskDescription.Builder mTaskDescriptionBuilder = null;
    private final Point mPositionInParent = new Point();
    private boolean mIsVisible = false;

    public static WindowContainerToken createMockWCToken() {
        final IWindowContainerToken itoken = mock(IWindowContainerToken.class);
@@ -68,17 +74,42 @@ public final class TestRunningTaskInfoBuilder {
        return this;
    }

    public TestRunningTaskInfoBuilder setDisplayId(int displayId) {
        mDisplayId = displayId;
        return this;
    }

    public TestRunningTaskInfoBuilder setTaskDescriptionBuilder(
            ActivityManager.TaskDescription.Builder builder) {
        mTaskDescriptionBuilder = builder;
        return this;
    }

    public TestRunningTaskInfoBuilder setPositionInParent(int x, int y) {
        mPositionInParent.set(x, y);
        return this;
    }

    public TestRunningTaskInfoBuilder setVisible(boolean isVisible) {
        mIsVisible = isVisible;
        return this;
    }

    public ActivityManager.RunningTaskInfo build() {
        final ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
        info.parentTaskId = INVALID_TASK_ID;
        info.taskId = sNextTaskId++;
        info.parentTaskId = mParentTaskId;
        info.displayId = mDisplayId;
        info.configuration.windowConfiguration.setBounds(mBounds);
        info.configuration.windowConfiguration.setActivityType(mActivityType);
        info.configuration.windowConfiguration.setWindowingMode(mWindowingMode);
        info.token = mToken;
        info.isResizeable = true;
        info.supportsMultiWindow = true;
        info.taskDescription =
                mTaskDescriptionBuilder != null ? mTaskDescriptionBuilder.build() : null;
        info.positionInParent = mPositionInParent;
        info.isVisible = mIsVisible;
        return info;
    }
}
+7 −3
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;

import static com.android.wm.shell.MockSurfaceControlHelper.createMockSurfaceControlTransaction;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;

@@ -37,6 +38,7 @@ import android.view.SurfaceControl;

import androidx.test.filters.SmallTest;

import com.android.wm.shell.MockSurfaceControlHelper;
import com.android.wm.shell.ShellTestCase;

import org.junit.Before;
@@ -103,7 +105,8 @@ public class PipAnimationControllerTest extends ShellTestCase {
        final PipAnimationController.PipTransitionAnimator oldAnimator = mPipAnimationController
                .getAnimator(mTaskInfo, mLeash, baseValue, startValue, endValue1, null,
                        TRANSITION_DIRECTION_TO_PIP, 0, ROTATION_0);
        oldAnimator.setSurfaceControlTransactionFactory(PipDummySurfaceControlTx::new);
        oldAnimator.setSurfaceControlTransactionFactory(
                MockSurfaceControlHelper::createMockSurfaceControlTransaction);
        oldAnimator.start();

        final PipAnimationController.PipTransitionAnimator newAnimator = mPipAnimationController
@@ -133,7 +136,7 @@ public class PipAnimationControllerTest extends ShellTestCase {

    @Test
    public void pipTransitionAnimator_rotatedEndValue() {
        final PipDummySurfaceControlTx tx = new PipDummySurfaceControlTx();
        final SurfaceControl.Transaction tx = createMockSurfaceControlTransaction();
        final Rect startBounds = new Rect(200, 700, 400, 800);
        final Rect endBounds = new Rect(0, 0, 500, 1000);
        // Fullscreen to PiP.
@@ -183,7 +186,8 @@ public class PipAnimationControllerTest extends ShellTestCase {
        final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
                .getAnimator(mTaskInfo, mLeash, baseValue, startValue, endValue, null,
                        TRANSITION_DIRECTION_TO_PIP, 0, ROTATION_0);
        animator.setSurfaceControlTransactionFactory(PipDummySurfaceControlTx::new);
        animator.setSurfaceControlTransactionFactory(
                MockSurfaceControlHelper::createMockSurfaceControlTransaction);

        animator.setPipAnimationCallback(mPipAnimationCallback);

Loading