summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jiaming Liu <jiamingliu@google.com> 2024-04-12 16:17:51 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-04-12 16:17:51 +0000
commitd46319583fd20e7824c65fc6d24a250eb845542e (patch)
treec478dadad0ebc3611a94a6a57b97539f3f7f0679
parent65ed54918576e10eee0379f5cb09f0e2fc27cb7c (diff)
parentf3ad69e1bccce37acabe2eb5f9158279e9352de6 (diff)
Merge "Allow system organizer to specify TF override orientation" into main
-rw-r--r--core/java/android/window/TaskFragmentCreationParams.java43
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java54
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java16
4 files changed, 114 insertions, 2 deletions
diff --git a/core/java/android/window/TaskFragmentCreationParams.java b/core/java/android/window/TaskFragmentCreationParams.java
index 93297e64c621..89327fe358f5 100644
--- a/core/java/android/window/TaskFragmentCreationParams.java
+++ b/core/java/android/window/TaskFragmentCreationParams.java
@@ -18,10 +18,13 @@ package android.window;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.WindowingMode;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.TestApi;
+import android.content.pm.ActivityInfo.ScreenOrientation;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.Parcel;
@@ -101,11 +104,20 @@ public final class TaskFragmentCreationParams implements Parcelable {
*/
private final boolean mAllowTransitionWhenEmpty;
+ /**
+ * The override orientation for the TaskFragment. This is effective only for a system organizer.
+ * The value is ignored otherwise. Default to {@code SCREEN_ORIENTATION_UNSPECIFIED}.
+ *
+ * @see TaskFragmentOrganizer#registerOrganizer(boolean)
+ */
+ private final @ScreenOrientation int mOverrideOrientation;
+
private TaskFragmentCreationParams(
@NonNull TaskFragmentOrganizerToken organizer, @NonNull IBinder fragmentToken,
@NonNull IBinder ownerToken, @NonNull Rect initialRelativeBounds,
@WindowingMode int windowingMode, @Nullable IBinder pairedPrimaryFragmentToken,
- @Nullable IBinder pairedActivityToken, boolean allowTransitionWhenEmpty) {
+ @Nullable IBinder pairedActivityToken, boolean allowTransitionWhenEmpty,
+ @ScreenOrientation int overrideOrientation) {
if (pairedPrimaryFragmentToken != null && pairedActivityToken != null) {
throw new IllegalArgumentException("pairedPrimaryFragmentToken and"
+ " pairedActivityToken should not be set at the same time.");
@@ -118,6 +130,7 @@ public final class TaskFragmentCreationParams implements Parcelable {
mPairedPrimaryFragmentToken = pairedPrimaryFragmentToken;
mPairedActivityToken = pairedActivityToken;
mAllowTransitionWhenEmpty = allowTransitionWhenEmpty;
+ mOverrideOrientation = overrideOrientation;
}
@NonNull
@@ -168,6 +181,11 @@ public final class TaskFragmentCreationParams implements Parcelable {
return mAllowTransitionWhenEmpty;
}
+ /** @hide */
+ public @ScreenOrientation int getOverrideOrientation() {
+ return mOverrideOrientation;
+ }
+
private TaskFragmentCreationParams(Parcel in) {
mOrganizer = TaskFragmentOrganizerToken.CREATOR.createFromParcel(in);
mFragmentToken = in.readStrongBinder();
@@ -177,6 +195,7 @@ public final class TaskFragmentCreationParams implements Parcelable {
mPairedPrimaryFragmentToken = in.readStrongBinder();
mPairedActivityToken = in.readStrongBinder();
mAllowTransitionWhenEmpty = in.readBoolean();
+ mOverrideOrientation = in.readInt();
}
/** @hide */
@@ -190,6 +209,7 @@ public final class TaskFragmentCreationParams implements Parcelable {
dest.writeStrongBinder(mPairedPrimaryFragmentToken);
dest.writeStrongBinder(mPairedActivityToken);
dest.writeBoolean(mAllowTransitionWhenEmpty);
+ dest.writeInt(mOverrideOrientation);
}
@NonNull
@@ -217,6 +237,7 @@ public final class TaskFragmentCreationParams implements Parcelable {
+ " pairedFragmentToken=" + mPairedPrimaryFragmentToken
+ " pairedActivityToken=" + mPairedActivityToken
+ " allowTransitionWhenEmpty=" + mAllowTransitionWhenEmpty
+ + " overrideOrientation=" + mOverrideOrientation
+ "}";
}
@@ -252,6 +273,8 @@ public final class TaskFragmentCreationParams implements Parcelable {
private boolean mAllowTransitionWhenEmpty;
+ private @ScreenOrientation int mOverrideOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
+
public Builder(@NonNull TaskFragmentOrganizerToken organizer,
@NonNull IBinder fragmentToken, @NonNull IBinder ownerToken) {
mOrganizer = organizer;
@@ -330,12 +353,28 @@ public final class TaskFragmentCreationParams implements Parcelable {
return this;
}
+ /**
+ * Sets the override orientation for the TaskFragment. This is effective only for a system
+ * organizer. The value is ignored otherwise. Default to
+ * {@code SCREEN_ORIENTATION_UNSPECIFIED}.
+ *
+ * @see TaskFragmentOrganizer#registerOrganizer(boolean)
+ *
+ * @hide
+ */
+ @RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
+ @NonNull
+ public Builder setOverrideOrientation(@ScreenOrientation int overrideOrientation) {
+ mOverrideOrientation = overrideOrientation;
+ return this;
+ }
+
/** Constructs the options to create TaskFragment with. */
@NonNull
public TaskFragmentCreationParams build() {
return new TaskFragmentCreationParams(mOrganizer, mFragmentToken, mOwnerToken,
mInitialRelativeBounds, mWindowingMode, mPairedPrimaryFragmentToken,
- mPairedActivityToken, mAllowTransitionWhenEmpty);
+ mPairedActivityToken, mAllowTransitionWhenEmpty, mOverrideOrientation);
}
}
}
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 393a01ff0406..8c9317a32483 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -2310,6 +2310,9 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
TaskFragmentOrganizerToken organizerToken = creationParams.getOrganizer();
taskFragment.setTaskFragmentOrganizer(organizerToken,
ownerActivity.getUid(), ownerActivity.info.processName);
+ if (mTaskFragmentOrganizerController.isSystemOrganizer(organizerToken.asBinder())) {
+ taskFragment.setOverrideOrientation(creationParams.getOverrideOrientation());
+ }
final int position;
if (creationParams.getPairedPrimaryFragmentToken() != null) {
// When there is a paired primary TaskFragment, we want to place the new TaskFragment
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 52485eec8505..002a3d5a0d53 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -19,6 +19,8 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
@@ -1024,6 +1026,58 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
}
@Test
+ public void testApplyTransaction_createTaskFragment_overrideOrientation_systemOrganizer() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_TASK_FRAGMENT_SYSTEM_ORGANIZER_FLAG);
+ mController.unregisterOrganizer(mIOrganizer);
+ registerTaskFragmentOrganizer(mIOrganizer, true /* isSystemOrganizer */);
+
+ final Task task = createTask(mDisplayContent);
+ final ActivityRecord activity = createActivityRecord(task);
+ final int uid = Binder.getCallingUid();
+ activity.info.applicationInfo.uid = uid;
+ activity.getTask().effectiveUid = uid;
+ final IBinder fragmentToken = new Binder();
+
+ // Create a TaskFragment with OverrideOrientation set.
+ final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder(
+ mOrganizerToken, fragmentToken, activity.token)
+ .setOverrideOrientation(SCREEN_ORIENTATION_BEHIND)
+ .build();
+ mTransaction.setTaskFragmentOrganizer(mIOrganizer);
+ mTransaction.createTaskFragment(params);
+ assertApplyTransactionAllowed(mTransaction);
+
+ // TaskFragment override orientation should be set for a system organizer.
+ final TaskFragment taskFragment = mWindowOrganizerController.getTaskFragment(fragmentToken);
+ assertNotNull(taskFragment);
+ assertEquals(SCREEN_ORIENTATION_BEHIND, taskFragment.getOverrideOrientation());
+ }
+
+ @Test
+ public void testApplyTransaction_createTaskFragment_overrideOrientation_nonSystemOrganizer() {
+ final Task task = createTask(mDisplayContent);
+ final ActivityRecord activity = createActivityRecord(task);
+ final int uid = Binder.getCallingUid();
+ activity.info.applicationInfo.uid = uid;
+ activity.getTask().effectiveUid = uid;
+ final IBinder fragmentToken = new Binder();
+
+ // Create a TaskFragment with OverrideOrientation set.
+ final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder(
+ mOrganizerToken, fragmentToken, activity.token)
+ .setOverrideOrientation(SCREEN_ORIENTATION_BEHIND)
+ .build();
+ mTransaction.setTaskFragmentOrganizer(mIOrganizer);
+ mTransaction.createTaskFragment(params);
+ assertApplyTransactionAllowed(mTransaction);
+
+ // TaskFragment override orientation is ignored for a non-system organizer.
+ final TaskFragment taskFragment = mWindowOrganizerController.getTaskFragment(fragmentToken);
+ assertNotNull(taskFragment);
+ assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, taskFragment.getOverrideOrientation());
+ }
+
+ @Test
public void testApplyTransaction_reparentActivityToTaskFragment_triggerLifecycleUpdate() {
final Task task = createTask(mDisplayContent);
final ActivityRecord activity = createActivityRecord(task);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index 3c5b12c68e1c..4837fcbfc262 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
@@ -752,6 +753,21 @@ public class TaskFragmentTest extends WindowTestsBase {
}
@Test
+ public void testGetOrientation_reportOverrideOrientation() {
+ final Task task = createTask(mDisplayContent);
+ final TaskFragment tf = createTaskFragmentWithActivity(task);
+ final ActivityRecord activity = tf.getTopMostActivity();
+ tf.setOverrideOrientation(SCREEN_ORIENTATION_BEHIND);
+
+ // Should report the override orientation
+ assertEquals(SCREEN_ORIENTATION_BEHIND, tf.getOrientation(SCREEN_ORIENTATION_UNSET));
+
+ // Should report the override orientation even if the activity requests a different value
+ activity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+ assertEquals(SCREEN_ORIENTATION_BEHIND, tf.getOrientation(SCREEN_ORIENTATION_UNSET));
+ }
+
+ @Test
public void testUpdateImeParentForActivityEmbedding() {
// Setup two activities in ActivityEmbedding.
final Task task = createTask(mDisplayContent);