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

Commit bde7413e authored by Massimo Carli's avatar Massimo Carli Committed by Android (Google) Code Review
Browse files

Merge "[21/n] Create Infrastructure for reachability" into main

parents 3a0fb660 a87b90e6
Loading
Loading
Loading
Loading
+57 −1
Original line number Diff line number Diff line
@@ -1129,6 +1129,19 @@ public final class WindowContainerTransaction implements Parcelable {
        return this;
    }

    /**
     * Adds a hierarchy op for app compat reachability.
     *
     * @param container The token for the container Task
     * @param taskId    The id of the current task
     * @hide
     */
    public WindowContainerTransaction setReachabilityOffset(
            @NonNull WindowContainerToken container, int taskId, int x, int y) {
        mHierarchyOps.add(HierarchyOp.createForReachability(container.asBinder(), taskId, x, y));
        return this;
    }

    /**
     * Merges another WCT into this one.
     * @param transfer When true, this will transfer everything from other potentially leaving
@@ -1590,6 +1603,7 @@ public final class WindowContainerTransaction implements Parcelable {
        public static final int HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE = 22;
        public static final int HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT = 23;
        public static final int HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK = 24;
        public static final int HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY = 25;

        @IntDef(prefix = {"HIERARCHY_OP_TYPE_"}, value = {
                HIERARCHY_OP_TYPE_REPARENT,
@@ -1617,6 +1631,7 @@ public final class WindowContainerTransaction implements Parcelable {
                HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE,
                HIERARCHY_OP_TYPE_SET_DISABLE_LAUNCH_ADJACENT,
                HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK,
                HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY,
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface HierarchyOpType {
@@ -1630,6 +1645,10 @@ public final class WindowContainerTransaction implements Parcelable {
        public static final String LAUNCH_KEY_SHORTCUT_CALLING_PACKAGE =
                "android:transaction.hop.shortcut_calling_package";

        // The following keys are used to define the reachability direction after a double tap.
        public static final String REACHABILITY_EVENT_X = "android:transaction.reachability_x";
        public static final String REACHABILITY_EVENT_Y = "android:transaction.reachability_y";

        @HierarchyOpType
        private final int mType;

@@ -1664,6 +1683,9 @@ public final class WindowContainerTransaction implements Parcelable {
        @Nullable
        private Bundle mLaunchOptions;

        @Nullable
        private Bundle mAppCompatOptions;

        @Nullable
        private Intent mActivityIntent;

@@ -1833,7 +1855,21 @@ public final class WindowContainerTransaction implements Parcelable {
                    .build();
        }

        /** Creates a hierarchy op for setting a task non-trimmable by recents. */
        /** Create a hierarchy op for app compat reachability. */
        @NonNull
        public static HierarchyOp createForReachability(IBinder container, int taskId, int x,
                int y) {
            final Bundle appCompatOptions = new Bundle();
            appCompatOptions.putInt(LAUNCH_KEY_TASK_ID, taskId);
            appCompatOptions.putInt(REACHABILITY_EVENT_X, x);
            appCompatOptions.putInt(REACHABILITY_EVENT_Y, y);
            return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY)
                    .setAppCompatOptions(appCompatOptions)
                    .setContainer(container)
                    .build();
        }

        /** Create a hierarchy op for setting a task non-trimmable by recents. */
        @NonNull
        @FlaggedApi(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
        public static HierarchyOp createForSetTaskTrimmableFromRecents(@NonNull IBinder container,
@@ -1863,6 +1899,7 @@ public final class WindowContainerTransaction implements Parcelable {
            mWindowingModes = copy.mWindowingModes;
            mActivityTypes = copy.mActivityTypes;
            mLaunchOptions = copy.mLaunchOptions;
            mAppCompatOptions = copy.mAppCompatOptions;
            mActivityIntent = copy.mActivityIntent;
            mTaskFragmentOperation = copy.mTaskFragmentOperation;
            mKeyguardState = copy.mKeyguardState;
@@ -1889,6 +1926,7 @@ public final class WindowContainerTransaction implements Parcelable {
            mWindowingModes = in.createIntArray();
            mActivityTypes = in.createIntArray();
            mLaunchOptions = in.readBundle();
            mAppCompatOptions = in.readBundle(getClass().getClassLoader());
            mActivityIntent = in.readTypedObject(Intent.CREATOR);
            mTaskFragmentOperation = in.readTypedObject(TaskFragmentOperation.CREATOR);
            mKeyguardState = in.readTypedObject(KeyguardState.CREATOR);
@@ -1965,6 +2003,11 @@ public final class WindowContainerTransaction implements Parcelable {
            return mLaunchOptions;
        }

        @Nullable
        public Bundle getAppCompatOptions() {
            return mAppCompatOptions;
        }

        @Nullable
        public Intent getActivityIntent() {
            return mActivityIntent;
@@ -2100,6 +2143,9 @@ public final class WindowContainerTransaction implements Parcelable {
                case HIERARCHY_OP_TYPE_LAUNCH_TASK:
                    sb.append(mLaunchOptions);
                    break;
                case HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY:
                    sb.append(mAppCompatOptions);
                    break;
                case HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT:
                    sb.append("container=").append(mContainer).append(" clearRoot=").append(mToTop);
                    break;
@@ -2182,6 +2228,7 @@ public final class WindowContainerTransaction implements Parcelable {
            dest.writeIntArray(mWindowingModes);
            dest.writeIntArray(mActivityTypes);
            dest.writeBundle(mLaunchOptions);
            dest.writeBundle(mAppCompatOptions);
            dest.writeTypedObject(mActivityIntent, flags);
            dest.writeTypedObject(mTaskFragmentOperation, flags);
            dest.writeTypedObject(mKeyguardState, flags);
@@ -2244,6 +2291,9 @@ public final class WindowContainerTransaction implements Parcelable {
            @Nullable
            private Bundle mLaunchOptions;

            @Nullable
            private Bundle mAppCompatOptions;

            @Nullable
            private Intent mActivityIntent;

@@ -2328,6 +2378,11 @@ public final class WindowContainerTransaction implements Parcelable {
                return this;
            }

            Builder setAppCompatOptions(@Nullable Bundle appCompatOptions) {
                mAppCompatOptions = appCompatOptions;
                return this;
            }

            Builder setActivityIntent(@Nullable Intent activityIntent) {
                mActivityIntent = activityIntent;
                return this;
@@ -2407,6 +2462,7 @@ public final class WindowContainerTransaction implements Parcelable {
                hierarchyOp.mToTop = mToTop;
                hierarchyOp.mReparentTopOnly = mReparentTopOnly;
                hierarchyOp.mLaunchOptions = mLaunchOptions;
                hierarchyOp.mAppCompatOptions = mAppCompatOptions;
                hierarchyOp.mActivityIntent = mActivityIntent;
                hierarchyOp.mPendingIntent = mPendingIntent;
                hierarchyOp.mAlwaysOnTop = mAlwaysOnTop;
+3 −0
Original line number Diff line number Diff line
@@ -193,6 +193,9 @@ public class Transitions implements RemoteCallable<Transitions>,
    /** Transition to end the recents transition */
    public static final int TRANSIT_END_RECENTS_TRANSITION = TRANSIT_FIRST_CUSTOM + 22;

    /** Transition type for app compat reachability. */
    public static final int TRANSIT_MOVE_LETTERBOX_REACHABILITY = TRANSIT_FIRST_CUSTOM + 23;

    /** Transition type for desktop mode transitions. */
    public static final int TRANSIT_DESKTOP_MODE_TYPES =
            WindowManager.TRANSIT_FIRST_CUSTOM + 100;
+11 −4
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.annotation.Nullable;
import android.graphics.Rect;

import com.android.internal.annotations.VisibleForTesting;
import com.android.window.flags.Flags;

import java.io.PrintWriter;
import java.util.function.Supplier;
@@ -97,8 +98,11 @@ class AppCompatReachabilityPolicy {
    private void handleHorizontalDoubleTap(int x) {
        final AppCompatReachabilityOverrides reachabilityOverrides =
                mActivityRecord.mAppCompatController.getReachabilityOverrides();
        if (!reachabilityOverrides.isHorizontalReachabilityEnabled()
                || mActivityRecord.isInTransition()) {
        // We don't return early when the Shell letterbox implementation is enabled because
        // double tap is always sent via transitions.
        final boolean isInTransition = !Flags.appCompatRefactoring()
                && mActivityRecord.isInTransition();
        if (!reachabilityOverrides.isHorizontalReachabilityEnabled() || isInTransition) {
            return;
        }
        final Rect letterboxInnerFrame = getLetterboxInnerFrame();
@@ -143,8 +147,11 @@ class AppCompatReachabilityPolicy {
    private void handleVerticalDoubleTap(int y) {
        final AppCompatReachabilityOverrides reachabilityOverrides =
                mActivityRecord.mAppCompatController.getReachabilityOverrides();
        if (!reachabilityOverrides.isVerticalReachabilityEnabled()
                || mActivityRecord.isInTransition()) {
        // We don't return early when the Shell letterbox implementation is enabled because
        // double tap is always sent via transitions.
        final boolean isInTransition = !Flags.appCompatRefactoring()
                && mActivityRecord.isInTransition();
        if (!reachabilityOverrides.isVerticalReachabilityEnabled() || isInTransition) {
            return;
        }
        final Rect letterboxInnerFrame = getLetterboxInnerFrame();
+27 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import static android.window.WindowContainerTransaction.Change.CHANGE_FOCUSABLE;
import static android.window.WindowContainerTransaction.Change.CHANGE_FORCE_TRANSLUCENT;
import static android.window.WindowContainerTransaction.Change.CHANGE_HIDDEN;
import static android.window.WindowContainerTransaction.Change.CHANGE_RELATIVE_BOUNDS;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_ROOT_TASK;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_KEYGUARD_STATE;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_ADD_INSETS_FRAME_PROVIDER;
@@ -77,6 +78,8 @@ import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_REPARENT_LEAF_TASK_IF_RELAUNCH;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_START_SHORTCUT;
import static android.window.WindowContainerTransaction.HierarchyOp.REACHABILITY_EVENT_X;
import static android.window.WindowContainerTransaction.HierarchyOp.REACHABILITY_EVENT_Y;

import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_WINDOW_ORGANIZER;
import static com.android.server.wm.ActivityRecord.State.PAUSING;
@@ -1196,6 +1199,30 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
                        caller.mPid, caller.mUid, taskId, safeOptions));
                break;
            }
            case HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY: {
                int doubleTapX = hop.getAppCompatOptions().getInt(REACHABILITY_EVENT_X);
                int doubleTapY = hop.getAppCompatOptions().getInt(REACHABILITY_EVENT_Y);
                final WindowContainer<?> wc = WindowContainer.fromBinder(hop.getContainer());
                if (wc == null) {
                    break;
                }
                final Task currentTask = wc.asTask();
                if (chain.mTransition != null) {
                    chain.mTransition.collect(wc);
                }
                if (currentTask != null) {
                    final ActivityRecord top = currentTask.topRunningActivity();
                    if (top != null) {
                        if (chain.mTransition != null) {
                            chain.mTransition.collect(top);
                        }
                        top.mAppCompatController.getReachabilityPolicy().handleDoubleTap(doubleTapX,
                                doubleTapY);
                    }
                }
                effects |= TRANSACT_EFFECTS_CLIENT_CONFIG;
                break;
            }
            case HIERARCHY_OP_TYPE_REORDER:
            case HIERARCHY_OP_TYPE_REPARENT: {
                final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
+35 −0
Original line number Diff line number Diff line
@@ -18,20 +18,30 @@ package com.android.server.wm;

import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY;
import static android.window.WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID;
import static android.window.WindowContainerTransaction.HierarchyOp.REACHABILITY_EVENT_X;
import static android.window.WindowContainerTransaction.HierarchyOp.REACHABILITY_EVENT_Y;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
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.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.times;

import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import android.window.WindowContainerTransaction.HierarchyOp;

import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
@@ -223,6 +233,31 @@ public class WindowContainerTransactionTests extends WindowTestsBase {
                < tda.mChildren.indexOf(desktopOrganizer.mTasks.get(2).getRootTask()));
    }

    @Test
    public void testAppCompat_setReachabilityOffsets() {
        final Task task = createTask(/* taskId */ 37);
        final WindowContainerToken containerToken = task.getTaskInfo().token;
        spyOn(containerToken);
        final Binder asBinder = new Binder();
        doReturn(asBinder).when(containerToken).asBinder();
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        wct.setReachabilityOffset(containerToken, /* taskId */ task.mTaskId, 10, 20);

        final List<HierarchyOp> hierarchyOps = wct.getHierarchyOps().stream()
                .filter(op -> op.getType() == HIERARCHY_OP_TYPE_APP_COMPAT_REACHABILITY)
                .toList();

        assertEquals(1, hierarchyOps.size());
        final HierarchyOp appCompatOp = hierarchyOps.getFirst();
        assertNotNull(appCompatOp);
        final Bundle appCompatOptions = appCompatOp.getAppCompatOptions();

        assertEquals(task.mTaskId, appCompatOptions.getInt(LAUNCH_KEY_TASK_ID));
        assertEquals(10, appCompatOptions.getInt(REACHABILITY_EVENT_X));
        assertEquals(20, appCompatOptions.getInt(REACHABILITY_EVENT_Y));
        assertSame(asBinder, appCompatOp.getContainer());
    }

    private Task createTask(int taskId) {
        return new Task.Builder(mAtm)
                .setTaskId(taskId)