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

Commit fed4c7c3 authored by Eghosa Ewansiha-Vlachavas's avatar Eghosa Ewansiha-Vlachavas
Browse files

[1/n] Disable DesktopModeLaunchParamsModifier if not entering desktop

`DesktopModeLaunchParamsModifier` previously always ran regardless of if
we were in/entering desktop. Although this did not cause any issue with
fullscreen tasks, it causes problems with PIP and Bubble tasks as they
all share the common variable `mLastNonFullscreenBounds`. Instead
`DesktopModeLaunchParamsModifer` should only modify the launch params if
we are in or entering desktop mode. We know we are in desktop mode if
there are freeform tasks present on the display and we know we are
entering desktop mode if the current tasks launch mode is or is to be
set to freeform.

Flag: com.android.window.flags.disable_desktop_launch_params_outside_desktop_bug_fix
Test: atest WmTests:DesktopModeLaunchParamsModifierTests
Fixes: 396108436

Change-Id: Iec0f308e86af68ea85fac4ffd3803403c2fa6a1a
parent ed7232ed
Loading
Loading
Loading
Loading
+70 −0
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@

package com.android.server.wm;

import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;

import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.DesktopModeHelper.canEnterDesktopMode;
@@ -23,10 +27,13 @@ import static com.android.server.wm.DesktopModeHelper.canEnterDesktopMode;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.WindowConfiguration;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.util.Slog;
import android.window.DesktopModeFlags;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
/**
 * The class that defines default launch params for tasks in desktop mode
@@ -74,6 +81,13 @@ class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
            appendLog("task null, skipping");
            return RESULT_SKIP;
        }

        if (DesktopModeFlags.DISABLE_DESKTOP_LAUNCH_PARAMS_OUTSIDE_DESKTOP_BUG_FIX.isTrue()
                && !isEnteringDesktopMode(task, options, currentParams)) {
            appendLog("not entering desktop mode, skipping");
            return RESULT_SKIP;
        }

        if (com.android.window.flags.Flags.fixLayoutExistingTask()
                && task.getCreatedByOrganizerTask() != null) {
            appendLog("has created-by-organizer-task, skipping");
@@ -122,6 +136,62 @@ class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
        return RESULT_CONTINUE;
    }

    /**
     * Returns true if a task is entering desktop mode, due to its windowing mode being freeform or
     * if there exists other freeform tasks on the display.
     */
    @VisibleForTesting
    boolean isEnteringDesktopMode(
            @NonNull Task task,
            @Nullable ActivityOptions options,
            @NonNull LaunchParamsController.LaunchParams currentParams) {
        //  As freeform tasks cannot exist outside of desktop mode, it is safe to assume if
        //  freeform tasks are visible we are in desktop mode and as a result any launching
        //  activity will also enter desktop mode. On this same relationship, we can also assume
        //  if there are not visible freeform tasks but a freeform activity is now launching, it
        //  will force the device into desktop mode.
        return (task.getDisplayContent().getTopMostVisibleFreeformActivity() != null
                    && checkSourceWindowModesCompatible(task, options, currentParams))
                || isRequestingFreeformWindowMode(task, options, currentParams);
    }

    private boolean isRequestingFreeformWindowMode(
            @NonNull Task task,
            @Nullable ActivityOptions options,
            @NonNull LaunchParamsController.LaunchParams currentParams) {
        return task.inFreeformWindowingMode()
                || (options != null && options.getLaunchWindowingMode() == WINDOWING_MODE_FREEFORM)
                || (currentParams.hasWindowingMode()
                && currentParams.mWindowingMode == WINDOWING_MODE_FREEFORM);
    }

    /**
     * Returns true is all possible source window modes are compatible with desktop mode.
     */
    private boolean checkSourceWindowModesCompatible(
            @NonNull Task task,
            @Nullable ActivityOptions options,
            @NonNull LaunchParamsController.LaunchParams currentParams) {
        return isCompatibleDesktopWindowingMode(task.getWindowingMode())
                && (options == null
                    || isCompatibleDesktopWindowingMode(options.getLaunchWindowingMode()))
                && isCompatibleDesktopWindowingMode(currentParams.mWindowingMode);
    }

    /**
     * Returns true is the requesting window mode is one that can lead to the activity entering
     * desktop.
     */
    private boolean isCompatibleDesktopWindowingMode(
            @WindowConfiguration.WindowingMode int windowingMode) {
        return switch (windowingMode) {
            case WINDOWING_MODE_UNDEFINED,
                 WINDOWING_MODE_FULLSCREEN,
                 WINDOWING_MODE_FREEFORM -> true;
            default -> false;
        };
    }

    private void initLogBuilder(Task task, ActivityRecord activity) {
        if (DEBUG) {
            mLogBuilder = new StringBuilder(
+5 −0
Original line number Diff line number Diff line
@@ -2007,6 +2007,11 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
        return getActivity(r -> !r.finishing, true /* traverseTopToBottom */);
    }

    ActivityRecord getTopMostVisibleFreeformActivity() {
        return getActivity(r -> r.isVisibleRequested() && r.inFreeformWindowingMode(),
                true /* traverseTopToBottom */);
    }

    ActivityRecord getTopActivity(boolean includeFinishing, boolean includeOverlays) {
        // Break down into 4 calls to avoid object creation due to capturing input params.
        if (includeFinishing) {
+79 −1
Original line number Diff line number Diff line
@@ -49,6 +49,8 @@ import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

import android.app.ActivityOptions;
import android.compat.testing.PlatformCompatChangeRule;
@@ -98,7 +100,8 @@ public class DesktopModeLaunchParamsModifierTests extends
        mResult = new LaunchParamsController.LaunchParams();
        mResult.reset();

        mTarget = new DesktopModeLaunchParamsModifier(mContext);
        mTarget = spy(new DesktopModeLaunchParamsModifier(mContext));
        doReturn(true).when(mTarget).isEnteringDesktopMode(any(), any(), any());
    }

    @Test
@@ -136,6 +139,81 @@ public class DesktopModeLaunchParamsModifierTests extends
        assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setTask(null).calculate());
    }

    @Test
    @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
            Flags.FLAG_DISABLE_DESKTOP_LAUNCH_PARAMS_OUTSIDE_DESKTOP_BUG_FIX})
    public void testReturnsSkipIfIsEnteringDesktopModeFalse() {
        setupDesktopModeLaunchParamsModifier();
        when(mTarget.isEnteringDesktopMode(any(), any(), any())).thenReturn(false);

        final Task task = new TaskBuilder(mSupervisor).build();

        assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setTask(task).calculate());
    }

    @Test
    @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
            Flags.FLAG_DISABLE_DESKTOP_LAUNCH_PARAMS_OUTSIDE_DESKTOP_BUG_FIX})
    public void testReturnsContinueIfVisibleFreeformTaskExists() {
        setupDesktopModeLaunchParamsModifier();
        when(mTarget.isEnteringDesktopMode(any(), any(), any())).thenCallRealMethod();

        final DisplayContent dc = spy(createNewDisplay());
        final Task existingFreeformTask = new TaskBuilder(mSupervisor).setCreateActivity(true)
                .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
        doReturn(existingFreeformTask.getRootActivity()).when(dc)
                .getTopMostVisibleFreeformActivity();
        final Task launchingTask = new TaskBuilder(mSupervisor).build();
        launchingTask.onDisplayChanged(dc);

        assertEquals(RESULT_CONTINUE,
                new CalculateRequestBuilder().setTask(launchingTask).calculate());
    }

    @Test
    @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
            Flags.FLAG_DISABLE_DESKTOP_LAUNCH_PARAMS_OUTSIDE_DESKTOP_BUG_FIX})
    public void testReturnsContinueIfTaskInFreeform() {
        setupDesktopModeLaunchParamsModifier();
        when(mTarget.isEnteringDesktopMode(any(), any(), any())).thenCallRealMethod();

        final Task task = new TaskBuilder(mSupervisor).setWindowingMode(WINDOWING_MODE_FREEFORM)
                .build();

        assertEquals(RESULT_CONTINUE,
                new CalculateRequestBuilder().setTask(task).calculate());
    }

    @Test
    @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
            Flags.FLAG_DISABLE_DESKTOP_LAUNCH_PARAMS_OUTSIDE_DESKTOP_BUG_FIX})
    public void testReturnsContinueIfFreeformRequestViaActivityOptions() {
        setupDesktopModeLaunchParamsModifier();
        when(mTarget.isEnteringDesktopMode(any(), any(), any())).thenCallRealMethod();

        final Task task = new TaskBuilder(mSupervisor).build();
        final ActivityOptions options = ActivityOptions.makeBasic();
        options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);

        assertEquals(RESULT_CONTINUE,
                new CalculateRequestBuilder().setTask(task).setOptions(options).calculate());
    }

    @Test
    @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
            Flags.FLAG_DISABLE_DESKTOP_LAUNCH_PARAMS_OUTSIDE_DESKTOP_BUG_FIX})
    public void testReturnsContinueIfFreeformRequestViaPreviousModifier() {
        setupDesktopModeLaunchParamsModifier();
        when(mTarget.isEnteringDesktopMode(any(), any(), any())).thenCallRealMethod();

        final Task task = new TaskBuilder(mSupervisor).build();
        final ActivityOptions options = ActivityOptions.makeBasic();
        options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);

        assertEquals(RESULT_CONTINUE,
                new CalculateRequestBuilder().setTask(task).setOptions(options).calculate());
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    public void testReturnsSkipIfNotBoundsPhase() {