Report changed keep clear areas to TvPipController
Bug: 218416347 Test: atest DisplayContentTests#testKeepClearAreasMultipleWindows Test: atest WindowStateTests#testKeepClearAreas Change-Id: Ic61b1f11a27b0411baa5dfc5146c96700f751527
This commit is contained in:
@@ -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) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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,11 +5456,17 @@ 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);
|
||||
mWmService.mDisplayNotificationController.dispatchKeepClearAreasChanged(
|
||||
this, restrictedKeepClearAreas, unrestrictedKeepClearAreas);
|
||||
|
||||
if (!mRestrictedKeepClearAreas.equals(restrictedKeepClearAreas)
|
||||
|| !mUnrestrictedKeepClearAreas.equals(unrestrictedKeepClearAreas)) {
|
||||
mRestrictedKeepClearAreas = restrictedKeepClearAreas;
|
||||
mUnrestrictedKeepClearAreas = unrestrictedKeepClearAreas;
|
||||
mWmService.mDisplayNotificationController.dispatchKeepClearAreasChanged(
|
||||
this, restrictedKeepClearAreas, unrestrictedKeepClearAreas);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,8 @@ import android.os.RemoteException;
|
||||
import android.util.IntArray;
|
||||
import android.view.IDisplayWindowListener;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Manages dispatch of relevant hierarchy changes to interested listeners. Listeners are assumed
|
||||
@@ -120,13 +121,13 @@ class DisplayWindowListenerController {
|
||||
mDisplayListeners.finishBroadcast();
|
||||
}
|
||||
|
||||
void dispatchKeepClearAreasChanged(DisplayContent display, List<Rect> restricted,
|
||||
List<Rect> unrestricted) {
|
||||
void dispatchKeepClearAreasChanged(DisplayContent display, Set<Rect> restricted,
|
||||
Set<Rect> unrestricted) {
|
||||
int count = mDisplayListeners.beginBroadcast();
|
||||
for (int i = 0; i < count; ++i) {
|
||||
try {
|
||||
mDisplayListeners.getBroadcastItem(i).onKeepClearAreasChanged(
|
||||
display.mDisplayId, restricted, unrestricted);
|
||||
mDisplayListeners.getBroadcastItem(i).onKeepClearAreasChanged(display.mDisplayId,
|
||||
new ArrayList<>(restricted), new ArrayList<>(unrestricted));
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,6 +263,7 @@ import dalvik.annotation.optimization.NeverCompile;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
@@ -1034,10 +1035,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
* The system is more careful about restricted ones and may apply restrictions to them, while
|
||||
* the unrestricted ones are considered safe.
|
||||
*
|
||||
* @param outRestricted list to add restricted keep-clear areas to
|
||||
* @param outUnrestricted list to add unrestricted keep-clear areas to
|
||||
* @param outRestricted collection to add restricted keep-clear areas to
|
||||
* @param outUnrestricted collection to add unrestricted keep-clear areas to
|
||||
*/
|
||||
void getKeepClearAreas(List<Rect> outRestricted, List<Rect> outUnrestricted) {
|
||||
void getKeepClearAreas(Collection<Rect> outRestricted, Collection<Rect> outUnrestricted) {
|
||||
final Matrix tmpMatrix = new Matrix();
|
||||
final float[] tmpFloat9 = new float[9];
|
||||
getKeepClearAreas(outRestricted, outUnrestricted, tmpMatrix, tmpFloat9);
|
||||
@@ -1049,13 +1050,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
* The system is more careful about restricted ones and may apply restrictions to them, while
|
||||
* the unrestricted ones are considered safe.
|
||||
*
|
||||
* @param outRestricted list to add restricted keep-clear areas to
|
||||
* @param outUnrestricted list to add unrestricted keep-clear areas to
|
||||
* @param outRestricted collection to add restricted keep-clear areas to
|
||||
* @param outUnrestricted collection to add unrestricted keep-clear areas to
|
||||
* @param tmpMatrix a temporary matrix to be used for transformations
|
||||
* @param float9 a temporary array of 9 floats
|
||||
*/
|
||||
void getKeepClearAreas(List<Rect> outRestricted, List<Rect> outUnrestricted, Matrix tmpMatrix,
|
||||
float[] float9) {
|
||||
void getKeepClearAreas(Collection<Rect> outRestricted, Collection<Rect> outUnrestricted,
|
||||
Matrix tmpMatrix, float[] float9) {
|
||||
outRestricted.addAll(getRectsInScreenSpace(mKeepClearAreas, tmpMatrix, float9));
|
||||
outUnrestricted.addAll(
|
||||
getRectsInScreenSpace(mUnrestrictedKeepClearAreas, tmpMatrix, float9));
|
||||
|
||||
@@ -2388,19 +2388,18 @@ public class DisplayContentTests extends WindowTestsBase {
|
||||
w2.setKeepClearAreas(Arrays.asList(rect2), Collections.emptyList());
|
||||
|
||||
// No keep clear areas on display, because the windows are not visible
|
||||
assertEquals(Arrays.asList(), mDisplayContent.getKeepClearAreas());
|
||||
assertEquals(Collections.emptySet(), mDisplayContent.getKeepClearAreas());
|
||||
|
||||
makeWindowVisible(w1);
|
||||
|
||||
// The returned keep-clear areas contain the areas just from the visible window
|
||||
assertEquals(new ArraySet(Arrays.asList(rect1)),
|
||||
new ArraySet(mDisplayContent.getKeepClearAreas()));
|
||||
assertEquals(new ArraySet(Arrays.asList(rect1)), mDisplayContent.getKeepClearAreas());
|
||||
|
||||
makeWindowVisible(w1, w2);
|
||||
|
||||
// The returned keep-clear areas contain the areas from all visible windows
|
||||
assertEquals(new ArraySet(Arrays.asList(rect1, rect2)),
|
||||
new ArraySet(mDisplayContent.getKeepClearAreas()));
|
||||
mDisplayContent.getKeepClearAreas());
|
||||
}
|
||||
|
||||
private void removeRootTaskTests(Runnable runnable) {
|
||||
|
||||
Reference in New Issue
Block a user