diff options
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);  |