desktop-exploded-view: Add header to individual windows.
The header has an app icon, app title and a close button. Currently clicking on the close button does nothing. Will address it in a following CL. Flag: com.android.launcher3.enable_desktop_exploded_view Test: Manual Bug: 353965691 Change-Id: I5e0303a02d5f8afd16a5f5f0335a8fa489ff98f2
This commit is contained in:
committed by
Xiaoqian Dai
parent
bdcf3de348
commit
89b039da83
+1
-3
@@ -18,9 +18,7 @@ package com.android.quickstep.recents.data
|
||||
|
||||
class FakeRecentsDeviceProfileRepository : RecentsDeviceProfileRepository {
|
||||
private var recentsDeviceProfile =
|
||||
RecentsDeviceProfile(
|
||||
isLargeScreen = false,
|
||||
)
|
||||
RecentsDeviceProfile(isLargeScreen = false, canEnterDesktopMode = false)
|
||||
|
||||
override fun getRecentsDeviceProfile() = recentsDeviceProfile
|
||||
|
||||
|
||||
-44
@@ -1,44 +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.recents.data
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.launcher3.FakeInvariantDeviceProfileTest
|
||||
import com.android.quickstep.views.RecentsViewContainer
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
/** Test for [RecentsDeviceProfileRepositoryImpl] */
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class RecentsDeviceProfileRepositoryImplTest : FakeInvariantDeviceProfileTest() {
|
||||
private val recentsViewContainer = mock<RecentsViewContainer>()
|
||||
|
||||
private val systemUnderTest = RecentsDeviceProfileRepositoryImpl(recentsViewContainer)
|
||||
|
||||
@Test
|
||||
fun deviceProfileMappedCorrectly() {
|
||||
initializeVarsForTablet()
|
||||
val tabletDeviceProfile = newDP()
|
||||
whenever(recentsViewContainer.deviceProfile).thenReturn(tabletDeviceProfile)
|
||||
|
||||
assertThat(systemUnderTest.getRecentsDeviceProfile())
|
||||
.isEqualTo(RecentsDeviceProfile(isLargeScreen = true))
|
||||
}
|
||||
}
|
||||
+107
-9
@@ -16,16 +16,23 @@
|
||||
|
||||
package com.android.quickstep.task.thumbnail
|
||||
|
||||
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
|
||||
import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.graphics.Matrix
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.platform.test.annotations.EnableFlags
|
||||
import android.platform.test.flag.junit.SetFlagsRule
|
||||
import android.view.Surface
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.launcher3.Flags
|
||||
import com.android.launcher3.util.TestDispatcherProvider
|
||||
import com.android.quickstep.recents.data.FakeRecentsDeviceProfileRepository
|
||||
import com.android.quickstep.recents.data.FakeTasksRepository
|
||||
import com.android.quickstep.recents.data.RecentsDeviceProfile
|
||||
import com.android.quickstep.recents.usecase.GetThumbnailPositionUseCase
|
||||
import com.android.quickstep.recents.usecase.ThumbnailPositionState.MatrixScaling
|
||||
import com.android.quickstep.recents.usecase.ThumbnailPositionState.MissingThumbnail
|
||||
@@ -34,6 +41,7 @@ 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.ThumbnailHeader
|
||||
import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
|
||||
import com.android.quickstep.task.viewmodel.TaskContainerData
|
||||
import com.android.quickstep.task.viewmodel.TaskThumbnailViewModelImpl
|
||||
@@ -44,6 +52,7 @@ import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.kotlin.mock
|
||||
@@ -52,6 +61,8 @@ import org.mockito.kotlin.whenever
|
||||
/** Test for [TaskThumbnailView] */
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class TaskThumbnailViewModelImplTest {
|
||||
@get:Rule val setFlagsRule = SetFlagsRule()
|
||||
|
||||
private val dispatcher = StandardTestDispatcher()
|
||||
private val testScope = TestScope(dispatcher)
|
||||
|
||||
@@ -59,6 +70,7 @@ class TaskThumbnailViewModelImplTest {
|
||||
private val taskContainerData = TaskContainerData()
|
||||
private val dispatcherProvider = TestDispatcherProvider(dispatcher)
|
||||
private val tasksRepository = FakeTasksRepository()
|
||||
private val deviceProfileRepository = FakeRecentsDeviceProfileRepository()
|
||||
private val mGetThumbnailPositionUseCase = mock<GetThumbnailPositionUseCase>()
|
||||
private val splashAlphaUseCase: SplashAlphaUseCase = mock()
|
||||
|
||||
@@ -68,12 +80,18 @@ class TaskThumbnailViewModelImplTest {
|
||||
taskContainerData,
|
||||
dispatcherProvider,
|
||||
tasksRepository,
|
||||
deviceProfileRepository,
|
||||
mGetThumbnailPositionUseCase,
|
||||
splashAlphaUseCase,
|
||||
)
|
||||
}
|
||||
|
||||
private val tasks = (0..5).map(::createTaskWithId)
|
||||
private val fullscreenTaskIdRange: IntRange = 0..5
|
||||
private val freeformTaskIdRange: IntRange = 6..10
|
||||
|
||||
private val fullscreenTasks = fullscreenTaskIdRange.map(::createTaskWithId)
|
||||
private val freeformTasks = freeformTaskIdRange.map(::createFreeformTaskWithId)
|
||||
private val tasks = fullscreenTasks + freeformTasks
|
||||
|
||||
@Test
|
||||
fun initialStateIsUninitialized() =
|
||||
@@ -88,7 +106,7 @@ class TaskThumbnailViewModelImplTest {
|
||||
recentsViewData.runningTaskIds.value = setOf(taskId)
|
||||
systemUnderTest.bind(taskId)
|
||||
|
||||
assertThat(systemUnderTest.uiState.first()).isEqualTo(LiveTile)
|
||||
assertThat(systemUnderTest.uiState.first()).isEqualTo(LiveTile.WithoutHeader)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -108,7 +126,7 @@ class TaskThumbnailViewModelImplTest {
|
||||
assertThat(systemUnderTest.uiState.first())
|
||||
.isEqualTo(
|
||||
SnapshotSplash(
|
||||
Snapshot(
|
||||
Snapshot.WithoutHeader(
|
||||
backgroundColor = Color.rgb(1, 1, 1),
|
||||
bitmap = expectedThumbnailData.thumbnail!!,
|
||||
thumbnailRotation = Surface.ROTATION_0,
|
||||
@@ -127,7 +145,7 @@ class TaskThumbnailViewModelImplTest {
|
||||
tasksRepository.setVisibleTasks(setOf(runningTaskId, stoppedTaskId))
|
||||
recentsViewData.runningTaskIds.value = setOf(runningTaskId)
|
||||
systemUnderTest.bind(runningTaskId)
|
||||
assertThat(systemUnderTest.uiState.first()).isEqualTo(LiveTile)
|
||||
assertThat(systemUnderTest.uiState.first()).isEqualTo(LiveTile.WithoutHeader)
|
||||
|
||||
systemUnderTest.bind(stoppedTaskId)
|
||||
assertThat(systemUnderTest.uiState.first())
|
||||
@@ -175,7 +193,7 @@ class TaskThumbnailViewModelImplTest {
|
||||
assertThat(systemUnderTest.uiState.first())
|
||||
.isEqualTo(
|
||||
SnapshotSplash(
|
||||
Snapshot(
|
||||
Snapshot.WithoutHeader(
|
||||
backgroundColor = Color.rgb(2, 2, 2),
|
||||
bitmap = expectedThumbnailData.thumbnail!!,
|
||||
thumbnailRotation = Surface.ROTATION_270,
|
||||
@@ -202,7 +220,7 @@ class TaskThumbnailViewModelImplTest {
|
||||
assertThat(systemUnderTest.uiState.first())
|
||||
.isEqualTo(
|
||||
SnapshotSplash(
|
||||
Snapshot(
|
||||
Snapshot.WithoutHeader(
|
||||
backgroundColor = Color.rgb(2, 2, 2),
|
||||
bitmap = expectedThumbnailData.thumbnail!!,
|
||||
thumbnailRotation = Surface.ROTATION_0,
|
||||
@@ -212,6 +230,57 @@ class TaskThumbnailViewModelImplTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_EXPLODED_VIEW)
|
||||
fun bindRunningTask_inDesktop_thenStateIs_LiveTile_withHeader() =
|
||||
testScope.runTest {
|
||||
deviceProfileRepository.setRecentsDeviceProfile(
|
||||
RecentsDeviceProfile(isLargeScreen = true, canEnterDesktopMode = true)
|
||||
)
|
||||
|
||||
val taskId = freeformTaskIdRange.first
|
||||
val expectedIconData = mock<Drawable>()
|
||||
tasksRepository.seedIconData(taskId, "Task $taskId", "Task $taskId", expectedIconData)
|
||||
tasksRepository.seedTasks(freeformTasks)
|
||||
tasksRepository.setVisibleTasks(setOf(taskId))
|
||||
recentsViewData.runningTaskIds.value = setOf(taskId)
|
||||
systemUnderTest.bind(taskId)
|
||||
|
||||
assertThat(systemUnderTest.uiState.first())
|
||||
.isEqualTo(LiveTile.WithHeader(ThumbnailHeader(expectedIconData, "Task $taskId")))
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_EXPLODED_VIEW)
|
||||
fun bindStoppedTaskWithThumbnail_inDesktop_thenStateIs_SnapshotSplash_withHeader() =
|
||||
testScope.runTest {
|
||||
deviceProfileRepository.setRecentsDeviceProfile(
|
||||
RecentsDeviceProfile(isLargeScreen = true, canEnterDesktopMode = true)
|
||||
)
|
||||
|
||||
val taskId = freeformTaskIdRange.first
|
||||
val expectedThumbnailData = createThumbnailData(rotation = Surface.ROTATION_0)
|
||||
tasksRepository.seedThumbnailData(mapOf(taskId to expectedThumbnailData))
|
||||
val expectedIconData = mock<Drawable>()
|
||||
tasksRepository.seedIconData(taskId, "Task $taskId", "Task $taskId", expectedIconData)
|
||||
tasksRepository.seedTasks(freeformTasks)
|
||||
tasksRepository.setVisibleTasks(setOf(taskId))
|
||||
|
||||
systemUnderTest.bind(taskId)
|
||||
assertThat(systemUnderTest.uiState.first())
|
||||
.isEqualTo(
|
||||
SnapshotSplash(
|
||||
Snapshot.WithHeader(
|
||||
backgroundColor = Color.rgb(taskId, taskId, taskId),
|
||||
bitmap = expectedThumbnailData.thumbnail!!,
|
||||
thumbnailRotation = Surface.ROTATION_0,
|
||||
header = ThumbnailHeader(expectedIconData, "Task $taskId"),
|
||||
),
|
||||
expectedIconData,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getSnapshotMatrix_MissingThumbnail() =
|
||||
testScope.runTest {
|
||||
@@ -269,9 +338,38 @@ class TaskThumbnailViewModelImplTest {
|
||||
}
|
||||
|
||||
private fun createTaskWithId(taskId: Int) =
|
||||
Task(Task.TaskKey(taskId, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
|
||||
colorBackground = Color.argb(taskId, taskId, taskId, taskId)
|
||||
}
|
||||
Task(
|
||||
Task.TaskKey(
|
||||
taskId,
|
||||
WINDOWING_MODE_FULLSCREEN,
|
||||
Intent(),
|
||||
ComponentName("", ""),
|
||||
0,
|
||||
2000,
|
||||
)
|
||||
)
|
||||
.apply {
|
||||
colorBackground = Color.argb(taskId, taskId, taskId, taskId)
|
||||
titleDescription = "Task $taskId"
|
||||
icon = mock<Drawable>()
|
||||
}
|
||||
|
||||
private fun createFreeformTaskWithId(taskId: Int) =
|
||||
Task(
|
||||
Task.TaskKey(
|
||||
taskId,
|
||||
WINDOWING_MODE_FREEFORM,
|
||||
Intent(),
|
||||
ComponentName("", ""),
|
||||
0,
|
||||
2000,
|
||||
)
|
||||
)
|
||||
.apply {
|
||||
colorBackground = Color.argb(taskId, taskId, taskId, taskId)
|
||||
titleDescription = "Task $taskId"
|
||||
icon = mock<Drawable>()
|
||||
}
|
||||
|
||||
private fun createThumbnailData(rotation: Int = Surface.ROTATION_0): ThumbnailData {
|
||||
val bitmap = mock<Bitmap>()
|
||||
|
||||
Reference in New Issue
Block a user