Loading core/java/android/app/TaskInfo.java +10 −0 Original line number Diff line number Diff line Loading @@ -296,6 +296,12 @@ public class TaskInfo { */ public boolean isTopActivityTransparent; /** * Whether the top activity has specified style floating. * @hide */ public boolean isTopActivityStyleFloating; /** * Encapsulate specific App Compat information. * @hide Loading Loading @@ -429,6 +435,7 @@ public class TaskInfo { && parentTaskId == that.parentTaskId && Objects.equals(topActivity, that.topActivity) && isTopActivityTransparent == that.isTopActivityTransparent && isTopActivityStyleFloating == that.isTopActivityStyleFloating && appCompatTaskInfo.equalsForTaskOrganizer(that.appCompatTaskInfo); } Loading Loading @@ -498,6 +505,7 @@ public class TaskInfo { mTopActivityLocusId = source.readTypedObject(LocusId.CREATOR); displayAreaFeatureId = source.readInt(); isTopActivityTransparent = source.readBoolean(); isTopActivityStyleFloating = source.readBoolean(); appCompatTaskInfo = source.readTypedObject(AppCompatTaskInfo.CREATOR); } Loading Loading @@ -545,6 +553,7 @@ public class TaskInfo { dest.writeTypedObject(mTopActivityLocusId, flags); dest.writeInt(displayAreaFeatureId); dest.writeBoolean(isTopActivityTransparent); dest.writeBoolean(isTopActivityStyleFloating); dest.writeTypedObject(appCompatTaskInfo, flags); } Loading Loading @@ -582,6 +591,7 @@ public class TaskInfo { + " locusId=" + mTopActivityLocusId + " displayAreaFeatureId=" + displayAreaFeatureId + " isTopActivityTransparent=" + isTopActivityTransparent + " isTopActivityStyleFloating=" + isTopActivityStyleFloating + " appCompatTaskInfo=" + appCompatTaskInfo + "}"; } Loading libs/WindowManager/Shell/src/com/android/wm/shell/compatui/AppCompatUtils.kt +12 −2 Original line number Diff line number Diff line Loading @@ -19,6 +19,16 @@ package com.android.wm.shell.compatui import android.app.TaskInfo fun isSingleTopActivityTranslucent(task: TaskInfo) = task.isTopActivityTransparent && task.numActivities == 1 import android.content.Context import com.android.internal.R // TODO(b/347289970): Consider replacing with API fun isTopActivityExemptFromDesktopWindowing(context: Context, task: TaskInfo) = isSystemUiTask(context, task) || (task.isTopActivityTransparent && task.numActivities == 1 && !task.isTopActivityStyleFloating) private fun isSystemUiTask(context: Context, task: TaskInfo): Boolean { val sysUiPackageName: String = context.resources.getString(R.string.config_systemUi) return task.baseActivity?.packageName == sysUiPackageName } libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +9 −25 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT import com.android.wm.shell.compatui.isSingleTopActivityTranslucent import com.android.wm.shell.compatui.isTopActivityExemptFromDesktopWindowing import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksListener import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler.DragToDesktopStateListener import com.android.wm.shell.draganddrop.DragAndDropController Loading Loading @@ -158,8 +158,6 @@ class DesktopTasksController( visualIndicator = null } } private val sysUIPackageName = context.resources.getString( com.android.internal.R.string.config_systemUi) private val transitionAreaHeight get() = Loading Loading @@ -219,11 +217,6 @@ class DesktopTasksController( return visualIndicator } // TODO(b/347289970): Consider replacing with API private fun isSystemUIApplication(taskInfo: RunningTaskInfo): Boolean { return taskInfo.baseActivity?.packageName == sysUIPackageName } fun setOnTaskResizeAnimationListener(listener: OnTaskResizeAnimationListener) { toggleResizeDesktopTaskTransitionHandler.setOnTaskResizeAnimationListener(listener) enterDesktopTaskTransitionHandler.setOnTaskResizeAnimationListener(listener) Loading Loading @@ -351,19 +344,12 @@ class DesktopTasksController( wct: WindowContainerTransaction = WindowContainerTransaction(), transitionSource: DesktopModeTransitionSource, ) { if (Flags.enableDesktopWindowingModalsPolicy() && isSingleTopActivityTranslucent(task)) { KtProtoLog.w( WM_SHELL_DESKTOP_MODE, "DesktopTasksController: Cannot enter desktop, " + "translucent top activity found. This is likely a modal dialog." ) return } if (isSystemUIApplication(task)) { if (Flags.enableDesktopWindowingModalsPolicy() && isTopActivityExemptFromDesktopWindowing(context, task)) { KtProtoLog.w( WM_SHELL_DESKTOP_MODE, "DesktopTasksController: Cannot enter desktop, " + "systemUI top activity found." "ineligible top activity found." ) return } Loading Loading @@ -942,10 +928,8 @@ class DesktopTasksController( when { // Check if the closing task needs to be handled TransitionUtil.isClosingType(request.type) -> handleTaskClosing(task) // Check if the task has a top transparent activity shouldLaunchAsModal(task) -> handleIncompatibleTaskLaunch(task) // Check if the task has a top systemUI activity isSystemUIApplication(task) -> handleIncompatibleTaskLaunch(task) // Check if the top task shouldn't be allowed to enter desktop mode isIncompatibleTask(task) -> handleIncompatibleTaskLaunch(task) // Check if fullscreen task should be updated task.isFullscreen -> handleFullscreenTaskLaunch(task, transition) // Check if freeform task should be updated Loading Loading @@ -979,9 +963,9 @@ class DesktopTasksController( .forEach { finishTransaction.setCornerRadius(it.leash, cornerRadius) } } // TODO(b/347289970): Consider replacing with API private fun shouldLaunchAsModal(task: TaskInfo) = Flags.enableDesktopWindowingModalsPolicy() && isSingleTopActivityTranslucent(task) private fun isIncompatibleTask(task: TaskInfo) = Flags.enableDesktopWindowingModalsPolicy() && isTopActivityExemptFromDesktopWindowing(context, task) private fun shouldHandleTaskClosing(request: TransitionRequestInfo): Boolean { return Flags.enableDesktopWindowingWallpaperActivity() && Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +2 −15 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ import static android.view.WindowInsets.Type.statusBars; import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; import static com.android.wm.shell.compatui.AppCompatUtils.isSingleTopActivityTranslucent; import static com.android.wm.shell.compatui.AppCompatUtils.isTopActivityExemptFromDesktopWindowing; import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; Loading Loading @@ -105,7 +105,6 @@ import com.android.wm.shell.windowdecor.extension.TaskInfoKt; import com.android.wm.shell.windowdecor.viewholder.AppHeaderViewHolder; import java.io.PrintWriter; import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; Loading Loading @@ -1034,12 +1033,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { && taskInfo.isFocused) { return false; } // TODO(b/347289970): Consider replacing with API if (Flags.enableDesktopWindowingModalsPolicy() && isSingleTopActivityTranslucent(taskInfo)) { return false; } if (isSystemUIApplication(taskInfo)) { && isTopActivityExemptFromDesktopWindowing(mContext, taskInfo)) { return false; } return DesktopModeStatus.canEnterDesktopMode(mContext) Loading Loading @@ -1118,14 +1113,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { && mSplitScreenController.isTaskInSplitScreen(taskId); } // TODO(b/347289970): Consider replacing with API private boolean isSystemUIApplication(RunningTaskInfo taskInfo) { if (taskInfo.baseActivity != null) { return (Objects.equals(taskInfo.baseActivity.getPackageName(), mSysUIPackageName)); } return false; } private void dump(PrintWriter pw, String prefix) { final String innerPrefix = prefix + " "; pw.println(prefix + "DesktopModeWindowDecorViewModel"); Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/AppCompatUtilsTest.kt +37 −6 Original line number Diff line number Diff line Loading @@ -16,8 +16,10 @@ package com.android.wm.shell.compatui import android.content.ComponentName import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.internal.R import com.android.wm.shell.ShellTestCase import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask import org.junit.Assert.assertFalse Loading @@ -34,26 +36,55 @@ import org.junit.runner.RunWith @RunWith(AndroidTestingRunner::class) @SmallTest class AppCompatUtilsTest : ShellTestCase() { @Test fun testIsSingleTopActivityTranslucent() { assertTrue(isSingleTopActivityTranslucent( fun testIsTopActivityExemptFromDesktopWindowing_topActivityTransparent() { assertTrue(isTopActivityExemptFromDesktopWindowing(mContext, createFreeformTask(/* displayId */ 0) .apply { isTopActivityTransparent = true numActivities = 1 })) assertFalse(isSingleTopActivityTranslucent( assertFalse(isTopActivityExemptFromDesktopWindowing(mContext, createFreeformTask(/* displayId */ 0) .apply { isTopActivityTransparent = true numActivities = 0 })) assertFalse(isSingleTopActivityTranslucent( } @Test fun testIsTopActivityExemptFromDesktopWindowing_singleTopActivity() { assertTrue(isTopActivityExemptFromDesktopWindowing(mContext, createFreeformTask(/* displayId */ 0) .apply { isTopActivityTransparent = true numActivities = 1 })) assertFalse(isTopActivityExemptFromDesktopWindowing(mContext, createFreeformTask(/* displayId */ 0) .apply { isTopActivityTransparent = false numActivities = 1 })) } @Test fun testIsTopActivityExemptFromDesktopWindowing__topActivityStyleFloating() { assertFalse(isTopActivityExemptFromDesktopWindowing(mContext, createFreeformTask(/* displayId */ 0) .apply { isTopActivityStyleFloating = true })) } @Test fun testIsTopActivityExemptFromDesktopWindowing_systemUiTask() { val systemUIPackageName = context.resources.getString(R.string.config_systemUi) val baseComponent = ComponentName(systemUIPackageName, /* class */ "") assertTrue(isTopActivityExemptFromDesktopWindowing(mContext, createFreeformTask(/* displayId */ 0) .apply { baseActivity = baseComponent })) } } Loading
core/java/android/app/TaskInfo.java +10 −0 Original line number Diff line number Diff line Loading @@ -296,6 +296,12 @@ public class TaskInfo { */ public boolean isTopActivityTransparent; /** * Whether the top activity has specified style floating. * @hide */ public boolean isTopActivityStyleFloating; /** * Encapsulate specific App Compat information. * @hide Loading Loading @@ -429,6 +435,7 @@ public class TaskInfo { && parentTaskId == that.parentTaskId && Objects.equals(topActivity, that.topActivity) && isTopActivityTransparent == that.isTopActivityTransparent && isTopActivityStyleFloating == that.isTopActivityStyleFloating && appCompatTaskInfo.equalsForTaskOrganizer(that.appCompatTaskInfo); } Loading Loading @@ -498,6 +505,7 @@ public class TaskInfo { mTopActivityLocusId = source.readTypedObject(LocusId.CREATOR); displayAreaFeatureId = source.readInt(); isTopActivityTransparent = source.readBoolean(); isTopActivityStyleFloating = source.readBoolean(); appCompatTaskInfo = source.readTypedObject(AppCompatTaskInfo.CREATOR); } Loading Loading @@ -545,6 +553,7 @@ public class TaskInfo { dest.writeTypedObject(mTopActivityLocusId, flags); dest.writeInt(displayAreaFeatureId); dest.writeBoolean(isTopActivityTransparent); dest.writeBoolean(isTopActivityStyleFloating); dest.writeTypedObject(appCompatTaskInfo, flags); } Loading Loading @@ -582,6 +591,7 @@ public class TaskInfo { + " locusId=" + mTopActivityLocusId + " displayAreaFeatureId=" + displayAreaFeatureId + " isTopActivityTransparent=" + isTopActivityTransparent + " isTopActivityStyleFloating=" + isTopActivityStyleFloating + " appCompatTaskInfo=" + appCompatTaskInfo + "}"; } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/compatui/AppCompatUtils.kt +12 −2 Original line number Diff line number Diff line Loading @@ -19,6 +19,16 @@ package com.android.wm.shell.compatui import android.app.TaskInfo fun isSingleTopActivityTranslucent(task: TaskInfo) = task.isTopActivityTransparent && task.numActivities == 1 import android.content.Context import com.android.internal.R // TODO(b/347289970): Consider replacing with API fun isTopActivityExemptFromDesktopWindowing(context: Context, task: TaskInfo) = isSystemUiTask(context, task) || (task.isTopActivityTransparent && task.numActivities == 1 && !task.isTopActivityStyleFloating) private fun isSystemUiTask(context: Context, task: TaskInfo): Boolean { val sysUiPackageName: String = context.resources.getString(R.string.config_systemUi) return task.baseActivity?.packageName == sysUiPackageName }
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +9 −25 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT import com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT import com.android.wm.shell.compatui.isSingleTopActivityTranslucent import com.android.wm.shell.compatui.isTopActivityExemptFromDesktopWindowing import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksListener import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler.DragToDesktopStateListener import com.android.wm.shell.draganddrop.DragAndDropController Loading Loading @@ -158,8 +158,6 @@ class DesktopTasksController( visualIndicator = null } } private val sysUIPackageName = context.resources.getString( com.android.internal.R.string.config_systemUi) private val transitionAreaHeight get() = Loading Loading @@ -219,11 +217,6 @@ class DesktopTasksController( return visualIndicator } // TODO(b/347289970): Consider replacing with API private fun isSystemUIApplication(taskInfo: RunningTaskInfo): Boolean { return taskInfo.baseActivity?.packageName == sysUIPackageName } fun setOnTaskResizeAnimationListener(listener: OnTaskResizeAnimationListener) { toggleResizeDesktopTaskTransitionHandler.setOnTaskResizeAnimationListener(listener) enterDesktopTaskTransitionHandler.setOnTaskResizeAnimationListener(listener) Loading Loading @@ -351,19 +344,12 @@ class DesktopTasksController( wct: WindowContainerTransaction = WindowContainerTransaction(), transitionSource: DesktopModeTransitionSource, ) { if (Flags.enableDesktopWindowingModalsPolicy() && isSingleTopActivityTranslucent(task)) { KtProtoLog.w( WM_SHELL_DESKTOP_MODE, "DesktopTasksController: Cannot enter desktop, " + "translucent top activity found. This is likely a modal dialog." ) return } if (isSystemUIApplication(task)) { if (Flags.enableDesktopWindowingModalsPolicy() && isTopActivityExemptFromDesktopWindowing(context, task)) { KtProtoLog.w( WM_SHELL_DESKTOP_MODE, "DesktopTasksController: Cannot enter desktop, " + "systemUI top activity found." "ineligible top activity found." ) return } Loading Loading @@ -942,10 +928,8 @@ class DesktopTasksController( when { // Check if the closing task needs to be handled TransitionUtil.isClosingType(request.type) -> handleTaskClosing(task) // Check if the task has a top transparent activity shouldLaunchAsModal(task) -> handleIncompatibleTaskLaunch(task) // Check if the task has a top systemUI activity isSystemUIApplication(task) -> handleIncompatibleTaskLaunch(task) // Check if the top task shouldn't be allowed to enter desktop mode isIncompatibleTask(task) -> handleIncompatibleTaskLaunch(task) // Check if fullscreen task should be updated task.isFullscreen -> handleFullscreenTaskLaunch(task, transition) // Check if freeform task should be updated Loading Loading @@ -979,9 +963,9 @@ class DesktopTasksController( .forEach { finishTransaction.setCornerRadius(it.leash, cornerRadius) } } // TODO(b/347289970): Consider replacing with API private fun shouldLaunchAsModal(task: TaskInfo) = Flags.enableDesktopWindowingModalsPolicy() && isSingleTopActivityTranslucent(task) private fun isIncompatibleTask(task: TaskInfo) = Flags.enableDesktopWindowingModalsPolicy() && isTopActivityExemptFromDesktopWindowing(context, task) private fun shouldHandleTaskClosing(request: TransitionRequestInfo): Boolean { return Flags.enableDesktopWindowingWallpaperActivity() && Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +2 −15 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ import static android.view.WindowInsets.Type.statusBars; import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT; import static com.android.wm.shell.compatui.AppCompatUtils.isSingleTopActivityTranslucent; import static com.android.wm.shell.compatui.AppCompatUtils.isTopActivityExemptFromDesktopWindowing; import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; Loading Loading @@ -105,7 +105,6 @@ import com.android.wm.shell.windowdecor.extension.TaskInfoKt; import com.android.wm.shell.windowdecor.viewholder.AppHeaderViewHolder; import java.io.PrintWriter; import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; Loading Loading @@ -1034,12 +1033,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { && taskInfo.isFocused) { return false; } // TODO(b/347289970): Consider replacing with API if (Flags.enableDesktopWindowingModalsPolicy() && isSingleTopActivityTranslucent(taskInfo)) { return false; } if (isSystemUIApplication(taskInfo)) { && isTopActivityExemptFromDesktopWindowing(mContext, taskInfo)) { return false; } return DesktopModeStatus.canEnterDesktopMode(mContext) Loading Loading @@ -1118,14 +1113,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { && mSplitScreenController.isTaskInSplitScreen(taskId); } // TODO(b/347289970): Consider replacing with API private boolean isSystemUIApplication(RunningTaskInfo taskInfo) { if (taskInfo.baseActivity != null) { return (Objects.equals(taskInfo.baseActivity.getPackageName(), mSysUIPackageName)); } return false; } private void dump(PrintWriter pw, String prefix) { final String innerPrefix = prefix + " "; pw.println(prefix + "DesktopModeWindowDecorViewModel"); Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/AppCompatUtilsTest.kt +37 −6 Original line number Diff line number Diff line Loading @@ -16,8 +16,10 @@ package com.android.wm.shell.compatui import android.content.ComponentName import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.internal.R import com.android.wm.shell.ShellTestCase import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask import org.junit.Assert.assertFalse Loading @@ -34,26 +36,55 @@ import org.junit.runner.RunWith @RunWith(AndroidTestingRunner::class) @SmallTest class AppCompatUtilsTest : ShellTestCase() { @Test fun testIsSingleTopActivityTranslucent() { assertTrue(isSingleTopActivityTranslucent( fun testIsTopActivityExemptFromDesktopWindowing_topActivityTransparent() { assertTrue(isTopActivityExemptFromDesktopWindowing(mContext, createFreeformTask(/* displayId */ 0) .apply { isTopActivityTransparent = true numActivities = 1 })) assertFalse(isSingleTopActivityTranslucent( assertFalse(isTopActivityExemptFromDesktopWindowing(mContext, createFreeformTask(/* displayId */ 0) .apply { isTopActivityTransparent = true numActivities = 0 })) assertFalse(isSingleTopActivityTranslucent( } @Test fun testIsTopActivityExemptFromDesktopWindowing_singleTopActivity() { assertTrue(isTopActivityExemptFromDesktopWindowing(mContext, createFreeformTask(/* displayId */ 0) .apply { isTopActivityTransparent = true numActivities = 1 })) assertFalse(isTopActivityExemptFromDesktopWindowing(mContext, createFreeformTask(/* displayId */ 0) .apply { isTopActivityTransparent = false numActivities = 1 })) } @Test fun testIsTopActivityExemptFromDesktopWindowing__topActivityStyleFloating() { assertFalse(isTopActivityExemptFromDesktopWindowing(mContext, createFreeformTask(/* displayId */ 0) .apply { isTopActivityStyleFloating = true })) } @Test fun testIsTopActivityExemptFromDesktopWindowing_systemUiTask() { val systemUIPackageName = context.resources.getString(R.string.config_systemUi) val baseComponent = ComponentName(systemUIPackageName, /* class */ "") assertTrue(isTopActivityExemptFromDesktopWindowing(mContext, createFreeformTask(/* displayId */ 0) .apply { baseActivity = baseComponent })) } }