Merge "Bind panels with lower priority flags" into tm-qpr-dev

This commit is contained in:
Fabian Kozynski
2023-01-12 14:44:58 +00:00
committed by Android (Google) Code Review
10 changed files with 79 additions and 4 deletions

View File

@@ -51,12 +51,21 @@ interface ControlsBindingController : UserAwareController {
fun bindAndLoadSuggested(component: ComponentName, callback: LoadCallback)
/**
* Request to bind to the given service.
* Request to bind to the given service. This should only be used for services using the full
* [ControlsProviderService] API, where SystemUI renders the devices' UI.
*
* @param component The [ComponentName] of the service to bind
*/
fun bindService(component: ComponentName)
/**
* Bind to a service that provides a Device Controls panel (embedded activity). This will allow
* the app to remain "warm", and reduce latency.
*
* @param component The [ComponentName] of the [ControlsProviderService] to bind.
*/
fun bindServiceForPanel(component: ComponentName)
/**
* Send a subscribe message to retrieve status of a set of controls.
*

View File

@@ -170,6 +170,10 @@ open class ControlsBindingControllerImpl @Inject constructor(
retrieveLifecycleManager(component).bindService()
}
override fun bindServiceForPanel(component: ComponentName) {
retrieveLifecycleManager(component).bindServiceForPanel()
}
override fun changeUser(newUser: UserHandle) {
if (newUser == currentUser) return

View File

@@ -188,6 +188,14 @@ interface ControlsController : UserAwareController {
/** See [ControlsUiController.getPreferredSelectedItem]. */
fun getPreferredSelection(): SelectedItem
/**
* Bind to a service that provides a Device Controls panel (embedded activity). This will allow
* the app to remain "warm", and reduce latency.
*
* @param component The [ComponentName] of the [ControlsProviderService] to bind.
*/
fun bindComponentForPanel(componentName: ComponentName)
/**
* Interface for structure to pass data to [ControlsFavoritingActivity].
*/

View File

@@ -477,6 +477,10 @@ class ControlsControllerImpl @Inject constructor (
bindingController.unsubscribe()
}
override fun bindComponentForPanel(componentName: ComponentName) {
bindingController.bindServiceForPanel(componentName)
}
override fun addFavorite(
componentName: ComponentName,
structureName: CharSequence,

View File

@@ -78,6 +78,10 @@ class ControlsProviderLifecycleManager(
private const val DEBUG = true
private val BIND_FLAGS = Context.BIND_AUTO_CREATE or Context.BIND_FOREGROUND_SERVICE or
Context.BIND_NOT_PERCEPTIBLE
// Use BIND_NOT_PERCEPTIBLE so it will be at lower priority from SystemUI.
// However, don't use WAIVE_PRIORITY, as by itself, it will kill the app
// once the Task is finished in the device controls panel.
private val BIND_FLAGS_PANEL = Context.BIND_AUTO_CREATE or Context.BIND_NOT_PERCEPTIBLE
}
private val intent = Intent().apply {
@@ -87,18 +91,19 @@ class ControlsProviderLifecycleManager(
})
}
private fun bindService(bind: Boolean) {
private fun bindService(bind: Boolean, forPanel: Boolean = false) {
executor.execute {
requiresBound = bind
if (bind) {
if (bindTryCount != MAX_BIND_RETRIES) {
if (bindTryCount != MAX_BIND_RETRIES && wrapper == null) {
if (DEBUG) {
Log.d(TAG, "Binding service $intent")
}
bindTryCount++
try {
val flags = if (forPanel) BIND_FLAGS_PANEL else BIND_FLAGS
val bound = context
.bindServiceAsUser(intent, serviceConnection, BIND_FLAGS, user)
.bindServiceAsUser(intent, serviceConnection, flags, user)
if (!bound) {
context.unbindService(serviceConnection)
}
@@ -279,6 +284,10 @@ class ControlsProviderLifecycleManager(
bindService(true)
}
fun bindServiceForPanel() {
bindService(bind = true, forPanel = true)
}
/**
* Request unbind from the service.
*/

View File

@@ -232,6 +232,8 @@ class ControlsUiControllerImpl @Inject constructor (
ControlKey(selected.structure.componentName, it.ci.controlId)
}
controlsController.get().subscribeToFavorites(selected.structure)
} else {
controlsController.get().bindComponentForPanel(selected.componentName)
}
listingCallback = createCallback(::showControlsView)
}

View File

@@ -268,6 +268,14 @@ class ControlsBindingControllerImplTest : SysuiTestCase() {
verify(providers[0]).bindService()
}
@Test
fun testBindServiceForPanel() {
controller.bindServiceForPanel(TEST_COMPONENT_NAME_1)
executor.runAllReady()
verify(providers[0]).bindServiceForPanel()
}
@Test
fun testSubscribe() {
val controlInfo1 = ControlInfo("id_1", "", "", DeviceTypes.TYPE_UNKNOWN)

View File

@@ -919,6 +919,12 @@ class ControlsControllerImplTest : SysuiTestCase() {
.getFile(ControlsFavoritePersistenceWrapper.FILE_NAME, context.user.identifier)
assertThat(userStructure.file).isNotNull()
}
@Test
fun testBindForPanel() {
controller.bindComponentForPanel(TEST_COMPONENT)
verify(bindingController).bindServiceForPanel(TEST_COMPONENT)
}
}
private class DidRunRunnable() : Runnable {

View File

@@ -104,6 +104,22 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
assertTrue(context.isBound(componentName))
}
@Test
fun testBindForPanel() {
manager.bindServiceForPanel()
executor.runAllReady()
assertTrue(context.isBound(componentName))
}
@Test
fun testUnbindPanelIsUnbound() {
manager.bindServiceForPanel()
executor.runAllReady()
manager.unbindService()
executor.runAllReady()
assertFalse(context.isBound(componentName))
}
@Test
fun testNullBinding() {
val mockContext = mock(Context::class.java)

View File

@@ -228,6 +228,15 @@ class ControlsUiControllerImplTest : SysuiTestCase() {
verify(controlsController, never()).refreshStatus(any(), any())
}
@Test
fun testPanelBindsForPanel() {
val panel = SelectedItem.PanelItem("App name", ComponentName("pkg", "cls"))
setUpPanel(panel)
underTest.show(parent, {}, context)
verify(controlsController).bindComponentForPanel(panel.componentName)
}
@Test
fun testPanelCallsTaskViewFactoryCreate() {
mockLayoutInflater()