Merge "Handle the uncontrolled task in split-screen" into tm-qpr-dev am: 9e73750458
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19166690 Change-Id: Id239035fb76ebfc0b7eff00c8686e87a8af93131 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -348,8 +348,10 @@ public final class WindowContainerTransaction implements Parcelable {
|
|||||||
* @param currentParent of the tasks to perform the operation no.
|
* @param currentParent of the tasks to perform the operation no.
|
||||||
* {@code null} will perform the operation on the display.
|
* {@code null} will perform the operation on the display.
|
||||||
* @param newParent for the tasks. {@code null} will perform the operation on the display.
|
* @param newParent for the tasks. {@code null} will perform the operation on the display.
|
||||||
* @param windowingModes of the tasks to reparent.
|
* @param windowingModes of the tasks to reparent. {@code null} ignore this attribute when
|
||||||
* @param activityTypes of the tasks to reparent.
|
* perform the operation.
|
||||||
|
* @param activityTypes of the tasks to reparent. {@code null} ignore this attribute when
|
||||||
|
* perform the operation.
|
||||||
* @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to
|
* @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to
|
||||||
* the bottom.
|
* the bottom.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -15,6 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.wm.shell.common.split;
|
package com.android.wm.shell.common.split;
|
||||||
|
|
||||||
|
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
|
||||||
|
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||||
|
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
||||||
|
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
||||||
|
|
||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
|
|
||||||
/** Helper utility class of methods and constants that are available to be imported in Launcher. */
|
/** Helper utility class of methods and constants that are available to be imported in Launcher. */
|
||||||
@@ -44,4 +49,10 @@ public class SplitScreenConstants {
|
|||||||
})
|
})
|
||||||
public @interface SplitPosition {
|
public @interface SplitPosition {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final int[] CONTROLLED_ACTIVITY_TYPES = {ACTIVITY_TYPE_STANDARD};
|
||||||
|
public static final int[] CONTROLLED_WINDOWING_MODES =
|
||||||
|
{WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED};
|
||||||
|
public static final int[] CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE =
|
||||||
|
{WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED, WINDOWING_MODE_MULTI_WINDOW};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
package com.android.wm.shell.splitscreen;
|
package com.android.wm.shell.splitscreen;
|
||||||
|
|
||||||
|
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
|
||||||
|
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.view.SurfaceSession;
|
import android.view.SurfaceSession;
|
||||||
import android.window.WindowContainerToken;
|
import android.window.WindowContainerToken;
|
||||||
@@ -74,10 +77,10 @@ class MainStage extends StageTaskListener {
|
|||||||
if (mRootTaskInfo == null) return;
|
if (mRootTaskInfo == null) return;
|
||||||
final WindowContainerToken rootToken = mRootTaskInfo.token;
|
final WindowContainerToken rootToken = mRootTaskInfo.token;
|
||||||
wct.reparentTasks(
|
wct.reparentTasks(
|
||||||
rootToken,
|
rootToken,
|
||||||
null /* newParent */,
|
null /* newParent */,
|
||||||
CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE,
|
null /* windowingModes */,
|
||||||
CONTROLLED_ACTIVITY_TYPES,
|
null /* activityTypes */,
|
||||||
toTop);
|
toTop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ class SideStage extends StageTaskListener {
|
|||||||
wct.reparentTasks(
|
wct.reparentTasks(
|
||||||
mRootTaskInfo.token,
|
mRootTaskInfo.token,
|
||||||
null /* newParent */,
|
null /* newParent */,
|
||||||
CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE,
|
null /* windowingModes */,
|
||||||
CONTROLLED_ACTIVITY_TYPES,
|
null /* activityTypes */,
|
||||||
toTop);
|
toTop);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import static android.view.Display.DEFAULT_DISPLAY;
|
|||||||
import static android.view.RemoteAnimationTarget.MODE_OPENING;
|
import static android.view.RemoteAnimationTarget.MODE_OPENING;
|
||||||
|
|
||||||
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
|
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
|
||||||
|
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
|
||||||
|
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
|
||||||
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_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_TOP_OR_LEFT;
|
||||||
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
|
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
|
||||||
@@ -64,6 +66,7 @@ import androidx.annotation.Nullable;
|
|||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.logging.InstanceId;
|
import com.android.internal.logging.InstanceId;
|
||||||
import com.android.internal.protolog.common.ProtoLog;
|
import com.android.internal.protolog.common.ProtoLog;
|
||||||
|
import com.android.internal.util.ArrayUtils;
|
||||||
import com.android.launcher3.icons.IconProvider;
|
import com.android.launcher3.icons.IconProvider;
|
||||||
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
|
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
|
||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
import com.android.wm.shell.ShellTaskOrganizer;
|
||||||
@@ -227,6 +230,12 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
|||||||
&& mStageCoordinator.getStageOfTask(taskId) != STAGE_TYPE_UNDEFINED;
|
&& mStageCoordinator.getStageOfTask(taskId) != STAGE_TYPE_UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isValidToEnterSplitScreen(@NonNull ActivityManager.RunningTaskInfo taskInfo) {
|
||||||
|
return taskInfo.supportsMultiWindow
|
||||||
|
&& ArrayUtils.contains(CONTROLLED_ACTIVITY_TYPES, taskInfo.getActivityType())
|
||||||
|
&& ArrayUtils.contains(CONTROLLED_WINDOWING_MODES, taskInfo.getWindowingMode());
|
||||||
|
}
|
||||||
|
|
||||||
public @SplitPosition int getSplitPosition(int taskId) {
|
public @SplitPosition int getSplitPosition(int taskId) {
|
||||||
return mStageCoordinator.getSplitPosition(taskId);
|
return mStageCoordinator.getSplitPosition(taskId);
|
||||||
}
|
}
|
||||||
@@ -463,11 +472,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
|||||||
return Objects.equals(launchingActivity, pairedActivity);
|
return Objects.equals(launchingActivity, pairedActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mFocusingTaskInfo != null
|
if (mFocusingTaskInfo != null && isValidToEnterSplitScreen(mFocusingTaskInfo)) {
|
||||||
// TODO (b/238032411): have an API to determine whether an activity is valid for
|
|
||||||
// split screen or not.
|
|
||||||
&& mFocusingTaskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
|
|
||||||
&& mFocusingTaskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD) {
|
|
||||||
return Objects.equals(mFocusingTaskInfo.baseIntent.getComponent(), launchingActivity);
|
return Objects.equals(mFocusingTaskInfo.baseIntent.getComponent(), launchingActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ import android.view.RemoteAnimationTarget;
|
|||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.view.SurfaceSession;
|
import android.view.SurfaceSession;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
import android.widget.Toast;
|
||||||
import android.window.DisplayAreaInfo;
|
import android.window.DisplayAreaInfo;
|
||||||
import android.window.RemoteTransition;
|
import android.window.RemoteTransition;
|
||||||
import android.window.TransitionInfo;
|
import android.window.TransitionInfo;
|
||||||
@@ -98,6 +99,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
|||||||
import com.android.internal.logging.InstanceId;
|
import com.android.internal.logging.InstanceId;
|
||||||
import com.android.internal.protolog.common.ProtoLog;
|
import com.android.internal.protolog.common.ProtoLog;
|
||||||
import com.android.launcher3.icons.IconProvider;
|
import com.android.launcher3.icons.IconProvider;
|
||||||
|
import com.android.wm.shell.R;
|
||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
import com.android.wm.shell.ShellTaskOrganizer;
|
||||||
import com.android.wm.shell.common.DisplayController;
|
import com.android.wm.shell.common.DisplayController;
|
||||||
import com.android.wm.shell.common.DisplayImeController;
|
import com.android.wm.shell.common.DisplayImeController;
|
||||||
@@ -1921,10 +1923,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
|||||||
@Override
|
@Override
|
||||||
public void onNoLongerSupportMultiWindow() {
|
public void onNoLongerSupportMultiWindow() {
|
||||||
if (mMainStage.isActive()) {
|
if (mMainStage.isActive()) {
|
||||||
|
final Toast splitUnsupportedToast = Toast.makeText(mContext,
|
||||||
|
R.string.dock_non_resizeble_failed_to_dock_text, Toast.LENGTH_SHORT);
|
||||||
final boolean isMainStage = mMainStageListener == this;
|
final boolean isMainStage = mMainStageListener == this;
|
||||||
if (!ENABLE_SHELL_TRANSITIONS) {
|
if (!ENABLE_SHELL_TRANSITIONS) {
|
||||||
StageCoordinator.this.exitSplitScreen(isMainStage ? mMainStage : mSideStage,
|
StageCoordinator.this.exitSplitScreen(isMainStage ? mMainStage : mSideStage,
|
||||||
EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
|
EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
|
||||||
|
splitUnsupportedToast.show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1933,6 +1938,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
|||||||
prepareExitSplitScreen(stageType, wct);
|
prepareExitSplitScreen(stageType, wct);
|
||||||
mSplitTransitions.startDismissTransition(wct,StageCoordinator.this, stageType,
|
mSplitTransitions.startDismissTransition(wct,StageCoordinator.this, stageType,
|
||||||
EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
|
EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
|
||||||
|
splitUnsupportedToast.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,12 +17,12 @@
|
|||||||
package com.android.wm.shell.splitscreen;
|
package com.android.wm.shell.splitscreen;
|
||||||
|
|
||||||
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
|
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
|
||||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
|
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
||||||
|
|
||||||
|
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
|
||||||
|
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE;
|
||||||
import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
|
import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
|
||||||
|
|
||||||
import android.annotation.CallSuper;
|
import android.annotation.CallSuper;
|
||||||
@@ -40,6 +40,7 @@ import android.window.WindowContainerTransaction;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.android.internal.util.ArrayUtils;
|
||||||
import com.android.launcher3.icons.IconProvider;
|
import com.android.launcher3.icons.IconProvider;
|
||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
import com.android.wm.shell.ShellTaskOrganizer;
|
||||||
import com.android.wm.shell.common.SurfaceUtils;
|
import com.android.wm.shell.common.SurfaceUtils;
|
||||||
@@ -62,12 +63,6 @@ import java.util.function.Predicate;
|
|||||||
class StageTaskListener implements ShellTaskOrganizer.TaskListener {
|
class StageTaskListener implements ShellTaskOrganizer.TaskListener {
|
||||||
private static final String TAG = StageTaskListener.class.getSimpleName();
|
private static final String TAG = StageTaskListener.class.getSimpleName();
|
||||||
|
|
||||||
protected static final int[] CONTROLLED_ACTIVITY_TYPES = {ACTIVITY_TYPE_STANDARD};
|
|
||||||
protected static final int[] CONTROLLED_WINDOWING_MODES =
|
|
||||||
{WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED};
|
|
||||||
protected static final int[] CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE =
|
|
||||||
{WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED, WINDOWING_MODE_MULTI_WINDOW};
|
|
||||||
|
|
||||||
/** Callback interface for listening to changes in a split-screen stage. */
|
/** Callback interface for listening to changes in a split-screen stage. */
|
||||||
public interface StageListenerCallbacks {
|
public interface StageListenerCallbacks {
|
||||||
void onRootTaskAppeared();
|
void onRootTaskAppeared();
|
||||||
@@ -212,12 +207,15 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
|
|||||||
}
|
}
|
||||||
mRootTaskInfo = taskInfo;
|
mRootTaskInfo = taskInfo;
|
||||||
} else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
|
} else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
|
||||||
if (!taskInfo.supportsMultiWindow) {
|
if (!taskInfo.supportsMultiWindow
|
||||||
// Leave split screen if the task no longer supports multi window.
|
|| !ArrayUtils.contains(CONTROLLED_ACTIVITY_TYPES, taskInfo.getActivityType())
|
||||||
|
|| !ArrayUtils.contains(CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE,
|
||||||
|
taskInfo.getWindowingMode())) {
|
||||||
|
// Leave split screen if the task no longer supports multi window or have
|
||||||
|
// uncontrolled task.
|
||||||
mCallbacks.onNoLongerSupportMultiWindow();
|
mCallbacks.onNoLongerSupportMultiWindow();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
|
mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
|
||||||
mCallbacks.onChildTaskStatusChanged(taskInfo.taskId, true /* present */,
|
mCallbacks.onChildTaskStatusChanged(taskInfo.taskId, true /* present */,
|
||||||
taskInfo.isVisible);
|
taskInfo.isVisible);
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ package com.android.systemui.shared.recents.model;
|
|||||||
|
|
||||||
import static android.view.Display.DEFAULT_DISPLAY;
|
import static android.view.Display.DEFAULT_DISPLAY;
|
||||||
|
|
||||||
|
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
|
||||||
|
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.ActivityManager.TaskDescription;
|
import android.app.ActivityManager.TaskDescription;
|
||||||
import android.app.TaskInfo;
|
import android.app.TaskInfo;
|
||||||
@@ -31,6 +34,8 @@ import android.view.ViewDebug;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.android.internal.util.ArrayUtils;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@@ -242,8 +247,10 @@ public class Task {
|
|||||||
ActivityManager.TaskDescription td = taskInfo.taskDescription;
|
ActivityManager.TaskDescription td = taskInfo.taskDescription;
|
||||||
return new Task(taskKey,
|
return new Task(taskKey,
|
||||||
td != null ? td.getPrimaryColor() : 0,
|
td != null ? td.getPrimaryColor() : 0,
|
||||||
td != null ? td.getBackgroundColor() : 0,
|
td != null ? td.getBackgroundColor() : 0, taskInfo.supportsMultiWindow
|
||||||
taskInfo.supportsMultiWindow, isLocked, td, taskInfo.topActivity);
|
&& ArrayUtils.contains(CONTROLLED_ACTIVITY_TYPES, taskInfo.getActivityType())
|
||||||
|
&& ArrayUtils.contains(CONTROLLED_WINDOWING_MODES, taskInfo.getWindowingMode()),
|
||||||
|
isLocked, td, taskInfo.topActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task(TaskKey key) {
|
public Task(TaskKey key) {
|
||||||
|
|||||||
@@ -1235,8 +1235,12 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
|
|||||||
+ " task=" + task);
|
+ " task=" + task);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!ArrayUtils.contains(hop.getActivityTypes(), task.getActivityType())
|
if (!ArrayUtils.isEmpty(hop.getActivityTypes())
|
||||||
|| !ArrayUtils.contains(hop.getWindowingModes(), task.getWindowingMode())) {
|
&& !ArrayUtils.contains(hop.getActivityTypes(), task.getActivityType())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!ArrayUtils.isEmpty(hop.getWindowingModes())
|
||||||
|
&& !ArrayUtils.contains(hop.getWindowingModes(), task.getWindowingMode())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (isLockTaskModeViolation(finalNewParent, task, isInLockTaskMode)) {
|
if (isLockTaskModeViolation(finalNewParent, task, isInLockTaskMode)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user