summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java18
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java133
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java18
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java19
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipKeepClearAlgorithm.java44
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipKeepClearAlgorithm.kt42
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java35
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/SplitScreenController.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java17
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java15
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipKeepClearAlgorithmTest.java96
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java2
15 files changed, 350 insertions, 108 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
index e528df8c89b4..3f0b01bef0ce 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
@@ -131,7 +131,7 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou
mDisplayController.getDisplayContext(mRootTaskInfo.displayId),
mRootTaskInfo.configuration, this /* layoutChangeListener */,
mParentContainerCallbacks, mDisplayImeController, mController.getTaskOrganizer(),
- true /* applyDismissingParallax */);
+ SplitLayout.PARALLAX_DISMISSING);
mDisplayInsetsController.addInsetsChangedListener(mRootTaskInfo.displayId, mSplitLayout);
final WindowContainerToken token1 = task1.token;
@@ -327,13 +327,15 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou
@Override
public void onLayoutPositionChanging(SplitLayout layout) {
mSyncQueue.runInSync(t ->
- layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2));
+ layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2,
+ true /* applyResizingOffset */));
}
@Override
public void onLayoutSizeChanging(SplitLayout layout) {
mSyncQueue.runInSync(t ->
- layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2));
+ layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2,
+ true /* applyResizingOffset */));
}
@Override
@@ -342,7 +344,8 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou
layout.applyTaskChanges(wct, mTaskInfo1, mTaskInfo2);
mSyncQueue.queue(wct);
mSyncQueue.runInSync(t ->
- layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2));
+ layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2,
+ false /* applyResizingOffset */));
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index 577ced53f992..42ac19509693 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -48,18 +48,16 @@ import com.android.wm.shell.common.annotations.ShellMainThread;
* Controls the window animation run when a user initiates a back gesture.
*/
public class BackAnimationController implements RemoteCallable<BackAnimationController> {
-
- private static final String BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP =
- "persist.debug.back_predictability_progress_threshold";
- // By default, enable new back dispatching without any animations.
- private static final int BACK_PREDICTABILITY_PROP =
- SystemProperties.getInt("persist.debug.back_predictability", 1);
- public static final boolean IS_ENABLED = BACK_PREDICTABILITY_PROP > 0;
- private static final int PROGRESS_THRESHOLD = SystemProperties
- .getInt(BACK_PREDICTABILITY_PROGRESS_THRESHOLD_PROP, -1);
private static final String TAG = "BackAnimationController";
+ private static final String PREDICTIVE_BACK_PROGRESS_THRESHOLD_PROP =
+ "persist.wm.debug.predictive_back_progress_threshold";
+ public static final boolean IS_ENABLED =
+ SystemProperties.getInt("persist.wm.debug.predictive_back", 1) != 0;
+ private static final int PROGRESS_THRESHOLD = SystemProperties
+ .getInt(PREDICTIVE_BACK_PROGRESS_THRESHOLD_PROP, -1);
@VisibleForTesting
- boolean mEnableAnimations = (BACK_PREDICTABILITY_PROP & (1 << 1)) != 0;
+ boolean mEnableAnimations = SystemProperties.getInt(
+ "persist.wm.debug.predictive_back_anim", 0) != 0;
/**
* Location of the initial touch event of the back gesture.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 116d3524e711..ec81d230fae7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -72,6 +72,10 @@ import java.io.PrintWriter;
*/
public final class SplitLayout implements DisplayInsetsController.OnInsetsChangedListener {
+ public static final int PARALLAX_NONE = 0;
+ public static final int PARALLAX_DISMISSING = 1;
+ public static final int PARALLAX_ALIGN_CENTER = 2;
+
private final int mDividerWindowWidth;
private final int mDividerInsets;
private final int mDividerSize;
@@ -87,7 +91,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
private final SplitWindowManager mSplitWindowManager;
private final DisplayImeController mDisplayImeController;
private final ImePositionProcessor mImePositionProcessor;
- private final DismissingEffectPolicy mDismissingEffectPolicy;
+ private final ResizingEffectPolicy mSurfaceEffectPolicy;
private final ShellTaskOrganizer mTaskOrganizer;
private final InsetsState mInsetsState = new InsetsState();
@@ -105,7 +109,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
SplitLayoutHandler splitLayoutHandler,
SplitWindowManager.ParentContainerCallbacks parentContainerCallbacks,
DisplayImeController displayImeController, ShellTaskOrganizer taskOrganizer,
- boolean applyDismissingParallax) {
+ int parallaxType) {
mContext = context.createConfigurationContext(configuration);
mOrientation = configuration.orientation;
mRotation = configuration.windowConfiguration.getRotation();
@@ -115,7 +119,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
parentContainerCallbacks);
mTaskOrganizer = taskOrganizer;
mImePositionProcessor = new ImePositionProcessor(mContext.getDisplayId());
- mDismissingEffectPolicy = new DismissingEffectPolicy(applyDismissingParallax);
+ mSurfaceEffectPolicy = new ResizingEffectPolicy(parallaxType);
final Resources resources = context.getResources();
mDividerSize = resources.getDimensionPixelSize(R.dimen.split_divider_bar_width);
@@ -281,7 +285,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
}
DockedDividerUtils.sanitizeStackBounds(mBounds1, true /** topLeft */);
DockedDividerUtils.sanitizeStackBounds(mBounds2, false /** topLeft */);
- mDismissingEffectPolicy.applyDividerPosition(position, isLandscape);
+ mSurfaceEffectPolicy.applyDividerPosition(position, isLandscape);
}
/** Inflates {@link DividerView} on the root surface. */
@@ -486,7 +490,8 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
/** Apply recorded surface layout to the {@link SurfaceControl.Transaction}. */
public void applySurfaceChanges(SurfaceControl.Transaction t, SurfaceControl leash1,
- SurfaceControl leash2, SurfaceControl dimLayer1, SurfaceControl dimLayer2) {
+ SurfaceControl leash2, SurfaceControl dimLayer1, SurfaceControl dimLayer2,
+ boolean applyResizingOffset) {
final SurfaceControl dividerLeash = getDividerLeash();
if (dividerLeash != null) {
mTempRect.set(getRefDividerBounds());
@@ -506,7 +511,10 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
return;
}
- mDismissingEffectPolicy.adjustDismissingSurface(t, leash1, leash2, dimLayer1, dimLayer2);
+ mSurfaceEffectPolicy.adjustDimSurface(t, dimLayer1, dimLayer2);
+ if (applyResizingOffset) {
+ mSurfaceEffectPolicy.adjustRootSurface(t, leash1, leash2);
+ }
}
/** Apply recorded task layout to the {@link WindowContainerTransaction}. */
@@ -590,7 +598,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
* Calls when resizing the split bounds.
*
* @see #applySurfaceChanges(SurfaceControl.Transaction, SurfaceControl, SurfaceControl,
- * SurfaceControl, SurfaceControl)
+ * SurfaceControl, SurfaceControl, boolean)
*/
void onLayoutSizeChanging(SplitLayout layout);
@@ -600,7 +608,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
* @see #applyTaskChanges(WindowContainerTransaction, ActivityManager.RunningTaskInfo,
* ActivityManager.RunningTaskInfo)
* @see #applySurfaceChanges(SurfaceControl.Transaction, SurfaceControl, SurfaceControl,
- * SurfaceControl, SurfaceControl)
+ * SurfaceControl, SurfaceControl, boolean)
*/
void onLayoutSizeChanged(SplitLayout layout);
@@ -609,7 +617,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
* panel.
*
* @see #applySurfaceChanges(SurfaceControl.Transaction, SurfaceControl, SurfaceControl,
- * SurfaceControl, SurfaceControl)
+ * SurfaceControl, SurfaceControl, boolean)
*/
void onLayoutPositionChanging(SplitLayout layout);
@@ -637,21 +645,25 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
* Calculates and applies proper dismissing parallax offset and dimming value to hint users
* dismissing gesture.
*/
- private class DismissingEffectPolicy {
+ private class ResizingEffectPolicy {
/** Indicates whether to offset splitting bounds to hint dismissing progress or not. */
- private final boolean mApplyParallax;
+ private final int mParallaxType;
+
+ int mShrinkSide = DOCKED_INVALID;
// The current dismissing side.
int mDismissingSide = DOCKED_INVALID;
// The parallax offset to hint the dismissing side and progress.
- final Point mDismissingParallaxOffset = new Point();
+ final Point mParallaxOffset = new Point();
// The dimming value to hint the dismissing side and progress.
float mDismissingDimValue = 0.0f;
+ final Rect mContentBounds = new Rect();
+ final Rect mSurfaceBounds = new Rect();
- DismissingEffectPolicy(boolean applyDismissingParallax) {
- mApplyParallax = applyDismissingParallax;
+ ResizingEffectPolicy(int parallaxType) {
+ mParallaxType = parallaxType;
}
/**
@@ -662,7 +674,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
*/
void applyDividerPosition(int position, boolean isLandscape) {
mDismissingSide = DOCKED_INVALID;
- mDismissingParallaxOffset.set(0, 0);
+ mParallaxOffset.set(0, 0);
mDismissingDimValue = 0;
int totalDismissingDistance = 0;
@@ -676,15 +688,39 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
- mDividerSnapAlgorithm.getDismissEndTarget().position;
}
+ final boolean topLeftShrink = isLandscape
+ ? position < mWinBounds1.right : position < mWinBounds1.bottom;
+ if (topLeftShrink) {
+ mShrinkSide = isLandscape ? DOCKED_LEFT : DOCKED_TOP;
+ mContentBounds.set(mWinBounds1);
+ mSurfaceBounds.set(mBounds1);
+ } else {
+ mShrinkSide = isLandscape ? DOCKED_RIGHT : DOCKED_BOTTOM;
+ mContentBounds.set(mWinBounds2);
+ mSurfaceBounds.set(mBounds2);
+ }
+
if (mDismissingSide != DOCKED_INVALID) {
float fraction = Math.max(0,
Math.min(mDividerSnapAlgorithm.calculateDismissingFraction(position), 1f));
mDismissingDimValue = DIM_INTERPOLATOR.getInterpolation(fraction);
- fraction = calculateParallaxDismissingFraction(fraction, mDismissingSide);
+ if (mParallaxType == PARALLAX_DISMISSING) {
+ fraction = calculateParallaxDismissingFraction(fraction, mDismissingSide);
+ if (isLandscape) {
+ mParallaxOffset.x = (int) (fraction * totalDismissingDistance);
+ } else {
+ mParallaxOffset.y = (int) (fraction * totalDismissingDistance);
+ }
+ }
+ }
+
+ if (mParallaxType == PARALLAX_ALIGN_CENTER) {
if (isLandscape) {
- mDismissingParallaxOffset.x = (int) (fraction * totalDismissingDistance);
+ mParallaxOffset.x =
+ (mSurfaceBounds.width() - mContentBounds.width()) / 2;
} else {
- mDismissingParallaxOffset.y = (int) (fraction * totalDismissingDistance);
+ mParallaxOffset.y =
+ (mSurfaceBounds.height() - mContentBounds.height()) / 2;
}
}
}
@@ -704,41 +740,66 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
}
/** Applies parallax offset and dimming value to the root surface at the dismissing side. */
- boolean adjustDismissingSurface(SurfaceControl.Transaction t,
- SurfaceControl leash1, SurfaceControl leash2,
+ void adjustRootSurface(SurfaceControl.Transaction t,
+ SurfaceControl leash1, SurfaceControl leash2) {
+ SurfaceControl targetLeash = null;
+
+ if (mParallaxType == PARALLAX_DISMISSING) {
+ switch (mDismissingSide) {
+ case DOCKED_TOP:
+ case DOCKED_LEFT:
+ targetLeash = leash1;
+ mTempRect.set(mBounds1);
+ break;
+ case DOCKED_BOTTOM:
+ case DOCKED_RIGHT:
+ targetLeash = leash2;
+ mTempRect.set(mBounds2);
+ break;
+ }
+ } else if (mParallaxType == PARALLAX_ALIGN_CENTER) {
+ switch (mShrinkSide) {
+ case DOCKED_TOP:
+ case DOCKED_LEFT:
+ targetLeash = leash1;
+ mTempRect.set(mBounds1);
+ break;
+ case DOCKED_BOTTOM:
+ case DOCKED_RIGHT:
+ targetLeash = leash2;
+ mTempRect.set(mBounds2);
+ break;
+ }
+ }
+ if (mParallaxType != PARALLAX_NONE && targetLeash != null) {
+ t.setPosition(targetLeash,
+ mTempRect.left + mParallaxOffset.x, mTempRect.top + mParallaxOffset.y);
+ // Transform the screen-based split bounds to surface-based crop bounds.
+ mTempRect.offsetTo(-mParallaxOffset.x, -mParallaxOffset.y);
+ t.setWindowCrop(targetLeash, mTempRect);
+ }
+ }
+
+ void adjustDimSurface(SurfaceControl.Transaction t,
SurfaceControl dimLayer1, SurfaceControl dimLayer2) {
- SurfaceControl targetLeash, targetDimLayer;
+ SurfaceControl targetDimLayer;
switch (mDismissingSide) {
case DOCKED_TOP:
case DOCKED_LEFT:
- targetLeash = leash1;
targetDimLayer = dimLayer1;
- mTempRect.set(mBounds1);
break;
case DOCKED_BOTTOM:
case DOCKED_RIGHT:
- targetLeash = leash2;
targetDimLayer = dimLayer2;
- mTempRect.set(mBounds2);
break;
case DOCKED_INVALID:
default:
t.setAlpha(dimLayer1, 0).hide(dimLayer1);
t.setAlpha(dimLayer2, 0).hide(dimLayer2);
- return false;
- }
-
- if (mApplyParallax) {
- t.setPosition(targetLeash,
- mTempRect.left + mDismissingParallaxOffset.x,
- mTempRect.top + mDismissingParallaxOffset.y);
- // Transform the screen-based split bounds to surface-based crop bounds.
- mTempRect.offsetTo(-mDismissingParallaxOffset.x, -mDismissingParallaxOffset.y);
- t.setWindowCrop(targetLeash, mTempRect);
+ return;
}
t.setAlpha(targetDimLayer, mDismissingDimValue)
.setVisibility(targetDimLayer, mDismissingDimValue > 0.001f);
- return true;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 73f393140cbc..7f9ecca20b48 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -63,6 +63,7 @@ import com.android.wm.shell.pip.PipUiEventLogger;
import com.android.wm.shell.pip.phone.PhonePipMenuController;
import com.android.wm.shell.pip.phone.PipAppOpsListener;
import com.android.wm.shell.pip.phone.PipController;
+import com.android.wm.shell.pip.phone.PipKeepClearAlgorithm;
import com.android.wm.shell.pip.phone.PipMotionHelper;
import com.android.wm.shell.pip.phone.PipTouchHandler;
import com.android.wm.shell.recents.RecentTasksController;
@@ -207,7 +208,8 @@ public class WMShellModule {
@Provides
static Optional<Pip> providePip(Context context, DisplayController displayController,
PipAppOpsListener pipAppOpsListener, PipBoundsAlgorithm pipBoundsAlgorithm,
- PipBoundsState pipBoundsState, PipMediaController pipMediaController,
+ PipKeepClearAlgorithm pipKeepClearAlgorithm, PipBoundsState pipBoundsState,
+ PipMotionHelper pipMotionHelper, PipMediaController pipMediaController,
PhonePipMenuController phonePipMenuController, PipTaskOrganizer pipTaskOrganizer,
PipTouchHandler pipTouchHandler, PipTransitionController pipTransitionController,
WindowManagerShellWrapper windowManagerShellWrapper,
@@ -215,9 +217,11 @@ public class WMShellModule {
Optional<OneHandedController> oneHandedController,
@ShellMainThread ShellExecutor mainExecutor) {
return Optional.ofNullable(PipController.create(context, displayController,
- pipAppOpsListener, pipBoundsAlgorithm, pipBoundsState, pipMediaController,
- phonePipMenuController, pipTaskOrganizer, pipTouchHandler, pipTransitionController,
- windowManagerShellWrapper, taskStackListener, oneHandedController, mainExecutor));
+ pipAppOpsListener, pipBoundsAlgorithm, pipKeepClearAlgorithm, pipBoundsState,
+ pipMotionHelper,
+ pipMediaController, phonePipMenuController, pipTaskOrganizer, pipTouchHandler,
+ pipTransitionController, windowManagerShellWrapper, taskStackListener,
+ oneHandedController, mainExecutor));
}
@WMSingleton
@@ -234,6 +238,12 @@ public class WMShellModule {
@WMSingleton
@Provides
+ static PipKeepClearAlgorithm providePipKeepClearAlgorithm() {
+ return new PipKeepClearAlgorithm();
+ }
+
+ @WMSingleton
+ @Provides
static PipBoundsAlgorithm providesPipBoundsAlgorithm(Context context,
PipBoundsState pipBoundsState, PipSnapAlgorithm pipSnapAlgorithm) {
return new PipBoundsAlgorithm(context, pipBoundsState, pipSnapAlgorithm);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 623ef05ec7e2..175a2445f28d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -107,7 +107,9 @@ public class PipController implements PipTransitionController.PipTransitionCallb
private PipAppOpsListener mAppOpsListener;
private PipMediaController mMediaController;
private PipBoundsAlgorithm mPipBoundsAlgorithm;
+ private PipKeepClearAlgorithm mPipKeepClearAlgorithm;
private PipBoundsState mPipBoundsState;
+ private PipMotionHelper mPipMotionHelper;
private PipTouchHandler mTouchHandler;
private PipTransitionController mPipTransitionController;
private TaskStackListenerImpl mTaskStackListener;
@@ -241,6 +243,10 @@ public class PipController implements PipTransitionController.PipTransitionCallb
Set<Rect> unrestricted) {
if (mPipBoundsState.getDisplayId() == displayId) {
mPipBoundsState.setKeepClearAreas(restricted, unrestricted);
+ mPipMotionHelper.moveToBounds(mPipKeepClearAlgorithm.adjust(
+ mPipBoundsState.getBounds(),
+ mPipBoundsState.getRestrictedKeepClearAreas(),
+ mPipBoundsState.getUnrestrictedKeepClearAreas()));
}
}
};
@@ -293,7 +299,8 @@ public class PipController implements PipTransitionController.PipTransitionCallb
@Nullable
public static Pip create(Context context, DisplayController displayController,
PipAppOpsListener pipAppOpsListener, PipBoundsAlgorithm pipBoundsAlgorithm,
- PipBoundsState pipBoundsState, PipMediaController pipMediaController,
+ PipKeepClearAlgorithm pipKeepClearAlgorithm, PipBoundsState pipBoundsState,
+ PipMotionHelper pipMotionHelper, PipMediaController pipMediaController,
PhonePipMenuController phonePipMenuController, PipTaskOrganizer pipTaskOrganizer,
PipTouchHandler pipTouchHandler, PipTransitionController pipTransitionController,
WindowManagerShellWrapper windowManagerShellWrapper,
@@ -307,9 +314,9 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
return new PipController(context, displayController, pipAppOpsListener, pipBoundsAlgorithm,
- pipBoundsState, pipMediaController, phonePipMenuController, pipTaskOrganizer,
- pipTouchHandler, pipTransitionController, windowManagerShellWrapper,
- taskStackListener, oneHandedController, mainExecutor)
+ pipKeepClearAlgorithm, pipBoundsState, pipMotionHelper, pipMediaController,
+ phonePipMenuController, pipTaskOrganizer, pipTouchHandler, pipTransitionController,
+ windowManagerShellWrapper, taskStackListener, oneHandedController, mainExecutor)
.mImpl;
}
@@ -317,7 +324,9 @@ public class PipController implements PipTransitionController.PipTransitionCallb
DisplayController displayController,
PipAppOpsListener pipAppOpsListener,
PipBoundsAlgorithm pipBoundsAlgorithm,
+ PipKeepClearAlgorithm pipKeepClearAlgorithm,
@NonNull PipBoundsState pipBoundsState,
+ PipMotionHelper pipMotionHelper,
PipMediaController pipMediaController,
PhonePipMenuController phonePipMenuController,
PipTaskOrganizer pipTaskOrganizer,
@@ -339,7 +348,9 @@ public class PipController implements PipTransitionController.PipTransitionCallb
mWindowManagerShellWrapper = windowManagerShellWrapper;
mDisplayController = displayController;
mPipBoundsAlgorithm = pipBoundsAlgorithm;
+ mPipKeepClearAlgorithm = pipKeepClearAlgorithm;
mPipBoundsState = pipBoundsState;
+ mPipMotionHelper = pipMotionHelper;
mPipTaskOrganizer = pipTaskOrganizer;
mMainExecutor = mainExecutor;
mMediaController = pipMediaController;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipKeepClearAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipKeepClearAlgorithm.java
new file mode 100644
index 000000000000..a83258f9063b
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipKeepClearAlgorithm.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.pip.phone;
+
+import android.graphics.Rect;
+
+import java.util.Set;
+
+/**
+ * Calculates the adjusted position that does not occlude keep clear areas.
+ */
+public class PipKeepClearAlgorithm {
+
+ /** Returns a new {@code Rect} that does not occlude the provided keep clear areas. */
+ public Rect adjust(Rect defaultBounds, Set<Rect> restrictedKeepClearAreas,
+ Set<Rect> unrestrictedKeepClearAreas) {
+ if (restrictedKeepClearAreas.isEmpty()) {
+ return defaultBounds;
+ }
+ // TODO(b/183746978): implement the adjustment algorithm
+ // naively check if areas intersect, an if so move PiP upwards
+ Rect outBounds = new Rect(defaultBounds);
+ for (Rect r : restrictedKeepClearAreas) {
+ if (r.intersect(outBounds)) {
+ outBounds.offset(0, r.top - outBounds.bottom);
+ }
+ }
+ return outBounds;
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipKeepClearAlgorithm.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipKeepClearAlgorithm.kt
index 9ede4433a978..239ea38e1e9c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipKeepClearAlgorithm.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipKeepClearAlgorithm.kt
@@ -363,48 +363,54 @@ class TvPipKeepClearAlgorithm(private val clock: () -> Long) {
private fun getNearbyStashedPosition(bounds: Rect, keepClearAreas: Set<Rect>): Rect {
val screenBounds = transformedScreenBounds
- val stashCandidates = Array(2) { Rect(bounds) }
+ val stashCandidates = mutableListOf<Rect>()
val areasOverlappingPipX = keepClearAreas.filter { it.intersectsX(bounds) }
val areasOverlappingPipY = keepClearAreas.filter { it.intersectsY(bounds) }
if (screenBounds.bottom - bounds.bottom <= bounds.top - screenBounds.top) {
- // bottom is closer than top, stash downwards
val fullStashTop = screenBounds.bottom - stashOffset
val maxBottom = areasOverlappingPipX.maxByOrNull { it.bottom }!!.bottom
val partialStashTop = maxBottom + pipAreaPadding
- val downPosition = stashCandidates[0]
+ val downPosition = Rect(bounds)
downPosition.offsetTo(bounds.left, min(fullStashTop, partialStashTop))
- } else {
- // top is closer than bottom, stash upwards
- val fullStashY = screenBounds.top - bounds.height() + stashOffset
+ stashCandidates += downPosition
+ }
+ if (screenBounds.bottom - bounds.bottom >= bounds.top - screenBounds.top) {
+ val fullStashBottom = screenBounds.top - bounds.height() + stashOffset
val minTop = areasOverlappingPipX.minByOrNull { it.top }!!.top
- val partialStashY = minTop - bounds.height() - pipAreaPadding
+ val partialStashBottom = minTop - bounds.height() - pipAreaPadding
- val upPosition = stashCandidates[0]
- upPosition.offsetTo(bounds.left, max(fullStashY, partialStashY))
+ val upPosition = Rect(bounds)
+ upPosition.offsetTo(bounds.left, max(fullStashBottom, partialStashBottom))
+ stashCandidates += upPosition
}
if (screenBounds.right - bounds.right <= bounds.left - screenBounds.left) {
- // right is closer than left, stash rightwards
- val fullStashLeft = screenBounds.right - stashOffset
+ val fullStashRight = screenBounds.right - stashOffset
val maxRight = areasOverlappingPipY.maxByOrNull { it.right }!!.right
- val partialStashLeft = maxRight + pipAreaPadding
+ val partialStashRight = maxRight + pipAreaPadding
- val rightPosition = stashCandidates[1]
- rightPosition.offsetTo(min(fullStashLeft, partialStashLeft), bounds.top)
- } else {
- // left is closer than right, stash leftwards
+ val rightPosition = Rect(bounds)
+ rightPosition.offsetTo(min(fullStashRight, partialStashRight), bounds.top)
+ stashCandidates += rightPosition
+ }
+ if (screenBounds.right - bounds.right >= bounds.left - screenBounds.left) {
val fullStashLeft = screenBounds.left - bounds.width() + stashOffset
val minLeft = areasOverlappingPipY.minByOrNull { it.left }!!.left
val partialStashLeft = minLeft - bounds.width() - pipAreaPadding
- val rightPosition = stashCandidates[1]
- rightPosition.offsetTo(max(fullStashLeft, partialStashLeft), bounds.top)
+ val leftPosition = Rect(bounds)
+ leftPosition.offsetTo(max(fullStashLeft, partialStashLeft), bounds.top)
+ stashCandidates += leftPosition
+ }
+
+ if (stashCandidates.isEmpty()) {
+ return bounds
}
return stashCandidates.minByOrNull {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index f20870ff0b2d..aec51baa4af7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -377,7 +377,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
return;
}
- mStageCoordinator.updateSurfaceBounds(null /* layout */, t);
+ mStageCoordinator.updateSurfaceBounds(null /* layout */, t,
+ false /* applyResizingOffset */);
for (int i = 0; i < apps.length; ++i) {
if (apps[i].mode == MODE_OPENING) {
t.show(apps[i].leash);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index e150cf9cd112..45931de5e35e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -30,6 +30,7 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.transitTypeToString;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
+import static com.android.wm.shell.common.split.SplitLayout.PARALLAX_ALIGN_CENTER;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
@@ -495,7 +496,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// Using legacy transitions, so we can't use blast sync since it conflicts.
mTaskOrganizer.applyTransaction(wct);
- mSyncQueue.runInSync(t -> updateSurfaceBounds(mSplitLayout, t));
+ mSyncQueue.runInSync(t ->
+ updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */));
}
/**
@@ -704,9 +706,11 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mMainStage.deactivate(wct, !fromEnteringPip && mMainStage == childrenToTop);
wct.reorder(mRootTaskInfo.token, false /* onTop */);
mTaskOrganizer.applyTransaction(wct);
- mSyncQueue.runInSync(t -> t
- .setWindowCrop(mMainStage.mRootLeash, null)
- .setWindowCrop(mSideStage.mRootLeash, null));
+ mSyncQueue.runInSync(t -> {
+ setResizingSplits(false /* resizing */);
+ t.setWindowCrop(mMainStage.mRootLeash, null)
+ .setWindowCrop(mSideStage.mRootLeash, null);
+ });
// Hide divider and reset its position.
mSplitLayout.resetDividerPosition();
@@ -780,7 +784,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
void finishEnterSplitScreen(SurfaceControl.Transaction t) {
mSplitLayout.init();
setDividerVisibility(true, t);
- updateSurfaceBounds(mSplitLayout, t);
+ updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
setSplitsVisible(true);
mShouldUpdateRecents = true;
updateRecentTasksSplitPair();
@@ -925,7 +929,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (mSplitLayout == null) {
mSplitLayout = new SplitLayout(TAG + "SplitDivider", mContext,
mRootTaskInfo.configuration, this, mParentContainerCallbacks,
- mDisplayImeController, mTaskOrganizer, false /* applyDismissingParallax */);
+ mDisplayImeController, mTaskOrganizer,
+ PARALLAX_ALIGN_CENTER /* parallaxType */);
mDisplayInsetsController.addInsetsChangedListener(mDisplayId, mSplitLayout);
}
@@ -1075,7 +1080,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
prepareEnterSplitScreen(wct);
mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> {
- updateSurfaceBounds(mSplitLayout, t);
+ updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
setDividerVisibility(true, t);
});
}
@@ -1094,8 +1099,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Override
public void onSnappedToDismiss(boolean bottomOrRight) {
- setResizingSplits(false /* resizing */);
-
final boolean mainStageToTop =
bottomOrRight ? mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT
: mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT;
@@ -1104,6 +1107,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return;
}
+ setResizingSplits(false /* resizing */);
final int dismissTop = mainStageToTop ? STAGE_TYPE_MAIN : STAGE_TYPE_SIDE;
final WindowContainerTransaction wct = new WindowContainerTransaction();
prepareExitSplitScreen(dismissTop, wct);
@@ -1121,14 +1125,14 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Override
public void onLayoutPositionChanging(SplitLayout layout) {
- mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t));
+ mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t, false /* applyResizingOffset */));
}
@Override
public void onLayoutSizeChanging(SplitLayout layout) {
mSyncQueue.runInSync(t -> {
setResizingSplits(true /* resizing */);
- updateSurfaceBounds(layout, t);
+ updateSurfaceBounds(layout, t, true /* applyResizingOffset */);
mMainStage.onResizing(getMainStageBounds(), t);
mSideStage.onResizing(getSideStageBounds(), t);
});
@@ -1142,7 +1146,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> {
setResizingSplits(false /* resizing */);
- updateSurfaceBounds(layout, t);
+ updateSurfaceBounds(layout, t, false /* applyResizingOffset */);
mMainStage.onResized(t);
mSideStage.onResized(t);
});
@@ -1174,13 +1178,15 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
layout.applyTaskChanges(wct, topLeftStage.mRootTaskInfo, bottomRightStage.mRootTaskInfo);
}
- void updateSurfaceBounds(@Nullable SplitLayout layout, @NonNull SurfaceControl.Transaction t) {
+ void updateSurfaceBounds(@Nullable SplitLayout layout, @NonNull SurfaceControl.Transaction t,
+ boolean applyResizingOffset) {
final StageTaskListener topLeftStage =
mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mSideStage : mMainStage;
final StageTaskListener bottomRightStage =
mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mMainStage : mSideStage;
(layout != null ? layout : mSplitLayout).applySurfaceChanges(t, topLeftStage.mRootLeash,
- bottomRightStage.mRootLeash, topLeftStage.mDimLayer, bottomRightStage.mDimLayer);
+ bottomRightStage.mRootLeash, topLeftStage.mDimLayer, bottomRightStage.mDimLayer,
+ applyResizingOffset);
}
void setResizingSplits(boolean resizing) {
@@ -1220,7 +1226,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mTaskOrganizer.applyTransaction(wct);
}
- @Override
public void onDisplayAdded(int displayId) {
if (displayId != DEFAULT_DISPLAY) {
return;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/SplitScreenController.java
index f1520edf53b1..07174051a344 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/SplitScreenController.java
@@ -253,7 +253,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
IRemoteAnimationFinishedCallback finishedCallback,
SurfaceControl.Transaction t) {
- mStageCoordinator.updateSurfaceBounds(null /* layout */, t);
+ mStageCoordinator.updateSurfaceBounds(null /* layout */, t,
+ false /* applyResizingOffset */);
if (apps != null) {
for (int i = 0; i < apps.length; ++i) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java
index 6ef20e37d5bc..ac25c7510931 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java
@@ -265,7 +265,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mMainStage.activate(getMainStageBounds(), wct);
mSideStage.addTask(task, getSideStageBounds(), wct);
mSyncQueue.queue(wct);
- mSyncQueue.runInSync(t -> updateSurfaceBounds(null /* layout */, t));
+ mSyncQueue.runInSync(
+ t -> updateSurfaceBounds(null /* layout */, t, false /* applyResizingOffset */));
return true;
}
@@ -801,12 +802,12 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Override
public void onLayoutPositionChanging(SplitLayout layout) {
- mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t));
+ mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t, true /* applyResizingOffset */));
}
@Override
public void onLayoutSizeChanging(SplitLayout layout) {
- mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t));
+ mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t, true /* applyResizingOffset */));
mSideStage.setOutlineVisibility(false);
}
@@ -816,7 +817,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
updateWindowBounds(layout, wct);
updateUnfoldBounds();
mSyncQueue.queue(wct);
- mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t));
+ mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t, false /* applyResizingOffset */));
mSideStage.setOutlineVisibility(true);
mLogger.logResize(mSplitLayout.getDividerPositionAsFraction());
}
@@ -840,13 +841,15 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
layout.applyTaskChanges(wct, topLeftStage.mRootTaskInfo, bottomRightStage.mRootTaskInfo);
}
- void updateSurfaceBounds(@Nullable SplitLayout layout, @NonNull SurfaceControl.Transaction t) {
+ void updateSurfaceBounds(@Nullable SplitLayout layout, @NonNull SurfaceControl.Transaction t,
+ boolean applyResizingOffset) {
final StageTaskListener topLeftStage =
mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mSideStage : mMainStage;
final StageTaskListener bottomRightStage =
mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mMainStage : mSideStage;
(layout != null ? layout : mSplitLayout).applySurfaceChanges(t, topLeftStage.mRootLeash,
- bottomRightStage.mRootLeash, topLeftStage.mDimLayer, bottomRightStage.mDimLayer);
+ bottomRightStage.mRootLeash, topLeftStage.mDimLayer, bottomRightStage.mDimLayer,
+ applyResizingOffset);
}
@Override
@@ -882,7 +885,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
if (mSplitLayout == null) {
mSplitLayout = new SplitLayout(TAG + "SplitDivider", mContext,
mDisplayAreaInfo.configuration, this, mParentContainerCallbacks,
- mDisplayImeController, mTaskOrganizer, true /* applyDismissingParallax */);
+ mDisplayImeController, mTaskOrganizer, SplitLayout.PARALLAX_DISMISSING);
mDisplayInsetsController.addInsetsChangedListener(mDisplayId, mSplitLayout);
if (mMainUnfoldController != null && mSideUnfoldController != null) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
index 8b4e1f8bfdb7..f1e602fcf778 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
@@ -73,7 +73,7 @@ public class SplitLayoutTests extends ShellTestCase {
mCallbacks,
mDisplayImeController,
mTaskOrganizer,
- false /* applyDismissingParallax */));
+ SplitLayout.PARALLAX_NONE));
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
index aef298ed478a..deb955b30842 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
@@ -74,6 +74,7 @@ public class PipControllerTest extends ShellTestCase {
@Mock private PhonePipMenuController mMockPhonePipMenuController;
@Mock private PipAppOpsListener mMockPipAppOpsListener;
@Mock private PipBoundsAlgorithm mMockPipBoundsAlgorithm;
+ @Mock private PipKeepClearAlgorithm mMockPipKeepClearAlgorithm;
@Mock private PipSnapAlgorithm mMockPipSnapAlgorithm;
@Mock private PipMediaController mMockPipMediaController;
@Mock private PipTaskOrganizer mMockPipTaskOrganizer;
@@ -97,9 +98,10 @@ public class PipControllerTest extends ShellTestCase {
return null;
}).when(mMockExecutor).execute(any());
mPipController = new PipController(mContext, mMockDisplayController,
- mMockPipAppOpsListener, mMockPipBoundsAlgorithm, mMockPipBoundsState,
- mMockPipMediaController, mMockPhonePipMenuController, mMockPipTaskOrganizer,
- mMockPipTouchHandler, mMockPipTransitionController, mMockWindowManagerShellWrapper,
+ mMockPipAppOpsListener, mMockPipBoundsAlgorithm, mMockPipKeepClearAlgorithm,
+ mMockPipBoundsState, mMockPipMotionHelper, mMockPipMediaController,
+ mMockPhonePipMenuController, mMockPipTaskOrganizer, mMockPipTouchHandler,
+ mMockPipTransitionController, mMockWindowManagerShellWrapper,
mMockTaskStackListener, mMockOneHandedController, mMockExecutor);
when(mMockPipBoundsAlgorithm.getSnapAlgorithm()).thenReturn(mMockPipSnapAlgorithm);
when(mMockPipTouchHandler.getMotionHelper()).thenReturn(mMockPipMotionHelper);
@@ -128,9 +130,10 @@ public class PipControllerTest extends ShellTestCase {
when(spyContext.getPackageManager()).thenReturn(mockPackageManager);
assertNull(PipController.create(spyContext, mMockDisplayController,
- mMockPipAppOpsListener, mMockPipBoundsAlgorithm, mMockPipBoundsState,
- mMockPipMediaController, mMockPhonePipMenuController, mMockPipTaskOrganizer,
- mMockPipTouchHandler, mMockPipTransitionController, mMockWindowManagerShellWrapper,
+ mMockPipAppOpsListener, mMockPipBoundsAlgorithm, mMockPipKeepClearAlgorithm,
+ mMockPipBoundsState, mMockPipMotionHelper, mMockPipMediaController,
+ mMockPhonePipMenuController, mMockPipTaskOrganizer, mMockPipTouchHandler,
+ mMockPipTransitionController, mMockWindowManagerShellWrapper,
mMockTaskStackListener, mMockOneHandedController, mMockExecutor));
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipKeepClearAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipKeepClearAlgorithmTest.java
new file mode 100644
index 000000000000..f657b5e62d82
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipKeepClearAlgorithmTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.pip.phone;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import android.graphics.Rect;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.ShellTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Set;
+
+/**
+ * Unit tests against {@link PipKeepClearAlgorithm}.
+ */
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class PipKeepClearAlgorithmTest extends ShellTestCase {
+
+ private PipKeepClearAlgorithm mPipKeepClearAlgorithm;
+
+
+ @Before
+ public void setUp() throws Exception {
+ mPipKeepClearAlgorithm = new PipKeepClearAlgorithm();
+ }
+
+ @Test
+ public void adjust_withCollidingRestrictedKeepClearAreas_movesBounds() {
+ final Rect inBounds = new Rect(0, 0, 100, 100);
+ final Rect keepClearRect = new Rect(50, 50, 150, 150);
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(inBounds, Set.of(keepClearRect),
+ Set.of());
+
+ assertFalse(outBounds.contains(keepClearRect));
+ }
+
+ @Test
+ public void adjust_withNonCollidingRestrictedKeepClearAreas_boundsDoNotChange() {
+ final Rect inBounds = new Rect(0, 0, 100, 100);
+ final Rect keepClearRect = new Rect(100, 100, 150, 150);
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(inBounds, Set.of(keepClearRect),
+ Set.of());
+
+ assertEquals(inBounds, outBounds);
+ }
+
+ @Test
+ public void adjust_withCollidingUnrestrictedKeepClearAreas_boundsDoNotChange() {
+ // TODO(b/183746978): update this test to accommodate for the updated algorithm
+ final Rect inBounds = new Rect(0, 0, 100, 100);
+ final Rect keepClearRect = new Rect(50, 50, 150, 150);
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(inBounds, Set.of(),
+ Set.of(keepClearRect));
+
+ assertEquals(inBounds, outBounds);
+ }
+
+ @Test
+ public void adjust_withNonCollidingUnrestrictedKeepClearAreas_boundsDoNotChange() {
+ final Rect inBounds = new Rect(0, 0, 100, 100);
+ final Rect keepClearRect = new Rect(100, 100, 150, 150);
+
+ final Rect outBounds = mPipKeepClearAlgorithm.adjust(inBounds, Set.of(),
+ Set.of(keepClearRect));
+
+ assertEquals(inBounds, outBounds);
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index 061136c65daf..c571d44d3da9 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -309,7 +309,7 @@ public class StageCoordinatorTests extends ShellTestCase {
public void testFinishEnterSplitScreen_applySurfaceLayout() {
mStageCoordinator.finishEnterSplitScreen(new SurfaceControl.Transaction());
- verify(mSplitLayout).applySurfaceChanges(any(), any(), any(), any(), any());
+ verify(mSplitLayout).applySurfaceChanges(any(), any(), any(), any(), any(), eq(false));
}
private class UnfoldControllerProvider implements