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

Commit 3508c449 authored by Jeremy Sim's avatar Jeremy Sim
Browse files

Flexible Split: State manager

Adds SplitState, a class that manages the "state" of SplitLayout.

Bug: 349828130
Flag: com.android.wm.shell.enable_flexible_two_app_split
Test: Nothing changes when flag is off. Tested manually, it responds correct to split initiation, drag to split, launch adjacent, app pair launch, divider movement, quick switch, Overview dismiss, and other forms of split breaking.
Change-Id: I8d20b0c255eb94749509ef8e5fb8ca1303661373
parent 3b80c8fc
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -85,6 +85,9 @@ public class SplitScreenConstants {
    public @interface SplitIndex {
    }

    /** Signifies that user is currently not in split screen. */
    public static final int NOT_IN_SPLIT = -1;

    /**
     * A snap target for two apps, where the split is 33-66. With FLAG_ENABLE_FLEXIBLE_SPLIT,
     * only used on tablets.
@@ -151,6 +154,23 @@ public class SplitScreenConstants {
    })
    public @interface PersistentSnapPosition {}

    /**
     * These are all the valid "states" that split screen can be in. It's the set of
     * {@link PersistentSnapPosition} + {@link #NOT_IN_SPLIT}.
     */
    @IntDef(value = {
            NOT_IN_SPLIT,
            SNAP_TO_2_33_66,
            SNAP_TO_2_50_50,
            SNAP_TO_2_66_33,
            SNAP_TO_2_90_10,
            SNAP_TO_2_10_90,
            SNAP_TO_3_33_33_33,
            SNAP_TO_3_45_45_10,
            SNAP_TO_3_10_45_45,
    })
    public @interface SplitScreenState {}

    /**
     * Checks if the snapPosition in question is a {@link PersistentSnapPosition}.
     */
+26 −4
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Handler;
import android.util.Log;
import android.view.Display;
import android.view.InsetsController;
import android.view.InsetsSource;
@@ -142,6 +143,9 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
    @ShellMainThread
    private final Handler mHandler;

    /** Singleton source of truth for the current state of split screen on this device. */
    private final SplitState mSplitState;

    private int mDividerWindowWidth;
    private int mDividerInsets;
    private int mDividerSize;
@@ -204,7 +208,8 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
            SplitLayoutHandler splitLayoutHandler,
            SplitWindowManager.ParentContainerCallbacks parentContainerCallbacks,
            DisplayController displayController, DisplayImeController displayImeController,
            ShellTaskOrganizer taskOrganizer, int parallaxType, @ShellMainThread Handler handler) {
            ShellTaskOrganizer taskOrganizer, int parallaxType, SplitState splitState,
            @ShellMainThread Handler handler) {
        mHandler = handler;
        mContext = context.createConfigurationContext(configuration);
        mOrientation = configuration.orientation;
@@ -220,6 +225,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
        mTaskOrganizer = taskOrganizer;
        mImePositionProcessor = new ImePositionProcessor(mContext.getDisplayId());
        mSurfaceEffectPolicy = new ResizingEffectPolicy(parallaxType);
        mSplitState = splitState;

        final Resources res = mContext.getResources();
        mDimNonImeSide = res.getBoolean(R.bool.config_dimNonImeAttachedSide);
@@ -381,6 +387,11 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
        return mDividerSnapAlgorithm.calculateNearestSnapPosition(mDividerPosition);
    }

    /** Updates the {@link SplitState} using the current divider position. */
    public void updateStateWithCurrentPosition() {
        mSplitState.set(calculateCurrentSnapPosition());
    }

    /**
     * Returns the divider position as a fraction from 0 to 1.
     */
@@ -413,7 +424,13 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
            removeTouchZones();
        }

        int currentPosition = calculateCurrentSnapPosition();
        int currentPosition = mSplitState.get();
        // TODO (b/349828130): Can delete this warning after brief soak time.
        if (currentPosition != calculateCurrentSnapPosition()) {
            Log.wtf(TAG, "SplitState is " + mSplitState.get()
                    + ", expected " + calculateCurrentSnapPosition());
        }

        switch (currentPosition) {
            case SNAP_TO_2_10_90:
            case SNAP_TO_3_10_45_45:
@@ -764,7 +781,10 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
                break;
            default:
                flingDividerPosition(currentPosition, snapTarget.position, duration, interpolator,
                        () -> setDividerPosition(snapTarget.position, true /* applyLayoutChange */));
                        () -> {
                            setDividerPosition(snapTarget.position, true /* applyLayoutChange */);
                            mSplitState.set(snapTarget.snapPosition);
                        });
                break;
        }
    }
@@ -836,10 +856,12 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange

    /** Fling divider from current position to center position. */
    public void flingDividerToCenter(@Nullable Runnable finishCallback) {
        final int pos = mDividerSnapAlgorithm.getMiddleTarget().position;
        final SnapTarget target = mDividerSnapAlgorithm.getMiddleTarget();
        final int pos = target.position;
        flingDividerPosition(getDividerPosition(), pos, FLING_ENTER_DURATION, FAST_OUT_SLOW_IN,
                () -> {
                    setDividerPosition(pos, true /* applyLayoutChange */);
                    mSplitState.set(target.snapPosition);
                    if (finishCallback != null) {
                        finishCallback.run();
                    }
+42 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 com.android.wm.shell.common.split;

import static com.android.wm.shell.shared.split.SplitScreenConstants.NOT_IN_SPLIT;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SplitScreenState;

/**
 * A class that manages the "state" of split screen. See {@link SplitScreenState} for definitions.
 */
public class SplitState {
    private @SplitScreenState int mState = NOT_IN_SPLIT;

    /** Updates the current state of split screen on this device. */
    public void set(@SplitScreenState int newState) {
        mState = newState;
    }

    /** Reports the current state of split screen on this device. */
    public @SplitScreenState int get() {
        return mState;
    }

    /** Sets NOT_IN_SPLIT when user exits split. */
    public void exit() {
        set(NOT_IN_SPLIT);
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.split.SplitState;
import com.android.wm.shell.dagger.pip.TvPipModule;
import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.shared.TransactionPool;
@@ -89,6 +90,7 @@ public class TvWMShellModule {
            Optional<RecentTasksController> recentTasks,
            LaunchAdjacentController launchAdjacentController,
            MultiInstanceHelper multiInstanceHelper,
            SplitState splitState,
            @ShellMainThread ShellExecutor mainExecutor,
            Handler mainHandler,
            SystemWindows systemWindows) {
@@ -96,6 +98,6 @@ public class TvWMShellModule {
                shellTaskOrganizer, syncQueue, rootTDAOrganizer, displayController,
                displayImeController, displayInsetsController, transitions, transactionPool,
                iconProvider, recentTasks, launchAdjacentController, multiInstanceHelper,
                mainExecutor, mainHandler, systemWindows);
                splitState, mainExecutor, mainHandler, systemWindows);
    }
}
+7 −0
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ import com.android.wm.shell.common.pip.PipPerfHintController;
import com.android.wm.shell.common.pip.PipSnapAlgorithm;
import com.android.wm.shell.common.pip.PipUiEventLogger;
import com.android.wm.shell.common.pip.SizeSpecSource;
import com.android.wm.shell.common.split.SplitState;
import com.android.wm.shell.compatui.CompatUIConfiguration;
import com.android.wm.shell.compatui.CompatUIController;
import com.android.wm.shell.compatui.CompatUIShellCommandHandler;
@@ -867,6 +868,12 @@ public abstract class WMShellBaseModule {
        return Optional.empty();
    }

    @WMSingleton
    @Provides
    static SplitState provideSplitState() {
        return new SplitState();
    }

    //
    // Starting window
    //
Loading