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

Commit c28dfa68 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Run CD transitions on separate track than recents transitions" into main

parents eb04555b 4c22e225
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -158,6 +158,8 @@ public enum DesktopExperienceFlags {
            Flags.FLAG_ENABLE_NON_DEFAULT_DISPLAY_SPLIT),
    ENABLE_NO_WINDOW_DECORATION_FOR_DESKS(Flags::enableNoWindowDecorationForDesks, true,
        Flags.FLAG_ENABLE_NO_WINDOW_DECORATION_FOR_DESKS),
    ENABLE_PARALLEL_CD_TRANSITIONS_DURING_RECENTS(Flags::parallelCdTransitionsDuringRecents, false,
            Flags.FLAG_PARALLEL_CD_TRANSITIONS_DURING_RECENTS),
    ENABLE_PERSISTING_DISPLAY_SIZE_FOR_CONNECTED_DISPLAYS(
            Flags::enablePersistingDisplaySizeForConnectedDisplays, true,
            Flags.FLAG_ENABLE_PERSISTING_DISPLAY_SIZE_FOR_CONNECTED_DISPLAYS),
+10 −0
Original line number Diff line number Diff line
@@ -684,6 +684,16 @@ flag {
    bug: "362720309"
}

flag {
    name: "parallel_cd_transitions_during_recents"
    namespace: "lse_desktop_experience"
    description: "Runs CD transitions in a separate track when the recents transition is running"
    bug: "416499938"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "nested_tasks_with_independent_bounds_bugfix"
    namespace: "lse_desktop_experience"
+12 −0
Original line number Diff line number Diff line
@@ -2622,6 +2622,8 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
        sb.append(" id=" + mSyncId);
        sb.append(" type=" + transitTypeToString(mType));
        sb.append(" flags=0x" + Integer.toHexString(mFlags));
        sb.append(" parallelCollectType=" + parallelCollectTypeToString(mParallelCollectType));
        sb.append(" recentsDisplayId=" + mRecentsDisplayId);
        if (mOverrideOptions != null) {
            sb.append(" overrideAnimOptions=" + mOverrideOptions);
        }
@@ -3925,6 +3927,16 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
        }
    }

    @NonNull
    private static String parallelCollectTypeToString(@ParallelType int parallelCollectType) {
        return switch (parallelCollectType) {
            case PARALLEL_TYPE_NONE -> "NONE";
            case PARALLEL_TYPE_MUTUAL -> "MUTUAL";
            case PARALLEL_TYPE_RECENTS -> "RECENTS";
            default -> "UNKNOWN(" + parallelCollectType + ")";
        };
    }

    /**
     * Represents a condition that must be met before an associated transition can be considered
     * ready.
+22 −6
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_DISPLAY_LEVEL_TRANSITION;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.window.DesktopExperienceFlags.ENABLE_PARALLEL_CD_TRANSITIONS_DURING_RECENTS;

import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY;

@@ -1236,7 +1237,7 @@ class TransitionController {
     * `collecting` transition. It may still ultimately block in sync-engine or become dependent
     * in {@link #getIsIndependent} later.
     */
    boolean getCanBeIndependent(Transition collecting, @Nullable Transition queued) {
    static boolean getCanBeIndependent(Transition collecting, @Nullable Transition queued) {
        // For tests
        if (queued != null && queued.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL
                && collecting.mParallelCollectType == Transition.PARALLEL_TYPE_MUTUAL) {
@@ -1248,12 +1249,19 @@ class TransitionController {
                // Must serialize with itself.
                return false;
            }
            // allow this if `collecting` only has activities
            for (int i = 0; i < collecting.mParticipants.size(); ++i) {
                final WindowContainer wc = collecting.mParticipants.valueAt(i);
                final boolean isOnDifferentDisplay = !queued.isOnDisplay(wc.mDisplayContent);
                if (isOnDifferentDisplay
                        && ENABLE_PARALLEL_CD_TRANSITIONS_DURING_RECENTS.isTrue()) {
                    // Running in a different display, could be independent.
                    continue;
                }
                final ActivityRecord ar = wc.asActivityRecord();
                if (ar == null && wc.asWindowState() == null && wc.asWindowToken() == null) {
                    // Is task or above, so can't be independent
                final boolean isTaskOrAbove = ar == null && wc.asWindowState() == null
                        && wc.asWindowToken() == null;
                if (isTaskOrAbove) {
                    // Is task or above, so can't be independent.
                    return false;
                }
                if (ar != null && ar.isActivityTypeHomeOrRecents()) {
@@ -1306,9 +1314,17 @@ class TransitionController {
        // actually animating.
        for (int i = 0; i < other.mTargets.size(); ++i) {
            final WindowContainer wc = other.mTargets.get(i).mContainer;
            final boolean isOnDifferentDisplay = !recents.isOnDisplay(wc.mDisplayContent);
            if (isOnDifferentDisplay
                    && ENABLE_PARALLEL_CD_TRANSITIONS_DURING_RECENTS.isTrue()) {
                // Running in a different display, could be independent.
                continue;
            }
            final ActivityRecord ar = wc.asActivityRecord();
            if (ar == null && wc.asWindowState() == null && wc.asWindowToken() == null) {
                // Is task or above, so for now don't let them be independent.
            final boolean isTaskOrAbove = ar == null && wc.asWindowState() == null
                    && wc.asWindowToken() == null;
            if (isTaskOrAbove) {
                // Is task or above, so for now don't let them be independent
                return false;
            }
            if (ar != null && recents.isTransientLaunch(ar)) {
+125 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.server.wm;

import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OPEN;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.Transition.PARALLEL_TYPE_RECENTS;
import static com.android.server.wm.TransitionController.getCanBeIndependent;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;

import android.annotation.NonNull;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.view.WindowManager.TransitionType;

import androidx.test.filters.SmallTest;

import com.android.window.flags.Flags;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
 * Tests for {@link TransitionController}.
 *
 * Build/Install/Run:
 * atest WmTests:TransitionControllerTest
 */
@SmallTest
@Presubmit
@RunWith(WindowTestRunner.class)
public class TransitionControllerTest extends WindowTestsBase {

    private TransitionController mController;

    @Before
    public void setUp() {
        mController = new TransitionController(mAtm);
        mController.setSyncEngine(createTestBLASTSyncEngine());
    }

    @Test
    public void testGetCanBeIndependent_recentsParallelQueued_collectingTaskInSameDisplay_false() {
        final Task task = new ActivityBuilder(mAtm).setCreateTask(true).build().getTask();
        task.mDisplayContent = mDefaultDisplay;
        final Transition collecting = createTestTransition(TRANSIT_CLOSE);
        collecting.mParticipants.add(task);
        final Transition queued = createRecentsParallelTransition(mDefaultDisplay);

        final boolean canBeIndependent = getCanBeIndependent(collecting, queued);

        assertFalse(canBeIndependent);
    }

    @Test
    @DisableFlags(Flags.FLAG_PARALLEL_CD_TRANSITIONS_DURING_RECENTS)
    public void testGetCanBeIndependent_recentsParallelQueued_collectingTaskInOtherDisplay_false() {
        final Task task = new ActivityBuilder(mAtm).setCreateTask(true).build().getTask();
        task.mDisplayContent = mock(DisplayContent.class);
        final Transition collecting = createTestTransition(TRANSIT_CLOSE);
        collecting.mParticipants.add(task);
        final Transition queued = createRecentsParallelTransition(mDefaultDisplay);

        final boolean canBeIndependent = getCanBeIndependent(collecting, queued);

        assertFalse(canBeIndependent);
    }

    @Test
    @EnableFlags(Flags.FLAG_PARALLEL_CD_TRANSITIONS_DURING_RECENTS)
    public void testGetCanBeIndependent_recentsParallelQueued_collectingTaskInOtherDisplay_true() {
        final Transition collecting = createTestTransition(TRANSIT_CLOSE);
        final Task task = new ActivityBuilder(mAtm).setCreateTask(true).build().getTask();
        task.mDisplayContent = mock(DisplayContent.class);
        collecting.mParticipants.add(task);
        final Transition queued = createRecentsParallelTransition(mDefaultDisplay);

        final boolean canBeIndependent = getCanBeIndependent(collecting, queued);

        assertTrue(canBeIndependent);
    }

    private Transition createTestTransition(@TransitionType int type) {
        final Transition transition = new Transition(type, 0 /* flags */, mController,
                mController.mSyncEngine);
        spyOn(transition.mLogger);
        doNothing().when(transition.mLogger).logOnSendAsync(any());
        return transition;
    }

    private Transition createRecentsParallelTransition(@NonNull DisplayContent display) {
        final Transition transition = createTestTransition(TRANSIT_OPEN);
        transition.mParallelCollectType = PARALLEL_TYPE_RECENTS;
        transition.startCollecting(0 /* timeoutMs */);
        final ActivityRecord recent = new ActivityBuilder(mAtm)
                .setCreateTask(true)
                .setVisible(true)
                .build();
        recent.mDisplayContent = display;
        transition.collect(recent);
        return transition;
    }
}