Merge "Add API to set launch TDA featureId in options"

This commit is contained in:
Chris Li
2022-06-30 08:42:46 +00:00
committed by Gerrit Code Review
6 changed files with 159 additions and 4 deletions

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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)) {

View File

@@ -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

View File

@@ -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);