Merge changes I31d9a51e,I1bc14be7 into main

* changes:
  Prevent requestLayout() when updating drawables that don't change size
  Fix splash icon size to 52dp
This commit is contained in:
Uwais Ashraf
2024-08-22 09:13:41 +00:00
committed by Android (Google) Code Review
19 changed files with 109 additions and 245 deletions
+22 -14
View File
@@ -15,22 +15,23 @@
-->
<com.android.quickstep.task.thumbnail.TaskThumbnailView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent" >
<ImageView
<com.android.quickstep.views.FixedSizeImageView
android:id="@+id/task_thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:importantForAccessibility="no"
android:scaleType="matrix"
android:visibility="gone"/>
android:visibility="invisible"/>
<com.android.quickstep.task.thumbnail.LiveTileView
android:id="@+id/task_thumbnail_live_tile"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"/>
android:visibility="invisible"/>
<View
android:id="@+id/task_thumbnail_scrim"
@@ -39,16 +40,23 @@
android:background="@color/overview_foreground_scrim_color"
android:alpha="0" />
<FrameLayout
android:id="@+id/splash_container"
<View
android:id="@+id/splash_background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<ImageView
android:id="@+id/splash_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:importantForAccessibility="no" />
</FrameLayout>
android:background="@android:color/black"
android:alpha="0"
android:importantForAccessibility="no" />
<com.android.quickstep.views.FixedSizeImageView
android:id="@+id/splash_icon"
android:layout_width="@dimen/task_thumbnail_splash_icon_size"
android:layout_height="@dimen/task_thumbnail_splash_icon_size"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:scaleType="fitCenter"
android:alpha="0"
android:importantForAccessibility="no" />
</com.android.quickstep.task.thumbnail.TaskThumbnailView>
+2
View File
@@ -41,6 +41,8 @@
<dimen name="task_thumbnail_icon_size">48dp</dimen>
<!-- The icon size for the focused task, placed in center of touch target -->
<dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
<!-- The splash icon size on in Overview when a task is settled in the list -->
<dimen name="task_thumbnail_splash_icon_size">52dp</dimen>
<!-- The border width shown when task is hovered -->
<dimen name="task_hover_border_width">4dp</dimen>
<!-- The space under the focused task icon -->
@@ -23,6 +23,4 @@ package com.android.quickstep.recents.data
*/
data class RecentsDeviceProfile(
val isLargeScreen: Boolean,
val widthPx: Int,
val heightPx: Int,
)
@@ -26,7 +26,5 @@ class RecentsDeviceProfileRepositoryImpl(private val container: RecentsViewConta
RecentsDeviceProfileRepository {
override fun getRecentsDeviceProfile() =
with(container.deviceProfile) {
RecentsDeviceProfile(isLargeScreen = isTablet, widthPx = widthPx, heightPx = heightPx)
}
with(container.deviceProfile) { RecentsDeviceProfile(isLargeScreen = isTablet) }
}
@@ -27,7 +27,6 @@ import com.android.quickstep.recents.usecase.GetThumbnailPositionUseCase
import com.android.quickstep.recents.usecase.GetThumbnailUseCase
import com.android.quickstep.recents.usecase.SysUiStatusNavFlagsUseCase
import com.android.quickstep.recents.viewmodel.RecentsViewData
import com.android.quickstep.task.thumbnail.GetSplashSizeUseCase
import com.android.quickstep.task.thumbnail.SplashAlphaUseCase
import com.android.quickstep.task.thumbnail.TaskThumbnailViewData
import com.android.quickstep.task.viewmodel.TaskContainerData
@@ -176,7 +175,6 @@ class RecentsDependencies private constructor(private val appContext: Context) {
getThumbnailPositionUseCase = inject(),
tasksRepository = inject(),
splashAlphaUseCase = inject(scopeId),
getSplashSizeUseCase = inject(scopeId),
)
TaskOverlayViewModel::class.java -> {
val task = extras["Task"] as Task
@@ -204,12 +202,6 @@ class RecentsDependencies private constructor(private val appContext: Context) {
tasksRepository = inject(),
rotationStateRepository = inject(),
)
GetSplashSizeUseCase::class.java ->
GetSplashSizeUseCase(
taskThumbnailViewData = inject(scopeId),
taskViewData = inject(scopeId, extras),
deviceProfileRepository = inject(),
)
else -> {
log("Factory for ${modelClass.simpleName} not defined!", Log.ERROR)
error("Factory for ${modelClass.simpleName} not defined!")
@@ -1,46 +0,0 @@
/*
* 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.task.thumbnail
import android.graphics.Point
import android.graphics.drawable.Drawable
import com.android.quickstep.recents.data.RecentsDeviceProfileRepository
import com.android.quickstep.task.viewmodel.TaskViewData
import kotlin.math.min
class GetSplashSizeUseCase(
private val taskThumbnailViewData: TaskThumbnailViewData,
private val taskViewData: TaskViewData,
private val deviceProfileRepository: RecentsDeviceProfileRepository,
) {
fun execute(splashImage: Drawable): Point {
val recentsDeviceProfile = deviceProfileRepository.getRecentsDeviceProfile()
val screenWidth = recentsDeviceProfile.widthPx
val screenHeight = recentsDeviceProfile.heightPx
val scaleAtFullscreen =
min(
screenWidth / taskThumbnailViewData.width.value,
screenHeight / taskThumbnailViewData.height.value,
)
val scaleFactor: Float = 1f / taskViewData.nonGridScale.value / scaleAtFullscreen
return Point(
(splashImage.intrinsicWidth * scaleFactor / taskThumbnailViewData.scaleX.value).toInt(),
(splashImage.intrinsicHeight * scaleFactor / taskThumbnailViewData.scaleY.value)
.toInt(),
)
}
}
@@ -17,7 +17,6 @@
package com.android.quickstep.task.thumbnail
import android.graphics.Bitmap
import android.graphics.Point
import android.graphics.drawable.Drawable
import android.view.Surface
import androidx.annotation.ColorInt
@@ -31,7 +30,7 @@ sealed class TaskThumbnailUiState {
data class SnapshotSplash(
val snapshot: Snapshot,
val splash: Splash,
val splash: Drawable?,
) : TaskThumbnailUiState()
data class Snapshot(
@@ -39,9 +38,4 @@ sealed class TaskThumbnailUiState {
@Surface.Rotation val thumbnailRotation: Int,
@ColorInt val backgroundColor: Int
)
data class Splash(
val icon: Drawable?,
val size: Point,
)
}
@@ -24,11 +24,9 @@ import android.graphics.Rect
import android.util.AttributeSet
import android.view.View
import android.view.ViewOutlineProvider
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.annotation.ColorInt
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.isInvisible
import com.android.launcher3.R
import com.android.launcher3.Utilities
import com.android.launcher3.util.ViewPool
@@ -41,6 +39,7 @@ import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.SnapshotSplash
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
import com.android.quickstep.task.viewmodel.TaskThumbnailViewModel
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
@@ -51,7 +50,7 @@ import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
class TaskThumbnailView : FrameLayout, ViewPool.Reusable {
class TaskThumbnailView : ConstraintLayout, ViewPool.Reusable {
private val viewData: TaskThumbnailViewData by RecentsDependencies.inject(this)
private val viewModel: TaskThumbnailViewModel by RecentsDependencies.inject(this)
@@ -60,9 +59,9 @@ class TaskThumbnailView : FrameLayout, ViewPool.Reusable {
private val scrimView: View by lazy { findViewById(R.id.task_thumbnail_scrim) }
private val liveTileView: LiveTileView by lazy { findViewById(R.id.task_thumbnail_live_tile) }
private val thumbnailView: ImageView by lazy { findViewById(R.id.task_thumbnail) }
private val splashContainer: FrameLayout by lazy { findViewById(R.id.splash_container) }
private val splashIcon: ImageView by lazy { findViewById(R.id.splash_icon) }
private val thumbnailView: FixedSizeImageView by lazy { findViewById(R.id.task_thumbnail) }
private val splashBackground: View by lazy { findViewById(R.id.splash_background) }
private val splashIcon: FixedSizeImageView by lazy { findViewById(R.id.splash_icon) }
private var uiState: TaskThumbnailUiState = Uninitialized
private var inheritedScale: Float = 1f
@@ -107,7 +106,10 @@ class TaskThumbnailView : FrameLayout, ViewPool.Reusable {
.onEach { dimProgress -> scrimView.alpha = dimProgress }
.launchIn(viewAttachedScope)
viewModel.splashAlpha
.onEach { splashAlpha -> splashContainer.alpha = splashAlpha }
.onEach { splashAlpha ->
splashBackground.alpha = splashAlpha
splashIcon.alpha = splashAlpha
}
.launchIn(viewAttachedScope)
viewModel.cornerRadiusProgress.onEach { invalidateOutline() }.launchIn(viewAttachedScope)
viewModel.inheritedScale
@@ -152,15 +154,13 @@ class TaskThumbnailView : FrameLayout, ViewPool.Reusable {
override fun setScaleX(scaleX: Float) {
super.setScaleX(scaleX)
viewData.scaleX.value = scaleX
// Splash icon should ignore scale
// Splash icon should ignore scale on TTV
splashIcon.scaleX = 1 / scaleX
}
override fun setScaleY(scaleY: Float) {
super.setScaleY(scaleY)
viewData.scaleY.value = scaleY
// Splash icon should ignore scale
// Splash icon should ignore scale on TTV
splashIcon.scaleY = 1 / scaleY
}
@@ -173,9 +173,10 @@ class TaskThumbnailView : FrameLayout, ViewPool.Reusable {
}
private fun resetViews() {
liveTileView.isVisible = false
thumbnailView.isVisible = false
splashContainer.alpha = 0f
liveTileView.isInvisible = true
thumbnailView.isInvisible = true
splashBackground.alpha = 0f
splashIcon.alpha = 0f
scrimView.alpha = 0f
setBackgroundColor(Color.BLACK)
}
@@ -185,25 +186,20 @@ class TaskThumbnailView : FrameLayout, ViewPool.Reusable {
}
private fun drawLiveWindow() {
liveTileView.isVisible = true
liveTileView.isInvisible = false
}
private fun drawSnapshotSplash(snapshotSplash: SnapshotSplash) {
drawSnapshot(snapshotSplash.snapshot)
splashContainer.isVisible = true
splashContainer.setBackgroundColor(snapshotSplash.snapshot.backgroundColor)
splashIcon.setImageDrawable(snapshotSplash.splash.icon)
splashIcon.updateLayoutParams<LayoutParams> {
width = snapshotSplash.splash.size.x
height = snapshotSplash.splash.size.y
}
splashBackground.setBackgroundColor(snapshotSplash.snapshot.backgroundColor)
splashIcon.setImageDrawable(snapshotSplash.splash)
}
private fun drawSnapshot(snapshot: Snapshot) {
drawBackground(snapshot.backgroundColor)
thumbnailView.setImageBitmap(snapshot.bitmap)
thumbnailView.isVisible = true
thumbnailView.isInvisible = false
setImageMatrix()
}
@@ -21,6 +21,4 @@ import kotlinx.coroutines.flow.MutableStateFlow
class TaskThumbnailViewData {
val width = MutableStateFlow(0)
val height = MutableStateFlow(0)
val scaleX = MutableStateFlow(1f)
val scaleY = MutableStateFlow(1f)
}
@@ -19,20 +19,17 @@ package com.android.quickstep.task.viewmodel
import android.annotation.ColorInt
import android.app.ActivityTaskManager.INVALID_TASK_ID
import android.graphics.Matrix
import android.graphics.Point
import androidx.core.graphics.ColorUtils
import com.android.quickstep.recents.data.RecentTasksRepository
import com.android.quickstep.recents.usecase.GetThumbnailPositionUseCase
import com.android.quickstep.recents.usecase.ThumbnailPositionState
import com.android.quickstep.recents.viewmodel.RecentsViewData
import com.android.quickstep.task.thumbnail.GetSplashSizeUseCase
import com.android.quickstep.task.thumbnail.SplashAlphaUseCase
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.BackgroundOnly
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.LiveTile
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Snapshot
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.SnapshotSplash
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Splash
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
import com.android.systemui.shared.recents.model.Task
import kotlin.math.max
@@ -55,7 +52,6 @@ class TaskThumbnailViewModel(
private val tasksRepository: RecentTasksRepository,
private val getThumbnailPositionUseCase: GetThumbnailPositionUseCase,
private val splashAlphaUseCase: SplashAlphaUseCase,
private val getSplashSizeUseCase: GetSplashSizeUseCase,
) {
private val task = MutableStateFlow<Flow<Task?>>(flowOf(null))
private val splashProgress = MutableStateFlow(flowOf(0f))
@@ -100,7 +96,7 @@ class TaskThumbnailViewModel(
isBackgroundOnly(taskVal) ->
BackgroundOnly(taskVal.colorBackground.removeAlpha())
isSnapshotSplashState(taskVal) ->
SnapshotSplash(createSnapshotState(taskVal), createSplashState(taskVal))
SnapshotSplash(createSnapshotState(taskVal), taskVal.icon)
else -> Uninitialized
}
}
@@ -139,12 +135,6 @@ class TaskThumbnailViewModel(
return Snapshot(bitmap, thumbnailData.rotation, task.colorBackground.removeAlpha())
}
private fun createSplashState(task: Task): Splash {
val taskIcon = task.icon
val size = if (taskIcon == null) Point() else getSplashSizeUseCase.execute(taskIcon)
return Splash(taskIcon, size)
}
@ColorInt private fun Int.removeAlpha(): Int = ColorUtils.setAlphaComponent(this, 0xff)
private companion object {
@@ -23,8 +23,6 @@ class TaskViewData(taskViewType: TaskViewType) {
// This is typically a View concern but it is used to invalidate rendering in other Views
val scale = MutableStateFlow(1f)
val nonGridScale = MutableStateFlow(1f)
// TODO(b/331753115): This property should not be in TaskViewData once TaskView is MVVM.
/** Whether outline of TaskView is formed by outline thumbnail view(s). */
val isOutlineFormedByThumbnailView: Boolean = taskViewType != TaskViewType.DESKTOP
@@ -22,8 +22,4 @@ class TaskViewModel(private val taskViewData: TaskViewData) : ViewModel() {
fun updateScale(scale: Float) {
taskViewData.scale.value = scale
}
fun updateNonGridScale(nonGridScale: Float) {
taskViewData.nonGridScale.value = nonGridScale
}
}
@@ -0,0 +1,56 @@
/*
* 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.views
import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.ViewGroup
import android.widget.ImageView
/**
* An [ImageView] that does not requestLayout() unless setLayoutParams is called.
*
* This is useful, particularly during animations, for [ImageView]s that are not supposed to be
* resized.
*/
@SuppressLint("AppCompatCustomView")
class FixedSizeImageView : ImageView {
private var shouldRequestLayoutOnChanges = false
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
) : super(context, attrs, defStyleAttr)
override fun setLayoutParams(params: ViewGroup.LayoutParams?) {
shouldRequestLayoutOnChanges = true
super.setLayoutParams(params)
shouldRequestLayoutOnChanges = false
}
override fun requestLayout() {
if (shouldRequestLayoutOnChanges) {
super.requestLayout()
}
}
}
@@ -293,9 +293,6 @@ constructor(
set(value) {
field = value
applyScale()
if (enableRefactorTaskThumbnail()) {
taskViewModel.updateNonGridScale(value)
}
}
private var dismissScale = 1f
@@ -20,8 +20,6 @@ class FakeRecentsDeviceProfileRepository : RecentsDeviceProfileRepository {
private var recentsDeviceProfile =
RecentsDeviceProfile(
isLargeScreen = false,
widthPx = 1080,
heightPx = 1920,
)
override fun getRecentsDeviceProfile() = recentsDeviceProfile
@@ -39,6 +39,6 @@ class RecentsDeviceProfileRepositoryImplTest : FakeInvariantDeviceProfileTest()
whenever(recentsViewContainer.deviceProfile).thenReturn(tabletDeviceProfile)
assertThat(systemUnderTest.getRecentsDeviceProfile())
.isEqualTo(RecentsDeviceProfile(isLargeScreen = true, widthPx = 1600, heightPx = 2560))
.isEqualTo(RecentsDeviceProfile(isLargeScreen = true))
}
}
@@ -1,84 +0,0 @@
/*
* 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.task.thumbnail
import android.graphics.Point
import android.graphics.drawable.Drawable
import com.android.quickstep.recents.data.FakeRecentsDeviceProfileRepository
import com.android.quickstep.task.viewmodel.TaskViewData
import com.android.quickstep.views.TaskViewType
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
class GetSplashSizeUseCaseTest {
private val taskThumbnailViewData = TaskThumbnailViewData()
private val taskViewData = TaskViewData(TaskViewType.SINGLE)
private val recentsDeviceProfileRepository = FakeRecentsDeviceProfileRepository()
private val systemUnderTest =
GetSplashSizeUseCase(taskThumbnailViewData, taskViewData, recentsDeviceProfileRepository)
@Test
fun execute_whenNoScaleRequired_returnsIntrinsicSize() {
taskThumbnailViewData.width.value =
recentsDeviceProfileRepository.getRecentsDeviceProfile().widthPx
taskThumbnailViewData.height.value =
recentsDeviceProfileRepository.getRecentsDeviceProfile().heightPx
assertThat(systemUnderTest.execute(createIcon(100, 100))).isEqualTo(Point(100, 100))
}
@Test
fun execute_whenThumbnailViewIsSmallerThanScreen_returnsScaledSize() {
taskThumbnailViewData.width.value =
recentsDeviceProfileRepository.getRecentsDeviceProfile().widthPx / 2
taskThumbnailViewData.height.value =
recentsDeviceProfileRepository.getRecentsDeviceProfile().heightPx / 2
assertThat(systemUnderTest.execute(createIcon(100, 100))).isEqualTo(Point(50, 50))
}
@Test
fun execute_whenThumbnailViewIsSmallerThanScreen_withNonGridScale_returnsScaledSize() {
taskThumbnailViewData.width.value =
recentsDeviceProfileRepository.getRecentsDeviceProfile().widthPx / 2
taskThumbnailViewData.height.value =
recentsDeviceProfileRepository.getRecentsDeviceProfile().heightPx / 2
taskViewData.nonGridScale.value = 2f
assertThat(systemUnderTest.execute(createIcon(100, 100))).isEqualTo(Point(25, 25))
}
@Test
fun execute_whenThumbnailViewIsSmallerThanScreen_withThumbnailViewScale_returnsScaledSize() {
taskThumbnailViewData.width.value =
recentsDeviceProfileRepository.getRecentsDeviceProfile().widthPx / 2
taskThumbnailViewData.height.value =
recentsDeviceProfileRepository.getRecentsDeviceProfile().heightPx / 2
taskThumbnailViewData.scaleX.value = 2f
taskThumbnailViewData.scaleY.value = 2f
assertThat(systemUnderTest.execute(createIcon(100, 100))).isEqualTo(Point(25, 25))
}
private fun createIcon(width: Int, height: Int): Drawable =
mock<Drawable>().apply {
whenever(intrinsicWidth).thenReturn(width)
whenever(intrinsicHeight).thenReturn(height)
}
}
@@ -21,7 +21,6 @@ import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.Matrix
import android.graphics.Point
import android.graphics.drawable.Drawable
import android.view.Surface
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -35,7 +34,6 @@ import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.BackgroundOnly
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.LiveTile
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Snapshot
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.SnapshotSplash
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Splash
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
import com.android.quickstep.task.viewmodel.TaskContainerData
import com.android.quickstep.task.viewmodel.TaskThumbnailViewModel
@@ -46,10 +44,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.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
@@ -63,7 +59,6 @@ class TaskThumbnailViewModelTest {
private val tasksRepository = FakeTasksRepository()
private val mGetThumbnailPositionUseCase = mock<GetThumbnailPositionUseCase>()
private val splashAlphaUseCase: SplashAlphaUseCase = mock()
private val getSplashSizeUseCase: GetSplashSizeUseCase = mock()
private val systemUnderTest by lazy {
TaskThumbnailViewModel(
recentsViewData,
@@ -72,17 +67,11 @@ class TaskThumbnailViewModelTest {
tasksRepository,
mGetThumbnailPositionUseCase,
splashAlphaUseCase,
getSplashSizeUseCase,
)
}
private val tasks = (0..5).map(::createTaskWithId)
@Before
fun setUp() {
whenever(getSplashSizeUseCase.execute(any())).thenReturn(Point())
}
@Test
fun initialStateIsUninitialized() = runTest {
assertThat(systemUnderTest.uiState.first()).isEqualTo(Uninitialized)
@@ -120,7 +109,7 @@ class TaskThumbnailViewModelTest {
bitmap = expectedThumbnailData.thumbnail!!,
thumbnailRotation = Surface.ROTATION_0,
),
Splash(expectedIconData.icon, Point())
expectedIconData.icon
)
)
}
@@ -215,7 +204,7 @@ class TaskThumbnailViewModelTest {
bitmap = expectedThumbnailData.thumbnail!!,
thumbnailRotation = Surface.ROTATION_270,
),
Splash(expectedIconData.icon, Point())
expectedIconData.icon
)
)
}
@@ -241,28 +230,11 @@ class TaskThumbnailViewModelTest {
bitmap = expectedThumbnailData.thumbnail!!,
thumbnailRotation = Surface.ROTATION_0,
),
Splash(expectedIconData.icon, Point())
expectedIconData.icon
)
)
}
@Test
fun bindStoppedTask_thenStateContainsSplashSizeFromUseCase() = runTest {
val taskId = 2
val expectedSplashSize = Point(100, 150)
whenever(getSplashSizeUseCase.execute(any())).thenReturn(expectedSplashSize)
val expectedThumbnailData = createThumbnailData(rotation = Surface.ROTATION_270)
tasksRepository.seedThumbnailData(mapOf(taskId to expectedThumbnailData))
val expectedIconData = createIconData("Task 2")
tasksRepository.seedIconData(mapOf(taskId to expectedIconData))
tasksRepository.seedTasks(tasks)
tasksRepository.setVisibleTasks(listOf(taskId))
systemUnderTest.bind(taskId)
val uiState = systemUnderTest.uiState.first() as SnapshotSplash
assertThat(uiState.splash.size).isEqualTo(expectedSplashSize)
}
@Test
fun getSnapshotMatrix_MissingThumbnail() = runTest {
val taskId = 2
+1
View File
@@ -456,6 +456,7 @@
<!-- Overview placeholder to compile in Launcher3 without Quickstep -->
<dimen name="task_thumbnail_icon_size">0dp</dimen>
<dimen name="task_thumbnail_icon_drawable_size">0dp</dimen>
<dimen name="task_thumbnail_splash_icon_size">0dp</dimen>
<dimen name="task_thumbnail_icon_drawable_size_grid">0dp</dimen>
<dimen name="task_thumbnail_icon_menu_drawable_touch_size">0dp</dimen>
<dimen name="task_menu_edge_padding">0dp</dimen>