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

Commit 1cefb1b7 authored by Winson Chung's avatar Winson Chung Committed by Automerger Merge Worker
Browse files

Merge "Add split exit reasons" into sc-v2-dev am: a307ec79 am: 5f4395c5

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16196490

Change-Id: Ibf069086631aff2797859f57b4e03487acef79c9
parents eb7f4c07 5f4395c5
Loading
Loading
Loading
Loading
+56 −4
Original line number Original line Diff line number Diff line
@@ -48,11 +48,11 @@ import android.window.RemoteTransition;
import android.window.WindowContainerTransaction;
import android.window.WindowContainerTransaction;


import androidx.annotation.BinderThread;
import androidx.annotation.BinderThread;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Nullable;


import com.android.internal.logging.InstanceId;
import com.android.internal.logging.InstanceId;
import com.android.internal.util.FrameworkStatsLog;
import com.android.launcher3.icons.IconProvider;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -70,6 +70,8 @@ import com.android.wm.shell.transition.LegacyTransitions;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.transition.Transitions;


import java.io.PrintWriter;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.Arrays;
import java.util.Optional;
import java.util.Optional;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;
@@ -87,6 +89,29 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
        RemoteCallable<SplitScreenController> {
        RemoteCallable<SplitScreenController> {
    private static final String TAG = SplitScreenController.class.getSimpleName();
    private static final String TAG = SplitScreenController.class.getSimpleName();


    static final int EXIT_REASON_UNKNOWN = 0;
    static final int EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW = 1;
    static final int EXIT_REASON_APP_FINISHED = 2;
    static final int EXIT_REASON_DEVICE_FOLDED = 3;
    static final int EXIT_REASON_DRAG_DIVIDER = 4;
    static final int EXIT_REASON_RETURN_HOME = 5;
    static final int EXIT_REASON_ROOT_TASK_VANISHED = 6;
    static final int EXIT_REASON_SCREEN_LOCKED = 7;
    static final int EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP = 8;
    @IntDef(value = {
            EXIT_REASON_UNKNOWN,
            EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW,
            EXIT_REASON_APP_FINISHED,
            EXIT_REASON_DEVICE_FOLDED,
            EXIT_REASON_DRAG_DIVIDER,
            EXIT_REASON_RETURN_HOME,
            EXIT_REASON_ROOT_TASK_VANISHED,
            EXIT_REASON_SCREEN_LOCKED,
            EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP,
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface ExitReason{}

    private final ShellTaskOrganizer mTaskOrganizer;
    private final ShellTaskOrganizer mTaskOrganizer;
    private final SyncTransactionQueue mSyncQueue;
    private final SyncTransactionQueue mSyncQueue;
    private final Context mContext;
    private final Context mContext;
@@ -201,7 +226,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
                leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
                leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
    }
    }


    public void exitSplitScreen(int toTopTaskId, int exitReason) {
    public void exitSplitScreen(int toTopTaskId, @ExitReason int exitReason) {
        mStageCoordinator.exitSplitScreen(toTopTaskId, exitReason);
        mStageCoordinator.exitSplitScreen(toTopTaskId, exitReason);
    }
    }


@@ -348,6 +373,34 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
        mStageCoordinator.logOnDroppedToSplit(position, dragSessionId);
        mStageCoordinator.logOnDroppedToSplit(position, dragSessionId);
    }
    }


    /**
     * Return the {@param exitReason} as a string.
     */
    public static String exitReasonToString(int exitReason) {
        switch (exitReason) {
            case EXIT_REASON_UNKNOWN:
                return "UNKNOWN_EXIT";
            case EXIT_REASON_DRAG_DIVIDER:
                return "DRAG_DIVIDER";
            case EXIT_REASON_RETURN_HOME:
                return "RETURN_HOME";
            case EXIT_REASON_SCREEN_LOCKED:
                return "SCREEN_LOCKED";
            case EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP:
                return "SCREEN_LOCKED_SHOW_ON_TOP";
            case EXIT_REASON_DEVICE_FOLDED:
                return "DEVICE_FOLDED";
            case EXIT_REASON_ROOT_TASK_VANISHED:
                return "ROOT_TASK_VANISHED";
            case EXIT_REASON_APP_FINISHED:
                return "APP_FINISHED";
            case EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW:
                return "APP_DOES_NOT_SUPPORT_MULTIWINDOW";
            default:
                return "unknown reason, reason int = " + exitReason;
        }
    }

    public void dump(@NonNull PrintWriter pw, String prefix) {
    public void dump(@NonNull PrintWriter pw, String prefix) {
        pw.println(prefix + TAG);
        pw.println(prefix + TAG);
        if (mStageCoordinator != null) {
        if (mStageCoordinator != null) {
@@ -497,8 +550,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
        public void exitSplitScreen(int toTopTaskId) {
        public void exitSplitScreen(int toTopTaskId) {
            executeRemoteCallWithTaskPermission(mController, "exitSplitScreen",
            executeRemoteCallWithTaskPermission(mController, "exitSplitScreen",
                    (controller) -> {
                    (controller) -> {
                        controller.exitSplitScreen(toTopTaskId,
                        controller.exitSplitScreen(toTopTaskId, EXIT_REASON_UNKNOWN);
                                FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__UNKNOWN_EXIT);
                    });
                    });
        }
        }


+53 −2
Original line number Original line Diff line number Diff line
@@ -17,13 +17,34 @@
package com.android.wm.shell.splitscreen;
package com.android.wm.shell.splitscreen;


import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__OVERVIEW;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__OVERVIEW;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_DOES_NOT_SUPPORT_MULTIWINDOW;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DRAG_DIVIDER;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__ROOT_TASK_VANISHED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__UNKNOWN_EXIT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_UNDEFINED;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_FINISHED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DEVICE_FOLDED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_ROOT_TASK_VANISHED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_SCREEN_LOCKED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_UNKNOWN;

import android.util.Slog;


import com.android.internal.logging.InstanceId;
import com.android.internal.logging.InstanceId;
import com.android.internal.logging.InstanceIdSequence;
import com.android.internal.logging.InstanceIdSequence;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.FrameworkStatsLog;
import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
import com.android.wm.shell.splitscreen.SplitScreenController.ExitReason;


/**
/**
 * Helper class that to log Drag & Drop UIEvents for a single session, see also go/uievent
 * Helper class that to log Drag & Drop UIEvents for a single session, see also go/uievent
@@ -95,11 +116,41 @@ public class SplitscreenEventLogger {
                mLoggerSessionId.getId());
                mLoggerSessionId.getId());
    }
    }


    /**
     * Returns the framework logging constant given a splitscreen exit reason.
     */
    private int getLoggerExitReason(@ExitReason int exitReason) {
        switch (exitReason) {
            case EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW:
                return SPLITSCREEN_UICHANGED__EXIT_REASON__APP_DOES_NOT_SUPPORT_MULTIWINDOW;
            case EXIT_REASON_APP_FINISHED:
                return SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED;
            case EXIT_REASON_DEVICE_FOLDED:
                return SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED;
            case EXIT_REASON_DRAG_DIVIDER:
                return SPLITSCREEN_UICHANGED__EXIT_REASON__DRAG_DIVIDER;
            case EXIT_REASON_RETURN_HOME:
                return SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME;
            case EXIT_REASON_ROOT_TASK_VANISHED:
                return SPLITSCREEN_UICHANGED__EXIT_REASON__ROOT_TASK_VANISHED;
            case EXIT_REASON_SCREEN_LOCKED:
                return SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED;
            case EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP:
                return SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP;
            case EXIT_REASON_UNKNOWN:
                // Fall through
            default:
                Slog.e("SplitscreenEventLogger", "Unknown exit reason: " + exitReason);
                return SPLITSCREEN_UICHANGED__EXIT_REASON__UNKNOWN_EXIT;
        }
    }

    /**
    /**
     * Logs when the user exits splitscreen.  Only one of the main or side stages should be
     * Logs when the user exits splitscreen.  Only one of the main or side stages should be
     * specified to indicate which position was focused as a part of exiting (both can be unset).
     * specified to indicate which position was focused as a part of exiting (both can be unset).
     */
     */
    public void logExit(int exitReason, @SplitPosition int mainStagePosition, int mainStageUid,
    public void logExit(@ExitReason int exitReason,
            @SplitPosition int mainStagePosition, int mainStageUid,
            @SplitPosition int sideStagePosition, int sideStageUid, boolean isLandscape) {
            @SplitPosition int sideStagePosition, int sideStageUid, boolean isLandscape) {
        if (mLoggerSessionId == null) {
        if (mLoggerSessionId == null) {
            // Ignore changes until we've started logging the session
            // Ignore changes until we've started logging the session
@@ -113,7 +164,7 @@ public class SplitscreenEventLogger {
        FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
        FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
                FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__EXIT,
                FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__EXIT,
                0 /* enterReason */,
                0 /* enterReason */,
                exitReason,
                getLoggerExitReason(exitReason),
                0f /* splitRatio */,
                0f /* splitRatio */,
                getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape),
                getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape),
                mainStageUid,
                mainStageUid,
+23 −48
Original line number Original line Diff line number Diff line
@@ -25,15 +25,6 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.transitTypeToString;
import static android.view.WindowManager.transitTypeToString;
import static android.view.WindowManagerPolicyConstants.SPLIT_DIVIDER_LAYER;
import static android.view.WindowManagerPolicyConstants.SPLIT_DIVIDER_LAYER;


import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_DOES_NOT_SUPPORT_MULTIWINDOW;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DRAG_DIVIDER;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__ROOT_TASK_VANISHED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__UNKNOWN_EXIT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_UNDEFINED;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_UNDEFINED;
@@ -41,6 +32,13 @@ import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreen.stageTypeToString;
import static com.android.wm.shell.splitscreen.SplitScreen.stageTypeToString;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_APP_FINISHED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DEVICE_FOLDED;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_DRAG_DIVIDER;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP;
import static com.android.wm.shell.splitscreen.SplitScreenController.exitReasonToString;
import static com.android.wm.shell.splitscreen.SplitScreenTransitions.FLAG_IS_DIVIDER_BAR;
import static com.android.wm.shell.splitscreen.SplitScreenTransitions.FLAG_IS_DIVIDER_BAR;
import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_DISMISS_SNAP;
import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_DISMISS_SNAP;
@@ -94,6 +92,7 @@ import com.android.wm.shell.common.split.SplitLayout;
import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
import com.android.wm.shell.common.split.SplitWindowManager;
import com.android.wm.shell.common.split.SplitWindowManager;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.splitscreen.SplitScreenController.ExitReason;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.transition.Transitions;


import java.io.PrintWriter;
import java.io.PrintWriter;
@@ -527,7 +526,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        if (!showing && mMainStage.isActive()
        if (!showing && mMainStage.isActive()
                && mTopStageAfterFoldDismiss != STAGE_TYPE_UNDEFINED) {
                && mTopStageAfterFoldDismiss != STAGE_TYPE_UNDEFINED) {
            exitSplitScreen(mTopStageAfterFoldDismiss == STAGE_TYPE_MAIN ? mMainStage : mSideStage,
            exitSplitScreen(mTopStageAfterFoldDismiss == STAGE_TYPE_MAIN ? mMainStage : mSideStage,
                    SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED);
                    EXIT_REASON_DEVICE_FOLDED);
        }
        }
    }
    }


@@ -535,7 +534,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        mExitSplitScreenOnHide = exitSplitScreenOnHide;
        mExitSplitScreenOnHide = exitSplitScreenOnHide;
    }
    }


    void exitSplitScreen(int toTopTaskId, int exitReason) {
    void exitSplitScreen(int toTopTaskId, @ExitReason int exitReason) {
        if (!mMainStage.isActive()) return;
        if (!mMainStage.isActive()) return;


        StageTaskListener childrenToTop = null;
        StageTaskListener childrenToTop = null;
@@ -552,7 +551,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        applyExitSplitScreen(childrenToTop, wct, exitReason);
        applyExitSplitScreen(childrenToTop, wct, exitReason);
    }
    }


    private void exitSplitScreen(StageTaskListener childrenToTop, int exitReason) {
    private void exitSplitScreen(StageTaskListener childrenToTop, @ExitReason int exitReason) {
        if (!mMainStage.isActive()) return;
        if (!mMainStage.isActive()) return;


        final WindowContainerTransaction wct = new WindowContainerTransaction();
        final WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -560,7 +559,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    }
    }


    private void applyExitSplitScreen(StageTaskListener childrenToTop,
    private void applyExitSplitScreen(StageTaskListener childrenToTop,
            WindowContainerTransaction wct, int exitReason) {
            WindowContainerTransaction wct, @ExitReason int exitReason) {
        mSideStage.removeAllTasks(wct, childrenToTop == mSideStage);
        mSideStage.removeAllTasks(wct, childrenToTop == mSideStage);
        mMainStage.deactivate(wct, childrenToTop == mMainStage);
        mMainStage.deactivate(wct, childrenToTop == mMainStage);
        mTaskOrganizer.applyTransaction(wct);
        mTaskOrganizer.applyTransaction(wct);
@@ -572,6 +571,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        mSplitLayout.resetDividerPosition();
        mSplitLayout.resetDividerPosition();
        mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
        mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
        Slog.i(TAG, "applyExitSplitScreen, reason = " + exitReasonToString(exitReason));
        Slog.i(TAG, "applyExitSplitScreen, reason = " + exitReasonToString(exitReason));
        // Log the exit
        if (childrenToTop != null) {
        if (childrenToTop != null) {
            logExitToStage(exitReason, childrenToTop == mMainStage);
            logExitToStage(exitReason, childrenToTop == mMainStage);
        } else {
        } else {
@@ -724,8 +724,9 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                    // display, like the cases keyguard showing or screen off.
                    // display, like the cases keyguard showing or screen off.
                    || (!mMainStage.mRootTaskInfo.isSleeping
                    || (!mMainStage.mRootTaskInfo.isSleeping
                    && !mSideStage.mRootTaskInfo.isSleeping)) {
                    && !mSideStage.mRootTaskInfo.isSleeping)) {
                exitSplitScreen(null /* childrenToTop */,
            // Don't dismiss staged split when both stages are not visible due to sleeping display,
                        SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME);
            // like the cases keyguard showing or screen off.
                exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RETURN_HOME);
            }
            }
        } else if (mKeyguardOccluded) {
        } else if (mKeyguardOccluded) {
            // At least one of the stages is visible while keyguard occluded. Dismiss split because
            // At least one of the stages is visible while keyguard occluded. Dismiss split because
@@ -733,7 +734,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            // task contains show-when-locked activity remains on top after split dismissed.
            // task contains show-when-locked activity remains on top after split dismissed.
            final StageTaskListener toTop =
            final StageTaskListener toTop =
                    mainStageVisible ? mMainStage : (sideStageVisible ? mSideStage : null);
                    mainStageVisible ? mMainStage : (sideStageVisible ? mSideStage : null);
            exitSplitScreen(toTop, SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP);
            exitSplitScreen(toTop, EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
        }
        }


        mSyncQueue.runInSync(t -> {
        mSyncQueue.runInSync(t -> {
@@ -770,10 +771,10 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        if (!hasChildren) {
        if (!hasChildren) {
            if (isSideStage && mMainStageListener.mVisible) {
            if (isSideStage && mMainStageListener.mVisible) {
                // Exit to main stage if side stage no longer has children.
                // Exit to main stage if side stage no longer has children.
                exitSplitScreen(mMainStage, SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED);
                exitSplitScreen(mMainStage, EXIT_REASON_APP_FINISHED);
            } else if (!isSideStage && mSideStageListener.mVisible) {
            } else if (!isSideStage && mSideStageListener.mVisible) {
                // Exit to side stage if main stage no longer has children.
                // Exit to side stage if main stage no longer has children.
                exitSplitScreen(mSideStage, SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED);
                exitSplitScreen(mSideStage, EXIT_REASON_APP_FINISHED);
            }
            }
        } else if (isSideStage) {
        } else if (isSideStage) {
            final WindowContainerTransaction wct = new WindowContainerTransaction();
            final WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -808,8 +809,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            onSnappedToDismissTransition(mainStageToTop);
            onSnappedToDismissTransition(mainStageToTop);
            return;
            return;
        }
        }
        exitSplitScreen(mainStageToTop ? mMainStage : mSideStage,
        exitSplitScreen(mainStageToTop ? mMainStage : mSideStage, EXIT_REASON_DRAG_DIVIDER);
                SPLITSCREEN_UICHANGED__EXIT_REASON__DRAG_DIVIDER);
    }
    }


    @Override
    @Override
@@ -1267,7 +1267,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    /**
    /**
     * Logs the exit of splitscreen.
     * Logs the exit of splitscreen.
     */
     */
    private void logExit(int exitReason) {
    private void logExit(@ExitReason int exitReason) {
        mLogger.logExit(exitReason,
        mLogger.logExit(exitReason,
                SPLIT_POSITION_UNDEFINED, 0 /* mainStageUid */,
                SPLIT_POSITION_UNDEFINED, 0 /* mainStageUid */,
                SPLIT_POSITION_UNDEFINED, 0 /* sideStageUid */,
                SPLIT_POSITION_UNDEFINED, 0 /* sideStageUid */,
@@ -1278,7 +1278,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
     * Logs the exit of splitscreen to a specific stage. This must be called before the exit is
     * Logs the exit of splitscreen to a specific stage. This must be called before the exit is
     * executed.
     * executed.
     */
     */
    private void logExitToStage(int exitReason, boolean toMainStage) {
    private void logExitToStage(@ExitReason int exitReason, boolean toMainStage) {
        mLogger.logExit(exitReason,
        mLogger.logExit(exitReason,
                toMainStage ? getMainStagePosition() : SPLIT_POSITION_UNDEFINED,
                toMainStage ? getMainStagePosition() : SPLIT_POSITION_UNDEFINED,
                toMainStage ? mMainStage.getTopChildTaskUid() : 0 /* mainStageUid */,
                toMainStage ? mMainStage.getTopChildTaskUid() : 0 /* mainStageUid */,
@@ -1287,31 +1287,6 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                mSplitLayout.isLandscape());
                mSplitLayout.isLandscape());
    }
    }


    private String exitReasonToString(int exitReason) {
        switch (exitReason) {
            case SPLITSCREEN_UICHANGED__EXIT_REASON__UNKNOWN_EXIT:
                return "UNKNOWN_EXIT";
            case SPLITSCREEN_UICHANGED__EXIT_REASON__DRAG_DIVIDER:
                return "DRAG_DIVIDER";
            case SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME:
                return "RETURN_HOME";
            case SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED:
                return "SCREEN_LOCKED";
            case SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP:
                return "SCREEN_LOCKED_SHOW_ON_TOP";
            case SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED:
                return "DEVICE_FOLDED";
            case SPLITSCREEN_UICHANGED__EXIT_REASON__ROOT_TASK_VANISHED:
                return "ROOT_TASK_VANISHED";
            case SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED:
                return "APP_FINISHED";
            case SPLITSCREEN_UICHANGED__EXIT_REASON__APP_DOES_NOT_SUPPORT_MULTIWINDOW:
                return "APP_DOES_NOT_SUPPORT_MULTIWINDOW";
            default:
                return "unknown reason, reason int = " + exitReason;
        }
    }

    class StageListenerImpl implements StageTaskListener.StageListenerCallbacks {
    class StageListenerImpl implements StageTaskListener.StageListenerCallbacks {
        boolean mHasRootTask = false;
        boolean mHasRootTask = false;
        boolean mVisible = false;
        boolean mVisible = false;
@@ -1352,7 +1327,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        public void onNoLongerSupportMultiWindow() {
        public void onNoLongerSupportMultiWindow() {
            if (mMainStage.isActive()) {
            if (mMainStage.isActive()) {
                StageCoordinator.this.exitSplitScreen(null /* childrenToTop */,
                StageCoordinator.this.exitSplitScreen(null /* childrenToTop */,
                        SPLITSCREEN_UICHANGED__EXIT_REASON__APP_DOES_NOT_SUPPORT_MULTIWINDOW);
                        EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
            }
            }
        }
        }


+4 −6
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME;


import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.eq;
@@ -162,8 +163,7 @@ public class StageCoordinatorTests extends ShellTestCase {
    @Test
    @Test
    public void testExitSplitScreen() {
    public void testExitSplitScreen() {
        when(mMainStage.isActive()).thenReturn(true);
        when(mMainStage.isActive()).thenReturn(true);
        mStageCoordinator.exitSplitScreen(INVALID_TASK_ID,
        mStageCoordinator.exitSplitScreen(INVALID_TASK_ID, EXIT_REASON_RETURN_HOME);
                SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME);
        verify(mSideStage).removeAllTasks(any(WindowContainerTransaction.class), eq(false));
        verify(mSideStage).removeAllTasks(any(WindowContainerTransaction.class), eq(false));
        verify(mMainStage).deactivate(any(WindowContainerTransaction.class), eq(false));
        verify(mMainStage).deactivate(any(WindowContainerTransaction.class), eq(false));
    }
    }
@@ -174,8 +174,7 @@ public class StageCoordinatorTests extends ShellTestCase {
        final int testTaskId = 12345;
        final int testTaskId = 12345;
        when(mMainStage.containsTask(eq(testTaskId))).thenReturn(true);
        when(mMainStage.containsTask(eq(testTaskId))).thenReturn(true);
        when(mSideStage.containsTask(eq(testTaskId))).thenReturn(false);
        when(mSideStage.containsTask(eq(testTaskId))).thenReturn(false);
        mStageCoordinator.exitSplitScreen(testTaskId,
        mStageCoordinator.exitSplitScreen(testTaskId, EXIT_REASON_RETURN_HOME);
                SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME);
        verify(mMainStage).reorderChild(eq(testTaskId), eq(true),
        verify(mMainStage).reorderChild(eq(testTaskId), eq(true),
                any(WindowContainerTransaction.class));
                any(WindowContainerTransaction.class));
        verify(mSideStage).removeAllTasks(any(WindowContainerTransaction.class), eq(false));
        verify(mSideStage).removeAllTasks(any(WindowContainerTransaction.class), eq(false));
@@ -188,8 +187,7 @@ public class StageCoordinatorTests extends ShellTestCase {
        final int testTaskId = 12345;
        final int testTaskId = 12345;
        when(mMainStage.containsTask(eq(testTaskId))).thenReturn(false);
        when(mMainStage.containsTask(eq(testTaskId))).thenReturn(false);
        when(mSideStage.containsTask(eq(testTaskId))).thenReturn(true);
        when(mSideStage.containsTask(eq(testTaskId))).thenReturn(true);
        mStageCoordinator.exitSplitScreen(testTaskId,
        mStageCoordinator.exitSplitScreen(testTaskId, EXIT_REASON_RETURN_HOME);
                SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME);
        verify(mSideStage).reorderChild(eq(testTaskId), eq(true),
        verify(mSideStage).reorderChild(eq(testTaskId), eq(true),
                any(WindowContainerTransaction.class));
                any(WindowContainerTransaction.class));
        verify(mSideStage).removeAllTasks(any(WindowContainerTransaction.class), eq(true));
        verify(mSideStage).removeAllTasks(any(WindowContainerTransaction.class), eq(true));