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

Commit 24e52cc3 authored by Merissa Mitchell's avatar Merissa Mitchell
Browse files

[PiP on CD] Adjust rounded corners radius

for the current display, after the current display is updated in
PipDisplayLayoutState.

Also add a DisplayIdListener interface to inform PiP classes of display
id changes in PipDisplayLayoutState.

Recall: http://recall/clips/3e525e7a-06af-499a-9767-ccca7da0921b

Bug: 416788909
Test: atest WMShellUnitTests:com.android.wm.shell.pip2
Test: atest WMShellUnitTests:com.android.wm.shell.pip
Test: atest WMShellUnitTests:com.android.wm.shell.common.pip
Test: Manual - enter PiP on external display, verify that rounded
corners are scaled
Flag: com.android.window.flags.enable_connected_displays_pip

Change-Id: Id6417848341efc7bf2ab531444ae9d8fee8b99dd
parent c01d0372
Loading
Loading
Loading
Loading
+52 −9
Original line number Diff line number Diff line
@@ -26,9 +26,7 @@ import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.Size;
import android.view.Display;
import android.view.Surface;
import android.view.WindowManager;

import androidx.annotation.NonNull;

@@ -36,8 +34,11 @@ import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.dagger.WMSingleton;
import com.android.wm.shell.sysui.ShellInit;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;

@@ -48,18 +49,27 @@ import javax.inject.Inject;
public class PipDisplayLayoutState {
    private static final String TAG = PipDisplayLayoutState.class.getSimpleName();

    private Context mContext;
    private final Context mContext;
    private Context mUiContext;
    private int mDisplayId;
    @NonNull private DisplayLayout mDisplayLayout;
    @NonNull private final DisplayController mDisplayController;
    private Point mScreenEdgeInsets = null;
    private Insets mNavigationBarsInsets = Insets.NONE;
    private final List<DisplayIdListener> mDisplayIdListeners = new ArrayList<>();

    @Inject
    public PipDisplayLayoutState(Context context, @NonNull DisplayController displayController) {
    public PipDisplayLayoutState(Context context, @NonNull DisplayController displayController,
            ShellInit shellInit) {
        mContext = context;
        mUiContext = context;
        mDisplayLayout = new DisplayLayout();
        mDisplayController = displayController;
        shellInit.addInitCallback(this::onInit, this);
    }

    /** Called when Shell is done initializing. */
    public void onInit() {
        reloadResources();
    }

@@ -69,7 +79,7 @@ public class PipDisplayLayoutState {
    }

    private void reloadResources() {
        Resources res = mContext.getResources();
        Resources res = mUiContext.getResources();

        final String screenEdgeInsetsDpString = res.getString(
                R.string.config_defaultPictureInPictureScreenEdgeInsets);
@@ -131,7 +141,7 @@ public class PipDisplayLayoutState {
     * @param targetRotation
     */
    public void rotateTo(@Surface.Rotation int targetRotation) {
        mDisplayLayout.rotateTo(mContext.getResources(), targetRotation);
        mDisplayLayout.rotateTo(mUiContext.getResources(), targetRotation);
    }

    /** Returns the current display rotation of this layout state. */
@@ -147,14 +157,38 @@ public class PipDisplayLayoutState {

    /** Set the current display id for the associated display layout. */
    public void setDisplayId(int displayId) {
        if (mDisplayId == displayId) {
            return;
        }

        mDisplayId = displayId;
        updateUiContext();
    }

    private void updateUiContext() {
        final Context newContext = mDisplayController.getDisplayContext(mDisplayId);
        if (newContext == null) {
            return;
        }

        mUiContext = newContext;
        reloadResources();
        for (DisplayIdListener listener : mDisplayIdListeners) {
            listener.onDisplayIdChanged(mUiContext);
        }
    }

    /** Returns the context associated with the current display. */
    public Context getCurrentUiContext() {
        Display display = mDisplayController.getDisplay(mDisplayId);
        return mContext.createWindowContext(display,
                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, /* options= */null);
        return mUiContext;
    }

    /** Registers a DisplayIdListener. */
    public void addDisplayIdListener(DisplayIdListener listener) {
        if (mDisplayIdListeners.contains(listener)) {
            return;
        }
        mDisplayIdListeners.add(listener);
    }

    /** Set the navigationBars side and widthOrHeight. */
@@ -171,4 +205,13 @@ public class PipDisplayLayoutState {
        pw.println(innerPrefix + "mScreenEdgeInsets=" + mScreenEdgeInsets);
        pw.println(innerPrefix + "mNavigationBarsInsets=" + mNavigationBarsInsets);
    }

    /** Listener interface for display id changes. */
    public interface DisplayIdListener {
        /**
         * Informs listener of display id change. Default implementation does nothing.
         * @param displayContext associated with the updated display
         */
        default void onDisplayIdChanged(@NonNull Context displayContext) {}
    }
}
+10 −7
Original line number Diff line number Diff line
@@ -228,11 +228,12 @@ public abstract class Pip2Module {
            PipTransitionState pipTransitionState,
            PipScheduler pipScheduler, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
            PipBoundsState pipBoundsState, DisplayController displayController,
            PipDisplayLayoutState pipDisplayLayoutState, PipBoundsAlgorithm pipBoundsAlgorithm
            PipDisplayLayoutState pipDisplayLayoutState, PipBoundsAlgorithm pipBoundsAlgorithm,
            PipSurfaceTransactionHelper pipSurfaceTransactionHelper
    ) {
        return new PipDisplayTransferHandler(context, pipTransitionState, pipScheduler,
                rootTaskDisplayAreaOrganizer, pipBoundsState, displayController,
                pipDisplayLayoutState, pipBoundsAlgorithm);
                pipDisplayLayoutState, pipBoundsAlgorithm, pipSurfaceTransactionHelper);
    }

    @WMSingleton
@@ -244,10 +245,12 @@ public abstract class Pip2Module {
            PipScheduler pipScheduler,
            Optional<PipPerfHintController> pipPerfHintControllerOptional,
            PipTransitionState pipTransitionState,
            PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
            PipUiEventLogger pipUiEventLogger, PipDisplayLayoutState pipDisplayLayoutState) {
        return new PipMotionHelper(context, pipBoundsState, menuController, pipSnapAlgorithm,
                floatingContentCoordinator, pipScheduler, pipPerfHintControllerOptional,
                pipTransitionState, pipUiEventLogger, pipDisplayLayoutState);
                pipTransitionState, pipSurfaceTransactionHelper, pipUiEventLogger,
                pipDisplayLayoutState);
    }

    @WMSingleton
@@ -275,8 +278,7 @@ public abstract class Pip2Module {
            PipBoundsAlgorithm pipBoundsAlgorithm,
            @ShellMainThread ShellExecutor mainExecutor) {
        return new PipTaskListener(context, pipSurfaceTransactionHelper, shellTaskOrganizer,
                pipTransitionState,
                pipScheduler, pipBoundsState, pipBoundsAlgorithm, mainExecutor);
                pipTransitionState, pipScheduler, pipBoundsState, pipBoundsAlgorithm, mainExecutor);
    }

    @WMSingleton
@@ -326,7 +328,8 @@ public abstract class Pip2Module {

    @WMSingleton
    @Provides
    static PipSurfaceTransactionHelper providePipSurfaceTransactionHelper(Context context) {
        return new PipSurfaceTransactionHelper(context);
    static PipSurfaceTransactionHelper providePipSurfaceTransactionHelper(Context context,
            @NonNull ShellInit shellInit, PipDisplayLayoutState pipDisplayLayoutState) {
        return new PipSurfaceTransactionHelper(context, shellInit, pipDisplayLayoutState);
    }
}
+33 −10
Original line number Diff line number Diff line
@@ -24,32 +24,51 @@ import android.gui.BoxShadowSettings;
import android.view.Choreographer;
import android.view.SurfaceControl;

import androidx.annotation.NonNull;

import com.android.wm.shell.Flags;
import com.android.wm.shell.R;
import com.android.wm.shell.common.BoxShadowHelper;
import com.android.wm.shell.common.pip.PipDisplayLayoutState;
import com.android.wm.shell.common.pip.PipUtils;
import com.android.wm.shell.sysui.ShellInit;

/**
 * Abstracts the common operations on {@link SurfaceControl.Transaction} for PiP transition.
 */
public class PipSurfaceTransactionHelper {
public class PipSurfaceTransactionHelper implements PipDisplayLayoutState.DisplayIdListener {
    private final Matrix mTmpTransform = new Matrix();
    private final float[] mTmpFloat9 = new float[9];
    private final Rect mTmpDestinationRect = new Rect();

    private final int mCornerRadius;
    private final int mShadowRadius;
    private final float mMirrorOpacity;
    private int mCornerRadius;
    private int mShadowRadius;
    private float mMirrorOpacity;

    private BoxShadowSettings mBoxShadowSettings;
    private BorderSettings mBorderSettings;
    private Context mContext;
    private PipDisplayLayoutState mPipDisplayLayoutState;

    public PipSurfaceTransactionHelper(Context context, @NonNull ShellInit shellInit,
            PipDisplayLayoutState pipDisplayLayoutState) {
        mContext = context;
        mPipDisplayLayoutState = pipDisplayLayoutState;
        shellInit.addInitCallback(this::onInit, this);
    }

    /** Called when Shell is done initializing. */
    public void onInit() {
        mPipDisplayLayoutState.addDisplayIdListener(this);
        onThemeChanged(mContext);
        reloadResources();
    }

    public PipSurfaceTransactionHelper(Context context) {
        mCornerRadius = context.getResources().getDimensionPixelSize(R.dimen.pip_corner_radius);
        mShadowRadius = context.getResources().getDimensionPixelSize(R.dimen.pip_shadow_radius);
        mMirrorOpacity = context.getResources().getFloat(
    private void reloadResources() {
        mCornerRadius = mContext.getResources().getDimensionPixelSize(R.dimen.pip_corner_radius);
        mShadowRadius = mContext.getResources().getDimensionPixelSize(R.dimen.pip_shadow_radius);
        mMirrorOpacity = mContext.getResources().getFloat(
                R.dimen.config_pipDraggingAcrossDisplaysOpacity);
        onThemeChanged(context);
    }

    /**
@@ -76,7 +95,11 @@ public class PipSurfaceTransactionHelper {
        }
    }


    @Override
    public void onDisplayIdChanged(@NonNull Context context) {
        mContext = context;
        reloadResources();
    }

    /**
     * Gets corner radius which is loaded from resources.
+25 −30
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@ import androidx.annotation.NonNull;

import com.android.wm.shell.R;
import com.android.wm.shell.bubbles.DismissViewUtils;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.pip.PipDisplayLayoutState;
import com.android.wm.shell.common.pip.PipUiEventLogger;
@@ -47,7 +46,8 @@ import kotlin.Unit;
/**
 * Handler of all Magnetized Object related code for PiP.
 */
public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListener {
public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListener,
        PipDisplayLayoutState.DisplayIdListener {

    /* The multiplier to apply scale the target size by when applying the magnetic field radius */
    private static final float MAGNETIC_FIELD_RADIUS_MULTIPLIER = 1.25f;
@@ -90,33 +90,34 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
    private final PipMotionHelper mMotionHelper;
    private final PipUiEventLogger mPipUiEventLogger;
    private WindowManager mWindowManager;
    /** The display id for the display that is associated with mWindowManager. */
    private int mWindowManagerDisplayId = -1;
    private final PipDisplayLayoutState mPipDisplayLayoutState;
    private final DisplayController mDisplayController;
    private final ShellExecutor mMainExecutor;

    public PipDismissTargetHandler(Context context, PipUiEventLogger pipUiEventLogger,
            PipMotionHelper motionHelper, PipDisplayLayoutState pipDisplayLayoutState,
            DisplayController displayController, ShellExecutor mainExecutor) {
            ShellExecutor mainExecutor) {
        mContext = context;
        mPipUiEventLogger = pipUiEventLogger;
        mMotionHelper = motionHelper;
        mPipDisplayLayoutState = pipDisplayLayoutState;
        mDisplayController = displayController;
        mMainExecutor = mainExecutor;
        mWindowManager = mContext.getSystemService(WindowManager.class);

        pipDisplayLayoutState.addDisplayIdListener(this);
    }

    private void maybeCleanUpDismissTarget() {
        if (mTargetViewContainer != null) {
            // Remove the old view from view hierarchy
            cleanUpDismissTarget();
        }
    }

    void init() {
        maybeCleanUpDismissTarget();

        Resources res = mContext.getResources();
        mEnableDismissDragToEdge = res.getBoolean(R.bool.config_pipEnableDismissDragToEdge);
        mDismissAreaHeight = res.getDimensionPixelSize(R.dimen.floating_dismiss_gradient_height);

        if (mTargetViewContainer != null) {
            // init can be called multiple times, remove the old one from view hierarchy first.
            cleanUpDismissTarget();
        }

        mTargetViewContainer = new DismissView(mContext);
        DismissViewUtils.setup(mTargetViewContainer);
        mTargetView = mTargetViewContainer.getCircle();
@@ -189,6 +190,16 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
        return true;
    }

    @Override
    public void onDisplayIdChanged(@NonNull Context context) {
        maybeCleanUpDismissTarget();

        mContext = context;
        mWindowManager = mContext.getSystemService(WindowManager.class);
        // If the displayId has changed, reset the UI for the current display
        init();
    }

    /**
     * Potentially start consuming future motion events if PiP is currently near the magnetized
     * object.
@@ -251,8 +262,6 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen

    /** Adds the magnetic target view to the WindowManager so it's ready to be animated in. */
    public void createOrUpdateDismissTarget() {
        getWindowManager();

        if (mTargetViewContainer.getParent() == null) {
            mTargetViewContainer.cancelAnimators();

@@ -322,18 +331,4 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
            mWindowManager.removeViewImmediate(mTargetViewContainer);
        }
    }

    /** Sets mWindowManager to WindowManager associated with the display where PiP is active on. */
    private void getWindowManager() {
        final int pipDisplayId = mPipDisplayLayoutState.getDisplayId();
        if (mWindowManager != null && pipDisplayId == mWindowManagerDisplayId) {
            return;
        }
        mWindowManagerDisplayId = pipDisplayId;
        mContext = mPipDisplayLayoutState.getCurrentUiContext();
        mWindowManager = mContext.getSystemService(WindowManager.class);
        // TODO(b/414864788): Utilize display-id change callback for updating UI
        // If the displayId has changed, reset the UI for the current display
        init();
    }
}
+3 −2
Original line number Diff line number Diff line
@@ -75,7 +75,8 @@ public class PipDisplayTransferHandler implements
    public PipDisplayTransferHandler(Context context, PipTransitionState pipTransitionState,
            PipScheduler pipScheduler, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
            PipBoundsState pipBoundsState, DisplayController displayController,
            PipDisplayLayoutState pipDisplayLayoutState, PipBoundsAlgorithm pipBoundsAlgorithm) {
            PipDisplayLayoutState pipDisplayLayoutState, PipBoundsAlgorithm pipBoundsAlgorithm,
            PipSurfaceTransactionHelper pipSurfaceTransactionHelper) {
        mContext = context;
        mPipTransitionState = pipTransitionState;
        mPipTransitionState.addPipTransitionStateChangedListener(this);
@@ -83,7 +84,7 @@ public class PipDisplayTransferHandler implements
        mSurfaceControlTransactionFactory =
                new PipSurfaceTransactionHelper.VsyncSurfaceControlTransactionFactory();
        mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer;
        mPipSurfaceTransactionHelper = new PipSurfaceTransactionHelper(context);
        mPipSurfaceTransactionHelper = pipSurfaceTransactionHelper;
        mPipBoundsState = pipBoundsState;
        mDisplayController = displayController;
        mPipDisplayLayoutState = pipDisplayLayoutState;
Loading