Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f3ad69e1 authored by Jiaming Liu's avatar Jiaming Liu
Browse files

Allow system organizer to specify TF override orientation

For embedded -1 TF in the home task, we want it to use the same
orientation as the Launcher activity, so we should allow the TF
orientation to be set as SCREEN_ORIENTATION_BEHIND.

Bug: 331945991
Test: atest TaskFragmentTest TaskFragmentOrganizerControllerTest
Change-Id: I4d3b9533cbc401668a099bd2b61caada1a28e9a1
parent c6483d04
Loading
Loading
Loading
Loading
+41 −2
Original line number Diff line number Diff line
@@ -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);
        }
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -2277,6 +2277,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
+54 −0
Original line number Diff line number Diff line
@@ -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;
@@ -1023,6 +1025,58 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
                task.mChildren.indexOf(mTaskFragment));
    }

    @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);
+16 −0
Original line number Diff line number Diff line
@@ -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;
@@ -751,6 +752,21 @@ public class TaskFragmentTest extends WindowTestsBase {
        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, task.getOrientation(SCREEN_ORIENTATION_UNSET));
    }

    @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.