Loading core/java/android/window/flags/lse_desktop_experience.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -78,3 +78,10 @@ flag { description: "Allows for additional windows tied to WindowDecoration to be layered between status bar and notification shade." bug: "316186265" } flag { name: "enable_app_header_with_task_density" namespace: "lse_desktop_experience" description: "Matches the App Header density to that of the app window, instead of SysUI's" bug: "332414819" } libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +22 −12 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.ScreenDecorationsUtils; import com.android.launcher3.icons.BaseIconFactory; import com.android.launcher3.icons.IconProvider; import com.android.window.flags.Flags; import com.android.wm.shell.R; import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.ShellTaskOrganizer; Loading Loading @@ -332,13 +333,16 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop) { final int captionLayoutId = getDesktopModeWindowDecorLayoutId(taskInfo.getWindowingMode()); final boolean isAppHeader = captionLayoutId == R.layout.desktop_mode_app_controls_window_decor; final boolean isAppHandle = captionLayoutId == R.layout.desktop_mode_focused_window_decor; relayoutParams.reset(); relayoutParams.mRunningTaskInfo = taskInfo; relayoutParams.mLayoutResId = captionLayoutId; relayoutParams.mCaptionHeightId = getCaptionHeightIdStatic(taskInfo.getWindowingMode()); relayoutParams.mCaptionWidthId = getCaptionWidthId(relayoutParams.mLayoutResId); if (captionLayoutId == R.layout.desktop_mode_app_controls_window_decor) { if (isAppHeader) { if (TaskInfoKt.isTransparentCaptionBarAppearance(taskInfo)) { // If the app is requesting to customize the caption bar, allow input to fall // through to the windows below so that the app can respond to input events on Loading @@ -359,7 +363,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin controlsElement.mWidthResId = R.dimen.desktop_mode_customizable_caption_margin_end; controlsElement.mAlignment = RelayoutParams.OccludingCaptionElement.Alignment.END; relayoutParams.mOccludingCaptionElements.add(controlsElement); } else if (captionLayoutId == R.layout.desktop_mode_focused_window_decor) { } else if (isAppHandle) { // The focused decor (fullscreen/split) does not need to handle input because input in // the App Handle is handled by the InputMonitor in DesktopModeWindowDecorViewModel. relayoutParams.mInputFeatures Loading @@ -372,19 +376,25 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin } relayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw; relayoutParams.mSetTaskPositionAndCrop = shouldSetTaskPositionAndCrop; // The configuration used to lay out the window decoration. The system context's config is // used when the task density has been overridden to a custom density so that the resources // and views of the decoration aren't affected and match the rest of the System UI, if not // then just use the task's configuration. A copy is made instead of using the original // reference so that the configuration isn't mutated on config changes and diff checks can // be made in WindowDecoration#relayout using the pre/post-relayout configuration. // See b/301119301. // The configuration used to layout the window decoration. A copy is made instead of using // the original reference so that the configuration isn't mutated on config changes and // diff checks can be made in WindowDecoration#relayout using the pre/post-relayout // configuration. See b/301119301. // TODO(b/301119301): consider moving the config data needed for diffs to relayout params // instead of using a whole Configuration as a parameter. final Configuration windowDecorConfig = new Configuration(); windowDecorConfig.setTo(DesktopTasksController.isDesktopDensityOverrideSet() ? context.getResources().getConfiguration() // Use system context. : taskInfo.configuration); // Use task configuration. if (Flags.enableAppHeaderWithTaskDensity() && isAppHeader) { // Should match the density of the task. The task may have had its density overridden // to be different that SysUI's. windowDecorConfig.setTo(taskInfo.configuration); } else if (DesktopTasksController.isDesktopDensityOverrideSet()) { // The task has had its density overridden, but keep using the system's density to // layout the header. windowDecorConfig.setTo(context.getResources().getConfiguration()); } else { windowDecorConfig.setTo(taskInfo.configuration); } relayoutParams.mWindowDecorConfig = windowDecorConfig; if (DesktopModeStatus.useRoundedCorners()) { Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java +50 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.wm.shell.windowdecor; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT; import static android.view.WindowInsetsController.APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND; import static com.google.common.truth.Truth.assertThat; Loading @@ -39,6 +40,9 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Handler; import android.os.SystemProperties; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.testing.AndroidTestingRunner; import android.testing.TestableContext; import android.view.Choreographer; Loading @@ -51,6 +55,7 @@ import android.window.WindowContainerTransaction; import androidx.test.filters.SmallTest; import com.android.internal.R; import com.android.window.flags.Flags; import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; Loading @@ -61,6 +66,7 @@ import com.android.wm.shell.windowdecor.WindowDecoration.RelayoutParams; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; Loading @@ -83,6 +89,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { private static final String USE_ROUNDED_CORNERS_SYSPROP_KEY = "persist.wm.debug.desktop_use_rounded_corners"; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT); @Mock private DisplayController mMockDisplayController; @Mock Loading Loading @@ -174,6 +182,48 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { assertThat(relayoutParams.mCornerRadius).isGreaterThan(0); } @Test @EnableFlags(Flags.FLAG_ENABLE_APP_HEADER_WITH_TASK_DENSITY) public void updateRelayoutParams_appHeader_usesTaskDensity() { final int systemDensity = mTestableContext.getOrCreateTestableResources().getResources() .getConfiguration().densityDpi; final int customTaskDensity = systemDensity + 300; final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM); taskInfo.configuration.densityDpi = customTaskDensity; final RelayoutParams relayoutParams = new RelayoutParams(); DesktopModeWindowDecoration.updateRelayoutParams( relayoutParams, mTestableContext, taskInfo, /* applyStartTransactionOnDraw= */ true, /* shouldSetTaskPositionAndCrop */ false); assertThat(relayoutParams.mWindowDecorConfig.densityDpi).isEqualTo(customTaskDensity); } @Test @DisableFlags(Flags.FLAG_ENABLE_APP_HEADER_WITH_TASK_DENSITY) public void updateRelayoutParams_appHeader_usesSystemDensity() { final int systemDensity = mTestableContext.getOrCreateTestableResources().getResources() .getConfiguration().densityDpi; final int customTaskDensity = systemDensity + 300; final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN); taskInfo.configuration.densityDpi = customTaskDensity; final RelayoutParams relayoutParams = new RelayoutParams(); DesktopModeWindowDecoration.updateRelayoutParams( relayoutParams, mTestableContext, taskInfo, /* applyStartTransactionOnDraw= */ true, /* shouldSetTaskPositionAndCrop */ false); assertThat(relayoutParams.mWindowDecorConfig.densityDpi).isEqualTo(systemDensity); } @Test public void updateRelayoutParams_freeformAndTransparentAppearance_allowsInputFallthrough() { final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); Loading Loading
core/java/android/window/flags/lse_desktop_experience.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -78,3 +78,10 @@ flag { description: "Allows for additional windows tied to WindowDecoration to be layered between status bar and notification shade." bug: "316186265" } flag { name: "enable_app_header_with_task_density" namespace: "lse_desktop_experience" description: "Matches the App Header density to that of the app window, instead of SysUI's" bug: "332414819" }
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +22 −12 Original line number Diff line number Diff line Loading @@ -60,6 +60,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.ScreenDecorationsUtils; import com.android.launcher3.icons.BaseIconFactory; import com.android.launcher3.icons.IconProvider; import com.android.window.flags.Flags; import com.android.wm.shell.R; import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.ShellTaskOrganizer; Loading Loading @@ -332,13 +333,16 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop) { final int captionLayoutId = getDesktopModeWindowDecorLayoutId(taskInfo.getWindowingMode()); final boolean isAppHeader = captionLayoutId == R.layout.desktop_mode_app_controls_window_decor; final boolean isAppHandle = captionLayoutId == R.layout.desktop_mode_focused_window_decor; relayoutParams.reset(); relayoutParams.mRunningTaskInfo = taskInfo; relayoutParams.mLayoutResId = captionLayoutId; relayoutParams.mCaptionHeightId = getCaptionHeightIdStatic(taskInfo.getWindowingMode()); relayoutParams.mCaptionWidthId = getCaptionWidthId(relayoutParams.mLayoutResId); if (captionLayoutId == R.layout.desktop_mode_app_controls_window_decor) { if (isAppHeader) { if (TaskInfoKt.isTransparentCaptionBarAppearance(taskInfo)) { // If the app is requesting to customize the caption bar, allow input to fall // through to the windows below so that the app can respond to input events on Loading @@ -359,7 +363,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin controlsElement.mWidthResId = R.dimen.desktop_mode_customizable_caption_margin_end; controlsElement.mAlignment = RelayoutParams.OccludingCaptionElement.Alignment.END; relayoutParams.mOccludingCaptionElements.add(controlsElement); } else if (captionLayoutId == R.layout.desktop_mode_focused_window_decor) { } else if (isAppHandle) { // The focused decor (fullscreen/split) does not need to handle input because input in // the App Handle is handled by the InputMonitor in DesktopModeWindowDecorViewModel. relayoutParams.mInputFeatures Loading @@ -372,19 +376,25 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin } relayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw; relayoutParams.mSetTaskPositionAndCrop = shouldSetTaskPositionAndCrop; // The configuration used to lay out the window decoration. The system context's config is // used when the task density has been overridden to a custom density so that the resources // and views of the decoration aren't affected and match the rest of the System UI, if not // then just use the task's configuration. A copy is made instead of using the original // reference so that the configuration isn't mutated on config changes and diff checks can // be made in WindowDecoration#relayout using the pre/post-relayout configuration. // See b/301119301. // The configuration used to layout the window decoration. A copy is made instead of using // the original reference so that the configuration isn't mutated on config changes and // diff checks can be made in WindowDecoration#relayout using the pre/post-relayout // configuration. See b/301119301. // TODO(b/301119301): consider moving the config data needed for diffs to relayout params // instead of using a whole Configuration as a parameter. final Configuration windowDecorConfig = new Configuration(); windowDecorConfig.setTo(DesktopTasksController.isDesktopDensityOverrideSet() ? context.getResources().getConfiguration() // Use system context. : taskInfo.configuration); // Use task configuration. if (Flags.enableAppHeaderWithTaskDensity() && isAppHeader) { // Should match the density of the task. The task may have had its density overridden // to be different that SysUI's. windowDecorConfig.setTo(taskInfo.configuration); } else if (DesktopTasksController.isDesktopDensityOverrideSet()) { // The task has had its density overridden, but keep using the system's density to // layout the header. windowDecorConfig.setTo(context.getResources().getConfiguration()); } else { windowDecorConfig.setTo(taskInfo.configuration); } relayoutParams.mWindowDecorConfig = windowDecorConfig; if (DesktopModeStatus.useRoundedCorners()) { Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java +50 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.wm.shell.windowdecor; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT; import static android.view.WindowInsetsController.APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND; import static com.google.common.truth.Truth.assertThat; Loading @@ -39,6 +40,9 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Handler; import android.os.SystemProperties; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.testing.AndroidTestingRunner; import android.testing.TestableContext; import android.view.Choreographer; Loading @@ -51,6 +55,7 @@ import android.window.WindowContainerTransaction; import androidx.test.filters.SmallTest; import com.android.internal.R; import com.android.window.flags.Flags; import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; Loading @@ -61,6 +66,7 @@ import com.android.wm.shell.windowdecor.WindowDecoration.RelayoutParams; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; Loading @@ -83,6 +89,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { private static final String USE_ROUNDED_CORNERS_SYSPROP_KEY = "persist.wm.debug.desktop_use_rounded_corners"; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT); @Mock private DisplayController mMockDisplayController; @Mock Loading Loading @@ -174,6 +182,48 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { assertThat(relayoutParams.mCornerRadius).isGreaterThan(0); } @Test @EnableFlags(Flags.FLAG_ENABLE_APP_HEADER_WITH_TASK_DENSITY) public void updateRelayoutParams_appHeader_usesTaskDensity() { final int systemDensity = mTestableContext.getOrCreateTestableResources().getResources() .getConfiguration().densityDpi; final int customTaskDensity = systemDensity + 300; final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM); taskInfo.configuration.densityDpi = customTaskDensity; final RelayoutParams relayoutParams = new RelayoutParams(); DesktopModeWindowDecoration.updateRelayoutParams( relayoutParams, mTestableContext, taskInfo, /* applyStartTransactionOnDraw= */ true, /* shouldSetTaskPositionAndCrop */ false); assertThat(relayoutParams.mWindowDecorConfig.densityDpi).isEqualTo(customTaskDensity); } @Test @DisableFlags(Flags.FLAG_ENABLE_APP_HEADER_WITH_TASK_DENSITY) public void updateRelayoutParams_appHeader_usesSystemDensity() { final int systemDensity = mTestableContext.getOrCreateTestableResources().getResources() .getConfiguration().densityDpi; final int customTaskDensity = systemDensity + 300; final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN); taskInfo.configuration.densityDpi = customTaskDensity; final RelayoutParams relayoutParams = new RelayoutParams(); DesktopModeWindowDecoration.updateRelayoutParams( relayoutParams, mTestableContext, taskInfo, /* applyStartTransactionOnDraw= */ true, /* shouldSetTaskPositionAndCrop */ false); assertThat(relayoutParams.mWindowDecorConfig.densityDpi).isEqualTo(systemDensity); } @Test public void updateRelayoutParams_freeformAndTransparentAppearance_allowsInputFallthrough() { final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); Loading