Loading data/etc/services.core.protolog.json +12 −0 Original line number Diff line number Diff line Loading @@ -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", Loading services/core/java/com/android/server/wm/DisplayAreaPolicy.java +4 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java +82 −5 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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} Loading Loading @@ -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; Loading @@ -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. Loading @@ -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) { Loading Loading @@ -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, Loading Loading @@ -323,7 +344,7 @@ class DisplayAreaPolicyBuilder { mRootHierarchyBuilder.mRoot, displayAreaGroupRoots); } return new Result(wmService, mRootHierarchyBuilder.mRoot, displayAreaGroupRoots, mSelectRootForWindowFunc); mSelectRootForWindowFunc, mSelectTaskDisplayAreaFunc); } /** Loading Loading @@ -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} Loading Loading @@ -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; Loading @@ -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 Loading Loading @@ -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 { Loading services/core/java/com/android/server/wm/DisplayContent.java +1 −2 Original line number Diff line number Diff line Loading @@ -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 Loading services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java +208 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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(); Loading @@ -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); Loading Loading @@ -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( Loading Loading
data/etc/services.core.protolog.json +12 −0 Original line number Diff line number Diff line Loading @@ -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", Loading
services/core/java/com/android/server/wm/DisplayAreaPolicy.java +4 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 Loading
services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java +82 −5 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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} Loading Loading @@ -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; Loading @@ -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. Loading @@ -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) { Loading Loading @@ -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, Loading Loading @@ -323,7 +344,7 @@ class DisplayAreaPolicyBuilder { mRootHierarchyBuilder.mRoot, displayAreaGroupRoots); } return new Result(wmService, mRootHierarchyBuilder.mRoot, displayAreaGroupRoots, mSelectRootForWindowFunc); mSelectRootForWindowFunc, mSelectTaskDisplayAreaFunc); } /** Loading Loading @@ -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} Loading Loading @@ -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; Loading @@ -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 Loading Loading @@ -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 { Loading
services/core/java/com/android/server/wm/DisplayContent.java +1 −2 Original line number Diff line number Diff line Loading @@ -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 Loading
services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java +208 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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(); Loading @@ -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); Loading Loading @@ -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( Loading