From 82587b1a426f84544568303d67f859f2aaad6037 Mon Sep 17 00:00:00 2001 From: Fabian Kozynski Date: Thu, 10 Nov 2022 15:48:00 -0500 Subject: [PATCH] Distinguish between selected panel or structure To pave the way, we add a SelectedItem that could contain a StructureInfo or information for a Panel. In particular, a Panel points to the ComponentName of the ControlsProviderService (and not of the activity) for backwards compatibility and migration. As we still need to match the SelectionInfo that has the activity information, this is not an issue. Also, add persistence for the panel using the same keys (and an extra boolean) for better migration. Test: atest com.android.systemui.controls Test: atest DeviceControlsTile Fixes: 258442632 Change-Id: I544f5cdcb4fdfe0488df05d686173ed3bb709b8e --- .../controls/controller/ControlsController.kt | 5 +- .../controller/ControlsControllerImpl.kt | 5 +- .../controls/controller/StructureInfo.kt | 7 +- .../controls/ui/ControlsUiController.kt | 40 +++++- .../controls/ui/ControlsUiControllerImpl.kt | 135 +++++++++++------- .../systemui/qs/tiles/DeviceControlsTile.kt | 10 +- .../ui/ControlsUiControllerImplTest.kt | 47 ++++-- .../systemui/controls/ui/SelectionItemTest.kt | 112 +++++++++++++++ .../qs/tiles/DeviceControlsTileTest.kt | 51 ++++--- 9 files changed, 321 insertions(+), 91 deletions(-) create mode 100644 packages/SystemUI/tests/src/com/android/systemui/controls/ui/SelectionItemTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt index 31fadb13db08e..2f49c3fe863e1 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt @@ -24,6 +24,7 @@ import com.android.systemui.controls.ControlStatus import com.android.systemui.util.UserAwareController import com.android.systemui.controls.management.ControlsFavoritingActivity import com.android.systemui.controls.ui.ControlsUiController +import com.android.systemui.controls.ui.SelectedItem import java.util.function.Consumer /** @@ -184,8 +185,8 @@ interface ControlsController : UserAwareController { */ fun countFavoritesForComponent(componentName: ComponentName): Int - /** See [ControlsUiController.getPreferredStructure]. */ - fun getPreferredStructure(): StructureInfo + /** See [ControlsUiController.getPreferredSelectedItem]. */ + fun getPreferredSelection(): SelectedItem /** * Interface for structure to pass data to [ControlsFavoritingActivity]. diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt index 50ce9d4ec0f4d..bdfe1fbeb4b55 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt @@ -38,6 +38,7 @@ import com.android.systemui.controls.ControlStatus import com.android.systemui.controls.ControlsServiceInfo import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.ui.ControlsUiController +import com.android.systemui.controls.ui.SelectedItem import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dump.DumpManager @@ -556,8 +557,8 @@ class ControlsControllerImpl @Inject constructor ( ) } - override fun getPreferredStructure(): StructureInfo { - return uiController.getPreferredStructure(getFavorites()) + override fun getPreferredSelection(): SelectedItem { + return uiController.getPreferredSelectedItem(getFavorites()) } override fun dump(pw: PrintWriter, args: Array) { diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/StructureInfo.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/StructureInfo.kt index 34bfa135f0c85..c8090bfb60e89 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/StructureInfo.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/StructureInfo.kt @@ -31,4 +31,9 @@ data class StructureInfo( val componentName: ComponentName, val structure: CharSequence, val controls: List -) +) { + companion object { + val EMPTY_COMPONENT = ComponentName("", "") + val EMPTY_STRUCTURE = StructureInfo(EMPTY_COMPONENT, "", mutableListOf()) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt index c1cfbcb0c2115..180e09e5aaf02 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt @@ -53,9 +53,43 @@ interface ControlsUiController { ) /** - * Returns the structure that is currently preferred by the user. + * Returns the element that is currently preferred by the user. * - * This structure will be the one that appears when the user first opens the controls activity. + * This element will be the one that appears when the user first opens the controls activity. */ - fun getPreferredStructure(structures: List): StructureInfo + fun getPreferredSelectedItem(structures: List): SelectedItem } + +sealed class SelectedItem { + + abstract val name: CharSequence + abstract val hasControls: Boolean + abstract val componentName: ComponentName + + /** + * Represents the currently selected item for a structure. + */ + data class StructureItem(val structure: StructureInfo) : SelectedItem() { + override val name: CharSequence = structure.structure + override val hasControls: Boolean = structure.controls.isNotEmpty() + override val componentName: ComponentName = structure.componentName + } + + /** + * Represents the currently selected item for a service that provides a panel activity. + * + * The [componentName] is that of the service, as that is the expected identifier that should + * not change (to always provide proper migration). + */ + data class PanelItem( + val appName: CharSequence, + override val componentName: + ComponentName + ) : SelectedItem() { + override val name: CharSequence = appName + override val hasControls: Boolean = true + } + companion object { + val EMPTY_SELECTION: SelectedItem = StructureItem(StructureInfo.EMPTY_STRUCTURE) + } +} \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt index 6cb0e8b048693..905636f563d13 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt @@ -41,13 +41,14 @@ import android.widget.LinearLayout import android.widget.ListPopupWindow import android.widget.Space import android.widget.TextView +import androidx.annotation.VisibleForTesting import com.android.systemui.R import com.android.systemui.controls.ControlsMetricsLogger import com.android.systemui.controls.ControlsServiceInfo import com.android.systemui.controls.CustomIconCache -import com.android.systemui.controls.controller.ControlInfo import com.android.systemui.controls.controller.ControlsController import com.android.systemui.controls.controller.StructureInfo +import com.android.systemui.controls.controller.StructureInfo.Companion.EMPTY_COMPONENT import com.android.systemui.controls.management.ControlAdapter import com.android.systemui.controls.management.ControlsEditingActivity import com.android.systemui.controls.management.ControlsFavoritingActivity @@ -90,24 +91,17 @@ class ControlsUiControllerImpl @Inject constructor ( companion object { private const val PREF_COMPONENT = "controls_component" - private const val PREF_STRUCTURE = "controls_structure" + private const val PREF_STRUCTURE_OR_APP_NAME = "controls_structure" + private const val PREF_IS_PANEL = "controls_is_panel" private const val FADE_IN_MILLIS = 200L - - private val EMPTY_COMPONENT = ComponentName("", "") - private val EMPTY_STRUCTURE = StructureInfo( - EMPTY_COMPONENT, - "", - mutableListOf() - ) } - private var selectedStructure: StructureInfo = EMPTY_STRUCTURE + private var selectedItem: SelectedItem = SelectedItem.EMPTY_SELECTION private lateinit var allStructures: List private val controlsById = mutableMapOf() private val controlViewsById = mutableMapOf() private lateinit var parent: ViewGroup - private lateinit var lastItems: List private var popup: ListPopupWindow? = null private var hidden = true private lateinit var onDismiss: Runnable @@ -128,10 +122,12 @@ class ControlsUiControllerImpl @Inject constructor ( private val onSeedingComplete = Consumer { accepted -> if (accepted) { - selectedStructure = controlsController.get().getFavorites().maxByOrNull { + selectedItem = controlsController.get().getFavorites().maxByOrNull { it.controls.size - } ?: EMPTY_STRUCTURE - updatePreferences(selectedStructure) + }?.let { + SelectedItem.StructureItem(it) + } ?: SelectedItem.EMPTY_SELECTION + updatePreferences(selectedItem) } reload(parent) } @@ -146,7 +142,15 @@ class ControlsUiControllerImpl @Inject constructor ( override fun onServicesUpdated(serviceInfos: List) { val lastItems = serviceInfos.map { val uid = it.serviceInfo.applicationInfo.uid - SelectionItem(it.loadLabel(), "", it.loadIcon(), it.componentName, uid) + + SelectionItem( + it.loadLabel(), + "", + it.loadIcon(), + it.componentName, + uid, + it.panelActivity + ) } uiExecutor.execute { parent.removeAllViews() @@ -160,11 +164,11 @@ class ControlsUiControllerImpl @Inject constructor ( override fun resolveActivity(): Class<*> { val allStructures = controlsController.get().getFavorites() - val selectedStructure = getPreferredStructure(allStructures) + val selected = getPreferredSelectedItem(allStructures) return if (controlsController.get().addSeedingFavoritesCallback(onSeedingComplete)) { ControlsActivity::class.java - } else if (selectedStructure.controls.isEmpty() && allStructures.size <= 1) { + } else if (!selected.hasControls && allStructures.size <= 1) { ControlsProviderSelectorActivity::class.java } else { ControlsActivity::class.java @@ -186,21 +190,24 @@ class ControlsUiControllerImpl @Inject constructor ( controlActionCoordinator.activityContext = activityContext allStructures = controlsController.get().getFavorites() - selectedStructure = getPreferredStructure(allStructures) + selectedItem = getPreferredSelectedItem(allStructures) if (controlsController.get().addSeedingFavoritesCallback(onSeedingComplete)) { listingCallback = createCallback(::showSeedingView) - } else if (selectedStructure.controls.isEmpty() && allStructures.size <= 1) { + } else if (!selectedItem.hasControls && allStructures.size <= 1) { // only show initial view if there are really no favorites across any structure listingCallback = createCallback(::showInitialSetupView) } else { - selectedStructure.controls.map { - ControlWithState(selectedStructure.componentName, it, null) - }.associateByTo(controlsById) { - ControlKey(selectedStructure.componentName, it.ci.controlId) + val selected = selectedItem + if (selected is SelectedItem.StructureItem) { + selected.structure.controls.map { + ControlWithState(selected.structure.componentName, it, null) + }.associateByTo(controlsById) { + ControlKey(selected.structure.componentName, it.ci.controlId) + } + controlsController.get().subscribeToFavorites(selected.structure) } listingCallback = createCallback(::showControlsView) - controlsController.get().subscribeToFavorites(selectedStructure) } controlsListingController.get().addCallback(listingCallback) @@ -297,7 +304,7 @@ class ControlsUiControllerImpl @Inject constructor ( } itemsWithStructure.sortWith(localeComparator) - val selectionItem = findSelectionItem(selectedStructure, itemsWithStructure) ?: items[0] + val selectionItem = findSelectionItem(selectedItem, itemsWithStructure) ?: items[0] controlsMetricsLogger.refreshBegin(selectionItem.uid, !keyguardStateController.isUnlocked()) @@ -307,6 +314,8 @@ class ControlsUiControllerImpl @Inject constructor ( } private fun createMenu() { + if (selectedItem !is SelectedItem.StructureItem) return + val selectedStructure = (selectedItem as SelectedItem.StructureItem).structure val items = arrayOf( context.resources.getString(R.string.controls_menu_add), context.resources.getString(R.string.controls_menu_edit) @@ -399,6 +408,8 @@ class ControlsUiControllerImpl @Inject constructor ( } private fun createListView(selected: SelectionItem) { + if (selectedItem !is SelectedItem.StructureItem) return + val selectedStructure = (selectedItem as SelectedItem.StructureItem).structure val inflater = LayoutInflater.from(context) inflater.inflate(R.layout.controls_with_favorites, parent, true) @@ -453,35 +464,44 @@ class ControlsUiControllerImpl @Inject constructor ( } } - override fun getPreferredStructure(structures: List): StructureInfo { - if (structures.isEmpty()) return EMPTY_STRUCTURE + override fun getPreferredSelectedItem(structures: List): SelectedItem { + val sp = sharedPreferences - val component = sharedPreferences.getString(PREF_COMPONENT, null)?.let { + val component = sp.getString(PREF_COMPONENT, null)?.let { ComponentName.unflattenFromString(it) } ?: EMPTY_COMPONENT - val structure = sharedPreferences.getString(PREF_STRUCTURE, "") - - return structures.firstOrNull { - component == it.componentName && structure == it.structure - } ?: structures.get(0) + val name = sp.getString(PREF_STRUCTURE_OR_APP_NAME, "")!! + val isPanel = sp.getBoolean(PREF_IS_PANEL, false) + return if (isPanel) { + SelectedItem.PanelItem(name, component) + } else { + if (structures.isEmpty()) return SelectedItem.EMPTY_SELECTION + SelectedItem.StructureItem(structures.firstOrNull { + component == it.componentName && name == it.structure + } ?: structures.get(0)) + } } - private fun updatePreferences(si: StructureInfo) { - if (si == EMPTY_STRUCTURE) return + private fun updatePreferences(si: SelectedItem) { sharedPreferences.edit() - .putString(PREF_COMPONENT, si.componentName.flattenToString()) - .putString(PREF_STRUCTURE, si.structure.toString()) - .commit() + .putString(PREF_COMPONENT, si.componentName.flattenToString()) + .putString(PREF_STRUCTURE_OR_APP_NAME, si.name.toString()) + .putBoolean(PREF_IS_PANEL, si is SelectedItem.PanelItem) + .commit() } private fun switchAppOrStructure(item: SelectionItem) { - val newSelection = allStructures.first { - it.structure == item.structure && it.componentName == item.componentName + val newSelection = if (item.isPanel) { + SelectedItem.PanelItem(item.appName, item.componentName) + } else { + SelectedItem.StructureItem(allStructures.first { + it.structure == item.structure && it.componentName == item.componentName + }) } - if (newSelection != selectedStructure) { - selectedStructure = newSelection - updatePreferences(selectedStructure) + if (newSelection != selectedItem) { + selectedItem = newSelection + updatePreferences(selectedItem) reload(parent) } } @@ -545,20 +565,37 @@ class ControlsUiControllerImpl @Inject constructor ( return row } - private fun findSelectionItem(si: StructureInfo, items: List): SelectionItem? = - items.firstOrNull { - it.componentName == si.componentName && it.structure == si.structure - } + private fun findSelectionItem(si: SelectedItem, items: List): SelectionItem? = + items.firstOrNull { it.matches(si) } } -private data class SelectionItem( +@VisibleForTesting +internal data class SelectionItem( val appName: CharSequence, val structure: CharSequence, val icon: Drawable, val componentName: ComponentName, - val uid: Int + val uid: Int, + val panelComponentName: ComponentName? ) { fun getTitle() = if (structure.isEmpty()) { appName } else { structure } + + val isPanel: Boolean = panelComponentName != null + + fun matches(selectedItem: SelectedItem): Boolean { + if (componentName != selectedItem.componentName) { + // Not the same component so they are not the same. + return false + } + if (isPanel || selectedItem is SelectedItem.PanelItem) { + // As they have the same component, if [this.isPanel] then we may be migrating from + // device controls API into panel. Want this to match, even if the selectedItem is not + // a panel. We don't want to match on app name because that can change with locale. + return true + } + // Return true if we find a structure with the correct name + return structure == (selectedItem as SelectedItem.StructureItem).structure.structure + } } private class ItemAdapter( diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt index c65bd9b4348e1..41d854969e20f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt @@ -32,6 +32,7 @@ import com.android.systemui.controls.dagger.ControlsComponent import com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.ui.ControlsUiController +import com.android.systemui.controls.ui.SelectedItem import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.ActivityStarter @@ -125,14 +126,15 @@ class DeviceControlsTile @Inject constructor( state.icon = icon if (controlsComponent.isEnabled() && hasControlsApps.get()) { if (controlsComponent.getVisibility() == AVAILABLE) { - val structureInfo = controlsComponent - .getControlsController().get().getPreferredStructure() - state.state = if (structureInfo.controls.isEmpty()) { + val selection = controlsComponent + .getControlsController().get().getPreferredSelection() + state.state = if (selection is SelectedItem.StructureItem && + selection.structure.controls.isEmpty()) { Tile.STATE_INACTIVE } else { Tile.STATE_ACTIVE } - val label = structureInfo.structure + val label = selection.name state.secondaryLabel = if (label == tileLabel) null else label } else { state.state = Tile.STATE_INACTIVE diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt index 49c7442b9708a..a86cb00b3a818 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt @@ -44,7 +44,6 @@ import org.mockito.Mock import org.mockito.Mockito.anyInt import org.mockito.Mockito.anyString import org.mockito.Mockito.mock -import org.mockito.Mockito.times import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @@ -105,8 +104,8 @@ class ControlsUiControllerImplTest : SysuiTestCase() { @Test fun testGetPreferredStructure() { val structureInfo = mock(StructureInfo::class.java) - underTest.getPreferredStructure(listOf(structureInfo)) - verify(userFileManager, times(2)) + underTest.getPreferredSelectedItem(listOf(structureInfo)) + verify(userFileManager) .getSharedPreferences( fileName = DeviceControlsControllerImpl.PREFS_CONTROLS_FILE, mode = 0, @@ -116,25 +115,30 @@ class ControlsUiControllerImplTest : SysuiTestCase() { @Test fun testGetPreferredStructure_differentUserId() { - val structureInfo = + val selectedItems = listOf( - StructureInfo(ComponentName.unflattenFromString("pkg/.cls1"), "a", ArrayList()), - StructureInfo(ComponentName.unflattenFromString("pkg/.cls2"), "b", ArrayList()), + SelectedItem.StructureItem( + StructureInfo(ComponentName.unflattenFromString("pkg/.cls1"), "a", ArrayList()) + ), + SelectedItem.StructureItem( + StructureInfo(ComponentName.unflattenFromString("pkg/.cls2"), "b", ArrayList()) + ), ) + val structures = selectedItems.map { it.structure } sharedPreferences .edit() - .putString("controls_component", structureInfo[0].componentName.flattenToString()) - .putString("controls_structure", structureInfo[0].structure.toString()) + .putString("controls_component", selectedItems[0].componentName.flattenToString()) + .putString("controls_structure", selectedItems[0].name.toString()) .commit() val differentSharedPreferences = FakeSharedPreferences() differentSharedPreferences .edit() - .putString("controls_component", structureInfo[1].componentName.flattenToString()) - .putString("controls_structure", structureInfo[1].structure.toString()) + .putString("controls_component", selectedItems[1].componentName.flattenToString()) + .putString("controls_structure", selectedItems[1].name.toString()) .commit() - val previousPreferredStructure = underTest.getPreferredStructure(structureInfo) + val previousPreferredStructure = underTest.getPreferredSelectedItem(structures) `when`( userFileManager.getSharedPreferences( @@ -146,10 +150,25 @@ class ControlsUiControllerImplTest : SysuiTestCase() { .thenReturn(differentSharedPreferences) `when`(userTracker.userId).thenReturn(1) - val currentPreferredStructure = underTest.getPreferredStructure(structureInfo) + val currentPreferredStructure = underTest.getPreferredSelectedItem(structures) - assertThat(previousPreferredStructure).isEqualTo(structureInfo[0]) - assertThat(currentPreferredStructure).isEqualTo(structureInfo[1]) + assertThat(previousPreferredStructure).isEqualTo(selectedItems[0]) + assertThat(currentPreferredStructure).isEqualTo(selectedItems[1]) assertThat(currentPreferredStructure).isNotEqualTo(previousPreferredStructure) } + + @Test + fun testGetPreferredPanel() { + val panel = SelectedItem.PanelItem("App name", ComponentName("pkg", "cls")) + sharedPreferences + .edit() + .putString("controls_component", panel.componentName.flattenToString()) + .putString("controls_structure", panel.appName.toString()) + .putBoolean("controls_is_panel", true) + .commit() + + val selected = underTest.getPreferredSelectedItem(emptyList()) + + assertThat(selected).isEqualTo(panel) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/SelectionItemTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/SelectionItemTest.kt new file mode 100644 index 0000000000000..57176f0eabe0f --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/SelectionItemTest.kt @@ -0,0 +1,112 @@ +package com.android.systemui.controls.ui + +import android.content.ComponentName +import android.testing.AndroidTestingRunner +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.controls.controller.StructureInfo +import com.android.systemui.util.mockito.mock +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidTestingRunner::class) +class SelectionItemTest : SysuiTestCase() { + + @Test + fun testMatchBadComponentName_false() { + val selectionItem = + SelectionItem( + appName = "app", + structure = "structure", + icon = mock(), + componentName = ComponentName("pkg", "cls"), + uid = 0, + panelComponentName = null + ) + + assertThat( + selectionItem.matches( + SelectedItem.StructureItem( + StructureInfo(ComponentName("", ""), "s", emptyList()) + ) + ) + ) + .isFalse() + assertThat(selectionItem.matches(SelectedItem.PanelItem("name", ComponentName("", "")))) + .isFalse() + } + + @Test + fun testMatchSameComponentName_panelSelected_true() { + val componentName = ComponentName("pkg", "cls") + + val selectionItem = + SelectionItem( + appName = "app", + structure = "structure", + icon = mock(), + componentName = componentName, + uid = 0, + panelComponentName = null + ) + assertThat(selectionItem.matches(SelectedItem.PanelItem("name", componentName))).isTrue() + } + + @Test + fun testMatchSameComponentName_panelSelection_true() { + val componentName = ComponentName("pkg", "cls") + + val selectionItem = + SelectionItem( + appName = "app", + structure = "structure", + icon = mock(), + componentName = componentName, + uid = 0, + panelComponentName = ComponentName("pkg", "panel") + ) + assertThat(selectionItem.matches(SelectedItem.PanelItem("name", componentName))).isTrue() + } + + @Test + fun testMatchSameComponentSameStructure_true() { + val componentName = ComponentName("pkg", "cls") + val structureName = "structure" + + val structureItem = + SelectedItem.StructureItem(StructureInfo(componentName, structureName, emptyList())) + + val selectionItem = + SelectionItem( + appName = "app", + structure = structureName, + icon = mock(), + componentName = componentName, + uid = 0, + panelComponentName = null + ) + assertThat(selectionItem.matches(structureItem)).isTrue() + } + + @Test + fun testMatchSameComponentDifferentStructure_false() { + val componentName = ComponentName("pkg", "cls") + val structureName = "structure" + + val structureItem = + SelectedItem.StructureItem(StructureInfo(componentName, structureName, emptyList())) + + val selectionItem = + SelectionItem( + appName = "app", + structure = "other", + icon = mock(), + componentName = componentName, + uid = 0, + panelComponentName = null + ) + assertThat(selectionItem.matches(structureItem)).isFalse() + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt index f7b9438e6535e..e0b3125fd62a8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt @@ -40,6 +40,7 @@ import com.android.systemui.controls.dagger.ControlsComponent import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.ui.ControlsActivity import com.android.systemui.controls.ui.ControlsUiController +import com.android.systemui.controls.ui.SelectedItem import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost @@ -118,8 +119,9 @@ class DeviceControlsTileTest : SysuiTestCase() { `when`(qsHost.context).thenReturn(spiedContext) `when`(qsHost.uiEventLogger).thenReturn(uiEventLogger) `when`(controlsComponent.isEnabled()).thenReturn(true) - `when`(controlsController.getPreferredStructure()) - .thenReturn(StructureInfo(ComponentName("pkg", "cls"), "structure", listOf())) + `when`(controlsController.getPreferredSelection()) + .thenReturn(SelectedItem.StructureItem( + StructureInfo(ComponentName("pkg", "cls"), "structure", listOf()))) secureSettings.putInt(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS, 1) setupControlsComponent() @@ -226,12 +228,12 @@ class DeviceControlsTileTest : SysuiTestCase() { capture(listingCallbackCaptor) ) `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) - `when`(controlsController.getPreferredStructure()).thenReturn( - StructureInfo( + `when`(controlsController.getPreferredSelection()).thenReturn( + SelectedItem.StructureItem(StructureInfo( ComponentName("pkg", "cls"), "structure", listOf(ControlInfo("id", "title", "subtitle", 1)) - ) + )) ) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) @@ -247,8 +249,9 @@ class DeviceControlsTileTest : SysuiTestCase() { capture(listingCallbackCaptor) ) `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) - `when`(controlsController.getPreferredStructure()) - .thenReturn(StructureInfo(ComponentName("pkg", "cls"), "structure", listOf())) + `when`(controlsController.getPreferredSelection()) + .thenReturn(SelectedItem.StructureItem( + StructureInfo(ComponentName("pkg", "cls"), "structure", listOf()))) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() @@ -256,6 +259,22 @@ class DeviceControlsTileTest : SysuiTestCase() { assertThat(tile.state.state).isEqualTo(Tile.STATE_INACTIVE) } + @Test + fun testStateActiveIfPreferredIsPanel() { + verify(controlsListingController).observe( + any(LifecycleOwner::class.java), + capture(listingCallbackCaptor) + ) + `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) + `when`(controlsController.getPreferredSelection()) + .thenReturn(SelectedItem.PanelItem("appName", ComponentName("pkg", "cls"))) + + listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) + testableLooper.processAllMessages() + + assertThat(tile.state.state).isEqualTo(Tile.STATE_ACTIVE) + } + @Test fun testStateInactiveIfLocked() { verify(controlsListingController).observe( @@ -303,12 +322,12 @@ class DeviceControlsTileTest : SysuiTestCase() { ) `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) `when`(controlsUiController.resolveActivity()).thenReturn(ControlsActivity::class.java) - `when`(controlsController.getPreferredStructure()).thenReturn( - StructureInfo( - ComponentName("pkg", "cls"), - "structure", - listOf(ControlInfo("id", "title", "subtitle", 1)) - ) + `when`(controlsController.getPreferredSelection()).thenReturn( + SelectedItem.StructureItem(StructureInfo( + ComponentName("pkg", "cls"), + "structure", + listOf(ControlInfo("id", "title", "subtitle", 1)) + )) ) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) @@ -334,12 +353,12 @@ class DeviceControlsTileTest : SysuiTestCase() { `when`(controlsComponent.getVisibility()) .thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK) `when`(controlsUiController.resolveActivity()).thenReturn(ControlsActivity::class.java) - `when`(controlsController.getPreferredStructure()).thenReturn( - StructureInfo( + `when`(controlsController.getPreferredSelection()).thenReturn( + SelectedItem.StructureItem(StructureInfo( ComponentName("pkg", "cls"), "structure", listOf(ControlInfo("id", "title", "subtitle", 1)) - ) + )) ) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))