summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Fabian Kozynski <kozynski@google.com> 2023-01-12 16:12:00 -0500
committer Fabian Kozynski <kozynski@google.com> 2023-01-23 10:05:29 -0500
commiteae741388e1c960a76f03f7289bf9c6370d5352e (patch)
tree71fee633b50251a472aaaf890b9e49e41196c85e
parent694d2d571106b424634fffae1431525bb70bb6bb (diff)
Add new add flow for panels
This adds a flow for adding panels that will query consent from the user. Note that this needs Flags.APP_PANELS_ALL_APPS_ALLOWED for those panels to show in the first place. Test: manual, trigger dialog Test: atest com.android.systemui.controls Bug: 265180342 Change-Id: I5a0c382f98595daffbd7e4dfe1e52adb43b2f1c5
-rw-r--r--packages/SystemUI/res/values/strings.xml10
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt35
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt50
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/management/PanelConfirmationDialogFactory.kt60
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt32
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/management/AppAdapterTest.kt110
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsProviderSelectorActivityTest.kt155
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/management/PanelConfirmationDialogFactoryTest.kt106
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt18
14 files changed, 566 insertions, 59 deletions
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 066b185c6d1f..8dcd3b0eb476 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2238,6 +2238,14 @@
<!-- Removed control in management screen [CHAR LIMIT=20] -->
<string name="controls_removed">Removed</string>
+ <!-- Title for the dialog presented to the user to authorize this app to display a Device
+ controls panel (embedded activity) instead of controls rendered by SystemUI [CHAR LIMIT=30] -->
+ <string name="controls_panel_authorization_title">Add <xliff:g id="appName" example="My app">%s</xliff:g>?</string>
+
+ <!-- Shows in a dialog presented to the user to authorize this app to display a Device controls
+ panel (embedded activity) instead of controls rendered by SystemUI [CHAR LIMIT=NONE] -->
+ <string name="controls_panel_authorization">When you add <xliff:g id="appName" example="My app">%s</xliff:g>, it can add controls and content to this panel. In some apps, you can choose which controls show up here.</string>
+
<!-- a11y state description for a control that is currently favorited [CHAR LIMIT=NONE] -->
<string name="accessibility_control_favorite">Favorited</string>
<!-- a11y state description for a control that is currently favorited with its position [CHAR LIMIT=NONE] -->
@@ -2387,6 +2395,8 @@
<string name="controls_menu_add">Add controls</string>
<!-- Controls menu, edit [CHAR_LIMIT=30] -->
<string name="controls_menu_edit">Edit controls</string>
+ <!-- Controls menu, add another app [CHAR LIMIT=30] -->
+ <string name="controls_menu_add_another_app">Add app</string>
<!-- Title for the media output dialog with media related devices [CHAR LIMIT=50] -->
<string name="media_output_dialog_add_output">Add outputs</string>
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 f29f6d0dd0cb..822190f21da1 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
@@ -188,6 +188,8 @@ interface ControlsController : UserAwareController {
/** See [ControlsUiController.getPreferredSelectedItem]. */
fun getPreferredSelection(): SelectedItem
+ fun setPreferredSelection(selectedItem: SelectedItem)
+
/**
* Bind to a service that provides a Device Controls panel (embedded activity). This will allow
* the app to remain "warm", and reduce latency.
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 111fcbbe30be..1cbfe01a9a1a 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -36,6 +36,7 @@ import com.android.systemui.backup.BackupHelper
import com.android.systemui.controls.ControlStatus
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.management.ControlsListingController
+import com.android.systemui.controls.panels.AuthorizedPanelsRepository
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.controls.ui.SelectedItem
import com.android.systemui.dagger.SysUISingleton
@@ -61,6 +62,7 @@ class ControlsControllerImpl @Inject constructor (
private val listingController: ControlsListingController,
private val userFileManager: UserFileManager,
private val userTracker: UserTracker,
+ private val authorizedPanelsRepository: AuthorizedPanelsRepository,
optionalWrapper: Optional<ControlsFavoritePersistenceWrapper>,
dumpManager: DumpManager,
) : Dumpable, ControlsController {
@@ -249,6 +251,11 @@ class ControlsControllerImpl @Inject constructor (
private fun resetFavorites() {
Favorites.clear()
Favorites.load(persistenceWrapper.readFavorites())
+ // After loading favorites, add the package names of any apps with favorites to the list
+ // of authorized panels. That way, if the user has previously favorited controls for an app,
+ // that panel will be authorized.
+ authorizedPanelsRepository.addAuthorizedPanels(
+ Favorites.getAllStructures().map { it.componentName.packageName }.toSet())
}
private fun confirmAvailability(): Boolean {
@@ -489,6 +496,7 @@ class ControlsControllerImpl @Inject constructor (
if (!confirmAvailability()) return
executor.execute {
if (Favorites.addFavorite(componentName, structureName, controlInfo)) {
+ authorizedPanelsRepository.addAuthorizedPanels(setOf(componentName.packageName))
persistenceWrapper.storeFavorites(Favorites.getAllStructures())
}
}
@@ -555,6 +563,10 @@ class ControlsControllerImpl @Inject constructor (
return uiController.getPreferredSelectedItem(getFavorites())
}
+ override fun setPreferredSelection(selectedItem: SelectedItem) {
+ uiController.updatePreferences(selectedItem)
+ }
+
override fun dump(pw: PrintWriter, args: Array<out String>) {
pw.println("ControlsController state:")
pw.println(" Changing users: $userChanging")
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt
index 753d5addeb11..3fe0f03488d1 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt
@@ -45,14 +45,15 @@ import java.util.concurrent.Executor
* @param onAppSelected a callback to indicate that an app has been selected in the list.
*/
class AppAdapter(
- backgroundExecutor: Executor,
- uiExecutor: Executor,
- lifecycle: Lifecycle,
- controlsListingController: ControlsListingController,
- private val layoutInflater: LayoutInflater,
- private val onAppSelected: (ComponentName?) -> Unit = {},
- private val favoritesRenderer: FavoritesRenderer,
- private val resources: Resources
+ backgroundExecutor: Executor,
+ uiExecutor: Executor,
+ lifecycle: Lifecycle,
+ controlsListingController: ControlsListingController,
+ private val layoutInflater: LayoutInflater,
+ private val onAppSelected: (ControlsServiceInfo) -> Unit = {},
+ private val favoritesRenderer: FavoritesRenderer,
+ private val resources: Resources,
+ private val authorizedPanels: Set<String> = emptySet(),
) : RecyclerView.Adapter<AppAdapter.Holder>() {
private var listOfServices = emptyList<ControlsServiceInfo>()
@@ -64,8 +65,10 @@ class AppAdapter(
val localeComparator = compareBy<ControlsServiceInfo, CharSequence>(collator) {
it.loadLabel() ?: ""
}
- listOfServices = serviceInfos.filter { it.panelActivity == null }
- .sortedWith(localeComparator)
+ // No panel or the panel is not authorized
+ listOfServices = serviceInfos.filter {
+ it.panelActivity == null || it.panelActivity?.packageName !in authorizedPanels
+ }.sortedWith(localeComparator)
uiExecutor.execute(::notifyDataSetChanged)
}
}
@@ -86,8 +89,8 @@ class AppAdapter(
override fun onBindViewHolder(holder: Holder, index: Int) {
holder.bindData(listOfServices[index])
- holder.itemView.setOnClickListener {
- onAppSelected(ComponentName.unflattenFromString(listOfServices[index].key))
+ holder.view.setOnClickListener {
+ onAppSelected(listOfServices[index])
}
}
@@ -95,6 +98,8 @@ class AppAdapter(
* Holder for binding views in the [RecyclerView]-
*/
class Holder(view: View, val favRenderer: FavoritesRenderer) : RecyclerView.ViewHolder(view) {
+ val view: View = itemView
+
private val icon: ImageView = itemView.requireViewById(com.android.internal.R.id.icon)
private val title: TextView = itemView.requireViewById(com.android.internal.R.id.title)
private val favorites: TextView = itemView.requireViewById(R.id.favorites)
@@ -106,7 +111,11 @@ class AppAdapter(
fun bindData(data: ControlsServiceInfo) {
icon.setImageDrawable(data.loadIcon())
title.text = data.loadLabel()
- val text = favRenderer.renderFavoritesForComponent(data.componentName)
+ val text = if (data.panelActivity == null) {
+ favRenderer.renderFavoritesForComponent(data.componentName)
+ } else {
+ null
+ }
favorites.text = text
favorites.visibility = if (text == null) View.GONE else View.VISIBLE
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
index 90bc5d0f8daa..54587b20c7e1 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
@@ -17,6 +17,7 @@
package com.android.systemui.controls.management
import android.app.ActivityOptions
+import android.app.Dialog
import android.content.ComponentName
import android.content.Context
import android.content.Intent
@@ -31,12 +32,15 @@ import android.widget.TextView
import android.window.OnBackInvokedCallback
import android.window.OnBackInvokedDispatcher
import androidx.activity.ComponentActivity
+import androidx.annotation.VisibleForTesting
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.systemui.R
+import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.controller.ControlsController
+import com.android.systemui.controls.panels.AuthorizedPanelsRepository
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.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.settings.UserTracker
@@ -52,7 +56,8 @@ open class ControlsProviderSelectorActivity @Inject constructor(
private val listingController: ControlsListingController,
private val controlsController: ControlsController,
private val userTracker: UserTracker,
- private val uiController: ControlsUiController
+ private val authorizedPanelsRepository: AuthorizedPanelsRepository,
+ private val panelConfirmationDialogFactory: PanelConfirmationDialogFactory
) : ComponentActivity() {
companion object {
@@ -72,6 +77,7 @@ open class ControlsProviderSelectorActivity @Inject constructor(
}
}
}
+ private var dialog: Dialog? = null
private val mOnBackInvokedCallback = OnBackInvokedCallback {
if (DEBUG) {
@@ -138,9 +144,11 @@ open class ControlsProviderSelectorActivity @Inject constructor(
lifecycle,
listingController,
LayoutInflater.from(this),
- ::launchFavoritingActivity,
+ ::onAppSelected,
FavoritesRenderer(resources, controlsController::countFavoritesForComponent),
- resources).apply {
+ resources,
+ authorizedPanelsRepository.getAuthorizedPanels()
+ ).apply {
registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
var hasAnimated = false
override fun onChanged() {
@@ -167,13 +175,35 @@ open class ControlsProviderSelectorActivity @Inject constructor(
Log.d(TAG, "Unregistered onBackInvokedCallback")
}
onBackInvokedDispatcher.unregisterOnBackInvokedCallback(mOnBackInvokedCallback)
+ dialog?.cancel()
+ }
+
+ fun onAppSelected(serviceInfo: ControlsServiceInfo) {
+ dialog?.cancel()
+ if (serviceInfo.panelActivity == null) {
+ launchFavoritingActivity(serviceInfo.componentName)
+ } else {
+ val appName = serviceInfo.loadLabel() ?: ""
+ dialog = panelConfirmationDialogFactory.createConfirmationDialog(this, appName) { ok ->
+ if (ok) {
+ authorizedPanelsRepository.addAuthorizedPanels(
+ setOf(serviceInfo.componentName.packageName)
+ )
+ animateExitAndFinish()
+ val selected = SelectedItem.PanelItem(appName, componentName)
+ controlsController.setPreferredSelection(selected)
+ openControlsOrigin()
+ }
+ dialog = null
+ }.also { it.show() }
+ }
}
/**
* Launch the [ControlsFavoritingActivity] for the specified component.
* @param component a component name for a [ControlsProviderService]
*/
- fun launchFavoritingActivity(component: ComponentName?) {
+ private fun launchFavoritingActivity(component: ComponentName?) {
executor.execute {
component?.let {
val intent = Intent(applicationContext, ControlsFavoritingActivity::class.java)
@@ -194,7 +224,15 @@ open class ControlsProviderSelectorActivity @Inject constructor(
super.onDestroy()
}
- private fun animateExitAndFinish() {
+ private fun openControlsOrigin() {
+ startActivity(
+ Intent(applicationContext, ControlsActivity::class.java),
+ ActivityOptions.makeSceneTransitionAnimation(this).toBundle()
+ )
+ }
+
+ @VisibleForTesting
+ internal open fun animateExitAndFinish() {
val rootView = requireViewById<ViewGroup>(R.id.controls_management_root)
ControlsAnimations.exitAnimation(
rootView,
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/PanelConfirmationDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/controls/management/PanelConfirmationDialogFactory.kt
new file mode 100644
index 000000000000..6f87aa996f94
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/PanelConfirmationDialogFactory.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2023 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.management
+
+import android.app.Dialog
+import android.content.Context
+import android.content.DialogInterface
+import com.android.systemui.R
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import java.util.function.Consumer
+import javax.inject.Inject
+
+/**
+ * Factory to create dialogs for consenting to show app panels for specific apps.
+ *
+ * [internalDialogFactory] is for facilitating testing.
+ */
+class PanelConfirmationDialogFactory(
+ private val internalDialogFactory: (Context) -> SystemUIDialog
+) {
+ @Inject constructor() : this({ SystemUIDialog(it) })
+
+ /**
+ * Creates a dialog to show to the user. [response] will be true if an only if the user responds
+ * affirmatively.
+ */
+ fun createConfirmationDialog(
+ context: Context,
+ appName: CharSequence,
+ response: Consumer<Boolean>
+ ): Dialog {
+ val listener =
+ DialogInterface.OnClickListener { _, which ->
+ response.accept(which == DialogInterface.BUTTON_POSITIVE)
+ }
+ return internalDialogFactory(context).apply {
+ setTitle(this.context.getString(R.string.controls_panel_authorization_title, appName))
+ setMessage(this.context.getString(R.string.controls_panel_authorization, appName))
+ setCanceledOnTouchOutside(true)
+ setOnCancelListener { response.accept(false) }
+ setPositiveButton(R.string.controls_dialog_ok, listener)
+ setNeutralButton(R.string.cancel, listener)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
index 1a6b84a8e054..3e672f391e81 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
@@ -17,8 +17,15 @@
package com.android.systemui.controls.panels
+/**
+ * Repository for keeping track of which packages the panel has authorized to show control panels
+ * (embedded activity).
+ */
interface AuthorizedPanelsRepository {
+
+ /** A set of package names that the user has previously authorized to show panels. */
fun getAuthorizedPanels(): Set<String>
+ /** Adds [packageNames] to the set of packages that the user has authorized to show panels. */
fun addAuthorizedPanels(packageNames: Set<String>)
}
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 f5c5905779a1..c1cec9dd0f94 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
@@ -58,6 +58,8 @@ interface ControlsUiController {
* This element will be the one that appears when the user first opens the controls activity.
*/
fun getPreferredSelectedItem(structures: List<StructureInfo>): SelectedItem
+
+ fun updatePreferences(selectedItem: SelectedItem)
}
sealed class SelectedItem {
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 6289788f650a..966dbf1a9694 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -60,10 +60,13 @@ import com.android.systemui.controls.management.ControlsEditingActivity
import com.android.systemui.controls.management.ControlsFavoritingActivity
import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.management.ControlsProviderSelectorActivity
+import com.android.systemui.controls.panels.AuthorizedPanelsRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
import com.android.systemui.globalactions.GlobalActionsPopupMenu
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.settings.UserFileManager
@@ -99,6 +102,8 @@ class ControlsUiControllerImpl @Inject constructor (
private val userTracker: UserTracker,
private val taskViewFactory: Optional<TaskViewFactory>,
private val controlsSettingsRepository: ControlsSettingsRepository,
+ private val authorizedPanelsRepository: AuthorizedPanelsRepository,
+ private val featureFlags: FeatureFlags,
dumpManager: DumpManager
) : ControlsUiController, Dumpable {
@@ -160,6 +165,7 @@ class ControlsUiControllerImpl @Inject constructor (
): ControlsListingController.ControlsListingCallback {
return object : ControlsListingController.ControlsListingCallback {
override fun onServicesUpdated(serviceInfos: List<ControlsServiceInfo>) {
+ val authorizedPanels = authorizedPanelsRepository.getAuthorizedPanels()
val lastItems = serviceInfos.map {
val uid = it.serviceInfo.applicationInfo.uid
@@ -169,7 +175,11 @@ class ControlsUiControllerImpl @Inject constructor (
it.loadIcon(),
it.componentName,
uid,
- it.panelActivity
+ if (it.componentName.packageName in authorizedPanels) {
+ it.panelActivity
+ } else {
+ null
+ }
)
}
uiExecutor.execute {
@@ -417,14 +427,20 @@ class ControlsUiControllerImpl @Inject constructor (
val isPanel = selectedItem is SelectedItem.PanelItem
val selectedStructure = (selectedItem as? SelectedItem.StructureItem)?.structure
?: EMPTY_STRUCTURE
+ val newFlows = featureFlags.isEnabled(Flags.CONTROLS_MANAGEMENT_NEW_FLOWS)
+ val addControlsId = if (newFlows || isPanel) {
+ R.string.controls_menu_add_another_app
+ } else {
+ R.string.controls_menu_add
+ }
val items = if (isPanel) {
arrayOf(
- context.resources.getString(R.string.controls_menu_add),
+ context.resources.getString(addControlsId),
)
} else {
arrayOf(
- context.resources.getString(R.string.controls_menu_add),
+ context.resources.getString(addControlsId),
context.resources.getString(R.string.controls_menu_edit)
)
}
@@ -449,7 +465,7 @@ class ControlsUiControllerImpl @Inject constructor (
when (pos) {
// 0: Add Control
0 -> {
- if (isPanel) {
+ if (isPanel || newFlows) {
startProviderSelectorActivity()
} else {
startFavoritingActivity(selectedStructure)
@@ -610,11 +626,11 @@ class ControlsUiControllerImpl @Inject constructor (
}
}
- private fun updatePreferences(si: SelectedItem) {
+ override fun updatePreferences(selectedItem: SelectedItem) {
sharedPreferences.edit()
- .putString(PREF_COMPONENT, si.componentName.flattenToString())
- .putString(PREF_STRUCTURE_OR_APP_NAME, si.name.toString())
- .putBoolean(PREF_IS_PANEL, si is SelectedItem.PanelItem)
+ .putString(PREF_COMPONENT, selectedItem.componentName.flattenToString())
+ .putString(PREF_STRUCTURE_OR_APP_NAME, selectedItem.name.toString())
+ .putBoolean(PREF_IS_PANEL, selectedItem is SelectedItem.PanelItem)
.commit()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
index 25f471b0d3e0..d54babfbdc0e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
@@ -33,6 +33,7 @@ import com.android.systemui.backup.BackupHelper
import com.android.systemui.controls.ControlStatus
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.management.ControlsListingController
+import com.android.systemui.controls.panels.AuthorizedPanelsRepository
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.dump.DumpManager
import com.android.systemui.settings.UserFileManager
@@ -66,6 +67,7 @@ import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.clearInvocations
import org.mockito.MockitoAnnotations
@SmallTest
@@ -88,6 +90,8 @@ class ControlsControllerImplTest : SysuiTestCase() {
private lateinit var userTracker: UserTracker
@Mock
private lateinit var userFileManager: UserFileManager
+ @Mock
+ private lateinit var authorizedPanelsRepository: AuthorizedPanelsRepository
@Captor
private lateinit var structureInfoCaptor: ArgumentCaptor<StructureInfo>
@@ -168,6 +172,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
listingController,
userFileManager,
userTracker,
+ authorizedPanelsRepository,
Optional.of(persistenceWrapper),
mock(DumpManager::class.java)
)
@@ -224,6 +229,7 @@ class ControlsControllerImplTest : SysuiTestCase() {
listingController,
userFileManager,
userTracker,
+ authorizedPanelsRepository,
Optional.of(persistenceWrapper),
mock(DumpManager::class.java)
)
@@ -231,6 +237,26 @@ class ControlsControllerImplTest : SysuiTestCase() {
}
@Test
+ fun testAddAuthorizedPackagesFromSavedFavoritesOnStart() {
+ clearInvocations(authorizedPanelsRepository)
+ `when`(persistenceWrapper.readFavorites()).thenReturn(listOf(TEST_STRUCTURE_INFO))
+ ControlsControllerImpl(
+ mContext,
+ delayableExecutor,
+ uiController,
+ bindingController,
+ listingController,
+ userFileManager,
+ userTracker,
+ authorizedPanelsRepository,
+ Optional.of(persistenceWrapper),
+ mock(DumpManager::class.java)
+ )
+ verify(authorizedPanelsRepository)
+ .addAuthorizedPanels(setOf(TEST_STRUCTURE_INFO.componentName.packageName))
+ }
+
+ @Test
fun testOnActionResponse() {
controller.onActionResponse(TEST_COMPONENT, TEST_CONTROL_ID, ControlAction.RESPONSE_OK)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/AppAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/AppAdapterTest.kt
index 765c4c0ac0f0..226ef3b85706 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/AppAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/AppAdapterTest.kt
@@ -21,12 +21,15 @@ import android.content.res.Resources
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.LayoutInflater
+import android.view.View
import androidx.test.filters.SmallTest
import com.android.settingslib.core.lifecycle.Lifecycle
import com.android.systemui.SysuiTestCase
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -36,8 +39,10 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Mock
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+import java.text.Collator
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -49,25 +54,18 @@ class AppAdapterTest : SysuiTestCase() {
@Mock lateinit var lifecycle: Lifecycle
@Mock lateinit var controlsListingController: ControlsListingController
@Mock lateinit var layoutInflater: LayoutInflater
- @Mock lateinit var onAppSelected: (ComponentName?) -> Unit
+ @Mock lateinit var onAppSelected: (ControlsServiceInfo) -> Unit
@Mock lateinit var favoritesRenderer: FavoritesRenderer
val resources: Resources = context.resources
lateinit var adapter: AppAdapter
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- adapter = AppAdapter(backgroundExecutor,
- uiExecutor,
- lifecycle,
- controlsListingController,
- layoutInflater,
- onAppSelected,
- favoritesRenderer,
- resources)
}
@Test
fun testOnServicesUpdated_nullLoadLabel() {
+ adapter = createAdapterWithAuthorizedPanels(emptySet())
val captor = ArgumentCaptor
.forClass(ControlsListingController.ControlsListingCallback::class.java)
val controlsServiceInfo = mock<ControlsServiceInfo>()
@@ -76,14 +74,14 @@ class AppAdapterTest : SysuiTestCase() {
verify(controlsListingController).observe(any(Lifecycle::class.java), captor.capture())
captor.value.onServicesUpdated(serviceInfo)
- backgroundExecutor.runAllReady()
- uiExecutor.runAllReady()
+ FakeExecutor.exhaustExecutors(backgroundExecutor, uiExecutor)
assertThat(adapter.itemCount).isEqualTo(serviceInfo.size)
}
@Test
- fun testOnServicesUpdatedDoesntHavePanels() {
+ fun testOnServicesUpdated_showsNotAuthorizedPanels() {
+ adapter = createAdapterWithAuthorizedPanels(emptySet())
val captor = ArgumentCaptor
.forClass(ControlsListingController.ControlsListingCallback::class.java)
val serviceInfo = listOf(
@@ -93,20 +91,88 @@ class AppAdapterTest : SysuiTestCase() {
verify(controlsListingController).observe(any(Lifecycle::class.java), captor.capture())
captor.value.onServicesUpdated(serviceInfo)
- backgroundExecutor.runAllReady()
- uiExecutor.runAllReady()
+ FakeExecutor.exhaustExecutors(backgroundExecutor, uiExecutor)
+
+ assertThat(adapter.itemCount).isEqualTo(2)
+ }
+
+ @Test
+ fun testOnServicesUpdated_doesntShowAuthorizedPanels() {
+ adapter = createAdapterWithAuthorizedPanels(setOf(TEST_PACKAGE))
+
+ val captor = ArgumentCaptor
+ .forClass(ControlsListingController.ControlsListingCallback::class.java)
+ val serviceInfo = listOf(
+ ControlsServiceInfo("no panel", null),
+ ControlsServiceInfo("panel", ComponentName(TEST_PACKAGE, "cls"))
+ )
+ verify(controlsListingController).observe(any(Lifecycle::class.java), captor.capture())
+
+ captor.value.onServicesUpdated(serviceInfo)
+ FakeExecutor.exhaustExecutors(backgroundExecutor, uiExecutor)
assertThat(adapter.itemCount).isEqualTo(1)
}
- fun ControlsServiceInfo(
- label: CharSequence,
- panelComponentName: ComponentName? = null
- ): ControlsServiceInfo {
- return mock {
- `when`(this.loadLabel()).thenReturn(label)
- `when`(this.panelActivity).thenReturn(panelComponentName)
- `when`(this.loadIcon()).thenReturn(mock())
+ @Test
+ fun testOnBindSetsClickListenerToCallOnAppSelected() {
+ adapter = createAdapterWithAuthorizedPanels(emptySet())
+
+ val captor = ArgumentCaptor
+ .forClass(ControlsListingController.ControlsListingCallback::class.java)
+ val serviceInfo = listOf(
+ ControlsServiceInfo("no panel", null),
+ ControlsServiceInfo("panel", ComponentName(TEST_PACKAGE, "cls"))
+ )
+ verify(controlsListingController).observe(any(Lifecycle::class.java), captor.capture())
+
+ captor.value.onServicesUpdated(serviceInfo)
+ FakeExecutor.exhaustExecutors(backgroundExecutor, uiExecutor)
+
+ val sorted = serviceInfo.sortedWith(
+ compareBy(Collator.getInstance(resources.configuration.locales[0])) {
+ it.loadLabel() ?: ""
+ })
+
+ sorted.forEachIndexed { index, info ->
+ val fakeView: View = mock()
+ val fakeHolder: AppAdapter.Holder = mock()
+ `when`(fakeHolder.view).thenReturn(fakeView)
+
+ clearInvocations(onAppSelected)
+ adapter.onBindViewHolder(fakeHolder, index)
+ val listenerCaptor: ArgumentCaptor<View.OnClickListener> = argumentCaptor()
+ verify(fakeView).setOnClickListener(capture(listenerCaptor))
+ listenerCaptor.value.onClick(fakeView)
+
+ verify(onAppSelected).invoke(info)
+ }
+ }
+
+ private fun createAdapterWithAuthorizedPanels(packages: Set<String>): AppAdapter {
+ return AppAdapter(backgroundExecutor,
+ uiExecutor,
+ lifecycle,
+ controlsListingController,
+ layoutInflater,
+ onAppSelected,
+ favoritesRenderer,
+ resources,
+ packages)
+ }
+
+ companion object {
+ private fun ControlsServiceInfo(
+ label: CharSequence,
+ panelComponentName: ComponentName? = null
+ ): ControlsServiceInfo {
+ return mock {
+ `when`(loadLabel()).thenReturn(label)
+ `when`(panelActivity).thenReturn(panelComponentName)
+ `when`(loadIcon()).thenReturn(mock())
+ }
}
+
+ private const val TEST_PACKAGE = "package"
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsProviderSelectorActivityTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsProviderSelectorActivityTest.kt
index 56c3efe1b8e6..8dfd22378a14 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsProviderSelectorActivityTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsProviderSelectorActivityTest.kt
@@ -16,7 +16,13 @@
package com.android.systemui.controls.management
+import android.app.Dialog
+import android.content.ComponentName
import android.content.Intent
+import android.content.pm.ApplicationInfo
+import android.content.pm.ServiceInfo
+import android.graphics.drawable.Drawable
+import android.os.Bundle
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.window.OnBackInvokedCallback
@@ -25,14 +31,23 @@ import androidx.test.filters.SmallTest
import androidx.test.rule.ActivityTestRule
import androidx.test.runner.intercepting.SingleActivityFactory
import com.android.systemui.SysuiTestCase
+import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.controller.ControlsController
-import com.android.systemui.controls.ui.ControlsUiController
+import com.android.systemui.controls.panels.AuthorizedPanelsRepository
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.MoreExecutors
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executor
+import java.util.function.Consumer
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -41,7 +56,11 @@ import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers
import org.mockito.Captor
import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.never
import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.MockitoAnnotations
@SmallTest
@@ -58,9 +77,10 @@ class ControlsProviderSelectorActivityTest : SysuiTestCase() {
@Mock lateinit var userTracker: UserTracker
- @Mock lateinit var uiController: ControlsUiController
+ @Mock lateinit var authorizedPanelsRepository: AuthorizedPanelsRepository
+
+ @Mock lateinit var dialogFactory: PanelConfirmationDialogFactory
- private lateinit var controlsProviderSelectorActivity: ControlsProviderSelectorActivity_Factory
private var latch: CountDownLatch = CountDownLatch(1)
@Mock private lateinit var mockDispatcher: OnBackInvokedDispatcher
@@ -81,7 +101,8 @@ class ControlsProviderSelectorActivityTest : SysuiTestCase() {
listingController,
controlsController,
userTracker,
- uiController,
+ authorizedPanelsRepository,
+ dialogFactory,
mockDispatcher,
latch
)
@@ -113,13 +134,99 @@ class ControlsProviderSelectorActivityTest : SysuiTestCase() {
verify(mockDispatcher).unregisterOnBackInvokedCallback(captureCallback.value)
}
- public class TestableControlsProviderSelectorActivity(
+ @Test
+ fun testOnAppSelectedForNonPanelStartsFavoritingActivity() {
+ val info = ControlsServiceInfo(ComponentName("test_pkg", "service"), "", null)
+ activityRule.activity.onAppSelected(info)
+
+ verifyNoMoreInteractions(dialogFactory)
+
+ assertThat(activityRule.activity.lastStartedActivity?.component?.className)
+ .isEqualTo(ControlsFavoritingActivity::class.java.name)
+
+ assertThat(activityRule.activity.triedToFinish).isTrue()
+ }
+
+ @Test
+ fun testOnAppSelectedForPanelTriggersDialog() {
+ val label = "label"
+ val info =
+ ControlsServiceInfo(
+ ComponentName("test_pkg", "service"),
+ label,
+ ComponentName("test_pkg", "activity")
+ )
+
+ val dialog: Dialog = mock()
+ whenever(dialogFactory.createConfirmationDialog(any(), any(), any())).thenReturn(dialog)
+
+ activityRule.activity.onAppSelected(info)
+ verify(dialogFactory).createConfirmationDialog(any(), eq(label), any())
+ verify(dialog).show()
+
+ assertThat(activityRule.activity.triedToFinish).isFalse()
+ }
+
+ @Test
+ fun dialogAcceptAddsPackage() {
+ val label = "label"
+ val info =
+ ControlsServiceInfo(
+ ComponentName("test_pkg", "service"),
+ label,
+ ComponentName("test_pkg", "activity")
+ )
+
+ val dialog: Dialog = mock()
+ whenever(dialogFactory.createConfirmationDialog(any(), any(), any())).thenReturn(dialog)
+
+ activityRule.activity.onAppSelected(info)
+
+ val captor: ArgumentCaptor<Consumer<Boolean>> = argumentCaptor()
+ verify(dialogFactory).createConfirmationDialog(any(), any(), capture(captor))
+
+ captor.value.accept(true)
+
+ val setCaptor: ArgumentCaptor<Set<String>> = argumentCaptor()
+ verify(authorizedPanelsRepository).addAuthorizedPanels(capture(setCaptor))
+ assertThat(setCaptor.value).containsExactly(info.componentName.packageName)
+
+ assertThat(activityRule.activity.triedToFinish).isTrue()
+ }
+
+ @Test
+ fun dialogCancelDoesntAddPackage() {
+ val label = "label"
+ val info =
+ ControlsServiceInfo(
+ ComponentName("test_pkg", "service"),
+ label,
+ ComponentName("test_pkg", "activity")
+ )
+
+ val dialog: Dialog = mock()
+ whenever(dialogFactory.createConfirmationDialog(any(), any(), any())).thenReturn(dialog)
+
+ activityRule.activity.onAppSelected(info)
+
+ val captor: ArgumentCaptor<Consumer<Boolean>> = argumentCaptor()
+ verify(dialogFactory).createConfirmationDialog(any(), any(), capture(captor))
+
+ captor.value.accept(false)
+
+ verify(authorizedPanelsRepository, never()).addAuthorizedPanels(any())
+
+ assertThat(activityRule.activity.triedToFinish).isFalse()
+ }
+
+ class TestableControlsProviderSelectorActivity(
executor: Executor,
backExecutor: Executor,
listingController: ControlsListingController,
controlsController: ControlsController,
userTracker: UserTracker,
- uiController: ControlsUiController,
+ authorizedPanelsRepository: AuthorizedPanelsRepository,
+ dialogFactory: PanelConfirmationDialogFactory,
private val mockDispatcher: OnBackInvokedDispatcher,
private val latch: CountDownLatch
) :
@@ -129,16 +236,50 @@ class ControlsProviderSelectorActivityTest : SysuiTestCase() {
listingController,
controlsController,
userTracker,
- uiController
+ authorizedPanelsRepository,
+ dialogFactory
) {
+
+ var lastStartedActivity: Intent? = null
+ var triedToFinish = false
+
override fun getOnBackInvokedDispatcher(): OnBackInvokedDispatcher {
return mockDispatcher
}
+ override fun startActivity(intent: Intent?, options: Bundle?) {
+ lastStartedActivity = intent
+ }
+
override fun onStop() {
super.onStop()
// ensures that test runner thread does not proceed until ui thread is done
latch.countDown()
}
+
+ override fun animateExitAndFinish() {
+ // Activity should only be finished from the rule.
+ triedToFinish = true
+ }
+ }
+
+ companion object {
+ private fun ControlsServiceInfo(
+ componentName: ComponentName,
+ label: CharSequence,
+ panelComponentName: ComponentName? = null
+ ): ControlsServiceInfo {
+ val serviceInfo =
+ ServiceInfo().apply {
+ applicationInfo = ApplicationInfo()
+ packageName = componentName.packageName
+ name = componentName.className
+ }
+ return Mockito.spy(ControlsServiceInfo(mock(), serviceInfo)).apply {
+ doReturn(label).`when`(this).loadLabel()
+ doReturn(mock<Drawable>()).`when`(this).loadIcon()
+ doReturn(panelComponentName).`when`(this).panelActivity
+ }
+ }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/management/PanelConfirmationDialogFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/management/PanelConfirmationDialogFactoryTest.kt
new file mode 100644
index 000000000000..756f267671e1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/management/PanelConfirmationDialogFactoryTest.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2023 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.management
+
+import android.content.DialogInterface
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class PanelConfirmationDialogFactoryTest : SysuiTestCase() {
+
+ @Test
+ fun testDialogHasCorrectInfo() {
+ val mockDialog: SystemUIDialog = mock() { `when`(context).thenReturn(mContext) }
+ val factory = PanelConfirmationDialogFactory { mockDialog }
+ val appName = "appName"
+
+ factory.createConfirmationDialog(context, appName) {}
+
+ verify(mockDialog).setCanceledOnTouchOutside(true)
+ verify(mockDialog)
+ .setTitle(context.getString(R.string.controls_panel_authorization_title, appName))
+ verify(mockDialog)
+ .setMessage(context.getString(R.string.controls_panel_authorization, appName))
+ }
+
+ @Test
+ fun testDialogPositiveButton() {
+ val mockDialog: SystemUIDialog = mock() { `when`(context).thenReturn(mContext) }
+ val factory = PanelConfirmationDialogFactory { mockDialog }
+
+ var response: Boolean? = null
+
+ factory.createConfirmationDialog(context, "") { response = it }
+
+ val captor: ArgumentCaptor<DialogInterface.OnClickListener> = argumentCaptor()
+ verify(mockDialog).setPositiveButton(eq(R.string.controls_dialog_ok), capture(captor))
+
+ captor.value.onClick(mockDialog, DialogInterface.BUTTON_POSITIVE)
+
+ assertThat(response).isTrue()
+ }
+
+ @Test
+ fun testDialogNeutralButton() {
+ val mockDialog: SystemUIDialog = mock() { `when`(context).thenReturn(mContext) }
+ val factory = PanelConfirmationDialogFactory { mockDialog }
+
+ var response: Boolean? = null
+
+ factory.createConfirmationDialog(context, "") { response = it }
+
+ val captor: ArgumentCaptor<DialogInterface.OnClickListener> = argumentCaptor()
+ verify(mockDialog).setNeutralButton(eq(R.string.cancel), capture(captor))
+
+ captor.value.onClick(mockDialog, DialogInterface.BUTTON_NEUTRAL)
+
+ assertThat(response).isFalse()
+ }
+
+ @Test
+ fun testDialogCancel() {
+ val mockDialog: SystemUIDialog = mock() { `when`(context).thenReturn(mContext) }
+ val factory = PanelConfirmationDialogFactory { mockDialog }
+
+ var response: Boolean? = null
+
+ factory.createConfirmationDialog(context, "") { response = it }
+
+ val captor: ArgumentCaptor<DialogInterface.OnCancelListener> = argumentCaptor()
+ verify(mockDialog).setOnCancelListener(capture(captor))
+
+ captor.value.onCancel(mockDialog)
+
+ assertThat(response).isFalse()
+ }
+}
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 edc6882e71c0..ed40c90b2c69 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
@@ -39,8 +39,10 @@ import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.controls.controller.StructureInfo
import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.management.ControlsProviderSelectorActivity
+import com.android.systemui.controls.panels.AuthorizedPanelsRepository
import com.android.systemui.controls.settings.FakeControlsSettingsRepository
import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.FeatureFlags
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.settings.UserFileManager
import com.android.systemui.settings.UserTracker
@@ -91,6 +93,8 @@ class ControlsUiControllerImplTest : SysuiTestCase() {
@Mock lateinit var userTracker: UserTracker
@Mock lateinit var taskViewFactory: TaskViewFactory
@Mock lateinit var dumpManager: DumpManager
+ @Mock lateinit var authorizedPanelsRepository: AuthorizedPanelsRepository
+ @Mock lateinit var featureFlags: FeatureFlags
val sharedPreferences = FakeSharedPreferences()
lateinit var controlsSettingsRepository: FakeControlsSettingsRepository
@@ -132,6 +136,8 @@ class ControlsUiControllerImplTest : SysuiTestCase() {
userTracker,
Optional.of(taskViewFactory),
controlsSettingsRepository,
+ authorizedPanelsRepository,
+ featureFlags,
dumpManager
)
`when`(
@@ -240,7 +246,9 @@ class ControlsUiControllerImplTest : SysuiTestCase() {
@Test
fun testPanelCallsTaskViewFactoryCreate() {
mockLayoutInflater()
- val panel = SelectedItem.PanelItem("App name", ComponentName("pkg", "cls"))
+ val packageName = "pkg"
+ `when`(authorizedPanelsRepository.getAuthorizedPanels()).thenReturn(setOf(packageName))
+ val panel = SelectedItem.PanelItem("App name", ComponentName(packageName, "cls"))
val serviceInfo = setUpPanel(panel)
underTest.show(parent, {}, context)
@@ -258,9 +266,11 @@ class ControlsUiControllerImplTest : SysuiTestCase() {
@Test
fun testPanelControllerStartActivityWithCorrectArguments() {
mockLayoutInflater()
+ val packageName = "pkg"
+ `when`(authorizedPanelsRepository.getAuthorizedPanels()).thenReturn(setOf(packageName))
controlsSettingsRepository.setAllowActionOnTrivialControlsInLockscreen(true)
- val panel = SelectedItem.PanelItem("App name", ComponentName("pkg", "cls"))
+ val panel = SelectedItem.PanelItem("App name", ComponentName(packageName, "cls"))
val serviceInfo = setUpPanel(panel)
underTest.show(parent, {}, context)
@@ -290,9 +300,11 @@ class ControlsUiControllerImplTest : SysuiTestCase() {
@Test
fun testPendingIntentExtrasAreModified() {
mockLayoutInflater()
+ val packageName = "pkg"
+ `when`(authorizedPanelsRepository.getAuthorizedPanels()).thenReturn(setOf(packageName))
controlsSettingsRepository.setAllowActionOnTrivialControlsInLockscreen(true)
- val panel = SelectedItem.PanelItem("App name", ComponentName("pkg", "cls"))
+ val panel = SelectedItem.PanelItem("App name", ComponentName(packageName, "cls"))
val serviceInfo = setUpPanel(panel)
underTest.show(parent, {}, context)