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

Commit 6d7332e4 authored by Alina Zaidi's avatar Alina Zaidi
Browse files

[Dev option] Use Dev option to override whether DW should be enabled

Add utilities for dev option toggle in
DesktopModeStatus. Store an Int in Settings on manual override of
toggle.

Default value of this dev options solely depends on
enable_desktop_windowing_mode, which is intended

Toggle is shown only if DW is eligible on device

Currently this option only overrides features guarded by
enable_desktop_windowing_mode, later on it will be used to override a
few other DW features

Test: Added tests. Locally tested CUJs
Bug: 348193756
Flag:  com.android.window.flags.show_desktop_windowing_dev_option

Change-Id: I1c1f946b586a5ca0440b29879925ba1a624717aa
parent 37af53c7
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -13383,7 +13383,19 @@ public final class Settings {
                = "enable_freeform_support";
        /**
         * Whether to enable experimental desktop mode on secondary displays.
         * Whether to override the availability of the desktop mode on the main display of the
         * device. If on, users can make move an app to the desktop, allowing a freeform windowing
         * experience.
         * @hide
         */
        @Readable
        public static final String DEVELOPMENT_OVERRIDE_DESKTOP_MODE_FEATURES =
                "override_desktop_mode_features";
        /**
         * Whether to enable the legacy freeform support on secondary displays. If enabled, the
         * SECONDARY_HOME of the launcher is started on any secondary display, allowing for a
         * desktop experience.
         * @hide
         */
        @Readable
+45 −5
Original line number Diff line number Diff line
@@ -16,9 +16,13 @@

package com.android.wm.shell.shared;

import static android.provider.Settings.Global.DEVELOPMENT_OVERRIDE_DESKTOP_MODE_FEATURES;

import android.annotation.NonNull;
import android.content.Context;
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Log;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -29,6 +33,8 @@ import com.android.window.flags.Flags;
 */
public class DesktopModeStatus {

    private static final String TAG = "DesktopModeStatus";

    /**
     * Flag to indicate whether task resizing is veiled.
     */
@@ -98,11 +104,12 @@ public class DesktopModeStatus {
            "persist.wm.debug.desktop_max_task_limit", DEFAULT_MAX_TASK_LIMIT);

    /**
     * Return {@code true} if desktop windowing is enabled. Only to be used for testing. Callers
     * should use {@link #canEnterDesktopMode(Context)} to query the state of desktop windowing.
     * Return {@code true} if desktop windowing flag is enabled. Only to be used for testing.
     * Callers should use {@link #canEnterDesktopMode(Context)} to query the state of desktop
     * windowing.
     */
    @VisibleForTesting
    public static boolean isEnabled() {
    public static boolean isDesktopModeFlagEnabled() {
        return Flags.enableDesktopWindowingMode();
    }

@@ -153,11 +160,37 @@ public class DesktopModeStatus {
        return context.getResources().getBoolean(R.bool.config_isDesktopModeSupported);
    }

    /**
     * Return {@code true} if desktop mode dev option should be shown on current device
     */
    public static boolean canShowDesktopModeDevOption(@NonNull Context context) {
        return isDeviceEligibleForDesktopMode(context) && Flags.showDesktopWindowingDevOption();
    }

    /** Returns if desktop mode dev option should be enabled if there is no user override. */
    public static boolean shouldDevOptionBeEnabledByDefault() {
        return isDesktopModeFlagEnabled();
    }

    /**
     * Return {@code true} if desktop mode is enabled and can be entered on the current device.
     */
    public static boolean canEnterDesktopMode(@NonNull Context context) {
        return (!enforceDeviceRestrictions() || isDesktopModeSupported(context)) && isEnabled();
        if (!isDeviceEligibleForDesktopMode(context)) return false;

        // If dev option has ever been manually toggled by the user, return its value
        // TODO(b/348193756) : Move the logic for DW override based on toggle overides to a common
        //  infrastructure and add caching for the computation
        int defaultOverrideState = -1;
        int toggleState = Settings.Global.getInt(context.getContentResolver(),
                DEVELOPMENT_OVERRIDE_DESKTOP_MODE_FEATURES, defaultOverrideState);
        if (toggleState != defaultOverrideState) {
            Log.d(TAG, "Using Desktop mode dev option overridden state");
            return toggleState != 0;
        }

        // Return Desktop windowing flag value
        return isDesktopModeFlagEnabled();
    }

    /**
@@ -181,4 +214,11 @@ public class DesktopModeStatus {
        return DESKTOP_DENSITY_OVERRIDE >= DESKTOP_DENSITY_MIN
                && DESKTOP_DENSITY_OVERRIDE <= DESKTOP_DENSITY_MAX;
    }

    /**
     * Return {@code true} if desktop mode is unrestricted and is supported in the device.
     */
    private static boolean isDeviceEligibleForDesktopMode(@NonNull Context context) {
        return !enforceDeviceRestrictions() || isDesktopModeSupported(context);
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -191,7 +191,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
            .strictness(Strictness.LENIENT)
            .spyStatic(DesktopModeStatus::class.java)
            .startMocking()
    whenever(DesktopModeStatus.isEnabled()).thenReturn(true)
    whenever(DesktopModeStatus.isDesktopModeFlagEnabled()).thenReturn(true)
    doReturn(true).`when` { DesktopModeStatus.isDesktopModeSupported(any()) }

    shellInit = spy(ShellInit(testExecutor))
@@ -261,7 +261,7 @@ class DesktopTasksControllerTest : ShellTestCase() {

  @Test
  fun instantiate_flagOff_doNotAddInitCallback() {
    whenever(DesktopModeStatus.isEnabled()).thenReturn(false)
    whenever(DesktopModeStatus.isDesktopModeFlagEnabled()).thenReturn(false)
    clearInvocations(shellInit)

    createController()
+17 −3
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@ import android.platform.test.flag.junit.SetFlagsRule
import android.testing.AndroidTestingRunner
import android.view.Display
import android.window.WindowContainerToken
import com.android.dx.mockito.inline.extended.ExtendedMockito
import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
import com.android.dx.mockito.inline.extended.StaticMockitoSession
import com.android.window.flags.Flags
import com.android.wm.shell.R
import com.android.wm.shell.common.DisplayController
@@ -37,6 +40,7 @@ import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT
import com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP
import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.assertTrue
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -45,6 +49,7 @@ import org.mockito.Mock
import org.mockito.Mockito.any
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
import org.mockito.quality.Strictness

/**
 * Tests for [DragPositioningCallbackUtility].
@@ -82,9 +87,13 @@ class DragPositioningCallbackUtilityTest {
    @Rule
    val setFlagsRule = SetFlagsRule()

    private lateinit var mockitoSession: StaticMockitoSession

    @Before
    fun setup() {
        MockitoAnnotations.initMocks(this)
        mockitoSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT)
                .spyStatic(DesktopModeStatus::class.java).startMocking()

        whenever(taskToken.asBinder()).thenReturn(taskBinder)
        whenever(mockDisplayController.getDisplayLayout(DISPLAY_ID)).thenReturn(mockDisplayLayout)
@@ -105,6 +114,11 @@ class DragPositioningCallbackUtilityTest {
        whenever(mockDisplay.displayId).thenAnswer { DISPLAY_ID }
    }

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

    @Test
    fun testChangeBoundsDoesNotChangeHeightWhenLessThanMin() {
        val startingPoint = PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.top.toFloat())
@@ -252,7 +266,7 @@ class DragPositioningCallbackUtilityTest {
    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS)
    fun taskMinWidthHeightUndefined_changeBoundsInDesktopModeLessThanMin_shouldNotChangeBounds() {
        whenever(DesktopModeStatus.canEnterDesktopMode(mockContext)).thenReturn(true)
        doReturn(true).`when`{ DesktopModeStatus.canEnterDesktopMode(mockContext) }
        initializeTaskInfo(taskMinWidth = -1, taskMinHeight = -1)
        val startingPoint =
            PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat())
@@ -275,7 +289,7 @@ class DragPositioningCallbackUtilityTest {
    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS)
    fun taskMinWidthHeightUndefined_changeBoundsInDesktopModeAllowedSize_shouldChangeBounds() {
        whenever(DesktopModeStatus.canEnterDesktopMode(mockContext)).thenReturn(true)
        doReturn(true).`when`{ DesktopModeStatus.canEnterDesktopMode(mockContext) }
        initializeTaskInfo(taskMinWidth = -1, taskMinHeight = -1)
        val startingPoint =
            PointF(STARTING_BOUNDS.right.toFloat(), STARTING_BOUNDS.bottom.toFloat())
@@ -361,7 +375,7 @@ class DragPositioningCallbackUtilityTest {
    @Test
    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_SIZE_CONSTRAINTS)
    fun testChangeBoundsInDesktopMode_windowSizeExceedsStableBounds_shouldBeLimitedToDisplaySize() {
        whenever(DesktopModeStatus.canEnterDesktopMode(mockContext)).thenReturn(true)
        doReturn(true).`when`{ DesktopModeStatus.canEnterDesktopMode(mockContext) }
        val startingPoint =
            PointF(OFF_CENTER_STARTING_BOUNDS.right.toFloat(),
                OFF_CENTER_STARTING_BOUNDS.bottom.toFloat())
+4 −4
Original line number Diff line number Diff line
@@ -1010,10 +1010,10 @@
    <!-- UI debug setting: force allow on external summary [CHAR LIMIT=150] -->
    <string name="force_resizable_activities_summary">Make all activities resizable for multi-window, regardless of manifest values.</string>

    <!-- UI debug setting: enable freeform window support [CHAR LIMIT=50] -->
    <string name="enable_freeform_support">Enable freeform windows</string>
    <!-- UI debug setting: enable freeform window support summary [CHAR LIMIT=150] -->
    <string name="enable_freeform_support_summary">Enable support for experimental freeform windows.</string>
    <!-- UI debug setting: enable legacy freeform window support [CHAR LIMIT=50] -->
    <string name="enable_freeform_support">Enable freeform windows (legacy)</string>
    <!-- UI debug setting: enable legacy freeform window support summary [CHAR LIMIT=150] -->
    <string name="enable_freeform_support_summary">Enable support for experimental legacy freeform windows.</string>

    <!-- Local (desktop) backup password menu title [CHAR LIMIT=25] -->
    <string name="local_backup_password_title">Desktop backup password</string>
Loading