Loading quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java +46 −1 Original line number Diff line number Diff line Loading @@ -37,6 +37,9 @@ import com.android.quickstep.SystemUiProxy; import com.android.quickstep.views.DesktopAppSelectView; import com.android.wm.shell.desktopmode.IDesktopTaskListener; import java.util.HashSet; import java.util.Set; /** * Controls the visibility of the workspace and the resumed / paused state when desktop mode * is enabled. Loading @@ -48,6 +51,7 @@ public class DesktopVisibilityController { private static final boolean IS_STASHING_ENABLED = SystemProperties.getBoolean( "persist.wm.debug.desktop_stashing", false); private final Launcher mLauncher; private final Set<DesktopVisibilityListener> mDesktopVisibilityListeners = new HashSet<>(); private int mVisibleDesktopTasksCount; private boolean mInOverviewState; Loading Loading @@ -127,6 +131,16 @@ public class DesktopVisibilityController { return mVisibleDesktopTasksCount; } /** Registers a listener for Desktop Mode visibility updates. */ public void registerDesktopVisibilityListener(DesktopVisibilityListener listener) { mDesktopVisibilityListeners.add(listener); } /** Removes a previously registered Desktop Mode visibility listener. */ public void unregisterDesktopVisibilityListener(DesktopVisibilityListener listener) { mDesktopVisibilityListeners.remove(listener); } /** * Sets the number of desktop windows that are visible and updates launcher visibility based on * it. Loading @@ -140,7 +154,12 @@ public class DesktopVisibilityController { if (visibleTasksCount != mVisibleDesktopTasksCount) { final boolean wasVisible = mVisibleDesktopTasksCount > 0; final boolean isVisible = visibleTasksCount > 0; final boolean wereDesktopTasksVisibleBefore = areDesktopTasksVisible(); mVisibleDesktopTasksCount = visibleTasksCount; final boolean areDesktopTasksVisibleNow = areDesktopTasksVisible(); if (wereDesktopTasksVisibleBefore != areDesktopTasksVisibleNow) { notifyDesktopVisibilityListeners(areDesktopTasksVisibleNow); } if (!enableDesktopWindowingWallpaperActivity() && wasVisible != isVisible) { // TODO: b/333533253 - Remove after flag rollout Loading Loading @@ -179,15 +198,22 @@ public class DesktopVisibilityController { + " currentValue=" + mInOverviewState); } if (overviewStateEnabled != mInOverviewState) { final boolean wereDesktopTasksVisibleBefore = areDesktopTasksVisible(); mInOverviewState = overviewStateEnabled; final boolean areDesktopTasksVisibleNow = areDesktopTasksVisible(); if (wereDesktopTasksVisibleBefore != areDesktopTasksVisibleNow) { notifyDesktopVisibilityListeners(areDesktopTasksVisibleNow); } if (enableDesktopWindowingWallpaperActivity()) { return; } // TODO: b/333533253 - Clean up after flag rollout if (mInOverviewState) { setLauncherViewsVisibility(View.VISIBLE); markLauncherResumed(); } else if (areDesktopTasksVisible() && !mGestureInProgress) { } else if (areDesktopTasksVisibleNow && !mGestureInProgress) { // Switching out of overview state and gesture finished. // If desktop tasks are still visible, hide launcher again. setLauncherViewsVisibility(View.INVISIBLE); Loading @@ -196,6 +222,15 @@ public class DesktopVisibilityController { } } private void notifyDesktopVisibilityListeners(boolean areDesktopTasksVisible) { if (DEBUG) { Log.d(TAG, "notifyDesktopVisibilityListeners: visible=" + areDesktopTasksVisible); } for (DesktopVisibilityListener listener : mDesktopVisibilityListeners) { listener.onDesktopVisibilityChanged(areDesktopTasksVisible); } } /** * TODO: b/333533253 - Remove after flag rollout */ Loading Loading @@ -359,4 +394,14 @@ public class DesktopVisibilityController { mSelectAppToast.hide(); mSelectAppToast = null; } /** A listener for when the user enters/exits Desktop Mode. */ public interface DesktopVisibilityListener { /** * Callback for when the user enters or exits Desktop Mode * * @param visible whether Desktop Mode is now visible */ void onDesktopVisibilityChanged(boolean visible); } } quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsController.kt 0 → 100644 +139 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.launcher3.taskbar import android.app.ActivityManager.RunningTaskInfo import android.app.WindowConfiguration import android.util.Log import android.util.SparseArray import androidx.annotation.VisibleForTesting import androidx.core.util.valueIterator import com.android.launcher3.model.data.AppInfo import com.android.launcher3.model.data.ItemInfo import com.android.launcher3.model.data.WorkspaceItemInfo import com.android.launcher3.statehandlers.DesktopVisibilityController import com.android.quickstep.RecentsModel import kotlin.collections.filterNotNull /** * Shows running apps when in Desktop Mode. * * Users can enter and exit Desktop Mode at run-time, meaning this class falls back to the default * recent-apps behaviour when outside of Desktop Mode. * * This class should only be used if * [com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps] is enabled. */ class DesktopTaskbarRunningAppsController( private val recentsModel: RecentsModel, private val desktopVisibilityController: DesktopVisibilityController?, ) : TaskbarRecentAppsController() { private var apps: Array<AppInfo>? = null private var allRunningDesktopAppInfos: List<AppInfo>? = null private var runningDesktopAppInfosExceptHotseatItems: List<ItemInfo>? = null private val isInDesktopMode: Boolean get() = desktopVisibilityController?.areDesktopTasksVisible() ?: false override fun onDestroy() { super.onDestroy() apps = null } @VisibleForTesting public override fun setApps(apps: Array<AppInfo>?) { this.apps = apps } override fun isEnabled() = true @VisibleForTesting public override fun updateHotseatItemInfos(hotseatItems: Array<ItemInfo>?): Array<ItemInfo>? { val actualHotseatItems = hotseatItems ?: return super.updateHotseatItemInfos(null) if (!isInDesktopMode) { Log.d(TAG, "updateHotseatItemInfos: not in Desktop Mode") return hotseatItems } val newHotseatItemInfos = actualHotseatItems // Ignore predicted apps - we show running apps instead .filter { itemInfo -> !itemInfo.isPredictedItem } .toMutableList() val runningDesktopAppInfos = runningDesktopAppInfosExceptHotseatItems ?: return newHotseatItemInfos.toTypedArray() newHotseatItemInfos.addAll(runningDesktopAppInfos) return newHotseatItemInfos.toTypedArray() } @VisibleForTesting public override fun updateRunningApps(hotseatItems: SparseArray<ItemInfo>?) { if (!isInDesktopMode) { Log.d(TAG, "updateRunningApps: not in Desktop Mode") mControllers.taskbarViewController.commitRunningAppsToUI() return } val allRunningDesktopAppInfos = getRunningDesktopAppInfos() this.allRunningDesktopAppInfos = allRunningDesktopAppInfos runningDesktopAppInfosExceptHotseatItems = hotseatItems?.let { getRunningDesktopAppInfosExceptHotseatApps(allRunningDesktopAppInfos, it.toList()) } mControllers.taskbarViewController.commitRunningAppsToUI() } private fun getRunningDesktopAppInfosExceptHotseatApps( allRunningDesktopAppInfos: List<AppInfo>, hotseatItems: List<ItemInfo> ): List<ItemInfo> { val hotseatPackages = hotseatItems.map { it.targetPackage } return allRunningDesktopAppInfos .filter { appInfo -> !hotseatPackages.contains(appInfo.targetPackage) } .map { WorkspaceItemInfo(it) } } private fun getRunningDesktopAppInfos(): List<AppInfo> { return getAppInfosFromRunningTasks( recentsModel.runningTasks .filter { taskInfo: RunningTaskInfo -> taskInfo.windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM } .toList() ) } // TODO(b/335398876) fetch app icons from Tasks instead of AppInfos private fun getAppInfosFromRunningTasks(tasks: List<RunningTaskInfo>): List<AppInfo> { // Early return if apps is empty, since we then have no AppInfo to compare to if (apps == null) { return emptyList() } val packageNames = tasks.map { it.realActivity?.packageName }.distinct().filterNotNull() return packageNames .map { packageName -> apps?.find { app -> packageName == app.targetPackage } } .filterNotNull() } private fun <E> SparseArray<E>.toList(): List<E> { return valueIterator().asSequence().toList() } companion object { private const val TAG = "TabletDesktopTaskbarRunningAppsController" } } quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +19 −5 Original line number Diff line number Diff line Loading @@ -41,6 +41,8 @@ import static com.android.launcher3.testing.shared.ResourceUtils.getBoolByName; import static com.android.quickstep.util.AnimUtils.completeRunnableListCallback; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING; import static com.android.window.flags.Flags.enableDesktopWindowingMode; import static com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps; import android.animation.AnimatorSet; import android.animation.ValueAnimator; Loading Loading @@ -127,7 +129,9 @@ import com.android.launcher3.util.TraceHelper; import com.android.launcher3.util.VibratorWrapper; import com.android.launcher3.util.ViewCache; import com.android.launcher3.views.ActivityContext; import com.android.quickstep.LauncherActivityInterface; import com.android.quickstep.NavHandle; import com.android.quickstep.RecentsModel; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.Task; Loading Loading @@ -244,7 +248,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { mAccessibilityDelegate = new TaskbarShortcutMenuAccessibilityDelegate(this); final boolean isDesktopMode = getPackageManager().hasSystemFeature(FEATURE_PC); final boolean isPcMode = getPackageManager().hasSystemFeature(FEATURE_PC); // If Bubble bar is present, TaskbarControllers depends on it so build it first. Optional<BubbleControllers> bubbleControllersOptional = Optional.empty(); Loading Loading @@ -276,7 +280,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { mControllers = new TaskbarControllers(this, new TaskbarDragController(this), buttonController, isDesktopMode isPcMode ? new DesktopNavbarButtonsViewController(this, mNavigationBarPanelContext, navButtonsView) : new NavbarButtonsViewController(this, mNavigationBarPanelContext, Loading @@ -301,9 +305,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { new VoiceInteractionWindowController(this), new TaskbarTranslationController(this), new TaskbarSpringOnStashController(this), isDesktopMode ? new DesktopTaskbarRecentAppsController(this) : TaskbarRecentAppsController.DEFAULT, createTaskbarRecentAppsController(isPcMode), new TaskbarEduTooltipController(this), new KeyboardQuickSwitchController(), new TaskbarPinningController(this), Loading @@ -312,6 +314,18 @@ public class TaskbarActivityContext extends BaseTaskbarContext { mLauncherPrefs = LauncherPrefs.get(this); } private TaskbarRecentAppsController createTaskbarRecentAppsController(boolean isPcMode) { if (isPcMode) return new DesktopTaskbarRecentAppsController(this); // TODO(b/335401172): unify DesktopMode checks in Launcher final boolean showRunningAppsInDesktopMode = enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps(); return showRunningAppsInDesktopMode ? new DesktopTaskbarRunningAppsController( RecentsModel.INSTANCE.get(this), LauncherActivityInterface.INSTANCE.getDesktopVisibilityController()) : TaskbarRecentAppsController.DEFAULT; } /** Updates {@link DeviceProfile} instances for any Taskbar windows. */ public void updateDeviceProfile(DeviceProfile launcherDp) { applyDeviceProfile(launcherDp); Loading quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java +30 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,9 @@ */ package com.android.launcher3.taskbar; import static com.android.window.flags.Flags.enableDesktopWindowingMode; import static com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps; import android.util.SparseArray; import android.view.View; Loading @@ -26,6 +29,7 @@ import com.android.launcher3.model.BgDataModel.FixedContainerItems; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.statehandlers.DesktopVisibilityController; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSet; Loading @@ -33,6 +37,7 @@ import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.LauncherBindableItemsContainer; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.Preconditions; import com.android.quickstep.LauncherActivityInterface; import com.android.quickstep.RecentsModel; import java.io.PrintWriter; Loading Loading @@ -62,6 +67,8 @@ public class TaskbarModelCallbacks implements // Used to defer any UI updates during the SUW unstash animation. private boolean mDeferUpdatesForSUW; private Runnable mDeferredUpdates; private DesktopVisibilityController.DesktopVisibilityListener mDesktopVisibilityListener = visible -> updateRunningApps(); public TaskbarModelCallbacks( TaskbarActivityContext context, TaskbarView container) { Loading @@ -73,6 +80,15 @@ public class TaskbarModelCallbacks implements mControllers = controllers; if (mControllers.taskbarRecentAppsController.isEnabled()) { RecentsModel.INSTANCE.get(mContext).registerRunningTasksListener(this); if (shouldShowRunningAppsInDesktopMode()) { DesktopVisibilityController desktopVisibilityController = LauncherActivityInterface.INSTANCE.getDesktopVisibilityController(); if (desktopVisibilityController != null) { desktopVisibilityController.registerDesktopVisibilityListener( mDesktopVisibilityListener); } } } } Loading @@ -81,6 +97,20 @@ public class TaskbarModelCallbacks implements */ public void unregisterListeners() { RecentsModel.INSTANCE.get(mContext).unregisterRunningTasksListener(); if (shouldShowRunningAppsInDesktopMode()) { DesktopVisibilityController desktopVisibilityController = LauncherActivityInterface.INSTANCE.getDesktopVisibilityController(); if (desktopVisibilityController != null) { desktopVisibilityController.unregisterDesktopVisibilityListener( mDesktopVisibilityListener); } } } private boolean shouldShowRunningAppsInDesktopMode() { // TODO(b/335401172): unify DesktopMode checks in Launcher return enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps(); } @Override Loading quickstep/src/com/android/quickstep/SystemUiProxy.java +10 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.quickstep; import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE; import static android.content.pm.PackageManager.FEATURE_PC; import static com.android.launcher3.Flags.enableUnfoldStateAnimation; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; Loading @@ -23,6 +24,8 @@ import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.launcher3.util.SplitConfigurationOptions.StagePosition; import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.RECENT_TASKS_MISSING; import static com.android.quickstep.util.LogUtils.splitFailureMessage; import static com.android.window.flags.Flags.enableDesktopWindowingMode; import static com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps; import android.app.ActivityManager; import android.app.ActivityOptions; Loading @@ -32,7 +35,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ShortcutInfo; import android.graphics.Point; import android.graphics.Rect; Loading Loading @@ -1366,8 +1368,7 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle { * Gets the set of running tasks. */ public ArrayList<ActivityManager.RunningTaskInfo> getRunningTasks(int numTasks) { if (mRecentTasks != null && mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PC)) { if (mRecentTasks != null && shouldEnableRunningTasksForDesktopMode()) { try { return new ArrayList<>(Arrays.asList(mRecentTasks.getRunningTasks(numTasks))); } catch (RemoteException e) { Loading @@ -1377,6 +1378,12 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle { return new ArrayList<>(); } private boolean shouldEnableRunningTasksForDesktopMode() { // TODO(b/335401172): unify DesktopMode checks in Launcher return (enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps()) || mContext.getPackageManager().hasSystemFeature(FEATURE_PC); } private boolean handleMessageAsync(Message msg) { switch (msg.what) { case MSG_SET_SHELF_HEIGHT: Loading Loading
quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java +46 −1 Original line number Diff line number Diff line Loading @@ -37,6 +37,9 @@ import com.android.quickstep.SystemUiProxy; import com.android.quickstep.views.DesktopAppSelectView; import com.android.wm.shell.desktopmode.IDesktopTaskListener; import java.util.HashSet; import java.util.Set; /** * Controls the visibility of the workspace and the resumed / paused state when desktop mode * is enabled. Loading @@ -48,6 +51,7 @@ public class DesktopVisibilityController { private static final boolean IS_STASHING_ENABLED = SystemProperties.getBoolean( "persist.wm.debug.desktop_stashing", false); private final Launcher mLauncher; private final Set<DesktopVisibilityListener> mDesktopVisibilityListeners = new HashSet<>(); private int mVisibleDesktopTasksCount; private boolean mInOverviewState; Loading Loading @@ -127,6 +131,16 @@ public class DesktopVisibilityController { return mVisibleDesktopTasksCount; } /** Registers a listener for Desktop Mode visibility updates. */ public void registerDesktopVisibilityListener(DesktopVisibilityListener listener) { mDesktopVisibilityListeners.add(listener); } /** Removes a previously registered Desktop Mode visibility listener. */ public void unregisterDesktopVisibilityListener(DesktopVisibilityListener listener) { mDesktopVisibilityListeners.remove(listener); } /** * Sets the number of desktop windows that are visible and updates launcher visibility based on * it. Loading @@ -140,7 +154,12 @@ public class DesktopVisibilityController { if (visibleTasksCount != mVisibleDesktopTasksCount) { final boolean wasVisible = mVisibleDesktopTasksCount > 0; final boolean isVisible = visibleTasksCount > 0; final boolean wereDesktopTasksVisibleBefore = areDesktopTasksVisible(); mVisibleDesktopTasksCount = visibleTasksCount; final boolean areDesktopTasksVisibleNow = areDesktopTasksVisible(); if (wereDesktopTasksVisibleBefore != areDesktopTasksVisibleNow) { notifyDesktopVisibilityListeners(areDesktopTasksVisibleNow); } if (!enableDesktopWindowingWallpaperActivity() && wasVisible != isVisible) { // TODO: b/333533253 - Remove after flag rollout Loading Loading @@ -179,15 +198,22 @@ public class DesktopVisibilityController { + " currentValue=" + mInOverviewState); } if (overviewStateEnabled != mInOverviewState) { final boolean wereDesktopTasksVisibleBefore = areDesktopTasksVisible(); mInOverviewState = overviewStateEnabled; final boolean areDesktopTasksVisibleNow = areDesktopTasksVisible(); if (wereDesktopTasksVisibleBefore != areDesktopTasksVisibleNow) { notifyDesktopVisibilityListeners(areDesktopTasksVisibleNow); } if (enableDesktopWindowingWallpaperActivity()) { return; } // TODO: b/333533253 - Clean up after flag rollout if (mInOverviewState) { setLauncherViewsVisibility(View.VISIBLE); markLauncherResumed(); } else if (areDesktopTasksVisible() && !mGestureInProgress) { } else if (areDesktopTasksVisibleNow && !mGestureInProgress) { // Switching out of overview state and gesture finished. // If desktop tasks are still visible, hide launcher again. setLauncherViewsVisibility(View.INVISIBLE); Loading @@ -196,6 +222,15 @@ public class DesktopVisibilityController { } } private void notifyDesktopVisibilityListeners(boolean areDesktopTasksVisible) { if (DEBUG) { Log.d(TAG, "notifyDesktopVisibilityListeners: visible=" + areDesktopTasksVisible); } for (DesktopVisibilityListener listener : mDesktopVisibilityListeners) { listener.onDesktopVisibilityChanged(areDesktopTasksVisible); } } /** * TODO: b/333533253 - Remove after flag rollout */ Loading Loading @@ -359,4 +394,14 @@ public class DesktopVisibilityController { mSelectAppToast.hide(); mSelectAppToast = null; } /** A listener for when the user enters/exits Desktop Mode. */ public interface DesktopVisibilityListener { /** * Callback for when the user enters or exits Desktop Mode * * @param visible whether Desktop Mode is now visible */ void onDesktopVisibilityChanged(boolean visible); } }
quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarRunningAppsController.kt 0 → 100644 +139 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.launcher3.taskbar import android.app.ActivityManager.RunningTaskInfo import android.app.WindowConfiguration import android.util.Log import android.util.SparseArray import androidx.annotation.VisibleForTesting import androidx.core.util.valueIterator import com.android.launcher3.model.data.AppInfo import com.android.launcher3.model.data.ItemInfo import com.android.launcher3.model.data.WorkspaceItemInfo import com.android.launcher3.statehandlers.DesktopVisibilityController import com.android.quickstep.RecentsModel import kotlin.collections.filterNotNull /** * Shows running apps when in Desktop Mode. * * Users can enter and exit Desktop Mode at run-time, meaning this class falls back to the default * recent-apps behaviour when outside of Desktop Mode. * * This class should only be used if * [com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps] is enabled. */ class DesktopTaskbarRunningAppsController( private val recentsModel: RecentsModel, private val desktopVisibilityController: DesktopVisibilityController?, ) : TaskbarRecentAppsController() { private var apps: Array<AppInfo>? = null private var allRunningDesktopAppInfos: List<AppInfo>? = null private var runningDesktopAppInfosExceptHotseatItems: List<ItemInfo>? = null private val isInDesktopMode: Boolean get() = desktopVisibilityController?.areDesktopTasksVisible() ?: false override fun onDestroy() { super.onDestroy() apps = null } @VisibleForTesting public override fun setApps(apps: Array<AppInfo>?) { this.apps = apps } override fun isEnabled() = true @VisibleForTesting public override fun updateHotseatItemInfos(hotseatItems: Array<ItemInfo>?): Array<ItemInfo>? { val actualHotseatItems = hotseatItems ?: return super.updateHotseatItemInfos(null) if (!isInDesktopMode) { Log.d(TAG, "updateHotseatItemInfos: not in Desktop Mode") return hotseatItems } val newHotseatItemInfos = actualHotseatItems // Ignore predicted apps - we show running apps instead .filter { itemInfo -> !itemInfo.isPredictedItem } .toMutableList() val runningDesktopAppInfos = runningDesktopAppInfosExceptHotseatItems ?: return newHotseatItemInfos.toTypedArray() newHotseatItemInfos.addAll(runningDesktopAppInfos) return newHotseatItemInfos.toTypedArray() } @VisibleForTesting public override fun updateRunningApps(hotseatItems: SparseArray<ItemInfo>?) { if (!isInDesktopMode) { Log.d(TAG, "updateRunningApps: not in Desktop Mode") mControllers.taskbarViewController.commitRunningAppsToUI() return } val allRunningDesktopAppInfos = getRunningDesktopAppInfos() this.allRunningDesktopAppInfos = allRunningDesktopAppInfos runningDesktopAppInfosExceptHotseatItems = hotseatItems?.let { getRunningDesktopAppInfosExceptHotseatApps(allRunningDesktopAppInfos, it.toList()) } mControllers.taskbarViewController.commitRunningAppsToUI() } private fun getRunningDesktopAppInfosExceptHotseatApps( allRunningDesktopAppInfos: List<AppInfo>, hotseatItems: List<ItemInfo> ): List<ItemInfo> { val hotseatPackages = hotseatItems.map { it.targetPackage } return allRunningDesktopAppInfos .filter { appInfo -> !hotseatPackages.contains(appInfo.targetPackage) } .map { WorkspaceItemInfo(it) } } private fun getRunningDesktopAppInfos(): List<AppInfo> { return getAppInfosFromRunningTasks( recentsModel.runningTasks .filter { taskInfo: RunningTaskInfo -> taskInfo.windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM } .toList() ) } // TODO(b/335398876) fetch app icons from Tasks instead of AppInfos private fun getAppInfosFromRunningTasks(tasks: List<RunningTaskInfo>): List<AppInfo> { // Early return if apps is empty, since we then have no AppInfo to compare to if (apps == null) { return emptyList() } val packageNames = tasks.map { it.realActivity?.packageName }.distinct().filterNotNull() return packageNames .map { packageName -> apps?.find { app -> packageName == app.targetPackage } } .filterNotNull() } private fun <E> SparseArray<E>.toList(): List<E> { return valueIterator().asSequence().toList() } companion object { private const val TAG = "TabletDesktopTaskbarRunningAppsController" } }
quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +19 −5 Original line number Diff line number Diff line Loading @@ -41,6 +41,8 @@ import static com.android.launcher3.testing.shared.ResourceUtils.getBoolByName; import static com.android.quickstep.util.AnimUtils.completeRunnableListCallback; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING; import static com.android.window.flags.Flags.enableDesktopWindowingMode; import static com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps; import android.animation.AnimatorSet; import android.animation.ValueAnimator; Loading Loading @@ -127,7 +129,9 @@ import com.android.launcher3.util.TraceHelper; import com.android.launcher3.util.VibratorWrapper; import com.android.launcher3.util.ViewCache; import com.android.launcher3.views.ActivityContext; import com.android.quickstep.LauncherActivityInterface; import com.android.quickstep.NavHandle; import com.android.quickstep.RecentsModel; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.Task; Loading Loading @@ -244,7 +248,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { mAccessibilityDelegate = new TaskbarShortcutMenuAccessibilityDelegate(this); final boolean isDesktopMode = getPackageManager().hasSystemFeature(FEATURE_PC); final boolean isPcMode = getPackageManager().hasSystemFeature(FEATURE_PC); // If Bubble bar is present, TaskbarControllers depends on it so build it first. Optional<BubbleControllers> bubbleControllersOptional = Optional.empty(); Loading Loading @@ -276,7 +280,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { mControllers = new TaskbarControllers(this, new TaskbarDragController(this), buttonController, isDesktopMode isPcMode ? new DesktopNavbarButtonsViewController(this, mNavigationBarPanelContext, navButtonsView) : new NavbarButtonsViewController(this, mNavigationBarPanelContext, Loading @@ -301,9 +305,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { new VoiceInteractionWindowController(this), new TaskbarTranslationController(this), new TaskbarSpringOnStashController(this), isDesktopMode ? new DesktopTaskbarRecentAppsController(this) : TaskbarRecentAppsController.DEFAULT, createTaskbarRecentAppsController(isPcMode), new TaskbarEduTooltipController(this), new KeyboardQuickSwitchController(), new TaskbarPinningController(this), Loading @@ -312,6 +314,18 @@ public class TaskbarActivityContext extends BaseTaskbarContext { mLauncherPrefs = LauncherPrefs.get(this); } private TaskbarRecentAppsController createTaskbarRecentAppsController(boolean isPcMode) { if (isPcMode) return new DesktopTaskbarRecentAppsController(this); // TODO(b/335401172): unify DesktopMode checks in Launcher final boolean showRunningAppsInDesktopMode = enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps(); return showRunningAppsInDesktopMode ? new DesktopTaskbarRunningAppsController( RecentsModel.INSTANCE.get(this), LauncherActivityInterface.INSTANCE.getDesktopVisibilityController()) : TaskbarRecentAppsController.DEFAULT; } /** Updates {@link DeviceProfile} instances for any Taskbar windows. */ public void updateDeviceProfile(DeviceProfile launcherDp) { applyDeviceProfile(launcherDp); Loading
quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java +30 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,9 @@ */ package com.android.launcher3.taskbar; import static com.android.window.flags.Flags.enableDesktopWindowingMode; import static com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps; import android.util.SparseArray; import android.view.View; Loading @@ -26,6 +29,7 @@ import com.android.launcher3.model.BgDataModel.FixedContainerItems; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.statehandlers.DesktopVisibilityController; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSet; Loading @@ -33,6 +37,7 @@ import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.LauncherBindableItemsContainer; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.Preconditions; import com.android.quickstep.LauncherActivityInterface; import com.android.quickstep.RecentsModel; import java.io.PrintWriter; Loading Loading @@ -62,6 +67,8 @@ public class TaskbarModelCallbacks implements // Used to defer any UI updates during the SUW unstash animation. private boolean mDeferUpdatesForSUW; private Runnable mDeferredUpdates; private DesktopVisibilityController.DesktopVisibilityListener mDesktopVisibilityListener = visible -> updateRunningApps(); public TaskbarModelCallbacks( TaskbarActivityContext context, TaskbarView container) { Loading @@ -73,6 +80,15 @@ public class TaskbarModelCallbacks implements mControllers = controllers; if (mControllers.taskbarRecentAppsController.isEnabled()) { RecentsModel.INSTANCE.get(mContext).registerRunningTasksListener(this); if (shouldShowRunningAppsInDesktopMode()) { DesktopVisibilityController desktopVisibilityController = LauncherActivityInterface.INSTANCE.getDesktopVisibilityController(); if (desktopVisibilityController != null) { desktopVisibilityController.registerDesktopVisibilityListener( mDesktopVisibilityListener); } } } } Loading @@ -81,6 +97,20 @@ public class TaskbarModelCallbacks implements */ public void unregisterListeners() { RecentsModel.INSTANCE.get(mContext).unregisterRunningTasksListener(); if (shouldShowRunningAppsInDesktopMode()) { DesktopVisibilityController desktopVisibilityController = LauncherActivityInterface.INSTANCE.getDesktopVisibilityController(); if (desktopVisibilityController != null) { desktopVisibilityController.unregisterDesktopVisibilityListener( mDesktopVisibilityListener); } } } private boolean shouldShowRunningAppsInDesktopMode() { // TODO(b/335401172): unify DesktopMode checks in Launcher return enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps(); } @Override Loading
quickstep/src/com/android/quickstep/SystemUiProxy.java +10 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.quickstep; import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE; import static android.content.pm.PackageManager.FEATURE_PC; import static com.android.launcher3.Flags.enableUnfoldStateAnimation; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; Loading @@ -23,6 +24,8 @@ import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.launcher3.util.SplitConfigurationOptions.StagePosition; import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.RECENT_TASKS_MISSING; import static com.android.quickstep.util.LogUtils.splitFailureMessage; import static com.android.window.flags.Flags.enableDesktopWindowingMode; import static com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps; import android.app.ActivityManager; import android.app.ActivityOptions; Loading @@ -32,7 +35,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ShortcutInfo; import android.graphics.Point; import android.graphics.Rect; Loading Loading @@ -1366,8 +1368,7 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle { * Gets the set of running tasks. */ public ArrayList<ActivityManager.RunningTaskInfo> getRunningTasks(int numTasks) { if (mRecentTasks != null && mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PC)) { if (mRecentTasks != null && shouldEnableRunningTasksForDesktopMode()) { try { return new ArrayList<>(Arrays.asList(mRecentTasks.getRunningTasks(numTasks))); } catch (RemoteException e) { Loading @@ -1377,6 +1378,12 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle { return new ArrayList<>(); } private boolean shouldEnableRunningTasksForDesktopMode() { // TODO(b/335401172): unify DesktopMode checks in Launcher return (enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps()) || mContext.getPackageManager().hasSystemFeature(FEATURE_PC); } private boolean handleMessageAsync(Message msg) { switch (msg.what) { case MSG_SET_SHELF_HEIGHT: Loading