Merge "Add repository for controls related settings" into tm-qpr-dev

This commit is contained in:
Fabian Kozynski
2022-11-30 19:26:28 +00:00
committed by Android (Google) Code Review
9 changed files with 388 additions and 119 deletions

View File

@@ -0,0 +1,29 @@
/*
* 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.controls
import kotlinx.coroutines.flow.StateFlow
/** Repository for Device controls related settings. */
interface ControlsSettingsRepository {
/** Whether device controls activity can be shown above lockscreen for this user. */
val canShowControlsInLockscreen: StateFlow<Boolean>
/** Whether trivial controls can be actioned from the lockscreen for this user. */
val allowActionOnTrivialControlsInLockscreen: StateFlow<Boolean>
}

View File

@@ -0,0 +1,90 @@
/*
* 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.controls
import android.provider.Settings
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.qs.SettingObserver
import com.android.systemui.user.data.repository.UserRepository
import com.android.systemui.util.settings.SecureSettings
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn
/**
* This implementation uses an `@Application` [CoroutineScope] to provide hot flows for the values
* of the tracked settings.
*/
@SysUISingleton
class ControlsSettingsRepositoryImpl
@Inject
constructor(
@Application private val scope: CoroutineScope,
@Background private val backgroundDispatcher: CoroutineDispatcher,
private val userRepository: UserRepository,
private val secureSettings: SecureSettings
) : ControlsSettingsRepository {
override val canShowControlsInLockscreen =
makeFlowForSetting(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS)
override val allowActionOnTrivialControlsInLockscreen =
makeFlowForSetting(Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS)
@OptIn(ExperimentalCoroutinesApi::class)
private fun makeFlowForSetting(setting: String): StateFlow<Boolean> {
return userRepository.selectedUserInfo
.distinctUntilChanged()
.flatMapLatest { userInfo ->
conflatedCallbackFlow {
val observer =
object : SettingObserver(secureSettings, null, setting, userInfo.id) {
override fun handleValueChanged(
value: Int,
observedChange: Boolean
) {
trySend(value == 1)
}
}
observer.isListening = true
trySend(observer.value == 1)
awaitClose { observer.isListening = false }
}
.flowOn(backgroundDispatcher)
.distinctUntilChanged()
}
.stateIn(
scope,
started = SharingStarted.Eagerly,
// When the observer starts listening, the flow will emit the current value
// so the initialValue here is irrelevant.
initialValue = false,
)
}
}

View File

@@ -16,13 +16,10 @@
package com.android.systemui.controls.dagger
import android.content.ContentResolver
import android.content.Context
import android.database.ContentObserver
import android.os.UserHandle
import android.provider.Settings
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
import com.android.systemui.controls.ControlsSettingsRepository
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.controls.controller.ControlsTileResourceConfiguration
import com.android.systemui.controls.controller.ControlsTileResourceConfigurationImpl
@@ -31,12 +28,10 @@ import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.settings.SecureSettings
import dagger.Lazy
import kotlinx.coroutines.flow.StateFlow
import java.util.Optional
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
/**
* Pseudo-component to inject into classes outside `com.android.systemui.controls`.
@@ -46,47 +41,26 @@ import kotlinx.coroutines.flow.asStateFlow
*/
@SysUISingleton
class ControlsComponent @Inject constructor(
@ControlsFeatureEnabled private val featureEnabled: Boolean,
private val context: Context,
private val lazyControlsController: Lazy<ControlsController>,
private val lazyControlsUiController: Lazy<ControlsUiController>,
private val lazyControlsListingController: Lazy<ControlsListingController>,
private val lockPatternUtils: LockPatternUtils,
private val keyguardStateController: KeyguardStateController,
private val userTracker: UserTracker,
private val secureSettings: SecureSettings,
private val optionalControlsTileResourceConfiguration:
Optional<ControlsTileResourceConfiguration>
@ControlsFeatureEnabled private val featureEnabled: Boolean,
private val context: Context,
private val lazyControlsController: Lazy<ControlsController>,
private val lazyControlsUiController: Lazy<ControlsUiController>,
private val lazyControlsListingController: Lazy<ControlsListingController>,
private val lockPatternUtils: LockPatternUtils,
private val keyguardStateController: KeyguardStateController,
private val userTracker: UserTracker,
controlsSettingsRepository: ControlsSettingsRepository,
optionalControlsTileResourceConfiguration: Optional<ControlsTileResourceConfiguration>
) {
private val contentResolver: ContentResolver
get() = context.contentResolver
private val _canShowWhileLockedSetting = MutableStateFlow(false)
val canShowWhileLockedSetting = _canShowWhileLockedSetting.asStateFlow()
val canShowWhileLockedSetting: StateFlow<Boolean> =
controlsSettingsRepository.canShowControlsInLockscreen
private val controlsTileResourceConfiguration: ControlsTileResourceConfiguration =
optionalControlsTileResourceConfiguration.orElse(
ControlsTileResourceConfigurationImpl()
)
val showWhileLockedObserver = object : ContentObserver(null) {
override fun onChange(selfChange: Boolean) {
updateShowWhileLocked()
}
}
init {
if (featureEnabled) {
secureSettings.registerContentObserverForUser(
Settings.Secure.getUriFor(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS),
false, /* notifyForDescendants */
showWhileLockedObserver,
UserHandle.USER_ALL
)
updateShowWhileLocked()
}
}
fun getControlsController(): Optional<ControlsController> {
return if (featureEnabled) Optional.of(lazyControlsController.get()) else Optional.empty()
}
@@ -127,11 +101,6 @@ class ControlsComponent @Inject constructor(
return Visibility.AVAILABLE
}
private fun updateShowWhileLocked() {
_canShowWhileLockedSetting.value = secureSettings.getIntForUser(
Settings.Secure.LOCKSCREEN_SHOW_CONTROLS, 0, UserHandle.USER_CURRENT) != 0
}
enum class Visibility {
AVAILABLE, AVAILABLE_AFTER_UNLOCK, UNAVAILABLE
}

View File

@@ -20,6 +20,8 @@ import android.app.Activity
import android.content.pm.PackageManager
import com.android.systemui.controls.ControlsMetricsLogger
import com.android.systemui.controls.ControlsMetricsLoggerImpl
import com.android.systemui.controls.ControlsSettingsRepository
import com.android.systemui.controls.ControlsSettingsRepositoryImpl
import com.android.systemui.controls.controller.ControlsBindingController
import com.android.systemui.controls.controller.ControlsBindingControllerImpl
import com.android.systemui.controls.controller.ControlsController
@@ -82,6 +84,11 @@ abstract class ControlsModule {
@Binds
abstract fun provideUiController(controller: ControlsUiControllerImpl): ControlsUiController
@Binds
abstract fun provideSettingsManager(
manager: ControlsSettingsRepositoryImpl
): ControlsSettingsRepository
@Binds
abstract fun provideMetricsLogger(logger: ControlsMetricsLoggerImpl): ControlsMetricsLogger

View File

@@ -24,9 +24,6 @@ import android.app.PendingIntent
import android.content.Context
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.database.ContentObserver
import android.net.Uri
import android.os.Handler
import android.os.UserHandle
import android.os.VibrationEffect
import android.provider.Settings.Secure
@@ -40,6 +37,7 @@ import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.R
import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.controls.ControlsMetricsLogger
import com.android.systemui.controls.ControlsSettingsRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
@@ -68,17 +66,17 @@ class ControlActionCoordinatorImpl @Inject constructor(
private val vibrator: VibratorHelper,
private val secureSettings: SecureSettings,
private val userContextProvider: UserContextProvider,
@Main mainHandler: Handler
private val controlsSettingsRepository: ControlsSettingsRepository,
) : ControlActionCoordinator {
private var dialog: Dialog? = null
private var pendingAction: Action? = null
private var actionsInProgress = mutableSetOf<String>()
private val isLocked: Boolean
get() = !keyguardStateController.isUnlocked()
private var mAllowTrivialControls: Boolean = secureSettings.getIntForUser(
Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS, 0, UserHandle.USER_CURRENT) != 0
private var mShowDeviceControlsInLockscreen: Boolean = secureSettings.getIntForUser(
Secure.LOCKSCREEN_SHOW_CONTROLS, 0, UserHandle.USER_CURRENT) != 0
private val allowTrivialControls: Boolean
get() = controlsSettingsRepository.allowActionOnTrivialControlsInLockscreen.value
private val showDeviceControlsInLockscreen: Boolean
get() = controlsSettingsRepository.canShowControlsInLockscreen.value
override lateinit var activityContext: Context
companion object {
@@ -86,38 +84,6 @@ class ControlActionCoordinatorImpl @Inject constructor(
private const val MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG = 2
}
init {
val lockScreenShowControlsUri =
secureSettings.getUriFor(Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS)
val showControlsUri =
secureSettings.getUriFor(Secure.LOCKSCREEN_SHOW_CONTROLS)
val controlsContentObserver = object : ContentObserver(mainHandler) {
override fun onChange(selfChange: Boolean, uri: Uri?) {
super.onChange(selfChange, uri)
when (uri) {
lockScreenShowControlsUri -> {
mAllowTrivialControls = secureSettings.getIntForUser(
Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS,
0, UserHandle.USER_CURRENT) != 0
}
showControlsUri -> {
mShowDeviceControlsInLockscreen = secureSettings
.getIntForUser(Secure.LOCKSCREEN_SHOW_CONTROLS,
0, UserHandle.USER_CURRENT) != 0
}
}
}
}
secureSettings.registerContentObserverForUser(
lockScreenShowControlsUri,
false /* notifyForDescendants */, controlsContentObserver, UserHandle.USER_ALL
)
secureSettings.registerContentObserverForUser(
showControlsUri,
false /* notifyForDescendants */, controlsContentObserver, UserHandle.USER_ALL
)
}
override fun closeDialogs() {
dialog?.dismiss()
dialog = null
@@ -224,7 +190,7 @@ class ControlActionCoordinatorImpl @Inject constructor(
@AnyThread
@VisibleForTesting
fun bouncerOrRun(action: Action) {
val authRequired = action.authIsRequired || !mAllowTrivialControls
val authRequired = action.authIsRequired || !allowTrivialControls
if (keyguardStateController.isShowing() && authRequired) {
if (isLocked) {
@@ -282,7 +248,7 @@ class ControlActionCoordinatorImpl @Inject constructor(
PREFS_CONTROLS_FILE, Context.MODE_PRIVATE)
val attempts = prefs.getInt(PREFS_SETTINGS_DIALOG_ATTEMPTS, 0)
if (attempts >= MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG ||
(mShowDeviceControlsInLockscreen && mAllowTrivialControls)) {
(showDeviceControlsInLockscreen && allowTrivialControls)) {
return
}
val builder = AlertDialog
@@ -304,7 +270,7 @@ class ControlActionCoordinatorImpl @Inject constructor(
true
}
if (mShowDeviceControlsInLockscreen) {
if (showDeviceControlsInLockscreen) {
dialog = builder
.setTitle(R.string.controls_settings_trivial_controls_dialog_title)
.setMessage(R.string.controls_settings_trivial_controls_dialog_message)

View File

@@ -0,0 +1,187 @@
/*
* 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.controls
import android.content.pm.UserInfo
import android.provider.Settings
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.util.settings.FakeSettings
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@SmallTest
@RunWith(JUnit4::class)
@OptIn(ExperimentalCoroutinesApi::class)
class ControlsSettingsRepositoryImplTest : SysuiTestCase() {
companion object {
private const val LOCKSCREEN_SHOW = Settings.Secure.LOCKSCREEN_SHOW_CONTROLS
private const val LOCKSCREEN_ACTION = Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS
private fun createUser(id: Int): UserInfo {
return UserInfo(id, "user_$id", 0)
}
private val ALL_USERS = (0..1).map { it to createUser(it) }.toMap()
}
private lateinit var underTest: ControlsSettingsRepository
private lateinit var testScope: TestScope
private lateinit var secureSettings: FakeSettings
private lateinit var userRepository: FakeUserRepository
@Before
fun setUp() {
secureSettings = FakeSettings()
userRepository = FakeUserRepository()
userRepository.setUserInfos(ALL_USERS.values.toList())
val coroutineDispatcher = UnconfinedTestDispatcher()
testScope = TestScope(coroutineDispatcher)
underTest =
ControlsSettingsRepositoryImpl(
scope = testScope.backgroundScope,
backgroundDispatcher = coroutineDispatcher,
userRepository = userRepository,
secureSettings = secureSettings,
)
}
@Test
fun showInLockScreen() =
testScope.runTest {
setUser(0)
val values = mutableListOf<Boolean>()
val job =
launch(UnconfinedTestDispatcher()) {
underTest.canShowControlsInLockscreen.toList(values)
}
assertThat(values.last()).isFalse()
secureSettings.putBool(LOCKSCREEN_SHOW, true)
assertThat(values.last()).isTrue()
secureSettings.putBool(LOCKSCREEN_SHOW, false)
assertThat(values.last()).isFalse()
secureSettings.putBoolForUser(LOCKSCREEN_SHOW, true, 1)
assertThat(values.last()).isFalse()
setUser(1)
assertThat(values.last()).isTrue()
job.cancel()
}
@Test
fun showInLockScreen_changesInOtherUsersAreNotQueued() =
testScope.runTest {
setUser(0)
val values = mutableListOf<Boolean>()
val job =
launch(UnconfinedTestDispatcher()) {
underTest.canShowControlsInLockscreen.toList(values)
}
secureSettings.putBoolForUser(LOCKSCREEN_SHOW, true, 1)
secureSettings.putBoolForUser(LOCKSCREEN_SHOW, false, 1)
setUser(1)
assertThat(values.last()).isFalse()
assertThat(values).containsNoneIn(listOf(true))
job.cancel()
}
@Test
fun actionInLockScreen() =
testScope.runTest {
setUser(0)
val values = mutableListOf<Boolean>()
val job =
launch(UnconfinedTestDispatcher()) {
underTest.allowActionOnTrivialControlsInLockscreen.toList(values)
}
assertThat(values.last()).isFalse()
secureSettings.putBool(LOCKSCREEN_ACTION, true)
assertThat(values.last()).isTrue()
secureSettings.putBool(LOCKSCREEN_ACTION, false)
assertThat(values.last()).isFalse()
secureSettings.putBoolForUser(LOCKSCREEN_ACTION, true, 1)
assertThat(values.last()).isFalse()
setUser(1)
assertThat(values.last()).isTrue()
job.cancel()
}
@Test
fun actionInLockScreen_changesInOtherUsersAreNotQueued() =
testScope.runTest {
setUser(0)
val values = mutableListOf<Boolean>()
val job =
launch(UnconfinedTestDispatcher()) {
underTest.allowActionOnTrivialControlsInLockscreen.toList(values)
}
secureSettings.putBoolForUser(LOCKSCREEN_ACTION, true, 1)
secureSettings.putBoolForUser(LOCKSCREEN_ACTION, false, 1)
setUser(1)
assertThat(values.last()).isFalse()
assertThat(values).containsNoneIn(listOf(true))
job.cancel()
}
@Test
fun valueIsUpdatedWhenNotSubscribed() =
testScope.runTest {
setUser(0)
assertThat(underTest.canShowControlsInLockscreen.value).isFalse()
secureSettings.putBool(LOCKSCREEN_SHOW, true)
assertThat(underTest.canShowControlsInLockscreen.value).isTrue()
}
private suspend fun setUser(id: Int) {
secureSettings.userId = id
userRepository.setSelectedUserInfo(ALL_USERS[id]!!)
}
}

View File

@@ -0,0 +1,37 @@
/*
* 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.controls
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
class FakeControlsSettingsRepository : ControlsSettingsRepository {
private val _canShowControlsInLockscreen = MutableStateFlow(false)
override val canShowControlsInLockscreen = _canShowControlsInLockscreen.asStateFlow()
private val _allowActionOnTrivialControlsInLockscreen = MutableStateFlow(false)
override val allowActionOnTrivialControlsInLockscreen =
_allowActionOnTrivialControlsInLockscreen.asStateFlow()
fun setCanShowControlsInLockscreen(value: Boolean) {
_canShowControlsInLockscreen.value = value
}
fun setAllowActionOnTrivialControlsInLockscreen(value: Boolean) {
_allowActionOnTrivialControlsInLockscreen.value = value
}
}

View File

@@ -18,30 +18,24 @@ package com.android.systemui.controls.ui
import android.content.Context
import android.content.SharedPreferences
import android.database.ContentObserver
import android.net.Uri
import android.os.Handler
import android.os.UserHandle
import android.provider.Settings
import android.test.suitebuilder.annotation.SmallTest
import android.testing.AndroidTestingRunner
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.controls.ControlsMetricsLogger
import com.android.systemui.controls.FakeControlsSettingsRepository
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.settings.UserContextProvider
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.settings.SecureSettings
import com.android.wm.shell.TaskViewFactory
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Answers
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.`when`
@@ -79,8 +73,6 @@ class ControlActionCoordinatorImplTest : SysuiTestCase() {
@Mock
private lateinit var secureSettings: SecureSettings
@Mock
private lateinit var mainHandler: Handler
@Mock
private lateinit var userContextProvider: UserContextProvider
companion object {
@@ -91,17 +83,15 @@ class ControlActionCoordinatorImplTest : SysuiTestCase() {
private lateinit var coordinator: ControlActionCoordinatorImpl
private lateinit var action: ControlActionCoordinatorImpl.Action
private lateinit var controlsSettingsRepository: FakeControlsSettingsRepository
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
`when`(secureSettings.getUriFor(Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS))
.thenReturn(Settings.Secure
.getUriFor(Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS))
`when`(secureSettings.getIntForUser(Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS,
0, UserHandle.USER_CURRENT))
.thenReturn(1)
controlsSettingsRepository = FakeControlsSettingsRepository()
controlsSettingsRepository.setAllowActionOnTrivialControlsInLockscreen(true)
controlsSettingsRepository.setCanShowControlsInLockscreen(true)
coordinator = spy(ControlActionCoordinatorImpl(
mContext,
@@ -115,7 +105,7 @@ class ControlActionCoordinatorImplTest : SysuiTestCase() {
vibratorHelper,
secureSettings,
userContextProvider,
mainHandler
controlsSettingsRepository
))
val userContext = mock(Context::class.java)
@@ -128,9 +118,6 @@ class ControlActionCoordinatorImplTest : SysuiTestCase() {
`when`(pref.getInt(DeviceControlsControllerImpl.PREFS_SETTINGS_DIALOG_ATTEMPTS, 0))
.thenReturn(2)
verify(secureSettings).registerContentObserverForUser(any(Uri::class.java),
anyBoolean(), any(ContentObserver::class.java), anyInt())
`when`(cvh.cws.ci.controlId).thenReturn(ID)
`when`(cvh.cws.control?.isAuthRequired()).thenReturn(true)
action = spy(coordinator.Action(ID, {}, false, true))

View File

@@ -17,19 +17,18 @@
package com.android.systemui.controls.dagger
import android.testing.AndroidTestingRunner
import android.provider.Settings
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
import com.android.systemui.SysuiTestCase
import com.android.systemui.controls.FakeControlsSettingsRepository
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.controls.controller.ControlsTileResourceConfiguration
import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.settings.SecureSettings
import dagger.Lazy
import java.util.Optional
import org.junit.Assert.assertEquals
@@ -63,13 +62,13 @@ class ControlsComponentTest : SysuiTestCase() {
@Mock
private lateinit var lockPatternUtils: LockPatternUtils
@Mock
private lateinit var secureSettings: SecureSettings
@Mock
private lateinit var optionalControlsTileResourceConfiguration:
Optional<ControlsTileResourceConfiguration>
@Mock
private lateinit var controlsTileResourceConfiguration: ControlsTileResourceConfiguration
private lateinit var controlsSettingsRepository: FakeControlsSettingsRepository
companion object {
fun <T> eq(value: T): T = Mockito.eq(value) ?: value
}
@@ -78,6 +77,8 @@ class ControlsComponentTest : SysuiTestCase() {
fun setUp() {
MockitoAnnotations.initMocks(this)
controlsSettingsRepository = FakeControlsSettingsRepository()
`when`(userTracker.userHandle.identifier).thenReturn(0)
`when`(optionalControlsTileResourceConfiguration.orElse(any()))
.thenReturn(controlsTileResourceConfiguration)
@@ -125,8 +126,7 @@ class ControlsComponentTest : SysuiTestCase() {
`when`(lockPatternUtils.getStrongAuthForUser(anyInt()))
.thenReturn(STRONG_AUTH_NOT_REQUIRED)
`when`(keyguardStateController.isUnlocked()).thenReturn(false)
`when`(secureSettings.getInt(eq(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS), anyInt()))
.thenReturn(0)
controlsSettingsRepository.setCanShowControlsInLockscreen(false)
val component = setupComponent(true)
assertEquals(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK, component.getVisibility())
@@ -137,9 +137,7 @@ class ControlsComponentTest : SysuiTestCase() {
`when`(lockPatternUtils.getStrongAuthForUser(anyInt()))
.thenReturn(STRONG_AUTH_NOT_REQUIRED)
`when`(keyguardStateController.isUnlocked()).thenReturn(false)
`when`(secureSettings.getIntForUser(eq(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS),
anyInt(), anyInt()))
.thenReturn(1)
controlsSettingsRepository.setCanShowControlsInLockscreen(true)
val component = setupComponent(true)
assertEquals(ControlsComponent.Visibility.AVAILABLE, component.getVisibility())
@@ -147,8 +145,7 @@ class ControlsComponentTest : SysuiTestCase() {
@Test
fun testFeatureEnabledAndCanShowWhileUnlockedVisibility() {
`when`(secureSettings.getInt(eq(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS), anyInt()))
.thenReturn(0)
controlsSettingsRepository.setCanShowControlsInLockscreen(false)
`when`(lockPatternUtils.getStrongAuthForUser(anyInt()))
.thenReturn(STRONG_AUTH_NOT_REQUIRED)
`when`(keyguardStateController.isUnlocked()).thenReturn(true)
@@ -187,7 +184,7 @@ class ControlsComponentTest : SysuiTestCase() {
lockPatternUtils,
keyguardStateController,
userTracker,
secureSettings,
controlsSettingsRepository,
optionalControlsTileResourceConfiguration
)
}