Store desktop tasks per display id
Store active and visible tasks per display id. When notifying the listener of changes, include the display id. Adding support to controllers to bring only tasks to front from current display when switching a task to freeform. Using tasks display id when deciding if a fullscreen task should switch to freeform on launch or if freeform should switch to fullscreen. TODO: - add display id to show desktop calls - update sysui state when tasks are shown/hidden on other displays (currently only default display is supported) - tests for desktop mode proto 1 Bug: 278084491 Test: atest DesktopModeTaskRepositoryTest DesktopTasksControllerTest DesktopModeControllerTest Change-Id: I6ebdc4c9b444c22bf7fe58ce82f8db6544fac5e5
This commit is contained in:
@@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.WindowManager.TRANSIT_CHANGE;
|
||||
import static android.view.WindowManager.TRANSIT_NONE;
|
||||
import static android.view.WindowManager.TRANSIT_OPEN;
|
||||
@@ -264,10 +265,10 @@ public class DesktopModeController implements RemoteCallable<DesktopModeControll
|
||||
/**
|
||||
* Show apps on desktop
|
||||
*/
|
||||
void showDesktopApps() {
|
||||
void showDesktopApps(int displayId) {
|
||||
// Bring apps to front, ignoring their visibility status to always ensure they are on top.
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
bringDesktopAppsToFront(wct);
|
||||
bringDesktopAppsToFront(displayId, wct);
|
||||
|
||||
if (!wct.isEmpty()) {
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||
@@ -280,12 +281,12 @@ public class DesktopModeController implements RemoteCallable<DesktopModeControll
|
||||
}
|
||||
|
||||
/** Get number of tasks that are marked as visible */
|
||||
int getVisibleTaskCount() {
|
||||
return mDesktopModeTaskRepository.getVisibleTaskCount();
|
||||
int getVisibleTaskCount(int displayId) {
|
||||
return mDesktopModeTaskRepository.getVisibleTaskCount(displayId);
|
||||
}
|
||||
|
||||
private void bringDesktopAppsToFront(WindowContainerTransaction wct) {
|
||||
final ArraySet<Integer> activeTasks = mDesktopModeTaskRepository.getActiveTasks();
|
||||
private void bringDesktopAppsToFront(int displayId, WindowContainerTransaction wct) {
|
||||
final ArraySet<Integer> activeTasks = mDesktopModeTaskRepository.getActiveTasks(displayId);
|
||||
ProtoLog.d(WM_SHELL_DESKTOP_MODE, "bringDesktopAppsToFront: tasks=%s", activeTasks.size());
|
||||
|
||||
final List<RunningTaskInfo> taskInfos = new ArrayList<>();
|
||||
@@ -386,6 +387,7 @@ public class DesktopModeController implements RemoteCallable<DesktopModeControll
|
||||
@Override
|
||||
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
|
||||
@NonNull TransitionRequestInfo request) {
|
||||
RunningTaskInfo triggerTask = request.getTriggerTask();
|
||||
// Only do anything if we are in desktop mode and opening/moving-to-front a task/app in
|
||||
// freeform
|
||||
if (!DesktopModeStatus.isActive(mContext)) {
|
||||
@@ -399,16 +401,15 @@ public class DesktopModeController implements RemoteCallable<DesktopModeControll
|
||||
WindowManager.transitTypeToString(request.getType()));
|
||||
return null;
|
||||
}
|
||||
if (request.getTriggerTask() == null
|
||||
|| request.getTriggerTask().getWindowingMode() != WINDOWING_MODE_FREEFORM) {
|
||||
if (triggerTask == null || triggerTask.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
|
||||
ProtoLog.d(WM_SHELL_DESKTOP_MODE, "skip shell transition request: not freeform task");
|
||||
return null;
|
||||
}
|
||||
ProtoLog.d(WM_SHELL_DESKTOP_MODE, "handle shell transition request: %s", request);
|
||||
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
bringDesktopAppsToFront(wct);
|
||||
wct.reorder(request.getTriggerTask().token, true /* onTop */);
|
||||
bringDesktopAppsToFront(triggerTask.displayId, wct);
|
||||
wct.reorder(triggerTask.token, true /* onTop */);
|
||||
|
||||
return wct;
|
||||
}
|
||||
@@ -493,16 +494,18 @@ public class DesktopModeController implements RemoteCallable<DesktopModeControll
|
||||
mController = null;
|
||||
}
|
||||
|
||||
// TODO(b/278084491): pass in display id
|
||||
public void showDesktopApps() {
|
||||
executeRemoteCallWithTaskPermission(mController, "showDesktopApps",
|
||||
DesktopModeController::showDesktopApps);
|
||||
controller -> controller.showDesktopApps(DEFAULT_DISPLAY));
|
||||
}
|
||||
|
||||
// TODO(b/278084491): pass in display id
|
||||
@Override
|
||||
public int getVisibleTaskCount() throws RemoteException {
|
||||
int[] result = new int[1];
|
||||
executeRemoteCallWithTaskPermission(mController, "getVisibleTaskCount",
|
||||
controller -> result[0] = controller.getVisibleTaskCount(),
|
||||
controller -> result[0] = controller.getVisibleTaskCount(DEFAULT_DISPLAY),
|
||||
true /* blocking */
|
||||
);
|
||||
return result[0];
|
||||
|
||||
@@ -20,6 +20,8 @@ import android.graphics.Region
|
||||
import android.util.ArrayMap
|
||||
import android.util.ArraySet
|
||||
import android.util.SparseArray
|
||||
import androidx.core.util.forEach
|
||||
import androidx.core.util.keyIterator
|
||||
import androidx.core.util.valueIterator
|
||||
import java.util.concurrent.Executor
|
||||
import java.util.function.Consumer
|
||||
@@ -29,14 +31,18 @@ import java.util.function.Consumer
|
||||
*/
|
||||
class DesktopModeTaskRepository {
|
||||
|
||||
/**
|
||||
* Set of task ids that are marked as active in desktop mode.
|
||||
* Active tasks in desktop mode are freeform tasks that are visible or have been visible after
|
||||
* desktop mode was activated.
|
||||
* Task gets removed from this list when it vanishes. Or when desktop mode is turned off.
|
||||
*/
|
||||
private val activeTasks = ArraySet<Int>()
|
||||
private val visibleTasks = ArraySet<Int>()
|
||||
/** Task data that is tracked per display */
|
||||
private data class DisplayData(
|
||||
/**
|
||||
* Set of task ids that are marked as active in desktop mode. Active tasks in desktop mode
|
||||
* are freeform tasks that are visible or have been visible after desktop mode was
|
||||
* activated. Task gets removed from this list when it vanishes. Or when desktop mode is
|
||||
* turned off.
|
||||
*/
|
||||
val activeTasks: ArraySet<Int> = ArraySet(),
|
||||
val visibleTasks: ArraySet<Int> = ArraySet(),
|
||||
)
|
||||
|
||||
// Tasks currently in freeform mode, ordered from top to bottom (top is at index 0).
|
||||
private val freeformTasksInZOrder = mutableListOf<Int>()
|
||||
private val activeTasksListeners = ArraySet<ActiveTasksListener>()
|
||||
@@ -47,9 +53,22 @@ class DesktopModeTaskRepository {
|
||||
private var desktopGestureExclusionListener: Consumer<Region>? = null
|
||||
private var desktopGestureExclusionExecutor: Executor? = null
|
||||
|
||||
/**
|
||||
* Add a [ActiveTasksListener] to be notified of updates to active tasks in the repository.
|
||||
*/
|
||||
private val displayData =
|
||||
object : SparseArray<DisplayData>() {
|
||||
/**
|
||||
* Get the [DisplayData] associated with this [displayId]
|
||||
*
|
||||
* Creates a new instance if one does not exist
|
||||
*/
|
||||
fun getOrCreate(displayId: Int): DisplayData {
|
||||
if (!contains(displayId)) {
|
||||
put(displayId, DisplayData())
|
||||
}
|
||||
return get(displayId)
|
||||
}
|
||||
}
|
||||
|
||||
/** Add a [ActiveTasksListener] to be notified of updates to active tasks in the repository. */
|
||||
fun addActiveTaskListener(activeTasksListener: ActiveTasksListener) {
|
||||
activeTasksListeners.add(activeTasksListener)
|
||||
}
|
||||
@@ -57,10 +76,17 @@ class DesktopModeTaskRepository {
|
||||
/**
|
||||
* Add a [VisibleTasksListener] to be notified when freeform tasks are visible or not.
|
||||
*/
|
||||
fun addVisibleTasksListener(visibleTasksListener: VisibleTasksListener, executor: Executor) {
|
||||
visibleTasksListeners.put(visibleTasksListener, executor)
|
||||
executor.execute(
|
||||
Runnable { visibleTasksListener.onVisibilityChanged(visibleTasks.size > 0) })
|
||||
fun addVisibleTasksListener(
|
||||
visibleTasksListener: VisibleTasksListener,
|
||||
executor: Executor
|
||||
) {
|
||||
visibleTasksListeners[visibleTasksListener] = executor
|
||||
displayData.keyIterator().forEach { displayId ->
|
||||
val visibleTasks = getVisibleTaskCount(displayId)
|
||||
executor.execute {
|
||||
visibleTasksListener.onVisibilityChanged(displayId, visibleTasks > 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,14 +126,21 @@ class DesktopModeTaskRepository {
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a task with given [taskId] as active.
|
||||
* Mark a task with given [taskId] as active on given [displayId]
|
||||
*
|
||||
* @return `true` if the task was not active
|
||||
* @return `true` if the task was not active on given [displayId]
|
||||
*/
|
||||
fun addActiveTask(taskId: Int): Boolean {
|
||||
val added = activeTasks.add(taskId)
|
||||
fun addActiveTask(displayId: Int, taskId: Int): Boolean {
|
||||
// Check if task is active on another display, if so, remove it
|
||||
displayData.forEach { id, data ->
|
||||
if (id != displayId && data.activeTasks.remove(taskId)) {
|
||||
activeTasksListeners.onEach { it.onActiveTasksChanged(id) }
|
||||
}
|
||||
}
|
||||
|
||||
val added = displayData.getOrCreate(displayId).activeTasks.add(taskId)
|
||||
if (added) {
|
||||
activeTasksListeners.onEach { it.onActiveTasksChanged() }
|
||||
activeTasksListeners.onEach { it.onActiveTasksChanged(displayId) }
|
||||
}
|
||||
return added
|
||||
}
|
||||
@@ -118,65 +151,93 @@ class DesktopModeTaskRepository {
|
||||
* @return `true` if the task was active
|
||||
*/
|
||||
fun removeActiveTask(taskId: Int): Boolean {
|
||||
val removed = activeTasks.remove(taskId)
|
||||
if (removed) {
|
||||
activeTasksListeners.onEach { it.onActiveTasksChanged() }
|
||||
var result = false
|
||||
displayData.forEach { displayId, data ->
|
||||
if (data.activeTasks.remove(taskId)) {
|
||||
activeTasksListeners.onEach { it.onActiveTasksChanged(displayId) }
|
||||
result = true
|
||||
}
|
||||
}
|
||||
return removed
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a task with the given [taskId] was marked as an active task
|
||||
*/
|
||||
fun isActiveTask(taskId: Int): Boolean {
|
||||
return activeTasks.contains(taskId)
|
||||
return displayData.valueIterator().asSequence().any { data ->
|
||||
data.activeTasks.contains(taskId)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a task is visible.
|
||||
*/
|
||||
fun isVisibleTask(taskId: Int): Boolean {
|
||||
return visibleTasks.contains(taskId)
|
||||
return displayData.valueIterator().asSequence().any { data ->
|
||||
data.visibleTasks.contains(taskId)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a set of the active tasks
|
||||
* Get a set of the active tasks for given [displayId]
|
||||
*/
|
||||
fun getActiveTasks(): ArraySet<Int> {
|
||||
return ArraySet(activeTasks)
|
||||
fun getActiveTasks(displayId: Int): ArraySet<Int> {
|
||||
return ArraySet(displayData[displayId]?.activeTasks)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of freeform tasks, ordered from top-bottom (top at index 0).
|
||||
*/
|
||||
// TODO(b/278084491): pass in display id
|
||||
fun getFreeformTasksInZOrder(): List<Int> {
|
||||
return freeformTasksInZOrder
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates whether a freeform task with this id is visible or not and notifies listeners.
|
||||
*
|
||||
* If the task was visible on a different display with a different displayId, it is removed from
|
||||
* the set of visible tasks on that display. Listeners will be notified.
|
||||
*/
|
||||
fun updateVisibleFreeformTasks(taskId: Int, visible: Boolean) {
|
||||
val prevCount: Int = visibleTasks.size
|
||||
fun updateVisibleFreeformTasks(displayId: Int, taskId: Int, visible: Boolean) {
|
||||
if (visible) {
|
||||
visibleTasks.add(taskId)
|
||||
} else {
|
||||
visibleTasks.remove(taskId)
|
||||
}
|
||||
if (prevCount == 0 && visibleTasks.size == 1 ||
|
||||
prevCount > 0 && visibleTasks.size == 0) {
|
||||
for ((listener, executor) in visibleTasksListeners) {
|
||||
executor.execute(
|
||||
Runnable { listener.onVisibilityChanged(visibleTasks.size > 0) })
|
||||
// Task is visible. Check if we need to remove it from any other display.
|
||||
val otherDisplays = displayData.keyIterator().asSequence().filter { it != displayId }
|
||||
for (otherDisplayId in otherDisplays) {
|
||||
if (displayData[otherDisplayId].visibleTasks.remove(taskId)) {
|
||||
// Task removed from other display, check if we should notify listeners
|
||||
if (displayData[otherDisplayId].visibleTasks.isEmpty()) {
|
||||
notifyVisibleTaskListeners(otherDisplayId, hasVisibleFreeformTasks = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val prevCount = getVisibleTaskCount(displayId)
|
||||
if (visible) {
|
||||
displayData.getOrCreate(displayId).visibleTasks.add(taskId)
|
||||
} else {
|
||||
displayData[displayId]?.visibleTasks?.remove(taskId)
|
||||
}
|
||||
val newCount = getVisibleTaskCount(displayId)
|
||||
// Check if count changed and if there was no tasks or this is the first task
|
||||
if (prevCount != newCount && (prevCount == 0 || newCount == 0)) {
|
||||
notifyVisibleTaskListeners(displayId, newCount > 0)
|
||||
}
|
||||
}
|
||||
|
||||
private fun notifyVisibleTaskListeners(displayId: Int, hasVisibleFreeformTasks: Boolean) {
|
||||
visibleTasksListeners.forEach { (listener, executor) ->
|
||||
executor.execute { listener.onVisibilityChanged(displayId, hasVisibleFreeformTasks) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of tasks that are marked as visible
|
||||
* Get number of tasks that are marked as visible on given [displayId]
|
||||
*/
|
||||
fun getVisibleTaskCount(): Int {
|
||||
return visibleTasks.size
|
||||
fun getVisibleTaskCount(displayId: Int): Int {
|
||||
return displayData[displayId]?.visibleTasks?.size ?: 0
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,7 +287,7 @@ class DesktopModeTaskRepository {
|
||||
* Called when the active tasks change in desktop mode.
|
||||
*/
|
||||
@JvmDefault
|
||||
fun onActiveTasksChanged() {}
|
||||
fun onActiveTasksChanged(displayId: Int) {}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,6 +298,6 @@ class DesktopModeTaskRepository {
|
||||
* Called when the desktop starts or stops showing freeform tasks.
|
||||
*/
|
||||
@JvmDefault
|
||||
fun onVisibilityChanged(hasVisibleFreeformTasks: Boolean) {}
|
||||
fun onVisibilityChanged(displayId: Int, hasVisibleFreeformTasks: Boolean) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.graphics.Rect
|
||||
import android.graphics.Region
|
||||
import android.os.IBinder
|
||||
import android.os.SystemProperties
|
||||
import android.view.Display.DEFAULT_DISPLAY
|
||||
import android.view.SurfaceControl
|
||||
import android.view.WindowManager.TRANSIT_CHANGE
|
||||
import android.view.WindowManager.TRANSIT_NONE
|
||||
@@ -97,10 +98,11 @@ class DesktopTasksController(
|
||||
}
|
||||
|
||||
/** Show all tasks, that are part of the desktop, on top of launcher */
|
||||
fun showDesktopApps() {
|
||||
fun showDesktopApps(displayId: Int) {
|
||||
ProtoLog.v(WM_SHELL_DESKTOP_MODE, "showDesktopApps")
|
||||
val wct = WindowContainerTransaction()
|
||||
bringDesktopAppsToFront(wct)
|
||||
// TODO(b/278084491): pass in display id
|
||||
bringDesktopAppsToFront(displayId, wct)
|
||||
|
||||
// Execute transaction if there are pending operations
|
||||
if (!wct.isEmpty) {
|
||||
@@ -114,8 +116,8 @@ class DesktopTasksController(
|
||||
}
|
||||
|
||||
/** Get number of tasks that are marked as visible */
|
||||
fun getVisibleTaskCount(): Int {
|
||||
return desktopModeTaskRepository.getVisibleTaskCount()
|
||||
fun getVisibleTaskCount(displayId: Int): Int {
|
||||
return desktopModeTaskRepository.getVisibleTaskCount(displayId)
|
||||
}
|
||||
|
||||
/** Move a task with given `taskId` to desktop */
|
||||
@@ -129,7 +131,7 @@ class DesktopTasksController(
|
||||
|
||||
val wct = WindowContainerTransaction()
|
||||
// Bring other apps to front first
|
||||
bringDesktopAppsToFront(wct)
|
||||
bringDesktopAppsToFront(task.displayId, wct)
|
||||
addMoveToDesktopChanges(wct, task.token)
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||
transitions.startTransition(TRANSIT_CHANGE, wct, null /* handler */)
|
||||
@@ -165,7 +167,7 @@ class DesktopTasksController(
|
||||
freeformBounds: Rect
|
||||
) {
|
||||
val wct = WindowContainerTransaction()
|
||||
bringDesktopAppsToFront(wct)
|
||||
bringDesktopAppsToFront(taskInfo.displayId, wct)
|
||||
addMoveToDesktopChanges(wct, taskInfo.getToken())
|
||||
wct.setBounds(taskInfo.token, freeformBounds)
|
||||
|
||||
@@ -244,9 +246,9 @@ class DesktopTasksController(
|
||||
?: WINDOWING_MODE_UNDEFINED
|
||||
}
|
||||
|
||||
private fun bringDesktopAppsToFront(wct: WindowContainerTransaction) {
|
||||
private fun bringDesktopAppsToFront(displayId: Int, wct: WindowContainerTransaction) {
|
||||
ProtoLog.v(WM_SHELL_DESKTOP_MODE, "bringDesktopAppsToFront")
|
||||
val activeTasks = desktopModeTaskRepository.getActiveTasks()
|
||||
val activeTasks = desktopModeTaskRepository.getActiveTasks(displayId)
|
||||
|
||||
// First move home to front and then other tasks on top of it
|
||||
moveHomeTaskToFront(wct)
|
||||
@@ -290,18 +292,17 @@ class DesktopTasksController(
|
||||
request: TransitionRequestInfo
|
||||
): WindowContainerTransaction? {
|
||||
// Check if we should skip handling this transition
|
||||
val task: RunningTaskInfo? = request.triggerTask
|
||||
val shouldHandleRequest =
|
||||
when {
|
||||
// Only handle open or to front transitions
|
||||
request.type != TRANSIT_OPEN && request.type != TRANSIT_TO_FRONT -> false
|
||||
// Only handle when it is a task transition
|
||||
task == null -> false
|
||||
request.triggerTask == null -> false
|
||||
// Only handle standard type tasks
|
||||
task.activityType != ACTIVITY_TYPE_STANDARD -> false
|
||||
request.triggerTask.activityType != ACTIVITY_TYPE_STANDARD -> false
|
||||
// Only handle fullscreen or freeform tasks
|
||||
task.windowingMode != WINDOWING_MODE_FULLSCREEN &&
|
||||
task.windowingMode != WINDOWING_MODE_FREEFORM -> false
|
||||
request.triggerTask.windowingMode != WINDOWING_MODE_FULLSCREEN &&
|
||||
request.triggerTask.windowingMode != WINDOWING_MODE_FREEFORM -> false
|
||||
// Otherwise process it
|
||||
else -> true
|
||||
}
|
||||
@@ -310,10 +311,11 @@ class DesktopTasksController(
|
||||
return null
|
||||
}
|
||||
|
||||
val activeTasks = desktopModeTaskRepository.getActiveTasks()
|
||||
val task: RunningTaskInfo = request.triggerTask
|
||||
val activeTasks = desktopModeTaskRepository.getActiveTasks(task.displayId)
|
||||
|
||||
// Check if we should switch a fullscreen task to freeform
|
||||
if (task?.windowingMode == WINDOWING_MODE_FULLSCREEN) {
|
||||
if (task.windowingMode == WINDOWING_MODE_FULLSCREEN) {
|
||||
// If there are any visible desktop tasks, switch the task to freeform
|
||||
if (activeTasks.any { desktopModeTaskRepository.isVisibleTask(it) }) {
|
||||
ProtoLog.d(
|
||||
@@ -329,7 +331,7 @@ class DesktopTasksController(
|
||||
}
|
||||
|
||||
// CHeck if we should switch a freeform task to fullscreen
|
||||
if (task?.windowingMode == WINDOWING_MODE_FREEFORM) {
|
||||
if (task.windowingMode == WINDOWING_MODE_FREEFORM) {
|
||||
// If no visible desktop tasks, switch this task to freeform as the transition came
|
||||
// outside of this controller
|
||||
if (activeTasks.none { desktopModeTaskRepository.isVisibleTask(it) }) {
|
||||
@@ -559,20 +561,21 @@ class DesktopTasksController(
|
||||
controller = null
|
||||
}
|
||||
|
||||
// TODO(b/278084491): pass in display id
|
||||
override fun showDesktopApps() {
|
||||
ExecutorUtils.executeRemoteCallWithTaskPermission(
|
||||
controller,
|
||||
"showDesktopApps",
|
||||
Consumer(DesktopTasksController::showDesktopApps)
|
||||
)
|
||||
"showDesktopApps"
|
||||
) { c -> c.showDesktopApps(DEFAULT_DISPLAY) }
|
||||
}
|
||||
|
||||
// TODO(b/278084491): pass in display id
|
||||
override fun getVisibleTaskCount(): Int {
|
||||
val result = IntArray(1)
|
||||
ExecutorUtils.executeRemoteCallWithTaskPermission(
|
||||
controller,
|
||||
"getVisibleTaskCount",
|
||||
{ controller -> result[0] = controller.getVisibleTaskCount() },
|
||||
{ controller -> result[0] = controller.getVisibleTaskCount(DEFAULT_DISPLAY) },
|
||||
true /* blocking */
|
||||
)
|
||||
return result[0]
|
||||
|
||||
@@ -94,11 +94,12 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
|
||||
mDesktopModeTaskRepository.ifPresent(repository -> {
|
||||
repository.addOrMoveFreeformTaskToTop(taskInfo.taskId);
|
||||
if (taskInfo.isVisible) {
|
||||
if (repository.addActiveTask(taskInfo.taskId)) {
|
||||
if (repository.addActiveTask(taskInfo.displayId, taskInfo.taskId)) {
|
||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
|
||||
"Adding active freeform task: #%d", taskInfo.taskId);
|
||||
}
|
||||
repository.updateVisibleFreeformTasks(taskInfo.taskId, true);
|
||||
repository.updateVisibleFreeformTasks(taskInfo.displayId, taskInfo.taskId,
|
||||
true);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -117,7 +118,7 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
|
||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
|
||||
"Removing active freeform task: #%d", taskInfo.taskId);
|
||||
}
|
||||
repository.updateVisibleFreeformTasks(taskInfo.taskId, false);
|
||||
repository.updateVisibleFreeformTasks(taskInfo.displayId, taskInfo.taskId, false);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -137,12 +138,13 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener,
|
||||
if (DesktopModeStatus.isAnyEnabled()) {
|
||||
mDesktopModeTaskRepository.ifPresent(repository -> {
|
||||
if (taskInfo.isVisible) {
|
||||
if (repository.addActiveTask(taskInfo.taskId)) {
|
||||
if (repository.addActiveTask(taskInfo.displayId, taskInfo.taskId)) {
|
||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
|
||||
"Adding active freeform task: #%d", taskInfo.taskId);
|
||||
}
|
||||
}
|
||||
repository.updateVisibleFreeformTasks(taskInfo.taskId, taskInfo.isVisible);
|
||||
repository.updateVisibleFreeformTasks(taskInfo.displayId, taskInfo.taskId,
|
||||
taskInfo.isVisible);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ public class RecentTasksController implements TaskStackListenerCallback,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActiveTasksChanged() {
|
||||
public void onActiveTasksChanged(int displayId) {
|
||||
notifyRecentTasksChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
||||
import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.WindowManager.TRANSIT_CHANGE;
|
||||
import static android.view.WindowManager.TRANSIT_CLOSE;
|
||||
import static android.view.WindowManager.TRANSIT_NONE;
|
||||
@@ -82,6 +83,8 @@ import java.util.Arrays;
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class DesktopModeControllerTest extends ShellTestCase {
|
||||
|
||||
private static final int SECOND_DISPLAY = 2;
|
||||
|
||||
@Mock
|
||||
private ShellController mShellController;
|
||||
@Mock
|
||||
@@ -248,22 +251,22 @@ public class DesktopModeControllerTest extends ShellTestCase {
|
||||
public void testShowDesktopApps_allAppsInvisible_bringsToFront() {
|
||||
// Set up two active tasks on desktop, task2 is on top of task1.
|
||||
RunningTaskInfo freeformTask1 = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(freeformTask1.taskId);
|
||||
mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, freeformTask1.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(freeformTask1.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(
|
||||
freeformTask1.taskId, false /* visible */);
|
||||
DEFAULT_DISPLAY, freeformTask1.taskId, false /* visible */);
|
||||
RunningTaskInfo freeformTask2 = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(freeformTask2.taskId);
|
||||
mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, freeformTask2.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(freeformTask2.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(
|
||||
freeformTask2.taskId, false /* visible */);
|
||||
DEFAULT_DISPLAY, freeformTask2.taskId, false /* visible */);
|
||||
when(mShellTaskOrganizer.getRunningTaskInfo(freeformTask1.taskId)).thenReturn(
|
||||
freeformTask1);
|
||||
when(mShellTaskOrganizer.getRunningTaskInfo(freeformTask2.taskId)).thenReturn(
|
||||
freeformTask2);
|
||||
|
||||
// Run show desktop apps logic
|
||||
mController.showDesktopApps();
|
||||
mController.showDesktopApps(DEFAULT_DISPLAY);
|
||||
|
||||
final WindowContainerTransaction wct = getBringAppsToFrontTransaction();
|
||||
// Check wct has reorder calls
|
||||
@@ -283,17 +286,19 @@ public class DesktopModeControllerTest extends ShellTestCase {
|
||||
@Test
|
||||
public void testShowDesktopApps_appsAlreadyVisible_bringsToFront() {
|
||||
final RunningTaskInfo task1 = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(task1.taskId);
|
||||
mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task1.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task1.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(task1.taskId, true /* visible */);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task1.taskId,
|
||||
true /* visible */);
|
||||
when(mShellTaskOrganizer.getRunningTaskInfo(task1.taskId)).thenReturn(task1);
|
||||
final RunningTaskInfo task2 = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(task2.taskId);
|
||||
mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task2.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task2.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(task2.taskId, true /* visible */);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task2.taskId,
|
||||
true /* visible */);
|
||||
when(mShellTaskOrganizer.getRunningTaskInfo(task2.taskId)).thenReturn(task2);
|
||||
|
||||
mController.showDesktopApps();
|
||||
mController.showDesktopApps(DEFAULT_DISPLAY);
|
||||
|
||||
final WindowContainerTransaction wct = getBringAppsToFrontTransaction();
|
||||
// Check wct has reorder calls
|
||||
@@ -312,17 +317,19 @@ public class DesktopModeControllerTest extends ShellTestCase {
|
||||
@Test
|
||||
public void testShowDesktopApps_someAppsInvisible_reordersAll() {
|
||||
final RunningTaskInfo task1 = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(task1.taskId);
|
||||
mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task1.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task1.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(task1.taskId, false /* visible */);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task1.taskId,
|
||||
false /* visible */);
|
||||
when(mShellTaskOrganizer.getRunningTaskInfo(task1.taskId)).thenReturn(task1);
|
||||
final RunningTaskInfo task2 = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(task2.taskId);
|
||||
mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task2.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task2.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(task2.taskId, true /* visible */);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task2.taskId,
|
||||
true /* visible */);
|
||||
when(mShellTaskOrganizer.getRunningTaskInfo(task2.taskId)).thenReturn(task2);
|
||||
|
||||
mController.showDesktopApps();
|
||||
mController.showDesktopApps(DEFAULT_DISPLAY);
|
||||
|
||||
final WindowContainerTransaction wct = getBringAppsToFrontTransaction();
|
||||
// Both tasks should be reordered to top, even if one was already visible.
|
||||
@@ -335,39 +342,88 @@ public class DesktopModeControllerTest extends ShellTestCase {
|
||||
assertThat(op2.getContainer()).isEqualTo(task2.token.asBinder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowDesktopApps_twoDisplays_bringsToFrontOnlyOneDisplay() {
|
||||
RunningTaskInfo taskDefaultDisplay = createFreeformTask(DEFAULT_DISPLAY);
|
||||
mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, taskDefaultDisplay.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(taskDefaultDisplay.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(
|
||||
DEFAULT_DISPLAY, taskDefaultDisplay.taskId, false /* visible */);
|
||||
when(mShellTaskOrganizer.getRunningTaskInfo(taskDefaultDisplay.taskId)).thenReturn(
|
||||
taskDefaultDisplay);
|
||||
|
||||
RunningTaskInfo taskSecondDisplay = createFreeformTask(SECOND_DISPLAY);
|
||||
mDesktopModeTaskRepository.addActiveTask(SECOND_DISPLAY, taskSecondDisplay.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(taskSecondDisplay.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(
|
||||
SECOND_DISPLAY, taskSecondDisplay.taskId, false /* visible */);
|
||||
when(mShellTaskOrganizer.getRunningTaskInfo(taskSecondDisplay.taskId)).thenReturn(
|
||||
taskSecondDisplay);
|
||||
|
||||
mController.showDesktopApps(DEFAULT_DISPLAY);
|
||||
|
||||
WindowContainerTransaction wct = getBringAppsToFrontTransaction();
|
||||
assertThat(wct.getHierarchyOps()).hasSize(1);
|
||||
HierarchyOp op = wct.getHierarchyOps().get(0);
|
||||
assertThat(op.getContainer()).isEqualTo(taskDefaultDisplay.token.asBinder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVisibleTaskCount_noTasks_returnsZero() {
|
||||
assertThat(mController.getVisibleTaskCount()).isEqualTo(0);
|
||||
assertThat(mController.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVisibleTaskCount_twoTasks_bothVisible_returnsTwo() {
|
||||
RunningTaskInfo task1 = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(task1.taskId);
|
||||
mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task1.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task1.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(task1.taskId, true /* visible */);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task1.taskId,
|
||||
true /* visible */);
|
||||
|
||||
RunningTaskInfo task2 = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(task2.taskId);
|
||||
mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task2.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task2.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(task2.taskId, true /* visible */);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task2.taskId,
|
||||
true /* visible */);
|
||||
|
||||
assertThat(mController.getVisibleTaskCount()).isEqualTo(2);
|
||||
assertThat(mController.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVisibleTaskCount_twoTasks_oneVisible_returnsOne() {
|
||||
RunningTaskInfo task1 = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(task1.taskId);
|
||||
mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task1.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task1.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(task1.taskId, true /* visible */);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task1.taskId,
|
||||
true /* visible */);
|
||||
|
||||
RunningTaskInfo task2 = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(task2.taskId);
|
||||
mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, task2.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(task2.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(task2.taskId, false /* visible */);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY, task2.taskId,
|
||||
false /* visible */);
|
||||
|
||||
assertThat(mController.getVisibleTaskCount()).isEqualTo(1);
|
||||
assertThat(mController.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetVisibleTaskCount_twoTasksVisibleOnDifferentDisplays_returnsOne() {
|
||||
RunningTaskInfo taskDefaultDisplay = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(DEFAULT_DISPLAY, taskDefaultDisplay.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(taskDefaultDisplay.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(DEFAULT_DISPLAY,
|
||||
taskDefaultDisplay.taskId,
|
||||
true /* visible */);
|
||||
|
||||
RunningTaskInfo taskSecondDisplay = createFreeformTask();
|
||||
mDesktopModeTaskRepository.addActiveTask(SECOND_DISPLAY, taskSecondDisplay.taskId);
|
||||
mDesktopModeTaskRepository.addOrMoveFreeformTaskToTop(taskSecondDisplay.taskId);
|
||||
mDesktopModeTaskRepository.updateVisibleFreeformTasks(SECOND_DISPLAY,
|
||||
taskSecondDisplay.taskId,
|
||||
true /* visible */);
|
||||
|
||||
assertThat(mController.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
package com.android.wm.shell.desktopmode
|
||||
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.view.Display.DEFAULT_DISPLAY
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.wm.shell.ShellTestCase
|
||||
import com.android.wm.shell.TestShellExecutor
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import junit.framework.Assert.fail
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -41,8 +43,8 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() {
|
||||
val listener = TestListener()
|
||||
repo.addActiveTaskListener(listener)
|
||||
|
||||
repo.addActiveTask(1)
|
||||
assertThat(listener.activeTaskChangedCalls).isEqualTo(1)
|
||||
repo.addActiveTask(DEFAULT_DISPLAY, taskId = 1)
|
||||
assertThat(listener.activeChangesOnDefaultDisplay).isEqualTo(1)
|
||||
assertThat(repo.isActiveTask(1)).isTrue()
|
||||
}
|
||||
|
||||
@@ -51,9 +53,9 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() {
|
||||
val listener = TestListener()
|
||||
repo.addActiveTaskListener(listener)
|
||||
|
||||
repo.addActiveTask(1)
|
||||
repo.addActiveTask(1)
|
||||
assertThat(listener.activeTaskChangedCalls).isEqualTo(1)
|
||||
repo.addActiveTask(DEFAULT_DISPLAY, taskId = 1)
|
||||
repo.addActiveTask(DEFAULT_DISPLAY, taskId = 1)
|
||||
assertThat(listener.activeChangesOnDefaultDisplay).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -61,9 +63,22 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() {
|
||||
val listener = TestListener()
|
||||
repo.addActiveTaskListener(listener)
|
||||
|
||||
repo.addActiveTask(1)
|
||||
repo.addActiveTask(2)
|
||||
assertThat(listener.activeTaskChangedCalls).isEqualTo(2)
|
||||
repo.addActiveTask(DEFAULT_DISPLAY, taskId = 1)
|
||||
repo.addActiveTask(DEFAULT_DISPLAY, taskId = 2)
|
||||
assertThat(listener.activeChangesOnDefaultDisplay).isEqualTo(2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addActiveTask_multipleDisplays_notifiesCorrectListener() {
|
||||
val listener = TestListener()
|
||||
repo.addActiveTaskListener(listener)
|
||||
|
||||
repo.addActiveTask(DEFAULT_DISPLAY, taskId = 1)
|
||||
repo.addActiveTask(DEFAULT_DISPLAY, taskId = 2)
|
||||
repo.addActiveTask(SECOND_DISPLAY, taskId = 3)
|
||||
|
||||
assertThat(listener.activeChangesOnDefaultDisplay).isEqualTo(2)
|
||||
assertThat(listener.activeChangesOnSecondaryDisplay).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,10 +86,10 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() {
|
||||
val listener = TestListener()
|
||||
repo.addActiveTaskListener(listener)
|
||||
|
||||
repo.addActiveTask(1)
|
||||
repo.addActiveTask(DEFAULT_DISPLAY, taskId = 1)
|
||||
repo.removeActiveTask(1)
|
||||
// Notify once for add and once for remove
|
||||
assertThat(listener.activeTaskChangedCalls).isEqualTo(2)
|
||||
assertThat(listener.activeChangesOnDefaultDisplay).isEqualTo(2)
|
||||
assertThat(repo.isActiveTask(1)).isFalse()
|
||||
}
|
||||
|
||||
@@ -83,7 +98,17 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() {
|
||||
val listener = TestListener()
|
||||
repo.addActiveTaskListener(listener)
|
||||
repo.removeActiveTask(99)
|
||||
assertThat(listener.activeTaskChangedCalls).isEqualTo(0)
|
||||
assertThat(listener.activeChangesOnDefaultDisplay).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun remoteActiveTask_listenerForOtherDisplayNotNotified() {
|
||||
val listener = TestListener()
|
||||
repo.addActiveTaskListener(listener)
|
||||
repo.addActiveTask(DEFAULT_DISPLAY, taskId = 1)
|
||||
repo.removeActiveTask(1)
|
||||
assertThat(listener.activeChangesOnSecondaryDisplay).isEqualTo(0)
|
||||
assertThat(repo.isActiveTask(1)).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -93,14 +118,27 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() {
|
||||
|
||||
@Test
|
||||
fun addListener_notifiesVisibleFreeformTask() {
|
||||
repo.updateVisibleFreeformTasks(1, true)
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
|
||||
val listener = TestVisibilityListener()
|
||||
val executor = TestShellExecutor()
|
||||
repo.addVisibleTasksListener(listener, executor)
|
||||
executor.flushAll()
|
||||
|
||||
assertThat(listener.hasVisibleFreeformTasks).isTrue()
|
||||
assertThat(listener.visibleFreeformTaskChangedCalls).isEqualTo(1)
|
||||
assertThat(listener.hasVisibleTasksOnDefaultDisplay).isTrue()
|
||||
assertThat(listener.visibleChangesOnDefaultDisplay).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addListener_tasksOnDifferentDisplay_doesNotNotify() {
|
||||
repo.updateVisibleFreeformTasks(SECOND_DISPLAY, taskId = 1, visible = true)
|
||||
val listener = TestVisibilityListener()
|
||||
val executor = TestShellExecutor()
|
||||
repo.addVisibleTasksListener(listener, executor)
|
||||
executor.flushAll()
|
||||
|
||||
assertThat(listener.hasVisibleTasksOnDefaultDisplay).isFalse()
|
||||
// One call as adding listener notifies it
|
||||
assertThat(listener.visibleChangesOnDefaultDisplay).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -108,13 +146,61 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() {
|
||||
val listener = TestVisibilityListener()
|
||||
val executor = TestShellExecutor()
|
||||
repo.addVisibleTasksListener(listener, executor)
|
||||
repo.updateVisibleFreeformTasks(1, true)
|
||||
repo.updateVisibleFreeformTasks(2, true)
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = true)
|
||||
executor.flushAll()
|
||||
|
||||
assertThat(listener.hasVisibleFreeformTasks).isTrue()
|
||||
// Equal to 2 because adding the listener notifies the current state
|
||||
assertThat(listener.visibleFreeformTaskChangedCalls).isEqualTo(2)
|
||||
assertThat(listener.hasVisibleTasksOnDefaultDisplay).isTrue()
|
||||
assertThat(listener.visibleChangesOnDefaultDisplay).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateVisibleFreeformTasks_addVisibleTaskNotifiesListenerForThatDisplay() {
|
||||
val listener = TestVisibilityListener()
|
||||
val executor = TestShellExecutor()
|
||||
repo.addVisibleTasksListener(listener, executor)
|
||||
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
|
||||
executor.flushAll()
|
||||
|
||||
assertThat(listener.hasVisibleTasksOnDefaultDisplay).isTrue()
|
||||
assertThat(listener.visibleChangesOnDefaultDisplay).isEqualTo(1)
|
||||
assertThat(listener.hasVisibleTasksOnSecondaryDisplay).isFalse()
|
||||
assertThat(listener.visibleChangesOnSecondaryDisplay).isEqualTo(0)
|
||||
|
||||
repo.updateVisibleFreeformTasks(displayId = 1, taskId = 2, visible = true)
|
||||
executor.flushAll()
|
||||
|
||||
// Listener for secondary display is notified
|
||||
assertThat(listener.hasVisibleTasksOnSecondaryDisplay).isTrue()
|
||||
assertThat(listener.visibleChangesOnSecondaryDisplay).isEqualTo(1)
|
||||
// No changes to listener for default display
|
||||
assertThat(listener.visibleChangesOnDefaultDisplay).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun updateVisibleFreeformTasks_taskOnDefaultBecomesVisibleOnSecondDisplay_listenersNotified() {
|
||||
val listener = TestVisibilityListener()
|
||||
val executor = TestShellExecutor()
|
||||
repo.addVisibleTasksListener(listener, executor)
|
||||
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
|
||||
executor.flushAll()
|
||||
assertThat(listener.hasVisibleTasksOnDefaultDisplay).isTrue()
|
||||
|
||||
// Mark task 1 visible on secondary display
|
||||
repo.updateVisibleFreeformTasks(displayId = 1, taskId = 1, visible = true)
|
||||
executor.flushAll()
|
||||
|
||||
// Default display should have 2 calls
|
||||
// 1 - visible task added
|
||||
// 2 - visible task removed
|
||||
assertThat(listener.visibleChangesOnDefaultDisplay).isEqualTo(2)
|
||||
assertThat(listener.hasVisibleTasksOnDefaultDisplay).isFalse()
|
||||
|
||||
// Secondary display should have 1 call for visible task added
|
||||
assertThat(listener.visibleChangesOnSecondaryDisplay).isEqualTo(1)
|
||||
assertThat(listener.hasVisibleTasksOnSecondaryDisplay).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -122,52 +208,83 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() {
|
||||
val listener = TestVisibilityListener()
|
||||
val executor = TestShellExecutor()
|
||||
repo.addVisibleTasksListener(listener, executor)
|
||||
repo.updateVisibleFreeformTasks(1, true)
|
||||
repo.updateVisibleFreeformTasks(2, true)
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = true)
|
||||
executor.flushAll()
|
||||
|
||||
assertThat(listener.hasVisibleFreeformTasks).isTrue()
|
||||
repo.updateVisibleFreeformTasks(1, false)
|
||||
assertThat(listener.hasVisibleTasksOnDefaultDisplay).isTrue()
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = false)
|
||||
executor.flushAll()
|
||||
|
||||
// Equal to 2 because adding the listener notifies the current state
|
||||
assertThat(listener.visibleFreeformTaskChangedCalls).isEqualTo(2)
|
||||
assertThat(listener.visibleChangesOnDefaultDisplay).isEqualTo(1)
|
||||
|
||||
repo.updateVisibleFreeformTasks(2, false)
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = false)
|
||||
executor.flushAll()
|
||||
|
||||
assertThat(listener.hasVisibleFreeformTasks).isFalse()
|
||||
assertThat(listener.visibleFreeformTaskChangedCalls).isEqualTo(3)
|
||||
assertThat(listener.hasVisibleTasksOnDefaultDisplay).isFalse()
|
||||
assertThat(listener.visibleChangesOnDefaultDisplay).isEqualTo(2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getVisibleTaskCount() {
|
||||
// No tasks, count is 0
|
||||
assertThat(repo.getVisibleTaskCount()).isEqualTo(0)
|
||||
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0)
|
||||
|
||||
// New task increments count to 1
|
||||
repo.updateVisibleFreeformTasks(taskId = 1, visible = true)
|
||||
assertThat(repo.getVisibleTaskCount()).isEqualTo(1)
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
|
||||
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1)
|
||||
|
||||
// Visibility update to same task does not increase count
|
||||
repo.updateVisibleFreeformTasks(taskId = 1, visible = true)
|
||||
assertThat(repo.getVisibleTaskCount()).isEqualTo(1)
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
|
||||
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1)
|
||||
|
||||
// Second task visible increments count
|
||||
repo.updateVisibleFreeformTasks(taskId = 2, visible = true)
|
||||
assertThat(repo.getVisibleTaskCount()).isEqualTo(2)
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = true)
|
||||
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(2)
|
||||
|
||||
// Hiding a task decrements count
|
||||
repo.updateVisibleFreeformTasks(taskId = 1, visible = false)
|
||||
assertThat(repo.getVisibleTaskCount()).isEqualTo(1)
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = false)
|
||||
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1)
|
||||
|
||||
// Hiding all tasks leaves count at 0
|
||||
repo.updateVisibleFreeformTasks(taskId = 2, visible = false)
|
||||
assertThat(repo.getVisibleTaskCount()).isEqualTo(0)
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 2, visible = false)
|
||||
assertThat(repo.getVisibleTaskCount(displayId = 9)).isEqualTo(0)
|
||||
|
||||
// Hiding a not existing task, count remains at 0
|
||||
repo.updateVisibleFreeformTasks(taskId = 999, visible = false)
|
||||
assertThat(repo.getVisibleTaskCount()).isEqualTo(0)
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 999, visible = false)
|
||||
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getVisibleTaskCount_multipleDisplays() {
|
||||
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0)
|
||||
assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(0)
|
||||
|
||||
// New task on default display increments count for that display only
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = true)
|
||||
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1)
|
||||
assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(0)
|
||||
|
||||
// New task on secondary display, increments count for that display only
|
||||
repo.updateVisibleFreeformTasks(SECOND_DISPLAY, taskId = 2, visible = true)
|
||||
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1)
|
||||
assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(1)
|
||||
|
||||
// Marking task visible on another display, updates counts for both displays
|
||||
repo.updateVisibleFreeformTasks(SECOND_DISPLAY, taskId = 1, visible = true)
|
||||
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0)
|
||||
assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(2)
|
||||
|
||||
// Marking task that is on secondary display, hidden on default display, does not affect
|
||||
// secondary display
|
||||
repo.updateVisibleFreeformTasks(DEFAULT_DISPLAY, taskId = 1, visible = false)
|
||||
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0)
|
||||
assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(2)
|
||||
|
||||
// Hiding a task on that display, decrements count
|
||||
repo.updateVisibleFreeformTasks(SECOND_DISPLAY, taskId = 1, visible = false)
|
||||
assertThat(repo.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0)
|
||||
assertThat(repo.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -197,19 +314,40 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() {
|
||||
}
|
||||
|
||||
class TestListener : DesktopModeTaskRepository.ActiveTasksListener {
|
||||
var activeTaskChangedCalls = 0
|
||||
override fun onActiveTasksChanged() {
|
||||
activeTaskChangedCalls++
|
||||
var activeChangesOnDefaultDisplay = 0
|
||||
var activeChangesOnSecondaryDisplay = 0
|
||||
override fun onActiveTasksChanged(displayId: Int) {
|
||||
when (displayId) {
|
||||
DEFAULT_DISPLAY -> activeChangesOnDefaultDisplay++
|
||||
SECOND_DISPLAY -> activeChangesOnSecondaryDisplay++
|
||||
else -> fail("Active task listener received unexpected display id: $displayId")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TestVisibilityListener : DesktopModeTaskRepository.VisibleTasksListener {
|
||||
var hasVisibleFreeformTasks = false
|
||||
var visibleFreeformTaskChangedCalls = 0
|
||||
var hasVisibleTasksOnDefaultDisplay = false
|
||||
var hasVisibleTasksOnSecondaryDisplay = false
|
||||
|
||||
override fun onVisibilityChanged(hasVisibleTasks: Boolean) {
|
||||
hasVisibleFreeformTasks = hasVisibleTasks
|
||||
visibleFreeformTaskChangedCalls++
|
||||
var visibleChangesOnDefaultDisplay = 0
|
||||
var visibleChangesOnSecondaryDisplay = 0
|
||||
|
||||
override fun onVisibilityChanged(displayId: Int, hasVisibleFreeformTasks: Boolean) {
|
||||
when (displayId) {
|
||||
DEFAULT_DISPLAY -> {
|
||||
hasVisibleTasksOnDefaultDisplay = hasVisibleFreeformTasks
|
||||
visibleChangesOnDefaultDisplay++
|
||||
}
|
||||
SECOND_DISPLAY -> {
|
||||
hasVisibleTasksOnSecondaryDisplay = hasVisibleFreeformTasks
|
||||
visibleChangesOnSecondaryDisplay++
|
||||
}
|
||||
else -> fail("Visible task listener received unexpected display id: $displayId")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SECOND_DISPLAY = 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW
|
||||
import android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED
|
||||
import android.os.Binder
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.view.Display.DEFAULT_DISPLAY
|
||||
import android.view.WindowManager
|
||||
import android.view.WindowManager.TRANSIT_CHANGE
|
||||
import android.view.WindowManager.TRANSIT_NONE
|
||||
@@ -84,10 +85,10 @@ class DesktopTasksControllerTest : ShellTestCase() {
|
||||
@Mock lateinit var exitDesktopTransitionHandler: ExitDesktopTaskTransitionHandler
|
||||
@Mock lateinit var enterDesktopTransitionHandler: EnterDesktopTaskTransitionHandler
|
||||
|
||||
lateinit var mockitoSession: StaticMockitoSession
|
||||
lateinit var controller: DesktopTasksController
|
||||
lateinit var shellInit: ShellInit
|
||||
lateinit var desktopModeTaskRepository: DesktopModeTaskRepository
|
||||
private lateinit var mockitoSession: StaticMockitoSession
|
||||
private lateinit var controller: DesktopTasksController
|
||||
private lateinit var shellInit: ShellInit
|
||||
private lateinit var desktopModeTaskRepository: DesktopModeTaskRepository
|
||||
|
||||
// Mock running tasks are registered here so we can get the list from mock shell task organizer
|
||||
private val runningTasks = mutableListOf<RunningTaskInfo>()
|
||||
@@ -155,7 +156,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
|
||||
markTaskHidden(task1)
|
||||
markTaskHidden(task2)
|
||||
|
||||
controller.showDesktopApps()
|
||||
controller.showDesktopApps(DEFAULT_DISPLAY)
|
||||
|
||||
val wct = getLatestWct(expectTransition = TRANSIT_NONE)
|
||||
assertThat(wct.hierarchyOps).hasSize(3)
|
||||
@@ -173,7 +174,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
|
||||
markTaskVisible(task1)
|
||||
markTaskVisible(task2)
|
||||
|
||||
controller.showDesktopApps()
|
||||
controller.showDesktopApps(DEFAULT_DISPLAY)
|
||||
|
||||
val wct = getLatestWct(expectTransition = TRANSIT_NONE)
|
||||
assertThat(wct.hierarchyOps).hasSize(3)
|
||||
@@ -191,7 +192,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
|
||||
markTaskHidden(task1)
|
||||
markTaskVisible(task2)
|
||||
|
||||
controller.showDesktopApps()
|
||||
controller.showDesktopApps(DEFAULT_DISPLAY)
|
||||
|
||||
val wct = getLatestWct(expectTransition = TRANSIT_NONE)
|
||||
assertThat(wct.hierarchyOps).hasSize(3)
|
||||
@@ -205,16 +206,34 @@ class DesktopTasksControllerTest : ShellTestCase() {
|
||||
fun showDesktopApps_noActiveTasks_reorderHomeToTop() {
|
||||
val homeTask = setUpHomeTask()
|
||||
|
||||
controller.showDesktopApps()
|
||||
controller.showDesktopApps(DEFAULT_DISPLAY)
|
||||
|
||||
val wct = getLatestWct(expectTransition = TRANSIT_NONE)
|
||||
assertThat(wct.hierarchyOps).hasSize(1)
|
||||
wct.assertReorderAt(index = 0, homeTask)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun showDesktopApps_twoDisplays_bringsToFrontOnlyOneDisplay() {
|
||||
val homeTaskDefaultDisplay = setUpHomeTask(DEFAULT_DISPLAY)
|
||||
val taskDefaultDisplay = setUpFreeformTask(DEFAULT_DISPLAY)
|
||||
setUpHomeTask(SECOND_DISPLAY)
|
||||
val taskSecondDisplay = setUpFreeformTask(SECOND_DISPLAY)
|
||||
markTaskHidden(taskDefaultDisplay)
|
||||
markTaskHidden(taskSecondDisplay)
|
||||
|
||||
controller.showDesktopApps(DEFAULT_DISPLAY)
|
||||
|
||||
val wct = getLatestWct(expectTransition = TRANSIT_NONE)
|
||||
assertThat(wct.hierarchyOps).hasSize(2)
|
||||
// Expect order to be from bottom: home, task
|
||||
wct.assertReorderAt(index = 0, homeTaskDefaultDisplay)
|
||||
wct.assertReorderAt(index = 1, taskDefaultDisplay)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getVisibleTaskCount_noTasks_returnsZero() {
|
||||
assertThat(controller.getVisibleTaskCount()).isEqualTo(0)
|
||||
assertThat(controller.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -222,7 +241,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
|
||||
setUpHomeTask()
|
||||
setUpFreeformTask().also(::markTaskVisible)
|
||||
setUpFreeformTask().also(::markTaskVisible)
|
||||
assertThat(controller.getVisibleTaskCount()).isEqualTo(2)
|
||||
assertThat(controller.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(2)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -230,7 +249,15 @@ class DesktopTasksControllerTest : ShellTestCase() {
|
||||
setUpHomeTask()
|
||||
setUpFreeformTask().also(::markTaskVisible)
|
||||
setUpFreeformTask().also(::markTaskHidden)
|
||||
assertThat(controller.getVisibleTaskCount()).isEqualTo(1)
|
||||
assertThat(controller.getVisibleTaskCount(DEFAULT_DISPLAY)).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getVisibleTaskCount_twoTasksVisibleOnDifferentDisplays_returnsOne() {
|
||||
setUpHomeTask()
|
||||
setUpFreeformTask(DEFAULT_DISPLAY).also(::markTaskVisible)
|
||||
setUpFreeformTask(SECOND_DISPLAY).also(::markTaskVisible)
|
||||
assertThat(controller.getVisibleTaskCount(SECOND_DISPLAY)).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -258,6 +285,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
|
||||
controller.moveToDesktop(fullscreenTask)
|
||||
|
||||
with(getLatestWct(expectTransition = TRANSIT_CHANGE)) {
|
||||
// Operations should include home task, freeform task
|
||||
assertThat(hierarchyOps).hasSize(3)
|
||||
assertReorderSequence(homeTask, freeformTask, fullscreenTask)
|
||||
assertThat(changes[fullscreenTask.token.asBinder()]?.windowingMode)
|
||||
@@ -265,6 +293,28 @@ class DesktopTasksControllerTest : ShellTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun moveToDesktop_onlyFreeformTasksFromCurrentDisplayBroughtToFront() {
|
||||
setUpHomeTask(displayId = DEFAULT_DISPLAY)
|
||||
val freeformTaskDefault = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
|
||||
val fullscreenTaskDefault = setUpFullscreenTask(displayId = DEFAULT_DISPLAY)
|
||||
markTaskHidden(freeformTaskDefault)
|
||||
|
||||
val homeTaskSecond = setUpHomeTask(displayId = SECOND_DISPLAY)
|
||||
val freeformTaskSecond = setUpFreeformTask(displayId = SECOND_DISPLAY)
|
||||
markTaskHidden(freeformTaskSecond)
|
||||
|
||||
controller.moveToDesktop(fullscreenTaskDefault)
|
||||
|
||||
with(getLatestWct(expectTransition = TRANSIT_CHANGE)) {
|
||||
// Check that hierarchy operations do not include tasks from second display
|
||||
assertThat(hierarchyOps.map { it.container })
|
||||
.doesNotContain(homeTaskSecond.token.asBinder())
|
||||
assertThat(hierarchyOps.map { it.container })
|
||||
.doesNotContain(freeformTaskSecond.token.asBinder())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun moveToFullscreen() {
|
||||
val task = setUpFreeformTask()
|
||||
@@ -280,6 +330,19 @@ class DesktopTasksControllerTest : ShellTestCase() {
|
||||
verifyWCTNotExecuted()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun moveToFullscreen_secondDisplayTaskHasFreeform_secondDisplayNotAffected() {
|
||||
val taskDefaultDisplay = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
|
||||
val taskSecondDisplay = setUpFreeformTask(displayId = SECOND_DISPLAY)
|
||||
|
||||
controller.moveToFullscreen(taskDefaultDisplay)
|
||||
|
||||
with(getLatestWct(expectTransition = TRANSIT_CHANGE)) {
|
||||
assertThat(changes.keys).contains(taskDefaultDisplay.token.asBinder())
|
||||
assertThat(changes.keys).doesNotContain(taskSecondDisplay.token.asBinder())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getTaskWindowingMode() {
|
||||
val fullscreenTask = setUpFullscreenTask()
|
||||
@@ -323,6 +386,18 @@ class DesktopTasksControllerTest : ShellTestCase() {
|
||||
assertThat(controller.handleRequest(Binder(), createTransition(fullscreenTask))).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handleRequest_fullscreenTask_freeformTaskOnOtherDisplay_returnNull() {
|
||||
assumeTrue(ENABLE_SHELL_TRANSITIONS)
|
||||
|
||||
val fullscreenTaskDefaultDisplay = createFullscreenTask(displayId = DEFAULT_DISPLAY)
|
||||
createFreeformTask(displayId = SECOND_DISPLAY)
|
||||
|
||||
val result =
|
||||
controller.handleRequest(Binder(), createTransition(fullscreenTaskDefaultDisplay))
|
||||
assertThat(result).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handleRequest_freeformTask_freeformVisible_returnNull() {
|
||||
assumeTrue(ENABLE_SHELL_TRANSITIONS)
|
||||
@@ -361,6 +436,18 @@ class DesktopTasksControllerTest : ShellTestCase() {
|
||||
.isEqualTo(WINDOWING_MODE_FULLSCREEN)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handleRequest_freeformTask_freeformOnOtherDisplayOnly_returnSwitchToFullscreenWCT() {
|
||||
assumeTrue(ENABLE_SHELL_TRANSITIONS)
|
||||
|
||||
val taskDefaultDisplay = createFreeformTask(displayId = DEFAULT_DISPLAY)
|
||||
createFreeformTask(displayId = SECOND_DISPLAY)
|
||||
|
||||
val result = controller.handleRequest(Binder(), createTransition(taskDefaultDisplay))
|
||||
assertThat(result?.changes?.get(taskDefaultDisplay.token.asBinder())?.windowingMode)
|
||||
.isEqualTo(WINDOWING_MODE_FULLSCREEN)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handleRequest_notOpenOrToFrontTransition_returnNull() {
|
||||
assumeTrue(ENABLE_SHELL_TRANSITIONS)
|
||||
@@ -400,35 +487,43 @@ class DesktopTasksControllerTest : ShellTestCase() {
|
||||
assertThat(controller.handleRequest(Binder(), createTransition(task))).isNull()
|
||||
}
|
||||
|
||||
private fun setUpFreeformTask(): RunningTaskInfo {
|
||||
val task = createFreeformTask()
|
||||
private fun setUpFreeformTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo {
|
||||
val task = createFreeformTask(displayId)
|
||||
whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
|
||||
desktopModeTaskRepository.addActiveTask(task.taskId)
|
||||
desktopModeTaskRepository.addActiveTask(displayId, task.taskId)
|
||||
desktopModeTaskRepository.addOrMoveFreeformTaskToTop(task.taskId)
|
||||
runningTasks.add(task)
|
||||
return task
|
||||
}
|
||||
|
||||
private fun setUpHomeTask(): RunningTaskInfo {
|
||||
val task = createHomeTask()
|
||||
private fun setUpHomeTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo {
|
||||
val task = createHomeTask(displayId)
|
||||
whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
|
||||
runningTasks.add(task)
|
||||
return task
|
||||
}
|
||||
|
||||
private fun setUpFullscreenTask(): RunningTaskInfo {
|
||||
val task = createFullscreenTask()
|
||||
private fun setUpFullscreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo {
|
||||
val task = createFullscreenTask(displayId)
|
||||
whenever(shellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
|
||||
runningTasks.add(task)
|
||||
return task
|
||||
}
|
||||
|
||||
private fun markTaskVisible(task: RunningTaskInfo) {
|
||||
desktopModeTaskRepository.updateVisibleFreeformTasks(task.taskId, visible = true)
|
||||
desktopModeTaskRepository.updateVisibleFreeformTasks(
|
||||
task.displayId,
|
||||
task.taskId,
|
||||
visible = true
|
||||
)
|
||||
}
|
||||
|
||||
private fun markTaskHidden(task: RunningTaskInfo) {
|
||||
desktopModeTaskRepository.updateVisibleFreeformTasks(task.taskId, visible = false)
|
||||
desktopModeTaskRepository.updateVisibleFreeformTasks(
|
||||
task.displayId,
|
||||
task.taskId,
|
||||
visible = false
|
||||
)
|
||||
}
|
||||
|
||||
private fun getLatestWct(
|
||||
@@ -457,6 +552,10 @@ class DesktopTasksControllerTest : ShellTestCase() {
|
||||
): TransitionRequestInfo {
|
||||
return TransitionRequestInfo(type, task, null /* remoteTransition */)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val SECOND_DISPLAY = 2
|
||||
}
|
||||
}
|
||||
|
||||
private fun WindowContainerTransaction.assertReorderAt(index: Int, task: RunningTaskInfo) {
|
||||
|
||||
@@ -21,14 +21,17 @@ import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME
|
||||
import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
|
||||
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
|
||||
import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
|
||||
import android.view.Display.DEFAULT_DISPLAY
|
||||
import com.android.wm.shell.TestRunningTaskInfoBuilder
|
||||
|
||||
class DesktopTestHelpers {
|
||||
companion object {
|
||||
/** Create a task that has windowing mode set to [WINDOWING_MODE_FREEFORM] */
|
||||
@JvmStatic
|
||||
fun createFreeformTask(): RunningTaskInfo {
|
||||
@JvmOverloads
|
||||
fun createFreeformTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo {
|
||||
return TestRunningTaskInfoBuilder()
|
||||
.setDisplayId(displayId)
|
||||
.setToken(MockToken().token())
|
||||
.setActivityType(ACTIVITY_TYPE_STANDARD)
|
||||
.setWindowingMode(WINDOWING_MODE_FREEFORM)
|
||||
@@ -38,8 +41,10 @@ class DesktopTestHelpers {
|
||||
|
||||
/** Create a task that has windowing mode set to [WINDOWING_MODE_FULLSCREEN] */
|
||||
@JvmStatic
|
||||
fun createFullscreenTask(): RunningTaskInfo {
|
||||
@JvmOverloads
|
||||
fun createFullscreenTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo {
|
||||
return TestRunningTaskInfoBuilder()
|
||||
.setDisplayId(displayId)
|
||||
.setToken(MockToken().token())
|
||||
.setActivityType(ACTIVITY_TYPE_STANDARD)
|
||||
.setWindowingMode(WINDOWING_MODE_FULLSCREEN)
|
||||
@@ -49,8 +54,10 @@ class DesktopTestHelpers {
|
||||
|
||||
/** Create a new home task */
|
||||
@JvmStatic
|
||||
fun createHomeTask(): RunningTaskInfo {
|
||||
@JvmOverloads
|
||||
fun createHomeTask(displayId: Int = DEFAULT_DISPLAY): RunningTaskInfo {
|
||||
return TestRunningTaskInfoBuilder()
|
||||
.setDisplayId(displayId)
|
||||
.setToken(MockToken().token())
|
||||
.setActivityType(ACTIVITY_TYPE_HOME)
|
||||
.setWindowingMode(WINDOWING_MODE_FULLSCREEN)
|
||||
|
||||
@@ -33,6 +33,7 @@ import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.os.IBinder;
|
||||
import android.view.Display;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -347,12 +348,16 @@ public final class WMShell implements
|
||||
void initDesktopMode(DesktopMode desktopMode) {
|
||||
desktopMode.addVisibleTasksListener(
|
||||
new DesktopModeTaskRepository.VisibleTasksListener() {
|
||||
@Override
|
||||
public void onVisibilityChanged(boolean hasFreeformTasks) {
|
||||
mSysUiState.setFlag(SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE, hasFreeformTasks)
|
||||
.commitUpdate(mDisplayTracker.getDefaultDisplayId());
|
||||
}
|
||||
}, mSysUiMainExecutor);
|
||||
@Override
|
||||
public void onVisibilityChanged(int displayId, boolean hasFreeformTasks) {
|
||||
if (displayId == Display.DEFAULT_DISPLAY) {
|
||||
mSysUiState.setFlag(SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE,
|
||||
hasFreeformTasks)
|
||||
.commitUpdate(mDisplayTracker.getDefaultDisplayId());
|
||||
}
|
||||
// TODO(b/278084491): update sysui state for changes on other displays
|
||||
}
|
||||
}, mSysUiMainExecutor);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user