Merge "Add debug logs to TaplStartLauncherViaGestureTests" into main
diff --git a/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransition.kt b/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransition.kt
index e160f82..87a82f0 100644
--- a/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransition.kt
+++ b/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransition.kt
@@ -143,6 +143,7 @@
}
companion object {
+ /** Change modes that represent a task becoming visible / launching in Desktop mode. */
val LAUNCH_CHANGE_MODES = intArrayOf(TRANSIT_OPEN, TRANSIT_TO_FRONT)
private val launchBoundsAnimationDef =
diff --git a/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransitionManager.kt b/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransitionManager.kt
new file mode 100644
index 0000000..e32bcd1
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransitionManager.kt
@@ -0,0 +1,88 @@
+/*
+ * 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.desktop
+
+import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
+import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
+import android.content.Context
+import android.window.DesktopModeFlags
+import android.window.RemoteTransition
+import android.window.TransitionFilter
+import android.window.TransitionFilter.CONTAINER_ORDER_TOP
+import com.android.launcher3.desktop.DesktopAppLaunchTransition.AppLaunchType
+import com.android.launcher3.util.Executors.MAIN_EXECUTOR
+import com.android.quickstep.SystemUiProxy
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
+
+/** Manages transitions related to app launches in Desktop Mode. */
+class DesktopAppLaunchTransitionManager(
+ private val context: Context,
+ private val systemUiProxy: SystemUiProxy,
+) {
+ private var remoteWindowLimitUnminimizeTransition: RemoteTransition? = null
+
+ /**
+ * Register a [RemoteTransition] supporting Desktop app launches, and window limit
+ * minimizations.
+ */
+ fun registerTransitions() {
+ if (!shouldRegisterTransitions()) {
+ return
+ }
+ remoteWindowLimitUnminimizeTransition =
+ RemoteTransition(
+ DesktopAppLaunchTransition(context, MAIN_EXECUTOR, AppLaunchType.UNMINIMIZE)
+ )
+ systemUiProxy.registerRemoteTransition(
+ remoteWindowLimitUnminimizeTransition,
+ buildAppLaunchFilter(),
+ )
+ }
+
+ /**
+ * Unregister the [RemoteTransition] supporting Desktop app launches and window limit
+ * minimizations.
+ */
+ fun unregisterTransitions() {
+ if (!shouldRegisterTransitions()) {
+ return
+ }
+ systemUiProxy.unregisterRemoteTransition(remoteWindowLimitUnminimizeTransition)
+ remoteWindowLimitUnminimizeTransition = null
+ }
+
+ private fun shouldRegisterTransitions(): Boolean =
+ DesktopModeStatus.canEnterDesktopMode(context) &&
+ DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS.isTrue
+
+ companion object {
+ private fun buildAppLaunchFilter(): TransitionFilter {
+ val openRequirement =
+ TransitionFilter.Requirement().apply {
+ mActivityType = ACTIVITY_TYPE_STANDARD
+ mWindowingMode = WINDOWING_MODE_FREEFORM
+ mModes = DesktopAppLaunchTransition.LAUNCH_CHANGE_MODES
+ mMustBeTask = true
+ mOrder = CONTAINER_ORDER_TOP
+ }
+ return TransitionFilter().apply {
+ mTypeSet = DesktopAppLaunchTransition.LAUNCH_CHANGE_MODES
+ mRequirements = arrayOf(openRequirement)
+ }
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index b1cb2c6..4a94be7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -362,20 +362,21 @@
// This method can be called before init() is called.
return;
}
- if (mControllers.uiController.isIconAlignedWithHotseat()
- && !mTaskbarLauncherStateController.isAnimatingToLauncher()) {
- // Only animate the nav buttons while home and not animating home, otherwise let
- // the TaskbarViewController handle it.
- mControllers.navbarButtonsViewController
- .getTaskbarNavButtonTranslationYForInAppDisplay()
- .updateValue(mLauncher.getDeviceProfile().getTaskbarOffsetY()
- * mTaskbarInAppDisplayProgress.value);
- mControllers.navbarButtonsViewController
- .getOnTaskbarBackgroundNavButtonColorOverride().updateValue(progress);
-
+ if (mControllers.uiController.isIconAlignedWithHotseat()) {
+ if (!mTaskbarLauncherStateController.isAnimatingToLauncher()) {
+ // Only animate the nav buttons while home and not animating home, otherwise let
+ // the TaskbarViewController handle it.
+ mControllers.navbarButtonsViewController
+ .getTaskbarNavButtonTranslationYForInAppDisplay()
+ .updateValue(mLauncher.getDeviceProfile().getTaskbarOffsetY()
+ * mTaskbarInAppDisplayProgress.value);
+ mControllers.navbarButtonsViewController
+ .getOnTaskbarBackgroundNavButtonColorOverride().updateValue(progress);
+ }
if (isBubbleBarEnabled()) {
mControllers.bubbleControllers.ifPresent(
- c -> c.bubbleStashController.setInAppDisplayOverrideProgress(progress));
+ c -> c.bubbleStashController.setInAppDisplayOverrideProgress(
+ mTaskbarInAppDisplayProgress.value));
}
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashController.kt
index 9a68335..6632721 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashController.kt
@@ -119,7 +119,10 @@
if (field == value) return
field = value
if (launcherState == BubbleLauncherState.HOME) {
- bubbleBarViewController.bubbleBarTranslationY.updateValue(bubbleBarTranslationY)
+ if (bubbleBarTranslationYAnimator.isAnimating) {
+ bubbleBarTranslationYAnimator.cancelAnimation()
+ }
+ bubbleBarTranslationYAnimator.updateValue(bubbleBarTranslationY)
if (value == 0f || value == 1f) {
// Update insets only when we reach the end values
taskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index fcc5121..ad5720f 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -85,6 +85,7 @@
import com.android.launcher3.Flags;
import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.anim.AnimatedFloat;
+import com.android.launcher3.desktop.DesktopAppLaunchTransitionManager;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.statemanager.StatefulActivity;
@@ -662,6 +663,7 @@
private NavigationMode mGestureStartNavMode = null;
private DesktopVisibilityController mDesktopVisibilityController;
+ private DesktopAppLaunchTransitionManager mDesktopAppLaunchTransitionManager;
@Override
public void onCreate() {
@@ -686,6 +688,9 @@
mDesktopVisibilityController = new DesktopVisibilityController(this);
mTaskbarManager = new TaskbarManager(
this, mAllAppsActionManager, mNavCallbacks, mDesktopVisibilityController);
+ mDesktopAppLaunchTransitionManager =
+ new DesktopAppLaunchTransitionManager(this, SystemUiProxy.INSTANCE.get(this));
+ mDesktopAppLaunchTransitionManager.registerTransitions();
if (Flags.enableLauncherOverviewInWindow() || Flags.enableFallbackOverviewInWindow()) {
mRecentsWindowManager = new RecentsWindowManager(this);
}
@@ -851,6 +856,10 @@
if (mRecentsWindowManager != null) {
mRecentsWindowManager.destroy();
}
+ if (mDesktopAppLaunchTransitionManager != null) {
+ mDesktopAppLaunchTransitionManager.unregisterTransitions();
+ }
+ mDesktopAppLaunchTransitionManager = null;
mDesktopVisibilityController.onDestroy();
sConnected = false;
diff --git a/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt b/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt
index 275af00..6c627ef 100644
--- a/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt
+++ b/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt
@@ -73,26 +73,29 @@
getTaskDataById(taskId).map { it?.thumbnail }.distinctUntilChangedBy { it?.snapshotId }
override fun setVisibleTasks(visibleTaskIdList: Set<Int>) {
- // Remove tasks are no longer visible
val tasksNoLongerVisible = taskRequests.keys.subtract(visibleTaskIdList)
+ val newlyVisibleTasks = visibleTaskIdList.subtract(taskRequests.keys)
+ if (tasksNoLongerVisible.isNotEmpty() || newlyVisibleTasks.isNotEmpty()) {
+ Log.d(
+ TAG,
+ "setVisibleTasks to: $visibleTaskIdList, " +
+ "removed: $tasksNoLongerVisible, added: $newlyVisibleTasks",
+ )
+ }
+
+ // Remove tasks are no longer visible
removeTasks(tasksNoLongerVisible)
// Add new tasks to be requested
- val newlyVisibleTasks = visibleTaskIdList.subtract(taskRequests.keys)
newlyVisibleTasks.forEach { taskId -> requestTaskData(taskId) }
-
- if (tasksNoLongerVisible.isNotEmpty() || newlyVisibleTasks.isNotEmpty()) {
- Log.d(TAG, "setVisibleTasks to: $visibleTaskIdList, " +
- "removed: $tasksNoLongerVisible, added: $newlyVisibleTasks")
- }
}
private fun requestTaskData(taskId: Int) {
- Log.i(TAG, "requestTaskData: $taskId")
val task = tasks.value[taskId] ?: return
taskRequests[taskId] =
Pair(
task.key,
recentsCoroutineScope.launch {
+ Log.i(TAG, "requestTaskData: $taskId")
fetchIcon(task)
fetchThumbnail(task)
},
@@ -102,8 +105,8 @@
private fun removeTasks(tasksToRemove: Set<Int>) {
if (tasksToRemove.isEmpty()) return
+ Log.i(TAG, "removeTasks: $tasksToRemove")
tasksToRemove.forEach { taskId ->
- Log.i(TAG, "removeTask: $taskId")
val request = taskRequests.remove(taskId) ?: return
val (taskKey, job) = request
job.cancel()
diff --git a/quickstep/src/com/android/quickstep/recents/di/RecentsDependencies.kt b/quickstep/src/com/android/quickstep/recents/di/RecentsDependencies.kt
index f2b9976..dd11d48 100644
--- a/quickstep/src/com/android/quickstep/recents/di/RecentsDependencies.kt
+++ b/quickstep/src/com/android/quickstep/recents/di/RecentsDependencies.kt
@@ -19,6 +19,7 @@
import android.content.Context
import android.util.Log
import android.view.View
+import com.android.launcher3.util.coroutines.DispatcherProvider
import com.android.launcher3.util.coroutines.ProductionDispatchers
import com.android.quickstep.RecentsModel
import com.android.quickstep.recents.data.RecentTasksRepository
@@ -63,6 +64,7 @@
val recentsCoroutineScope =
CoroutineScope(SupervisorJob() + Dispatchers.Main + CoroutineName("RecentsView"))
set(CoroutineScope::class.java.simpleName, recentsCoroutineScope)
+ set(DispatcherProvider::class.java.simpleName, ProductionDispatchers)
val recentsModel = RecentsModel.INSTANCE.get(appContext)
val taskVisualsChangedDelegate =
TaskVisualsChangedDelegateImpl(
@@ -196,6 +198,7 @@
recentsViewData = inject(),
taskViewData = inject(scopeId, extras),
taskContainerData = inject(scopeId),
+ dispatcherProvider = inject(),
getThumbnailPositionUseCase = inject(),
tasksRepository = inject(),
splashAlphaUseCase = inject(scopeId),
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
index eb9c047..a8c8659 100644
--- a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
@@ -33,7 +33,6 @@
import com.android.launcher3.util.ViewPool
import com.android.quickstep.recents.di.RecentsDependencies
import com.android.quickstep.recents.di.get
-import com.android.quickstep.recents.di.inject
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.BackgroundOnly
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.LiveTile
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Snapshot
@@ -43,7 +42,6 @@
import com.android.quickstep.util.TaskCornerRadius
import com.android.quickstep.views.FixedSizeImageView
import com.android.systemui.shared.system.QuickStepContract
-import kotlin.math.abs
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -53,8 +51,7 @@
import kotlinx.coroutines.flow.onEach
class TaskThumbnailView : ConstraintLayout, ViewPool.Reusable {
-
- private val viewData: TaskThumbnailViewData by RecentsDependencies.inject(this)
+ private lateinit var viewData: TaskThumbnailViewData
private lateinit var viewModel: TaskThumbnailViewModel
private lateinit var viewAttachedScope: CoroutineScope
@@ -92,10 +89,12 @@
super.onAttachedToWindow()
viewAttachedScope =
CoroutineScope(SupervisorJob() + Dispatchers.Main + CoroutineName("TaskThumbnailView"))
+ viewData = RecentsDependencies.get(this)
+ updateViewDataValues()
viewModel = RecentsDependencies.get(this)
viewModel.uiState
.onEach { viewModelUiState ->
- Log.d(TAG, "viewModelUiState changed from $uiState to: $viewModelUiState")
+ Log.d(TAG, "viewModelUiState changed from: $uiState to: $viewModelUiState")
uiState = viewModelUiState
resetViews()
when (viewModelUiState) {
@@ -144,11 +143,15 @@
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
if (changed) {
- viewData.width.value = abs(right - left)
- viewData.height.value = abs(bottom - top)
+ updateViewDataValues()
}
}
+ private fun updateViewDataValues() {
+ viewData.width.value = width
+ viewData.height.value = height
+ }
+
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
if (uiState is SnapshotSplash) {
diff --git a/quickstep/src/com/android/quickstep/task/util/TaskOverlayHelper.kt b/quickstep/src/com/android/quickstep/task/util/TaskOverlayHelper.kt
index c82ed9a..203177a 100644
--- a/quickstep/src/com/android/quickstep/task/util/TaskOverlayHelper.kt
+++ b/quickstep/src/com/android/quickstep/task/util/TaskOverlayHelper.kt
@@ -85,14 +85,18 @@
}
private fun initOverlay(enabledState: Enabled) {
- Log.d(TAG, "initOverlay - taskId: ${task.key.id}, thumbnail: ${enabledState.thumbnail}")
+ if (DEBUG) {
+ Log.d(TAG, "initOverlay - taskId: ${task.key.id}, thumbnail: ${enabledState.thumbnail}")
+ }
with(getThumbnailPositionState()) {
overlay.initOverlay(task, enabledState.thumbnail, matrix, isRotated)
}
}
private fun reset() {
- Log.d(TAG, "reset - taskId: ${task.key.id}")
+ if (DEBUG) {
+ Log.d(TAG, "reset - taskId: ${task.key.id}")
+ }
overlay.reset()
}
@@ -105,5 +109,6 @@
companion object {
private const val TAG = "TaskOverlayHelper"
+ private const val DEBUG = false
}
}
diff --git a/quickstep/src/com/android/quickstep/task/viewmodel/TaskThumbnailViewModelImpl.kt b/quickstep/src/com/android/quickstep/task/viewmodel/TaskThumbnailViewModelImpl.kt
index bd47cec..8b15a82 100644
--- a/quickstep/src/com/android/quickstep/task/viewmodel/TaskThumbnailViewModelImpl.kt
+++ b/quickstep/src/com/android/quickstep/task/viewmodel/TaskThumbnailViewModelImpl.kt
@@ -21,6 +21,7 @@
import android.graphics.Matrix
import android.util.Log
import androidx.core.graphics.ColorUtils
+import com.android.launcher3.util.coroutines.DispatcherProvider
import com.android.quickstep.recents.data.RecentTasksRepository
import com.android.quickstep.recents.usecase.GetThumbnailPositionUseCase
import com.android.quickstep.recents.usecase.ThumbnailPositionState
@@ -42,6 +43,7 @@
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.runBlocking
@@ -50,6 +52,7 @@
recentsViewData: RecentsViewData,
taskViewData: TaskViewData,
taskContainerData: TaskContainerData,
+ dispatcherProvider: DispatcherProvider,
private val tasksRepository: RecentTasksRepository,
private val getThumbnailPositionUseCase: GetThumbnailPositionUseCase,
private val splashAlphaUseCase: SplashAlphaUseCase,
@@ -73,6 +76,7 @@
tintAmount ->
max(taskMenuOpenProgress * MAX_SCRIM_ALPHA, tintAmount)
}
+
override val splashAlpha = splashProgress.flatMapLatest { it }
private val isLiveTile =
@@ -84,6 +88,7 @@
runningTaskIds.contains(taskId) && !runningTaskShowScreenshot
}
.distinctUntilChanged()
+ .flowOn(dispatcherProvider.default)
override val uiState: Flow<TaskThumbnailUiState> =
combine(task.flatMapLatest { it }, isLiveTile) { taskVal, isRunning ->
@@ -105,6 +110,7 @@
}
}
.distinctUntilChanged()
+ .flowOn(dispatcherProvider.default)
override fun bind(taskId: Int) {
Log.d(TAG, "bind taskId: $taskId")
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 839c42e..3a4e328 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -3694,31 +3694,43 @@
int currentPageScroll = getScrollForPage(mCurrentPage);
int lastGridTaskScroll = getScrollForPage(indexOfChild(lastGridTaskView));
boolean currentPageSnapsToEndOfGrid = currentPageScroll == lastGridTaskScroll;
+
+ int topGridRowSize = mTopRowIdSet.size();
+ int numLargeTiles = mUtils.getLargeTileCount(getTaskViews());
+ int bottomGridRowSize = taskCount - mTopRowIdSet.size() - numLargeTiles;
+ boolean topRowLonger = topGridRowSize > bottomGridRowSize;
+ boolean bottomRowLonger = bottomGridRowSize > topGridRowSize;
+ boolean dismissedTaskFromTop = mTopRowIdSet.contains(dismissedTaskViewId);
+ boolean dismissedTaskFromBottom = !dismissedTaskFromTop && !isFocusedTaskDismissed;
+ if (dismissedTaskFromTop || (isFocusedTaskDismissed && nextFocusedTaskFromTop)) {
+ topGridRowSize--;
+ }
+ if (dismissedTaskFromBottom || (isFocusedTaskDismissed && !nextFocusedTaskFromTop)) {
+ bottomGridRowSize--;
+ }
+ int longRowWidth = Math.max(topGridRowSize, bottomGridRowSize)
+ * (mLastComputedGridTaskSize.width() + mPageSpacing);
+ if (!enableGridOnlyOverview() && !isStagingFocusedTask) {
+ longRowWidth += mLastComputedTaskSize.width() + mPageSpacing;
+ }
+ // Compensate the removed gap if we don't already have shortTotalCompensation,
+ // and adjust accordingly to the new shortTotalCompensation after dismiss.
+ int newClearAllShortTotalWidthTranslation = 0;
+ if (mClearAllShortTotalWidthTranslation == 0) {
+ // If first task is not in the expected position (mLastComputedTaskSize) and being too
+ // close to ClearAllButton, then apply extra translation to ClearAllButton.
+ int firstTaskStart = mLastComputedGridSize.left + longRowWidth;
+ int expectedFirstTaskStart = mLastComputedTaskSize.right;
+ if (firstTaskStart < expectedFirstTaskStart) {
+ newClearAllShortTotalWidthTranslation = expectedFirstTaskStart - firstTaskStart;
+ }
+ }
if (lastGridTaskView != null && lastGridTaskView.isVisibleToUser()) {
// After dismissal, animate translation of the remaining tasks to fill any gap left
// between the end of the grid and the clear all button. Only animate if the clear
// all button is visible or would become visible after dismissal.
float longGridRowWidthDiff = 0;
- int topGridRowSize = mTopRowIdSet.size();
- int numLargeTiles = mUtils.getLargeTileCount(getTaskViews());
- int bottomGridRowSize = taskCount - mTopRowIdSet.size() - numLargeTiles;
- boolean topRowLonger = topGridRowSize > bottomGridRowSize;
- boolean bottomRowLonger = bottomGridRowSize > topGridRowSize;
- boolean dismissedTaskFromTop = mTopRowIdSet.contains(dismissedTaskViewId);
- boolean dismissedTaskFromBottom = !dismissedTaskFromTop && !isFocusedTaskDismissed;
- if (dismissedTaskFromTop || (isFocusedTaskDismissed && nextFocusedTaskFromTop)) {
- topGridRowSize--;
- }
- if (dismissedTaskFromBottom || (isFocusedTaskDismissed && !nextFocusedTaskFromTop)) {
- bottomGridRowSize--;
- }
- int longRowWidth = Math.max(topGridRowSize, bottomGridRowSize)
- * (mLastComputedGridTaskSize.width() + mPageSpacing);
- if (!enableGridOnlyOverview() && !isStagingFocusedTask) {
- longRowWidth += mLastComputedTaskSize.width() + mPageSpacing;
- }
-
float gapWidth = 0;
if ((topRowLonger && dismissedTaskFromTop)
|| (bottomRowLonger && dismissedTaskFromBottom)) {
@@ -3730,17 +3742,6 @@
}
if (gapWidth > 0) {
if (mClearAllShortTotalWidthTranslation == 0) {
- // Compensate the removed gap if we don't already have shortTotalCompensation,
- // and adjust accordingly to the new shortTotalCompensation after dismiss.
- int newClearAllShortTotalWidthTranslation = 0;
- if (longRowWidth < mLastComputedGridSize.width()) {
- DeviceProfile deviceProfile = mContainer.getDeviceProfile();
- newClearAllShortTotalWidthTranslation =
- (mIsRtl
- ? mLastComputedTaskSize.right
- : deviceProfile.widthPx - mLastComputedTaskSize.left)
- - longRowWidth - deviceProfile.overviewGridSideMargin;
- }
float gapCompensation = gapWidth - newClearAllShortTotalWidthTranslation;
longGridRowWidthDiff += mIsRtl ? -gapCompensation : gapCompensation;
}
@@ -3830,6 +3831,8 @@
: mUtils.getDesktopTaskViewCount(getTaskViews());
stagingTranslation = getPagedOrientationHandler().getPrimaryScroll(this)
- getScrollForPage(nextSnappedPage);
+ stagingTranslation += mIsRtl ? newClearAllShortTotalWidthTranslation
+ : -newClearAllShortTotalWidthTranslation;
}
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
@@ -3888,7 +3891,7 @@
anim.setFloat(taskView, TaskView.DISMISS_SCALE, scale,
clampToProgress(LINEAR, animationStartProgress,
dismissTranslationInterpolationEnd));
- primaryTranslation += mIsRtl ? dismissedTaskWidth : -dismissedTaskWidth;
+ primaryTranslation += dismissedTaskWidth;
animationEndProgress = dismissTranslationInterpolationEnd;
float secondaryTranslation = -mTaskGridVerticalDiff;
if (!nextFocusedTaskFromTop) {
diff --git a/quickstep/src/com/android/quickstep/views/RecentsViewModelHelper.kt b/quickstep/src/com/android/quickstep/views/RecentsViewModelHelper.kt
index f22c672..3616fbb 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsViewModelHelper.kt
+++ b/quickstep/src/com/android/quickstep/views/RecentsViewModelHelper.kt
@@ -25,6 +25,7 @@
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
/** Helper for [RecentsView] to interact with the [RecentsViewModel]. */
class RecentsViewModelHelper(private val recentsViewModel: RecentsViewModel) {
@@ -32,7 +33,7 @@
fun onAttachedToWindow() {
viewAttachedScope =
- CoroutineScope(SupervisorJob() + Dispatchers.Main + CoroutineName("RecentsView"))
+ CoroutineScope(SupervisorJob() + Dispatchers.Default + CoroutineName("RecentsView"))
}
fun onDetachedFromWindow() {
@@ -50,7 +51,7 @@
viewAttachedScope.launch {
recentsViewModel.waitForRunningTaskShowScreenshotToUpdate()
recentsViewModel.waitForThumbnailsToUpdate(updatedThumbnails)
- ViewUtils.postFrameDrawn(taskView, onFinishRunnable)
+ withContext(Dispatchers.Main) { ViewUtils.postFrameDrawn(taskView, onFinishRunnable) }
}
}
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskContainer.kt b/quickstep/src/com/android/quickstep/views/TaskContainer.kt
index 25aba39..c940fb4 100644
--- a/quickstep/src/com/android/quickstep/views/TaskContainer.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskContainer.kt
@@ -110,7 +110,6 @@
return snapshotView as TaskThumbnailViewDeprecated
}
- // TODO(b/334826842): Support shouldShowSplashView for new TTV.
val shouldShowSplashView: Boolean
get() =
if (enableRefactorTaskThumbnail())
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt
index 0760618..b1cb407 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskView.kt
@@ -1221,8 +1221,6 @@
if (isQuickSwitch) {
setFreezeRecentTasksReordering()
}
- // TODO(b/334826842) no work required - add splash functionality to new TTV -
- // cold start e.g. restart device. Small splash moving to bigger splash
disableStartingWindow = firstContainer.shouldShowSplashView
}
Executors.UI_HELPER_EXECUTOR.execute {
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashControllerTest.kt
index e3d41e7..b7ee6c4 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/stashing/PersistentBubbleStashControllerTest.kt
@@ -284,6 +284,21 @@
}
@Test
+ fun inAppDisplayOverrideProgress_onHome_cancelExistingAnimation() {
+ whenever(bubbleBarViewController.hasBubbles()).thenReturn(false)
+ persistentTaskBarStashController.launcherState = BubbleLauncherState.HOME
+
+ bubbleBarViewController.bubbleBarTranslationY.animateToValue(100f)
+ advanceTimeBy(10)
+ assertThat(bubbleBarViewController.bubbleBarTranslationY.isAnimating).isTrue()
+
+ getInstrumentation().runOnMainSync {
+ persistentTaskBarStashController.inAppDisplayOverrideProgress = 0.5f
+ }
+ assertThat(bubbleBarViewController.bubbleBarTranslationY.isAnimating).isFalse()
+ }
+
+ @Test
fun inAppDisplayProgressUpdate_inApp_noTranslationUpdate() {
whenever(bubbleBarViewController.hasBubbles()).thenReturn(false)
persistentTaskBarStashController.launcherState = BubbleLauncherState.IN_APP
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelImplTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelImplTest.kt
index c541d3d..e3a6adf 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelImplTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelImplTest.kt
@@ -24,6 +24,7 @@
import android.graphics.drawable.Drawable
import android.view.Surface
import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.launcher3.util.TestDispatcherProvider
import com.android.quickstep.recents.data.FakeTasksRepository
import com.android.quickstep.recents.usecase.GetThumbnailPositionUseCase
import com.android.quickstep.recents.usecase.ThumbnailPositionState.MatrixScaling
@@ -42,6 +43,8 @@
import com.android.systemui.shared.recents.model.ThumbnailData
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
@@ -51,18 +54,24 @@
/** Test for [TaskThumbnailView] */
@RunWith(AndroidJUnit4::class)
class TaskThumbnailViewModelImplTest {
+ private val dispatcher = StandardTestDispatcher()
+ private val testScope = TestScope(dispatcher)
+
private var taskViewType = TaskViewType.SINGLE
private val recentsViewData = RecentsViewData()
private val taskViewData by lazy { TaskViewData(taskViewType) }
private val taskContainerData = TaskContainerData()
+ private val dispatcherProvider = TestDispatcherProvider(dispatcher)
private val tasksRepository = FakeTasksRepository()
private val mGetThumbnailPositionUseCase = mock<GetThumbnailPositionUseCase>()
private val splashAlphaUseCase: SplashAlphaUseCase = mock()
+
private val systemUnderTest by lazy {
TaskThumbnailViewModelImpl(
recentsViewData,
taskViewData,
taskContainerData,
+ dispatcherProvider,
tasksRepository,
mGetThumbnailPositionUseCase,
splashAlphaUseCase,
@@ -72,81 +81,85 @@
private val tasks = (0..5).map(::createTaskWithId)
@Test
- fun initialStateIsUninitialized() = runTest {
- assertThat(systemUnderTest.uiState.first()).isEqualTo(Uninitialized)
- }
+ fun initialStateIsUninitialized() =
+ testScope.runTest { assertThat(systemUnderTest.uiState.first()).isEqualTo(Uninitialized) }
@Test
- fun bindRunningTask_thenStateIs_LiveTile() = runTest {
- val taskId = 1
- tasksRepository.seedTasks(tasks)
- tasksRepository.setVisibleTasks(setOf(taskId))
- recentsViewData.runningTaskIds.value = setOf(taskId)
- systemUnderTest.bind(taskId)
+ fun bindRunningTask_thenStateIs_LiveTile() =
+ testScope.runTest {
+ val taskId = 1
+ tasksRepository.seedTasks(tasks)
+ tasksRepository.setVisibleTasks(setOf(taskId))
+ recentsViewData.runningTaskIds.value = setOf(taskId)
+ systemUnderTest.bind(taskId)
- assertThat(systemUnderTest.uiState.first()).isEqualTo(LiveTile)
- }
+ assertThat(systemUnderTest.uiState.first()).isEqualTo(LiveTile)
+ }
@Test
- fun bindRunningTaskShouldShowScreenshot_thenStateIs_SnapshotSplash() = runTest {
- val taskId = 1
- val expectedThumbnailData = createThumbnailData()
- tasksRepository.seedThumbnailData(mapOf(taskId to expectedThumbnailData))
- val expectedIconData = mock<Drawable>()
- tasksRepository.seedIconData(taskId, "Task $taskId", "", expectedIconData)
- tasksRepository.seedTasks(tasks)
- tasksRepository.setVisibleTasks(setOf(taskId))
- recentsViewData.runningTaskIds.value = setOf(taskId)
- recentsViewData.runningTaskShowScreenshot.value = true
- systemUnderTest.bind(taskId)
+ fun bindRunningTaskShouldShowScreenshot_thenStateIs_SnapshotSplash() =
+ testScope.runTest {
+ val taskId = 1
+ val expectedThumbnailData = createThumbnailData()
+ tasksRepository.seedThumbnailData(mapOf(taskId to expectedThumbnailData))
+ val expectedIconData = mock<Drawable>()
+ tasksRepository.seedIconData(taskId, "Task $taskId", "", expectedIconData)
+ tasksRepository.seedTasks(tasks)
+ tasksRepository.setVisibleTasks(setOf(taskId))
+ recentsViewData.runningTaskIds.value = setOf(taskId)
+ recentsViewData.runningTaskShowScreenshot.value = true
+ systemUnderTest.bind(taskId)
- assertThat(systemUnderTest.uiState.first())
- .isEqualTo(
- SnapshotSplash(
- Snapshot(
- backgroundColor = Color.rgb(1, 1, 1),
- bitmap = expectedThumbnailData.thumbnail!!,
- thumbnailRotation = Surface.ROTATION_0,
- ),
- expectedIconData,
+ assertThat(systemUnderTest.uiState.first())
+ .isEqualTo(
+ SnapshotSplash(
+ Snapshot(
+ backgroundColor = Color.rgb(1, 1, 1),
+ bitmap = expectedThumbnailData.thumbnail!!,
+ thumbnailRotation = Surface.ROTATION_0,
+ ),
+ expectedIconData,
+ )
)
- )
- }
+ }
@Test
- fun setRecentsFullscreenProgress_thenCornerRadiusProgressIsPassedThrough() = runTest {
- recentsViewData.fullscreenProgress.value = 0.5f
+ fun setRecentsFullscreenProgress_thenCornerRadiusProgressIsPassedThrough() =
+ testScope.runTest {
+ recentsViewData.fullscreenProgress.value = 0.5f
- assertThat(systemUnderTest.cornerRadiusProgress.first()).isEqualTo(0.5f)
+ assertThat(systemUnderTest.cornerRadiusProgress.first()).isEqualTo(0.5f)
- recentsViewData.fullscreenProgress.value = 0.6f
+ recentsViewData.fullscreenProgress.value = 0.6f
- assertThat(systemUnderTest.cornerRadiusProgress.first()).isEqualTo(0.6f)
- }
+ assertThat(systemUnderTest.cornerRadiusProgress.first()).isEqualTo(0.6f)
+ }
@Test
- fun setRecentsFullscreenProgress_thenCornerRadiusProgressIsConstantForDesktop() = runTest {
- taskViewType = TaskViewType.DESKTOP
- recentsViewData.fullscreenProgress.value = 0.5f
+ fun setRecentsFullscreenProgress_thenCornerRadiusProgressIsConstantForDesktop() =
+ testScope.runTest {
+ taskViewType = TaskViewType.DESKTOP
+ recentsViewData.fullscreenProgress.value = 0.5f
- assertThat(systemUnderTest.cornerRadiusProgress.first()).isEqualTo(1f)
+ assertThat(systemUnderTest.cornerRadiusProgress.first()).isEqualTo(1f)
- recentsViewData.fullscreenProgress.value = 0.6f
+ recentsViewData.fullscreenProgress.value = 0.6f
- assertThat(systemUnderTest.cornerRadiusProgress.first()).isEqualTo(1f)
- }
+ assertThat(systemUnderTest.cornerRadiusProgress.first()).isEqualTo(1f)
+ }
@Test
- fun setAncestorScales_thenScaleIsCalculated() = runTest {
- recentsViewData.scale.value = 0.5f
- taskViewData.scale.value = 0.6f
+ fun setAncestorScales_thenScaleIsCalculated() =
+ testScope.runTest {
+ recentsViewData.scale.value = 0.5f
+ taskViewData.scale.value = 0.6f
- assertThat(systemUnderTest.inheritedScale.first()).isEqualTo(0.3f)
- }
+ assertThat(systemUnderTest.inheritedScale.first()).isEqualTo(0.3f)
+ }
@Test
fun bindRunningTaskThenStoppedTaskWithoutThumbnail_thenStateChangesToBackgroundOnly() =
- runTest {
+ testScope.runTest {
val runningTaskId = 1
val stoppedTaskId = 2
tasksRepository.seedTasks(tasks)
@@ -161,125 +174,138 @@
}
@Test
- fun bindStoppedTaskWithoutThumbnail_thenStateIs_BackgroundOnly_withAlphaRemoved() = runTest {
- val stoppedTaskId = 2
- tasksRepository.seedTasks(tasks)
- tasksRepository.setVisibleTasks(setOf(stoppedTaskId))
+ fun bindStoppedTaskWithoutThumbnail_thenStateIs_BackgroundOnly_withAlphaRemoved() =
+ testScope.runTest {
+ val stoppedTaskId = 2
+ tasksRepository.seedTasks(tasks)
+ tasksRepository.setVisibleTasks(setOf(stoppedTaskId))
- systemUnderTest.bind(stoppedTaskId)
- assertThat(systemUnderTest.uiState.first())
- .isEqualTo(BackgroundOnly(backgroundColor = Color.rgb(2, 2, 2)))
- }
+ systemUnderTest.bind(stoppedTaskId)
+ assertThat(systemUnderTest.uiState.first())
+ .isEqualTo(BackgroundOnly(backgroundColor = Color.rgb(2, 2, 2)))
+ }
@Test
- fun bindLockedTaskWithThumbnail_thenStateIs_BackgroundOnly() = runTest {
- val taskId = 2
- tasksRepository.seedThumbnailData(mapOf(taskId to createThumbnailData()))
- tasks[taskId].isLocked = true
- tasksRepository.seedTasks(tasks)
- tasksRepository.setVisibleTasks(setOf(taskId))
+ fun bindLockedTaskWithThumbnail_thenStateIs_BackgroundOnly() =
+ testScope.runTest {
+ val taskId = 2
+ tasksRepository.seedThumbnailData(mapOf(taskId to createThumbnailData()))
+ tasks[taskId].isLocked = true
+ tasksRepository.seedTasks(tasks)
+ tasksRepository.setVisibleTasks(setOf(taskId))
- systemUnderTest.bind(taskId)
- assertThat(systemUnderTest.uiState.first())
- .isEqualTo(BackgroundOnly(backgroundColor = Color.rgb(2, 2, 2)))
- }
+ systemUnderTest.bind(taskId)
+ assertThat(systemUnderTest.uiState.first())
+ .isEqualTo(BackgroundOnly(backgroundColor = Color.rgb(2, 2, 2)))
+ }
@Test
- fun bindStoppedTaskWithThumbnail_thenStateIs_SnapshotSplash_withAlphaRemoved() = runTest {
- val taskId = 2
- val expectedThumbnailData = createThumbnailData(rotation = Surface.ROTATION_270)
- tasksRepository.seedThumbnailData(mapOf(taskId to expectedThumbnailData))
- val expectedIconData = mock<Drawable>()
- tasksRepository.seedIconData(taskId, "Task $taskId", "", expectedIconData)
- tasksRepository.seedTasks(tasks)
- tasksRepository.setVisibleTasks(setOf(taskId))
+ fun bindStoppedTaskWithThumbnail_thenStateIs_SnapshotSplash_withAlphaRemoved() =
+ testScope.runTest {
+ val taskId = 2
+ val expectedThumbnailData = createThumbnailData(rotation = Surface.ROTATION_270)
+ tasksRepository.seedThumbnailData(mapOf(taskId to expectedThumbnailData))
+ val expectedIconData = mock<Drawable>()
+ tasksRepository.seedIconData(taskId, "Task $taskId", "", expectedIconData)
+ tasksRepository.seedTasks(tasks)
+ tasksRepository.setVisibleTasks(setOf(taskId))
- systemUnderTest.bind(taskId)
- assertThat(systemUnderTest.uiState.first())
- .isEqualTo(
- SnapshotSplash(
- Snapshot(
- backgroundColor = Color.rgb(2, 2, 2),
- bitmap = expectedThumbnailData.thumbnail!!,
- thumbnailRotation = Surface.ROTATION_270,
- ),
- expectedIconData,
+ systemUnderTest.bind(taskId)
+ assertThat(systemUnderTest.uiState.first())
+ .isEqualTo(
+ SnapshotSplash(
+ Snapshot(
+ backgroundColor = Color.rgb(2, 2, 2),
+ bitmap = expectedThumbnailData.thumbnail!!,
+ thumbnailRotation = Surface.ROTATION_270,
+ ),
+ expectedIconData,
+ )
)
- )
- }
+ }
@Test
- fun bindNonVisibleStoppedTask_whenMadeVisible_thenStateIsSnapshotSplash() = runTest {
- val taskId = 2
- val expectedThumbnailData = createThumbnailData()
- tasksRepository.seedThumbnailData(mapOf(taskId to expectedThumbnailData))
- val expectedIconData = mock<Drawable>()
- tasksRepository.seedIconData(taskId, "Task $taskId", "", expectedIconData)
- tasksRepository.seedTasks(tasks)
+ fun bindNonVisibleStoppedTask_whenMadeVisible_thenStateIsSnapshotSplash() =
+ testScope.runTest {
+ val taskId = 2
+ val expectedThumbnailData = createThumbnailData()
+ tasksRepository.seedThumbnailData(mapOf(taskId to expectedThumbnailData))
+ val expectedIconData = mock<Drawable>()
+ tasksRepository.seedIconData(taskId, "Task $taskId", "", expectedIconData)
+ tasksRepository.seedTasks(tasks)
- systemUnderTest.bind(taskId)
- assertThat(systemUnderTest.uiState.first()).isEqualTo(Uninitialized)
+ systemUnderTest.bind(taskId)
+ assertThat(systemUnderTest.uiState.first()).isEqualTo(Uninitialized)
- tasksRepository.setVisibleTasks(setOf(taskId))
- assertThat(systemUnderTest.uiState.first())
- .isEqualTo(
- SnapshotSplash(
- Snapshot(
- backgroundColor = Color.rgb(2, 2, 2),
- bitmap = expectedThumbnailData.thumbnail!!,
- thumbnailRotation = Surface.ROTATION_0,
- ),
- expectedIconData,
+ tasksRepository.setVisibleTasks(setOf(taskId))
+ assertThat(systemUnderTest.uiState.first())
+ .isEqualTo(
+ SnapshotSplash(
+ Snapshot(
+ backgroundColor = Color.rgb(2, 2, 2),
+ bitmap = expectedThumbnailData.thumbnail!!,
+ thumbnailRotation = Surface.ROTATION_0,
+ ),
+ expectedIconData,
+ )
)
- )
- }
+ }
@Test
- fun getSnapshotMatrix_MissingThumbnail() = runTest {
- val taskId = 2
- val isRtl = true
+ fun getSnapshotMatrix_MissingThumbnail() =
+ testScope.runTest {
+ val taskId = 2
+ val isRtl = true
- whenever(mGetThumbnailPositionUseCase.run(taskId, CANVAS_WIDTH, CANVAS_HEIGHT, isRtl))
- .thenReturn(MissingThumbnail)
+ whenever(mGetThumbnailPositionUseCase.run(taskId, CANVAS_WIDTH, CANVAS_HEIGHT, isRtl))
+ .thenReturn(MissingThumbnail)
- systemUnderTest.bind(taskId)
- assertThat(systemUnderTest.getThumbnailPositionState(CANVAS_WIDTH, CANVAS_HEIGHT, isRtl))
- .isEqualTo(Matrix.IDENTITY_MATRIX)
- }
+ systemUnderTest.bind(taskId)
+ assertThat(
+ systemUnderTest.getThumbnailPositionState(CANVAS_WIDTH, CANVAS_HEIGHT, isRtl)
+ )
+ .isEqualTo(Matrix.IDENTITY_MATRIX)
+ }
@Test
- fun getSnapshotMatrix_MatrixScaling() = runTest {
- val taskId = 2
- val isRtl = true
+ fun getSnapshotMatrix_MatrixScaling() =
+ testScope.runTest {
+ val taskId = 2
+ val isRtl = true
- whenever(mGetThumbnailPositionUseCase.run(taskId, CANVAS_WIDTH, CANVAS_HEIGHT, isRtl))
- .thenReturn(MatrixScaling(MATRIX, isRotated = false))
+ whenever(mGetThumbnailPositionUseCase.run(taskId, CANVAS_WIDTH, CANVAS_HEIGHT, isRtl))
+ .thenReturn(MatrixScaling(MATRIX, isRotated = false))
- systemUnderTest.bind(taskId)
- assertThat(systemUnderTest.getThumbnailPositionState(CANVAS_WIDTH, CANVAS_HEIGHT, isRtl))
- .isEqualTo(MATRIX)
- }
+ systemUnderTest.bind(taskId)
+ assertThat(
+ systemUnderTest.getThumbnailPositionState(CANVAS_WIDTH, CANVAS_HEIGHT, isRtl)
+ )
+ .isEqualTo(MATRIX)
+ }
@Test
- fun getForegroundScrimDimProgress_returnsForegroundMaxScrim() = runTest {
- recentsViewData.tintAmount.value = 0.32f
- taskContainerData.taskMenuOpenProgress.value = 0f
- assertThat(systemUnderTest.dimProgress.first()).isEqualTo(0.32f)
- }
+ fun getForegroundScrimDimProgress_returnsForegroundMaxScrim() =
+ testScope.runTest {
+ recentsViewData.tintAmount.value = 0.32f
+ taskContainerData.taskMenuOpenProgress.value = 0f
+ assertThat(systemUnderTest.dimProgress.first()).isEqualTo(0.32f)
+ }
@Test
- fun getTaskMenuScrimDimProgress_returnsTaskMenuScrim() = runTest {
- recentsViewData.tintAmount.value = 0f
- taskContainerData.taskMenuOpenProgress.value = 1f
- assertThat(systemUnderTest.dimProgress.first()).isEqualTo(0.4f)
- }
+ fun getTaskMenuScrimDimProgress_returnsTaskMenuScrim() =
+ testScope.runTest {
+ recentsViewData.tintAmount.value = 0f
+ taskContainerData.taskMenuOpenProgress.value = 1f
+ assertThat(systemUnderTest.dimProgress.first()).isEqualTo(0.4f)
+ }
@Test
- fun getForegroundScrimDimProgress_returnsNoScrim() = runTest {
- recentsViewData.tintAmount.value = 0f
- taskContainerData.taskMenuOpenProgress.value = 0f
- assertThat(systemUnderTest.dimProgress.first()).isEqualTo(0f)
- }
+ fun getForegroundScrimDimProgress_returnsNoScrim() =
+ testScope.runTest {
+ recentsViewData.tintAmount.value = 0f
+ taskContainerData.taskMenuOpenProgress.value = 0f
+ assertThat(systemUnderTest.dimProgress.first()).isEqualTo(0f)
+ }
private fun createTaskWithId(taskId: Int) =
Task(Task.TaskKey(taskId, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
diff --git a/quickstep/tests/src/com/android/quickstep/desktop/DesktopAppLaunchTransitionManagerTest.kt b/quickstep/tests/src/com/android/quickstep/desktop/DesktopAppLaunchTransitionManagerTest.kt
new file mode 100644
index 0000000..26189df
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/desktop/DesktopAppLaunchTransitionManagerTest.kt
@@ -0,0 +1,110 @@
+/*
+ * 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.desktop
+
+import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
+import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
+import android.content.Context
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
+import android.platform.test.flag.junit.SetFlagsRule
+import android.view.WindowManager.TRANSIT_OPEN
+import android.view.WindowManager.TRANSIT_TO_FRONT
+import android.window.TransitionFilter
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
+import com.android.quickstep.SystemUiProxy
+import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+import org.mockito.quality.Strictness
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DesktopAppLaunchTransitionManagerTest {
+
+ @get:Rule val mSetFlagsRule = SetFlagsRule()
+
+ private val mockitoSession =
+ mockitoSession()
+ .strictness(Strictness.LENIENT)
+ .mockStatic(DesktopModeStatus::class.java)
+ .startMocking()
+
+ private val context = mock<Context>()
+ private val systemUiProxy = mock<SystemUiProxy>()
+ private lateinit var transitionManager: DesktopAppLaunchTransitionManager
+
+ @Before
+ fun setUp() {
+ whenever(context.resources).thenReturn(mock())
+ whenever(DesktopModeStatus.canEnterDesktopMode(context)).thenReturn(true)
+ transitionManager = DesktopAppLaunchTransitionManager(context, systemUiProxy)
+ }
+
+ @After
+ fun tearDown() {
+ mockitoSession.finishMocking()
+ }
+
+ @Test
+ @EnableFlags(FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS)
+ fun registerTransitions_appLaunchFlagEnabled_registersTransition() {
+ transitionManager.registerTransitions()
+
+ verify(systemUiProxy, times(1)).registerRemoteTransition(any(), any())
+ }
+
+ @Test
+ @DisableFlags(FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS)
+ fun registerTransitions_appLaunchFlagDisabled_doesntRegisterTransition() {
+ transitionManager.registerTransitions()
+
+ verify(systemUiProxy, times(0)).registerRemoteTransition(any(), any())
+ }
+
+ @Test
+ @EnableFlags(FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS)
+ fun registerTransitions_usesCorrectFilter() {
+ transitionManager.registerTransitions()
+ val filterArgumentCaptor = argumentCaptor<TransitionFilter>()
+
+ verify(systemUiProxy, times(1))
+ .registerRemoteTransition(any(), filterArgumentCaptor.capture())
+
+ assertThat(filterArgumentCaptor.lastValue).isNotNull()
+ assertThat(filterArgumentCaptor.lastValue.mTypeSet)
+ .isEqualTo(intArrayOf(TRANSIT_OPEN, TRANSIT_TO_FRONT))
+ assertThat(filterArgumentCaptor.lastValue.mRequirements).hasLength(1)
+ val launchRequirement = filterArgumentCaptor.lastValue.mRequirements!![0]
+ assertThat(launchRequirement.mModes).isEqualTo(intArrayOf(TRANSIT_OPEN, TRANSIT_TO_FRONT))
+ assertThat(launchRequirement.mActivityType).isEqualTo(ACTIVITY_TYPE_STANDARD)
+ assertThat(launchRequirement.mWindowingMode).isEqualTo(WINDOWING_MODE_FREEFORM)
+ }
+}
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index 68e493d..1ddd453 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -183,7 +183,6 @@
</activity>
<activity-alias android:name="Activity2"
android:label="TestActivity2"
- android:icon="@drawable/test_icon"
android:exported="true"
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
<intent-filter>
@@ -193,7 +192,6 @@
</activity-alias>
<activity-alias android:name="Activity3"
android:label="TestActivity3"
- android:icon="@drawable/test_icon"
android:exported="true"
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
<intent-filter>
@@ -203,7 +201,6 @@
</activity-alias>
<activity-alias android:name="Activity4"
android:label="TestActivity4"
- android:icon="@drawable/test_icon"
android:exported="true"
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
<intent-filter>
@@ -213,7 +210,6 @@
</activity-alias>
<activity-alias android:name="Activity5"
android:label="TestActivity5"
- android:icon="@drawable/test_icon"
android:exported="true"
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
<intent-filter>
@@ -223,7 +219,6 @@
</activity-alias>
<activity-alias android:name="Activity6"
android:label="TestActivity6"
- android:icon="@drawable/test_icon"
android:exported="true"
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
<intent-filter>
@@ -233,7 +228,6 @@
</activity-alias>
<activity-alias android:name="Activity7"
android:label="TestActivity7"
- android:icon="@drawable/test_icon"
android:exported="true"
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
<intent-filter>
@@ -243,7 +237,6 @@
</activity-alias>
<activity-alias android:name="Activity8"
android:label="TestActivity8"
- android:icon="@drawable/test_icon"
android:exported="true"
android:targetActivity="com.android.launcher3.testcomponent.BaseTestingActivity">
<intent-filter>
@@ -253,7 +246,6 @@
</activity-alias>
<activity-alias android:name="Activity9" android:exported="true"
android:label="TestActivity9"
- android:icon="@drawable/test_icon"
android:targetActivity="com.android.launcher3.testcomponent.OtherBaseTestingActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -262,7 +254,6 @@
</activity-alias>
<activity-alias android:name="Activity10" android:exported="true"
android:label="TestActivity10"
- android:icon="@drawable/test_icon"
android:targetActivity="com.android.launcher3.testcomponent.OtherBaseTestingActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -271,7 +262,6 @@
</activity-alias>
<activity-alias android:name="Activity11" android:exported="true"
android:label="TestActivity11"
- android:icon="@drawable/test_icon"
android:targetActivity="com.android.launcher3.testcomponent.OtherBaseTestingActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -280,7 +270,6 @@
</activity-alias>
<activity-alias android:name="Activity12" android:exported="true"
android:label="TestActivity12"
- android:icon="@drawable/test_icon"
android:targetActivity="com.android.launcher3.testcomponent.OtherBaseTestingActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -289,7 +278,6 @@
</activity-alias>
<activity-alias android:name="Activity13" android:exported="true"
android:label="TestActivity13"
- android:icon="@drawable/test_icon"
android:targetActivity="com.android.launcher3.testcomponent.OtherBaseTestingActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -298,7 +286,6 @@
</activity-alias>
<activity-alias android:name="Activity14" android:exported="true"
android:label="TestActivity14"
- android:icon="@drawable/test_icon"
android:targetActivity="com.android.launcher3.testcomponent.OtherBaseTestingActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -376,7 +363,7 @@
</activity>
<activity android:name="com.android.launcher3.testcomponent.ImeTestActivity"
android:label="ImeTestActivity"
- android:icon="@drawable/test_icon"
+ android:icon="@drawable/test_theme_icon"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/tests/multivalentTests/src/com/android/launcher3/model/FolderIconLoadTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/FolderIconLoadTest.kt
index e8f778f..7cd5da4 100644
--- a/tests/multivalentTests/src/com/android/launcher3/model/FolderIconLoadTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/model/FolderIconLoadTest.kt
@@ -18,7 +18,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.launcher3.LauncherAppState
-import com.android.launcher3.icons.BitmapInfo
import com.android.launcher3.icons.waitForUpdateHandlerToFinish
import com.android.launcher3.model.data.WorkspaceItemInfo
import com.android.launcher3.util.Executors
@@ -161,9 +160,6 @@
assertWithMessage("Index $index was not highRes")
.that(items[index].bitmap.isNullOrLowRes)
.isFalse()
- assertWithMessage("Index $index was the default icon")
- .that(isDefaultIcon(items[index].bitmap))
- .isFalse()
}
}
@@ -172,17 +168,9 @@
assertWithMessage("Index $index was not lowRes")
.that(items[index].bitmap.isNullOrLowRes)
.isTrue()
- assertWithMessage("Index $index was the default icon")
- .that(isDefaultIcon(items[index].bitmap))
- .isFalse()
}
}
- private fun isDefaultIcon(bitmap: BitmapInfo) =
- LauncherAppState.getInstance(modelHelper.sandboxContext)
- .iconCache
- .isDefaultIcon(bitmap, modelHelper.sandboxContext.user)
-
/** Recreate DeviceProfiles after changing InvariantDeviceProfile */
private fun recreateSupportedDeviceProfiles() {
LauncherAppState.getIDP(modelHelper.sandboxContext).supportedProfiles =
diff --git a/tests/res/drawable/test_icon.xml b/tests/res/drawable/test_icon.xml
deleted file mode 100644
index 72ebfeb..0000000
--- a/tests/res/drawable/test_icon.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-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.
--->
-<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
- <background android:drawable="@android:color/white"/>
- <foreground>
- <color android:color="#FFFF0000" />
- </foreground>
- <monochrome>
- <vector android:width="48dp" android:height="48dp" android:viewportWidth="48.0" android:viewportHeight="48.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M0,24L48,24 48,48, 0,48 Z"/>
- </vector>
- </monochrome>
-</adaptive-icon>