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

Commit 618c1e32 authored by Louis Chang's avatar Louis Chang
Browse files

Make most of the windowing modes compatible

When a bubble task, initially in multi-window mode, finishes its
activity and exits its bubble, the task becomes fullscreen
windowingMode (sets as undefined and inherits the fullscreen
windowingMode from its parent). Since the two windowingModes are
not compatible, multiple recent tasks are added if this process
is repeated.

Unless one of them is pinned and the other is not, all windowing
modes are compatible

Bug: 427336494
Test: RecentTasksTest
Flag: com.android.window.flags.fix_task_compatible_modes
Change-Id: Ia8cc8b6ebb73c3dfd4ab2f0d8b1e43bd848f3b2e
parent 2a285706
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -199,6 +199,17 @@ flag {
    is_fixed_read_only: true
}

flag {
    namespace: "windowing_sdk"
    name: "fix_task_compatible_modes"
    description: "Make most of the windowing modes compatible"
    bug: "427336494"
    is_fixed_read_only: true
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    namespace: "windowing_sdk"
    name: "support_gemini_on_multi_display"
+24 −22
Original line number Diff line number Diff line
@@ -2046,27 +2046,29 @@ class RecentTasks {
     * or the windowing mode with the task, so they can be undefined when restored.
     */
    private boolean hasCompatibleActivityTypeAndWindowingMode(Task t1, Task t2) {
        final int activityType = t1.getActivityType();
        final int windowingMode = t1.getWindowingMode();
        final boolean isUndefinedType = activityType == ACTIVITY_TYPE_UNDEFINED;
        final boolean isUndefinedMode = windowingMode == WINDOWING_MODE_UNDEFINED;
        final int otherActivityType = t2.getActivityType();
        final int otherWindowingMode = t2.getWindowingMode();
        final boolean isOtherUndefinedType = otherActivityType == ACTIVITY_TYPE_UNDEFINED;
        final boolean isOtherUndefinedMode = otherWindowingMode == WINDOWING_MODE_UNDEFINED;

        // An activity type and windowing mode is compatible if they are the exact same type/mode,
        // or if one of the type/modes is undefined. This is with the exception of
        // freeform/fullscreen where both modes are assumed to be compatible with each other.
        final boolean isCompatibleType = activityType == otherActivityType
                || isUndefinedType || isOtherUndefinedType;
        final boolean isCompatibleMode = windowingMode == otherWindowingMode
                || (windowingMode == WINDOWING_MODE_FREEFORM
                && otherWindowingMode == WINDOWING_MODE_FULLSCREEN)
                || (windowingMode == WINDOWING_MODE_FULLSCREEN
                && otherWindowingMode == WINDOWING_MODE_FREEFORM)
                || isUndefinedMode || isOtherUndefinedMode;

        return isCompatibleType && isCompatibleMode;
        final int activityType1 = t1.getActivityType();
        final int activityType2 = t2.getActivityType();
        final boolean isCompatibleType = activityType1 == activityType2
                || activityType1 == ACTIVITY_TYPE_UNDEFINED
                || activityType2 == ACTIVITY_TYPE_UNDEFINED;

        if (!isCompatibleType) return false;

        final int windowingMode1 = t1.getWindowingMode();
        final int windowingMode2 = t2.getWindowingMode();

        if (com.android.window.flags.Flags.fixTaskCompatibleModes()) {
            // Unless one of them is pinned and the other is not, all modes are compatible.
            return (windowingMode1 == windowingMode2) || (windowingMode1 != WINDOWING_MODE_PINNED
                    && windowingMode2 != WINDOWING_MODE_PINNED);
        } else {
            return windowingMode1 == windowingMode2
                    || windowingMode1 == WINDOWING_MODE_UNDEFINED
                    || windowingMode2 == WINDOWING_MODE_UNDEFINED
                    || (windowingMode1 == WINDOWING_MODE_FREEFORM
                    && windowingMode2 == WINDOWING_MODE_FULLSCREEN)
                    || (windowingMode1 == WINDOWING_MODE_FULLSCREEN
                    && windowingMode2 == WINDOWING_MODE_FREEFORM);
        }
    }
}
+13 −1
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ import android.os.Bundle;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserManager;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
import android.util.ArraySet;
@@ -81,6 +82,7 @@ import android.window.TaskSnapshot;
import androidx.test.filters.MediumTest;

import com.android.server.wm.RecentTasks.Callbacks;
import com.android.window.flags.Flags;

import org.junit.Before;
import org.junit.Rule;
@@ -429,11 +431,21 @@ public class RecentTasksTest extends WindowTestsBase {

    @Test
    public void testAddTaskCompatibleWindowingMode_withFreeformAndFullscreen_expectRemove() {
        verifyCompatibleWindowingModeWithFullscreen(WINDOWING_MODE_FREEFORM);
    }

    @Test
    @EnableFlags(Flags.FLAG_FIX_TASK_COMPATIBLE_MODES)
    public void testAddTaskCompatibleWindowingMode_withMultiWindowAndFullscreen_expectRemove() {
        verifyCompatibleWindowingModeWithFullscreen(WINDOWING_MODE_MULTI_WINDOW);
    }

    private void verifyCompatibleWindowingModeWithFullscreen(int windowingMode) {
        Task task1 = createTaskBuilder(".Task1")
                .setTaskId(1)
                .setFlags(FLAG_ACTIVITY_NEW_TASK)
                .build();
        doReturn(WINDOWING_MODE_FREEFORM).when(task1).getWindowingMode();
        doReturn(windowingMode).when(task1).getWindowingMode();
        mRecentTasks.add(task1);
        mCallbacksRecorder.clear();