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

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

Modify desktop windowing exemption logic and criteria

Modify modal exemption logic for desktop windowing to only check for
translucent activities and not floating activities as apps in desktop
windowing are freeform and thus meet the floating criteria.

Unify modal and systemUi activity exemption under one condition for
all ineligible activities to reduce individual checks required to
exempt current activities and any that may be needed in the future.

Flag: com.android.window.flags.enable_desktop_windowing_modals_policy
Fixes: 286929122
Fixes: 347739178
Bug: 347289970
Test: atest WMShellUnitTests:DesktopModeWindowDecorViewModelTests
Test: atest WMShellUnitTests:DesktopTasksControllerTest
Test: atest WMShellUnitTests:AppCompatUtilsTest

Change-Id: I29a415f2922b5eafd7008d87a984e495d1ca7ef0
parent 1b459ac9
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -296,6 +296,12 @@ public class TaskInfo {
     */
    public boolean isTopActivityTransparent;

    /**
     * Whether the top activity has specified style floating.
     * @hide
     */
    public boolean isTopActivityStyleFloating;

    /**
     * Encapsulate specific App Compat information.
     * @hide
@@ -429,6 +435,7 @@ public class TaskInfo {
                && parentTaskId == that.parentTaskId
                && Objects.equals(topActivity, that.topActivity)
                && isTopActivityTransparent == that.isTopActivityTransparent
                && isTopActivityStyleFloating == that.isTopActivityStyleFloating
                && appCompatTaskInfo.equalsForTaskOrganizer(that.appCompatTaskInfo);
    }

@@ -498,6 +505,7 @@ public class TaskInfo {
        mTopActivityLocusId = source.readTypedObject(LocusId.CREATOR);
        displayAreaFeatureId = source.readInt();
        isTopActivityTransparent = source.readBoolean();
        isTopActivityStyleFloating = source.readBoolean();
        appCompatTaskInfo = source.readTypedObject(AppCompatTaskInfo.CREATOR);
    }

@@ -545,6 +553,7 @@ public class TaskInfo {
        dest.writeTypedObject(mTopActivityLocusId, flags);
        dest.writeInt(displayAreaFeatureId);
        dest.writeBoolean(isTopActivityTransparent);
        dest.writeBoolean(isTopActivityStyleFloating);
        dest.writeTypedObject(appCompatTaskInfo, flags);
    }

@@ -582,6 +591,7 @@ public class TaskInfo {
                + " locusId=" + mTopActivityLocusId
                + " displayAreaFeatureId=" + displayAreaFeatureId
                + " isTopActivityTransparent=" + isTopActivityTransparent
                + " isTopActivityStyleFloating=" + isTopActivityStyleFloating
                + " appCompatTaskInfo=" + appCompatTaskInfo
                + "}";
    }
+12 −2
Original line number Diff line number Diff line
@@ -19,6 +19,16 @@
package com.android.wm.shell.compatui

import android.app.TaskInfo
fun isSingleTopActivityTranslucent(task: TaskInfo) =
    task.isTopActivityTransparent && task.numActivities == 1
import android.content.Context
import com.android.internal.R

// TODO(b/347289970): Consider replacing with API
fun isTopActivityExemptFromDesktopWindowing(context: Context, task: TaskInfo) =
    isSystemUiTask(context, task) || (task.isTopActivityTransparent && task.numActivities == 1
            && !task.isTopActivityStyleFloating)

private fun isSystemUiTask(context: Context, task: TaskInfo): Boolean {
    val sysUiPackageName: String =
        context.resources.getString(R.string.config_systemUi)
    return task.baseActivity?.packageName == sysUiPackageName
}
+9 −25
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource
import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT
import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT
import com.android.wm.shell.compatui.isSingleTopActivityTranslucent
import com.android.wm.shell.compatui.isTopActivityExemptFromDesktopWindowing
import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksListener
import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler.DragToDesktopStateListener
import com.android.wm.shell.draganddrop.DragAndDropController
@@ -158,8 +158,6 @@ class DesktopTasksController(
                visualIndicator = null
            }
        }
    private val sysUIPackageName = context.resources.getString(
        com.android.internal.R.string.config_systemUi)

    private val transitionAreaHeight
        get() =
@@ -219,11 +217,6 @@ class DesktopTasksController(
        return visualIndicator
    }

    // TODO(b/347289970): Consider replacing with API
    private fun isSystemUIApplication(taskInfo: RunningTaskInfo): Boolean {
        return taskInfo.baseActivity?.packageName == sysUIPackageName
    }

    fun setOnTaskResizeAnimationListener(listener: OnTaskResizeAnimationListener) {
        toggleResizeDesktopTaskTransitionHandler.setOnTaskResizeAnimationListener(listener)
        enterDesktopTaskTransitionHandler.setOnTaskResizeAnimationListener(listener)
@@ -351,19 +344,12 @@ class DesktopTasksController(
        wct: WindowContainerTransaction = WindowContainerTransaction(),
        transitionSource: DesktopModeTransitionSource,
    ) {
        if (Flags.enableDesktopWindowingModalsPolicy() && isSingleTopActivityTranslucent(task)) {
            KtProtoLog.w(
                WM_SHELL_DESKTOP_MODE,
                "DesktopTasksController: Cannot enter desktop, " +
                    "translucent top activity found. This is likely a modal dialog."
            )
            return
        }
        if (isSystemUIApplication(task)) {
        if (Flags.enableDesktopWindowingModalsPolicy()
            && isTopActivityExemptFromDesktopWindowing(context, task)) {
            KtProtoLog.w(
                WM_SHELL_DESKTOP_MODE,
                "DesktopTasksController: Cannot enter desktop, " +
                        "systemUI top activity found."
                        "ineligible top activity found."
            )
            return
        }
@@ -942,10 +928,8 @@ class DesktopTasksController(
                when {
                    // Check if the closing task needs to be handled
                    TransitionUtil.isClosingType(request.type) -> handleTaskClosing(task)
                    // Check if the task has a top transparent activity
                    shouldLaunchAsModal(task) -> handleIncompatibleTaskLaunch(task)
                    // Check if the task has a top systemUI activity
                    isSystemUIApplication(task) -> handleIncompatibleTaskLaunch(task)
                    // Check if the top task shouldn't be allowed to enter desktop mode
                    isIncompatibleTask(task) -> handleIncompatibleTaskLaunch(task)
                    // Check if fullscreen task should be updated
                    task.isFullscreen -> handleFullscreenTaskLaunch(task, transition)
                    // Check if freeform task should be updated
@@ -979,9 +963,9 @@ class DesktopTasksController(
            .forEach { finishTransaction.setCornerRadius(it.leash, cornerRadius) }
    }

    // TODO(b/347289970): Consider replacing with API
    private fun shouldLaunchAsModal(task: TaskInfo) =
        Flags.enableDesktopWindowingModalsPolicy() && isSingleTopActivityTranslucent(task)
    private fun isIncompatibleTask(task: TaskInfo) =
        Flags.enableDesktopWindowingModalsPolicy()
                && isTopActivityExemptFromDesktopWindowing(context, task)

    private fun shouldHandleTaskClosing(request: TransitionRequestInfo): Boolean {
        return Flags.enableDesktopWindowingWallpaperActivity() &&
+2 −15
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@ import static android.view.WindowInsets.Type.statusBars;

import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.compatui.AppCompatUtils.isSingleTopActivityTranslucent;
import static com.android.wm.shell.compatui.AppCompatUtils.isTopActivityExemptFromDesktopWindowing;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE;
import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
@@ -105,7 +105,6 @@ import com.android.wm.shell.windowdecor.extension.TaskInfoKt;
import com.android.wm.shell.windowdecor.viewholder.AppHeaderViewHolder;

import java.io.PrintWriter;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;

@@ -1029,12 +1028,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                && taskInfo.isFocused) {
            return false;
        }
        // TODO(b/347289970): Consider replacing with API
        if (Flags.enableDesktopWindowingModalsPolicy()
                && isSingleTopActivityTranslucent(taskInfo)) {
            return false;
        }
        if (isSystemUIApplication(taskInfo)) {
                && isTopActivityExemptFromDesktopWindowing(mContext, taskInfo)) {
            return false;
        }
        return DesktopModeStatus.canEnterDesktopMode(mContext)
@@ -1113,14 +1108,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
                && mSplitScreenController.isTaskInSplitScreen(taskId);
    }

    // TODO(b/347289970): Consider replacing with API
    private boolean isSystemUIApplication(RunningTaskInfo taskInfo) {
        if (taskInfo.baseActivity != null) {
            return (Objects.equals(taskInfo.baseActivity.getPackageName(), mSysUIPackageName));
        }
        return false;
    }

    private void dump(PrintWriter pw, String prefix) {
        final String innerPrefix = prefix + "  ";
        pw.println(prefix + "DesktopModeWindowDecorViewModel");
+37 −6
Original line number Diff line number Diff line
@@ -16,8 +16,10 @@

package com.android.wm.shell.compatui

import android.content.ComponentName
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.internal.R
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask
import org.junit.Assert.assertFalse
@@ -34,26 +36,55 @@ import org.junit.runner.RunWith
@RunWith(AndroidTestingRunner::class)
@SmallTest
class AppCompatUtilsTest : ShellTestCase() {

    @Test
    fun testIsSingleTopActivityTranslucent() {
        assertTrue(isSingleTopActivityTranslucent(
    fun testIsTopActivityExemptFromDesktopWindowing_topActivityTransparent() {
        assertTrue(isTopActivityExemptFromDesktopWindowing(mContext,
            createFreeformTask(/* displayId */ 0)
                    .apply {
                        isTopActivityTransparent = true
                        numActivities = 1
                    }))
        assertFalse(isSingleTopActivityTranslucent(
        assertFalse(isTopActivityExemptFromDesktopWindowing(mContext,
            createFreeformTask(/* displayId */ 0)
                    .apply {
                        isTopActivityTransparent = true
                        numActivities = 0
                    }))
        assertFalse(isSingleTopActivityTranslucent(
    }

    @Test
    fun testIsTopActivityExemptFromDesktopWindowing_singleTopActivity() {
        assertTrue(isTopActivityExemptFromDesktopWindowing(mContext,
            createFreeformTask(/* displayId */ 0)
                    .apply {
                        isTopActivityTransparent = true
                        numActivities = 1
                    }))
        assertFalse(isTopActivityExemptFromDesktopWindowing(mContext,
            createFreeformTask(/* displayId */ 0)
                    .apply {
                        isTopActivityTransparent = false
                        numActivities = 1
                    }))
    }

    @Test
    fun testIsTopActivityExemptFromDesktopWindowing__topActivityStyleFloating() {
        assertFalse(isTopActivityExemptFromDesktopWindowing(mContext,
            createFreeformTask(/* displayId */ 0)
                    .apply {
                        isTopActivityStyleFloating = true
                    }))
    }

    @Test
    fun testIsTopActivityExemptFromDesktopWindowing_systemUiTask() {
        val systemUIPackageName = context.resources.getString(R.string.config_systemUi)
        val baseComponent = ComponentName(systemUIPackageName, /* class */ "")
        assertTrue(isTopActivityExemptFromDesktopWindowing(mContext,
            createFreeformTask(/* displayId */ 0)
                    .apply {
                        baseActivity = baseComponent
                    }))
    }
}
Loading