Snap for 11954976 from a8f0155c89 to 24Q3-release
Change-Id: Ic44cd683f66940661c2a6d3a7274b1438ed3098c
This commit is contained in:
@@ -284,3 +284,21 @@ flag {
|
||||
description: "Enables folders in all apps"
|
||||
bug: "341582436"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_recents_in_taskbar"
|
||||
namespace: "launcher"
|
||||
description: "Replace hybrid hotseat app predictions with strictly Recent Apps"
|
||||
bug: "315354060"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "enable_first_screen_broadcast_archiving_extras"
|
||||
namespace: "launcher"
|
||||
description: "adds Extras to first screen broadcast for archived apps"
|
||||
bug: "322314760"
|
||||
is_fixed_read_only: true
|
||||
metadata {
|
||||
purpose: PURPOSE_BUGFIX
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,6 @@ import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
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 static com.android.wm.shell.Flags.enableTinyTaskbar;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
@@ -304,7 +302,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
new VoiceInteractionWindowController(this),
|
||||
new TaskbarTranslationController(this),
|
||||
new TaskbarSpringOnStashController(this),
|
||||
createTaskbarRecentAppsController(),
|
||||
new TaskbarRecentAppsController(
|
||||
RecentsModel.INSTANCE.get(this),
|
||||
LauncherActivityInterface.INSTANCE::getDesktopVisibilityController),
|
||||
TaskbarEduTooltipController.newInstance(this),
|
||||
new KeyboardQuickSwitchController(),
|
||||
new TaskbarPinningController(this, () ->
|
||||
@@ -314,16 +314,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
mLauncherPrefs = LauncherPrefs.get(this);
|
||||
}
|
||||
|
||||
private TaskbarRecentAppsController createTaskbarRecentAppsController() {
|
||||
// TODO(b/335401172): unify DesktopMode checks in Launcher
|
||||
if (enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps()) {
|
||||
return new DesktopTaskbarRunningAppsController(
|
||||
RecentsModel.INSTANCE.get(this),
|
||||
LauncherActivityInterface.INSTANCE::getDesktopVisibilityController);
|
||||
}
|
||||
return TaskbarRecentAppsController.DEFAULT;
|
||||
}
|
||||
|
||||
/** Updates {@link DeviceProfile} instances for any Taskbar windows. */
|
||||
public void updateDeviceProfile(DeviceProfile launcherDp) {
|
||||
applyDeviceProfile(launcherDp);
|
||||
|
||||
@@ -180,8 +180,9 @@ public class TaskbarControllers {
|
||||
taskbarUnfoldAnimationController, taskbarKeyguardController,
|
||||
stashedHandleViewController, taskbarStashController,
|
||||
taskbarAutohideSuspendController, taskbarPopupController, taskbarInsetsController,
|
||||
voiceInteractionWindowController, taskbarTranslationController,
|
||||
taskbarEduTooltipController, keyboardQuickSwitchController, taskbarPinningController
|
||||
voiceInteractionWindowController, taskbarRecentAppsController,
|
||||
taskbarTranslationController, taskbarEduTooltipController,
|
||||
keyboardQuickSwitchController, taskbarPinningController,
|
||||
};
|
||||
mBackgroundRendererControllers = new BackgroundRendererController[] {
|
||||
taskbarDragLayerController, taskbarScrimViewController,
|
||||
|
||||
@@ -5,9 +5,6 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISABLED;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DOZING;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DEVICE_DREAMING;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_WAKEFULNESS_MASK;
|
||||
@@ -16,6 +13,7 @@ import static com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_A
|
||||
import android.app.KeyguardManager;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.quickstep.util.SystemUiFlagUtils;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
|
||||
|
||||
@@ -26,19 +24,6 @@ import java.io.PrintWriter;
|
||||
*/
|
||||
public class TaskbarKeyguardController implements TaskbarControllers.LoggableTaskbarController {
|
||||
|
||||
private static final long KEYGUARD_SYSUI_FLAGS = SYSUI_STATE_BOUNCER_SHOWING
|
||||
| SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING | SYSUI_STATE_DEVICE_DOZING
|
||||
| SYSUI_STATE_OVERVIEW_DISABLED | SYSUI_STATE_HOME_DISABLED
|
||||
| SYSUI_STATE_BACK_DISABLED | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
|
||||
| SYSUI_STATE_WAKEFULNESS_MASK;
|
||||
|
||||
// If any of these SysUi flags (via QuickstepContract) is set, the device to be considered
|
||||
// locked.
|
||||
public static final long MASK_ANY_SYSUI_LOCKED = SYSUI_STATE_BOUNCER_SHOWING
|
||||
| SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
|
||||
| SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
|
||||
| SYSUI_STATE_DEVICE_DREAMING;
|
||||
|
||||
private final TaskbarActivityContext mContext;
|
||||
private long mKeyguardSysuiFlags;
|
||||
private boolean mBouncerShowing;
|
||||
@@ -55,7 +40,7 @@ public class TaskbarKeyguardController implements TaskbarControllers.LoggableTas
|
||||
}
|
||||
|
||||
public void updateStateForSysuiFlags(@SystemUiStateFlags long systemUiStateFlags) {
|
||||
long interestingKeyguardFlags = systemUiStateFlags & KEYGUARD_SYSUI_FLAGS;
|
||||
long interestingKeyguardFlags = systemUiStateFlags & SystemUiFlagUtils.KEYGUARD_SYSUI_FLAGS;
|
||||
if (interestingKeyguardFlags == mKeyguardSysuiFlags) {
|
||||
// No change in keyguard relevant flags
|
||||
return;
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.android.launcher3.taskbar;
|
||||
|
||||
import static com.android.app.animation.Interpolators.EMPHASIZED;
|
||||
import static com.android.launcher3.taskbar.TaskbarKeyguardController.MASK_ANY_SYSUI_LOCKED;
|
||||
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
|
||||
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_OVERVIEW;
|
||||
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_STASHED_LAUNCHER_STATE;
|
||||
@@ -51,6 +50,7 @@ import com.android.launcher3.uioverrides.QuickstepLauncher;
|
||||
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
|
||||
import com.android.quickstep.RecentsAnimationCallbacks;
|
||||
import com.android.quickstep.RecentsAnimationController;
|
||||
import com.android.quickstep.util.SystemUiFlagUtils;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.systemui.animation.ViewRootSync;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
@@ -343,8 +343,7 @@ public class TaskbarLauncherStateController {
|
||||
prevIsAwake && hasAnyFlag(FLAGS_LAUNCHER_ACTIVE));
|
||||
}
|
||||
|
||||
boolean isDeviceLocked = hasAnyFlag(systemUiStateFlags, MASK_ANY_SYSUI_LOCKED);
|
||||
updateStateForFlag(FLAG_DEVICE_LOCKED, isDeviceLocked);
|
||||
updateStateForFlag(FLAG_DEVICE_LOCKED, SystemUiFlagUtils.isLocked(systemUiStateFlags));
|
||||
|
||||
// Taskbar is hidden whenever the device is dreaming. The dreaming state includes the
|
||||
// interactive dreams, AoD, screen off. Since the SYSUI_STATE_DEVICE_DREAMING only kicks in
|
||||
|
||||
@@ -79,7 +79,7 @@ public class TaskbarModelCallbacks implements
|
||||
|
||||
public void init(TaskbarControllers controllers) {
|
||||
mControllers = controllers;
|
||||
if (mControllers.taskbarRecentAppsController.isEnabled()) {
|
||||
if (mControllers.taskbarRecentAppsController.getCanShowRunningApps()) {
|
||||
RecentsModel.INSTANCE.get(mContext).registerRunningTasksListener(this);
|
||||
|
||||
if (shouldShowRunningAppsInDesktopMode()) {
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 static java.util.Collections.emptySet;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Base class for providing recent apps functionality
|
||||
*/
|
||||
public class TaskbarRecentAppsController {
|
||||
|
||||
public static final TaskbarRecentAppsController DEFAULT = new TaskbarRecentAppsController();
|
||||
|
||||
// Initialized in init.
|
||||
protected TaskbarControllers mControllers;
|
||||
|
||||
@CallSuper
|
||||
protected void init(TaskbarControllers taskbarControllers) {
|
||||
mControllers = taskbarControllers;
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
protected void onDestroy() {
|
||||
mControllers = null;
|
||||
}
|
||||
|
||||
/** Stores the current {@link AppInfo} instances, no-op except in desktop environment. */
|
||||
protected void setApps(AppInfo[] apps) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether recent apps functionality is enabled, should return false except in
|
||||
* desktop environment.
|
||||
*/
|
||||
protected boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Called to update hotseatItems, no-op except in desktop environment. */
|
||||
protected ItemInfo[] updateHotseatItemInfos(@NonNull ItemInfo[] hotseatItems) {
|
||||
return hotseatItems;
|
||||
}
|
||||
|
||||
/** Called to update the list of currently running apps, no-op except in desktop environment. */
|
||||
protected void updateRunningApps() {}
|
||||
|
||||
/** Returns the currently running apps, or an empty Set if outside of Desktop environment. */
|
||||
public Set<String> getRunningApps() {
|
||||
return emptySet();
|
||||
}
|
||||
|
||||
/** Returns the set of apps whose tasks are all minimized. */
|
||||
public Set<String> getMinimizedApps() {
|
||||
return emptySet();
|
||||
}
|
||||
}
|
||||
+85
-78
@@ -13,37 +13,44 @@
|
||||
* 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.Flags.enableRecentsInTaskbar
|
||||
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.taskbar.TaskbarControllers.LoggableTaskbarController
|
||||
import com.android.quickstep.RecentsModel
|
||||
import kotlin.collections.filterNotNull
|
||||
import com.android.window.flags.Flags.enableDesktopWindowingMode
|
||||
import com.android.window.flags.Flags.enableDesktopWindowingTaskbarRunningApps
|
||||
import java.io.PrintWriter
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Provides recent apps functionality, when the Taskbar Recent Apps section is enabled. Behavior:
|
||||
* - When in Fullscreen mode: show the N most recent Tasks
|
||||
* - When in Desktop Mode: show the currently running (open) Tasks
|
||||
*/
|
||||
class DesktopTaskbarRunningAppsController(
|
||||
class TaskbarRecentAppsController(
|
||||
private val recentsModel: RecentsModel,
|
||||
// Pass a provider here instead of the actual DesktopVisibilityController instance since that
|
||||
// instance might not be available when this constructor is called.
|
||||
private val desktopVisibilityControllerProvider: () -> DesktopVisibilityController?,
|
||||
) : TaskbarRecentAppsController() {
|
||||
) : LoggableTaskbarController {
|
||||
|
||||
// TODO(b/335401172): unify DesktopMode checks in Launcher.
|
||||
val canShowRunningApps =
|
||||
enableDesktopWindowingMode() && enableDesktopWindowingTaskbarRunningApps()
|
||||
|
||||
// TODO(b/343532825): Add a setting to disable Recents even when the flag is on.
|
||||
@VisibleForTesting
|
||||
var isEnabled = enableRecentsInTaskbar() || canShowRunningApps
|
||||
|
||||
// Initialized in init.
|
||||
private lateinit var controllers: TaskbarControllers
|
||||
|
||||
private var apps: Array<AppInfo>? = null
|
||||
private var allRunningDesktopAppInfos: List<AppInfo>? = null
|
||||
@@ -55,22 +62,40 @@ class DesktopTaskbarRunningAppsController(
|
||||
private val isInDesktopMode: Boolean
|
||||
get() = desktopVisibilityController?.areDesktopTasksVisible() ?: false
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
val runningApps: Set<String>
|
||||
get() {
|
||||
if (!isEnabled || !isInDesktopMode) {
|
||||
return emptySet()
|
||||
}
|
||||
return allRunningDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet() ?: emptySet()
|
||||
}
|
||||
|
||||
val minimizedApps: Set<String>
|
||||
get() {
|
||||
if (!isInDesktopMode) {
|
||||
return emptySet()
|
||||
}
|
||||
return allMinimizedDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet()
|
||||
?: emptySet()
|
||||
}
|
||||
|
||||
fun init(taskbarControllers: TaskbarControllers) {
|
||||
controllers = taskbarControllers
|
||||
}
|
||||
|
||||
fun onDestroy() {
|
||||
apps = null
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public override fun setApps(apps: Array<AppInfo>?) {
|
||||
/** Stores the current [AppInfo] instances, no-op except in desktop environment. */
|
||||
fun setApps(apps: Array<AppInfo>?) {
|
||||
this.apps = apps
|
||||
}
|
||||
|
||||
override fun isEnabled() = true
|
||||
|
||||
@VisibleForTesting
|
||||
public override fun updateHotseatItemInfos(hotseatItems: Array<ItemInfo?>): Array<ItemInfo?> {
|
||||
if (!isInDesktopMode) {
|
||||
Log.d(TAG, "updateHotseatItemInfos: not in Desktop Mode")
|
||||
/** Called to update hotseatItems, in order to de-dupe them from Recent/Running tasks later. */
|
||||
// TODO(next CL): add new section of Tasks instead of changing Hotseat items
|
||||
fun updateHotseatItemInfos(hotseatItems: Array<ItemInfo?>): Array<ItemInfo?> {
|
||||
if (!isEnabled || !isInDesktopMode) {
|
||||
return hotseatItems
|
||||
}
|
||||
val newHotseatItemInfos =
|
||||
@@ -89,55 +114,6 @@ class DesktopTaskbarRunningAppsController(
|
||||
return newHotseatItemInfos.toTypedArray()
|
||||
}
|
||||
|
||||
override fun getRunningApps(): Set<String> {
|
||||
if (!isInDesktopMode) {
|
||||
return emptySet()
|
||||
}
|
||||
return allRunningDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet() ?: emptySet()
|
||||
}
|
||||
|
||||
override fun getMinimizedApps(): Set<String> {
|
||||
if (!isInDesktopMode) {
|
||||
return emptySet()
|
||||
}
|
||||
return allMinimizedDesktopAppInfos?.mapNotNull { it.targetPackage }?.toSet() ?: emptySet()
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public override fun updateRunningApps() {
|
||||
if (!isInDesktopMode) {
|
||||
Log.d(TAG, "updateRunningApps: not in Desktop Mode")
|
||||
mControllers.taskbarViewController.commitRunningAppsToUI()
|
||||
return
|
||||
}
|
||||
val runningTasks = getDesktopRunningTasks()
|
||||
val runningAppInfo = getAppInfosFromRunningTasks(runningTasks)
|
||||
allRunningDesktopAppInfos = runningAppInfo
|
||||
updateMinimizedApps(runningTasks, runningAppInfo)
|
||||
mControllers.taskbarViewController.commitRunningAppsToUI()
|
||||
}
|
||||
|
||||
private fun updateMinimizedApps(
|
||||
runningTasks: List<RunningTaskInfo>,
|
||||
runningAppInfo: List<AppInfo>,
|
||||
) {
|
||||
val allRunningAppTasks =
|
||||
runningAppInfo
|
||||
.mapNotNull { appInfo -> appInfo.targetPackage?.let { appInfo to it } }
|
||||
.associate { (appInfo, targetPackage) ->
|
||||
appInfo to
|
||||
runningTasks
|
||||
.filter { it.realActivity?.packageName == targetPackage }
|
||||
.map { it.taskId }
|
||||
}
|
||||
val minimizedTaskIds = runningTasks.associate { it.taskId to !it.isVisible }
|
||||
allMinimizedDesktopAppInfos =
|
||||
allRunningAppTasks
|
||||
.filterValues { taskIds -> taskIds.all { minimizedTaskIds[it] ?: false } }
|
||||
.keys
|
||||
.toList()
|
||||
}
|
||||
|
||||
private fun getRunningDesktopAppInfosExceptHotseatApps(
|
||||
allRunningDesktopAppInfos: List<AppInfo>,
|
||||
hotseatItems: List<ItemInfo>
|
||||
@@ -165,12 +141,43 @@ class DesktopTaskbarRunningAppsController(
|
||||
.filterNotNull()
|
||||
}
|
||||
|
||||
private fun getAppInfosFromRunningTask(task: RunningTaskInfo): AppInfo? =
|
||||
apps?.firstOrNull { it.targetPackage == task.realActivity?.packageName }
|
||||
/** Called to update the list of currently running apps, no-op except in desktop environment. */
|
||||
fun updateRunningApps() {
|
||||
if (!isEnabled || !isInDesktopMode) {
|
||||
return controllers.taskbarViewController.commitRunningAppsToUI()
|
||||
}
|
||||
val runningTasks = getDesktopRunningTasks()
|
||||
val runningAppInfo = getAppInfosFromRunningTasks(runningTasks)
|
||||
allRunningDesktopAppInfos = runningAppInfo
|
||||
updateMinimizedApps(runningTasks, runningAppInfo)
|
||||
controllers.taskbarViewController.commitRunningAppsToUI()
|
||||
}
|
||||
|
||||
private fun <E> SparseArray<E>.toList(): List<E> = valueIterator().asSequence().toList()
|
||||
private fun updateMinimizedApps(
|
||||
runningTasks: List<RunningTaskInfo>,
|
||||
runningAppInfo: List<AppInfo>,
|
||||
) {
|
||||
val allRunningAppTasks =
|
||||
runningAppInfo
|
||||
.mapNotNull { appInfo -> appInfo.targetPackage?.let { appInfo to it } }
|
||||
.associate { (appInfo, targetPackage) ->
|
||||
appInfo to
|
||||
runningTasks
|
||||
.filter { it.realActivity?.packageName == targetPackage }
|
||||
.map { it.taskId }
|
||||
}
|
||||
val minimizedTaskIds = runningTasks.associate { it.taskId to !it.isVisible }
|
||||
allMinimizedDesktopAppInfos =
|
||||
allRunningAppTasks
|
||||
.filterValues { taskIds -> taskIds.all { minimizedTaskIds[it] ?: false } }
|
||||
.keys
|
||||
.toList()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "TabletDesktopTaskbarRunningAppsController"
|
||||
override fun dumpLogs(prefix: String, pw: PrintWriter) {
|
||||
pw.println("$prefix TaskbarRecentAppsController:")
|
||||
pw.println("$prefix\tisEnabled=$isEnabled")
|
||||
pw.println("$prefix\tcanShowRunningApps=$canShowRunningApps")
|
||||
// TODO(next CL): add more logs
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@ import static com.android.internal.jank.InteractionJankMonitor.Configuration;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_HIDE;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_SHOW;
|
||||
import static com.android.launcher3.taskbar.TaskbarKeyguardController.MASK_ANY_SYSUI_LOCKED;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
import static com.android.launcher3.util.FlagDebugUtils.appendFlag;
|
||||
import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange;
|
||||
@@ -35,7 +34,6 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_I
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
@@ -66,6 +64,7 @@ import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
|
||||
import com.android.quickstep.LauncherActivityInterface;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.quickstep.util.SystemUiFlagUtils;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -950,9 +949,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
&& DisplayController.isTransientTaskbar(mActivity);
|
||||
updateStateForFlag(FLAG_STASHED_SYSUI,
|
||||
hasAnyFlag(systemUiStateFlags, SYSUI_STATE_SCREEN_PINNING) || stashForBubbles);
|
||||
boolean isLocked = hasAnyFlag(systemUiStateFlags, MASK_ANY_SYSUI_LOCKED)
|
||||
&& !hasAnyFlag(systemUiStateFlags, SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY);
|
||||
updateStateForFlag(FLAG_STASHED_DEVICE_LOCKED, isLocked);
|
||||
updateStateForFlag(FLAG_STASHED_DEVICE_LOCKED,
|
||||
SystemUiFlagUtils.isLocked(systemUiStateFlags));
|
||||
|
||||
mIsImeShowing = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_IME_SHOWING);
|
||||
mIsImeSwitcherShowing = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_IME_SWITCHER_SHOWING);
|
||||
|
||||
@@ -153,6 +153,7 @@ public class BubbleDragController {
|
||||
@Override
|
||||
protected void onDragDismiss() {
|
||||
mBubblePinController.onDragEnd();
|
||||
mBubbleBarViewController.onBubbleDragEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1614,7 +1614,8 @@ public abstract class AbsSwipeUpHandler<T extends RecentsViewContainer,
|
||||
mSwipePipToHomeAnimator.getComponentName(),
|
||||
mSwipePipToHomeAnimator.getDestinationBounds(),
|
||||
mSwipePipToHomeAnimator.getContentOverlay(),
|
||||
mSwipePipToHomeAnimator.getAppBounds());
|
||||
mSwipePipToHomeAnimator.getAppBounds(),
|
||||
mSwipePipToHomeAnimator.getSourceRectHint());
|
||||
|
||||
windowAnim = mSwipePipToHomeAnimators;
|
||||
} else {
|
||||
|
||||
@@ -684,11 +684,11 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable {
|
||||
* should be responsible for cleaning up the overlay.
|
||||
*/
|
||||
public void stopSwipePipToHome(int taskId, ComponentName componentName, Rect destinationBounds,
|
||||
SurfaceControl overlay, Rect appBounds) {
|
||||
SurfaceControl overlay, Rect appBounds, Rect sourceRectHint) {
|
||||
if (mPip != null) {
|
||||
try {
|
||||
mPip.stopSwipePipToHome(taskId, componentName, destinationBounds, overlay,
|
||||
appBounds);
|
||||
appBounds, sourceRectHint);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call stopSwipePipToHome");
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ import static com.android.quickstep.GestureState.STATE_END_TARGET_ANIMATION_FINI
|
||||
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED;
|
||||
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED;
|
||||
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.START_RECENTS_ANIMATION;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityOptions;
|
||||
@@ -44,9 +46,11 @@ import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.quickstep.util.ActiveGestureLog;
|
||||
import com.android.quickstep.util.SystemUiFlagUtils;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListener;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListeners;
|
||||
|
||||
@@ -373,20 +377,54 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
||||
return mCallbacks;
|
||||
}
|
||||
|
||||
public void endLiveTile() {
|
||||
if (mLastGestureState == null) {
|
||||
return;
|
||||
}
|
||||
BaseContainerInterface containerInterface = mLastGestureState.getContainerInterface();
|
||||
if (containerInterface.isInLiveTileMode()
|
||||
&& containerInterface.getCreatedContainer() != null) {
|
||||
RecentsView recentsView = containerInterface.getCreatedContainer().getOverviewPanel();
|
||||
if (recentsView != null) {
|
||||
recentsView.switchToScreenshot(null,
|
||||
() -> recentsView.finishRecentsAnimation(true /* toRecents */,
|
||||
false /* shouldPip */, null));
|
||||
public void onSystemUiFlagsChanged(@QuickStepContract.SystemUiStateFlags long lastSysUIFlags,
|
||||
@QuickStepContract.SystemUiStateFlags long newSysUIFlags) {
|
||||
long isShadeExpandedFlagMask =
|
||||
SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED | SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
|
||||
boolean wasExpanded = hasAnyFlag(lastSysUIFlags, isShadeExpandedFlagMask);
|
||||
boolean isExpanded = hasAnyFlag(newSysUIFlags, isShadeExpandedFlagMask);
|
||||
if (wasExpanded != isExpanded && isExpanded) {
|
||||
// End live tile when expanding the notification panel for the first time from
|
||||
// overview.
|
||||
if (endLiveTile()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
boolean wasLocked = SystemUiFlagUtils.isLocked(lastSysUIFlags);
|
||||
boolean isLocked = SystemUiFlagUtils.isLocked(newSysUIFlags);
|
||||
if (wasLocked != isLocked && isLocked) {
|
||||
// Finish the running recents animation when locking the device.
|
||||
finishRunningRecentsAnimation(
|
||||
mController != null && mController.getFinishTargetIsLauncher());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasAnyFlag(long flags, long flagMask) {
|
||||
return (flags & flagMask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches the {@link RecentsView} to screenshot if in live tile mode.
|
||||
*
|
||||
* @return true iff the {@link RecentsView} was in live tile mode and was switched to screenshot
|
||||
*/
|
||||
public boolean endLiveTile() {
|
||||
if (mLastGestureState == null) {
|
||||
return false;
|
||||
}
|
||||
BaseContainerInterface containerInterface = mLastGestureState.getContainerInterface();
|
||||
if (!containerInterface.isInLiveTileMode()
|
||||
|| containerInterface.getCreatedContainer() == null) {
|
||||
return false;
|
||||
}
|
||||
RecentsView recentsView = containerInterface.getCreatedContainer().getOverviewPanel();
|
||||
if (recentsView == null) {
|
||||
return false;
|
||||
}
|
||||
recentsView.switchToScreenshot(null, () -> recentsView.finishRecentsAnimation(
|
||||
true /* toRecents */, false /* shouldPip */, null));
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setLiveTileCleanUpHandler(Runnable cleanUpHandler) {
|
||||
|
||||
@@ -47,8 +47,6 @@ import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SY
|
||||
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
|
||||
import static com.android.wm.shell.Flags.enableBubblesLongPressNavHandle;
|
||||
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION;
|
||||
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BUBBLES;
|
||||
@@ -719,16 +717,7 @@ public class TouchInteractionService extends Service {
|
||||
SystemUiProxy.INSTANCE.get(this).setLastSystemUiStateFlags(systemUiStateFlags);
|
||||
mOverviewComponentObserver.onSystemUiStateChanged();
|
||||
mTaskbarManager.onSystemUiFlagsChanged(systemUiStateFlags);
|
||||
|
||||
long isShadeExpandedFlag =
|
||||
SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED | SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
|
||||
boolean wasExpanded = (lastSysUIFlags & isShadeExpandedFlag) != 0;
|
||||
boolean isExpanded = (systemUiStateFlags & isShadeExpandedFlag) != 0;
|
||||
if (wasExpanded != isExpanded && isExpanded) {
|
||||
// End live tile when expanding the notification panel for the first time from
|
||||
// overview.
|
||||
mTaskAnimationManager.endLiveTile();
|
||||
}
|
||||
mTaskAnimationManager.onSystemUiFlagsChanged(lastSysUIFlags, systemUiStateFlags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -267,6 +267,10 @@ public class SwipePipToHomeAnimator extends RectFSpringAnim {
|
||||
return mAppBounds;
|
||||
}
|
||||
|
||||
public Rect getSourceRectHint() {
|
||||
return mSourceRectHint;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SurfaceControl getContentOverlay() {
|
||||
return mPipContentOverlay == null ? null : mPipContentOverlay.getLeash();
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.quickstep.util
|
||||
|
||||
import com.android.systemui.shared.system.QuickStepContract
|
||||
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags
|
||||
|
||||
/** Util class for holding and checking [SystemUiStateFlags] masks. */
|
||||
object SystemUiFlagUtils {
|
||||
const val KEYGUARD_SYSUI_FLAGS =
|
||||
(QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING or
|
||||
QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING or
|
||||
QuickStepContract.SYSUI_STATE_DEVICE_DOZING or
|
||||
QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED or
|
||||
QuickStepContract.SYSUI_STATE_HOME_DISABLED or
|
||||
QuickStepContract.SYSUI_STATE_BACK_DISABLED or
|
||||
QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED or
|
||||
QuickStepContract.SYSUI_STATE_WAKEFULNESS_MASK)
|
||||
|
||||
// If any of these SysUi flags (via QuickstepContract) is set, the device to be considered
|
||||
// locked.
|
||||
private const val MASK_ANY_SYSUI_LOCKED =
|
||||
(QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING or
|
||||
QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING or
|
||||
QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED or
|
||||
QuickStepContract.SYSUI_STATE_DEVICE_DREAMING)
|
||||
|
||||
/**
|
||||
* Returns true iff the given [SystemUiStateFlags] imply that the device is considered locked.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isLocked(@SystemUiStateFlags flags: Long): Boolean {
|
||||
return hasAnyFlag(flags, MASK_ANY_SYSUI_LOCKED) &&
|
||||
!hasAnyFlag(flags, QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY)
|
||||
}
|
||||
|
||||
private fun hasAnyFlag(@SystemUiStateFlags flags: Long, flagMask: Long): Boolean {
|
||||
return (flags and flagMask) != 0L
|
||||
}
|
||||
}
|
||||
@@ -278,7 +278,7 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
||||
boolean showSingleTaskActions = !mIsGroupedTask;
|
||||
boolean showGroupActions = mIsGroupedTask && mDp.isTablet && mCanSaveAppPair;
|
||||
Log.d(TAG, "updateActionButtonsVisibility() called: showSingleTaskActions = ["
|
||||
+ showSingleTaskActions + ", showGroupActions = [" + showGroupActions + "]");
|
||||
+ showSingleTaskActions + "], showGroupActions = [" + showGroupActions + "]");
|
||||
getActionsAlphas().get(INDEX_GROUPED_ALPHA).setValue(showSingleTaskActions ? 1 : 0);
|
||||
getGroupActionsAlphas().get(INDEX_GROUPED_ALPHA).setValue(showGroupActions ? 1 : 0);
|
||||
}
|
||||
|
||||
@@ -18,13 +18,16 @@ package com.android.quickstep.views;
|
||||
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_CANCEL_BUTTON;
|
||||
import static com.android.settingslib.widget.theme.R.dimen.settingslib_preferred_minimum_touch_target;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.FloatProperty;
|
||||
import android.view.TouchDelegate;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
@@ -41,9 +44,7 @@ import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.statemanager.BaseState;
|
||||
import com.android.launcher3.statemanager.StateManager;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
|
||||
import com.android.quickstep.util.SplitSelectStateController;
|
||||
|
||||
/**
|
||||
@@ -133,6 +134,28 @@ public class SplitInstructionsView extends LinearLayout {
|
||||
cancelTextView.setVisibility(VISIBLE);
|
||||
cancelTextView.setOnClickListener((v) -> exitSplitSelection());
|
||||
instructionTextView.setText(R.string.toast_contextual_split_select_app);
|
||||
|
||||
// After layout, expand touch target of cancel button to meet minimum a11y measurements.
|
||||
post(() -> {
|
||||
int minTouchSize = getResources()
|
||||
.getDimensionPixelSize(settingslib_preferred_minimum_touch_target);
|
||||
Rect r = new Rect();
|
||||
cancelTextView.getHitRect(r);
|
||||
|
||||
if (r.width() < minTouchSize) {
|
||||
// add 1 to ensure ceiling on int division
|
||||
int expandAmount = (minTouchSize + 1 - r.width()) / 2;
|
||||
r.left -= expandAmount;
|
||||
r.right += expandAmount;
|
||||
}
|
||||
if (r.height() < minTouchSize) {
|
||||
int expandAmount = (minTouchSize + 1 - r.height()) / 2;
|
||||
r.top -= expandAmount;
|
||||
r.bottom += expandAmount;
|
||||
}
|
||||
|
||||
setTouchDelegate(new TouchDelegate(r, cancelTextView));
|
||||
});
|
||||
}
|
||||
|
||||
// Set accessibility title, will be announced by a11y tools.
|
||||
|
||||
+24
-26
@@ -37,7 +37,7 @@ import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() {
|
||||
class TaskbarRecentAppsControllerTest : TaskbarBaseTestCase() {
|
||||
|
||||
@get:Rule val mockitoRule = MockitoJUnit.rule()
|
||||
|
||||
@@ -46,19 +46,18 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() {
|
||||
|
||||
private var nextTaskId: Int = 500
|
||||
|
||||
private lateinit var taskbarRunningAppsController: DesktopTaskbarRunningAppsController
|
||||
private lateinit var recentAppsController: TaskbarRecentAppsController
|
||||
private lateinit var userHandle: UserHandle
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
super.setup()
|
||||
userHandle = Process.myUserHandle()
|
||||
taskbarRunningAppsController =
|
||||
DesktopTaskbarRunningAppsController(mockRecentsModel) {
|
||||
mockDesktopVisibilityController
|
||||
}
|
||||
taskbarRunningAppsController.init(taskbarControllers)
|
||||
taskbarRunningAppsController.setApps(
|
||||
recentAppsController =
|
||||
TaskbarRecentAppsController(mockRecentsModel) { mockDesktopVisibilityController }
|
||||
recentAppsController.init(taskbarControllers)
|
||||
recentAppsController.isEnabled = true
|
||||
recentAppsController.setApps(
|
||||
ALL_APP_PACKAGES.map { createTestAppInfo(packageName = it) }.toTypedArray()
|
||||
)
|
||||
}
|
||||
@@ -69,7 +68,7 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() {
|
||||
val hotseatItems =
|
||||
createHotseatItemsFromPackageNames(listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2))
|
||||
|
||||
assertThat(taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()))
|
||||
assertThat(recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()))
|
||||
.isEqualTo(hotseatItems.toTypedArray())
|
||||
}
|
||||
|
||||
@@ -81,10 +80,10 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() {
|
||||
val runningTasks =
|
||||
createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
|
||||
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
|
||||
taskbarRunningAppsController.updateRunningApps()
|
||||
recentAppsController.updateRunningApps()
|
||||
|
||||
val newHotseatItems =
|
||||
taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
|
||||
recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
|
||||
|
||||
assertThat(newHotseatItems.map { it?.targetPackage })
|
||||
.containsExactlyElementsIn(hotseatPackages)
|
||||
@@ -96,7 +95,7 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() {
|
||||
val hotseatItems =
|
||||
createHotseatItemsFromPackageNames(listOf(HOTSEAT_PACKAGE_1, HOTSEAT_PACKAGE_2))
|
||||
|
||||
assertThat(taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()))
|
||||
assertThat(recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray()))
|
||||
.isEqualTo(hotseatItems.toTypedArray())
|
||||
}
|
||||
|
||||
@@ -108,10 +107,10 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() {
|
||||
val runningTasks =
|
||||
createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
|
||||
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
|
||||
taskbarRunningAppsController.updateRunningApps()
|
||||
recentAppsController.updateRunningApps()
|
||||
|
||||
val newHotseatItems =
|
||||
taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
|
||||
recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
|
||||
|
||||
val expectedPackages =
|
||||
listOf(
|
||||
@@ -134,10 +133,10 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() {
|
||||
listOf(HOTSEAT_PACKAGE_1, RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2)
|
||||
)
|
||||
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
|
||||
taskbarRunningAppsController.updateRunningApps()
|
||||
recentAppsController.updateRunningApps()
|
||||
|
||||
val newHotseatItems =
|
||||
taskbarRunningAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
|
||||
recentAppsController.updateHotseatItemInfos(hotseatItems.toTypedArray())
|
||||
|
||||
val expectedPackages =
|
||||
listOf(
|
||||
@@ -156,10 +155,10 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() {
|
||||
val runningTasks =
|
||||
createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
|
||||
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
|
||||
taskbarRunningAppsController.updateRunningApps()
|
||||
recentAppsController.updateRunningApps()
|
||||
|
||||
assertThat(taskbarRunningAppsController.runningApps).isEmpty()
|
||||
assertThat(taskbarRunningAppsController.minimizedApps).isEmpty()
|
||||
assertThat(recentAppsController.runningApps).isEmpty()
|
||||
assertThat(recentAppsController.minimizedApps).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -168,11 +167,11 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() {
|
||||
val runningTasks =
|
||||
createDesktopTasksFromPackageNames(listOf(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2))
|
||||
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
|
||||
taskbarRunningAppsController.updateRunningApps()
|
||||
recentAppsController.updateRunningApps()
|
||||
|
||||
assertThat(taskbarRunningAppsController.runningApps)
|
||||
assertThat(recentAppsController.runningApps)
|
||||
.containsExactly(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2)
|
||||
assertThat(taskbarRunningAppsController.minimizedApps).isEmpty()
|
||||
assertThat(recentAppsController.minimizedApps).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -187,12 +186,11 @@ class DesktopTaskbarRunningAppsControllerTest : TaskbarBaseTestCase() {
|
||||
)
|
||||
)
|
||||
whenever(mockRecentsModel.runningTasks).thenReturn(runningTasks)
|
||||
taskbarRunningAppsController.updateRunningApps()
|
||||
recentAppsController.updateRunningApps()
|
||||
|
||||
assertThat(taskbarRunningAppsController.runningApps)
|
||||
assertThat(recentAppsController.runningApps)
|
||||
.containsExactly(RUNNING_APP_PACKAGE_1, RUNNING_APP_PACKAGE_2, RUNNING_APP_PACKAGE_3)
|
||||
assertThat(taskbarRunningAppsController.minimizedApps)
|
||||
.containsExactly(RUNNING_APP_PACKAGE_3)
|
||||
assertThat(recentAppsController.minimizedApps).containsExactly(RUNNING_APP_PACKAGE_3)
|
||||
}
|
||||
|
||||
private fun createHotseatItemsFromPackageNames(packageNames: List<String>): List<ItemInfo> {
|
||||
@@ -88,6 +88,8 @@ public class TaplOverviewIconTest extends AbstractLauncherUiTest<QuickstepLaunch
|
||||
}
|
||||
|
||||
private void createAndLaunchASplitPair() {
|
||||
clearAllRecentTasks();
|
||||
|
||||
startTestActivity(2);
|
||||
startTestActivity(3);
|
||||
|
||||
|
||||
@@ -33,9 +33,7 @@ import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import com.android.launcher3.tapl.Overview;
|
||||
import com.android.launcher3.tapl.Taskbar;
|
||||
import com.android.launcher3.tapl.TaskbarAppIcon;
|
||||
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
|
||||
import com.android.launcher3.util.rule.TestStabilityRule;
|
||||
import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
|
||||
import com.android.wm.shell.Flags;
|
||||
|
||||
import org.junit.After;
|
||||
@@ -74,14 +72,6 @@ public class TaplTestsSplitscreen extends AbstractQuickStepTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@PortraitLandscape
|
||||
public void testSplitFromOverview() {
|
||||
createAndLaunchASplitPair();
|
||||
}
|
||||
|
||||
@Test
|
||||
@PortraitLandscape
|
||||
@TaskbarModeSwitch
|
||||
@TestStabilityRule.Stability(flavors = PLATFORM_POSTSUBMIT | LOCAL) // b/295225524
|
||||
public void testSplitAppFromHomeWithItself() throws Exception {
|
||||
// Currently only tablets have Taskbar in Overview, so test is only active on tablets
|
||||
@@ -152,11 +142,7 @@ public class TaplTestsSplitscreen extends AbstractQuickStepTest {
|
||||
// Currently only tablets have Taskbar in Overview, so test is only active on tablets
|
||||
assumeTrue(mLauncher.isTablet());
|
||||
|
||||
if (!mLauncher.getRecentTasks().isEmpty()) {
|
||||
// Clear all recent tasks
|
||||
mLauncher.goHome().switchToOverview().dismissAllTasks();
|
||||
}
|
||||
|
||||
clearAllRecentTasks();
|
||||
startAppFast(getAppPackageName());
|
||||
|
||||
Overview overview = mLauncher.goHome().switchToOverview();
|
||||
@@ -173,6 +159,8 @@ public class TaplTestsSplitscreen extends AbstractQuickStepTest {
|
||||
}
|
||||
|
||||
private void createAndLaunchASplitPair() {
|
||||
clearAllRecentTasks();
|
||||
|
||||
startTestActivity(2);
|
||||
startTestActivity(3);
|
||||
|
||||
|
||||
@@ -211,6 +211,7 @@ android_robolectric_test {
|
||||
"Launcher3TestResources",
|
||||
"SystemUISharedLib",
|
||||
"launcher-testing-shared",
|
||||
"android.appwidget.flags-aconfig-java",
|
||||
],
|
||||
libs: [
|
||||
"android.test.runner",
|
||||
|
||||
+8
-2
@@ -18,12 +18,12 @@ import android.widget.RemoteViews
|
||||
import androidx.test.core.app.ApplicationProvider.getApplicationContext
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
|
||||
import com.android.launcher3.Flags.FLAG_ENABLE_GENERATED_PREVIEWS
|
||||
import com.android.launcher3.InvariantDeviceProfile
|
||||
import com.android.launcher3.icons.IconCache
|
||||
import com.android.launcher3.icons.IconProvider
|
||||
import com.android.launcher3.model.WidgetItem
|
||||
import com.android.launcher3.tests.R
|
||||
import com.android.launcher3.util.ActivityContextWrapper
|
||||
import com.android.launcher3.util.Executors
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
@@ -41,7 +41,10 @@ class GeneratedPreviewTest {
|
||||
"com.android.launcher3.tests",
|
||||
"com.android.launcher3.testcomponent.AppWidgetNoConfig"
|
||||
)
|
||||
private val generatedPreviewLayout = R.layout.test_layout_appwidget_blue
|
||||
private val generatedPreviewLayout =
|
||||
getInstrumentation().context.run {
|
||||
resources.getIdentifier("test_layout_appwidget_blue", "layout", packageName)
|
||||
}
|
||||
private lateinit var context: Context
|
||||
private lateinit var generatedPreview: RemoteViews
|
||||
private lateinit var widgetCell: WidgetCell
|
||||
@@ -137,6 +140,7 @@ class GeneratedPreviewTest {
|
||||
assertThat(widgetItem.hasGeneratedPreview(WIDGET_CATEGORY_KEYGUARD)).isFalse()
|
||||
assertThat(widgetItem.hasGeneratedPreview(WIDGET_CATEGORY_SEARCHBOX)).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(FLAG_ENABLE_GENERATED_PREVIEWS)
|
||||
fun widgetItem_getGeneratedPreview() {
|
||||
@@ -148,6 +152,7 @@ class GeneratedPreviewTest {
|
||||
@RequiresFlagsEnabled(FLAG_ENABLE_GENERATED_PREVIEWS)
|
||||
fun widgetCell_showGeneratedPreview() {
|
||||
widgetCell.applyFromCellItem(widgetItem)
|
||||
DatabaseWidgetPreviewLoader.getLoaderExecutor().submit {}.get()
|
||||
assertThat(widgetCell.appWidgetHostViewPreview).isNotNull()
|
||||
assertThat(widgetCell.appWidgetHostViewPreview?.appWidgetInfo)
|
||||
.isEqualTo(appWidgetProviderInfo)
|
||||
@@ -157,6 +162,7 @@ class GeneratedPreviewTest {
|
||||
@RequiresFlagsDisabled(FLAG_ENABLE_GENERATED_PREVIEWS)
|
||||
fun widgetCell_showGeneratedPreview_flagDisabled() {
|
||||
widgetCell.applyFromCellItem(widgetItem)
|
||||
DatabaseWidgetPreviewLoader.getLoaderExecutor().submit {}.get()
|
||||
assertThat(widgetCell.appWidgetHostViewPreview).isNull()
|
||||
}
|
||||
}
|
||||
@@ -699,4 +699,11 @@ public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher> {
|
||||
UiDevice.getInstance(getInstrumentation()).pressHome();
|
||||
mLauncher.waitForLauncherInitialized();
|
||||
}
|
||||
|
||||
/** Clears all recent tasks */
|
||||
protected void clearAllRecentTasks() {
|
||||
if (!mLauncher.getRecentTasks().isEmpty()) {
|
||||
mLauncher.goHome().switchToOverview().dismissAllTasks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import static com.android.launcher3.tapl.OverviewTask.TASK_START_EVENT;
|
||||
import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -44,6 +45,7 @@ import java.util.stream.Collectors;
|
||||
* Common overview panel for both Launcher and fallback recents
|
||||
*/
|
||||
public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
|
||||
private static final String TAG = "BaseOverview";
|
||||
protected static final String TASK_RES_ID = "task";
|
||||
private static final Pattern EVENT_ALT_ESC_UP = Pattern.compile(
|
||||
"Key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_ESCAPE.*?metaState=0");
|
||||
@@ -384,25 +386,31 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
|
||||
|
||||
protected boolean isActionsViewVisible() {
|
||||
if (!hasTasks() || isClearAllVisible()) {
|
||||
Log.d(TAG, "Not expecting an actions bar: no tasks/'Clear all' is visible");
|
||||
return false;
|
||||
}
|
||||
boolean isTablet = mLauncher.isTablet();
|
||||
if (isTablet && mLauncher.isGridOnlyOverviewEnabled()) {
|
||||
Log.d(TAG, "Not expecting an actions bar: device is tablet with grid-only Overview");
|
||||
return false;
|
||||
}
|
||||
OverviewTask task = isTablet ? getFocusedTaskForTablet() : getCurrentTask();
|
||||
if (task == null) {
|
||||
Log.d(TAG, "Not expecting an actions bar: no current task");
|
||||
return false;
|
||||
}
|
||||
// In tablets, if focused task is not in center, overview actions aren't visible.
|
||||
if (isTablet && Math.abs(task.getExactCenterX() - mLauncher.getExactScreenCenterX()) >= 1) {
|
||||
Log.d(TAG, "Not expecting an actions bar: device is tablet and task is not centered");
|
||||
return false;
|
||||
}
|
||||
if (task.isTaskSplit() && (!mLauncher.isAppPairsEnabled() || !isTablet)) {
|
||||
Log.d(TAG, "Not expecting an actions bar: device is phone and task is split");
|
||||
// Overview actions aren't visible for split screen tasks, except for save app pair
|
||||
// button on tablets.
|
||||
return false;
|
||||
}
|
||||
Log.d(TAG, "Expecting an actions bar");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -447,10 +455,20 @@ public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
|
||||
}
|
||||
|
||||
private void verifyActionsViewVisibility() {
|
||||
// If no running tasks, no need to verify actions view visibility.
|
||||
if (getTasks().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isTablet = mLauncher.isTablet();
|
||||
OverviewTask task = isTablet ? getFocusedTaskForTablet() : getCurrentTask();
|
||||
|
||||
try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
|
||||
"want to assert overview actions view visibility")) {
|
||||
boolean isTablet = mLauncher.isTablet();
|
||||
OverviewTask task = isTablet ? getFocusedTaskForTablet() : getCurrentTask();
|
||||
"want to assert overview actions view visibility="
|
||||
+ isActionsViewVisible()
|
||||
+ ", focused task is "
|
||||
+ (task == null ? "null" : (task.isTaskSplit() ? "split" : "not split"))
|
||||
)) {
|
||||
|
||||
if (isActionsViewVisible()) {
|
||||
if (task.isTaskSplit()) {
|
||||
|
||||
Reference in New Issue
Block a user