Merge "Controls UI - Motion for activities" into rvc-dev am: 5cbc7dace2

Change-Id: I452a8236489e58d765210881d20309665ae79cdc
This commit is contained in:
TreeHugger Robot
2020-04-21 22:58:49 +00:00
committed by Automerger Merge Worker
8 changed files with 148 additions and 99 deletions

View File

@@ -31,6 +31,7 @@ import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.DelayableExecutor
import dagger.Lazy import dagger.Lazy
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@@ -284,13 +285,19 @@ open class ControlsBindingControllerImpl @Inject constructor(
val requestLimit: Long val requestLimit: Long
) : IControlsSubscriber.Stub() { ) : IControlsSubscriber.Stub() {
val loadedControls = ArrayList<Control>() val loadedControls = ArrayList<Control>()
private var isTerminated = false private var isTerminated = AtomicBoolean(false)
private var _loadCancelInternal: (() -> Unit)? = null private var _loadCancelInternal: (() -> Unit)? = null
private lateinit var subscription: IControlsSubscription private lateinit var subscription: IControlsSubscription
/**
* Potentially cancel a subscriber. The subscriber may also have terminated, in which case
* the request is ignored.
*/
fun loadCancel() = Runnable { fun loadCancel() = Runnable {
Log.d(TAG, "Cancel load requested") _loadCancelInternal?.let {
_loadCancelInternal?.invoke() Log.d(TAG, "Canceling loadSubscribtion")
it.invoke()
}
} }
override fun onSubscribe(token: IBinder, subs: IControlsSubscription) { override fun onSubscribe(token: IBinder, subs: IControlsSubscription) {
@@ -301,7 +308,7 @@ open class ControlsBindingControllerImpl @Inject constructor(
override fun onNext(token: IBinder, c: Control) { override fun onNext(token: IBinder, c: Control) {
backgroundExecutor.execute { backgroundExecutor.execute {
if (isTerminated) return@execute if (isTerminated.get()) return@execute
loadedControls.add(c) loadedControls.add(c)
@@ -325,13 +332,15 @@ open class ControlsBindingControllerImpl @Inject constructor(
} }
private fun maybeTerminateAndRun(postTerminateFn: Runnable) { private fun maybeTerminateAndRun(postTerminateFn: Runnable) {
if (isTerminated) return if (isTerminated.get()) return
isTerminated = true
_loadCancelInternal = {} _loadCancelInternal = {}
currentProvider?.cancelLoadTimeout() currentProvider?.cancelLoadTimeout()
backgroundExecutor.execute(postTerminateFn) backgroundExecutor.execute {
isTerminated.compareAndSet(false, true)
postTerminateFn.run()
}
} }
} }
} }

View File

@@ -52,18 +52,16 @@ interface ControlsController : UserAwareController {
* Load all available [Control] for a given service. * Load all available [Control] for a given service.
* *
* @param componentName the [ComponentName] of the [ControlsProviderService] to load from * @param componentName the [ComponentName] of the [ControlsProviderService] to load from
* @param dataCallback a callback in which to retrieve the result. * @param dataCallback a callback in which to retrieve the result
* @param cancelWrapper a callback to receive a [Runnable] that can be run to cancel the
* request
*/ */
fun loadForComponent( fun loadForComponent(
componentName: ComponentName, componentName: ComponentName,
dataCallback: Consumer<LoadData> dataCallback: Consumer<LoadData>,
cancelWrapper: Consumer<Runnable>
) )
/**
* Cancels a pending load call
*/
fun cancelLoad()
/** /**
* Request to subscribe for favorited controls per structure * Request to subscribe for favorited controls per structure
* *

View File

@@ -77,8 +77,6 @@ class ControlsControllerImpl @Inject constructor (
private var userChanging: Boolean = true private var userChanging: Boolean = true
private var loadCanceller: Runnable? = null
private var seedingInProgress = false private var seedingInProgress = false
private val seedingCallbacks = mutableListOf<Consumer<Boolean>>() private val seedingCallbacks = mutableListOf<Consumer<Boolean>>()
@@ -276,28 +274,29 @@ class ControlsControllerImpl @Inject constructor (
override fun loadForComponent( override fun loadForComponent(
componentName: ComponentName, componentName: ComponentName,
dataCallback: Consumer<ControlsController.LoadData> dataCallback: Consumer<ControlsController.LoadData>,
cancelWrapper: Consumer<Runnable>
) { ) {
if (!confirmAvailability()) { if (!confirmAvailability()) {
if (userChanging) { if (userChanging) {
// Try again later, userChanging should not last forever. If so, we have bigger // Try again later, userChanging should not last forever. If so, we have bigger
// problems. This will return a runnable that allows to cancel the delayed version, // problems. This will return a runnable that allows to cancel the delayed version,
// it will not be able to cancel the load if // it will not be able to cancel the load if
loadCanceller = executor.executeDelayed( executor.executeDelayed(
{ loadForComponent(componentName, dataCallback) }, { loadForComponent(componentName, dataCallback, cancelWrapper) },
USER_CHANGE_RETRY_DELAY, USER_CHANGE_RETRY_DELAY,
TimeUnit.MILLISECONDS TimeUnit.MILLISECONDS
) )
} else { }
dataCallback.accept(createLoadDataObject(emptyList(), emptyList(), true)) dataCallback.accept(createLoadDataObject(emptyList(), emptyList(), true))
} }
return
} cancelWrapper.accept(
loadCanceller = bindingController.bindAndLoad( bindingController.bindAndLoad(
componentName, componentName,
object : ControlsBindingController.LoadCallback { object : ControlsBindingController.LoadCallback {
override fun accept(controls: List<Control>) { override fun accept(controls: List<Control>) {
loadCanceller = null
executor.execute { executor.execute {
val favoritesForComponentKeys = Favorites val favoritesForComponentKeys = Favorites
.getControlsForComponent(componentName).map { it.controlId } .getControlsForComponent(componentName).map { it.controlId }
@@ -333,7 +332,6 @@ class ControlsControllerImpl @Inject constructor (
} }
override fun error(message: String) { override fun error(message: String) {
loadCanceller = null
executor.execute { executor.execute {
val controls = Favorites.getStructuresForComponent(componentName) val controls = Favorites.getStructuresForComponent(componentName)
.flatMap { st -> .flatMap { st ->
@@ -349,6 +347,7 @@ class ControlsControllerImpl @Inject constructor (
} }
} }
) )
)
} }
override fun addSeedingFavoritesCallback(callback: Consumer<Boolean>): Boolean { override fun addSeedingFavoritesCallback(callback: Consumer<Boolean>): Boolean {
@@ -432,12 +431,6 @@ class ControlsControllerImpl @Inject constructor (
seedingCallbacks.clear() seedingCallbacks.clear()
} }
override fun cancelLoad() {
loadCanceller?.let {
executor.execute(it)
}
}
private fun createRemovedStatus( private fun createRemovedStatus(
componentName: ComponentName, componentName: ComponentName,
controlInfo: ControlInfo, controlInfo: ControlInfo,

View File

@@ -32,6 +32,7 @@ import com.android.systemui.R
import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.controls.controller.ControlsControllerImpl import com.android.systemui.controls.controller.ControlsControllerImpl
import com.android.systemui.controls.controller.StructureInfo import com.android.systemui.controls.controller.StructureInfo
import com.android.systemui.globalactions.GlobalActionsComponent
import com.android.systemui.settings.CurrentUserTracker import com.android.systemui.settings.CurrentUserTracker
import com.android.systemui.util.LifecycleActivity import com.android.systemui.util.LifecycleActivity
import javax.inject.Inject import javax.inject.Inject
@@ -41,7 +42,8 @@ import javax.inject.Inject
*/ */
class ControlsEditingActivity @Inject constructor( class ControlsEditingActivity @Inject constructor(
private val controller: ControlsControllerImpl, private val controller: ControlsControllerImpl,
broadcastDispatcher: BroadcastDispatcher broadcastDispatcher: BroadcastDispatcher,
private val globalActionsComponent: GlobalActionsComponent
) : LifecycleActivity() { ) : LifecycleActivity() {
companion object { companion object {
@@ -86,12 +88,20 @@ class ControlsEditingActivity @Inject constructor(
bindViews() bindViews()
bindButtons() bindButtons()
}
override fun onStart() {
super.onStart()
setUpList() setUpList()
currentUserTracker.startTracking() currentUserTracker.startTracking()
} }
override fun onStop() {
super.onStop()
currentUserTracker.stopTracking()
}
private fun bindViews() { private fun bindViews() {
setContentView(R.layout.controls_management) setContentView(R.layout.controls_management)
@@ -129,12 +139,21 @@ class ControlsEditingActivity @Inject constructor(
} }
} }
val rootView = requireViewById<ViewGroup>(R.id.controls_management_root)
saveButton = requireViewById<Button>(R.id.done).apply { saveButton = requireViewById<Button>(R.id.done).apply {
isEnabled = false isEnabled = false
setText(R.string.save) setText(R.string.save)
setOnClickListener { setOnClickListener {
saveFavorites() saveFavorites()
finishAffinity() ControlsAnimations.exitAnimation(
rootView,
object : Runnable {
override fun run() {
finish()
}
}
).start()
globalActionsComponent.handleShowGlobalActionsMenu()
} }
} }
} }

View File

@@ -40,6 +40,7 @@ import com.android.systemui.controls.TooltipManager
import com.android.systemui.controls.controller.ControlsControllerImpl import com.android.systemui.controls.controller.ControlsControllerImpl
import com.android.systemui.controls.controller.StructureInfo import com.android.systemui.controls.controller.StructureInfo
import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.globalactions.GlobalActionsComponent
import com.android.systemui.settings.CurrentUserTracker import com.android.systemui.settings.CurrentUserTracker
import com.android.systemui.util.LifecycleActivity import com.android.systemui.util.LifecycleActivity
import java.text.Collator import java.text.Collator
@@ -51,7 +52,8 @@ class ControlsFavoritingActivity @Inject constructor(
@Main private val executor: Executor, @Main private val executor: Executor,
private val controller: ControlsControllerImpl, private val controller: ControlsControllerImpl,
private val listingController: ControlsListingController, private val listingController: ControlsListingController,
broadcastDispatcher: BroadcastDispatcher broadcastDispatcher: BroadcastDispatcher,
private val globalActionsComponent: GlobalActionsComponent
) : LifecycleActivity() { ) : LifecycleActivity() {
companion object { companion object {
@@ -82,6 +84,8 @@ class ControlsFavoritingActivity @Inject constructor(
private var listOfStructures = emptyList<StructureContainer>() private var listOfStructures = emptyList<StructureContainer>()
private lateinit var comparator: Comparator<StructureContainer> private lateinit var comparator: Comparator<StructureContainer>
private var cancelLoadRunnable: Runnable? = null
private var isPagerLoaded = false
private val currentUserTracker = object : CurrentUserTracker(broadcastDispatcher) { private val currentUserTracker = object : CurrentUserTracker(broadcastDispatcher) {
private val startingUser = controller.currentUserId private val startingUser = controller.currentUserId
@@ -124,14 +128,6 @@ class ControlsFavoritingActivity @Inject constructor(
component = intent.getParcelableExtra<ComponentName>(Intent.EXTRA_COMPONENT_NAME) component = intent.getParcelableExtra<ComponentName>(Intent.EXTRA_COMPONENT_NAME)
bindViews() bindViews()
setUpPager()
loadControls()
listingController.addCallback(listingCallback)
currentUserTracker.startTracking()
} }
private val controlsModelCallback = object : ControlsModel.ControlsModelCallback { private val controlsModelCallback = object : ControlsModel.ControlsModelCallback {
@@ -180,7 +176,7 @@ class ControlsFavoritingActivity @Inject constructor(
ControlsAnimations.enterAnimation(pageIndicator).start() ControlsAnimations.enterAnimation(pageIndicator).start()
ControlsAnimations.enterAnimation(structurePager).start() ControlsAnimations.enterAnimation(structurePager).start()
} }
}) }, Consumer { runnable -> cancelLoadRunnable = runnable })
} }
} }
@@ -299,6 +295,7 @@ class ControlsFavoritingActivity @Inject constructor(
} }
} }
val rootView = requireViewById<ViewGroup>(R.id.controls_management_root)
doneButton = requireViewById<Button>(R.id.done).apply { doneButton = requireViewById<Button>(R.id.done).apply {
isEnabled = false isEnabled = false
setOnClickListener { setOnClickListener {
@@ -309,7 +306,16 @@ class ControlsFavoritingActivity @Inject constructor(
StructureInfo(component!!, it.structureName, favoritesForStorage) StructureInfo(component!!, it.structureName, favoritesForStorage)
) )
} }
finishAffinity()
ControlsAnimations.exitAnimation(
rootView,
object : Runnable {
override fun run() {
finish()
}
}
).start()
globalActionsComponent.handleShowGlobalActionsMenu()
} }
} }
} }
@@ -319,15 +325,39 @@ class ControlsFavoritingActivity @Inject constructor(
mTooltipManager?.hide(false) mTooltipManager?.hide(false)
} }
override fun onStart() {
super.onStart()
listingController.addCallback(listingCallback)
currentUserTracker.startTracking()
}
override fun onResume() {
super.onResume()
// only do once, to make sure that any user changes do not get replaces if resume is called
// more than once
if (!isPagerLoaded) {
setUpPager()
loadControls()
isPagerLoaded = true
}
}
override fun onStop() {
super.onStop()
listingController.removeCallback(listingCallback)
currentUserTracker.stopTracking()
}
override fun onConfigurationChanged(newConfig: Configuration) { override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig) super.onConfigurationChanged(newConfig)
mTooltipManager?.hide(false) mTooltipManager?.hide(false)
} }
override fun onDestroy() { override fun onDestroy() {
currentUserTracker.stopTracking() cancelLoadRunnable?.run()
listingController.removeCallback(listingCallback)
controller.cancelLoad()
super.onDestroy() super.onDestroy()
} }

View File

@@ -84,8 +84,22 @@ class ControlsProviderSelectorActivity @Inject constructor(
} }
recyclerView = requireViewById(R.id.list) recyclerView = requireViewById(R.id.list)
recyclerView.alpha = 0.0f
recyclerView.layoutManager = LinearLayoutManager(applicationContext) recyclerView.layoutManager = LinearLayoutManager(applicationContext)
requireViewById<TextView>(R.id.title).apply {
text = resources.getText(R.string.controls_providers_title)
}
requireViewById<Button>(R.id.done).setOnClickListener {
this@ControlsProviderSelectorActivity.finishAffinity()
}
}
override fun onStart() {
super.onStart()
currentUserTracker.startTracking()
recyclerView.alpha = 0.0f
recyclerView.adapter = AppAdapter( recyclerView.adapter = AppAdapter(
backExecutor, backExecutor,
executor, executor,
@@ -105,16 +119,11 @@ class ControlsProviderSelectorActivity @Inject constructor(
} }
}) })
} }
requireViewById<TextView>(R.id.title).apply {
text = resources.getText(R.string.controls_providers_title)
} }
requireViewById<Button>(R.id.done).setOnClickListener { override fun onStop() {
this@ControlsProviderSelectorActivity.finishAffinity() super.onStop()
} currentUserTracker.stopTracking()
currentUserTracker.startTracking()
} }
/** /**

View File

@@ -2235,7 +2235,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private void dismissForControlsActivity() { private void dismissForControlsActivity() {
dismissWithAnimation(() -> { dismissWithAnimation(() -> {
ViewGroup root = (ViewGroup) mGlobalActionsLayout.getRootView(); ViewGroup root = (ViewGroup) mGlobalActionsLayout.getParent();
ControlsAnimations.exitAnimation(root, this::completeDismiss).start(); ControlsAnimations.exitAnimation(root, this::completeDismiss).start();
}); });
} }

View File

@@ -89,6 +89,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
@Captor @Captor
private lateinit var controlLoadCallbackCaptor: private lateinit var controlLoadCallbackCaptor:
ArgumentCaptor<ControlsBindingController.LoadCallback> ArgumentCaptor<ControlsBindingController.LoadCallback>
@Captor @Captor
private lateinit var broadcastReceiverCaptor: ArgumentCaptor<BroadcastReceiver> private lateinit var broadcastReceiverCaptor: ArgumentCaptor<BroadcastReceiver>
@Captor @Captor
@@ -97,6 +98,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
private lateinit var delayableExecutor: FakeExecutor private lateinit var delayableExecutor: FakeExecutor
private lateinit var controller: ControlsControllerImpl private lateinit var controller: ControlsControllerImpl
private lateinit var canceller: DidRunRunnable
companion object { companion object {
fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture() fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
@@ -146,6 +148,9 @@ class ControlsControllerImplTest : SysuiTestCase() {
} }
} }
canceller = DidRunRunnable()
`when`(bindingController.bindAndLoad(any(), any())).thenReturn(canceller)
controller = ControlsControllerImpl( controller = ControlsControllerImpl(
wrapper, wrapper,
delayableExecutor, delayableExecutor,
@@ -266,7 +271,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
assertTrue(favorites.isEmpty()) assertTrue(favorites.isEmpty())
assertFalse(data.errorOnLoad) assertFalse(data.errorOnLoad)
}) }, Consumer {})
verify(bindingController).bindAndLoad(eq(TEST_COMPONENT), verify(bindingController).bindAndLoad(eq(TEST_COMPONENT),
capture(controlLoadCallbackCaptor)) capture(controlLoadCallbackCaptor))
@@ -301,7 +306,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
assertEquals(1, favorites.size) assertEquals(1, favorites.size)
assertEquals(TEST_CONTROL_ID, favorites[0]) assertEquals(TEST_CONTROL_ID, favorites[0])
assertFalse(data.errorOnLoad) assertFalse(data.errorOnLoad)
}) }, Consumer {})
verify(bindingController).bindAndLoad(eq(TEST_COMPONENT), verify(bindingController).bindAndLoad(eq(TEST_COMPONENT),
capture(controlLoadCallbackCaptor)) capture(controlLoadCallbackCaptor))
@@ -332,7 +337,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
assertEquals(1, favorites.size) assertEquals(1, favorites.size)
assertEquals(TEST_CONTROL_ID, favorites[0]) assertEquals(TEST_CONTROL_ID, favorites[0])
assertFalse(data.errorOnLoad) assertFalse(data.errorOnLoad)
}) }, Consumer {})
verify(bindingController).bindAndLoad(eq(TEST_COMPONENT), verify(bindingController).bindAndLoad(eq(TEST_COMPONENT),
capture(controlLoadCallbackCaptor)) capture(controlLoadCallbackCaptor))
@@ -363,7 +368,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
assertEquals(1, favorites.size) assertEquals(1, favorites.size)
assertEquals(TEST_CONTROL_ID, favorites[0]) assertEquals(TEST_CONTROL_ID, favorites[0])
assertTrue(data.errorOnLoad) assertTrue(data.errorOnLoad)
}) }, Consumer {})
verify(bindingController).bindAndLoad(eq(TEST_COMPONENT), verify(bindingController).bindAndLoad(eq(TEST_COMPONENT),
capture(controlLoadCallbackCaptor)) capture(controlLoadCallbackCaptor))
@@ -377,22 +382,15 @@ class ControlsControllerImplTest : SysuiTestCase() {
@Test @Test
fun testCancelLoad() { fun testCancelLoad() {
val canceller = object : Runnable {
var ran = false
override fun run() {
ran = true
}
}
`when`(bindingController.bindAndLoad(any(), any())).thenReturn(canceller)
var loaded = false var loaded = false
var cancelRunnable: Runnable? = null
controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO) controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
delayableExecutor.runAllReady() delayableExecutor.runAllReady()
controller.loadForComponent(TEST_COMPONENT, Consumer { controller.loadForComponent(TEST_COMPONENT, Consumer {
loaded = true loaded = true
}) }, Consumer { runnable -> cancelRunnable = runnable })
controller.cancelLoad() cancelRunnable?.run()
delayableExecutor.runAllReady() delayableExecutor.runAllReady()
assertFalse(loaded) assertFalse(loaded)
@@ -400,61 +398,47 @@ class ControlsControllerImplTest : SysuiTestCase() {
} }
@Test @Test
fun testCancelLoad_noCancelAfterSuccessfulLoad() { fun testCancelLoad_afterSuccessfulLoad() {
val canceller = object : Runnable {
var ran = false
override fun run() {
ran = true
}
}
`when`(bindingController.bindAndLoad(any(), any())).thenReturn(canceller)
var loaded = false var loaded = false
var cancelRunnable: Runnable? = null
controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO) controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
delayableExecutor.runAllReady() delayableExecutor.runAllReady()
controller.loadForComponent(TEST_COMPONENT, Consumer { controller.loadForComponent(TEST_COMPONENT, Consumer {
loaded = true loaded = true
}) }, Consumer { runnable -> cancelRunnable = runnable })
verify(bindingController).bindAndLoad(eq(TEST_COMPONENT), verify(bindingController).bindAndLoad(eq(TEST_COMPONENT),
capture(controlLoadCallbackCaptor)) capture(controlLoadCallbackCaptor))
controlLoadCallbackCaptor.value.accept(emptyList()) controlLoadCallbackCaptor.value.accept(emptyList())
controller.cancelLoad() cancelRunnable?.run()
delayableExecutor.runAllReady() delayableExecutor.runAllReady()
assertTrue(loaded) assertTrue(loaded)
assertFalse(canceller.ran) assertTrue(canceller.ran)
} }
@Test @Test
fun testCancelLoad_noCancelAfterErrorLoad() { fun testCancelLoad_afterErrorLoad() {
val canceller = object : Runnable {
var ran = false
override fun run() {
ran = true
}
}
`when`(bindingController.bindAndLoad(any(), any())).thenReturn(canceller)
var loaded = false var loaded = false
var cancelRunnable: Runnable? = null
controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO) controller.replaceFavoritesForStructure(TEST_STRUCTURE_INFO)
delayableExecutor.runAllReady() delayableExecutor.runAllReady()
controller.loadForComponent(TEST_COMPONENT, Consumer { controller.loadForComponent(TEST_COMPONENT, Consumer {
loaded = true loaded = true
}) }, Consumer { runnable -> cancelRunnable = runnable })
verify(bindingController).bindAndLoad(eq(TEST_COMPONENT), verify(bindingController).bindAndLoad(eq(TEST_COMPONENT),
capture(controlLoadCallbackCaptor)) capture(controlLoadCallbackCaptor))
controlLoadCallbackCaptor.value.error("") controlLoadCallbackCaptor.value.error("")
controller.cancelLoad() cancelRunnable?.run()
delayableExecutor.runAllReady() delayableExecutor.runAllReady()
assertTrue(loaded) assertTrue(loaded)
assertFalse(canceller.ran) assertTrue(canceller.ran)
} }
@Test @Test
@@ -465,7 +449,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
val newControlInfo = TEST_CONTROL_INFO.copy(controlTitle = TEST_CONTROL_TITLE_2) val newControlInfo = TEST_CONTROL_INFO.copy(controlTitle = TEST_CONTROL_TITLE_2)
val control = statelessBuilderFromInfo(newControlInfo).build() val control = statelessBuilderFromInfo(newControlInfo).build()
controller.loadForComponent(TEST_COMPONENT, Consumer {}) controller.loadForComponent(TEST_COMPONENT, Consumer {}, Consumer {})
verify(bindingController).bindAndLoad(eq(TEST_COMPONENT), verify(bindingController).bindAndLoad(eq(TEST_COMPONENT),
capture(controlLoadCallbackCaptor)) capture(controlLoadCallbackCaptor))
@@ -963,3 +947,10 @@ class ControlsControllerImplTest : SysuiTestCase() {
assertTrue(controller.getFavoritesForStructure(TEST_COMPONENT_2, TEST_STRUCTURE).isEmpty()) assertTrue(controller.getFavoritesForStructure(TEST_COMPONENT_2, TEST_STRUCTURE).isEmpty())
} }
} }
private class DidRunRunnable() : Runnable {
var ran = false
override fun run() {
ran = true
}
}