summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ben Lin <linben@google.com> 2021-11-25 07:18:59 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-11-25 07:18:59 +0000
commita656a4e4e4c4bdc807b4bbe6688fe2d4a1530620 (patch)
treed17eef1bec42744449d13f1c1a187296828b4231
parentec0c08c77121261fcf78b9a99088b834b23d280a (diff)
parentb26f380809919a1f52b46e0ea669deec687cc0e8 (diff)
Merge "PiP: Show/hide enter split button based on focused task." into sc-v2-dev
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java49
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java23
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java11
8 files changed, 115 insertions, 5 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 75bc46125324..7f370367187c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -29,6 +29,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.TaskInfo;
+import android.app.WindowConfiguration;
import android.content.Context;
import android.content.LocusId;
import android.content.pm.ActivityInfo;
@@ -122,6 +123,16 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
}
/**
+ * Callbacks for events in which the focus has changed.
+ */
+ public interface FocusListener {
+ /**
+ * Notifies when the task which is focused has changed.
+ */
+ void onFocusTaskChanged(RunningTaskInfo taskInfo);
+ }
+
+ /**
* Keys map from either a task id or {@link TaskListenerType}.
* @see #addListenerForTaskId
* @see #addListenerForType
@@ -142,6 +153,8 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
/** @see #addLocusIdListener */
private final ArraySet<LocusIdListener> mLocusIdListeners = new ArraySet<>();
+ private final ArraySet<FocusListener> mFocusListeners = new ArraySet<>();
+
private final Object mLock = new Object();
private StartingWindowController mStartingWindow;
@@ -155,6 +168,9 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
@Nullable
private final Optional<RecentTasksController> mRecentTasks;
+ @Nullable
+ private RunningTaskInfo mLastFocusedTaskInfo;
+
public ShellTaskOrganizer(ShellExecutor mainExecutor, Context context) {
this(null /* taskOrganizerController */, mainExecutor, context, null /* sizeCompatUI */,
Optional.empty() /* recentTasksController */);
@@ -331,6 +347,27 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
}
}
+ /**
+ * Adds a listener to be notified for task focus changes.
+ */
+ public void addFocusListener(FocusListener listener) {
+ synchronized (mLock) {
+ mFocusListeners.add(listener);
+ if (mLastFocusedTaskInfo != null) {
+ listener.onFocusTaskChanged(mLastFocusedTaskInfo);
+ }
+ }
+ }
+
+ /**
+ * Removes listener.
+ */
+ public void removeLocusIdListener(FocusListener listener) {
+ synchronized (mLock) {
+ mFocusListeners.remove(listener);
+ }
+ }
+
@Override
public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
if (mStartingWindow != null) {
@@ -422,6 +459,18 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
mRecentTasks.ifPresent(recentTasks ->
recentTasks.onTaskWindowingModeChanged(taskInfo));
}
+ // TODO (b/207687679): Remove check for HOME once bug is fixed
+ final boolean isFocusedOrHome = taskInfo.isFocused
+ || (taskInfo.topActivityType == WindowConfiguration.ACTIVITY_TYPE_HOME
+ && taskInfo.isVisible);
+ final boolean focusTaskChanged = (mLastFocusedTaskInfo == null
+ || mLastFocusedTaskInfo.taskId != taskInfo.taskId) && isFocusedOrHome;
+ if (focusTaskChanged) {
+ for (int i = 0; i < mFocusListeners.size(); i++) {
+ mFocusListeners.valueAt(i).onFocusTaskChanged(taskInfo);
+ }
+ mLastFocusedTaskInfo = taskInfo;
+ }
}
}
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 46c7b508d6e8..f562fd9cf1af 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
@@ -241,10 +241,11 @@ public class WMShellModule {
static PhonePipMenuController providesPipPhoneMenuController(Context context,
PipBoundsState pipBoundsState, PipMediaController pipMediaController,
SystemWindows systemWindows,
+ Optional<SplitScreenController> splitScreenOptional,
@ShellMainThread ShellExecutor mainExecutor,
@ShellMainThread Handler mainHandler) {
return new PhonePipMenuController(context, pipBoundsState, pipMediaController,
- systemWindows, mainExecutor, mainHandler);
+ systemWindows, splitScreenOptional, mainExecutor, mainHandler);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java
index 8d9ad4d1b96c..caa1f017082b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java
@@ -90,6 +90,11 @@ public interface PipMenuController {
default void updateMenuBounds(Rect destinationBounds) {}
/**
+ * Update when the current focused task changes.
+ */
+ default void onFocusTaskChanged(RunningTaskInfo taskInfo) {}
+
+ /**
* Returns a default LayoutParams for the PIP Menu.
* @param width the PIP stack width.
* @param height the PIP stack height.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 90135f2a3c69..c2ebc3031b93 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -98,7 +98,7 @@ import java.util.function.IntConsumer;
* see also {@link PipMotionHelper}.
*/
public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
- DisplayController.OnDisplaysChangedListener {
+ DisplayController.OnDisplaysChangedListener, ShellTaskOrganizer.FocusListener {
private static final String TAG = PipTaskOrganizer.class.getSimpleName();
private static final boolean DEBUG = false;
/**
@@ -286,6 +286,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
mMainExecutor.execute(() -> {
mTaskOrganizer.addListenerForType(this, TASK_LISTENER_TYPE_PIP);
});
+ mTaskOrganizer.addFocusListener(this);
mPipTransitionController.setPipOrganizer(this);
displayController.addDisplayWindowListener(this);
}
@@ -772,6 +773,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
}
@Override
+ public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) {
+ mPipMenuController.onFocusTaskChanged(taskInfo);
+ }
+
+ @Override
public boolean supportSizeCompatUI() {
// PIP doesn't support size compat.
return false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
index 5687f4d62444..eb512afa644d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
@@ -19,6 +19,7 @@ package com.android.wm.shell.pip.phone;
import static android.view.WindowManager.SHELL_ROOT_LAYER_PIP;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.RemoteAction;
import android.content.Context;
import android.content.pm.ParceledListSlice;
@@ -43,10 +44,12 @@ import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipMediaController;
import com.android.wm.shell.pip.PipMediaController.ActionListener;
import com.android.wm.shell.pip.PipMenuController;
+import com.android.wm.shell.splitscreen.SplitScreenController;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
/**
* Manages the PiP menu view which can show menu options or a scrim.
@@ -114,6 +117,7 @@ public class PhonePipMenuController implements PipMenuController {
private final ArrayList<Listener> mListeners = new ArrayList<>();
private final SystemWindows mSystemWindows;
+ private final Optional<SplitScreenController> mSplitScreenController;
private ParceledListSlice<RemoteAction> mAppActions;
private ParceledListSlice<RemoteAction> mMediaActions;
private SyncRtSurfaceTransactionApplier mApplier;
@@ -145,6 +149,7 @@ public class PhonePipMenuController implements PipMenuController {
public PhonePipMenuController(Context context, PipBoundsState pipBoundsState,
PipMediaController mediaController, SystemWindows systemWindows,
+ Optional<SplitScreenController> splitScreenOptional,
ShellExecutor mainExecutor, Handler mainHandler) {
mContext = context;
mPipBoundsState = pipBoundsState;
@@ -152,6 +157,7 @@ public class PhonePipMenuController implements PipMenuController {
mSystemWindows = systemWindows;
mMainExecutor = mainExecutor;
mMainHandler = mainHandler;
+ mSplitScreenController = splitScreenOptional;
}
public boolean isMenuVisible() {
@@ -180,7 +186,8 @@ public class PhonePipMenuController implements PipMenuController {
if (mPipMenuView != null) {
detachPipMenuView();
}
- mPipMenuView = new PipMenuView(mContext, this, mMainExecutor, mMainHandler);
+ mPipMenuView = new PipMenuView(mContext, this, mMainExecutor, mMainHandler,
+ mSplitScreenController);
mSystemWindows.addView(mPipMenuView,
getPipMenuLayoutParams(MENU_WINDOW_TITLE, 0 /* width */, 0 /* height */),
0, SHELL_ROOT_LAYER_PIP);
@@ -209,6 +216,13 @@ public class PhonePipMenuController implements PipMenuController {
updateMenuLayout(destinationBounds);
}
+ @Override
+ public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) {
+ if (mPipMenuView != null) {
+ mPipMenuView.onFocusTaskChanged(taskInfo);
+ }
+ }
+
/**
* Tries to grab a surface control from {@link PipMenuView}. If this isn't available for some
* reason (ie. the window isn't ready yet, thus {@link android.view.ViewRootImpl} is
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
index b209699c1a19..82e827398bb7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
@@ -16,6 +16,7 @@
package com.android.wm.shell.pip.phone;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.provider.Settings.ACTION_PICTURE_IN_PICTURE_SETTINGS;
@@ -32,8 +33,10 @@ import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
+import android.app.ActivityManager;
import android.app.PendingIntent.CanceledException;
import android.app.RemoteAction;
+import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -61,11 +64,13 @@ import com.android.wm.shell.R;
import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.pip.PipUtils;
+import com.android.wm.shell.splitscreen.SplitScreenController;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
/**
* Translucent window that gets started on top of a task in PIP to allow the user to control it.
@@ -105,6 +110,7 @@ public class PipMenuView extends FrameLayout {
private boolean mAllowMenuTimeout = true;
private boolean mAllowTouches = true;
private int mDismissFadeOutDurationMs;
+ private boolean mFocusedTaskAllowSplitScreen;
private final List<RemoteAction> mActions = new ArrayList<>();
@@ -116,6 +122,7 @@ public class PipMenuView extends FrameLayout {
private AnimatorSet mMenuContainerAnimator;
private PhonePipMenuController mController;
+ private Optional<SplitScreenController> mSplitScreenControllerOptional;
private ValueAnimator.AnimatorUpdateListener mMenuBgUpdateListener =
new ValueAnimator.AnimatorUpdateListener() {
@@ -144,12 +151,14 @@ public class PipMenuView extends FrameLayout {
protected PipMenuIconsAlgorithm mPipMenuIconsAlgorithm;
public PipMenuView(Context context, PhonePipMenuController controller,
- ShellExecutor mainExecutor, Handler mainHandler) {
+ ShellExecutor mainExecutor, Handler mainHandler,
+ Optional<SplitScreenController> splitScreenController) {
super(context, null, 0);
mContext = context;
mController = controller;
mMainExecutor = mainExecutor;
mMainHandler = mainHandler;
+ mSplitScreenControllerOptional = splitScreenController;
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
inflate(context, R.layout.pip_menu, this);
@@ -255,6 +264,15 @@ public class PipMenuView extends FrameLayout {
return super.dispatchGenericMotionEvent(event);
}
+ public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) {
+ final boolean isSplitScreen = mSplitScreenControllerOptional.isPresent()
+ && mSplitScreenControllerOptional.get().isTaskInSplitScreen(taskInfo.taskId);
+ mFocusedTaskAllowSplitScreen = isSplitScreen
+ || (taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
+ && taskInfo.supportsSplitScreenMultiWindow
+ && taskInfo.topActivityType != WindowConfiguration.ACTIVITY_TYPE_HOME);
+ }
+
void showMenu(int menuState, Rect stackBounds, boolean allowMenuTimeout,
boolean resizeMenuOnShow, boolean withDelay, boolean showResizeHandle) {
mAllowMenuTimeout = allowMenuTimeout;
@@ -278,7 +296,8 @@ public class PipMenuView extends FrameLayout {
ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
mDismissButton.getAlpha(), 1f);
ObjectAnimator enterSplitAnim = ObjectAnimator.ofFloat(mEnterSplitButton, View.ALPHA,
- mEnterSplitButton.getAlpha(), ENABLE_ENTER_SPLIT ? 1f : 0f);
+ mEnterSplitButton.getAlpha(),
+ ENABLE_ENTER_SPLIT && mFocusedTaskAllowSplitScreen ? 1f : 0f);
if (menuState == MENU_STATE_FULL) {
mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim,
enterSplitAnim);
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 6b42ed775fb7..dc80813cdb2d 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
@@ -183,6 +183,11 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
return mStageCoordinator.isSplitScreenVisible();
}
+ public boolean isTaskInSplitScreen(int taskId) {
+ return isSplitScreenVisible()
+ && mStageCoordinator.getStageOfTask(taskId) != STAGE_TYPE_UNDEFINED;
+ }
+
public boolean moveToSideStage(int taskId, @SplitPosition int sideStagePosition) {
return moveToStage(taskId, STAGE_TYPE_SIDE, sideStagePosition,
new WindowContainerTransaction());
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 a3726d46d2a4..a390633481cd 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
@@ -274,6 +274,17 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return mSideStageListener.mVisible && mMainStageListener.mVisible;
}
+ @SplitScreen.StageType
+ int getStageOfTask(int taskId) {
+ if (mMainStage.containsTask(taskId)) {
+ return STAGE_TYPE_MAIN;
+ } else if (mSideStage.containsTask(taskId)) {
+ return STAGE_TYPE_SIDE;
+ }
+
+ return STAGE_TYPE_UNDEFINED;
+ }
+
boolean moveToStage(ActivityManager.RunningTaskInfo task, @SplitScreen.StageType int stageType,
@SplitPosition int stagePosition, WindowContainerTransaction wct) {
StageTaskListener targetStage;