Merge "PSS Task Switcher: Improve unit tests - Use real repositories" into udc-qpr-dev

This commit is contained in:
Treehugger Robot
2023-07-14 11:38:08 +00:00
committed by Android (Google) Code Review
7 changed files with 211 additions and 183 deletions

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2023 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.systemui.mediaprojection.taskswitcher.data.repository
import android.media.projection.MediaProjectionInfo
import android.media.projection.MediaProjectionManager
import android.os.Binder
import android.os.IBinder
import android.os.UserHandle
import android.view.ContentRecordingSession
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
class FakeMediaProjectionManager {
val mediaProjectionManager = mock<MediaProjectionManager>()
private val callbacks = mutableListOf<MediaProjectionManager.Callback>()
init {
whenever(mediaProjectionManager.addCallback(any(), any())).thenAnswer {
callbacks += it.arguments[0] as MediaProjectionManager.Callback
return@thenAnswer Unit
}
whenever(mediaProjectionManager.removeCallback(any())).thenAnswer {
callbacks -= it.arguments[0] as MediaProjectionManager.Callback
return@thenAnswer Unit
}
}
fun dispatchOnStart(info: MediaProjectionInfo = DEFAULT_INFO) {
callbacks.forEach { it.onStart(info) }
}
fun dispatchOnStop(info: MediaProjectionInfo = DEFAULT_INFO) {
callbacks.forEach { it.onStop(info) }
}
fun dispatchOnSessionSet(
info: MediaProjectionInfo = DEFAULT_INFO,
session: ContentRecordingSession?
) {
callbacks.forEach { it.onRecordingSessionSet(info, session) }
}
companion object {
fun createDisplaySession(): ContentRecordingSession =
ContentRecordingSession.createDisplaySession(/* displayToMirror = */ 123)
fun createSingleTaskSession(token: IBinder = Binder()): ContentRecordingSession =
ContentRecordingSession.createTaskSession(token)
private const val DEFAULT_PACKAGE_NAME = "com.media.projection.test"
private val DEFAULT_USER_HANDLE = UserHandle.getUserHandleForUid(UserHandle.myUserId())
private val DEFAULT_INFO = MediaProjectionInfo(DEFAULT_PACKAGE_NAME, DEFAULT_USER_HANDLE)
}
}

View File

@@ -1,42 +0,0 @@
/*
* Copyright (C) 2023 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.systemui.mediaprojection.taskswitcher.data.repository
import android.app.TaskInfo
import com.android.systemui.mediaprojection.taskswitcher.data.model.MediaProjectionState
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
class FakeMediaProjectionRepository : MediaProjectionRepository {
private val state = MutableStateFlow<MediaProjectionState>(MediaProjectionState.NotProjecting)
fun switchProjectedTask(newTask: TaskInfo) {
state.value = MediaProjectionState.SingleTask(newTask)
}
override val mediaProjectionState: Flow<MediaProjectionState> = state.asStateFlow()
fun projectEntireScreen() {
state.value = MediaProjectionState.EntireScreen
}
fun stopProjecting() {
state.value = MediaProjectionState.NotProjecting
}
}

View File

@@ -1,68 +0,0 @@
/*
* Copyright (C) 2023 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.systemui.mediaprojection.taskswitcher.data.repository
import android.app.ActivityManager.RunningTaskInfo
import android.content.Intent
import android.os.IBinder
import android.window.IWindowContainerToken
import android.window.WindowContainerToken
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
class FakeTasksRepository : TasksRepository {
private val _foregroundTask = MutableStateFlow(DEFAULT_TASK)
override val foregroundTask: Flow<RunningTaskInfo> = _foregroundTask.asStateFlow()
private val runningTasks = mutableListOf(DEFAULT_TASK)
override suspend fun findRunningTaskFromWindowContainerToken(
windowContainerToken: IBinder
): RunningTaskInfo? = runningTasks.firstOrNull { it.token.asBinder() == windowContainerToken }
fun addRunningTask(task: RunningTaskInfo) {
runningTasks.add(task)
}
fun moveTaskToForeground(task: RunningTaskInfo) {
_foregroundTask.value = task
}
companion object {
val DEFAULT_TASK = createTask(taskId = -1)
val LAUNCHER_INTENT: Intent = Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME)
fun createTask(
taskId: Int,
token: WindowContainerToken = createToken(),
baseIntent: Intent = Intent()
) =
RunningTaskInfo().apply {
this.taskId = taskId
this.token = token
this.baseIntent = baseIntent
}
fun createToken(): WindowContainerToken {
val realToken = object : IWindowContainerToken.Stub() {}
return WindowContainerToken(realToken)
}
}
}

View File

@@ -16,27 +16,22 @@
package com.android.systemui.mediaprojection.taskswitcher.data.repository package com.android.systemui.mediaprojection.taskswitcher.data.repository
import android.media.projection.MediaProjectionInfo
import android.media.projection.MediaProjectionManager
import android.os.Binder import android.os.Binder
import android.os.Handler import android.os.Handler
import android.os.UserHandle
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner
import android.view.ContentRecordingSession import android.view.ContentRecordingSession
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.mediaprojection.taskswitcher.data.model.MediaProjectionState import com.android.systemui.mediaprojection.taskswitcher.data.model.MediaProjectionState
import com.android.systemui.util.mockito.any import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeActivityTaskManager.Companion.createTask
import com.android.systemui.util.mockito.mock import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeActivityTaskManager.Companion.createToken
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@@ -45,29 +40,26 @@ import org.junit.runner.RunWith
@SmallTest @SmallTest
class MediaProjectionManagerRepositoryTest : SysuiTestCase() { class MediaProjectionManagerRepositoryTest : SysuiTestCase() {
private val mediaProjectionManager = mock<MediaProjectionManager>()
private val dispatcher = StandardTestDispatcher() private val dispatcher = StandardTestDispatcher()
private val testScope = TestScope(dispatcher) private val testScope = TestScope(dispatcher)
private val tasksRepo = FakeTasksRepository()
private lateinit var callback: MediaProjectionManager.Callback private val fakeMediaProjectionManager = FakeMediaProjectionManager()
private lateinit var repo: MediaProjectionManagerRepository private val fakeActivityTaskManager = FakeActivityTaskManager()
@Before private val tasksRepo =
fun setUp() { ActivityTaskManagerTasksRepository(
whenever(mediaProjectionManager.addCallback(any(), any())).thenAnswer { activityTaskManager = fakeActivityTaskManager.activityTaskManager,
callback = it.arguments[0] as MediaProjectionManager.Callback applicationScope = testScope.backgroundScope,
return@thenAnswer Unit backgroundDispatcher = dispatcher
} )
repo =
private val repo =
MediaProjectionManagerRepository( MediaProjectionManagerRepository(
mediaProjectionManager = mediaProjectionManager, mediaProjectionManager = fakeMediaProjectionManager.mediaProjectionManager,
handler = Handler.getMain(), handler = Handler.getMain(),
applicationScope = testScope.backgroundScope, applicationScope = testScope.backgroundScope,
tasksRepository = tasksRepo tasksRepository = tasksRepo
) )
}
@Test @Test
fun mediaProjectionState_onStart_emitsNotProjecting() = fun mediaProjectionState_onStart_emitsNotProjecting() =
@@ -75,7 +67,7 @@ class MediaProjectionManagerRepositoryTest : SysuiTestCase() {
val state by collectLastValue(repo.mediaProjectionState) val state by collectLastValue(repo.mediaProjectionState)
runCurrent() runCurrent()
callback.onStart(TEST_MEDIA_INFO) fakeMediaProjectionManager.dispatchOnStart()
assertThat(state).isEqualTo(MediaProjectionState.NotProjecting) assertThat(state).isEqualTo(MediaProjectionState.NotProjecting)
} }
@@ -86,7 +78,7 @@ class MediaProjectionManagerRepositoryTest : SysuiTestCase() {
val state by collectLastValue(repo.mediaProjectionState) val state by collectLastValue(repo.mediaProjectionState)
runCurrent() runCurrent()
callback.onStop(TEST_MEDIA_INFO) fakeMediaProjectionManager.dispatchOnStop()
assertThat(state).isEqualTo(MediaProjectionState.NotProjecting) assertThat(state).isEqualTo(MediaProjectionState.NotProjecting)
} }
@@ -97,7 +89,7 @@ class MediaProjectionManagerRepositoryTest : SysuiTestCase() {
val state by collectLastValue(repo.mediaProjectionState) val state by collectLastValue(repo.mediaProjectionState)
runCurrent() runCurrent()
callback.onRecordingSessionSet(TEST_MEDIA_INFO, /* session= */ null) fakeMediaProjectionManager.dispatchOnSessionSet(session = null)
assertThat(state).isEqualTo(MediaProjectionState.NotProjecting) assertThat(state).isEqualTo(MediaProjectionState.NotProjecting)
} }
@@ -108,8 +100,9 @@ class MediaProjectionManagerRepositoryTest : SysuiTestCase() {
val state by collectLastValue(repo.mediaProjectionState) val state by collectLastValue(repo.mediaProjectionState)
runCurrent() runCurrent()
val session = ContentRecordingSession.createDisplaySession(/* displayToMirror= */ 123) fakeMediaProjectionManager.dispatchOnSessionSet(
callback.onRecordingSessionSet(TEST_MEDIA_INFO, session) session = ContentRecordingSession.createDisplaySession(/* displayToMirror= */ 123)
)
assertThat(state).isEqualTo(MediaProjectionState.EntireScreen) assertThat(state).isEqualTo(MediaProjectionState.EntireScreen)
} }
@@ -120,9 +113,10 @@ class MediaProjectionManagerRepositoryTest : SysuiTestCase() {
val state by collectLastValue(repo.mediaProjectionState) val state by collectLastValue(repo.mediaProjectionState)
runCurrent() runCurrent()
val session = fakeMediaProjectionManager.dispatchOnSessionSet(
session =
ContentRecordingSession.createTaskSession(/* taskWindowContainerToken= */ null) ContentRecordingSession.createTaskSession(/* taskWindowContainerToken= */ null)
callback.onRecordingSessionSet(TEST_MEDIA_INFO, session) )
assertThat(state).isEqualTo(MediaProjectionState.EntireScreen) assertThat(state).isEqualTo(MediaProjectionState.EntireScreen)
} }
@@ -134,8 +128,9 @@ class MediaProjectionManagerRepositoryTest : SysuiTestCase() {
runCurrent() runCurrent()
val taskWindowContainerToken = Binder() val taskWindowContainerToken = Binder()
val session = ContentRecordingSession.createTaskSession(taskWindowContainerToken) fakeMediaProjectionManager.dispatchOnSessionSet(
callback.onRecordingSessionSet(TEST_MEDIA_INFO, session) session = ContentRecordingSession.createTaskSession(taskWindowContainerToken)
)
assertThat(state).isEqualTo(MediaProjectionState.EntireScreen) assertThat(state).isEqualTo(MediaProjectionState.EntireScreen)
} }
@@ -143,20 +138,16 @@ class MediaProjectionManagerRepositoryTest : SysuiTestCase() {
@Test @Test
fun mediaProjectionState_sessionSet_taskWithToken_matchingRunningTask_emitsSingleTask() = fun mediaProjectionState_sessionSet_taskWithToken_matchingRunningTask_emitsSingleTask() =
testScope.runTest { testScope.runTest {
val token = FakeTasksRepository.createToken() val token = createToken()
val task = FakeTasksRepository.createTask(taskId = 1, token = token) val task = createTask(taskId = 1, token = token)
tasksRepo.addRunningTask(task) fakeActivityTaskManager.addRunningTasks(task)
val state by collectLastValue(repo.mediaProjectionState) val state by collectLastValue(repo.mediaProjectionState)
runCurrent() runCurrent()
val session = ContentRecordingSession.createTaskSession(token.asBinder()) fakeMediaProjectionManager.dispatchOnSessionSet(
callback.onRecordingSessionSet(TEST_MEDIA_INFO, session) session = ContentRecordingSession.createTaskSession(token.asBinder())
)
assertThat(state).isEqualTo(MediaProjectionState.SingleTask(task)) assertThat(state).isEqualTo(MediaProjectionState.SingleTask(task))
} }
companion object {
val TEST_MEDIA_INFO =
MediaProjectionInfo(/* packageName= */ "com.test.package", UserHandle.CURRENT)
}
} }

View File

@@ -17,6 +17,7 @@
package com.android.systemui.mediaprojection.taskswitcher.domain.interactor package com.android.systemui.mediaprojection.taskswitcher.domain.interactor
import android.content.Intent import android.content.Intent
import android.os.Handler
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
@@ -24,7 +25,9 @@ import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.mediaprojection.taskswitcher.data.repository.ActivityTaskManagerTasksRepository import com.android.systemui.mediaprojection.taskswitcher.data.repository.ActivityTaskManagerTasksRepository
import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeActivityTaskManager import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeActivityTaskManager
import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeActivityTaskManager.Companion.createTask import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeActivityTaskManager.Companion.createTask
import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeMediaProjectionRepository import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeMediaProjectionManager
import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeMediaProjectionManager.Companion.createSingleTaskSession
import com.android.systemui.mediaprojection.taskswitcher.data.repository.MediaProjectionManagerRepository
import com.android.systemui.mediaprojection.taskswitcher.domain.model.TaskSwitchState import com.android.systemui.mediaprojection.taskswitcher.domain.model.TaskSwitchState
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -43,7 +46,8 @@ class TaskSwitchInteractorTest : SysuiTestCase() {
private val testScope = TestScope(dispatcher) private val testScope = TestScope(dispatcher)
private val fakeActivityTaskManager = FakeActivityTaskManager() private val fakeActivityTaskManager = FakeActivityTaskManager()
private val mediaRepo = FakeMediaProjectionRepository() private val fakeMediaProjectionManager = FakeMediaProjectionManager()
private val tasksRepo = private val tasksRepo =
ActivityTaskManagerTasksRepository( ActivityTaskManagerTasksRepository(
activityTaskManager = fakeActivityTaskManager.activityTaskManager, activityTaskManager = fakeActivityTaskManager.activityTaskManager,
@@ -51,15 +55,26 @@ class TaskSwitchInteractorTest : SysuiTestCase() {
backgroundDispatcher = dispatcher backgroundDispatcher = dispatcher
) )
private val mediaRepo =
MediaProjectionManagerRepository(
mediaProjectionManager = fakeMediaProjectionManager.mediaProjectionManager,
handler = Handler.getMain(),
applicationScope = testScope.backgroundScope,
tasksRepository = tasksRepo,
)
private val interactor = TaskSwitchInteractor(mediaRepo, tasksRepo) private val interactor = TaskSwitchInteractor(mediaRepo, tasksRepo)
@Test @Test
fun taskSwitchChanges_notProjecting_foregroundTaskChange_emitsNotProjectingTask() = fun taskSwitchChanges_notProjecting_foregroundTaskChange_emitsNotProjectingTask() =
testScope.runTest { testScope.runTest {
mediaRepo.stopProjecting() val backgroundTask = createTask(taskId = 0)
val foregroundTask = createTask(taskId = 1)
val taskSwitchState by collectLastValue(interactor.taskSwitchChanges) val taskSwitchState by collectLastValue(interactor.taskSwitchChanges)
fakeActivityTaskManager.moveTaskToForeground(createTask(taskId = 1)) fakeActivityTaskManager.addRunningTasks(backgroundTask, foregroundTask)
fakeMediaProjectionManager.dispatchOnStop()
fakeActivityTaskManager.moveTaskToForeground(foregroundTask)
assertThat(taskSwitchState).isEqualTo(TaskSwitchState.NotProjectingTask) assertThat(taskSwitchState).isEqualTo(TaskSwitchState.NotProjectingTask)
} }
@@ -67,10 +82,15 @@ class TaskSwitchInteractorTest : SysuiTestCase() {
@Test @Test
fun taskSwitchChanges_projectingScreen_foregroundTaskChange_emitsNotProjectingTask() = fun taskSwitchChanges_projectingScreen_foregroundTaskChange_emitsNotProjectingTask() =
testScope.runTest { testScope.runTest {
mediaRepo.projectEntireScreen() val backgroundTask = createTask(taskId = 0)
val foregroundTask = createTask(taskId = 1)
val taskSwitchState by collectLastValue(interactor.taskSwitchChanges) val taskSwitchState by collectLastValue(interactor.taskSwitchChanges)
fakeActivityTaskManager.moveTaskToForeground(createTask(taskId = 1)) fakeActivityTaskManager.addRunningTasks(backgroundTask, foregroundTask)
fakeMediaProjectionManager.dispatchOnSessionSet(
session = FakeMediaProjectionManager.createDisplaySession()
)
fakeActivityTaskManager.moveTaskToForeground(foregroundTask)
assertThat(taskSwitchState).isEqualTo(TaskSwitchState.NotProjectingTask) assertThat(taskSwitchState).isEqualTo(TaskSwitchState.NotProjectingTask)
} }
@@ -80,9 +100,12 @@ class TaskSwitchInteractorTest : SysuiTestCase() {
testScope.runTest { testScope.runTest {
val projectedTask = createTask(taskId = 0) val projectedTask = createTask(taskId = 0)
val foregroundTask = createTask(taskId = 1) val foregroundTask = createTask(taskId = 1)
mediaRepo.switchProjectedTask(projectedTask)
val taskSwitchState by collectLastValue(interactor.taskSwitchChanges) val taskSwitchState by collectLastValue(interactor.taskSwitchChanges)
fakeActivityTaskManager.addRunningTasks(projectedTask, foregroundTask)
fakeMediaProjectionManager.dispatchOnSessionSet(
session = createSingleTaskSession(token = projectedTask.token.asBinder())
)
fakeActivityTaskManager.moveTaskToForeground(foregroundTask) fakeActivityTaskManager.moveTaskToForeground(foregroundTask)
assertThat(taskSwitchState) assertThat(taskSwitchState)
@@ -99,9 +122,12 @@ class TaskSwitchInteractorTest : SysuiTestCase() {
testScope.runTest { testScope.runTest {
val projectedTask = createTask(taskId = 0) val projectedTask = createTask(taskId = 0)
val foregroundTask = createTask(taskId = 1, baseIntent = LAUNCHER_INTENT) val foregroundTask = createTask(taskId = 1, baseIntent = LAUNCHER_INTENT)
mediaRepo.switchProjectedTask(projectedTask)
val taskSwitchState by collectLastValue(interactor.taskSwitchChanges) val taskSwitchState by collectLastValue(interactor.taskSwitchChanges)
fakeActivityTaskManager.addRunningTasks(projectedTask, foregroundTask)
fakeMediaProjectionManager.dispatchOnSessionSet(
session = createSingleTaskSession(projectedTask.token.asBinder())
)
fakeActivityTaskManager.moveTaskToForeground(foregroundTask) fakeActivityTaskManager.moveTaskToForeground(foregroundTask)
assertThat(taskSwitchState).isEqualTo(TaskSwitchState.TaskUnchanged) assertThat(taskSwitchState).isEqualTo(TaskSwitchState.TaskUnchanged)
@@ -111,11 +137,13 @@ class TaskSwitchInteractorTest : SysuiTestCase() {
fun taskSwitchChanges_projectingTask_foregroundTaskSame_emitsTaskUnchanged() = fun taskSwitchChanges_projectingTask_foregroundTaskSame_emitsTaskUnchanged() =
testScope.runTest { testScope.runTest {
val projectedTask = createTask(taskId = 0) val projectedTask = createTask(taskId = 0)
val foregroundTask = createTask(taskId = 0)
mediaRepo.switchProjectedTask(projectedTask)
val taskSwitchState by collectLastValue(interactor.taskSwitchChanges) val taskSwitchState by collectLastValue(interactor.taskSwitchChanges)
fakeActivityTaskManager.moveTaskToForeground(foregroundTask) fakeActivityTaskManager.addRunningTasks(projectedTask)
fakeMediaProjectionManager.dispatchOnSessionSet(
session = createSingleTaskSession(projectedTask.token.asBinder())
)
fakeActivityTaskManager.moveTaskToForeground(projectedTask)
assertThat(taskSwitchState).isEqualTo(TaskSwitchState.TaskUnchanged) assertThat(taskSwitchState).isEqualTo(TaskSwitchState.TaskUnchanged)
} }

View File

@@ -18,13 +18,15 @@ package com.android.systemui.mediaprojection.taskswitcher.ui
import android.app.Notification import android.app.Notification
import android.app.NotificationManager import android.app.NotificationManager
import android.os.Handler
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.android.systemui.R import com.android.systemui.R
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.android.systemui.mediaprojection.taskswitcher.data.repository.ActivityTaskManagerTasksRepository import com.android.systemui.mediaprojection.taskswitcher.data.repository.ActivityTaskManagerTasksRepository
import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeActivityTaskManager import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeActivityTaskManager
import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeMediaProjectionRepository import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeMediaProjectionManager
import com.android.systemui.mediaprojection.taskswitcher.data.repository.MediaProjectionManagerRepository
import com.android.systemui.mediaprojection.taskswitcher.domain.interactor.TaskSwitchInteractor import com.android.systemui.mediaprojection.taskswitcher.domain.interactor.TaskSwitchInteractor
import com.android.systemui.mediaprojection.taskswitcher.ui.viewmodel.TaskSwitcherNotificationViewModel import com.android.systemui.mediaprojection.taskswitcher.ui.viewmodel.TaskSwitcherNotificationViewModel
import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.any
@@ -51,14 +53,25 @@ class TaskSwitcherNotificationCoordinatorTest : SysuiTestCase() {
private val dispatcher = UnconfinedTestDispatcher() private val dispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(dispatcher) private val testScope = TestScope(dispatcher)
private val fakeActivityTaskManager = FakeActivityTaskManager() private val fakeActivityTaskManager = FakeActivityTaskManager()
private val mediaRepo = FakeMediaProjectionRepository() private val fakeMediaProjectionManager = FakeMediaProjectionManager()
private val tasksRepo = private val tasksRepo =
ActivityTaskManagerTasksRepository( ActivityTaskManagerTasksRepository(
activityTaskManager = fakeActivityTaskManager.activityTaskManager, activityTaskManager = fakeActivityTaskManager.activityTaskManager,
applicationScope = testScope.backgroundScope, applicationScope = testScope.backgroundScope,
backgroundDispatcher = dispatcher backgroundDispatcher = dispatcher
) )
private val mediaRepo =
MediaProjectionManagerRepository(
mediaProjectionManager = fakeMediaProjectionManager.mediaProjectionManager,
handler = Handler.getMain(),
applicationScope = testScope.backgroundScope,
tasksRepository = tasksRepo,
)
private val interactor = TaskSwitchInteractor(mediaRepo, tasksRepo) private val interactor = TaskSwitchInteractor(mediaRepo, tasksRepo)
private val viewModel = TaskSwitcherNotificationViewModel(interactor) private val viewModel = TaskSwitcherNotificationViewModel(interactor)
@@ -90,7 +103,7 @@ class TaskSwitcherNotificationCoordinatorTest : SysuiTestCase() {
@Test @Test
fun hideNotification() { fun hideNotification() {
testScope.runTest { testScope.runTest {
mediaRepo.stopProjecting() fakeMediaProjectionManager.dispatchOnStop()
verify(notificationManager).cancel(any()) verify(notificationManager).cancel(any())
} }
@@ -99,7 +112,7 @@ class TaskSwitcherNotificationCoordinatorTest : SysuiTestCase() {
@Test @Test
fun notificationIdIsConsistent() { fun notificationIdIsConsistent() {
testScope.runTest { testScope.runTest {
mediaRepo.stopProjecting() fakeMediaProjectionManager.dispatchOnStop()
val idCancel = argumentCaptor<Int>() val idCancel = argumentCaptor<Int>()
verify(notificationManager).cancel(idCancel.capture()) verify(notificationManager).cancel(idCancel.capture())
@@ -114,7 +127,11 @@ class TaskSwitcherNotificationCoordinatorTest : SysuiTestCase() {
private fun switchTask() { private fun switchTask() {
val projectedTask = FakeActivityTaskManager.createTask(taskId = 1) val projectedTask = FakeActivityTaskManager.createTask(taskId = 1)
val foregroundTask = FakeActivityTaskManager.createTask(taskId = 2) val foregroundTask = FakeActivityTaskManager.createTask(taskId = 2)
mediaRepo.switchProjectedTask(projectedTask) fakeActivityTaskManager.addRunningTasks(projectedTask, foregroundTask)
fakeMediaProjectionManager.dispatchOnSessionSet(
session =
FakeMediaProjectionManager.createSingleTaskSession(projectedTask.token.asBinder())
)
fakeActivityTaskManager.moveTaskToForeground(foregroundTask) fakeActivityTaskManager.moveTaskToForeground(foregroundTask)
} }

View File

@@ -17,6 +17,7 @@
package com.android.systemui.mediaprojection.taskswitcher.ui.viewmodel package com.android.systemui.mediaprojection.taskswitcher.ui.viewmodel
import android.content.Intent import android.content.Intent
import android.os.Handler
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
@@ -24,7 +25,10 @@ import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.mediaprojection.taskswitcher.data.repository.ActivityTaskManagerTasksRepository import com.android.systemui.mediaprojection.taskswitcher.data.repository.ActivityTaskManagerTasksRepository
import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeActivityTaskManager import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeActivityTaskManager
import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeActivityTaskManager.Companion.createTask import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeActivityTaskManager.Companion.createTask
import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeMediaProjectionRepository import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeMediaProjectionManager
import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeMediaProjectionManager.Companion.createDisplaySession
import com.android.systemui.mediaprojection.taskswitcher.data.repository.FakeMediaProjectionManager.Companion.createSingleTaskSession
import com.android.systemui.mediaprojection.taskswitcher.data.repository.MediaProjectionManagerRepository
import com.android.systemui.mediaprojection.taskswitcher.domain.interactor.TaskSwitchInteractor import com.android.systemui.mediaprojection.taskswitcher.domain.interactor.TaskSwitchInteractor
import com.android.systemui.mediaprojection.taskswitcher.ui.model.TaskSwitcherNotificationUiState import com.android.systemui.mediaprojection.taskswitcher.ui.model.TaskSwitcherNotificationUiState
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
@@ -44,13 +48,23 @@ class TaskSwitcherNotificationViewModelTest : SysuiTestCase() {
private val testScope = TestScope(dispatcher) private val testScope = TestScope(dispatcher)
private val fakeActivityTaskManager = FakeActivityTaskManager() private val fakeActivityTaskManager = FakeActivityTaskManager()
private val mediaRepo = FakeMediaProjectionRepository() private val fakeMediaProjectionManager = FakeMediaProjectionManager()
private val tasksRepo = private val tasksRepo =
ActivityTaskManagerTasksRepository( ActivityTaskManagerTasksRepository(
activityTaskManager = fakeActivityTaskManager.activityTaskManager, activityTaskManager = fakeActivityTaskManager.activityTaskManager,
applicationScope = testScope.backgroundScope, applicationScope = testScope.backgroundScope,
backgroundDispatcher = dispatcher backgroundDispatcher = dispatcher
) )
private val mediaRepo =
MediaProjectionManagerRepository(
mediaProjectionManager = fakeMediaProjectionManager.mediaProjectionManager,
handler = Handler.getMain(),
applicationScope = testScope.backgroundScope,
tasksRepository = tasksRepo,
)
private val interactor = TaskSwitchInteractor(mediaRepo, tasksRepo) private val interactor = TaskSwitchInteractor(mediaRepo, tasksRepo)
private val viewModel = TaskSwitcherNotificationViewModel(interactor) private val viewModel = TaskSwitcherNotificationViewModel(interactor)
@@ -58,19 +72,23 @@ class TaskSwitcherNotificationViewModelTest : SysuiTestCase() {
@Test @Test
fun uiState_notProjecting_emitsNotShowing() = fun uiState_notProjecting_emitsNotShowing() =
testScope.runTest { testScope.runTest {
mediaRepo.stopProjecting()
val uiState by collectLastValue(viewModel.uiState) val uiState by collectLastValue(viewModel.uiState)
fakeMediaProjectionManager.dispatchOnStop()
assertThat(uiState).isEqualTo(TaskSwitcherNotificationUiState.NotShowing) assertThat(uiState).isEqualTo(TaskSwitcherNotificationUiState.NotShowing)
} }
@Test @Test
fun uiState_notProjecting_foregroundTaskChanged_emitsNotShowing() = fun uiState_notProjecting_foregroundTaskChanged_emitsNotShowing() =
testScope.runTest { testScope.runTest {
mediaRepo.stopProjecting() val backgroundTask = createTask(taskId = 0)
val foregroundTask = createTask(taskId = 1)
val uiState by collectLastValue(viewModel.uiState) val uiState by collectLastValue(viewModel.uiState)
mediaRepo.switchProjectedTask(createTask(taskId = 1)) fakeActivityTaskManager.addRunningTasks(backgroundTask, foregroundTask)
fakeMediaProjectionManager.dispatchOnStop()
fakeActivityTaskManager.moveTaskToForeground(foregroundTask)
assertThat(uiState).isEqualTo(TaskSwitcherNotificationUiState.NotShowing) assertThat(uiState).isEqualTo(TaskSwitcherNotificationUiState.NotShowing)
} }
@@ -78,19 +96,23 @@ class TaskSwitcherNotificationViewModelTest : SysuiTestCase() {
@Test @Test
fun uiState_projectingEntireScreen_emitsNotShowing() = fun uiState_projectingEntireScreen_emitsNotShowing() =
testScope.runTest { testScope.runTest {
mediaRepo.projectEntireScreen()
val uiState by collectLastValue(viewModel.uiState) val uiState by collectLastValue(viewModel.uiState)
fakeMediaProjectionManager.dispatchOnSessionSet(session = createDisplaySession())
assertThat(uiState).isEqualTo(TaskSwitcherNotificationUiState.NotShowing) assertThat(uiState).isEqualTo(TaskSwitcherNotificationUiState.NotShowing)
} }
@Test @Test
fun uiState_projectingEntireScreen_foregroundTaskChanged_emitsNotShowing() = fun uiState_projectingEntireScreen_foregroundTaskChanged_emitsNotShowing() =
testScope.runTest { testScope.runTest {
mediaRepo.projectEntireScreen() val backgroundTask = createTask(taskId = 0)
val foregroundTask = createTask(taskId = 1)
val uiState by collectLastValue(viewModel.uiState) val uiState by collectLastValue(viewModel.uiState)
mediaRepo.switchProjectedTask(createTask(taskId = 1)) fakeActivityTaskManager.addRunningTasks(backgroundTask, foregroundTask)
fakeMediaProjectionManager.dispatchOnSessionSet(session = createDisplaySession())
fakeActivityTaskManager.moveTaskToForeground(foregroundTask)
assertThat(uiState).isEqualTo(TaskSwitcherNotificationUiState.NotShowing) assertThat(uiState).isEqualTo(TaskSwitcherNotificationUiState.NotShowing)
} }
@@ -100,9 +122,12 @@ class TaskSwitcherNotificationViewModelTest : SysuiTestCase() {
testScope.runTest { testScope.runTest {
val projectedTask = createTask(taskId = 1) val projectedTask = createTask(taskId = 1)
val foregroundTask = createTask(taskId = 2) val foregroundTask = createTask(taskId = 2)
mediaRepo.switchProjectedTask(projectedTask)
val uiState by collectLastValue(viewModel.uiState) val uiState by collectLastValue(viewModel.uiState)
fakeActivityTaskManager.addRunningTasks(projectedTask, foregroundTask)
fakeMediaProjectionManager.dispatchOnSessionSet(
session = createSingleTaskSession(projectedTask.token.asBinder())
)
fakeActivityTaskManager.moveTaskToForeground(foregroundTask) fakeActivityTaskManager.moveTaskToForeground(foregroundTask)
assertThat(uiState) assertThat(uiState)
@@ -113,9 +138,12 @@ class TaskSwitcherNotificationViewModelTest : SysuiTestCase() {
fun uiState_projectingTask_foregroundTaskChanged_same_emitsNotShowing() = fun uiState_projectingTask_foregroundTaskChanged_same_emitsNotShowing() =
testScope.runTest { testScope.runTest {
val projectedTask = createTask(taskId = 1) val projectedTask = createTask(taskId = 1)
mediaRepo.switchProjectedTask(projectedTask)
val uiState by collectLastValue(viewModel.uiState) val uiState by collectLastValue(viewModel.uiState)
fakeActivityTaskManager.addRunningTasks(projectedTask)
fakeMediaProjectionManager.dispatchOnSessionSet(
session = createSingleTaskSession(projectedTask.token.asBinder())
)
fakeActivityTaskManager.moveTaskToForeground(projectedTask) fakeActivityTaskManager.moveTaskToForeground(projectedTask)
assertThat(uiState).isEqualTo(TaskSwitcherNotificationUiState.NotShowing) assertThat(uiState).isEqualTo(TaskSwitcherNotificationUiState.NotShowing)
@@ -126,9 +154,12 @@ class TaskSwitcherNotificationViewModelTest : SysuiTestCase() {
testScope.runTest { testScope.runTest {
val projectedTask = createTask(taskId = 1) val projectedTask = createTask(taskId = 1)
val foregroundTask = createTask(taskId = 2, baseIntent = LAUNCHER_INTENT) val foregroundTask = createTask(taskId = 2, baseIntent = LAUNCHER_INTENT)
mediaRepo.switchProjectedTask(projectedTask)
val uiState by collectLastValue(viewModel.uiState) val uiState by collectLastValue(viewModel.uiState)
fakeActivityTaskManager.addRunningTasks(projectedTask, foregroundTask)
fakeMediaProjectionManager.dispatchOnSessionSet(
session = createSingleTaskSession(projectedTask.token.asBinder())
)
fakeActivityTaskManager.moveTaskToForeground(foregroundTask) fakeActivityTaskManager.moveTaskToForeground(foregroundTask)
assertThat(uiState).isEqualTo(TaskSwitcherNotificationUiState.NotShowing) assertThat(uiState).isEqualTo(TaskSwitcherNotificationUiState.NotShowing)