summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2022-05-03 02:23:27 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2022-05-03 02:23:27 +0000
commit963dc4e957a39a868ee62992c9f90257e5efcbdf (patch)
treea71bbc37df3d5f40be9a6ff62c318edf64131e10
parent36db8e049735c280fa8cd4b86cfd73f5fdb96f42 (diff)
parent6725f73a88438e0413d78707b4334aecaef389ea (diff)
Merge "Notify organizer about TaskFragment parent windowing mode change" into tm-dev am: 6725f73a88
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/18032087 Change-Id: Ic004a0cc8ed861e591934a68dc90759dd6433198 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java7
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java2
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java51
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java2
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java22
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java132
-rw-r--r--services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java10
8 files changed, 207 insertions, 23 deletions
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
index 81caf7786cf5..3ff531573f1f 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
@@ -133,8 +133,7 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
// Create or resize the launching TaskFragment.
if (mFragmentInfos.containsKey(launchingFragmentToken)) {
resizeTaskFragment(wct, launchingFragmentToken, launchingFragmentBounds);
- wct.setWindowingMode(mFragmentInfos.get(launchingFragmentToken).getToken(),
- windowingMode);
+ updateWindowingMode(wct, launchingFragmentToken, windowingMode);
} else {
createTaskFragmentAndReparentActivity(wct, launchingFragmentToken, ownerToken,
launchingFragmentBounds, windowingMode, launchingActivity);
@@ -157,7 +156,7 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
void expandTaskFragment(WindowContainerTransaction wct, IBinder fragmentToken) {
resizeTaskFragment(wct, fragmentToken, new Rect());
setAdjacentTaskFragments(wct, fragmentToken, null /* secondary */, null /* splitRule */);
- setWindowingMode(wct, fragmentToken, WINDOWING_MODE_UNDEFINED);
+ updateWindowingMode(wct, fragmentToken, WINDOWING_MODE_UNDEFINED);
}
/**
@@ -260,7 +259,7 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
wct.setBounds(mFragmentInfos.get(fragmentToken).getToken(), bounds);
}
- private void setWindowingMode(WindowContainerTransaction wct, IBinder fragmentToken,
+ void updateWindowingMode(WindowContainerTransaction wct, IBinder fragmentToken,
@WindowingMode int windowingMode) {
if (!mFragmentInfos.containsKey(fragmentToken)) {
throw new IllegalArgumentException(
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index b370e59ac7c8..54d9c55f75c3 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -17,6 +17,7 @@
package androidx.window.extensions.embedding;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static androidx.window.extensions.embedding.SplitContainer.getFinishPrimaryWithSecondaryBehavior;
import static androidx.window.extensions.embedding.SplitContainer.getFinishSecondaryWithPrimaryBehavior;
@@ -179,6 +180,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// Enter PIP.
// All overrides will be cleanup.
container.setLastRequestedBounds(null /* bounds */);
+ container.setLastRequestedWindowingMode(WINDOWING_MODE_UNDEFINED);
cleanupForEnterPip(wct, container);
} else if (wasInPip) {
// Exit PIP.
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index d8423499730f..06c1d4ec8d32 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -30,7 +30,6 @@ import android.util.LayoutDirection;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowMetrics;
-import android.window.TaskFragmentCreationParams;
import android.window.WindowContainerTransaction;
import androidx.annotation.IntDef;
@@ -122,7 +121,6 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
createTaskFragment(wct, secondaryContainer.getTaskFragmentToken(),
primaryActivity.getActivityToken(), secondaryRectBounds,
windowingMode);
- secondaryContainer.setLastRequestedBounds(secondaryRectBounds);
// Set adjacent to each other so that the containers below will be invisible.
setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule);
@@ -198,18 +196,10 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
container = mController.newContainer(activity, taskId);
final int windowingMode = mController.getTaskContainer(taskId)
.getWindowingModeForSplitTaskFragment(bounds);
- final TaskFragmentCreationParams fragmentOptions =
- createFragmentOptions(
- container.getTaskFragmentToken(),
- activity.getActivityToken(),
- bounds,
- windowingMode);
- wct.createTaskFragment(fragmentOptions);
-
+ createTaskFragment(wct, container.getTaskFragmentToken(), activity.getActivityToken(),
+ bounds, windowingMode);
wct.reparentActivityToTaskFragment(container.getTaskFragmentToken(),
activity.getActivityToken());
-
- container.setLastRequestedBounds(bounds);
} else {
resizeTaskFragmentIfRegistered(wct, container, bounds);
final int windowingMode = mController.getTaskContainer(taskId)
@@ -262,9 +252,6 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
wct.requestFocusOnTaskFragment(primaryContainer.getTaskFragmentToken());
}
applyTransaction(wct);
-
- primaryContainer.setLastRequestedBounds(primaryRectBounds);
- secondaryContainer.setLastRequestedBounds(secondaryRectBounds);
}
/**
@@ -346,8 +333,22 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
@NonNull TaskFragmentContainer container,
@WindowingMode int windowingMode) {
if (container.getInfo() != null) {
- wct.setWindowingMode(container.getInfo().getToken(), windowingMode);
+ updateWindowingMode(wct, container.getTaskFragmentToken(), windowingMode);
+ }
+ }
+
+ @Override
+ void createTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
+ @NonNull IBinder ownerToken, @NonNull Rect bounds, @WindowingMode int windowingMode) {
+ final TaskFragmentContainer container = mController.getContainer(fragmentToken);
+ if (container == null) {
+ throw new IllegalStateException(
+ "Creating a task fragment that is not registered with controller.");
}
+
+ container.setLastRequestedBounds(bounds);
+ container.setLastRequestedWindowingMode(windowingMode);
+ super.createTaskFragment(wct, fragmentToken, ownerToken, bounds, windowingMode);
}
@Override
@@ -368,6 +369,24 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
super.resizeTaskFragment(wct, fragmentToken, bounds);
}
+ @Override
+ void updateWindowingMode(@NonNull WindowContainerTransaction wct,
+ @NonNull IBinder fragmentToken, @WindowingMode int windowingMode) {
+ final TaskFragmentContainer container = mController.getContainer(fragmentToken);
+ if (container == null) {
+ throw new IllegalStateException("Setting windowing mode for a task fragment that is"
+ + " not registered with controller.");
+ }
+
+ if (container.isLastRequestedWindowingModeEqual(windowingMode)) {
+ // Return early if the windowing mode were already requested
+ return;
+ }
+
+ container.setLastRequestedWindowingMode(windowingMode);
+ super.updateWindowingMode(wct, fragmentToken, windowingMode);
+ }
+
boolean shouldShowSideBySide(@NonNull SplitContainer splitContainer) {
final Rect parentBounds = getParentContainerBounds(splitContainer.getPrimaryContainer());
return shouldShowSideBySide(parentBounds, splitContainer.getSplitRule());
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index 3c0762d81494..a70755560eb1 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -106,7 +106,7 @@ class TaskContainer {
int getWindowingModeForSplitTaskFragment(@Nullable Rect taskFragmentBounds) {
// Only set to multi-windowing mode if the pair are showing side-by-side. Otherwise, it
// will be set to UNDEFINED which will then inherit the Task windowing mode.
- if (taskFragmentBounds == null || taskFragmentBounds.isEmpty()) {
+ if (taskFragmentBounds == null || taskFragmentBounds.isEmpty() || isInPictureInPicture()) {
return WINDOWING_MODE_UNDEFINED;
}
// We use WINDOWING_MODE_MULTI_WINDOW when the Task is fullscreen.
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index 871f545d203a..fe422bf37a69 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -17,11 +17,13 @@
package androidx.window.extensions.embedding;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityThread;
+import android.app.WindowConfiguration.WindowingMode;
import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
@@ -73,6 +75,12 @@ class TaskFragmentContainer {
private final Rect mLastRequestedBounds = new Rect();
/**
+ * Windowing mode that was requested last via {@link android.window.WindowContainerTransaction}.
+ */
+ @WindowingMode
+ private int mLastRequestedWindowingMode = WINDOWING_MODE_UNDEFINED;
+
+ /**
* Creates a container with an existing activity that will be re-parented to it in a window
* container transaction.
*/
@@ -300,6 +308,20 @@ class TaskFragmentContainer {
}
}
+ /**
+ * Checks if last requested windowing mode is equal to the provided value.
+ */
+ boolean isLastRequestedWindowingModeEqual(@WindowingMode int windowingMode) {
+ return mLastRequestedWindowingMode == windowingMode;
+ }
+
+ /**
+ * Updates the last requested windowing mode.
+ */
+ void setLastRequestedWindowingMode(@WindowingMode int windowingModes) {
+ mLastRequestedWindowingMode = windowingModes;
+ }
+
/** Gets the parent leaf Task id. */
int getTaskId() {
return mTaskId;
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
new file mode 100644
index 000000000000..906e9904566f
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window.extensions.embedding;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.window.TaskFragmentInfo;
+import android.window.WindowContainerTransaction;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Test class for {@link SplitPresenter}.
+ *
+ * Build/Install/Run:
+ * atest WMJetpackUnitTests:SplitPresenterTest
+ */
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SplitPresenterTest {
+ private static final int TASK_ID = 10;
+ private static final Rect TASK_BOUNDS = new Rect(0, 0, 600, 1200);
+
+ @Mock
+ private Activity mActivity;
+ @Mock
+ private Resources mActivityResources;
+ @Mock
+ private TaskFragmentInfo mTaskFragmentInfo;
+ @Mock
+ private WindowContainerTransaction mTransaction;
+ private SplitController mController;
+ private SplitPresenter mPresenter;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mController = new SplitController();
+ mPresenter = mController.mPresenter;
+ spyOn(mController);
+ spyOn(mPresenter);
+ final Configuration activityConfig = new Configuration();
+ activityConfig.windowConfiguration.setBounds(TASK_BOUNDS);
+ activityConfig.windowConfiguration.setMaxBounds(TASK_BOUNDS);
+ doReturn(mActivityResources).when(mActivity).getResources();
+ doReturn(activityConfig).when(mActivityResources).getConfiguration();
+ }
+
+ @Test
+ public void testCreateTaskFragment() {
+ final TaskFragmentContainer container = mController.newContainer(mActivity, TASK_ID);
+ mPresenter.createTaskFragment(mTransaction, container.getTaskFragmentToken(),
+ mActivity.getActivityToken(), TASK_BOUNDS, WINDOWING_MODE_MULTI_WINDOW);
+
+ assertTrue(container.areLastRequestedBoundsEqual(TASK_BOUNDS));
+ assertTrue(container.isLastRequestedWindowingModeEqual(WINDOWING_MODE_MULTI_WINDOW));
+ verify(mTransaction).createTaskFragment(any());
+ }
+
+ @Test
+ public void testResizeTaskFragment() {
+ final TaskFragmentContainer container = mController.newContainer(mActivity, TASK_ID);
+ mPresenter.mFragmentInfos.put(container.getTaskFragmentToken(), mTaskFragmentInfo);
+ mPresenter.resizeTaskFragment(mTransaction, container.getTaskFragmentToken(), TASK_BOUNDS);
+
+ assertTrue(container.areLastRequestedBoundsEqual(TASK_BOUNDS));
+ verify(mTransaction).setBounds(any(), eq(TASK_BOUNDS));
+
+ // No request to set the same bounds.
+ clearInvocations(mTransaction);
+ mPresenter.resizeTaskFragment(mTransaction, container.getTaskFragmentToken(), TASK_BOUNDS);
+
+ verify(mTransaction, never()).setBounds(any(), any());
+ }
+
+ @Test
+ public void testUpdateWindowingMode() {
+ final TaskFragmentContainer container = mController.newContainer(mActivity, TASK_ID);
+ mPresenter.mFragmentInfos.put(container.getTaskFragmentToken(), mTaskFragmentInfo);
+ mPresenter.updateWindowingMode(mTransaction, container.getTaskFragmentToken(),
+ WINDOWING_MODE_MULTI_WINDOW);
+
+ assertTrue(container.isLastRequestedWindowingModeEqual(WINDOWING_MODE_MULTI_WINDOW));
+ verify(mTransaction).setWindowingMode(any(), eq(WINDOWING_MODE_MULTI_WINDOW));
+
+ // No request to set the same windowing mode.
+ clearInvocations(mTransaction);
+ mPresenter.updateWindowingMode(mTransaction, container.getTaskFragmentToken(),
+ WINDOWING_MODE_MULTI_WINDOW);
+
+ verify(mTransaction, never()).setWindowingMode(any(), anyInt());
+
+ }
+}
diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
index eaf25260405a..6a7873998723 100644
--- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
@@ -197,7 +197,9 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr
final Task parent = tf.getParent().asTask();
final Configuration parentConfig = parent.getConfiguration();
final Configuration lastParentConfig = mLastSentTaskFragmentParentConfigs.get(tf);
- if (configurationsAreEqualForOrganizer(parentConfig, lastParentConfig)) {
+ if (configurationsAreEqualForOrganizer(parentConfig, lastParentConfig)
+ && parentConfig.windowConfiguration.getWindowingMode()
+ == lastParentConfig.windowConfiguration.getWindowingMode()) {
return;
}
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index 7a704742fba2..24d04da49e54 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -202,9 +202,17 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
verify(mOrganizer, never()).onTaskFragmentParentInfoChanged(any(), any());
- // Trigger callback if the info is changed.
+ // Trigger callback if the size is changed.
parentConfig.smallestScreenWidthDp = 100;
+ mController.onTaskFragmentParentInfoChanged(
+ mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
+ mController.dispatchPendingEvents();
+ verify(mOrganizer).onTaskFragmentParentInfoChanged(eq(mFragmentToken), any());
+
+ // Trigger callback if the windowing mode is changed.
+ clearInvocations(mOrganizer);
+ parentConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_PINNED);
mController.onTaskFragmentParentInfoChanged(
mTaskFragment.getTaskFragmentOrganizer(), mTaskFragment);
mController.dispatchPendingEvents();