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

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

Gate new desktop task menu button with device config check

Desktop windowing is enabled only when the desktop windowing flag is
enabled and the device is supported through setting a device config
flag. Add this device config check to the desktop task menu button so it
does not appear if the device is not compatible.

Flag: NONE
Fixes: 335178869
Test: atest -c NexusLauncherTests:com.android.quickstep.DesktopSystemShortcutTest
Change-Id: Ia2559c1ff57bb7921867e69a47d868c03eae57e7
parent 28e88696
Loading
Loading
Loading
Loading
+58 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.quickstep;

import android.content.Context;
import android.os.SystemProperties;

import com.android.internal.annotations.VisibleForTesting;
import com.android.window.flags.Flags;

// TODO(b/335401172): Explore unifying logic across core and shell
public class DesktopModeStatus {

    /**
     * Flag to indicate whether to restrict desktop mode to supported devices.
     */
    private static final boolean ENFORCE_DEVICE_RESTRICTIONS = SystemProperties.getBoolean(
            "persist.wm.debug.desktop_mode_enforce_device_restrictions", true);

    /**
     * Return {@code true} if desktop mode should be restricted to supported devices.
     */
    @VisibleForTesting
    public static boolean enforceDeviceRestrictions() {
        return ENFORCE_DEVICE_RESTRICTIONS;
    }

    /**
     * Return {@code true} if the current device supports desktop mode.
     */
    @VisibleForTesting
    public static boolean isDesktopModeSupported(Context context) {
        return context.getResources().getBoolean(
                com.android.internal.R.bool.config_isDesktopModeSupported);
    }

    /**
     * Return {@code true} if desktop mode can be entered on the current device.
     */
    public static boolean canEnterDesktopMode(Context context) {
        return Flags.enableDesktopWindowingMode()
                && (!enforceDeviceRestrictions() || isDesktopModeSupported(context));
    }
}
+2 −3
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import com.android.launcher3.popup.SystemShortcut
import com.android.quickstep.views.RecentsView
import com.android.quickstep.views.RecentsViewContainer
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
import com.android.window.flags.Flags

/** A menu item, "Desktop", that allows the user to bring the current app into Desktop Windowing. */
class DesktopSystemShortcut(
@@ -52,7 +51,7 @@ class DesktopSystemShortcut(
    }

    companion object {
        /** Creates a factory for creating Desktop system shorcuts. */
        /** Creates a factory for creating Desktop system shortcuts. */
        @JvmOverloads
        fun createFactory(
            abstractFloatingViewHelper: AbstractFloatingViewHelper = AbstractFloatingViewHelper()
@@ -62,7 +61,7 @@ class DesktopSystemShortcut(
                    container: RecentsViewContainer,
                    taskContainer: TaskIdAttributeContainer
                ): List<DesktopSystemShortcut>? {
                    return if (!Flags.enableDesktopWindowingMode()) null
                    return if (!DesktopModeStatus.canEnterDesktopMode(container.asContext())) null
                    else if (!taskContainer.task.isDockable) null
                    else
                        listOf(
+3 −3
Original line number Diff line number Diff line
@@ -68,7 +68,6 @@ import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SELECT_ACTIVE;
import static com.android.window.flags.Flags.enableDesktopWindowingMode;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -167,6 +166,7 @@ import com.android.launcher3.util.TranslateEdgeEffect;
import com.android.launcher3.util.VibratorWrapper;
import com.android.launcher3.util.ViewPool;
import com.android.quickstep.BaseContainerInterface;
import com.android.quickstep.DesktopModeStatus;
import com.android.quickstep.GestureState;
import com.android.quickstep.OverviewCommandHelper;
import com.android.quickstep.RecentsAnimationController;
@@ -2817,7 +2817,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
    }

    private boolean hasDesktopTask(Task[] runningTasks) {
        if (!enableDesktopWindowingMode()) {
        if (!DesktopModeStatus.canEnterDesktopMode(mContext)) {
            return false;
        }
        for (Task task : runningTasks) {
@@ -6229,7 +6229,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
     */
    public void moveTaskToDesktop(TaskIdAttributeContainer taskContainer,
            Runnable successCallback) {
        if (!enableDesktopWindowingMode()) {
        if (!DesktopModeStatus.canEnterDesktopMode(mContext)) {
            return;
        }
        switchToScreenshot(() -> finishRecentsAnimation(/* toRecents= */true, /* shouldPip= */false,
+65 −2
Original line number Diff line number Diff line
@@ -16,12 +16,14 @@

package com.android.quickstep

import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.android.dx.mockito.inline.extended.StaticMockitoSession
import android.content.ComponentName
import android.content.Intent
import android.platform.test.flag.junit.SetFlagsRule
import com.android.launcher3.AbstractFloatingView
import com.android.launcher3.AbstractFloatingViewHelper
import com.android.launcher3.Launcher
import com.android.launcher3.logging.StatsLogManager
import com.android.launcher3.logging.StatsLogManager.LauncherEvent
import com.android.launcher3.model.data.WorkspaceItemInfo
@@ -33,8 +35,11 @@ import com.android.systemui.shared.recents.model.Task
import com.android.systemui.shared.recents.model.Task.TaskKey
import com.android.window.flags.Flags
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.quality.Strictness
import org.mockito.kotlin.any
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
@@ -56,8 +61,23 @@ class DesktopSystemShortcutTest {
    private val factory: TaskShortcutFactory =
        DesktopSystemShortcut.createFactory(abstractFloatingViewHelper)

    private lateinit var mockitoSession: StaticMockitoSession

    @Before
    fun setUp(){
        mockitoSession = mockitoSession().strictness(Strictness.LENIENT)
                .spyStatic(DesktopModeStatus::class.java).startMocking()
        doReturn(true).`when` { DesktopModeStatus.enforceDeviceRestrictions() }
        doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
    }

    @After
    fun tearDown(){
        mockitoSession.finishMocking()
    }

    @Test
    fun createDesktopTaskShortcutFactory_featureOff() {
    fun createDesktopTaskShortcutFactory_desktopModeDisabled() {
        setFlagsRule.disableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)

        val task =
@@ -76,6 +96,49 @@ class DesktopSystemShortcutTest {
        assertThat(shortcuts).isNull()
    }

    @Test
    fun createDesktopTaskShortcutFactory_desktopModeEnabled_DeviceNotSupported() {
        setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
        doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }

        val task =
            Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
                isDockable = true
            }
        val taskContainer =
            taskView.TaskIdAttributeContainer(
                task,
                null,
                null,
                SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
            )

        val shortcuts = factory.getShortcuts(launcher, taskContainer)
        assertThat(shortcuts).isNull()
    }

    @Test
    fun createDesktopTaskShortcutFactory_desktopModeEnabled_DeviceNotSupported_OverrideEnabled() {
        setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
        doReturn(false).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }
        doReturn(false).`when` { DesktopModeStatus.enforceDeviceRestrictions() }

        val task =
            Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
                isDockable = true
            }
        val taskContainer =
            taskView.TaskIdAttributeContainer(
                task,
                null,
                null,
                SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
            )

        val shortcuts = factory.getShortcuts(launcher, taskContainer)
        assertThat(shortcuts).isNotNull()
    }

    @Test
    fun createDesktopTaskShortcutFactory_undockable() {
        setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)