blob: 02bfc19e07d4f7fa52014d7c2a2fb946c78a5df0 [file] [log] [blame]
/*
* Copyright (C) 2020 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.controls.controller
import android.content.ComponentName
import android.content.Context
import android.os.Binder
import android.os.UserHandle
import android.service.controls.Control
import android.service.controls.DeviceTypes
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock
import dagger.Lazy
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(AndroidTestingRunner::class)
class ControlsBindingControllerImplTest : SysuiTestCase() {
companion object {
fun <T> any(): T = Mockito.any<T>()
private val TEST_COMPONENT_NAME_1 = ComponentName("TEST_PKG", "TEST_CLS_1")
private val TEST_COMPONENT_NAME_2 = ComponentName("TEST_PKG", "TEST_CLS_2")
private val TEST_COMPONENT_NAME_3 = ComponentName("TEST_PKG", "TEST_CLS_3")
}
@Mock
private lateinit var mockControlsController: ControlsController
private val user = UserHandle.of(mContext.userId)
private val otherUser = UserHandle.of(user.identifier + 1)
private val executor = FakeExecutor(FakeSystemClock())
private lateinit var controller: ControlsBindingController
private val providers = TestableControlsBindingControllerImpl.providers
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
controller = TestableControlsBindingControllerImpl(
mContext, executor, Lazy { mockControlsController })
}
@After
fun tearDown() {
executor.advanceClockToLast()
executor.runAllReady()
providers.clear()
}
@Test
fun testStartOnUser() {
assertEquals(user.identifier, controller.currentUserId)
}
@Test
fun testBindAndLoad() {
val callback = object : ControlsBindingController.LoadCallback {
override fun error(message: String) {}
override fun accept(t: List<Control>) {}
}
controller.bindAndLoad(TEST_COMPONENT_NAME_1, callback)
assertEquals(1, providers.size)
val provider = providers.first()
verify(provider).maybeBindAndLoad(any())
}
@Test
fun testBindServices() {
controller.bindServices(listOf(TEST_COMPONENT_NAME_1, TEST_COMPONENT_NAME_2))
executor.runAllReady()
assertEquals(2, providers.size)
assertEquals(setOf(TEST_COMPONENT_NAME_1, TEST_COMPONENT_NAME_2),
providers.map { it.componentName }.toSet())
providers.forEach {
verify(it).bindService()
}
}
@Test
fun testSubscribe() {
val controlInfo1 = ControlInfo(TEST_COMPONENT_NAME_1, "id_1", "", DeviceTypes.TYPE_UNKNOWN)
val controlInfo2 = ControlInfo(TEST_COMPONENT_NAME_2, "id_2", "", DeviceTypes.TYPE_UNKNOWN)
controller.bindServices(listOf(TEST_COMPONENT_NAME_3))
controller.subscribe(listOf(controlInfo1, controlInfo2))
executor.runAllReady()
assertEquals(3, providers.size)
val provider1 = providers.first { it.componentName == TEST_COMPONENT_NAME_1 }
val provider2 = providers.first { it.componentName == TEST_COMPONENT_NAME_2 }
val provider3 = providers.first { it.componentName == TEST_COMPONENT_NAME_3 }
verify(provider1).maybeBindAndSubscribe(listOf(controlInfo1.controlId))
verify(provider2).maybeBindAndSubscribe(listOf(controlInfo2.controlId))
verify(provider3, never()).maybeBindAndSubscribe(any())
verify(provider3).unbindService() // Not needed services will be unbound
}
@Test
fun testUnsubscribe_notRefreshing() {
controller.bindServices(listOf(TEST_COMPONENT_NAME_1, TEST_COMPONENT_NAME_2))
controller.unsubscribe()
executor.runAllReady()
providers.forEach {
verify(it, never()).unsubscribe()
}
}
@Test
fun testUnsubscribe_refreshing() {
val controlInfo1 = ControlInfo(TEST_COMPONENT_NAME_1, "id_1", "", DeviceTypes.TYPE_UNKNOWN)
val controlInfo2 = ControlInfo(TEST_COMPONENT_NAME_2, "id_2", "", DeviceTypes.TYPE_UNKNOWN)
controller.subscribe(listOf(controlInfo1, controlInfo2))
controller.unsubscribe()
executor.runAllReady()
providers.forEach {
verify(it).unsubscribe()
}
}
@Test
fun testCurrentUserId() {
controller.changeUser(otherUser)
assertEquals(otherUser.identifier, controller.currentUserId)
}
@Test
fun testChangeUsers_providersHaveCorrectUser() {
controller.bindServices(listOf(TEST_COMPONENT_NAME_1))
controller.changeUser(otherUser)
controller.bindServices(listOf(TEST_COMPONENT_NAME_2))
val provider1 = providers.first { it.componentName == TEST_COMPONENT_NAME_1 }
assertEquals(user, provider1.user)
val provider2 = providers.first { it.componentName == TEST_COMPONENT_NAME_2 }
assertEquals(otherUser, provider2.user)
}
@Test
fun testChangeUsers_providersUnbound() {
controller.bindServices(listOf(TEST_COMPONENT_NAME_1))
controller.changeUser(otherUser)
val provider1 = providers.first { it.componentName == TEST_COMPONENT_NAME_1 }
verify(provider1).unbindService()
controller.bindServices(listOf(TEST_COMPONENT_NAME_2))
controller.changeUser(user)
reset(provider1)
val provider2 = providers.first { it.componentName == TEST_COMPONENT_NAME_2 }
verify(provider2).unbindService()
verify(provider1, never()).unbindService()
}
}
class TestableControlsBindingControllerImpl(
context: Context,
executor: DelayableExecutor,
lazyController: Lazy<ControlsController>
) : ControlsBindingControllerImpl(context, executor, lazyController) {
companion object {
val providers = mutableSetOf<ControlsProviderLifecycleManager>()
}
// Replaces the real provider with a mock and puts the mock in a visible set.
// The mock has the same componentName and user as the real one would have
override fun createProviderManager(component: ComponentName):
ControlsProviderLifecycleManager {
val realProvider = super.createProviderManager(component)
val provider = mock(ControlsProviderLifecycleManager::class.java)
val token = Binder()
`when`(provider.componentName).thenReturn(realProvider.componentName)
`when`(provider.token).thenReturn(token)
`when`(provider.user).thenReturn(realProvider.user)
providers.add(provider)
return provider
}
}