1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.quickstep.recents.viewmodel 18 19 import android.content.ComponentName 20 import android.content.Intent 21 import android.graphics.Bitmap 22 import android.graphics.Color 23 import android.view.Surface 24 import com.android.quickstep.recents.data.FakeTasksRepository 25 import com.android.systemui.shared.recents.model.Task 26 import com.android.systemui.shared.recents.model.ThumbnailData 27 import com.google.common.truth.Truth.assertThat 28 import kotlinx.coroutines.flow.first 29 import kotlinx.coroutines.test.runTest 30 import org.junit.Test 31 import org.mockito.kotlin.mock 32 import org.mockito.kotlin.whenever 33 34 class RecentsViewModelTest { 35 private val tasksRepository = FakeTasksRepository() 36 private val recentsViewData = RecentsViewData() 37 private val systemUnderTest = RecentsViewModel(tasksRepository, recentsViewData) 38 39 private val tasks = (0..5).map(::createTaskWithId) 40 41 @Test <lambda>null42 fun taskVisibilityControlThumbnailsAvailability() = runTest { 43 val thumbnailData1 = createThumbnailData() 44 val thumbnailData2 = createThumbnailData() 45 tasksRepository.seedTasks(tasks) 46 tasksRepository.seedThumbnailData(mapOf(1 to thumbnailData1, 2 to thumbnailData2)) 47 48 val thumbnailDataFlow1 = tasksRepository.getThumbnailById(1) 49 val thumbnailDataFlow2 = tasksRepository.getThumbnailById(2) 50 51 systemUnderTest.refreshAllTaskData() 52 53 assertThat(thumbnailDataFlow1.first()).isNull() 54 assertThat(thumbnailDataFlow2.first()).isNull() 55 56 systemUnderTest.updateVisibleTasks(listOf(1, 2)) 57 58 assertThat(thumbnailDataFlow1.first()).isEqualTo(thumbnailData1) 59 assertThat(thumbnailDataFlow2.first()).isEqualTo(thumbnailData2) 60 61 systemUnderTest.updateVisibleTasks(listOf(1)) 62 63 assertThat(thumbnailDataFlow1.first()).isEqualTo(thumbnailData1) 64 assertThat(thumbnailDataFlow2.first()).isNull() 65 66 systemUnderTest.onReset() 67 68 assertThat(thumbnailDataFlow1.first()).isNull() 69 assertThat(thumbnailDataFlow2.first()).isNull() 70 } 71 72 @Test <lambda>null73 fun updatesRunningTaskShowScreenshot() = runTest { 74 systemUnderTest.setRunningTaskShowScreenshot(true) 75 systemUnderTest.waitForRunningTaskShowScreenshotToUpdate() 76 } 77 78 @Test <lambda>null79 fun waitForThumbnailsToUpdate() = runTest { 80 // Given taskRepository with visible 2 tasks containing thumbnailData 81 val thumbnailData1 = createThumbnailData().apply { snapshotId = 1 } 82 val thumbnailData2 = createThumbnailData().apply { snapshotId = 2 } 83 tasksRepository.seedTasks(tasks) 84 tasksRepository.seedThumbnailData(mapOf(1 to thumbnailData1, 2 to thumbnailData2)) 85 systemUnderTest.updateVisibleTasks(listOf(1, 2)) 86 87 val thumbnailDataFlow1 = tasksRepository.getThumbnailById(1) 88 val thumbnailDataFlow2 = tasksRepository.getThumbnailById(2) 89 90 // Then getThumbnailById should initially contains correct thumbnailData 91 assertThat(thumbnailDataFlow1.first()).isEqualTo(thumbnailData1) 92 assertThat(thumbnailDataFlow2.first()).isEqualTo(thumbnailData2) 93 94 // When thumbnailData is updated in taskRepository 95 tasksRepository.seedThumbnailData( 96 mapOf(1 to thumbnailData1, 2 to createThumbnailData().apply { snapshotId = 3 }) 97 ) 98 // setVisibleTasks forces FakeTasksRepository to update the flows returned by 99 // getThumbnailById 100 tasksRepository.setVisibleTasks(setOf(1, 2)) 101 102 // Then wait for thumbnailData should complete, and the previous getThumbnailById flow 103 // should return updated values 104 systemUnderTest.waitForThumbnailsToUpdate( 105 mapOf(2 to createThumbnailData().apply { snapshotId = 3 }) 106 ) 107 assertThat(thumbnailDataFlow1.first()).isEqualTo(thumbnailData1) 108 assertThat(thumbnailDataFlow2.first()?.snapshotId).isEqualTo(3) 109 } 110 111 @Test <lambda>null112 fun waitForThumbnailsToUpdate_emptyMap() = runTest { 113 systemUnderTest.waitForThumbnailsToUpdate(emptyMap()) 114 } 115 116 @Test <lambda>null117 fun waitForThumbnailsToUpdate_null() = runTest { 118 systemUnderTest.waitForThumbnailsToUpdate(null) 119 } 120 createTaskWithIdnull121 private fun createTaskWithId(taskId: Int) = 122 Task(Task.TaskKey(taskId, 0, Intent(), ComponentName("", ""), 0, 2000)).apply { 123 colorBackground = Color.argb(taskId, taskId, taskId, taskId) 124 } 125 createThumbnailDatanull126 private fun createThumbnailData(rotation: Int = Surface.ROTATION_0): ThumbnailData { 127 val bitmap = mock<Bitmap>() 128 whenever(bitmap.width).thenReturn(THUMBNAIL_WIDTH) 129 whenever(bitmap.height).thenReturn(THUMBNAIL_HEIGHT) 130 131 return ThumbnailData(thumbnail = bitmap, rotation = rotation) 132 } 133 134 companion object { 135 const val THUMBNAIL_WIDTH = 100 136 const val THUMBNAIL_HEIGHT = 200 137 } 138 } 139