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

Commit a197b975 authored by Robert Horvath's avatar Robert Horvath
Browse files

Report changed keep clear areas to TvPipController

Bug: 218416347
Test: atest DisplayContentTests#testKeepClearAreasMultipleWindows
Test: atest WindowStateTests#testKeepClearAreas
Change-Id: Ic61b1f11a27b0411baa5dfc5146c96700f751527
parent b34bc34f
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.os.RemoteException;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
@@ -36,6 +37,7 @@ import com.android.wm.shell.common.annotations.ShellMainThread;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * This module deals with display rotations coming from WM. When WM starts a rotation: after it has
@@ -245,8 +247,8 @@ public class DisplayController {
        }
    }

    private void onKeepClearAreasChanged(int displayId, List<Rect> restricted,
            List<Rect> unrestricted) {
    private void onKeepClearAreasChanged(int displayId, Set<Rect> restricted,
            Set<Rect> unrestricted) {
        synchronized (mDisplays) {
            if (mDisplays.get(displayId) == null || getDisplay(displayId) == null) {
                Slog.w(TAG, "Skipping onKeepClearAreasChanged on unknown"
@@ -323,7 +325,8 @@ public class DisplayController {
        public void onKeepClearAreasChanged(int displayId, List<Rect> restricted,
                List<Rect> unrestricted) {
            mMainExecutor.execute(() -> {
                DisplayController.this.onKeepClearAreasChanged(displayId, restricted, unrestricted);
                DisplayController.this.onKeepClearAreasChanged(displayId,
                        new ArraySet<>(restricted), new ArraySet<>(unrestricted));
            });
        }
    }
@@ -364,7 +367,7 @@ public class DisplayController {
        /**
         * Called when keep-clear areas on a display have changed.
         */
        default void onKeepClearAreasChanged(int displayId, List<Rect> restricted,
                List<Rect> unrestricted) {}
        default void onKeepClearAreasChanged(int displayId, Set<Rect> restricted,
                Set<Rect> unrestricted) {}
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ public abstract class TvPipModule {
            PipTransitionController pipTransitionController,
            TvPipNotificationController tvPipNotificationController,
            TaskStackListenerImpl taskStackListener,
            DisplayController displayController,
            WindowManagerShellWrapper windowManagerShellWrapper,
            @ShellMainThread ShellExecutor mainExecutor) {
        return Optional.of(
@@ -81,6 +82,7 @@ public abstract class TvPipModule {
                        pipMediaController,
                        tvPipNotificationController,
                        taskStackListener,
                        displayController,
                        windowManagerShellWrapper,
                        mainExecutor));
    }
+39 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.content.pm.ActivityInfo;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.RemoteException;
import android.util.ArraySet;
import android.util.Log;
import android.util.Size;
import android.view.Display;
@@ -43,6 +44,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;

/**
@@ -90,6 +92,24 @@ public class PipBoundsState {
    private int mShelfHeight;
    /** Whether the user has resized the PIP manually. */
    private boolean mHasUserResizedPip;
    /**
     * Areas defined by currently visible apps that they prefer to keep clear from overlays such as
     * the PiP. Restricted areas may only move the PiP a limited amount from its anchor position.
     * The system will try to respect these areas, but when not possible will ignore them.
     *
     * @see android.view.View#setPreferKeepClearRects
     */
    private final Set<Rect> mRestrictedKeepClearAreas = new ArraySet<>();
    /**
     * Areas defined by currently visible apps holding
     * {@link android.Manifest.permission#SET_UNRESTRICTED_KEEP_CLEAR_AREAS} that they prefer to
     * keep clear from overlays such as the PiP.
     * Unrestricted areas can move the PiP farther than restricted areas, and the system will try
     * harder to respect these areas.
     *
     * @see android.view.View#setPreferKeepClearRects
     */
    private final Set<Rect> mUnrestrictedKeepClearAreas = new ArraySet<>();

    private @Nullable Runnable mOnMinimalSizeChangeCallback;
    private @Nullable TriConsumer<Boolean, Integer, Boolean> mOnShelfVisibilityChangeCallback;
@@ -367,6 +387,25 @@ public class PipBoundsState {
        }
    }

    /** Set the keep clear areas onscreen. The PiP should ideally not cover them. */
    public void setKeepClearAreas(@NonNull Set<Rect> restrictedAreas,
            @NonNull Set<Rect> unrestrictedAreas) {
        mRestrictedKeepClearAreas.clear();
        mRestrictedKeepClearAreas.addAll(restrictedAreas);
        mUnrestrictedKeepClearAreas.clear();
        mUnrestrictedKeepClearAreas.addAll(unrestrictedAreas);
    }

    @NonNull
    public Set<Rect> getRestrictedKeepClearAreas() {
        return mRestrictedKeepClearAreas;
    }

    @NonNull
    public Set<Rect> getUnrestrictedKeepClearAreas() {
        return mUnrestrictedKeepClearAreas;
    }

    /**
     * Initialize states when first entering PiP.
     */
+17 −1
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.view.Gravity;

import com.android.wm.shell.R;
import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TaskStackListenerCallback;
@@ -50,12 +51,14 @@ import com.android.wm.shell.pip.PipTransitionController;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Set;

/**
 * Manages the picture-in-picture (PIP) UI and states.
 */
public class TvPipController implements PipTransitionController.PipTransitionCallback,
        TvPipMenuController.Delegate, TvPipNotificationController.Delegate {
        TvPipMenuController.Delegate, TvPipNotificationController.Delegate,
        DisplayController.OnDisplaysChangedListener {
    private static final String TAG = "TvPipController";
    static final boolean DEBUG = false;

@@ -112,6 +115,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
            PipMediaController pipMediaController,
            TvPipNotificationController pipNotificationController,
            TaskStackListenerImpl taskStackListener,
            DisplayController displayController,
            WindowManagerShellWrapper wmShell,
            ShellExecutor mainExecutor) {
        return new TvPipController(
@@ -124,6 +128,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
                pipMediaController,
                pipNotificationController,
                taskStackListener,
                displayController,
                wmShell,
                mainExecutor).mImpl;
    }
@@ -138,6 +143,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
            PipMediaController pipMediaController,
            TvPipNotificationController pipNotificationController,
            TaskStackListenerImpl taskStackListener,
            DisplayController displayController,
            WindowManagerShellWrapper wmShell,
            ShellExecutor mainExecutor) {
        mContext = context;
@@ -163,6 +169,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal

        registerTaskStackListenerCallback(taskStackListener);
        registerWmShellPinnedStackListener(wmShell);
        displayController.addDisplayWindowListener(this);
    }

    private void onConfigurationChanged(Configuration newConfig) {
@@ -253,6 +260,15 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
        return mTvPipBoundsState.getTvFixedPipOrientation();
    }

    @Override
    public void onKeepClearAreasChanged(int displayId, Set<Rect> restricted,
            Set<Rect> unrestricted) {
        if (mTvPipBoundsState.getDisplayId() == displayId) {
            mTvPipBoundsState.setKeepClearAreas(restricted, unrestricted);
            movePinnedStack();
        }
    }

    /**
     * Animate to the updated position of the PiP based on the state and position of the PiP.
     */
+17 −8
Original line number Diff line number Diff line
@@ -414,6 +414,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    private final Region mSystemGestureExclusionUnrestricted = new Region();
    private int mSystemGestureExclusionLimit;

    private Set<Rect> mRestrictedKeepClearAreas = new ArraySet<>();
    private Set<Rect> mUnrestrictedKeepClearAreas = new ArraySet<>();

    /**
     * For default display it contains real metrics, empty for others.
     * @see WindowManagerService#createWatermark()
@@ -3351,7 +3354,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            pw.println(mSystemGestureExclusion);
        }

        final List<Rect> keepClearAreas = getKeepClearAreas();
        final Set<Rect> keepClearAreas = getKeepClearAreas();
        if (!keepClearAreas.isEmpty()) {
            pw.println();
            pw.print("  keepClearAreas=");
@@ -5453,12 +5456,18 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    }

    void updateKeepClearAreas() {
        final List<Rect> restrictedKeepClearAreas = new ArrayList();
        final List<Rect> unrestrictedKeepClearAreas = new ArrayList();
        final Set<Rect> restrictedKeepClearAreas = new ArraySet<>();
        final Set<Rect> unrestrictedKeepClearAreas = new ArraySet<>();
        getKeepClearAreas(restrictedKeepClearAreas, unrestrictedKeepClearAreas);

        if (!mRestrictedKeepClearAreas.equals(restrictedKeepClearAreas)
                || !mUnrestrictedKeepClearAreas.equals(unrestrictedKeepClearAreas)) {
            mRestrictedKeepClearAreas = restrictedKeepClearAreas;
            mUnrestrictedKeepClearAreas = unrestrictedKeepClearAreas;
            mWmService.mDisplayNotificationController.dispatchKeepClearAreasChanged(
                    this, restrictedKeepClearAreas, unrestrictedKeepClearAreas);
        }
    }

    /**
     * Fills {@param outRestricted} with all keep-clear areas from visible, relevant windows
@@ -5469,7 +5478,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
     * For context on restricted vs unrestricted keep-clear areas, see
     * {@link android.Manifest.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS}.
     */
    void getKeepClearAreas(List<Rect> outRestricted, List<Rect> outUnrestricted) {
    void getKeepClearAreas(Set<Rect> outRestricted, Set<Rect> outUnrestricted) {
        final Matrix tmpMatrix = new Matrix();
        final float[] tmpFloat9 = new float[9];
        forAllWindows(w -> {
@@ -5486,8 +5495,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
    /**
     * Returns all keep-clear areas from visible, relevant windows on this display.
     */
    ArrayList<Rect> getKeepClearAreas() {
        final ArrayList<Rect> keepClearAreas = new ArrayList<Rect>();
    Set<Rect> getKeepClearAreas() {
        final Set<Rect> keepClearAreas = new ArraySet<>();
        getKeepClearAreas(keepClearAreas, keepClearAreas);
        return keepClearAreas;
    }
Loading