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

Commit a91be253 authored by Pierre Barbier de Reuille's avatar Pierre Barbier de Reuille
Browse files

Add flag to enable desktop mode on specific devices

Flag: com.android.window.flags.enable_desktop_mode_through_dev_option
Bug: 382238347
Test: Build and check
Change-Id: I054b55c5de295b186fbfd6e29fc7c3a8943d6793
parent cd66718e
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -600,3 +600,13 @@ flag {
    description: "Enables split screen on non default displays"
    bug: "384999213"
}

flag {
    name: "enable_desktop_mode_through_dev_option"
    namespace: "lse_desktop_experience"
    description: "Enables support for desktop mode through developer options for devices eligible for desktop mode."
    bug: "382238347"
    metadata {
       purpose: PURPOSE_BUGFIX
    }
}
+3 −9
Original line number Diff line number Diff line
@@ -77,18 +77,11 @@ public class DesktopModeStatus {
    private static final boolean USE_ROUNDED_CORNERS = SystemProperties.getBoolean(
            "persist.wm.debug.desktop_use_rounded_corners", true);

    /**
     * Name of the system property used to set the device restriction.
     */
    @VisibleForTesting
    static final String ENFORCE_DEVICE_RESTRICTIONS_PROPERTY =
            "persist.wm.debug.desktop_mode_enforce_device_restrictions";

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

    private static final boolean USE_APP_TO_WEB_BUILD_TIME_GENERIC_LINKS =
            SystemProperties.getBoolean(
@@ -261,6 +254,7 @@ public class DesktopModeStatus {
        return DesktopModeFlags.isDesktopModeForcedEnabled()
                && canShowDesktopModeDevOption(context);
    }

    /**
     * Returns whether the multiple desktops feature is enabled for this device (both backend and
     * frontend implementations).
@@ -321,7 +315,7 @@ public class DesktopModeStatus {
     */
    public static boolean isDeviceEligibleForDesktopMode(@NonNull Context context) {
        return !enforceDeviceRestrictions() || isDesktopModeSupported(context) || (
                Flags.forceEnableDesktopModeWithDevOption() && isDesktopModeDevOptionSupported(
                Flags.enableDesktopModeThroughDevOption() && isDesktopModeDevOptionSupported(
                        context));
    }

+66 −33
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.wm.shell.shared.desktopmode

import android.content.Context
import android.content.res.Resources
import android.os.SystemProperties
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.annotations.Presubmit
@@ -28,7 +27,6 @@ import android.provider.Settings.Global.DEVELOPMENT_OVERRIDE_DESKTOP_MODE_FEATUR
import android.window.DesktopModeFlags
import androidx.test.filters.SmallTest
import com.android.internal.R
import com.android.modules.utils.testing.ExtendedMockitoRule
import com.android.window.flags.Flags
import com.android.wm.shell.ShellTestCase
import com.google.common.truth.Truth.assertThat
@@ -36,8 +34,6 @@ import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
@@ -47,14 +43,8 @@ import org.mockito.kotlin.whenever
@Presubmit
@EnableFlags(Flags.FLAG_SHOW_DESKTOP_WINDOWING_DEV_OPTION)
class DesktopModeStatusTest : ShellTestCase() {
    @get:Rule(order = 0)
    val mSetFlagsRule = SetFlagsRule();

    @get:Rule(order = 1)
    val extendedMockitoRule =
        ExtendedMockitoRule.Builder(this)
            .mockStatic(SystemProperties::class.java)
            .build()
    @get:Rule
    val mSetFlagsRule = SetFlagsRule()

    private val mockContext = mock<Context>()
    private val mockResources = mock<Resources>()
@@ -65,7 +55,7 @@ class DesktopModeStatusTest : ShellTestCase() {
        doReturn(false).whenever(mockResources).getBoolean(eq(R.bool.config_isDesktopModeSupported))
        doReturn(false).whenever(mockResources).getBoolean(
            eq(R.bool.config_isDesktopModeDevOptionSupported)
        );
        )
        doReturn(context.contentResolver).whenever(mockContext).contentResolver
        resetDesktopModeFlagsCache()
        resetEnforceDeviceRestriction()
@@ -76,28 +66,37 @@ class DesktopModeStatusTest : ShellTestCase() {
    fun tearDown() {
        resetDesktopModeFlagsCache()
        resetEnforceDeviceRestriction()
        resetFlagOverride();
        resetFlagOverride()
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @DisableFlags(
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
        Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION
    )
    @Test
    fun canEnterDesktopMode_DWFlagDisabled_configsOff_returnsFalse() {
        assertThat(DesktopModeStatus.canEnterDesktopMode(mockContext)).isFalse()
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @DisableFlags(
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
        Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION
    )
    @Test
    fun canEnterDesktopMode_DWFlagDisabled_configsOn_disableDeviceRestrictions_returnsFalse() {
        doReturn(true).whenever(mockResources).getBoolean(eq(R.bool.config_isDesktopModeSupported))
        doReturn(true).whenever(mockResources).getBoolean(
            eq(R.bool.config_isDesktopModeDevOptionSupported)
        );
        )
        disableEnforceDeviceRestriction()

        assertThat(DesktopModeStatus.canEnterDesktopMode(mockContext)).isFalse()
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @DisableFlags(
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
        Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION
    )
    @Test
    fun canEnterDesktopMode_DWFlagDisabled_configDevOptionOn_returnsFalse() {
        doReturn(true).whenever(mockResources).getBoolean(
@@ -107,23 +106,28 @@ class DesktopModeStatusTest : ShellTestCase() {
        assertThat(DesktopModeStatus.canEnterDesktopMode(mockContext)).isFalse()
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @DisableFlags(
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
        Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION
    )
    @Test
    fun canEnterDesktopMode_DWFlagDisabled_configDevOptionOn_flagOverrideOn_returnsTrue() {
        doReturn(true).whenever(mockResources).getBoolean(
            eq(R.bool.config_isDesktopModeDevOptionSupported)
        )
        setFlagOverride(DesktopModeFlags.ToggleOverride.OVERRIDE_ON);
        setFlagOverride(DesktopModeFlags.ToggleOverride.OVERRIDE_ON)

        assertThat(DesktopModeStatus.canEnterDesktopMode(mockContext)).isTrue()
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @Test
    fun canEnterDesktopMode_DWFlagEnabled_configsOff_returnsFalse() {
        assertThat(DesktopModeStatus.canEnterDesktopMode(mockContext)).isFalse()
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @Test
    fun canEnterDesktopMode_DWFlagEnabled_configDesktopModeOff_returnsFalse() {
@@ -134,6 +138,7 @@ class DesktopModeStatusTest : ShellTestCase() {
        assertThat(DesktopModeStatus.canEnterDesktopMode(mockContext)).isFalse()
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @Test
    fun canEnterDesktopMode_DWFlagEnabled_configDesktopModeOn_returnsTrue() {
@@ -142,14 +147,16 @@ class DesktopModeStatusTest : ShellTestCase() {
        assertThat(DesktopModeStatus.canEnterDesktopMode(mockContext)).isTrue()
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @Test
    fun canEnterDesktopMode_DWFlagEnabled_configsOff_disableDeviceRestrictions_returnsTrue() {
        disableEnforceDeviceRestriction();
        disableEnforceDeviceRestriction()

        assertThat(DesktopModeStatus.canEnterDesktopMode(mockContext)).isTrue()
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @Test
    fun canEnterDesktopMode_DWFlagEnabled_configDevOptionOn_flagOverrideOn_returnsTrue() {
@@ -161,22 +168,48 @@ class DesktopModeStatusTest : ShellTestCase() {
        assertThat(DesktopModeStatus.canEnterDesktopMode(mockContext)).isTrue()
    }

    private fun resetEnforceDeviceRestriction() {
        doAnswer { invocation -> invocation.getArgument<Boolean>(1) }.whenever(
            SystemProperties.getBoolean(
                DesktopModeStatus.ENFORCE_DEVICE_RESTRICTIONS_PROPERTY,
                anyBoolean()
            )
    @Test
    fun isDeviceEligibleForDesktopMode_configDEModeOn_returnsTrue() {
        doReturn(true).whenever(mockResources).getBoolean(eq(R.bool.config_isDesktopModeSupported))

        assertThat(DesktopModeStatus.isDeviceEligibleForDesktopMode(mockContext)).isTrue()
    }

    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
    @Test
    fun isDeviceEligibleForDesktopMode_supportFlagOff_returnsFalse() {
        assertThat(DesktopModeStatus.isDeviceEligibleForDesktopMode(mockContext)).isFalse()
    }

    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
    @Test
    fun isDeviceEligibleForDesktopMode_supportFlagOn_returnsFalse() {
        assertThat(DesktopModeStatus.isDeviceEligibleForDesktopMode(mockContext)).isFalse()
    }

    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
    @Test
    fun isDeviceEligibleForDesktopMode_supportFlagOn_configDevOptModeOn_returnsTrue() {
        doReturn(true).whenever(mockResources).getBoolean(
            eq(R.bool.config_isDesktopModeDevOptionSupported)
        )

        assertThat(DesktopModeStatus.isDeviceEligibleForDesktopMode(mockContext)).isTrue()
    }

    private fun resetEnforceDeviceRestriction() {
        setEnforceDeviceRestriction(true)
    }

    private fun disableEnforceDeviceRestriction() {
        doReturn(false).whenever(
            SystemProperties.getBoolean(
                DesktopModeStatus.ENFORCE_DEVICE_RESTRICTIONS_PROPERTY,
                anyBoolean()
            )
        )
        setEnforceDeviceRestriction(false)
    }

    private fun setEnforceDeviceRestriction(value: Boolean) {
        val field = DesktopModeStatus::class.java.getDeclaredField("ENFORCE_DEVICE_RESTRICTIONS")
        field.isAccessible = true
        field.setBoolean(null, value)
    }

    private fun resetDesktopModeFlagsCache() {
+8 −4
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.window.DesktopModeFlags;

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

/**
 * Constants for desktop mode feature
@@ -64,12 +65,15 @@ public final class DesktopModeHelper {
     * Check if Desktop mode should be enabled because the dev option is shown and enabled.
     */
    private static boolean isDesktopModeEnabledByDevOption(@NonNull Context context) {
        return DesktopModeFlags.isDesktopModeForcedEnabled()
                && isDesktopModeDevOptionsSupported(context);
        return DesktopModeFlags.isDesktopModeForcedEnabled() && (isDesktopModeDevOptionsSupported(
                context) || isDeviceEligibleForDesktopMode(context));
    }

    private static boolean isDeviceEligibleForDesktopMode(@NonNull Context context) {
        return !shouldEnforceDeviceRestrictions() || isDesktopModeSupported(context);
    @VisibleForTesting
    static boolean isDeviceEligibleForDesktopMode(@NonNull Context context) {
        return !shouldEnforceDeviceRestrictions() || isDesktopModeSupported(context)  || (
                Flags.enableDesktopModeThroughDevOption() && isDesktopModeDevOptionsSupported(
                        context));
    }

    /**
+42 −4
Original line number Diff line number Diff line
@@ -84,13 +84,15 @@ public class DesktopModeHelperTest {
        resetFlagOverride();
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @DisableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
            Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION})
    @Test
    public void canEnterDesktopMode_DWFlagDisabled_configsOff_returnsFalse() {
        assertThat(DesktopModeHelper.canEnterDesktopMode(mMockContext)).isFalse();
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @DisableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
            Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION})
    @Test
    public void canEnterDesktopMode_DWFlagDisabled_configsOn_disableDeviceCheck_returnsFalse()
            throws Exception {
@@ -102,7 +104,8 @@ public class DesktopModeHelperTest {
        assertThat(DesktopModeHelper.canEnterDesktopMode(mMockContext)).isFalse();
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @DisableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
            Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION})
    @Test
    public void canEnterDesktopMode_DWFlagDisabled_configDevOptionOn_returnsFalse() {
        doReturn(true).when(mMockResources).getBoolean(
@@ -111,7 +114,8 @@ public class DesktopModeHelperTest {
        assertThat(DesktopModeHelper.canEnterDesktopMode(mMockContext)).isFalse();
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @DisableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
            Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION})
    @Test
    public void canEnterDesktopMode_DWFlagDisabled_configDevOptionOn_flagOverrideOn_returnsTrue()
            throws Exception {
@@ -122,12 +126,14 @@ public class DesktopModeHelperTest {
        assertThat(DesktopModeHelper.canEnterDesktopMode(mMockContext)).isTrue();
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @Test
    public void canEnterDesktopMode_DWFlagEnabled_configsOff_returnsFalse() {
        assertThat(DesktopModeHelper.canEnterDesktopMode(mMockContext)).isFalse();
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @Test
    public void canEnterDesktopMode_DWFlagEnabled_configDesktopModeOff_returnsFalse() {
@@ -137,6 +143,7 @@ public class DesktopModeHelperTest {
        assertThat(DesktopModeHelper.canEnterDesktopMode(mMockContext)).isFalse();
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @Test
    public void canEnterDesktopMode_DWFlagEnabled_configDesktopModeOn_returnsTrue() {
@@ -145,6 +152,7 @@ public class DesktopModeHelperTest {
        assertThat(DesktopModeHelper.canEnterDesktopMode(mMockContext)).isTrue();
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @Test
    public void canEnterDesktopMode_DWFlagEnabled_configsOff_disableDeviceRestrictions_returnsTrue()
@@ -154,6 +162,7 @@ public class DesktopModeHelperTest {
        assertThat(DesktopModeHelper.canEnterDesktopMode(mMockContext)).isTrue();
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @Test
    public void canEnterDesktopMode_DWFlagEnabled_configDevOptionOn_flagOverrideOn_returnsTrue() {
@@ -165,6 +174,35 @@ public class DesktopModeHelperTest {
        assertThat(DesktopModeHelper.canEnterDesktopMode(mMockContext)).isTrue();
    }

    @Test
    public void isDeviceEligibleForDesktopMode_configDEModeOn_returnsTrue() {
        doReturn(true).when(mMockResources).getBoolean(eq(R.bool.config_isDesktopModeSupported));

        assertThat(DesktopModeHelper.isDeviceEligibleForDesktopMode(mMockContext)).isTrue();
    }

    @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
    @Test
    public void isDeviceEligibleForDesktopMode_supportFlagOff_returnsFalse() {
        assertThat(DesktopModeHelper.isDeviceEligibleForDesktopMode(mMockContext)).isFalse();
    }

    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
    @Test
    public void isDeviceEligibleForDesktopMode_supportFlagOn_returnsFalse() {
        assertThat(DesktopModeHelper.isDeviceEligibleForDesktopMode(mMockContext)).isFalse();
    }

    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_MODE_THROUGH_DEV_OPTION)
    @Test
    public void isDeviceEligibleForDesktopMode_supportFlagOn_configDevOptModeOn_returnsTrue() {
        doReturn(true).when(mMockResources).getBoolean(
                eq(R.bool.config_isDesktopModeDevOptionSupported)
        );

        assertThat(DesktopModeHelper.isDeviceEligibleForDesktopMode(mMockContext)).isTrue();
    }

    private void resetEnforceDeviceRestriction() throws Exception {
        setEnforceDeviceRestriction(true);
    }