Merge "Don't use flow for one-off get of ThumbnailData" into main

This commit is contained in:
Treehugger Robot
2024-12-10 19:21:36 +00:00
committed by Android (Google) Code Review
9 changed files with 82 additions and 44 deletions
@@ -36,6 +36,12 @@ interface RecentTasksRepository {
*/
fun getThumbnailById(taskId: Int): Flow<ThumbnailData?>
/**
* Gets the [ThumbnailData] associated with a task that has id [taskId]. Flow will settle on
* null if the task was not found or is invisible.
*/
fun getCurrentThumbnailById(taskId: Int): ThumbnailData?
/**
* Sets the tasks that are visible, indicating that properties relating to visuals need to be
* populated e.g. icons/thumbnails etc.
@@ -72,6 +72,8 @@ class TasksRepository(
override fun getThumbnailById(taskId: Int) =
getTaskDataById(taskId).map { it?.thumbnail }.distinctUntilChangedBy { it?.snapshotId }
override fun getCurrentThumbnailById(taskId: Int) = tasks.value[taskId]?.thumbnail
override fun setVisibleTasks(visibleTaskIdList: Set<Int>) {
val tasksNoLongerVisible = taskRequests.keys.subtract(visibleTaskIdList)
val newlyVisibleTasks = visibleTaskIdList.subtract(taskRequests.keys)
@@ -24,18 +24,17 @@ import com.android.quickstep.recents.data.RecentsRotationStateRepository
import com.android.quickstep.recents.usecase.ThumbnailPositionState.MatrixScaling
import com.android.quickstep.recents.usecase.ThumbnailPositionState.MissingThumbnail
import com.android.systemui.shared.recents.utilities.PreviewPositionHelper
import kotlinx.coroutines.flow.firstOrNull
/** Use case for retrieving [Matrix] for positioning Thumbnail in a View */
class GetThumbnailPositionUseCase(
private val deviceProfileRepository: RecentsDeviceProfileRepository,
private val rotationStateRepository: RecentsRotationStateRepository,
private val tasksRepository: RecentTasksRepository,
private val previewPositionHelper: PreviewPositionHelper = PreviewPositionHelper()
private val previewPositionHelper: PreviewPositionHelper = PreviewPositionHelper(),
) {
suspend fun run(taskId: Int, width: Int, height: Int, isRtl: Boolean): ThumbnailPositionState {
fun run(taskId: Int, width: Int, height: Int, isRtl: Boolean): ThumbnailPositionState {
val thumbnailData =
tasksRepository.getThumbnailById(taskId).firstOrNull() ?: return MissingThumbnail
tasksRepository.getCurrentThumbnailById(taskId) ?: return MissingThumbnail
val thumbnail = thumbnailData.thumbnail ?: return MissingThumbnail
previewPositionHelper.updateThumbnailMatrix(
Rect(0, 0, thumbnail.width, thumbnail.height),
@@ -44,11 +43,11 @@ class GetThumbnailPositionUseCase(
height,
deviceProfileRepository.getRecentsDeviceProfile().isLargeScreen,
rotationStateRepository.getRecentsRotationState().activityRotation,
isRtl
isRtl,
)
return MatrixScaling(
previewPositionHelper.matrix,
previewPositionHelper.isOrientationChanged
previewPositionHelper.isOrientationChanged,
)
}
}
@@ -18,13 +18,9 @@ package com.android.quickstep.recents.usecase
import android.graphics.Bitmap
import com.android.quickstep.recents.data.RecentTasksRepository
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.runBlocking
/** Use case for retrieving thumbnail. */
class GetThumbnailUseCase(private val taskRepository: RecentTasksRepository) {
/** Returns the latest thumbnail associated with [taskId] if loaded, or null otherwise */
fun run(taskId: Int): Bitmap? = runBlocking {
taskRepository.getThumbnailById(taskId).firstOrNull()?.thumbnail
}
fun run(taskId: Int): Bitmap? = taskRepository.getCurrentThumbnailById(taskId)?.thumbnail
}
@@ -22,14 +22,11 @@ import com.android.launcher3.util.SystemUiController.FLAG_DARK_STATUS
import com.android.launcher3.util.SystemUiController.FLAG_LIGHT_NAV
import com.android.launcher3.util.SystemUiController.FLAG_LIGHT_STATUS
import com.android.quickstep.recents.data.RecentTasksRepository
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.runBlocking
/** UseCase to calculate flags for status bar and navigation bar */
class SysUiStatusNavFlagsUseCase(private val taskRepository: RecentTasksRepository) {
fun getSysUiStatusNavFlags(taskId: Int): Int {
val thumbnailData =
runBlocking { taskRepository.getThumbnailById(taskId).firstOrNull() } ?: return 0
val thumbnailData = taskRepository.getCurrentThumbnailById(taskId) ?: return 0
val thumbnailAppearance = thumbnailData.appearance
var flags = 0
@@ -28,7 +28,6 @@ import com.android.systemui.shared.recents.model.Task
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.runBlocking
/** View model for TaskOverlay */
class TaskOverlayViewModel(
@@ -41,7 +40,7 @@ class TaskOverlayViewModel(
combine(
recentsViewData.overlayEnabled,
recentsViewData.settledFullyVisibleTaskIds.map { it.contains(task.key.id) },
recentTasksRepository.getThumbnailById(task.key.id)
recentTasksRepository.getThumbnailById(task.key.id),
) { isOverlayEnabled, isFullyVisible, thumbnailData ->
if (isOverlayEnabled && isFullyVisible) {
Enabled(
@@ -55,24 +54,22 @@ class TaskOverlayViewModel(
.distinctUntilChanged()
fun getThumbnailPositionState(width: Int, height: Int, isRtl: Boolean): ThumbnailPositionState {
return runBlocking {
val matrix: Matrix
val isRotated: Boolean
when (
val thumbnailPositionState =
getThumbnailPositionUseCase.run(task.key.id, width, height, isRtl)
) {
is MatrixScaling -> {
matrix = thumbnailPositionState.matrix
isRotated = thumbnailPositionState.isRotated
}
is MissingThumbnail -> {
matrix = Matrix.IDENTITY_MATRIX
isRotated = false
}
val matrix: Matrix
val isRotated: Boolean
when (
val thumbnailPositionState =
getThumbnailPositionUseCase.run(task.key.id, width, height, isRtl)
) {
is MatrixScaling -> {
matrix = thumbnailPositionState.matrix
isRotated = thumbnailPositionState.isRotated
}
is MissingThumbnail -> {
matrix = Matrix.IDENTITY_MATRIX
isRotated = false
}
ThumbnailPositionState(matrix, isRotated)
}
return ThumbnailPositionState(matrix, isRotated)
}
data class ThumbnailPositionState(val matrix: Matrix, val isRotated: Boolean)
@@ -44,7 +44,6 @@ import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.runBlocking
@OptIn(ExperimentalCoroutinesApi::class)
class TaskThumbnailViewModelImpl(
@@ -109,17 +108,14 @@ class TaskThumbnailViewModelImpl(
splashProgress.value = splashAlphaUseCase.execute(taskId)
}
override fun getThumbnailPositionState(width: Int, height: Int, isRtl: Boolean): Matrix {
return runBlocking {
when (
val thumbnailPositionState =
getThumbnailPositionUseCase.run(taskId, width, height, isRtl)
) {
is ThumbnailPositionState.MatrixScaling -> thumbnailPositionState.matrix
is ThumbnailPositionState.MissingThumbnail -> Matrix.IDENTITY_MATRIX
}
override fun getThumbnailPositionState(width: Int, height: Int, isRtl: Boolean): Matrix =
when (
val thumbnailPositionState =
getThumbnailPositionUseCase.run(taskId, width, height, isRtl)
) {
is ThumbnailPositionState.MatrixScaling -> thumbnailPositionState.matrix
is ThumbnailPositionState.MissingThumbnail -> Matrix.IDENTITY_MATRIX
}
}
private fun isBackgroundOnly(task: Task): Boolean = task.isLocked || task.thumbnail == null
@@ -49,6 +49,9 @@ class FakeTasksRepository : RecentTasksRepository {
override fun getThumbnailById(taskId: Int): Flow<ThumbnailData?> =
getTaskDataById(taskId).map { it?.thumbnail }
override fun getCurrentThumbnailById(taskId: Int): ThumbnailData? =
tasks.value.firstOrNull { it.key.id == taskId }?.thumbnail
override fun setVisibleTasks(visibleTaskIdList: Set<Int>) {
visibleTasks.value = visibleTaskIdList
tasks.value =
@@ -86,6 +86,48 @@ class TasksRepositoryTest {
assertThat(systemUnderTest.getTaskDataById(2).first()).isEqualTo(tasks[2])
}
@Test
fun getThumbnailByIdReturnsNullWithNoLoadedThumbnails() =
testScope.runTest {
recentsModel.seedTasks(defaultTaskList)
systemUnderTest.getAllTaskData(forceRefresh = true)
assertThat(systemUnderTest.getThumbnailById(1).first()).isNull()
}
@Test
fun getCurrentThumbnailByIdReturnsNullWithNoLoadedThumbnails() =
testScope.runTest {
recentsModel.seedTasks(defaultTaskList)
systemUnderTest.getAllTaskData(forceRefresh = true)
assertThat(systemUnderTest.getCurrentThumbnailById(1)).isNull()
}
@Test
fun getThumbnailByIdReturnsThumbnailWithLoadedThumbnails() =
testScope.runTest {
recentsModel.seedTasks(defaultTaskList)
systemUnderTest.getAllTaskData(forceRefresh = true)
val bitmap1 = taskThumbnailDataSource.taskIdToBitmap[1]
systemUnderTest.setVisibleTasks(setOf(1))
assertThat(systemUnderTest.getThumbnailById(1).first()!!.thumbnail).isEqualTo(bitmap1)
}
@Test
fun getCurrentThumbnailByIdReturnsThumbnailWithLoadedThumbnails() =
testScope.runTest {
recentsModel.seedTasks(defaultTaskList)
systemUnderTest.getAllTaskData(forceRefresh = true)
val bitmap1 = taskThumbnailDataSource.taskIdToBitmap[1]
systemUnderTest.setVisibleTasks(setOf(1))
assertThat(systemUnderTest.getCurrentThumbnailById(1)?.thumbnail).isEqualTo(bitmap1)
}
@Test
fun setVisibleTasksPopulatesThumbnails() =
testScope.runTest {