summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Alejandro Nijamkin <nijamkin@google.com> 2022-11-14 16:03:49 -0800
committer Alejandro Nijamkin <nijamkin@google.com> 2022-11-15 15:46:27 -0800
commit038616a71a9dea85f70eabbbd9486a67c55e82e6 (patch)
treec95f886ff54d08998b94d71ae7c02e11bb1fef49
parent6fe4159252d2e5aa1a41b129f4de0f95c07fecbd (diff)
Unit test for quick affordance content provider.
For merging and app bloat reasons, this test ended up being removed from the original CL that was submitted. Bug: 254857637 Test: this is a test Change-Id: I40ce21840a302949d02a18ecf05d6a2cec2ab2f5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProviderTest.kt399
1 files changed, 399 insertions, 0 deletions
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProviderTest.kt
new file mode 100644
index 000000000000..ed08849fe70c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardQuickAffordanceProviderTest.kt
@@ -0,0 +1,399 @@
+/*
+ * Copyright (C) 2022 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.keyguard
+
+import android.content.ContentValues
+import android.content.pm.PackageManager
+import android.content.pm.ProviderInfo
+import androidx.test.filters.SmallTest
+import com.android.internal.widget.LockPatternUtils
+import com.android.systemui.SystemUIAppComponentFactoryBase
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.keyguard.data.quickaffordance.FakeKeyguardQuickAffordanceConfig
+import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceSelectionManager
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.shared.keyguard.data.content.KeyguardQuickAffordanceProviderContract as Contract
+import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(JUnit4::class)
+class KeyguardQuickAffordanceProviderTest : SysuiTestCase() {
+
+ @Mock private lateinit var lockPatternUtils: LockPatternUtils
+ @Mock private lateinit var keyguardStateController: KeyguardStateController
+ @Mock private lateinit var userTracker: UserTracker
+ @Mock private lateinit var activityStarter: ActivityStarter
+
+ private lateinit var underTest: KeyguardQuickAffordanceProvider
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ underTest = KeyguardQuickAffordanceProvider()
+ val quickAffordanceRepository =
+ KeyguardQuickAffordanceRepository(
+ appContext = context,
+ scope = CoroutineScope(IMMEDIATE),
+ backgroundDispatcher = IMMEDIATE,
+ selectionManager = KeyguardQuickAffordanceSelectionManager(),
+ configs =
+ setOf(
+ FakeKeyguardQuickAffordanceConfig(
+ key = AFFORDANCE_1,
+ pickerIconResourceId = 1,
+ ),
+ FakeKeyguardQuickAffordanceConfig(
+ key = AFFORDANCE_2,
+ pickerIconResourceId = 2,
+ ),
+ ),
+ )
+ underTest.interactor =
+ KeyguardQuickAffordanceInteractor(
+ keyguardInteractor =
+ KeyguardInteractor(
+ repository = FakeKeyguardRepository(),
+ ),
+ registry = mock(),
+ lockPatternUtils = lockPatternUtils,
+ keyguardStateController = keyguardStateController,
+ userTracker = userTracker,
+ activityStarter = activityStarter,
+ featureFlags =
+ FakeFeatureFlags().apply {
+ set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, true)
+ },
+ repository = { quickAffordanceRepository },
+ )
+
+ underTest.attachInfoForTesting(
+ context,
+ ProviderInfo().apply { authority = Contract.AUTHORITY },
+ )
+ context.contentResolver.addProvider(Contract.AUTHORITY, underTest)
+ context.testablePermissions.setPermission(
+ Contract.PERMISSION,
+ PackageManager.PERMISSION_GRANTED,
+ )
+ }
+
+ @Test
+ fun `onAttachInfo - reportsContext`() {
+ val callback: SystemUIAppComponentFactoryBase.ContextAvailableCallback = mock()
+ underTest.setContextAvailableCallback(callback)
+
+ underTest.attachInfo(context, null)
+
+ verify(callback).onContextAvailable(context)
+ }
+
+ @Test
+ fun getType() {
+ assertThat(underTest.getType(Contract.AffordanceTable.URI))
+ .isEqualTo(
+ "vnd.android.cursor.dir/vnd." +
+ "${Contract.AUTHORITY}.${Contract.AffordanceTable.TABLE_NAME}"
+ )
+ assertThat(underTest.getType(Contract.SlotTable.URI))
+ .isEqualTo(
+ "vnd.android.cursor.dir/vnd.${Contract.AUTHORITY}.${Contract.SlotTable.TABLE_NAME}"
+ )
+ assertThat(underTest.getType(Contract.SelectionTable.URI))
+ .isEqualTo(
+ "vnd.android.cursor.dir/vnd." +
+ "${Contract.AUTHORITY}.${Contract.SelectionTable.TABLE_NAME}"
+ )
+ }
+
+ @Test
+ fun `insert and query selection`() =
+ runBlocking(IMMEDIATE) {
+ val slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START
+ val affordanceId = AFFORDANCE_2
+
+ insertSelection(
+ slotId = slotId,
+ affordanceId = affordanceId,
+ )
+
+ assertThat(querySelections())
+ .isEqualTo(
+ listOf(
+ Selection(
+ slotId = slotId,
+ affordanceId = affordanceId,
+ )
+ )
+ )
+ }
+
+ @Test
+ fun `query slots`() =
+ runBlocking(IMMEDIATE) {
+ assertThat(querySlots())
+ .isEqualTo(
+ listOf(
+ Slot(
+ id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
+ capacity = 1,
+ ),
+ Slot(
+ id = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
+ capacity = 1,
+ ),
+ )
+ )
+ }
+
+ @Test
+ fun `query affordances`() =
+ runBlocking(IMMEDIATE) {
+ assertThat(queryAffordances())
+ .isEqualTo(
+ listOf(
+ Affordance(
+ id = AFFORDANCE_1,
+ name = AFFORDANCE_1,
+ iconResourceId = 1,
+ ),
+ Affordance(
+ id = AFFORDANCE_2,
+ name = AFFORDANCE_2,
+ iconResourceId = 2,
+ ),
+ )
+ )
+ }
+
+ @Test
+ fun `delete and query selection`() =
+ runBlocking(IMMEDIATE) {
+ insertSelection(
+ slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
+ affordanceId = AFFORDANCE_1,
+ )
+ insertSelection(
+ slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
+ affordanceId = AFFORDANCE_2,
+ )
+
+ context.contentResolver.delete(
+ Contract.SelectionTable.URI,
+ "${Contract.SelectionTable.Columns.SLOT_ID} = ? AND" +
+ " ${Contract.SelectionTable.Columns.AFFORDANCE_ID} = ?",
+ arrayOf(
+ KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
+ AFFORDANCE_2,
+ ),
+ )
+
+ assertThat(querySelections())
+ .isEqualTo(
+ listOf(
+ Selection(
+ slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
+ affordanceId = AFFORDANCE_1,
+ )
+ )
+ )
+ }
+
+ @Test
+ fun `delete all selections in a slot`() =
+ runBlocking(IMMEDIATE) {
+ insertSelection(
+ slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
+ affordanceId = AFFORDANCE_1,
+ )
+ insertSelection(
+ slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
+ affordanceId = AFFORDANCE_2,
+ )
+
+ context.contentResolver.delete(
+ Contract.SelectionTable.URI,
+ Contract.SelectionTable.Columns.SLOT_ID,
+ arrayOf(
+ KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_END,
+ ),
+ )
+
+ assertThat(querySelections())
+ .isEqualTo(
+ listOf(
+ Selection(
+ slotId = KeyguardQuickAffordanceSlots.SLOT_ID_BOTTOM_START,
+ affordanceId = AFFORDANCE_1,
+ )
+ )
+ )
+ }
+
+ private fun insertSelection(
+ slotId: String,
+ affordanceId: String,
+ ) {
+ context.contentResolver.insert(
+ Contract.SelectionTable.URI,
+ ContentValues().apply {
+ put(Contract.SelectionTable.Columns.SLOT_ID, slotId)
+ put(Contract.SelectionTable.Columns.AFFORDANCE_ID, affordanceId)
+ }
+ )
+ }
+
+ private fun querySelections(): List<Selection> {
+ return context.contentResolver
+ .query(
+ Contract.SelectionTable.URI,
+ null,
+ null,
+ null,
+ null,
+ )
+ ?.use { cursor ->
+ buildList {
+ val slotIdColumnIndex =
+ cursor.getColumnIndex(Contract.SelectionTable.Columns.SLOT_ID)
+ val affordanceIdColumnIndex =
+ cursor.getColumnIndex(Contract.SelectionTable.Columns.AFFORDANCE_ID)
+ if (slotIdColumnIndex == -1 || affordanceIdColumnIndex == -1) {
+ return@buildList
+ }
+
+ while (cursor.moveToNext()) {
+ add(
+ Selection(
+ slotId = cursor.getString(slotIdColumnIndex),
+ affordanceId = cursor.getString(affordanceIdColumnIndex),
+ )
+ )
+ }
+ }
+ }
+ ?: emptyList()
+ }
+
+ private fun querySlots(): List<Slot> {
+ return context.contentResolver
+ .query(
+ Contract.SlotTable.URI,
+ null,
+ null,
+ null,
+ null,
+ )
+ ?.use { cursor ->
+ buildList {
+ val idColumnIndex = cursor.getColumnIndex(Contract.SlotTable.Columns.ID)
+ val capacityColumnIndex =
+ cursor.getColumnIndex(Contract.SlotTable.Columns.CAPACITY)
+ if (idColumnIndex == -1 || capacityColumnIndex == -1) {
+ return@buildList
+ }
+
+ while (cursor.moveToNext()) {
+ add(
+ Slot(
+ id = cursor.getString(idColumnIndex),
+ capacity = cursor.getInt(capacityColumnIndex),
+ )
+ )
+ }
+ }
+ }
+ ?: emptyList()
+ }
+
+ private fun queryAffordances(): List<Affordance> {
+ return context.contentResolver
+ .query(
+ Contract.AffordanceTable.URI,
+ null,
+ null,
+ null,
+ null,
+ )
+ ?.use { cursor ->
+ buildList {
+ val idColumnIndex = cursor.getColumnIndex(Contract.AffordanceTable.Columns.ID)
+ val nameColumnIndex =
+ cursor.getColumnIndex(Contract.AffordanceTable.Columns.NAME)
+ val iconColumnIndex =
+ cursor.getColumnIndex(Contract.AffordanceTable.Columns.ICON)
+ if (idColumnIndex == -1 || nameColumnIndex == -1 || iconColumnIndex == -1) {
+ return@buildList
+ }
+
+ while (cursor.moveToNext()) {
+ add(
+ Affordance(
+ id = cursor.getString(idColumnIndex),
+ name = cursor.getString(nameColumnIndex),
+ iconResourceId = cursor.getInt(iconColumnIndex),
+ )
+ )
+ }
+ }
+ }
+ ?: emptyList()
+ }
+
+ data class Slot(
+ val id: String,
+ val capacity: Int,
+ )
+
+ data class Affordance(
+ val id: String,
+ val name: String,
+ val iconResourceId: Int,
+ )
+
+ data class Selection(
+ val slotId: String,
+ val affordanceId: String,
+ )
+
+ companion object {
+ private val IMMEDIATE = Dispatchers.Main.immediate
+ private const val AFFORDANCE_1 = "affordance_1"
+ private const val AFFORDANCE_2 = "affordance_2"
+ }
+}