Update PiP exclusion bounds in TaskBarDelegate.

Navigation bar is only created and used when taskbar is not available.
When taskbar is available, we will use TaskbarDelegate to be the one
responsible to update pip exclusion bounds as PiP moves.

Bug: 210038947
Test: Unfold, enter PiP, stash - PiP can be yanked out
Change-Id: I8f789d3b603e41c3d15494afdadce2cddc4d4b9c
This commit is contained in:
Ben Lin
2021-12-09 15:02:18 -08:00
parent a66bc891ce
commit 82865fe924
9 changed files with 78 additions and 24 deletions

View File

@@ -112,11 +112,17 @@ public interface Pip {
default void showPictureInPictureMenu() {}
/**
* Called by NavigationBar in order to listen in for PiP bounds change. This is mostly used
* for times where the PiP bounds could conflict with SystemUI elements, such as a stashed
* PiP and the Back-from-Edge gesture.
* Called by NavigationBar and TaskbarDelegate in order to listen in for PiP bounds change. This
* is mostly used for times where the PiP bounds could conflict with SystemUI elements, such as
* a stashed PiP and the Back-from-Edge gesture.
*/
default void setPipExclusionBoundsChangeListener(Consumer<Rect> listener) { }
default void addPipExclusionBoundsChangeListener(Consumer<Rect> listener) { }
/**
* Remove a callback added previously. This is used when NavigationBar is removed from the
* view hierarchy or destroyed.
*/
default void removePipExclusionBoundsChangeListener(Consumer<Rect> listener) { }
/**
* Dump the current state and information if need.

View File

@@ -38,6 +38,8 @@ import com.android.wm.shell.common.DisplayLayout;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
@@ -89,7 +91,7 @@ public final class PipBoundsState {
private @Nullable Runnable mOnMinimalSizeChangeCallback;
private @Nullable TriConsumer<Boolean, Integer, Boolean> mOnShelfVisibilityChangeCallback;
private @Nullable Consumer<Rect> mOnPipExclusionBoundsChangeCallback;
private List<Consumer<Rect>> mOnPipExclusionBoundsChangeCallbacks = new ArrayList<>();
public PipBoundsState(@NonNull Context context) {
mContext = context;
@@ -108,8 +110,8 @@ public final class PipBoundsState {
/** Set the current PIP bounds. */
public void setBounds(@NonNull Rect bounds) {
mBounds.set(bounds);
if (mOnPipExclusionBoundsChangeCallback != null) {
mOnPipExclusionBoundsChangeCallback.accept(bounds);
for (Consumer<Rect> callback : mOnPipExclusionBoundsChangeCallbacks) {
callback.accept(bounds);
}
}
@@ -407,17 +409,25 @@ public final class PipBoundsState {
}
/**
* Set a callback to watch out for PiP bounds. This is mostly used by SystemUI's
* Add a callback to watch out for PiP bounds. This is mostly used by SystemUI's
* Back-gesture handler, to avoid conflicting with PiP when it's stashed.
*/
public void setPipExclusionBoundsChangeCallback(
public void addPipExclusionBoundsChangeCallback(
@Nullable Consumer<Rect> onPipExclusionBoundsChangeCallback) {
mOnPipExclusionBoundsChangeCallback = onPipExclusionBoundsChangeCallback;
if (mOnPipExclusionBoundsChangeCallback != null) {
mOnPipExclusionBoundsChangeCallback.accept(getBounds());
mOnPipExclusionBoundsChangeCallbacks.add(onPipExclusionBoundsChangeCallback);
for (Consumer<Rect> callback : mOnPipExclusionBoundsChangeCallbacks) {
callback.accept(getBounds());
}
}
/**
* Remove a callback that was previously added.
*/
public void removePipExclusionBoundsChangeCallback(
@Nullable Consumer<Rect> onPipExclusionBoundsChangeCallback) {
mOnPipExclusionBoundsChangeCallbacks.remove(onPipExclusionBoundsChangeCallback);
}
/** Source of truth for the current bounds of PIP that may be in motion. */
public static class MotionBoundsState {
/** The bounds used when PIP is in motion (e.g. during a drag or animation) */

View File

@@ -843,9 +843,16 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
@Override
public void setPipExclusionBoundsChangeListener(Consumer<Rect> listener) {
public void addPipExclusionBoundsChangeListener(Consumer<Rect> listener) {
mMainExecutor.execute(() -> {
mPipBoundsState.setPipExclusionBoundsChangeCallback(listener);
mPipBoundsState.addPipExclusionBoundsChangeCallback(listener);
});
}
@Override
public void removePipExclusionBoundsChangeListener(Consumer<Rect> listener) {
mMainExecutor.execute(() -> {
mPipBoundsState.removePipExclusionBoundsChangeCallback(listener);
});
}

View File

@@ -188,7 +188,7 @@ public class PipBoundsStateTest extends ShellTestCase {
final Rect newBounds = new Rect(50, 50, 100, 75);
mPipBoundsState.setBounds(currentBounds);
mPipBoundsState.setPipExclusionBoundsChangeCallback(callback);
mPipBoundsState.addPipExclusionBoundsChangeCallback(callback);
// Setting the listener immediately calls back with the current bounds.
verify(callback).accept(currentBounds);

View File

@@ -628,7 +628,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
mSplitScreenOptional.ifPresent(mNavigationBarView::registerDockedListener);
mPipOptional.ifPresent(mNavigationBarView::registerPipExclusionBoundsChangeListener);
mPipOptional.ifPresent(mNavigationBarView::addPipExclusionBoundsChangeListener);
prepareNavigationBarView();
checkNavBarModes();
@@ -699,6 +699,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
mHandler.removeCallbacks(mOnVariableDurationHomeLongClick);
mHandler.removeCallbacks(mEnableLayoutTransitions);
mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
mPipOptional.ifPresent(mNavigationBarView::removePipExclusionBoundsChangeListener);
mFrame = null;
mNavigationBarView = null;
mOrientationHandle = null;

View File

@@ -59,9 +59,11 @@ import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.wm.shell.pip.Pip;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Optional;
import javax.inject.Inject;
@@ -106,7 +108,8 @@ public class NavigationBarController implements
NavigationBar.Factory navigationBarFactory,
DumpManager dumpManager,
AutoHideController autoHideController,
LightBarController lightBarController) {
LightBarController lightBarController,
Optional<Pip> pipOptional) {
mContext = context;
mHandler = mainHandler;
mNavigationBarFactory = navigationBarFactory;
@@ -118,7 +121,7 @@ public class NavigationBarController implements
mTaskbarDelegate = taskbarDelegate;
mTaskbarDelegate.setDependencies(commandQueue, overviewProxyService,
navBarHelper, navigationModeController, sysUiFlagsContainer,
dumpManager, autoHideController, lightBarController);
dumpManager, autoHideController, lightBarController, pipOptional);
mIsTablet = isTablet(mContext);
dumpManager.registerDumpable(this);
}

View File

@@ -75,12 +75,12 @@ import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
import com.android.systemui.navigationbar.buttons.NearestTouchFrame;
import com.android.systemui.navigationbar.buttons.RotationContextButton;
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
import com.android.systemui.shared.rotation.FloatingRotationButton;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
import com.android.systemui.shared.rotation.FloatingRotationButton;
import com.android.systemui.shared.rotation.RotationButton.RotationButtonUpdatesCallback;
import com.android.systemui.shared.rotation.RotationButtonController;
import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.SysUiStatsLog;
@@ -1386,8 +1386,12 @@ public class NavigationBarView extends FrameLayout implements
legacySplitScreen.registerInSplitScreenListener(mDockedListener);
}
void registerPipExclusionBoundsChangeListener(Pip pip) {
pip.setPipExclusionBoundsChangeListener(mPipListener);
void addPipExclusionBoundsChangeListener(Pip pip) {
pip.addPipExclusionBoundsChangeListener(mPipListener);
}
void removePipExclusionBoundsChangeListener(Pip pip) {
pip.removePipExclusionBoundsChangeListener(mPipListener);
}
private static void dumpButton(PrintWriter pw, String caption, ButtonDispatcher button) {

View File

@@ -40,6 +40,7 @@ import android.app.StatusBarManager.WindowVisibleState;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.inputmethodservice.InputMethodService;
import android.os.IBinder;
@@ -68,9 +69,12 @@ import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.BarTransitions;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LightBarTransitionsController;
import com.android.wm.shell.pip.Pip;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Optional;
import java.util.function.Consumer;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -91,6 +95,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
private AutoHideController mAutoHideController;
private LightBarController mLightBarController;
private LightBarTransitionsController mLightBarTransitionsController;
private Optional<Pip> mPipOptional;
private int mDisplayId;
private int mNavigationIconHints;
private final NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater =
@@ -113,6 +118,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
private Context mWindowContext;
private ScreenPinningNotify mScreenPinningNotify;
private int mNavigationMode;
private final Consumer<Rect> mPipListener;
/**
* Tracks the system calls for when taskbar should transiently show or hide so we can return
@@ -143,6 +149,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
.create(context);
mContext = context;
mDisplayManager = mContext.getSystemService(DisplayManager.class);
mPipListener = mEdgeBackGestureHandler::setPipStashExclusionBounds;
}
public void setDependencies(CommandQueue commandQueue,
@@ -151,7 +158,8 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
NavigationModeController navigationModeController,
SysUiState sysUiState, DumpManager dumpManager,
AutoHideController autoHideController,
LightBarController lightBarController) {
LightBarController lightBarController,
Optional<Pip> pipOptional) {
// TODO: adding this in the ctor results in a dagger dependency cycle :(
mCommandQueue = commandQueue;
mOverviewProxyService = overviewProxyService;
@@ -162,6 +170,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
mAutoHideController = autoHideController;
mLightBarController = lightBarController;
mLightBarTransitionsController = createLightBarTransitionsController();
mPipOptional = pipOptional;
}
// Separated into a method to keep setDependencies() clean/readable.
@@ -207,6 +216,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
updateSysuiFlags();
mAutoHideController.setNavigationBar(mAutoHideUiElement);
mLightBarController.setNavigationBar(mLightBarTransitionsController);
mPipOptional.ifPresent(this::addPipExclusionBoundsChangeListener);
mInitialized = true;
}
@@ -228,9 +238,18 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
mAutoHideController.setNavigationBar(null);
mLightBarTransitionsController.destroy(mContext);
mLightBarController.setNavigationBar(null);
mPipOptional.ifPresent(this::removePipExclusionBoundsChangeListener);
mInitialized = false;
}
void addPipExclusionBoundsChangeListener(Pip pip) {
pip.addPipExclusionBoundsChangeListener(mPipListener);
}
void removePipExclusionBoundsChangeListener(Pip pip) {
pip.removePipExclusionBoundsChangeListener(mPipListener);
}
/**
* Returns {@code true} if this taskBar is {@link #init(int)}. Returns {@code false} if this
* taskbar has not yet been {@link #init(int)} or has been {@link #destroy()}.

View File

@@ -47,6 +47,7 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.wm.shell.pip.Pip;
import org.junit.After;
import org.junit.Before;
@@ -55,6 +56,8 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Optional;
/** atest NavigationBarControllerTest */
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@@ -88,7 +91,8 @@ public class NavigationBarControllerTest extends SysuiTestCase {
mNavigationBarFactory,
mock(DumpManager.class),
mock(AutoHideController.class),
mock(LightBarController.class)));
mock(LightBarController.class),
Optional.of(mock(Pip.class))));
initializeNavigationBars();
}