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

Commit 6d633a06 authored by Graciela Wissen Putri's avatar Graciela Wissen Putri Committed by Massimo Carli
Browse files

[2/n] Add opaque background if task in freeform

Force set an opaque background colour for all freeform tasks to prevent
risk of other floating tasks below from being visible if the window
above is translucent.

Flag: com.android.window.flags.enable_opaque_background_for_transparent_windows
Bug: 397219542
Test: atest WindowDecorationTests
Test: atest DesktopModeStatusTest

Change-Id: Iea4c173681ac6f2a2b4105a91b839328d4a4be72
parent c2b07151
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@ import static com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper.enabl


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.app.TaskInfo;
import android.content.Context;
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager;
import android.os.SystemProperties;
import android.os.SystemProperties;
@@ -286,6 +287,16 @@ public class DesktopModeStatus {
                && deviceHasLargeScreen(context);
                && deviceHasLargeScreen(context);
    }
    }


    /**
     * @return If {@code true} we set opaque background for all freeform tasks to prevent freeform
     * tasks below from being visible if freeform task window above is translucent.
     * Otherwise if fluid resize is enabled, add a background to freeform tasks.
     */
    public static boolean shouldSetBackground(@NonNull TaskInfo taskInfo) {
        return taskInfo.isFreeform() && (!DesktopModeStatus.isVeiledResizeEnabled()
                || DesktopModeFlags.ENABLE_OPAQUE_BACKGROUND_FOR_TRANSPARENT_WINDOWS.isTrue());
    }

    /**
    /**
     * @return {@code true} if the app handle should be shown because desktop mode is enabled or
     * @return {@code true} if the app handle should be shown because desktop mode is enabled or
     * the device has a large screen
     * the device has a large screen
+5 −0
Original line number Original line Diff line number Diff line
@@ -61,6 +61,7 @@ import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
import com.android.wm.shell.shared.annotations.ShellMainThread;
import com.android.wm.shell.shared.annotations.ShellMainThread;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHost;
import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHost;
import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHostSupplier;
import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHostSupplier;
import com.android.wm.shell.windowdecor.extension.TaskInfoKt;
import com.android.wm.shell.windowdecor.extension.TaskInfoKt;
@@ -247,6 +248,10 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
        relayoutParams.mOccludingCaptionElements.add(controlsElement);
        relayoutParams.mOccludingCaptionElements.add(controlsElement);
        relayoutParams.mCaptionTopPadding = getTopPadding(relayoutParams,
        relayoutParams.mCaptionTopPadding = getTopPadding(relayoutParams,
                taskInfo.getConfiguration().windowConfiguration.getBounds(), displayInsetsState);
                taskInfo.getConfiguration().windowConfiguration.getBounds(), displayInsetsState);
        // Set opaque background for all freeform tasks to prevent freeform tasks below
        // from being visible if freeform task window above is translucent.
        // Otherwise if fluid resize is enabled, add a background to freeform tasks.
        relayoutParams.mShouldSetBackground = DesktopModeStatus.shouldSetBackground(taskInfo);
    }
    }


    @SuppressLint("MissingPermission")
    @SuppressLint("MissingPermission")
+4 −0
Original line number Original line Diff line number Diff line
@@ -1064,6 +1064,10 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
            relayoutParams.mCornerRadius = shouldIgnoreCornerRadius ? INVALID_CORNER_RADIUS :
            relayoutParams.mCornerRadius = shouldIgnoreCornerRadius ? INVALID_CORNER_RADIUS :
                    getCornerRadius(context, relayoutParams.mLayoutResId);
                    getCornerRadius(context, relayoutParams.mLayoutResId);
        }
        }
        // Set opaque background for all freeform tasks to prevent freeform tasks below
        // from being visible if freeform task window above is translucent.
        // Otherwise if fluid resize is enabled, add a background to freeform tasks.
        relayoutParams.mShouldSetBackground = DesktopModeStatus.shouldSetBackground(taskInfo);
    }
    }


    private static int getCornerRadius(@NonNull Context context, int layoutResId) {
    private static int getCornerRadius(@NonNull Context context, int layoutResId) {
+6 −7
Original line number Original line Diff line number Diff line
@@ -16,7 +16,6 @@


package com.android.wm.shell.windowdecor;
package com.android.wm.shell.windowdecor;


import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
import static android.view.WindowInsets.Type.captionBar;
import static android.view.WindowInsets.Type.captionBar;
import static android.view.WindowInsets.Type.mandatorySystemGestures;
import static android.view.WindowInsets.Type.mandatorySystemGestures;
@@ -57,7 +56,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.desktopmode.DesktopModeEventLogger;
import com.android.wm.shell.desktopmode.DesktopModeEventLogger;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.windowdecor.WindowDecoration.RelayoutParams.OccludingCaptionElement;
import com.android.wm.shell.windowdecor.WindowDecoration.RelayoutParams.OccludingCaptionElement;
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewHostViewContainer;
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewHostViewContainer;
import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHost;
import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHost;
@@ -504,15 +502,14 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
            startT.show(mTaskSurface);
            startT.show(mTaskSurface);
        }
        }


        if (mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM
        if (params.mShouldSetBackground) {
                && !DesktopModeStatus.isVeiledResizeEnabled()) {
            final int backgroundColorInt = mTaskInfo.taskDescription != null
            // When fluid resize is enabled, add a background to freeform tasks
                    ? mTaskInfo.taskDescription.getBackgroundColor() : Color.BLACK;
            int backgroundColorInt = mTaskInfo.taskDescription.getBackgroundColor();
            mTmpColor[0] = (float) Color.red(backgroundColorInt) / 255.f;
            mTmpColor[0] = (float) Color.red(backgroundColorInt) / 255.f;
            mTmpColor[1] = (float) Color.green(backgroundColorInt) / 255.f;
            mTmpColor[1] = (float) Color.green(backgroundColorInt) / 255.f;
            mTmpColor[2] = (float) Color.blue(backgroundColorInt) / 255.f;
            mTmpColor[2] = (float) Color.blue(backgroundColorInt) / 255.f;
            startT.setColor(mTaskSurface, mTmpColor);
            startT.setColor(mTaskSurface, mTmpColor);
        } else if (!DesktopModeStatus.isVeiledResizeEnabled()) {
        } else {
            startT.unsetColor(mTaskSurface);
            startT.unsetColor(mTaskSurface);
        }
        }


@@ -833,6 +830,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
        boolean mSetTaskVisibilityPositionAndCrop;
        boolean mSetTaskVisibilityPositionAndCrop;
        boolean mHasGlobalFocus;
        boolean mHasGlobalFocus;
        boolean mShouldSetAppBounds;
        boolean mShouldSetAppBounds;
        boolean mShouldSetBackground;


        void reset() {
        void reset() {
            mLayoutResId = Resources.ID_NULL;
            mLayoutResId = Resources.ID_NULL;
@@ -857,6 +855,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
            mAsyncViewHost = false;
            mAsyncViewHost = false;
            mHasGlobalFocus = false;
            mHasGlobalFocus = false;
            mShouldSetAppBounds = false;
            mShouldSetAppBounds = false;
            mShouldSetBackground = false;
        }
        }


        boolean hasInputFeatureSpy() {
        boolean hasInputFeatureSpy() {
+73 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package com.android.wm.shell.shared.desktopmode
package com.android.wm.shell.shared.desktopmode


import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.content.Context
import android.content.Context
import android.content.res.Resources
import android.content.res.Resources
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.DisableFlags
@@ -27,6 +28,7 @@ import androidx.test.filters.SmallTest
import com.android.internal.R
import com.android.internal.R
import com.android.window.flags.Flags
import com.android.window.flags.Flags
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.util.createTaskInfo
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.After
import org.junit.Before
import org.junit.Before
@@ -152,6 +154,70 @@ class DesktopModeStatusTest : ShellTestCase() {
        assertThat(DesktopModeStatus.canEnterDesktopMode(mockContext)).isTrue()
        assertThat(DesktopModeStatus.canEnterDesktopMode(mockContext)).isTrue()
    }
    }


    @EnableFlags(
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
        Flags.FLAG_ENABLE_OPAQUE_BACKGROUND_FOR_TRANSPARENT_WINDOWS,
    )
    @Test
    fun shouldSetBackground_BTWFlagEnabled_freeformTask_returnsTrue() {
        val freeFormTaskInfo = createTaskInfo(deviceWindowingMode = WINDOWING_MODE_FREEFORM)
        assertThat(DesktopModeStatus.shouldSetBackground(freeFormTaskInfo)).isTrue()
    }

    @EnableFlags(
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
        Flags.FLAG_ENABLE_OPAQUE_BACKGROUND_FOR_TRANSPARENT_WINDOWS,
    )
    @Test
    fun shouldSetBackground_BTWFlagEnabled_notFreeformTask_returnsFalse() {
        val notFreeFormTaskInfo = createTaskInfo()
        assertThat(DesktopModeStatus.shouldSetBackground(notFreeFormTaskInfo)).isFalse()
    }

    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @DisableFlags(Flags.FLAG_ENABLE_OPAQUE_BACKGROUND_FOR_TRANSPARENT_WINDOWS)
    @Test
    fun shouldSetBackground_BTWFlagDisabled_freeformTaskAndFluid_returnsTrue() {
        val freeFormTaskInfo = createTaskInfo(deviceWindowingMode = WINDOWING_MODE_FREEFORM)

        setIsVeiledResizeEnabled(false)
        assertThat(DesktopModeStatus.shouldSetBackground(freeFormTaskInfo)).isTrue()
    }

    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
    @DisableFlags(Flags.FLAG_ENABLE_OPAQUE_BACKGROUND_FOR_TRANSPARENT_WINDOWS)
    @Test
    fun shouldSetBackground_BTWFlagDisabled_freeformTaskAndVeiled_returnsFalse() {
        val freeFormTaskInfo = createTaskInfo(deviceWindowingMode = WINDOWING_MODE_FREEFORM)

        setIsVeiledResizeEnabled(true)
        assertThat(DesktopModeStatus.shouldSetBackground(freeFormTaskInfo)).isFalse()
    }

    @EnableFlags(
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
        Flags.FLAG_ENABLE_OPAQUE_BACKGROUND_FOR_TRANSPARENT_WINDOWS,
    )
    @Test
    fun shouldSetBackground_BTWFlagEnabled_freeformTaskAndFluid_returnsTrue() {
        val freeFormTaskInfo = createTaskInfo(deviceWindowingMode = WINDOWING_MODE_FREEFORM)

        setIsVeiledResizeEnabled(false)
        assertThat(DesktopModeStatus.shouldSetBackground(freeFormTaskInfo)).isTrue()
    }

    @EnableFlags(
        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE,
        Flags.FLAG_ENABLE_OPAQUE_BACKGROUND_FOR_TRANSPARENT_WINDOWS,
    )
    @Test
    fun shouldSetBackground_BTWFlagEnabled_windowModesTask_freeformTaskAndVeiled_returnsTrue() {
        val freeFormTaskInfo = createTaskInfo(deviceWindowingMode = WINDOWING_MODE_FREEFORM)

        setIsVeiledResizeEnabled(true)
        assertThat(DesktopModeStatus.shouldSetBackground(freeFormTaskInfo)).isTrue()
    }

    @Test
    @Test
    fun isDeviceEligibleForDesktopMode_configDEModeOnAndIntDispHostsDesktop_returnsTrue() {
    fun isDeviceEligibleForDesktopMode_configDEModeOnAndIntDispHostsDesktop_returnsTrue() {
        doReturn(true).whenever(mockResources).getBoolean(eq(R.bool.config_isDesktopModeSupported))
        doReturn(true).whenever(mockResources).getBoolean(eq(R.bool.config_isDesktopModeSupported))
@@ -254,4 +320,11 @@ class DesktopModeStatusTest : ShellTestCase() {
        deviceRestrictions.isAccessible = true
        deviceRestrictions.isAccessible = true
        deviceRestrictions.setBoolean(/* obj= */ null, /* z= */ !eligible)
        deviceRestrictions.setBoolean(/* obj= */ null, /* z= */ !eligible)
    }
    }

    private fun setIsVeiledResizeEnabled(enabled: Boolean) {
        val deviceRestrictions =
            DesktopModeStatus::class.java.getDeclaredField("IS_VEILED_RESIZE_ENABLED")
        deviceRestrictions.isAccessible = true
        deviceRestrictions.setBoolean(/* obj= */ null, /* z= */ enabled)
    }
}
}
Loading