Loading libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasksListener.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -37,4 +37,9 @@ oneway interface IRecentTasksListener { * Called when a running task vanishes. */ void onRunningTaskVanished(in RunningTaskInfo taskInfo); /** * Called when a running task changes. */ void onRunningTaskChanged(in RunningTaskInfo taskInfo); } libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java +38 −6 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.wm.shell.recents; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.content.pm.PackageManager.FEATURE_PC; import static com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_RECENT_TASKS; Loading @@ -26,7 +27,6 @@ import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.app.IApplicationThread; import android.app.PendingIntent; import android.app.TaskInfo; import android.content.ComponentName; import android.content.Context; import android.content.Intent; Loading Loading @@ -86,7 +86,7 @@ public class RecentTasksController implements TaskStackListenerCallback, private final ActivityTaskManager mActivityTaskManager; private RecentsTransitionHandler mTransitionHandler = null; private IRecentTasksListener mListener; private final boolean mIsDesktopMode; private final boolean mPcFeatureEnabled; // Mapping of split task ids, mappings are symmetrical (ie. if t1 is the taskid of a task in a // pair, then mSplitTasks[t1] = t2, and mSplitTasks[t2] = t1) Loading Loading @@ -133,7 +133,7 @@ public class RecentTasksController implements TaskStackListenerCallback, mShellController = shellController; mShellCommandHandler = shellCommandHandler; mActivityTaskManager = activityTaskManager; mIsDesktopMode = mContext.getPackageManager().hasSystemFeature(FEATURE_PC); mPcFeatureEnabled = mContext.getPackageManager().hasSystemFeature(FEATURE_PC); mTaskStackListener = taskStackListener; mDesktopModeTaskRepository = desktopModeTaskRepository; mMainExecutor = mainExecutor; Loading Loading @@ -252,8 +252,10 @@ public class RecentTasksController implements TaskStackListenerCallback, notifyRunningTaskVanished(taskInfo); } public void onTaskWindowingModeChanged(TaskInfo taskInfo) { /** Notify listeners that the windowing mode of the given Task was updated. */ public void onTaskWindowingModeChanged(ActivityManager.RunningTaskInfo taskInfo) { notifyRecentTasksChanged(); notifyRunningTaskChanged(taskInfo); } @Override Loading @@ -278,7 +280,9 @@ public class RecentTasksController implements TaskStackListenerCallback, * Notify the running task listener that a task appeared on desktop environment. */ private void notifyRunningTaskAppeared(ActivityManager.RunningTaskInfo taskInfo) { if (mListener == null || !mIsDesktopMode || taskInfo.realActivity == null) { if (mListener == null || !shouldEnableRunningTasksForDesktopMode() || taskInfo.realActivity == null) { return; } try { Loading @@ -292,7 +296,9 @@ public class RecentTasksController implements TaskStackListenerCallback, * Notify the running task listener that a task was removed on desktop environment. */ private void notifyRunningTaskVanished(ActivityManager.RunningTaskInfo taskInfo) { if (mListener == null || !mIsDesktopMode || taskInfo.realActivity == null) { if (mListener == null || !shouldEnableRunningTasksForDesktopMode() || taskInfo.realActivity == null) { return; } try { Loading @@ -302,6 +308,27 @@ public class RecentTasksController implements TaskStackListenerCallback, } } /** * Notify the running task listener that a task was changed on desktop environment. */ private void notifyRunningTaskChanged(ActivityManager.RunningTaskInfo taskInfo) { if (mListener == null || !shouldEnableRunningTasksForDesktopMode() || taskInfo.realActivity == null) { return; } try { mListener.onRunningTaskChanged(taskInfo); } catch (RemoteException e) { Slog.w(TAG, "Failed call onRunningTaskChanged", e); } } private boolean shouldEnableRunningTasksForDesktopMode() { return mPcFeatureEnabled || (DesktopModeStatus.isEnabled() && enableDesktopWindowingTaskbarRunningApps()); } @VisibleForTesting void registerRecentTasksListener(IRecentTasksListener listener) { mListener = listener; Loading Loading @@ -476,6 +503,11 @@ public class RecentTasksController implements TaskStackListenerCallback, public void onRunningTaskVanished(ActivityManager.RunningTaskInfo taskInfo) { mListener.call(l -> l.onRunningTaskVanished(taskInfo)); } @Override public void onRunningTaskChanged(ActivityManager.RunningTaskInfo taskInfo) { mListener.call(l -> l.onRunningTaskChanged(taskInfo)); } }; public IRecentTasksImpl(RecentTasksController controller) { Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java +92 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; Loading @@ -45,16 +46,21 @@ import static java.lang.Integer.MAX_VALUE; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; import android.graphics.Rect; import android.os.Bundle; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.view.SurfaceControl; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.dx.mockito.inline.extended.StaticMockitoSession; import com.android.window.flags.Flags; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestShellExecutor; Loading @@ -70,6 +76,7 @@ import com.android.wm.shell.util.GroupedRecentTaskInfo; import com.android.wm.shell.util.SplitBounds; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; Loading Loading @@ -99,6 +106,11 @@ public class RecentTasksControllerTest extends ShellTestCase { private ActivityTaskManager mActivityTaskManager; @Mock private DisplayInsetsController mDisplayInsetsController; @Mock private IRecentTasksListener mRecentTasksListener; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private ShellTaskOrganizer mShellTaskOrganizer; private RecentTasksController mRecentTasksController; Loading Loading @@ -425,6 +437,85 @@ public class RecentTasksControllerTest extends ShellTestCase { verify(mRecentTasksController).notifyRecentTasksChanged(); } @Test @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE, Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS}) public void onTaskAdded_desktopModeRunningAppsEnabled_triggersOnRunningTaskAppeared() throws Exception { mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener); ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10); mRecentTasksControllerReal.onTaskAdded(taskInfo); verify(mRecentTasksListener).onRunningTaskAppeared(taskInfo); } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS) public void onTaskAdded_desktopModeRunningAppsDisabled_doesNotTriggerOnRunningTaskAppeared() throws Exception { mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener); ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10); mRecentTasksControllerReal.onTaskAdded(taskInfo); verify(mRecentTasksListener, never()).onRunningTaskAppeared(any()); } @Test @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE, Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS}) public void taskWindowingModeChanged_desktopRunningAppsEnabled_triggersOnRunningTaskChanged() throws Exception { mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener); ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10); mRecentTasksControllerReal.onTaskWindowingModeChanged(taskInfo); verify(mRecentTasksListener).onRunningTaskChanged(taskInfo); } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS) public void taskWindowingModeChanged_desktopRunningAppsDisabled_doesNotTriggerOnRunningTaskChanged() throws Exception { mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener); ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10); mRecentTasksControllerReal.onTaskWindowingModeChanged(taskInfo); verify(mRecentTasksListener, never()).onRunningTaskChanged(any()); } @Test @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE, Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS}) public void onTaskRemoved_desktopModeRunningAppsEnabled_triggersOnRunningTaskVanished() throws Exception { mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener); ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10); mRecentTasksControllerReal.onTaskRemoved(taskInfo); verify(mRecentTasksListener).onRunningTaskVanished(taskInfo); } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS) public void onTaskRemoved_desktopModeRunningAppsDisabled_doesNotTriggerOnRunningTaskVanished() throws Exception { mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener); ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10); mRecentTasksControllerReal.onTaskRemoved(taskInfo); verify(mRecentTasksListener, never()).onRunningTaskVanished(any()); } @Test public void getNullSplitBoundsNonSplitTask() { SplitBounds sb = mRecentTasksController.getSplitBoundsForTaskId(3); Loading Loading @@ -471,6 +562,7 @@ public class RecentTasksControllerTest extends ShellTestCase { private ActivityManager.RunningTaskInfo makeRunningTaskInfo(int taskId) { ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo(); info.taskId = taskId; info.realActivity = new ComponentName("testPackage", "testClass"); return info; } Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentTasksListener.aidl +5 −0 Original line number Diff line number Diff line Loading @@ -37,4 +37,9 @@ oneway interface IRecentTasksListener { * Called when a running task vanishes. */ void onRunningTaskVanished(in RunningTaskInfo taskInfo); /** * Called when a running task changes. */ void onRunningTaskChanged(in RunningTaskInfo taskInfo); }
libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java +38 −6 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.wm.shell.recents; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.content.pm.PackageManager.FEATURE_PC; import static com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_RECENT_TASKS; Loading @@ -26,7 +27,6 @@ import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.app.IApplicationThread; import android.app.PendingIntent; import android.app.TaskInfo; import android.content.ComponentName; import android.content.Context; import android.content.Intent; Loading Loading @@ -86,7 +86,7 @@ public class RecentTasksController implements TaskStackListenerCallback, private final ActivityTaskManager mActivityTaskManager; private RecentsTransitionHandler mTransitionHandler = null; private IRecentTasksListener mListener; private final boolean mIsDesktopMode; private final boolean mPcFeatureEnabled; // Mapping of split task ids, mappings are symmetrical (ie. if t1 is the taskid of a task in a // pair, then mSplitTasks[t1] = t2, and mSplitTasks[t2] = t1) Loading Loading @@ -133,7 +133,7 @@ public class RecentTasksController implements TaskStackListenerCallback, mShellController = shellController; mShellCommandHandler = shellCommandHandler; mActivityTaskManager = activityTaskManager; mIsDesktopMode = mContext.getPackageManager().hasSystemFeature(FEATURE_PC); mPcFeatureEnabled = mContext.getPackageManager().hasSystemFeature(FEATURE_PC); mTaskStackListener = taskStackListener; mDesktopModeTaskRepository = desktopModeTaskRepository; mMainExecutor = mainExecutor; Loading Loading @@ -252,8 +252,10 @@ public class RecentTasksController implements TaskStackListenerCallback, notifyRunningTaskVanished(taskInfo); } public void onTaskWindowingModeChanged(TaskInfo taskInfo) { /** Notify listeners that the windowing mode of the given Task was updated. */ public void onTaskWindowingModeChanged(ActivityManager.RunningTaskInfo taskInfo) { notifyRecentTasksChanged(); notifyRunningTaskChanged(taskInfo); } @Override Loading @@ -278,7 +280,9 @@ public class RecentTasksController implements TaskStackListenerCallback, * Notify the running task listener that a task appeared on desktop environment. */ private void notifyRunningTaskAppeared(ActivityManager.RunningTaskInfo taskInfo) { if (mListener == null || !mIsDesktopMode || taskInfo.realActivity == null) { if (mListener == null || !shouldEnableRunningTasksForDesktopMode() || taskInfo.realActivity == null) { return; } try { Loading @@ -292,7 +296,9 @@ public class RecentTasksController implements TaskStackListenerCallback, * Notify the running task listener that a task was removed on desktop environment. */ private void notifyRunningTaskVanished(ActivityManager.RunningTaskInfo taskInfo) { if (mListener == null || !mIsDesktopMode || taskInfo.realActivity == null) { if (mListener == null || !shouldEnableRunningTasksForDesktopMode() || taskInfo.realActivity == null) { return; } try { Loading @@ -302,6 +308,27 @@ public class RecentTasksController implements TaskStackListenerCallback, } } /** * Notify the running task listener that a task was changed on desktop environment. */ private void notifyRunningTaskChanged(ActivityManager.RunningTaskInfo taskInfo) { if (mListener == null || !shouldEnableRunningTasksForDesktopMode() || taskInfo.realActivity == null) { return; } try { mListener.onRunningTaskChanged(taskInfo); } catch (RemoteException e) { Slog.w(TAG, "Failed call onRunningTaskChanged", e); } } private boolean shouldEnableRunningTasksForDesktopMode() { return mPcFeatureEnabled || (DesktopModeStatus.isEnabled() && enableDesktopWindowingTaskbarRunningApps()); } @VisibleForTesting void registerRecentTasksListener(IRecentTasksListener listener) { mListener = listener; Loading Loading @@ -476,6 +503,11 @@ public class RecentTasksController implements TaskStackListenerCallback, public void onRunningTaskVanished(ActivityManager.RunningTaskInfo taskInfo) { mListener.call(l -> l.onRunningTaskVanished(taskInfo)); } @Override public void onRunningTaskChanged(ActivityManager.RunningTaskInfo taskInfo) { mListener.call(l -> l.onRunningTaskChanged(taskInfo)); } }; public IRecentTasksImpl(RecentTasksController controller) { Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java +92 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; Loading @@ -45,16 +46,21 @@ import static java.lang.Integer.MAX_VALUE; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; import android.graphics.Rect; import android.os.Bundle; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.view.SurfaceControl; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.dx.mockito.inline.extended.StaticMockitoSession; import com.android.window.flags.Flags; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestShellExecutor; Loading @@ -70,6 +76,7 @@ import com.android.wm.shell.util.GroupedRecentTaskInfo; import com.android.wm.shell.util.SplitBounds; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; Loading Loading @@ -99,6 +106,11 @@ public class RecentTasksControllerTest extends ShellTestCase { private ActivityTaskManager mActivityTaskManager; @Mock private DisplayInsetsController mDisplayInsetsController; @Mock private IRecentTasksListener mRecentTasksListener; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private ShellTaskOrganizer mShellTaskOrganizer; private RecentTasksController mRecentTasksController; Loading Loading @@ -425,6 +437,85 @@ public class RecentTasksControllerTest extends ShellTestCase { verify(mRecentTasksController).notifyRecentTasksChanged(); } @Test @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE, Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS}) public void onTaskAdded_desktopModeRunningAppsEnabled_triggersOnRunningTaskAppeared() throws Exception { mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener); ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10); mRecentTasksControllerReal.onTaskAdded(taskInfo); verify(mRecentTasksListener).onRunningTaskAppeared(taskInfo); } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS) public void onTaskAdded_desktopModeRunningAppsDisabled_doesNotTriggerOnRunningTaskAppeared() throws Exception { mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener); ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10); mRecentTasksControllerReal.onTaskAdded(taskInfo); verify(mRecentTasksListener, never()).onRunningTaskAppeared(any()); } @Test @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE, Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS}) public void taskWindowingModeChanged_desktopRunningAppsEnabled_triggersOnRunningTaskChanged() throws Exception { mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener); ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10); mRecentTasksControllerReal.onTaskWindowingModeChanged(taskInfo); verify(mRecentTasksListener).onRunningTaskChanged(taskInfo); } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS) public void taskWindowingModeChanged_desktopRunningAppsDisabled_doesNotTriggerOnRunningTaskChanged() throws Exception { mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener); ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10); mRecentTasksControllerReal.onTaskWindowingModeChanged(taskInfo); verify(mRecentTasksListener, never()).onRunningTaskChanged(any()); } @Test @EnableFlags({Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE, Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS}) public void onTaskRemoved_desktopModeRunningAppsEnabled_triggersOnRunningTaskVanished() throws Exception { mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener); ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10); mRecentTasksControllerReal.onTaskRemoved(taskInfo); verify(mRecentTasksListener).onRunningTaskVanished(taskInfo); } @Test @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE) @DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS) public void onTaskRemoved_desktopModeRunningAppsDisabled_doesNotTriggerOnRunningTaskVanished() throws Exception { mRecentTasksControllerReal.registerRecentTasksListener(mRecentTasksListener); ActivityManager.RunningTaskInfo taskInfo = makeRunningTaskInfo(/* taskId= */10); mRecentTasksControllerReal.onTaskRemoved(taskInfo); verify(mRecentTasksListener, never()).onRunningTaskVanished(any()); } @Test public void getNullSplitBoundsNonSplitTask() { SplitBounds sb = mRecentTasksController.getSplitBoundsForTaskId(3); Loading Loading @@ -471,6 +562,7 @@ public class RecentTasksControllerTest extends ShellTestCase { private ActivityManager.RunningTaskInfo makeRunningTaskInfo(int taskId) { ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo(); info.taskId = taskId; info.realActivity = new ComponentName("testPackage", "testClass"); return info; } Loading