diff options
| author | 2022-10-24 16:04:59 +0000 | |
|---|---|---|
| committer | 2022-10-24 16:04:59 +0000 | |
| commit | 731095e5cfe64a788f9fbd4b56612bbb58efa0bf (patch) | |
| tree | 1a63d05bf96900609f3e15b2e70965a8f5f754e0 /libs | |
| parent | 584274c3a72e8e6e6f4a19a169dd304e71ccf58a (diff) | |
| parent | 457d8317f15ae6fe5c05521f01160569b71fae22 (diff) | |
Merge "Track visible tasks in DesktopModeController and add a listener" into tm-qpr-dev
Diffstat (limited to 'libs')
6 files changed, 173 insertions, 21 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java index 44a467ffcf3d..cbd544cc4b86 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java @@ -18,9 +18,21 @@ package com.android.wm.shell.desktopmode; import com.android.wm.shell.common.annotations.ExternalThread; +import java.util.concurrent.Executor; + /** * Interface to interact with desktop mode feature in shell. */ @ExternalThread public interface DesktopMode { + + /** + * Adds a listener to find out about changes in the visibility of freeform tasks. + * + * @param listener the listener to add. + * @param callbackExecutor the executor to call the listener on. + */ + void addListener(DesktopModeTaskRepository.VisibleTasksListener listener, + Executor callbackExecutor); + } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java index b96facf4c46e..c8c36f504f76 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java @@ -60,6 +60,7 @@ import com.android.wm.shell.transition.Transitions; import java.util.ArrayList; import java.util.Comparator; +import java.util.concurrent.Executor; /** * Handles windowing changes when desktop mode system setting changes @@ -132,6 +133,17 @@ public class DesktopModeController implements RemoteCallable<DesktopModeControll return new IDesktopModeImpl(this); } + /** + * Adds a listener to find out about changes in the visibility of freeform tasks. + * + * @param listener the listener to add. + * @param callbackExecutor the executor to call the listener on. + */ + public void addListener(DesktopModeTaskRepository.VisibleTasksListener listener, + Executor callbackExecutor) { + mDesktopModeTaskRepository.addVisibleTasksListener(listener, callbackExecutor); + } + @VisibleForTesting void updateDesktopModeActive(boolean active) { ProtoLog.d(WM_SHELL_DESKTOP_MODE, "updateDesktopModeActive: active=%s", active); @@ -293,7 +305,14 @@ public class DesktopModeController implements RemoteCallable<DesktopModeControll */ @ExternalThread private final class DesktopModeImpl implements DesktopMode { - // Do nothing + + @Override + public void addListener(DesktopModeTaskRepository.VisibleTasksListener listener, + Executor callbackExecutor) { + mMainExecutor.execute(() -> { + DesktopModeController.this.addListener(listener, callbackExecutor); + }); + } } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt index 988601c0e8a8..c91d54a62ae6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepository.kt @@ -16,7 +16,9 @@ package com.android.wm.shell.desktopmode +import android.util.ArrayMap import android.util.ArraySet +import java.util.concurrent.Executor /** * Keeps track of task data related to desktop mode. @@ -30,20 +32,39 @@ class DesktopModeTaskRepository { * Task gets removed from this list when it vanishes. Or when desktop mode is turned off. */ private val activeTasks = ArraySet<Int>() - private val listeners = ArraySet<Listener>() + private val visibleTasks = ArraySet<Int>() + private val activeTasksListeners = ArraySet<ActiveTasksListener>() + // Track visible tasks separately because a task may be part of the desktop but not visible. + private val visibleTasksListeners = ArrayMap<VisibleTasksListener, Executor>() /** - * Add a [Listener] to be notified of updates to the repository. + * Add a [ActiveTasksListener] to be notified of updates to active tasks in the repository. */ - fun addListener(listener: Listener) { - listeners.add(listener) + fun addActiveTaskListener(activeTasksListener: ActiveTasksListener) { + activeTasksListeners.add(activeTasksListener) } /** - * Remove a previously registered [Listener] + * Add a [VisibleTasksListener] to be notified when freeform tasks are visible or not. */ - fun removeListener(listener: Listener) { - listeners.remove(listener) + fun addVisibleTasksListener(visibleTasksListener: VisibleTasksListener, executor: Executor) { + visibleTasksListeners.put(visibleTasksListener, executor) + executor.execute( + Runnable { visibleTasksListener.onVisibilityChanged(visibleTasks.size > 0) }) + } + + /** + * Remove a previously registered [ActiveTasksListener] + */ + fun removeActiveTasksListener(activeTasksListener: ActiveTasksListener) { + activeTasksListeners.remove(activeTasksListener) + } + + /** + * Remove a previously registered [VisibleTasksListener] + */ + fun removeVisibleTasksListener(visibleTasksListener: VisibleTasksListener) { + visibleTasksListeners.remove(visibleTasksListener) } /** @@ -52,7 +73,7 @@ class DesktopModeTaskRepository { fun addActiveTask(taskId: Int) { val added = activeTasks.add(taskId) if (added) { - listeners.onEach { it.onActiveTasksChanged() } + activeTasksListeners.onEach { it.onActiveTasksChanged() } } } @@ -62,7 +83,7 @@ class DesktopModeTaskRepository { fun removeActiveTask(taskId: Int) { val removed = activeTasks.remove(taskId) if (removed) { - listeners.onEach { it.onActiveTasksChanged() } + activeTasksListeners.onEach { it.onActiveTasksChanged() } } } @@ -81,9 +102,43 @@ class DesktopModeTaskRepository { } /** - * Defines interface for classes that can listen to changes in repository state. + * Updates whether a freeform task with this id is visible or not and notifies listeners. + */ + fun updateVisibleFreeformTasks(taskId: Int, visible: Boolean) { + val prevCount: Int = visibleTasks.size + 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) }) + } + } + } + + /** + * Defines interface for classes that can listen to changes for active tasks in desktop mode. + */ + interface ActiveTasksListener { + /** + * Called when the active tasks change in desktop mode. + */ + @JvmDefault + fun onActiveTasksChanged() {} + } + + /** + * Defines interface for classes that can listen to changes for visible tasks in desktop mode. */ - interface Listener { - fun onActiveTasksChanged() + interface VisibleTasksListener { + /** + * Called when the desktop starts or stops showing freeform tasks. + */ + @JvmDefault + fun onVisibilityChanged(hasVisibleFreeformTasks: Boolean) {} } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java index f82a34621262..eaa7158abbe5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java @@ -90,6 +90,8 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "Adding active freeform task: #%d", taskInfo.taskId); mDesktopModeTaskRepository.ifPresent(it -> it.addActiveTask(taskInfo.taskId)); + mDesktopModeTaskRepository.ifPresent( + it -> it.updateVisibleFreeformTasks(taskInfo.taskId, true)); } } @@ -103,6 +105,8 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, "Removing active freeform task: #%d", taskInfo.taskId); mDesktopModeTaskRepository.ifPresent(it -> it.removeActiveTask(taskInfo.taskId)); + mDesktopModeTaskRepository.ifPresent( + it -> it.updateVisibleFreeformTasks(taskInfo.taskId, false)); } if (!Transitions.ENABLE_SHELL_TRANSITIONS) { @@ -124,6 +128,8 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener { "Adding active freeform task: #%d", taskInfo.taskId); mDesktopModeTaskRepository.ifPresent(it -> it.addActiveTask(taskInfo.taskId)); } + mDesktopModeTaskRepository.ifPresent( + it -> it.updateVisibleFreeformTasks(taskInfo.taskId, taskInfo.isVisible)); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java index 08f3db65e62f..f9172ba183de 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java @@ -68,7 +68,7 @@ import java.util.function.Consumer; * Manages the recent task list from the system, caching it as necessary. */ public class RecentTasksController implements TaskStackListenerCallback, - RemoteCallable<RecentTasksController>, DesktopModeTaskRepository.Listener { + RemoteCallable<RecentTasksController>, DesktopModeTaskRepository.ActiveTasksListener { private static final String TAG = RecentTasksController.class.getSimpleName(); private final Context mContext; @@ -147,7 +147,7 @@ public class RecentTasksController implements TaskStackListenerCallback, this::createExternalInterface, this); mShellCommandHandler.addDumpCallback(this::dump, this); mTaskStackListener.addListener(this); - mDesktopModeTaskRepository.ifPresent(it -> it.addListener(this)); + mDesktopModeTaskRepository.ifPresent(it -> it.addActiveTaskListener(this)); } /** diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt index 9b28d11f6a9d..aaa5c8a35acb 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeTaskRepositoryTest.kt @@ -19,6 +19,7 @@ package com.android.wm.shell.desktopmode import android.testing.AndroidTestingRunner 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 org.junit.Before import org.junit.Test @@ -38,7 +39,7 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { @Test fun addActiveTask_listenerNotifiedAndTaskIsActive() { val listener = TestListener() - repo.addListener(listener) + repo.addActiveTaskListener(listener) repo.addActiveTask(1) assertThat(listener.activeTaskChangedCalls).isEqualTo(1) @@ -48,7 +49,7 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { @Test fun addActiveTask_sameTaskDoesNotNotify() { val listener = TestListener() - repo.addListener(listener) + repo.addActiveTaskListener(listener) repo.addActiveTask(1) repo.addActiveTask(1) @@ -58,7 +59,7 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { @Test fun addActiveTask_multipleTasksAddedNotifiesForEach() { val listener = TestListener() - repo.addListener(listener) + repo.addActiveTaskListener(listener) repo.addActiveTask(1) repo.addActiveTask(2) @@ -68,7 +69,7 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { @Test fun removeActiveTask_listenerNotifiedAndTaskNotActive() { val listener = TestListener() - repo.addListener(listener) + repo.addActiveTaskListener(listener) repo.addActiveTask(1) repo.removeActiveTask(1) @@ -80,7 +81,7 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { @Test fun removeActiveTask_removeNotExistingTaskDoesNotNotify() { val listener = TestListener() - repo.addListener(listener) + repo.addActiveTaskListener(listener) repo.removeActiveTask(99) assertThat(listener.activeTaskChangedCalls).isEqualTo(0) } @@ -90,10 +91,69 @@ class DesktopModeTaskRepositoryTest : ShellTestCase() { assertThat(repo.isActiveTask(99)).isFalse() } - class TestListener : DesktopModeTaskRepository.Listener { + @Test + fun addListener_notifiesVisibleFreeformTask() { + repo.updateVisibleFreeformTasks(1, true) + val listener = TestVisibilityListener() + val executor = TestShellExecutor() + repo.addVisibleTasksListener(listener, executor) + executor.flushAll() + + assertThat(listener.hasVisibleFreeformTasks).isTrue() + assertThat(listener.visibleFreeformTaskChangedCalls).isEqualTo(1) + } + + @Test + fun updateVisibleFreeformTasks_addVisibleTasksNotifiesListener() { + val listener = TestVisibilityListener() + val executor = TestShellExecutor() + repo.addVisibleTasksListener(listener, executor) + repo.updateVisibleFreeformTasks(1, true) + repo.updateVisibleFreeformTasks(2, true) + executor.flushAll() + + assertThat(listener.hasVisibleFreeformTasks).isTrue() + // Equal to 2 because adding the listener notifies the current state + assertThat(listener.visibleFreeformTaskChangedCalls).isEqualTo(2) + } + + @Test + fun updateVisibleFreeformTasks_removeVisibleTasksNotifiesListener() { + val listener = TestVisibilityListener() + val executor = TestShellExecutor() + repo.addVisibleTasksListener(listener, executor) + repo.updateVisibleFreeformTasks(1, true) + repo.updateVisibleFreeformTasks(2, true) + executor.flushAll() + + assertThat(listener.hasVisibleFreeformTasks).isTrue() + repo.updateVisibleFreeformTasks(1, false) + executor.flushAll() + + // Equal to 2 because adding the listener notifies the current state + assertThat(listener.visibleFreeformTaskChangedCalls).isEqualTo(2) + + repo.updateVisibleFreeformTasks(2, false) + executor.flushAll() + + assertThat(listener.hasVisibleFreeformTasks).isFalse() + assertThat(listener.visibleFreeformTaskChangedCalls).isEqualTo(3) + } + + class TestListener : DesktopModeTaskRepository.ActiveTasksListener { var activeTaskChangedCalls = 0 override fun onActiveTasksChanged() { activeTaskChangedCalls++ } } + + class TestVisibilityListener : DesktopModeTaskRepository.VisibleTasksListener { + var hasVisibleFreeformTasks = false + var visibleFreeformTaskChangedCalls = 0 + + override fun onVisibilityChanged(hasVisibleTasks: Boolean) { + hasVisibleFreeformTasks = hasVisibleTasks + visibleFreeformTaskChangedCalls++ + } + } } |