Merge "Choose TDA by DisplayAreaPolicy for WindowContext"

This commit is contained in:
Charles Chen
2022-01-13 09:29:59 +00:00
committed by Android (Google) Code Review
5 changed files with 307 additions and 7 deletions

View File

@@ -3691,6 +3691,18 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
"1874559932": {
"message": "The TaskDisplayArea with %s does not exist.",
"level": "WARN",
"group": "WM_DEBUG_WINDOW_ORGANIZER",
"at": "com\/android\/server\/wm\/DisplayAreaPolicyBuilder.java"
},
"1884961873": {
"message": "Sleep still need to stop %d activities",
"level": "VERBOSE",
"group": "WM_DEBUG_STATES",
"at": "com\/android\/server\/wm\/Task.java"
},
"1891501279": {
"message": "cancelAnimation(): reason=%s",
"level": "DEBUG",

View File

@@ -34,6 +34,7 @@ import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION
import static com.android.server.wm.DisplayAreaPolicyBuilder.Feature;
import static com.android.server.wm.DisplayAreaPolicyBuilder.HierarchyBuilder;
import android.annotation.Nullable;
import android.content.res.Resources;
import android.os.Bundle;
import android.text.TextUtils;
@@ -86,6 +87,9 @@ public abstract class DisplayAreaPolicy {
*/
public abstract TaskDisplayArea getDefaultTaskDisplayArea();
/** Returns the {@link TaskDisplayArea} specified by launch options. */
public abstract TaskDisplayArea getTaskDisplayArea(@Nullable Bundle options);
/** Provider for platform-default display area policy. */
static final class DefaultProvider implements DisplayAreaPolicy.Provider {
@Override

View File

@@ -27,12 +27,19 @@ import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_LAST;
import static android.window.DisplayAreaOrganizer.KEY_ROOT_DISPLAY_AREA_ID;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.os.Bundle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.window.DisplayAreaOrganizer;
import android.window.WindowContainerToken;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.server.policy.WindowManagerPolicy;
import java.util.ArrayList;
@@ -43,6 +50,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
/**
* A builder for instantiating a complex {@link DisplayAreaPolicy}
@@ -149,6 +157,8 @@ class DisplayAreaPolicyBuilder {
**/
@Nullable private BiFunction<Integer, Bundle, RootDisplayArea> mSelectRootForWindowFunc;
@Nullable private Function<Bundle, TaskDisplayArea> mSelectTaskDisplayAreaFunc;
/** Defines the root hierarchy for the whole logical display. */
DisplayAreaPolicyBuilder setRootHierarchy(HierarchyBuilder rootHierarchyBuilder) {
mRootHierarchyBuilder = rootHierarchyBuilder;
@@ -175,6 +185,16 @@ class DisplayAreaPolicyBuilder {
return this;
}
/**
* The policy will use this function to find the {@link TaskDisplayArea}.
* @see DefaultSelectTaskDisplayAreaFunction as an example.
*/
DisplayAreaPolicyBuilder setSelectTaskDisplayAreaFunc(
Function<Bundle, TaskDisplayArea> selectTaskDisplayAreaFunc) {
mSelectTaskDisplayAreaFunc = selectTaskDisplayAreaFunc;
return this;
}
/**
* Makes sure the setting meets the requirement:
* 1. {@link #mRootHierarchyBuilder} must be set.
@@ -182,8 +202,9 @@ class DisplayAreaPolicyBuilder {
* 3. {@link Feature} below the same {@link RootDisplayArea} must have unique ids.
* 4. There must be exactly one {@link HierarchyBuilder} that contains the IME container.
* 5. There must be exactly one {@link HierarchyBuilder} that contains the default
* {@link TaskDisplayArea} with id {@link FEATURE_DEFAULT_TASK_CONTAINER}.
* 6. None of the ids is greater than {@link FEATURE_VENDOR_LAST}.
* {@link TaskDisplayArea} with id
* {@link DisplayAreaOrganizer#FEATURE_DEFAULT_TASK_CONTAINER}.
* 6. None of the ids is greater than {@link DisplayAreaOrganizer#FEATURE_VENDOR_LAST}.
*/
private void validate() {
if (mRootHierarchyBuilder == null) {
@@ -250,7 +271,7 @@ class DisplayAreaPolicyBuilder {
* {@link Feature} below the same {@link RootDisplayArea} must have unique ids, but
* {@link Feature} below different {@link RootDisplayArea} can have the same id so that we can
* organize them together.
* None of the ids is greater than {@link FEATURE_VENDOR_LAST}
* None of the ids is greater than {@link DisplayAreaOrganizer#FEATURE_VENDOR_LAST}
*
* @param uniqueIdSet ids of {@link RootDisplayArea} and {@link TaskDisplayArea} that must be
* unique,
@@ -323,7 +344,7 @@ class DisplayAreaPolicyBuilder {
mRootHierarchyBuilder.mRoot, displayAreaGroupRoots);
}
return new Result(wmService, mRootHierarchyBuilder.mRoot, displayAreaGroupRoots,
mSelectRootForWindowFunc);
mSelectRootForWindowFunc, mSelectTaskDisplayAreaFunc);
}
/**
@@ -367,6 +388,51 @@ class DisplayAreaPolicyBuilder {
}
}
/**
* The default function to find {@link TaskDisplayArea} if there's no other function set
* through {@link #setSelectTaskDisplayAreaFunc(Function)}.
* <p>
* This function returns {@link TaskDisplayArea} specified by
* {@link ActivityOptions#getLaunchTaskDisplayArea()} if it is not {@code null}. Otherwise,
* returns {@link DisplayContent#getDefaultTaskDisplayArea()}.
* </p>
*/
private static class DefaultSelectTaskDisplayAreaFunction implements
Function<Bundle, TaskDisplayArea> {
private final TaskDisplayArea mDefaultTaskDisplayArea;
private final int mDisplayId;
DefaultSelectTaskDisplayAreaFunction(TaskDisplayArea defaultTaskDisplayArea) {
mDefaultTaskDisplayArea = defaultTaskDisplayArea;
mDisplayId = defaultTaskDisplayArea.getDisplayId();
}
@Override
public TaskDisplayArea apply(@Nullable Bundle options) {
if (options == null) {
return mDefaultTaskDisplayArea;
}
final ActivityOptions activityOptions = new ActivityOptions(options);
final WindowContainerToken tdaToken = activityOptions.getLaunchTaskDisplayArea();
if (tdaToken == null) {
return mDefaultTaskDisplayArea;
}
final TaskDisplayArea tda = WindowContainer.fromBinder(tdaToken.asBinder())
.asTaskDisplayArea();
if (tda == null) {
ProtoLog.w(WM_DEBUG_WINDOW_ORGANIZER, "The TaskDisplayArea with %s does not "
+ "exist.", tdaToken);
return mDefaultTaskDisplayArea;
}
if (tda.getDisplayId() != mDisplayId) {
throw new IllegalArgumentException("The specified TaskDisplayArea must attach "
+ "to Display#" + mDisplayId + ", but it is in Display#"
+ tda.getDisplayId());
}
return tda;
}
}
/**
* Builder to define {@link Feature} and {@link DisplayArea} hierarchy under a
* {@link RootDisplayArea}
@@ -722,11 +788,13 @@ class DisplayAreaPolicyBuilder {
static class Result extends DisplayAreaPolicy {
final List<RootDisplayArea> mDisplayAreaGroupRoots;
final BiFunction<Integer, Bundle, RootDisplayArea> mSelectRootForWindowFunc;
private final Function<Bundle, TaskDisplayArea> mSelectTaskDisplayAreaFunc;
private final TaskDisplayArea mDefaultTaskDisplayArea;
Result(WindowManagerService wmService, RootDisplayArea root,
List<RootDisplayArea> displayAreaGroupRoots,
BiFunction<Integer, Bundle, RootDisplayArea> selectRootForWindowFunc) {
BiFunction<Integer, Bundle, RootDisplayArea> selectRootForWindowFunc,
Function<Bundle, TaskDisplayArea> selectTaskDisplayAreaFunc) {
super(wmService, root);
mDisplayAreaGroupRoots = Collections.unmodifiableList(displayAreaGroupRoots);
mSelectRootForWindowFunc = selectRootForWindowFunc;
@@ -740,6 +808,9 @@ class DisplayAreaPolicyBuilder {
throw new IllegalStateException(
"No display area with FEATURE_DEFAULT_TASK_CONTAINER");
}
mSelectTaskDisplayAreaFunc = selectTaskDisplayAreaFunc != null
? selectTaskDisplayAreaFunc
: new DefaultSelectTaskDisplayAreaFunction(mDefaultTaskDisplayArea);
}
@Override
@@ -796,6 +867,12 @@ class DisplayAreaPolicyBuilder {
public TaskDisplayArea getDefaultTaskDisplayArea() {
return mDefaultTaskDisplayArea;
}
@NonNull
@Override
public TaskDisplayArea getTaskDisplayArea(@Nullable Bundle options) {
return mSelectTaskDisplayAreaFunc.apply(options);
}
}
static class PendingArea {

View File

@@ -6464,9 +6464,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
DisplayArea findAreaForWindowType(int windowType, Bundle options,
boolean ownerCanManageAppToken, boolean roundedCornerOverlay) {
// TODO(b/159767464): figure out how to find an appropriate TDA.
if (windowType >= FIRST_APPLICATION_WINDOW && windowType <= LAST_APPLICATION_WINDOW) {
return getDefaultTaskDisplayArea();
return mDisplayAreaPolicy.getTaskDisplayArea(options);
}
// Return IME container here because it could be in one of sub RootDisplayAreas depending on
// the focused edit text. Also, the RootDisplayArea choosing strategy is implemented by

View File

@@ -16,6 +16,7 @@
package com.android.server.wm;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -48,12 +49,14 @@ import static org.testng.Assert.assertThrows;
import static java.util.stream.Collectors.toList;
import android.app.ActivityOptions;
import android.content.res.Resources;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.view.SurfaceControl;
import android.window.WindowContainerToken;
import com.google.android.collect.Lists;
@@ -80,6 +83,8 @@ import java.util.stream.Collectors;
*/
@Presubmit
public class DisplayAreaPolicyBuilderTest {
private static final String KEY_LAUNCH_TASK_DISPLAY_AREA_FEATURE_ID =
"android.test.launchTaskDisplayAreaFeatureId";
@Rule
public final SystemServicesTestRule mSystemServices = new SystemServicesTestRule();
@@ -103,6 +108,7 @@ public class DisplayAreaPolicyBuilderTest {
mImeContainer = new DisplayArea.Tokens(mWms, ABOVE_TASKS, "ImeContainer");
mDisplayContent = mock(DisplayContent.class);
doReturn(true).when(mDisplayContent).isTrusted();
doReturn(DEFAULT_DISPLAY).when(mDisplayContent).getDisplayId();
mDisplayContent.isDefaultDisplay = true;
mDefaultTaskDisplayArea = new TaskDisplayArea(mDisplayContent, mWms, "Tasks",
FEATURE_DEFAULT_TASK_CONTAINER);
@@ -711,6 +717,208 @@ public class DisplayAreaPolicyBuilderTest {
.build();
}
@Test
public void testGetTaskDisplayArea_DefaultFunction_NullOptions_ReturnsDefaultTda() {
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy0 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mRoot)
.setTaskDisplayAreas(mTaskDisplayAreaList);
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy1 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mGroupRoot1)
.setImeContainer(mImeContainer)
.setTaskDisplayAreas(Lists.newArrayList(mTda1));
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy2 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mGroupRoot2)
.setTaskDisplayAreas(Lists.newArrayList(mTda2));
final DisplayAreaPolicyBuilder.Result policy = new DisplayAreaPolicyBuilder()
.setRootHierarchy(hierarchy0)
.addDisplayAreaGroupHierarchy(hierarchy1)
.addDisplayAreaGroupHierarchy(hierarchy2)
.build(mWms);
final TaskDisplayArea tda = policy.getTaskDisplayArea(null /* options */);
assertThat(tda).isEqualTo(mDefaultTaskDisplayArea);
assertThat(tda).isEqualTo(policy.getDefaultTaskDisplayArea());
}
@Test
public void testGetTaskDisplayArea_DefaultFunction_NotContainsLunchedTda_ReturnsDefaultTda() {
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy0 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mRoot)
.setTaskDisplayAreas(mTaskDisplayAreaList);
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy1 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mGroupRoot1)
.setImeContainer(mImeContainer)
.setTaskDisplayAreas(Lists.newArrayList(mTda1));
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy2 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mGroupRoot2)
.setTaskDisplayAreas(Lists.newArrayList(mTda2));
final DisplayAreaPolicyBuilder.Result policy = new DisplayAreaPolicyBuilder()
.setRootHierarchy(hierarchy0)
.addDisplayAreaGroupHierarchy(hierarchy1)
.addDisplayAreaGroupHierarchy(hierarchy2)
.build(mWms);
final TaskDisplayArea tda = policy.getTaskDisplayArea(new Bundle());
assertThat(tda).isEqualTo(mDefaultTaskDisplayArea);
assertThat(tda).isEqualTo(policy.getDefaultTaskDisplayArea());
}
@Test
public void testGetTaskDisplayArea_DefaultFunction_InvalidTdaToken_ReturnsDefaultTda() {
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy0 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mRoot)
.setTaskDisplayAreas(mTaskDisplayAreaList);
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy1 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mGroupRoot1)
.setImeContainer(mImeContainer)
.setTaskDisplayAreas(Lists.newArrayList(mTda1));
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy2 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mGroupRoot2)
.setTaskDisplayAreas(Lists.newArrayList(mTda2));
final DisplayAreaPolicyBuilder.Result policy = new DisplayAreaPolicyBuilder()
.setRootHierarchy(hierarchy0)
.addDisplayAreaGroupHierarchy(hierarchy1)
.addDisplayAreaGroupHierarchy(hierarchy2)
.build(mWms);
final ActivityOptions options = ActivityOptions.makeBasic();
final WindowContainerToken fakeToken = mRoot.mRemoteToken.toWindowContainerToken();
options.setLaunchTaskDisplayArea(fakeToken);
final TaskDisplayArea tda = policy.getTaskDisplayArea(options.toBundle());
assertThat(tda).isEqualTo(mDefaultTaskDisplayArea);
assertThat(tda).isEqualTo(policy.getDefaultTaskDisplayArea());
}
@Test(expected = IllegalArgumentException.class)
public void testGetTaskDisplayArea_DefaultFunction_TdaOnDifferentDisplay_ThrowException() {
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy0 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mRoot)
.setTaskDisplayAreas(mTaskDisplayAreaList);
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy1 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mGroupRoot1)
.setImeContainer(mImeContainer)
.setTaskDisplayAreas(Lists.newArrayList(mTda1));
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy2 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mGroupRoot2)
.setTaskDisplayAreas(Lists.newArrayList(mTda2));
final DisplayAreaPolicyBuilder.Result policy = new DisplayAreaPolicyBuilder()
.setRootHierarchy(hierarchy0)
.addDisplayAreaGroupHierarchy(hierarchy1)
.addDisplayAreaGroupHierarchy(hierarchy2)
.build(mWms);
final TaskDisplayArea tdaOnSecondaryDisplay = mock(TaskDisplayArea.class);
doReturn(DEFAULT_DISPLAY + 1).when(tdaOnSecondaryDisplay).getDisplayId();
doReturn(tdaOnSecondaryDisplay).when(tdaOnSecondaryDisplay).asTaskDisplayArea();
tdaOnSecondaryDisplay.mRemoteToken = new WindowContainer.RemoteToken(tdaOnSecondaryDisplay);
final WindowContainerToken tdaToken = tdaOnSecondaryDisplay.mRemoteToken
.toWindowContainerToken();
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchTaskDisplayArea(tdaToken);
final TaskDisplayArea tda = policy.getTaskDisplayArea(options.toBundle());
assertThat(tda).isEqualTo(mDefaultTaskDisplayArea);
assertThat(tda).isEqualTo(policy.getDefaultTaskDisplayArea());
}
@Test
public void testGetTaskDisplayArea_DefaultFunction_ContainsTdaToken_ReturnsTda() {
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy0 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mRoot)
.setTaskDisplayAreas(mTaskDisplayAreaList);
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy1 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mGroupRoot1)
.setImeContainer(mImeContainer)
.setTaskDisplayAreas(Lists.newArrayList(mTda1));
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy2 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mGroupRoot2)
.setTaskDisplayAreas(Lists.newArrayList(mTda2));
final DisplayAreaPolicyBuilder.Result policy = new DisplayAreaPolicyBuilder()
.setRootHierarchy(hierarchy0)
.addDisplayAreaGroupHierarchy(hierarchy1)
.addDisplayAreaGroupHierarchy(hierarchy2)
.build(mWms);
final ActivityOptions options = ActivityOptions.makeBasic();
final WindowContainerToken defaultTdaToken = mDefaultTaskDisplayArea.mRemoteToken
.toWindowContainerToken();
options.setLaunchTaskDisplayArea(defaultTdaToken);
TaskDisplayArea tda = policy.getTaskDisplayArea(options.toBundle());
assertThat(tda).isEqualTo(mDefaultTaskDisplayArea);
assertThat(tda).isEqualTo(policy.getDefaultTaskDisplayArea());
final WindowContainerToken tda1Token = mTda1.mRemoteToken.toWindowContainerToken();
options.setLaunchTaskDisplayArea(tda1Token);
tda = policy.getTaskDisplayArea(options.toBundle());
assertThat(tda).isEqualTo(mTda1);
final WindowContainerToken tda2Token = mTda2.mRemoteToken.toWindowContainerToken();
options.setLaunchTaskDisplayArea(tda2Token);
tda = policy.getTaskDisplayArea(options.toBundle());
assertThat(tda).isEqualTo(mTda2);
}
@Test
public void testBuilder_getTaskDisplayArea_setSelectTaskDisplayAreaFunc() {
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy0 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mRoot)
.setTaskDisplayAreas(mTaskDisplayAreaList);
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy1 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mGroupRoot1)
.setImeContainer(mImeContainer)
.setTaskDisplayAreas(Lists.newArrayList(mTda1));
final DisplayAreaPolicyBuilder.HierarchyBuilder hierarchy2 =
new DisplayAreaPolicyBuilder.HierarchyBuilder(mGroupRoot2)
.setTaskDisplayAreas(Lists.newArrayList(mTda2));
final DisplayAreaPolicyBuilder.Result policy = new DisplayAreaPolicyBuilder()
.setRootHierarchy(hierarchy0)
.setSelectTaskDisplayAreaFunc((options) -> {
if (options == null) {
return mDefaultTaskDisplayArea;
}
final int tdaFeatureId =
options.getInt(KEY_LAUNCH_TASK_DISPLAY_AREA_FEATURE_ID);
if (tdaFeatureId == mTda1.mFeatureId) {
return mTda1;
}
if (tdaFeatureId == mTda2.mFeatureId) {
return mTda2;
}
return mDefaultTaskDisplayArea;
})
.addDisplayAreaGroupHierarchy(hierarchy1)
.addDisplayAreaGroupHierarchy(hierarchy2)
.build(mWms);
TaskDisplayArea tda = policy.getTaskDisplayArea(null /* options */);
assertThat(tda).isEqualTo(mDefaultTaskDisplayArea);
assertThat(tda).isEqualTo(policy.getDefaultTaskDisplayArea());
final Bundle options = new Bundle();
options.putInt(KEY_LAUNCH_TASK_DISPLAY_AREA_FEATURE_ID, -1);
tda = policy.getTaskDisplayArea(options);
assertThat(tda).isEqualTo(mDefaultTaskDisplayArea);
options.putInt(KEY_LAUNCH_TASK_DISPLAY_AREA_FEATURE_ID, mDefaultTaskDisplayArea.mFeatureId);
tda = policy.getTaskDisplayArea(options);
assertThat(tda).isEqualTo(mDefaultTaskDisplayArea);
options.putInt(KEY_LAUNCH_TASK_DISPLAY_AREA_FEATURE_ID, mTda1.mFeatureId);
tda = policy.getTaskDisplayArea(options);
assertThat(tda).isEqualTo(mTda1);
options.putInt(KEY_LAUNCH_TASK_DISPLAY_AREA_FEATURE_ID, mTda2.mFeatureId);
tda = policy.getTaskDisplayArea(options);
assertThat(tda).isEqualTo(mTda2);
}
private static Resources resourcesWithProvider(String provider) {
Resources mock = mock(Resources.class);
when(mock.getString(