ActivityOptions.set/getLaunchStackId() be gone!
Removed ActivityOptions.set/getLaunchStackId() and replacement
ActivityOptions.set/getWindowingMode() and set/getActivityType()
Test: Existing tests pass.
Test: go/wm-smoke
Bug: 64146578
Change-Id: Ifc1c35f7b13c335cdf1a1694208e9fe0aea0c1fa
diff --git a/api/test-current.txt b/api/test-current.txt
index 7256e5c..d6560a7 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -4052,10 +4052,11 @@
method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
method public void requestUsageTimeReport(android.app.PendingIntent);
method public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle);
+ method public void setLaunchActivityType(int);
method public android.app.ActivityOptions setLaunchBounds(android.graphics.Rect);
method public android.app.ActivityOptions setLaunchDisplayId(int);
- method public void setLaunchStackId(int);
method public void setLaunchTaskId(int);
+ method public void setLaunchWindowingMode(int);
method public void setTaskOverlay(boolean, boolean);
method public android.os.Bundle toBundle();
method public void update(android.app.ActivityOptions);
@@ -6244,6 +6245,7 @@
field public static final int ACTIVITY_TYPE_UNDEFINED = 0; // 0x0
field public static final int WINDOWING_MODE_FREEFORM = 5; // 0x5
field public static final int WINDOWING_MODE_FULLSCREEN = 1; // 0x1
+ field public static final int WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY = 4; // 0x4
field public static final int WINDOWING_MODE_PINNED = 2; // 0x2
field public static final int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY = 3; // 0x3
field public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY = 4; // 0x4
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index a866503..78d05f5 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -770,21 +770,6 @@
}
/**
- * Returns true if animation specs should be constructed for app transition that moves
- * the task to the specified stack.
- * @hide
- */
- public static boolean useAnimationSpecForAppTransition(int stackId) {
- // TODO: INVALID_STACK_ID is also animated because we don't persist stack id's across
- // reboots.
- return stackId == FREEFORM_WORKSPACE_STACK_ID
- || stackId == FULLSCREEN_WORKSPACE_STACK_ID
- || stackId == ASSISTANT_STACK_ID
- || stackId == DOCKED_STACK_ID
- || stackId == INVALID_STACK_ID;
- }
-
- /**
* Returns true if activities from stasks in the given {@param stackId} are allowed to
* enter picture-in-picture.
* @hide
@@ -885,6 +870,18 @@
return windowingMode;
}
+ /** Returns the stack id for the input windowing mode.
+ * @hide */
+ // TODO: To be removed once we are not using stack id for stuff...
+ public static int getStackIdForWindowingMode(int windowingMode) {
+ switch (windowingMode) {
+ case WINDOWING_MODE_PINNED: return PINNED_STACK_ID;
+ case WINDOWING_MODE_FREEFORM: return FREEFORM_WORKSPACE_STACK_ID;
+ case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY: return DOCKED_STACK_ID;
+ default: return INVALID_STACK_ID;
+ }
+ }
+
/** Returns the activity type that should be used for this input stack id.
* @hide */
// TODO: To be removed once we are not using stack id for stuff...
@@ -905,6 +902,18 @@
}
return activityType;
}
+
+ /** Returns the stack id for the input activity type.
+ * @hide */
+ // TODO: To be removed once we are not using stack id for stuff...
+ public static int getStackIdForActivityType(int activityType) {
+ switch (activityType) {
+ case ACTIVITY_TYPE_HOME: return HOME_STACK_ID;
+ case ACTIVITY_TYPE_RECENTS: return RECENTS_STACK_ID;
+ case ACTIVITY_TYPE_ASSISTANT: return ASSISTANT_STACK_ID;
+ default: return INVALID_STACK_ID;
+ }
+ }
}
/**
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 0bffc9e..a68c3a5 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -18,6 +18,8 @@
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.INVALID_DISPLAY;
import android.annotation.Nullable;
@@ -164,10 +166,16 @@
private static final String KEY_LAUNCH_DISPLAY_ID = "android.activity.launchDisplayId";
/**
- * The stack id the activity should be launched into.
+ * The windowing mode the activity should be launched into.
* @hide
*/
- private static final String KEY_LAUNCH_STACK_ID = "android.activity.launchStackId";
+ private static final String KEY_LAUNCH_WINDOWING_MODE = "android.activity.windowingMode";
+
+ /**
+ * The activity type the activity should be launched as.
+ * @hide
+ */
+ private static final String KEY_LAUNCH_ACTIVITY_TYPE = "android.activity.activityType";
/**
* The task id the activity should be launched into.
@@ -272,7 +280,10 @@
private int mExitCoordinatorIndex;
private PendingIntent mUsageTimeReport;
private int mLaunchDisplayId = INVALID_DISPLAY;
- private int mLaunchStackId = INVALID_STACK_ID;
+ @WindowConfiguration.WindowingMode
+ private int mLaunchWindowingMode = WINDOWING_MODE_UNDEFINED;
+ @WindowConfiguration.ActivityType
+ private int mLaunchActivityType = ACTIVITY_TYPE_UNDEFINED;
private int mLaunchTaskId = -1;
private int mDockCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
private boolean mDisallowEnterPictureInPictureWhileLaunching;
@@ -860,7 +871,8 @@
break;
}
mLaunchDisplayId = opts.getInt(KEY_LAUNCH_DISPLAY_ID, INVALID_DISPLAY);
- mLaunchStackId = opts.getInt(KEY_LAUNCH_STACK_ID, INVALID_STACK_ID);
+ mLaunchWindowingMode = opts.getInt(KEY_LAUNCH_WINDOWING_MODE, WINDOWING_MODE_UNDEFINED);
+ mLaunchActivityType = opts.getInt(KEY_LAUNCH_ACTIVITY_TYPE, ACTIVITY_TYPE_UNDEFINED);
mLaunchTaskId = opts.getInt(KEY_LAUNCH_TASK_ID, -1);
mTaskOverlay = opts.getBoolean(KEY_TASK_OVERLAY, false);
mTaskOverlayCanResume = opts.getBoolean(KEY_TASK_OVERLAY_CAN_RESUME, false);
@@ -1070,14 +1082,34 @@
}
/** @hide */
- public int getLaunchStackId() {
- return mLaunchStackId;
+ public int getLaunchWindowingMode() {
+ return mLaunchWindowingMode;
+ }
+
+ /**
+ * Sets the windowing mode the activity should launch into. If the input windowing mode is
+ * {@link android.app.WindowConfiguration#WINDOWING_MODE_SPLIT_SCREEN_SECONDARY} and the device
+ * isn't currently in split-screen windowing mode, then the activity will be launched in
+ * {@link android.app.WindowConfiguration#WINDOWING_MODE_FULLSCREEN} windowing mode. For clarity
+ * on this you can use
+ * {@link android.app.WindowConfiguration#WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY}
+ *
+ * @hide
+ */
+ @TestApi
+ public void setLaunchWindowingMode(int windowingMode) {
+ mLaunchWindowingMode = windowingMode;
+ }
+
+ /** @hide */
+ public int getLaunchActivityType() {
+ return mLaunchActivityType;
}
/** @hide */
@TestApi
- public void setLaunchStackId(int launchStackId) {
- mLaunchStackId = launchStackId;
+ public void setLaunchActivityType(int activityType) {
+ mLaunchActivityType = activityType;
}
/**
@@ -1291,7 +1323,8 @@
break;
}
b.putInt(KEY_LAUNCH_DISPLAY_ID, mLaunchDisplayId);
- b.putInt(KEY_LAUNCH_STACK_ID, mLaunchStackId);
+ b.putInt(KEY_LAUNCH_WINDOWING_MODE, mLaunchWindowingMode);
+ b.putInt(KEY_LAUNCH_ACTIVITY_TYPE, mLaunchActivityType);
b.putInt(KEY_LAUNCH_TASK_ID, mLaunchTaskId);
b.putBoolean(KEY_TASK_OVERLAY, mTaskOverlay);
b.putBoolean(KEY_TASK_OVERLAY_CAN_RESUME, mTaskOverlayCanResume);
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index 07eb5de..0cb3804 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -63,8 +63,21 @@
/**
* The containers adjacent to the {@link #WINDOWING_MODE_SPLIT_SCREEN_PRIMARY} container in
* split-screen mode.
+ * NOTE: Containers launched with the windowing mode with APIs like
+ * {@link ActivityOptions#setLaunchWindowingMode(int)} will be launched in
+ * {@link #WINDOWING_MODE_FULLSCREEN} if the display isn't currently in split-screen windowing
+ * mode
+ * @see #WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY
*/
public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY = 4;
+ /**
+ * Alias for {@link #WINDOWING_MODE_SPLIT_SCREEN_SECONDARY} that makes it clear that the usage
+ * points for APIs like {@link ActivityOptions#setLaunchWindowingMode(int)} that the container
+ * will launch into fullscreen or split-screen secondary depending on if the device is currently
+ * in fullscreen mode or split-screen mode.
+ */
+ public static final int WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY =
+ WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
/** Can be freely resized within its parent container. */
public static final int WINDOWING_MODE_FREEFORM = 5;
@@ -75,6 +88,7 @@
WINDOWING_MODE_PINNED,
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
+ WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY,
WINDOWING_MODE_FREEFORM,
})
public @interface WindowingMode {}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index bc85fad..7903d6f 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -16,9 +16,10 @@
package android.widget;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
import android.annotation.ColorInt;
import android.annotation.DimenRes;
-import android.app.ActivityManager.StackId;
import android.app.ActivityOptions;
import android.app.ActivityThread;
import android.app.Application;
@@ -324,11 +325,11 @@
public boolean onClickHandler(View view, PendingIntent pendingIntent,
Intent fillInIntent) {
- return onClickHandler(view, pendingIntent, fillInIntent, StackId.INVALID_STACK_ID);
+ return onClickHandler(view, pendingIntent, fillInIntent, WINDOWING_MODE_UNDEFINED);
}
public boolean onClickHandler(View view, PendingIntent pendingIntent,
- Intent fillInIntent, int launchStackId) {
+ Intent fillInIntent, int windowingMode) {
try {
// TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
Context context = view.getContext();
@@ -339,8 +340,8 @@
opts = ActivityOptions.makeBasic();
}
- if (launchStackId != StackId.INVALID_STACK_ID) {
- opts.setLaunchStackId(launchStackId);
+ if (windowingMode != WINDOWING_MODE_UNDEFINED) {
+ opts.setLaunchWindowingMode(windowingMode);
}
context.startIntentSender(
pendingIntent.getIntentSender(), fillInIntent,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index aecf95f..c4e8701 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -565,8 +565,7 @@
// Launch the task
ssp.startActivityFromRecents(
- mContext, toTask.key, toTask.title, launchOpts, INVALID_STACK_ID,
- null /* resultListener */);
+ mContext, toTask.key, toTask.title, launchOpts, null /* resultListener */);
}
/**
@@ -639,8 +638,7 @@
// Launch the task
ssp.startActivityFromRecents(
- mContext, toTask.key, toTask.title, launchOpts, INVALID_STACK_ID,
- null /* resultListener */);
+ mContext, toTask.key, toTask.title, launchOpts, null /* resultListener */);
}
public void showNextAffiliatedTask() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java
index 3db106e..862a1ee 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java
@@ -16,6 +16,9 @@
package com.android.systemui.recents.events.activity;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
import android.graphics.Rect;
import com.android.systemui.recents.events.EventBus;
@@ -30,15 +33,23 @@
public final TaskView taskView;
public final Task task;
public final Rect targetTaskBounds;
- public final int targetTaskStack;
+ public final int targetWindowingMode;
+ public final int targetActivityType;
public final boolean screenPinningRequested;
- public LaunchTaskEvent(TaskView taskView, Task task, Rect targetTaskBounds, int targetTaskStack,
+ public LaunchTaskEvent(TaskView taskView, Task task, Rect targetTaskBounds,
boolean screenPinningRequested) {
+ this(taskView, task, targetTaskBounds, screenPinningRequested,
+ WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED);
+ }
+
+ public LaunchTaskEvent(TaskView taskView, Task task, Rect targetTaskBounds,
+ boolean screenPinningRequested, int windowingMode, int activityType) {
this.taskView = taskView;
this.task = task;
this.targetTaskBounds = targetTaskBounds;
- this.targetTaskStack = targetTaskStack;
+ this.targetWindowingMode = windowingMode;
+ this.targetActivityType = activityType;
this.screenPinningRequested = screenPinningRequested;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 7177782..366a908 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -23,6 +23,10 @@
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
import android.annotation.NonNull;
@@ -576,7 +580,7 @@
try {
final ActivityOptions options = ActivityOptions.makeBasic();
options.setDockCreateMode(createMode);
- options.setLaunchStackId(DOCKED_STACK_ID);
+ options.setLaunchWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
mIam.startActivityFromRecents(taskId, options.toBundle());
return true;
} catch (Exception e) {
@@ -1120,9 +1124,16 @@
opts != null ? opts.toBundle() : null, UserHandle.CURRENT));
}
+ public void startActivityFromRecents(Context context, Task.TaskKey taskKey, String taskName,
+ ActivityOptions options,
+ @Nullable final StartActivityFromRecentsResultListener resultListener) {
+ startActivityFromRecents(context, taskKey, taskName, options,
+ WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED, resultListener);
+ }
+
/** Starts an activity from recents. */
public void startActivityFromRecents(Context context, Task.TaskKey taskKey, String taskName,
- ActivityOptions options, int stackId,
+ ActivityOptions options, int windowingMode, int activityType,
@Nullable final StartActivityFromRecentsResultListener resultListener) {
if (mIam == null) {
return;
@@ -1133,12 +1144,14 @@
if (options == null) {
options = ActivityOptions.makeBasic();
}
- options.setLaunchStackId(FULLSCREEN_WORKSPACE_STACK_ID);
- } else if (stackId != INVALID_STACK_ID) {
+ options.setLaunchWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ } else if (windowingMode != WINDOWING_MODE_UNDEFINED
+ || activityType != ACTIVITY_TYPE_UNDEFINED) {
if (options == null) {
options = ActivityOptions.makeBasic();
}
- options.setLaunchStackId(stackId);
+ options.setLaunchWindowingMode(windowingMode);
+ options.setLaunchActivityType(activityType);
}
final ActivityOptions finalOptions = options;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index b2675d7..4d33216 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -21,6 +21,15 @@
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import android.annotation.Nullable;
import android.app.ActivityManager.StackId;
@@ -107,7 +116,7 @@
*/
public void launchTaskFromRecents(final TaskStack stack, @Nullable final Task task,
final TaskStackView stackView, final TaskView taskView,
- final boolean screenPinningRequested, final int destinationStack) {
+ final boolean screenPinningRequested, final int windowingMode, final int activityType) {
final ActivityOptions.OnAnimationStartedListener animStartedListener;
final AppTransitionAnimationSpecsFuture transitionFuture;
@@ -116,8 +125,8 @@
// Fetch window rect here already in order not to be blocked on lock contention in WM
// when the future calls it.
final Rect windowRect = Recents.getSystemServices().getWindowRect();
- transitionFuture = getAppTransitionFuture(
- () -> composeAnimationSpecs(task, stackView, destinationStack, windowRect));
+ transitionFuture = getAppTransitionFuture(() -> composeAnimationSpecs(
+ task, stackView, windowingMode, activityType, windowRect));
animStartedListener = new OnAnimationStartedListener() {
private boolean mHandled;
@@ -180,7 +189,8 @@
if (taskView == null) {
// If there is no task view, then we do not need to worry about animating out occluding
// task views, and we can launch immediately
- startTaskActivity(stack, task, taskView, opts, transitionFuture, destinationStack);
+ startTaskActivity(stack, task, taskView, opts, transitionFuture,
+ windowingMode, activityType);
} else {
LaunchTaskStartedEvent launchStartedEvent = new LaunchTaskStartedEvent(taskView,
screenPinningRequested);
@@ -189,13 +199,14 @@
@Override
public void run() {
startTaskActivity(stack, task, taskView, opts, transitionFuture,
- destinationStack);
+ windowingMode, activityType);
}
});
EventBus.getDefault().send(launchStartedEvent);
} else {
EventBus.getDefault().send(launchStartedEvent);
- startTaskActivity(stack, task, taskView, opts, transitionFuture, destinationStack);
+ startTaskActivity(stack, task, taskView, opts, transitionFuture,
+ windowingMode, activityType);
}
}
Recents.getSystemServices().sendCloseSystemWindows(
@@ -224,13 +235,13 @@
*
* @param taskView this is the {@link TaskView} that we are launching from. This can be null if
* we are toggling recents and the launch-to task is now offscreen.
- * @param destinationStack id of the stack to put the task into.
*/
private void startTaskActivity(TaskStack stack, Task task, @Nullable TaskView taskView,
ActivityOptions opts, AppTransitionAnimationSpecsFuture transitionFuture,
- int destinationStack) {
+ int windowingMode, int activityType) {
SystemServicesProxy ssp = Recents.getSystemServices();
- ssp.startActivityFromRecents(mContext, task.key, task.title, opts, destinationStack,
+ ssp.startActivityFromRecents(mContext, task.key, task.title, opts, windowingMode,
+ activityType,
succeeded -> {
if (succeeded) {
// Keep track of the index of the task launch
@@ -310,11 +321,9 @@
* Composes the animation specs for all the tasks in the target stack.
*/
private List<AppTransitionAnimationSpec> composeAnimationSpecs(final Task task,
- final TaskStackView stackView, final int destinationStack, Rect windowRect) {
- // Ensure we have a valid target stack id
- final int targetStackId = destinationStack != INVALID_STACK_ID ?
- destinationStack : task.key.stackId;
- if (!StackId.useAnimationSpecForAppTransition(targetStackId)) {
+ final TaskStackView stackView, int windowingMode, int activityType, Rect windowRect) {
+ if (activityType == ACTIVITY_TYPE_RECENTS || activityType == ACTIVITY_TYPE_HOME
+ || windowingMode == WINDOWING_MODE_PINNED) {
return null;
}
@@ -329,9 +338,12 @@
List<AppTransitionAnimationSpec> specs = new ArrayList<>();
// TODO: Sometimes targetStackId is not initialized after reboot, so we also have to
- // check for INVALID_STACK_ID
- if (targetStackId == FULLSCREEN_WORKSPACE_STACK_ID || targetStackId == DOCKED_STACK_ID
- || targetStackId == ASSISTANT_STACK_ID || targetStackId == INVALID_STACK_ID) {
+ // check for INVALID_STACK_ID (now WINDOWING_MODE_UNDEFINED)
+ if (windowingMode == WINDOWING_MODE_FULLSCREEN
+ || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
+ || activityType == ACTIVITY_TYPE_ASSISTANT
+ || windowingMode == WINDOWING_MODE_UNDEFINED) {
if (taskView == null) {
specs.add(composeOffscreenAnimationSpec(task, offscreenTaskRect));
} else {
@@ -353,7 +365,7 @@
int taskCount = tasks.size();
for (int i = taskCount - 1; i >= 0; i--) {
Task t = tasks.get(i);
- if (t.isFreeformTask() || targetStackId == FREEFORM_WORKSPACE_STACK_ID) {
+ if (t.isFreeformTask() || windowingMode == WINDOWING_MODE_FREEFORM) {
TaskView tv = stackView.getChildViewForTask(t);
if (tv == null) {
// TODO: Create a different animation task rect for this case (though it should
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index c44cd72..fd1b806 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -338,8 +338,7 @@
Task task = mTaskStackView.getFocusedTask();
if (task != null) {
TaskView taskView = mTaskStackView.getChildViewForTask(task);
- EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null,
- INVALID_STACK_ID, false));
+ EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null, false));
if (logEvent != 0) {
MetricsLogger.action(getContext(), logEvent,
@@ -363,32 +362,13 @@
Task task = getStack().getLaunchTarget();
if (task != null) {
TaskView taskView = mTaskStackView.getChildViewForTask(task);
- EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null,
- INVALID_STACK_ID, false));
+ EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null, false));
return true;
}
}
return false;
}
- /** Launches a given task. */
- public boolean launchTask(Task task, Rect taskBounds, int destinationStack) {
- if (mTaskStackView != null) {
- // Iterate the stack views and try and find the given task.
- List<TaskView> taskViews = mTaskStackView.getTaskViews();
- int taskViewCount = taskViews.size();
- for (int j = 0; j < taskViewCount; j++) {
- TaskView tv = taskViews.get(j);
- if (tv.getTask() == task) {
- EventBus.getDefault().send(new LaunchTaskEvent(tv, task, taskBounds,
- destinationStack, false));
- return true;
- }
- }
- }
- return false;
- }
-
/**
* Hides the task stack and shows the empty view.
*/
@@ -570,7 +550,8 @@
public final void onBusEvent(LaunchTaskEvent event) {
mLastTaskLaunchedWasFreeform = event.task.isFreeformTask();
mTransitionHelper.launchTaskFromRecents(getStack(), event.task, mTaskStackView,
- event.taskView, event.screenPinningRequested, event.targetTaskStack);
+ event.taskView, event.screenPinningRequested, event.targetWindowingMode,
+ event.targetActivityType);
if (Recents.getConfiguration().isLowRamDevice) {
hideStackActionButton(HIDE_STACK_ACTION_BUTTON_DURATION, false /* translate */);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 8899e30..74e9ef2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -1487,7 +1487,7 @@
Task frontTask = tasks.get(tasks.size() - 1);
if (frontTask != null && frontTask.isFreeformTask()) {
EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(frontTask),
- frontTask, null, INVALID_STACK_ID, false));
+ frontTask, null, false));
return true;
}
}
@@ -2369,12 +2369,12 @@
public void run() {
EventBus.getDefault().send(new LaunchTaskEvent(
getChildViewForTask(task), task, null,
- INVALID_STACK_ID, false /* screenPinningRequested */));
+ false /* screenPinningRequested */));
}
});
} else {
- EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(task),
- task, null, INVALID_STACK_ID, false /* screenPinningRequested */));
+ EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(task), task, null,
+ false /* screenPinningRequested */));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index ceeebd96..c64f6df 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -674,8 +674,7 @@
mActionButtonView.setTranslationZ(0f);
screenPinningRequested = true;
}
- EventBus.getDefault().send(new LaunchTaskEvent(this, mTask, null, INVALID_STACK_ID,
- screenPinningRequested));
+ EventBus.getDefault().send(new LaunchTaskEvent(this, mTask, null, screenPinningRequested));
MetricsLogger.action(v.getContext(), MetricsEvent.ACTION_OVERVIEW_SELECT,
mTask.key.getComponent().toString());
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index ae922fc..198ecae 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -16,6 +16,11 @@
package com.android.systemui.recents.views;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.Nullable;
@@ -57,10 +62,6 @@
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-
/* The task bar view */
public class TaskViewHeader extends FrameLayout
implements View.OnClickListener, View.OnLongClickListener {
@@ -172,7 +173,7 @@
int mTaskBarViewLightTextColor;
int mTaskBarViewDarkTextColor;
int mDisabledTaskBarBackgroundColor;
- int mMoveTaskTargetStackId = INVALID_STACK_ID;
+ int mTaskWindowingMode = WINDOWING_MODE_UNDEFINED;
// Header background
private HighlightColorDrawable mBackground;
@@ -485,12 +486,12 @@
// current task
if (mMoveTaskButton != null) {
if (t.isFreeformTask()) {
- mMoveTaskTargetStackId = FULLSCREEN_WORKSPACE_STACK_ID;
+ mTaskWindowingMode = WINDOWING_MODE_FULLSCREEN;
mMoveTaskButton.setImageDrawable(t.useLightOnPrimaryColor
? mLightFullscreenIcon
: mDarkFullscreenIcon);
} else {
- mMoveTaskTargetStackId = FREEFORM_WORKSPACE_STACK_ID;
+ mTaskWindowingMode = WINDOWING_MODE_FREEFORM;
mMoveTaskButton.setImageDrawable(t.useLightOnPrimaryColor
? mLightFreeformIcon
: mDarkFreeformIcon);
@@ -621,8 +622,8 @@
Constants.Metrics.DismissSourceHeaderButton);
} else if (v == mMoveTaskButton) {
TaskView tv = Utilities.findParent(this, TaskView.class);
- EventBus.getDefault().send(new LaunchTaskEvent(tv, mTask, null,
- mMoveTaskTargetStackId, false));
+ EventBus.getDefault().send(new LaunchTaskEvent(tv, mTask, null, false,
+ mTaskWindowingMode, ACTIVITY_TYPE_UNDEFINED));
} else if (v == mAppInfoView) {
EventBus.getDefault().send(new ShowApplicationInfoEvent(mTask));
} else if (v == mAppIconView) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
index 7e08d56..9d2d71e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
@@ -15,6 +15,12 @@
*/
package com.android.systemui.statusbar.car;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
import android.app.ActivityManager.StackId;
import android.content.Context;
import android.content.Intent;
@@ -117,7 +123,8 @@
// Set up the persistent docked task if needed.
if (mPersistentTaskIntent != null && !mStatusBar.hasDockedTask()
&& stackId != StackId.HOME_STACK_ID) {
- mStatusBar.startActivityOnStack(mPersistentTaskIntent, StackId.DOCKED_STACK_ID);
+ mStatusBar.startActivityOnStack(mPersistentTaskIntent,
+ WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
}
}
@@ -375,13 +382,15 @@
// rather than the "preferred/last run" app.
intent.putExtra(EXTRA_FACET_LAUNCH_PICKER, index == mCurrentFacetIndex);
- int stackId = StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+ int windowingMode = WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+ int activityType = ACTIVITY_TYPE_UNDEFINED;
if (intent.getCategories().contains(Intent.CATEGORY_HOME)) {
- stackId = StackId.HOME_STACK_ID;
+ windowingMode = WINDOWING_MODE_UNDEFINED;
+ activityType = ACTIVITY_TYPE_HOME;
}
setCurrentFacet(index);
- mStatusBar.startActivityOnStack(intent, stackId);
+ mStatusBar.startActivityOnStack(intent, windowingMode, activityType);
}
/**
@@ -391,6 +400,7 @@
*/
private void onFacetLongClicked(Intent intent, int index) {
setCurrentFacet(index);
- mStatusBar.startActivityOnStack(intent, StackId.FULLSCREEN_WORKSPACE_STACK_ID);
+ mStatusBar.startActivityOnStack(intent,
+ WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_UNDEFINED);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 680f693..10fc496 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -378,9 +378,10 @@
return result;
}
- public int startActivityOnStack(Intent intent, int stackId) {
- ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchStackId(stackId);
+ public int startActivityOnStack(Intent intent, int windowingMode, int activityType) {
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(windowingMode);
+ options.setLaunchActivityType(activityType);
return startActivityWithOptions(intent, options.toBundle());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index efc8d8b..4ee4330 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -20,6 +20,7 @@
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.windowStateToString;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
@@ -37,7 +38,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
-import android.app.ActivityManager.StackId;
import android.app.ActivityOptions;
import android.app.INotificationManager;
import android.app.KeyguardManager;
@@ -5932,7 +5932,7 @@
private boolean superOnClickHandler(View view, PendingIntent pendingIntent,
Intent fillInIntent) {
return super.onClickHandler(view, pendingIntent, fillInIntent,
- StackId.FULLSCREEN_WORKSPACE_STACK_ID);
+ WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
}
private boolean handleRemoteInput(View view, PendingIntent pendingIntent, Intent fillInIntent) {
@@ -7149,10 +7149,10 @@
}
protected Bundle getActivityOptions() {
- // Anything launched from the notification shade should always go into the
- // fullscreen stack.
- ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchStackId(StackId.FULLSCREEN_WORKSPACE_STACK_ID);
+ // Anything launched from the notification shade should always go into the secondary
+ // split-screen windowing mode.
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
return options.toBundle();
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6c82399..0dd0ade 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -10043,7 +10043,7 @@
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
"getTaskDescription()");
final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(id,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID);
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (tr != null) {
return tr.lastTaskDescription;
}
@@ -10156,7 +10156,7 @@
public void setTaskResizeable(int taskId, int resizeableMode) {
synchronized (this) {
final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(
- taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID);
+ taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (task == null) {
Slog.w(TAG, "setTaskResizeable: taskId=" + taskId + " not found");
return;
@@ -10219,7 +10219,7 @@
try {
synchronized (this) {
final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID);
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (task == null) {
Slog.w(TAG, "getTaskBounds: taskId=" + taskId + " not found");
return rect;
@@ -10251,7 +10251,7 @@
try {
synchronized (this) {
final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
- MATCH_TASK_IN_STACKS_ONLY, INVALID_STACK_ID);
+ MATCH_TASK_IN_STACKS_ONLY);
if (task == null) {
Slog.w(TAG, "cancelTaskWindowTransition: taskId=" + taskId + " not found");
return;
@@ -10270,7 +10270,7 @@
try {
synchronized (this) {
final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
- MATCH_TASK_IN_STACKS_ONLY, INVALID_STACK_ID);
+ MATCH_TASK_IN_STACKS_ONLY);
if (task == null) {
Slog.w(TAG, "cancelTaskThumbnailTransition: taskId=" + taskId + " not found");
return;
@@ -10290,7 +10290,7 @@
final TaskRecord task;
synchronized (this) {
task = mStackSupervisor.anyTaskForIdLocked(taskId,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS, INVALID_STACK_ID);
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (task == null) {
Slog.w(TAG, "getTaskSnapshot: taskId=" + taskId + " not found");
return null;
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 6901d2d..0aca9ea 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -75,6 +75,8 @@
import static android.app.ActivityManager.RESIZE_MODE_USER;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.INVALID_DISPLAY;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
@@ -115,7 +117,8 @@
private boolean mStreaming; // Streaming the profiling output to a file.
private String mAgent; // Agent to attach on startup.
private int mDisplayId;
- private int mStackId;
+ private int mWindowingMode;
+ private int mActivityType;
private int mTaskId;
private boolean mIsTaskOverlay;
@@ -271,7 +274,8 @@
mStreaming = false;
mUserId = defUser;
mDisplayId = INVALID_DISPLAY;
- mStackId = INVALID_STACK_ID;
+ mWindowingMode = WINDOWING_MODE_UNDEFINED;
+ mActivityType = ACTIVITY_TYPE_UNDEFINED;
mTaskId = INVALID_TASK_ID;
mIsTaskOverlay = false;
@@ -308,8 +312,10 @@
mReceiverPermission = getNextArgRequired();
} else if (opt.equals("--display")) {
mDisplayId = Integer.parseInt(getNextArgRequired());
- } else if (opt.equals("--stack")) {
- mStackId = Integer.parseInt(getNextArgRequired());
+ } else if (opt.equals("--windowingMode")) {
+ mWindowingMode = Integer.parseInt(getNextArgRequired());
+ } else if (opt.equals("--activityType")) {
+ mActivityType = Integer.parseInt(getNextArgRequired());
} else if (opt.equals("--task")) {
mTaskId = Integer.parseInt(getNextArgRequired());
} else if (opt.equals("--task-overlay")) {
@@ -396,9 +402,17 @@
options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(mDisplayId);
}
- if (mStackId != INVALID_STACK_ID) {
- options = ActivityOptions.makeBasic();
- options.setLaunchStackId(mStackId);
+ if (mWindowingMode != WINDOWING_MODE_UNDEFINED) {
+ if (options == null) {
+ options = ActivityOptions.makeBasic();
+ }
+ options.setLaunchWindowingMode(mWindowingMode);
+ }
+ if (mActivityType != ACTIVITY_TYPE_UNDEFINED) {
+ if (options == null) {
+ options = ActivityOptions.makeBasic();
+ }
+ options.setLaunchActivityType(mActivityType);
}
if (mTaskId != INVALID_TASK_ID) {
options = ActivityOptions.makeBasic();
@@ -2685,7 +2699,8 @@
pw.println(" --track-allocation: enable tracking of object allocations");
pw.println(" --user <USER_ID> | current: Specify which user to run as; if not");
pw.println(" specified then run as the current user.");
- pw.println(" --stack <STACK_ID>: Specify into which stack should the activity be put.");
+ pw.println(" --windowingMode <WINDOWING_MODE>: The windowing mode to launch the activity into.");
+ pw.println(" --activityType <ACTIVITY_TYPE>: The activity type to launch the activity as.");
pw.println(" start-service [--user <USER_ID> | current] <INTENT>");
pw.println(" Start a Service. Options are:");
pw.println(" --user <USER_ID> | current: Specify which user to run as; if not");
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 0ccb45f..7acabd2 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -17,7 +17,6 @@
package com.android.server.am;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
-import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
@@ -36,7 +35,6 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.activityTypeToString;
import static android.content.Intent.ACTION_MAIN;
@@ -89,10 +87,8 @@
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SAVED_STATE;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SCREENSHOTS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_THUMBNAILS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -1038,7 +1034,7 @@
}
} else if (realActivity.getClassName().contains(RECENTS_PACKAGE_NAME)) {
activityType = ACTIVITY_TYPE_RECENTS;
- } else if (options != null && options.getLaunchStackId() == ASSISTANT_STACK_ID
+ } else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_ASSISTANT
&& canLaunchAssistActivity(launchedFromPackage)) {
activityType = ACTIVITY_TYPE_ASSISTANT;
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index c8a2a23..ffe5fd4 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -21,6 +21,7 @@
import static android.Manifest.permission.START_ANY_ACTIVITY;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
+import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
import static android.app.ActivityManager.StackId.FIRST_STATIC_STACK_ID;
@@ -31,13 +32,20 @@
import static android.app.ActivityManager.StackId.LAST_STATIC_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
+import static android.app.ActivityManager.StackId.getStackIdForActivityType;
+import static android.app.ActivityManager.StackId.getStackIdForWindowingMode;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
@@ -83,6 +91,7 @@
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
import static com.android.server.am.ActivityStack.STACK_VISIBLE;
+import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
@@ -94,6 +103,7 @@
import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
@@ -707,24 +717,26 @@
}
TaskRecord anyTaskForIdLocked(int id) {
- return anyTaskForIdLocked(id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE,
- INVALID_STACK_ID);
+ return anyTaskForIdLocked(id, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE);
+ }
+
+ TaskRecord anyTaskForIdLocked(int id, @AnyTaskForIdMatchTaskMode int matchMode) {
+ return anyTaskForIdLocked(id, matchMode, null);
}
/**
* Returns a {@link TaskRecord} for the input id if available. {@code null} otherwise.
* @param id Id of the task we would like returned.
* @param matchMode The mode to match the given task id in.
- * @param stackId The stack to restore the task to (default launch stack will be used if
- * stackId is {@link android.app.ActivityManager.StackId#INVALID_STACK_ID}). Only
- * valid if the matchMode is
- * {@link #MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE}.
+ * @param aOptions The activity options to use for restoration. Can be null.
*/
- TaskRecord anyTaskForIdLocked(int id, @AnyTaskForIdMatchTaskMode int matchMode, int stackId) {
+ TaskRecord anyTaskForIdLocked(int id, @AnyTaskForIdMatchTaskMode int matchMode,
+ @Nullable ActivityOptions aOptions) {
// If there is a stack id set, ensure that we are attempting to actually restore a task
- if (matchMode != MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE &&
- stackId != INVALID_STACK_ID) {
- throw new IllegalArgumentException("Should not specify stackId for non-restore lookup");
+ // TODO: Don't really know if this is needed...
+ if (matchMode != MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE && aOptions != null) {
+ throw new IllegalArgumentException("Should not specify activity options for non-restore"
+ + " lookup");
}
int numDisplays = mActivityDisplays.size();
@@ -762,7 +774,7 @@
}
// Implicitly, this case is MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE
- if (!restoreRecentTaskLocked(task, stackId)) {
+ if (!restoreRecentTaskLocked(task, aOptions)) {
if (DEBUG_RECENTS) Slog.w(TAG_RECENTS,
"Couldn't restore task id=" + id + " found in recents");
return null;
@@ -857,8 +869,8 @@
// was 10, user 0 could only have taskIds 0 to 9, user 1: 10 to 19, user 2: 20 to 29, so on.
int candidateTaskId = nextTaskIdForUser(currentTaskId, userId);
while (mRecentTasks.taskIdTakenForUserLocked(candidateTaskId, userId)
- || anyTaskForIdLocked(candidateTaskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
- INVALID_STACK_ID) != null) {
+ || anyTaskForIdLocked(
+ candidateTaskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) != null) {
candidateTaskId = nextTaskIdForUser(candidateTaskId, userId);
if (candidateTaskId == currentTaskId) {
// Something wrong!
@@ -2084,38 +2096,35 @@
// we'll just indicate that this task returns to the home task.
task.setTaskToReturnTo(ACTIVITY_TYPE_HOME);
}
- ActivityStack currentStack = task.getStack();
+ final ActivityStack currentStack = task.getStack();
if (currentStack == null) {
Slog.e(TAG, "findTaskToMoveToFrontLocked: can't move task="
+ task + " to front. Stack is null");
return;
}
- if (task.isResizeable() && options != null) {
- int stackId = options.getLaunchStackId();
- if (canUseActivityOptionsLaunchBounds(options, stackId)) {
- final Rect bounds = TaskRecord.validateBounds(options.getLaunchBounds());
- task.updateOverrideConfiguration(bounds);
- if (stackId == INVALID_STACK_ID) {
- stackId = task.getLaunchStackId();
- }
- if (stackId != currentStack.mStackId) {
- task.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
- DEFER_RESUME, "findTaskToMoveToFrontLocked");
- stackId = currentStack.mStackId;
- // moveTaskToStackUncheckedLocked() should already placed the task on top,
- // still need moveTaskToFrontLocked() below for any transition settings.
- }
- if (StackId.resizeStackWithLaunchBounds(stackId)) {
- resizeStackLocked(stackId, bounds,
- null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
- !PRESERVE_WINDOWS, true /* allowResizeInDockedMode */, !DEFER_RESUME);
- } else {
- // WM resizeTask must be done after the task is moved to the correct stack,
- // because Task's setBounds() also updates dim layer's bounds, but that has
- // dependency on the stack.
- task.resizeWindowContainer();
- }
+ if (task.isResizeable() && canUseActivityOptionsLaunchBounds(options)) {
+ final Rect bounds = TaskRecord.validateBounds(options.getLaunchBounds());
+ task.updateOverrideConfiguration(bounds);
+
+ int stackId = getLaunchStackId(null, options, task);
+
+ if (stackId != currentStack.mStackId) {
+ task.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
+ DEFER_RESUME, "findTaskToMoveToFrontLocked");
+ stackId = currentStack.mStackId;
+ // moveTaskToStackUncheckedLocked() should already placed the task on top,
+ // still need moveTaskToFrontLocked() below for any transition settings.
+ }
+ if (StackId.resizeStackWithLaunchBounds(stackId)) {
+ resizeStackLocked(stackId, bounds,
+ null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
+ !PRESERVE_WINDOWS, true /* allowResizeInDockedMode */, !DEFER_RESUME);
+ } else {
+ // WM resizeTask must be done after the task is moved to the correct stack,
+ // because Task's setBounds() also updates dim layer's bounds, but that has
+ // dependency on the stack.
+ task.resizeWindowContainer();
}
}
@@ -2126,17 +2135,18 @@
if (DEBUG_STACK) Slog.d(TAG_STACK,
"findTaskToMoveToFront: moved to front of stack=" + currentStack);
- handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, DEFAULT_DISPLAY,
+ handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY,
currentStack.mStackId, forceNonResizeable);
}
- boolean canUseActivityOptionsLaunchBounds(ActivityOptions options, int launchStackId) {
+ boolean canUseActivityOptionsLaunchBounds(ActivityOptions options) {
// We use the launch bounds in the activity options is the device supports freeform
// window management or is launching into the pinned stack.
- if (options.getLaunchBounds() == null) {
+ if (options == null || options.getLaunchBounds() == null) {
return false;
}
- return (mService.mSupportsPictureInPicture && launchStackId == PINNED_STACK_ID)
+ return (mService.mSupportsPictureInPicture
+ && options.getLaunchWindowingMode() == WINDOWING_MODE_PINNED)
|| mService.mSupportsFreeformWindowManagement;
}
@@ -2161,6 +2171,179 @@
return (T) createStackOnDisplay(stackId, DEFAULT_DISPLAY, createOnTop);
}
+ private int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
+ @Nullable TaskRecord task) {
+
+ // First preference if the windowing mode in the activity options if set.
+ int windowingMode = (options != null)
+ ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
+
+ // If windowing mode is unset, then next preference is the candidate task, then the
+ // activity record.
+ if (windowingMode == WINDOWING_MODE_UNDEFINED) {
+ if (task != null) {
+ windowingMode = task.getWindowingMode();
+ }
+ if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) {
+ windowingMode = r.getWindowingMode();
+ }
+ }
+
+ // Make sure the windowing mode we are trying to use makes sense for what is supported.
+ if (!mService.mSupportsMultiWindow && windowingMode != WINDOWING_MODE_FULLSCREEN) {
+ windowingMode = WINDOWING_MODE_FULLSCREEN;
+ }
+
+ if (!mService.mSupportsSplitScreenMultiWindow
+ && (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)) {
+ windowingMode = WINDOWING_MODE_FULLSCREEN;
+ }
+
+ if (windowingMode == WINDOWING_MODE_FREEFORM
+ && !mService.mSupportsFreeformWindowManagement) {
+ windowingMode = WINDOWING_MODE_FULLSCREEN;
+ }
+
+ return windowingMode;
+ }
+
+ private int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
+ @Nullable TaskRecord task) {
+ // First preference if the activity type in the activity options if set.
+ int activityType = (options != null)
+ ? options.getLaunchActivityType() : ACTIVITY_TYPE_UNDEFINED;
+
+ if (activityType != ACTIVITY_TYPE_UNDEFINED) {
+ return activityType;
+ }
+
+ // If activity type is unset, then next preference is the task, then the activity record.
+ if (task != null) {
+ activityType = task.getActivityType();
+ }
+ if (activityType == ACTIVITY_TYPE_UNDEFINED && r != null) {
+ activityType = r.getActivityType();
+ }
+ return activityType;
+ }
+
+ int getLaunchStackId(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
+ @Nullable TaskRecord candidateTask) {
+ return getLaunchStackId(r, options, candidateTask, INVALID_DISPLAY);
+ }
+
+ /**
+ * Returns the right stack to use for launching factoring in all the input parameters.
+ *
+ * @param r The activity we are trying to launch. Can be null.
+ * @param options The activity options used to the launch. Can be null.
+ * @param candidateTask The possible task the activity might be launched in. Can be null.
+ *
+ * @return The stack to use for the launch or INVALID_STACK_ID.
+ */
+ int getLaunchStackId(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
+ @Nullable TaskRecord candidateTask, int candidateDisplayId) {
+ int taskId = INVALID_TASK_ID;
+ int displayId = INVALID_DISPLAY;
+ //Rect bounds = null;
+
+ // We give preference to the launch preference in activity options.
+ if (options != null) {
+ taskId = options.getLaunchTaskId();
+ displayId = options.getLaunchDisplayId();
+ // TODO: Need to work this into the equation...
+ //bounds = options.getLaunchBounds();
+ }
+
+ // First preference for stack goes to the task Id set in the activity options. Use the stack
+ // associated with that if possible.
+ if (taskId != INVALID_TASK_ID) {
+ // Temporarily set the task id to invalid in case in re-entry.
+ options.setLaunchTaskId(INVALID_TASK_ID);
+ final TaskRecord task = anyTaskForIdLocked(taskId,
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, options);
+ options.setLaunchTaskId(taskId);
+ if (task != null) {
+ return task.getStack().mStackId;
+ }
+ }
+
+ final int windowingMode = resolveWindowingMode(r, options, candidateTask);
+ final int activityType = resolveActivityType(r, options, candidateTask);
+ ActivityStack stack = null;
+
+ // Next preference for stack goes to the display Id set in the activity options or the
+ // candidate display.
+ if (displayId == INVALID_DISPLAY) {
+ displayId = candidateDisplayId;
+ }
+ if (displayId != INVALID_DISPLAY) {
+ if (r != null) {
+ // TODO: This should also take in the windowing mode and activity type into account.
+ stack = getValidLaunchStackOnDisplay(displayId, r);
+ if (stack != null) {
+ return stack.mStackId;
+ }
+ }
+ final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId);
+ if (display != null) {
+ for (int i = display.mStacks.size() - 1; i >= 0; --i) {
+ stack = display.mStacks.get(i);
+ if (stack.getWindowingMode() == windowingMode
+ && stack.getActivityType() == activityType) {
+ return stack.mStackId;
+ }
+ }
+ // TODO: We should create the stack we want on the display at this point.
+ }
+ }
+
+ // Give preference to the stack and display of the input task and activity if they match the
+ // mode we want to launch into.
+ if (candidateTask != null) {
+ stack = candidateTask.getStack();
+ }
+ if (stack == null && r != null) {
+ stack = r.getStack();
+ }
+ if (stack != null) {
+ if (stack.getWindowingMode() == windowingMode
+ && stack.getActivityType() == activityType) {
+ return stack.mStackId;
+ }
+ ActivityDisplay display = stack.getDisplay();
+
+ if (display != null) {
+ for (int i = display.mStacks.size() - 1; i >= 0; --i) {
+ stack = display.mStacks.get(i);
+ if (stack.getWindowingMode() == windowingMode
+ && stack.getActivityType() == activityType) {
+ return stack.mStackId;
+ }
+ }
+ }
+ }
+
+ // Give preference to the type of activity we are trying to launch followed by the windowing
+ // mode.
+ int stackId = getStackIdForActivityType(activityType);
+ if (stackId != INVALID_STACK_ID) {
+ return stackId;
+ }
+ stackId = getStackIdForWindowingMode(windowingMode);
+ if (stackId != INVALID_STACK_ID) {
+ return stackId;
+ }
+
+ // Whatever...return some default for now.
+ if (candidateTask != null && candidateTask.mBounds != null
+ && mService.mSupportsFreeformWindowManagement) {
+ return FREEFORM_WORKSPACE_STACK_ID;
+ }
+ return FULLSCREEN_WORKSPACE_STACK_ID;
+ }
+
/**
* Get a topmost stack on the display, that is a valid launch stack for specified activity.
* If there is no such stack, new dynamic stack can be created.
@@ -2178,7 +2361,7 @@
// Return the topmost valid stack on the display.
for (int i = activityDisplay.mStacks.size() - 1; i >= 0; --i) {
final ActivityStack stack = activityDisplay.mStacks.get(i);
- if (mService.mActivityStarter.isValidLaunchStackId(stack.mStackId, displayId, r)) {
+ if (isValidLaunchStackId(stack.mStackId, displayId, r)) {
return stack;
}
}
@@ -2186,7 +2369,7 @@
// If there is no valid stack on the external display - check if new dynamic stack will do.
if (displayId != Display.DEFAULT_DISPLAY) {
final int newDynamicStackId = getNextStackId();
- if (mService.mActivityStarter.isValidLaunchStackId(newDynamicStackId, displayId, r)) {
+ if (isValidLaunchStackId(newDynamicStackId, displayId, r)) {
return createStackOnDisplay(newDynamicStackId, displayId, true /*onTop*/);
}
}
@@ -2195,6 +2378,32 @@
return null;
}
+ boolean isValidLaunchStackId(int stackId, int displayId, ActivityRecord r) {
+ switch (stackId) {
+ case INVALID_STACK_ID:
+ case HOME_STACK_ID:
+ return false;
+ case FULLSCREEN_WORKSPACE_STACK_ID:
+ return true;
+ case FREEFORM_WORKSPACE_STACK_ID:
+ return r.supportsFreeform();
+ case DOCKED_STACK_ID:
+ return r.supportsSplitScreen();
+ case PINNED_STACK_ID:
+ return r.supportsPictureInPicture();
+ case RECENTS_STACK_ID:
+ return r.isActivityTypeRecents();
+ case ASSISTANT_STACK_ID:
+ return r.isActivityTypeAssistant();
+ default:
+ if (StackId.isDynamicStack(stackId)) {
+ return r.canBeLaunchedOnDisplay(displayId);
+ }
+ Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId);
+ return false;
+ }
+ }
+
ArrayList<ActivityStack> getStacks() {
ArrayList<ActivityStack> allStacks = new ArrayList<>();
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
@@ -2345,8 +2554,7 @@
continueUpdateBounds(RECENTS_STACK_ID);
for (int i = mResizingTasksDuringAnimation.size() - 1; i >= 0; i--) {
final int taskId = mResizingTasksDuringAnimation.valueAt(i);
- final TaskRecord task =
- anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_ONLY, INVALID_STACK_ID);
+ final TaskRecord task = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_ONLY);
if (task != null) {
task.setTaskDockedResizing(false);
}
@@ -2641,8 +2849,7 @@
*/
boolean removeTaskByIdLocked(int taskId, boolean killProcess, boolean removeFromRecents,
boolean pauseImmediately) {
- final TaskRecord tr = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
- INVALID_STACK_ID);
+ final TaskRecord tr = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (tr != null) {
tr.removeTaskActivitiesLocked(pauseImmediately);
cleanUpRemovedTaskLocked(tr, killProcess, removeFromRecents);
@@ -2741,23 +2948,11 @@
/**
* Restores a recent task to a stack
* @param task The recent task to be restored.
- * @param stackId The stack to restore the task to (default launch stack will be used
- * if stackId is {@link android.app.ActivityManager.StackId#INVALID_STACK_ID}
- * or is not a static stack).
+ * @param aOptions The activity options to use for restoration.
* @return true if the task has been restored successfully.
*/
- boolean restoreRecentTaskLocked(TaskRecord task, int stackId) {
- if (!StackId.isStaticStack(stackId)) {
- // If stack is not static (or stack id is invalid) - use the default one.
- // This means that tasks that were on external displays will be restored on the
- // primary display.
- stackId = task.getLaunchStackId();
- } else if (stackId == DOCKED_STACK_ID && !task.supportsSplitScreen()) {
- // Preferred stack is the docked stack, but the task can't go in the docked stack.
- // Put it in the fullscreen stack.
- stackId = FULLSCREEN_WORKSPACE_STACK_ID;
- }
-
+ boolean restoreRecentTaskLocked(TaskRecord task, ActivityOptions aOptions) {
+ final int stackId = getLaunchStackId(null, aOptions, task);
final ActivityStack currentStack = task.getStack();
if (currentStack != null) {
// Task has already been restored once. See if we need to do anything more
@@ -2770,15 +2965,7 @@
currentStack.removeTask(task, "restoreRecentTaskLocked", REMOVE_TASK_MODE_MOVING);
}
- final ActivityStack stack =
- getStack(stackId, CREATE_IF_NEEDED, !ON_TOP);
-
- if (stack == null) {
- // What does this mean??? Not sure how we would get here...
- if (DEBUG_RECENTS) Slog.v(TAG_RECENTS,
- "Unable to find/create stack to restore recent task=" + task);
- return false;
- }
+ final ActivityStack stack = getStack(stackId, CREATE_IF_NEEDED, !ON_TOP);
stack.addTask(task, false /* toTop */, "restoreRecentTask");
// TODO: move call for creation here and other place into Stack.addTask()
@@ -4015,21 +4202,20 @@
return list;
}
- void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredStackId,
+ void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredWindowingMode,
int preferredDisplayId, int actualStackId) {
- handleNonResizableTaskIfNeeded(task, preferredStackId, preferredDisplayId, actualStackId,
- false /* forceNonResizable */);
+ handleNonResizableTaskIfNeeded(task, preferredWindowingMode, preferredDisplayId,
+ actualStackId, false /* forceNonResizable */);
}
- void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredStackId,
+ void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredWindowingMode,
int preferredDisplayId, int actualStackId, boolean forceNonResizable) {
final boolean isSecondaryDisplayPreferred =
- (preferredDisplayId != DEFAULT_DISPLAY && preferredDisplayId != INVALID_DISPLAY)
- || StackId.isDynamicStack(preferredStackId);
+ (preferredDisplayId != DEFAULT_DISPLAY && preferredDisplayId != INVALID_DISPLAY);
final ActivityStack actualStack = getStack(actualStackId);
final boolean inSplitScreenMode = actualStack != null
&& actualStack.inSplitScreenWindowingMode();
- if (((!inSplitScreenMode && preferredStackId != DOCKED_STACK_ID)
+ if (((!inSplitScreenMode && preferredWindowingMode != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
&& !isSecondaryDisplayPreferred) || task.isActivityTypeHome()) {
return;
}
@@ -4424,18 +4610,22 @@
final String callingPackage;
final Intent intent;
final int userId;
+ int activityType = ACTIVITY_TYPE_UNDEFINED;
+ int windowingMode = WINDOWING_MODE_UNDEFINED;
final ActivityOptions activityOptions = (bOptions != null)
? new ActivityOptions(bOptions) : null;
- final int launchStackId = (activityOptions != null)
- ? activityOptions.getLaunchStackId() : INVALID_STACK_ID;
- if (StackId.isHomeOrRecentsStack(launchStackId)) {
+ if (activityOptions != null) {
+ activityType = activityOptions.getLaunchActivityType();
+ windowingMode = activityOptions.getLaunchWindowingMode();
+ }
+ if (activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS) {
throw new IllegalArgumentException("startActivityFromRecentsInner: Task "
+ taskId + " can't be launch in the home/recents stack.");
}
mWindowManager.deferSurfaceLayout();
try {
- if (launchStackId == DOCKED_STACK_ID) {
+ if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
mWindowManager.setDockedStackCreateState(
activityOptions.getDockCreateMode(), null /* initialBounds */);
@@ -4447,7 +4637,7 @@
}
task = anyTaskForIdLocked(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE,
- launchStackId);
+ activityOptions);
if (task == null) {
continueUpdateBounds(RECENTS_STACK_ID);
mWindowManager.executeAppTransition();
@@ -4458,14 +4648,13 @@
// Since we don't have an actual source record here, we assume that the currently
// focused activity was the source.
final ActivityStack focusedStack = getFocusedStack();
- final ActivityRecord sourceRecord =
- focusedStack != null ? focusedStack.topActivity() : null;
+ final ActivityRecord sourceRecord = focusedStack != null
+ ? focusedStack.topActivity() : null;
+ final int stackId = getLaunchStackId(null, activityOptions, task);
- if (launchStackId != INVALID_STACK_ID) {
- if (task.getStackId() != launchStackId) {
- task.reparent(launchStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, ANIMATE,
- DEFER_RESUME, "startActivityFromRecents");
- }
+ if (stackId != INVALID_STACK_ID && task.getStackId() != stackId) {
+ task.reparent(stackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
+ "startActivityFromRecents");
}
// If the user must confirm credentials (e.g. when first launching a work app and the
@@ -4484,7 +4673,7 @@
// If we are launching the task in the docked stack, put it into resizing mode so
// the window renders full-screen with the background filling the void. Also only
// call this at the end to make sure that tasks exists on the window manager side.
- if (launchStackId == DOCKED_STACK_ID) {
+ if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
setResizingDuringAnimation(task);
}
@@ -4502,7 +4691,7 @@
userId = task.userId;
int result = mService.startActivityInPackage(callingUid, callingPackage, intent, null,
null, null, 0, 0, bOptions, userId, task, "startActivityFromRecents");
- if (launchStackId == DOCKED_STACK_ID) {
+ if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
setResizingDuringAnimation(task);
}
return result;
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 16abcfb..d94e866 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -39,6 +39,8 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
@@ -1024,10 +1026,12 @@
ActivityRecord reusedActivity = getReusableIntentActivity();
- final int preferredLaunchStackId =
- (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
- final int preferredLaunchDisplayId =
- (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;
+ int preferredWindowingMode = WINDOWING_MODE_UNDEFINED;
+ int preferredLaunchDisplayId = DEFAULT_DISPLAY;
+ if (mOptions != null) {
+ preferredWindowingMode = mOptions.getLaunchWindowingMode();
+ preferredLaunchDisplayId = mOptions.getLaunchDisplayId();
+ }
if (reusedActivity != null) {
// When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
@@ -1158,7 +1162,7 @@
// Don't use mStartActivity.task to show the toast. We're not starting a new activity
// but reusing 'top'. Fields in mStartActivity may not be fully initialized.
- mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
+ mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
preferredLaunchDisplayId, topStack.mStackId);
return START_DELIVERED_TO_TOP;
@@ -1173,8 +1177,7 @@
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
- result = setTaskFromReuseOrCreateNewTask(
- taskToAffiliate, preferredLaunchStackId, topStack);
+ result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
} else if (mSourceRecord != null) {
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
@@ -1241,7 +1244,7 @@
}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
- mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
+ mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
preferredLaunchDisplayId, mTargetStack.mStackId);
return START_SUCCESS;
@@ -1654,8 +1657,8 @@
mTargetStack.moveToFront("intentActivityFound");
}
- mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(), INVALID_STACK_ID,
- DEFAULT_DISPLAY, mTargetStack.mStackId);
+ mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(),
+ WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack.mStackId);
// If the caller has requested that the target task be reset, then do so.
if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
@@ -1675,8 +1678,7 @@
// Task will be launched over the home stack, so return home.
task.setTaskToReturnTo(ACTIVITY_TYPE_HOME);
return;
- } else if (focusedStack != null && focusedStack != task.getStack() &&
- focusedStack.isActivityTypeAssistant()) {
+ } else if (focusedStack != task.getStack() && focusedStack.isActivityTypeAssistant()) {
// Task was launched over the assistant stack, so return there
task.setTaskToReturnTo(ACTIVITY_TYPE_ASSISTANT);
return;
@@ -1779,7 +1781,7 @@
}
private int setTaskFromReuseOrCreateNewTask(
- TaskRecord taskToAffiliate, int preferredLaunchStackId, ActivityStack topStack) {
+ TaskRecord taskToAffiliate, ActivityStack topStack) {
mTargetStack = computeStackFocus(
mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions);
@@ -1821,8 +1823,10 @@
// If stack id is specified in activity options, usually it means that activity is
// launched not from currently focused stack (e.g. from SysUI or from shell) - in
// that case we check the target stack.
+ // TODO: Not sure I understand the value or use of the commented out code and the
+ // comment above. See if this causes any issues and why...
updateTaskReturnToType(mStartActivity.getTask(), mLaunchFlags,
- preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : topStack);
+ /*preferredLaunchStackId != INVALID_STACK_ID ? mTargetStack : */topStack);
}
if (mDoResume) {
mTargetStack.moveToFront("reuseOrNewTask");
@@ -1964,7 +1968,8 @@
if (mLaunchBounds != null) {
mInTask.updateOverrideConfiguration(mLaunchBounds);
- int stackId = mInTask.getLaunchStackId();
+ // TODO: Shouldn't we already know what stack to use by the time we get here?
+ int stackId = mSupervisor.getLaunchStackId(null, null, mInTask);
if (stackId != mInTask.getStackId()) {
mInTask.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
DEFER_RESUME, "inTaskToFront");
@@ -2102,9 +2107,10 @@
}
}
// If there is no suitable dynamic stack then we figure out which static stack to use.
- final int stackId = task != null ? task.getLaunchStackId() :
- bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
- FULLSCREEN_WORKSPACE_STACK_ID;
+ final int stackId = task != null ? mSupervisor.getLaunchStackId(r, aOptions, task)
+ // TODO: This should go in mSupervisor.getLaunchStackId method...
+ : bounds != null && mService.mSupportsFreeformWindowManagement
+ ? FREEFORM_WORKSPACE_STACK_ID : FULLSCREEN_WORKSPACE_STACK_ID;
stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
}
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
@@ -2165,18 +2171,16 @@
return mSupervisor.getStack(ASSISTANT_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
}
- final int launchDisplayId =
- (aOptions != null) ? aOptions.getLaunchDisplayId() : INVALID_DISPLAY;
-
- final int launchStackId =
- (aOptions != null) ? aOptions.getLaunchStackId() : INVALID_STACK_ID;
-
- if (launchStackId != INVALID_STACK_ID && launchDisplayId != INVALID_DISPLAY) {
- throw new IllegalArgumentException(
- "Stack and display id can't be set at the same time.");
+ int launchDisplayId = INVALID_DISPLAY;
+ int launchStackId = INVALID_STACK_ID;
+ if (aOptions != null) {
+ launchDisplayId = aOptions.getLaunchDisplayId();
+ final int vrDisplayId = mUsingVr2dDisplay ? mSourceDisplayId : INVALID_DISPLAY;
+ launchStackId = mSupervisor.getLaunchStackId(r, aOptions, task, vrDisplayId);
}
- if (isValidLaunchStackId(launchStackId, launchDisplayId, r)) {
+ // TODO: Will no longer be needed once we are on longer using static stack ids.
+ if (mSupervisor.isValidLaunchStackId(launchStackId, launchDisplayId, r)) {
return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
}
if (launchStackId == DOCKED_STACK_ID) {
@@ -2184,12 +2188,14 @@
// for this activity, so we put the activity in the fullscreen stack.
return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
}
+ // TODO: Can probably be removed since ASS.getLaunchStackId() does display resolution.
if (launchDisplayId != INVALID_DISPLAY) {
// Stack id has higher priority than display id.
return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
}
// If we are using Vr2d display, find the virtual display stack.
+ // TODO: Can be removed.
if (mUsingVr2dDisplay) {
ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r);
if (DEBUG_STACK) {
@@ -2240,39 +2246,11 @@
}
}
- boolean isValidLaunchStackId(int stackId, int displayId, ActivityRecord r) {
- switch (stackId) {
- case INVALID_STACK_ID:
- case HOME_STACK_ID:
- return false;
- case FULLSCREEN_WORKSPACE_STACK_ID:
- return true;
- case FREEFORM_WORKSPACE_STACK_ID:
- return r.supportsFreeform();
- case DOCKED_STACK_ID:
- return r.supportsSplitScreen();
- case PINNED_STACK_ID:
- return r.supportsPictureInPicture();
- case RECENTS_STACK_ID:
- return r.isActivityTypeRecents();
- case ASSISTANT_STACK_ID:
- return r.isActivityTypeAssistant();
- default:
- if (StackId.isDynamicStack(stackId)) {
- return r.canBeLaunchedOnDisplay(displayId);
- }
- Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId);
- return false;
- }
- }
-
- Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
+ private Rect getOverrideBounds(ActivityRecord r, ActivityOptions options, TaskRecord inTask) {
Rect newBounds = null;
- if (options != null && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
- if (mSupervisor.canUseActivityOptionsLaunchBounds(
- options, options.getLaunchStackId())) {
- newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
- }
+ if (mSupervisor.canUseActivityOptionsLaunchBounds(options)
+ && (r.isResizeable() || (inTask != null && inTask.isResizeable()))) {
+ newBounds = TaskRecord.validateBounds(options.getLaunchBounds());
}
return newBounds;
}
diff --git a/services/core/java/com/android/server/am/LockTaskController.java b/services/core/java/com/android/server/am/LockTaskController.java
index 241e583..72b5de8 100644
--- a/services/core/java/com/android/server/am/LockTaskController.java
+++ b/services/core/java/com/android/server/am/LockTaskController.java
@@ -25,6 +25,7 @@
import static android.app.StatusBarManager.DISABLE_MASK;
import static android.app.StatusBarManager.DISABLE_NONE;
import static android.app.StatusBarManager.DISABLE_RECENT;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Context.DEVICE_POLICY_SERVICE;
import static android.content.Context.STATUS_BAR_SERVICE;
import static android.os.UserHandle.USER_ALL;
@@ -431,8 +432,8 @@
mSupervisor.resumeFocusedStackTopActivityLocked();
mWindowManager.executeAppTransition();
} else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
- mSupervisor.handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, DEFAULT_DISPLAY,
- task.getStackId(), true /* forceNonResizable */);
+ mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED,
+ DEFAULT_DISPLAY, task.getStackId(), true /* forceNonResizable */);
}
}
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 74c4826..f6e20cd 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -472,8 +472,7 @@
final int taskId = task.taskId;
if (mStackSupervisor.anyTaskForIdLocked(taskId,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS,
- INVALID_STACK_ID) != null) {
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) != null) {
// Should not happen.
Slog.wtf(TAG, "Existing task with taskId " + taskId + "found");
} else if (userId != task.userId) {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 48da655..28b71d9 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -26,6 +26,7 @@
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
+import static android.app.ActivityManager.StackId.getWindowingModeForStackId;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -507,8 +508,7 @@
updateOverrideConfiguration(bounds);
if (getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
// re-restore the task so it can have the proper stack association.
- mService.mStackSupervisor.restoreRecentTaskLocked(this,
- FREEFORM_WORKSPACE_STACK_ID);
+ mService.mStackSupervisor.restoreRecentTaskLocked(this, null);
}
return true;
}
@@ -729,7 +729,8 @@
}
// TODO: Handle incorrect request to move before the actual move, not after.
- supervisor.handleNonResizableTaskIfNeeded(this, preferredStackId, DEFAULT_DISPLAY, stackId);
+ supervisor.handleNonResizableTaskIfNeeded(this, getWindowingModeForStackId(preferredStackId,
+ supervisor.getStack(DOCKED_STACK_ID) != null), DEFAULT_DISPLAY, stackId);
boolean successful = (preferredStackId == stackId);
if (successful && stackId == DOCKED_STACK_ID) {
@@ -2079,27 +2080,6 @@
}
}
- /**
- * Returns the correct stack to use based on task type and currently set bounds,
- * regardless of the focused stack and current stack association of the task.
- * The task will be moved (and stack focus changed) later if necessary.
- */
- int getLaunchStackId() {
- if (isActivityTypeRecents()) {
- return RECENTS_STACK_ID;
- }
- if (isActivityTypeHome()) {
- return HOME_STACK_ID;
- }
- if (isActivityTypeAssistant()) {
- return ASSISTANT_STACK_ID;
- }
- if (mBounds != null) {
- return FREEFORM_WORKSPACE_STACK_ID;
- }
- return FULLSCREEN_WORKSPACE_STACK_ID;
- }
-
/** Returns the bounds that should be used to launch this task. */
private Rect getLaunchBounds() {
if (mStack == null) {
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index 661dd4f..cd1843b 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -17,7 +17,10 @@
package com.android.server.am;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -60,7 +63,7 @@
public void testRestoringInvalidTask() throws Exception {
final ActivityManagerService service = createActivityManagerService();
TaskRecord task = service.mStackSupervisor.anyTaskForIdLocked(0 /*taskId*/,
- MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, 0 /*stackId*/);
+ MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, null);
assertNull(task);
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 3788cf3..b040a63 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -20,6 +20,7 @@
import static android.app.ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION;
import static android.app.ActivityManager.START_VOICE_HIDDEN_SESSION;
import static android.app.ActivityManager.START_VOICE_NOT_ACTIVE_SESSION;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import android.app.ActivityManager;
import android.app.ActivityManager.StackId;
@@ -222,8 +223,8 @@
}
intent = new Intent(intent);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchStackId(StackId.ASSISTANT_STACK_ID);
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchActivityType(ACTIVITY_TYPE_ASSISTANT);
return mAm.startAssistantActivity(mComponent.getPackageName(), callingPid, callingUid,
intent, resolvedType, options.toBundle(), mUser);
} catch (RemoteException e) {