Add API to set launch TDA featureId in options
- Add new api in ActivityOptions for a caller to be able to specify launch TaskDisplayArea in ActivityOptions. - Add option to specify launch TaskDisplayArea featureId in ActivityManagerShellCommand. Bug: 234349363 Test: atest TaskLaunchParamsModifierTests Change-Id: I092787ede5245d15774e01054c408533fe632b57
This commit is contained in:
@@ -149,6 +149,7 @@ package android.app {
|
||||
method @NonNull @RequiresPermission(android.Manifest.permission.START_TASKS_FROM_RECENTS) public static android.app.ActivityOptions makeCustomTaskAnimation(@NonNull android.content.Context, int, int, @Nullable android.os.Handler, @Nullable android.app.ActivityOptions.OnAnimationStartedListener, @Nullable android.app.ActivityOptions.OnAnimationFinishedListener);
|
||||
method public static void setExitTransitionTimeout(long);
|
||||
method public void setLaunchActivityType(int);
|
||||
method public void setLaunchTaskDisplayAreaFeatureId(int);
|
||||
method public void setLaunchWindowingMode(int);
|
||||
method public void setLaunchedFromBubble(boolean);
|
||||
method public void setTaskAlwaysOnTop(boolean);
|
||||
|
||||
@@ -21,6 +21,7 @@ import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
|
||||
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 android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
@@ -207,6 +208,14 @@ public class ActivityOptions {
|
||||
private static final String KEY_LAUNCH_TASK_DISPLAY_AREA_TOKEN =
|
||||
"android.activity.launchTaskDisplayAreaToken";
|
||||
|
||||
/**
|
||||
* The task display area feature id the activity should be launched into.
|
||||
* @see #setLaunchTaskDisplayAreaFeatureId(int)
|
||||
* @hide
|
||||
*/
|
||||
private static final String KEY_LAUNCH_TASK_DISPLAY_AREA_FEATURE_ID =
|
||||
"android.activity.launchTaskDisplayAreaFeatureId";
|
||||
|
||||
/**
|
||||
* The root task token the activity should be launched into.
|
||||
* @see #setLaunchRootTask(WindowContainerToken)
|
||||
@@ -404,6 +413,7 @@ public class ActivityOptions {
|
||||
private int mLaunchDisplayId = INVALID_DISPLAY;
|
||||
private int mCallerDisplayId = INVALID_DISPLAY;
|
||||
private WindowContainerToken mLaunchTaskDisplayArea;
|
||||
private int mLaunchTaskDisplayAreaFeatureId = FEATURE_UNDEFINED;
|
||||
private WindowContainerToken mLaunchRootTask;
|
||||
private IBinder mLaunchTaskFragmentToken;
|
||||
@WindowConfiguration.WindowingMode
|
||||
@@ -1147,6 +1157,8 @@ public class ActivityOptions {
|
||||
mLaunchDisplayId = opts.getInt(KEY_LAUNCH_DISPLAY_ID, INVALID_DISPLAY);
|
||||
mCallerDisplayId = opts.getInt(KEY_CALLER_DISPLAY_ID, INVALID_DISPLAY);
|
||||
mLaunchTaskDisplayArea = opts.getParcelable(KEY_LAUNCH_TASK_DISPLAY_AREA_TOKEN);
|
||||
mLaunchTaskDisplayAreaFeatureId = opts.getInt(KEY_LAUNCH_TASK_DISPLAY_AREA_FEATURE_ID,
|
||||
FEATURE_UNDEFINED);
|
||||
mLaunchRootTask = opts.getParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN);
|
||||
mLaunchTaskFragmentToken = opts.getBinder(KEY_LAUNCH_TASK_FRAGMENT_TOKEN);
|
||||
mLaunchWindowingMode = opts.getInt(KEY_LAUNCH_WINDOWING_MODE, WINDOWING_MODE_UNDEFINED);
|
||||
@@ -1471,6 +1483,23 @@ public class ActivityOptions {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public int getLaunchTaskDisplayAreaFeatureId() {
|
||||
return mLaunchTaskDisplayAreaFeatureId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the TaskDisplayArea feature Id the activity should launch into.
|
||||
* Note: It is possible to have TaskDisplayAreas with the same featureId on multiple displays.
|
||||
* If launch display id is not specified, the TaskDisplayArea on the default display will be
|
||||
* used.
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public void setLaunchTaskDisplayAreaFeatureId(int launchTaskDisplayAreaFeatureId) {
|
||||
mLaunchTaskDisplayAreaFeatureId = launchTaskDisplayAreaFeatureId;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public WindowContainerToken getLaunchRootTask() {
|
||||
return mLaunchRootTask;
|
||||
@@ -1902,6 +1931,9 @@ public class ActivityOptions {
|
||||
if (mLaunchTaskDisplayArea != null) {
|
||||
b.putParcelable(KEY_LAUNCH_TASK_DISPLAY_AREA_TOKEN, mLaunchTaskDisplayArea);
|
||||
}
|
||||
if (mLaunchTaskDisplayAreaFeatureId != FEATURE_UNDEFINED) {
|
||||
b.putInt(KEY_LAUNCH_TASK_DISPLAY_AREA_FEATURE_ID, mLaunchTaskDisplayAreaFeatureId);
|
||||
}
|
||||
if (mLaunchRootTask != null) {
|
||||
b.putParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN, mLaunchRootTask);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import static android.app.WaitResult.launchStateToString;
|
||||
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 android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
|
||||
|
||||
import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
|
||||
import static com.android.internal.app.procstats.ProcessStats.ADJ_MEM_FACTOR_LOW;
|
||||
@@ -170,6 +171,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
private String mAgent; // Agent to attach on startup.
|
||||
private boolean mAttachAgentDuringBind; // Whether agent should be attached late.
|
||||
private int mDisplayId;
|
||||
private int mTaskDisplayAreaFeatureId;
|
||||
private int mWindowingMode;
|
||||
private int mActivityType;
|
||||
private int mTaskId;
|
||||
@@ -353,6 +355,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
mStreaming = false;
|
||||
mUserId = defUser;
|
||||
mDisplayId = INVALID_DISPLAY;
|
||||
mTaskDisplayAreaFeatureId = FEATURE_UNDEFINED;
|
||||
mWindowingMode = WINDOWING_MODE_UNDEFINED;
|
||||
mActivityType = ACTIVITY_TYPE_UNDEFINED;
|
||||
mTaskId = INVALID_TASK_ID;
|
||||
@@ -408,6 +411,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
mReceiverPermission = getNextArgRequired();
|
||||
} else if (opt.equals("--display")) {
|
||||
mDisplayId = Integer.parseInt(getNextArgRequired());
|
||||
} else if (opt.equals("--task-display-area-feature-id")) {
|
||||
mTaskDisplayAreaFeatureId = Integer.parseInt(getNextArgRequired());
|
||||
} else if (opt.equals("--windowingMode")) {
|
||||
mWindowingMode = Integer.parseInt(getNextArgRequired());
|
||||
} else if (opt.equals("--activityType")) {
|
||||
@@ -535,6 +540,12 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
options = ActivityOptions.makeBasic();
|
||||
options.setLaunchDisplayId(mDisplayId);
|
||||
}
|
||||
if (mTaskDisplayAreaFeatureId != FEATURE_UNDEFINED) {
|
||||
if (options == null) {
|
||||
options = ActivityOptions.makeBasic();
|
||||
}
|
||||
options.setLaunchTaskDisplayAreaFeatureId(mTaskDisplayAreaFeatureId);
|
||||
}
|
||||
if (mWindowingMode != WINDOWING_MODE_UNDEFINED) {
|
||||
if (options == null) {
|
||||
options = ActivityOptions.makeBasic();
|
||||
|
||||
@@ -25,7 +25,9 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
||||
import static android.app.WindowConfiguration.activityTypeToString;
|
||||
import static android.content.pm.PackageManager.PERMISSION_DENIED;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.Display.INVALID_DISPLAY;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
|
||||
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
@@ -248,8 +250,25 @@ public class SafeActivityOptions {
|
||||
}
|
||||
// Check if the caller is allowed to launch on the specified display area.
|
||||
final WindowContainerToken daToken = options.getLaunchTaskDisplayArea();
|
||||
final TaskDisplayArea taskDisplayArea = daToken != null
|
||||
TaskDisplayArea taskDisplayArea = daToken != null
|
||||
? (TaskDisplayArea) WindowContainer.fromBinder(daToken.asBinder()) : null;
|
||||
|
||||
// If we do not have a task display area token, check if the launch task display area
|
||||
// feature id is specified.
|
||||
if (taskDisplayArea == null) {
|
||||
final int launchTaskDisplayAreaFeatureId = options.getLaunchTaskDisplayAreaFeatureId();
|
||||
if (launchTaskDisplayAreaFeatureId != FEATURE_UNDEFINED) {
|
||||
final int launchDisplayId = options.getLaunchDisplayId() == INVALID_DISPLAY
|
||||
? DEFAULT_DISPLAY : options.getLaunchDisplayId();
|
||||
final DisplayContent dc = supervisor.mRootWindowContainer
|
||||
.getDisplayContent(launchDisplayId);
|
||||
if (dc != null) {
|
||||
taskDisplayArea = dc.getItemFromTaskDisplayAreas(tda ->
|
||||
tda.mFeatureId == launchTaskDisplayAreaFeatureId ? tda : null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aInfo != null && taskDisplayArea != null
|
||||
&& !supervisor.isCallerAllowedToLaunchOnTaskDisplayArea(callingPid, callingUid,
|
||||
taskDisplayArea, aInfo)) {
|
||||
|
||||
@@ -35,6 +35,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT;
|
||||
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.Display.INVALID_DISPLAY;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
|
||||
|
||||
import static com.android.server.wm.ActivityStarter.Request;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
|
||||
@@ -293,7 +294,8 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
|
||||
TaskDisplayArea taskDisplayArea = suggestedDisplayArea;
|
||||
// If launch task display area is set in options we should just use it. We assume the
|
||||
// suggestedDisplayArea has the right one in this case.
|
||||
if (options == null || options.getLaunchTaskDisplayArea() == null) {
|
||||
if (options == null || (options.getLaunchTaskDisplayArea() == null
|
||||
&& options.getLaunchTaskDisplayAreaFeatureId() == FEATURE_UNDEFINED)) {
|
||||
final int activityType =
|
||||
mSupervisor.mRootWindowContainer.resolveActivityType(root, options, task);
|
||||
display.forAllTaskDisplayAreas(displayArea -> {
|
||||
@@ -377,7 +379,22 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
|
||||
if (optionLaunchTaskDisplayAreaToken != null) {
|
||||
taskDisplayArea = (TaskDisplayArea) WindowContainer.fromBinder(
|
||||
optionLaunchTaskDisplayAreaToken.asBinder());
|
||||
if (DEBUG) appendLog("display-area-from-option=" + taskDisplayArea);
|
||||
if (DEBUG) appendLog("display-area-token-from-option=" + taskDisplayArea);
|
||||
}
|
||||
|
||||
if (taskDisplayArea == null && options != null) {
|
||||
final int launchTaskDisplayAreaFeatureId = options.getLaunchTaskDisplayAreaFeatureId();
|
||||
if (launchTaskDisplayAreaFeatureId != FEATURE_UNDEFINED) {
|
||||
final int launchDisplayId = options.getLaunchDisplayId() == INVALID_DISPLAY
|
||||
? DEFAULT_DISPLAY : options.getLaunchDisplayId();
|
||||
final DisplayContent dc = mSupervisor.mRootWindowContainer
|
||||
.getDisplayContent(launchDisplayId);
|
||||
if (dc != null) {
|
||||
taskDisplayArea = dc.getItemFromTaskDisplayAreas(tda ->
|
||||
tda.mFeatureId == launchTaskDisplayAreaFeatureId ? tda : null);
|
||||
if (DEBUG) appendLog("display-area-feature-from-option=" + taskDisplayArea);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If task display area is not specified in options - try display id
|
||||
|
||||
@@ -195,6 +195,28 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
|
||||
mResult.mPreferredTaskDisplayArea);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsesOptionsDisplayAreaFeatureIdIfSet() {
|
||||
final TestDisplayContent freeformDisplay = createNewDisplayContent(
|
||||
WINDOWING_MODE_FREEFORM);
|
||||
final TestDisplayContent fullscreenDisplay = createNewDisplayContent(
|
||||
WINDOWING_MODE_FULLSCREEN);
|
||||
|
||||
mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
|
||||
ActivityRecord source = createSourceActivity(freeformDisplay);
|
||||
|
||||
ActivityOptions options = ActivityOptions.makeBasic();
|
||||
options.setLaunchDisplayId(fullscreenDisplay.mDisplayId);
|
||||
options.setLaunchTaskDisplayAreaFeatureId(
|
||||
fullscreenDisplay.getDefaultTaskDisplayArea().mFeatureId);
|
||||
|
||||
assertEquals(RESULT_CONTINUE,
|
||||
new CalculateRequestBuilder().setSource(source).setOptions(options).calculate());
|
||||
|
||||
assertEquals(fullscreenDisplay.getDefaultTaskDisplayArea(),
|
||||
mResult.mPreferredTaskDisplayArea);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsesSourcesDisplayAreaIdPriorToTaskIfSet() {
|
||||
final TestDisplayContent freeformDisplay = createNewDisplayContent(
|
||||
@@ -453,7 +475,7 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotOverrideDisplayAreaWhenActivityOptionsHasDisplayArea() {
|
||||
public void testNotOverrideDisplayAreaWhenActivityOptionsHasDisplayAreaToken() {
|
||||
final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(mDefaultDisplay,
|
||||
mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
|
||||
final Task launchRoot = createTask(secondaryDisplayArea, WINDOWING_MODE_FULLSCREEN,
|
||||
@@ -474,6 +496,52 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
|
||||
mDefaultDisplay.getDefaultTaskDisplayArea(), mResult.mPreferredTaskDisplayArea);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotOverrideDisplayAreaWhenActivityOptionsHasDisplayAreaFeatureId() {
|
||||
final TaskDisplayArea secondaryDisplayArea = createTaskDisplayArea(mDefaultDisplay,
|
||||
mWm, "SecondaryDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
|
||||
final Task launchRoot = createTask(secondaryDisplayArea, WINDOWING_MODE_FULLSCREEN,
|
||||
ACTIVITY_TYPE_STANDARD);
|
||||
launchRoot.mCreatedByOrganizer = true;
|
||||
|
||||
secondaryDisplayArea.setLaunchRootTask(launchRoot, new int[] { WINDOWING_MODE_FULLSCREEN },
|
||||
new int[] { ACTIVITY_TYPE_STANDARD });
|
||||
|
||||
ActivityOptions options = ActivityOptions.makeBasic();
|
||||
options.setLaunchTaskDisplayAreaFeatureId(
|
||||
mDefaultDisplay.getDefaultTaskDisplayArea().mFeatureId);
|
||||
|
||||
assertEquals(RESULT_CONTINUE,
|
||||
new CalculateRequestBuilder().setOptions(options).calculate());
|
||||
|
||||
assertEquals(
|
||||
mDefaultDisplay.getDefaultTaskDisplayArea(), mResult.mPreferredTaskDisplayArea);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsesOptionsDisplayAreaFeatureIdDisplayIdNotSet() {
|
||||
final TestDisplayContent secondaryDisplay = createNewDisplayContent(
|
||||
WINDOWING_MODE_FULLSCREEN);
|
||||
final TaskDisplayArea tdaOnSecondaryDisplay = createTaskDisplayArea(secondaryDisplay,
|
||||
mWm, "TestTaskDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
|
||||
|
||||
final TaskDisplayArea tdaOnDefaultDisplay = createTaskDisplayArea(mDefaultDisplay,
|
||||
mWm, "TestTaskDisplayArea", FEATURE_RUNTIME_TASK_CONTAINER_FIRST);
|
||||
|
||||
mCurrent.mPreferredTaskDisplayArea = tdaOnSecondaryDisplay;
|
||||
ActivityRecord source = createSourceActivity(tdaOnSecondaryDisplay,
|
||||
WINDOWING_MODE_FULLSCREEN);
|
||||
|
||||
ActivityOptions options = ActivityOptions.makeBasic();
|
||||
options.setLaunchTaskDisplayAreaFeatureId(tdaOnSecondaryDisplay.mFeatureId);
|
||||
|
||||
assertEquals(RESULT_CONTINUE,
|
||||
new CalculateRequestBuilder().setSource(source).setOptions(options).calculate());
|
||||
// Display id wasn't specified in ActivityOptions - the activity should be placed on the
|
||||
// default display, into the TaskDisplayArea with the same feature id.
|
||||
assertEquals(tdaOnDefaultDisplay, mResult.mPreferredTaskDisplayArea);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecalculateFreeformInitialBoundsWithOverrideDisplayArea() {
|
||||
final TestDisplayContent freeformDisplay = createNewDisplayContent(
|
||||
@@ -1822,6 +1890,13 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
|
||||
return new ActivityBuilder(mAtm).setTask(rootTask).build();
|
||||
}
|
||||
|
||||
private ActivityRecord createSourceActivity(TaskDisplayArea taskDisplayArea,
|
||||
int windowingMode) {
|
||||
final Task rootTask = taskDisplayArea.createRootTask(windowingMode, ACTIVITY_TYPE_STANDARD,
|
||||
true);
|
||||
return new ActivityBuilder(mAtm).setTask(rootTask).build();
|
||||
}
|
||||
|
||||
private void addFreeformTaskTo(TestDisplayContent display, Rect bounds) {
|
||||
final Task rootTask = display.getDefaultTaskDisplayArea()
|
||||
.createRootTask(display.getWindowingMode(), ACTIVITY_TYPE_STANDARD, true);
|
||||
|
||||
Reference in New Issue
Block a user