blob: eceb1ddaaf062b79c41b80aa9a9dc673413204f3 [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.times
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)
providers.clear()
controller = TestableControlsBindingControllerImpl(
mContext, executor, Lazy { mockControlsController })
}
@After
fun tearDown() {
executor.advanceClockToLast()
executor.runAllReady()
}
@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)
verify(providers[0]).maybeBindAndLoad(any())
}
@Test
fun testBindService() {
controller.bindService(TEST_COMPONENT_NAME_1)
executor.runAllReady()
verify(providers[0]).bindService()
}
@Test
fun testSubscribe() {
val controlInfo1 = ControlInfo("id_1", "", DeviceTypes.TYPE_UNKNOWN)
val controlInfo2 = ControlInfo("id_2", "", DeviceTypes.TYPE_UNKNOWN)
val structure =
StructureInfo(TEST_COMPONENT_NAME_1, "Home", listOf(controlInfo1, controlInfo2))
controller.subscribe(structure)
executor.runAllReady()
verify(providers[0]).maybeBindAndSubscribe(
listOf(controlInfo1.controlId, controlInfo2.controlId))
}
@Test
fun testUnsubscribe_notRefreshing() {
controller.bindService(TEST_COMPONENT_NAME_2)
controller.unsubscribe()
executor.runAllReady()
verify(providers[0], never()).unsubscribe()
}
@Test
fun testUnsubscribe_refreshing() {
val controlInfo1 = ControlInfo("id_1", "", DeviceTypes.TYPE_UNKNOWN)
val controlInfo2 = ControlInfo("id_2", "", DeviceTypes.TYPE_UNKNOWN)
val structure =
StructureInfo(TEST_COMPONENT_NAME_1, "Home", listOf(controlInfo1, controlInfo2))
controller.subscribe(structure)
controller.unsubscribe()
executor.runAllReady()
verify(providers[0]).unsubscribe()
}
@Test
fun testCurrentUserId() {
controller.changeUser(otherUser)
assertEquals(otherUser.identifier, controller.currentUserId)
}
@Test
fun testChangeUsers_providersHaveCorrectUser() {
controller.bindService(TEST_COMPONENT_NAME_1)
assertEquals(user, providers[0].user)
controller.changeUser(otherUser)
controller.bindService(TEST_COMPONENT_NAME_2)
assertEquals(otherUser, providers[0].user)
}
@Test
fun testChangeUsers_providersUnbound() {
controller.bindService(TEST_COMPONENT_NAME_1)
controller.changeUser(otherUser)
verify(providers[0]).unbindService()
controller.bindService(TEST_COMPONENT_NAME_2)
controller.changeUser(user)
verify(providers[0]).unbindService()
}
@Test
fun testComponentRemoved_existingIsUnbound() {
controller.bindService(TEST_COMPONENT_NAME_1)
controller.onComponentRemoved(TEST_COMPONENT_NAME_1)
executor.runAllReady()
verify(providers[0], times(1)).unbindService()
}
}
class TestableControlsBindingControllerImpl(
context: Context,
executor: DelayableExecutor,
lazyController: Lazy<ControlsController>
) : ControlsBindingControllerImpl(context, executor, lazyController) {
companion object {
val providers = mutableListOf<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.clear()
providers.add(provider)
return provider
}
}