Merge "Add onTrustManagedChanged state to TrustRepository" into udc-dev

This commit is contained in:
Chandru S
2023-05-09 22:42:09 +00:00
committed by Android (Google) Code Review
5 changed files with 193 additions and 47 deletions

View File

@@ -17,9 +17,11 @@
package com.android.keyguard.logging
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.TrustManagedModel
import com.android.systemui.keyguard.shared.model.TrustModel
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogLevel
import com.android.systemui.log.LogLevel.DEBUG
import com.android.systemui.log.dagger.KeyguardUpdateMonitorLog
import javax.inject.Inject
@@ -39,7 +41,7 @@ constructor(
) {
logBuffer.log(
TAG,
LogLevel.DEBUG,
DEBUG,
{
bool1 = enabled
bool2 = newlyUnlocked
@@ -65,7 +67,7 @@ constructor(
fun trustModelEmitted(value: TrustModel) {
logBuffer.log(
TAG,
LogLevel.DEBUG,
DEBUG,
{
int1 = value.userId
bool1 = value.isTrusted
@@ -77,12 +79,40 @@ constructor(
fun isCurrentUserTrusted(isCurrentUserTrusted: Boolean) {
logBuffer.log(
TAG,
LogLevel.DEBUG,
DEBUG,
{ bool1 = isCurrentUserTrusted },
{ "isCurrentUserTrusted emitted: $bool1" }
)
}
fun isCurrentUserTrustManaged(isTrustManaged: Boolean) {
logBuffer.log(TAG, DEBUG, { bool1 = isTrustManaged }, { "isTrustManaged emitted: $bool1" })
}
fun onTrustManagedChanged(trustManaged: Boolean, userId: Int) {
logBuffer.log(
TAG,
DEBUG,
{
bool1 = trustManaged
int1 = userId
},
{ "onTrustManagedChanged isTrustManaged: $bool1 for user: $int1" }
)
}
fun trustManagedModelEmitted(it: TrustManagedModel) {
logBuffer.log(
TAG,
DEBUG,
{
bool1 = it.isTrustManaged
int1 = it.userId
},
{ "trustManagedModel emitted: userId: $int1, isTrustManaged: $bool1" }
)
}
companion object {
const val TAG = "TrustRepositoryLog"
}

View File

@@ -22,6 +22,7 @@ import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLoggin
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.keyguard.shared.model.TrustManagedModel
import com.android.systemui.keyguard.shared.model.TrustModel
import com.android.systemui.user.data.repository.UserRepository
import javax.inject.Inject
@@ -37,6 +38,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
/** Encapsulates any state relevant to trust agents and trust grants. */
interface TrustRepository {
@@ -45,6 +47,9 @@ interface TrustRepository {
/** Flow representing whether active unlock is available for the current user. */
val isCurrentUserActiveUnlockAvailable: StateFlow<Boolean>
/** Reports that whether trust is managed has changed for the current user. */
val isCurrentUserTrustManaged: StateFlow<Boolean>
}
@SysUISingleton
@@ -57,6 +62,7 @@ constructor(
private val logger: TrustRepositoryLogger,
) : TrustRepository {
private val latestTrustModelForUser = mutableMapOf<Int, TrustModel>()
private val trustManagedForUser = mutableMapOf<Int, TrustManagedModel>()
private val trust =
conflatedCallbackFlow {
@@ -79,9 +85,16 @@ constructor(
override fun onTrustError(message: CharSequence?) = Unit
override fun onTrustManagedChanged(enabled: Boolean, userId: Int) = Unit
override fun onEnabledTrustAgentsChanged(userId: Int) = Unit
override fun onTrustManagedChanged(isTrustManaged: Boolean, userId: Int) {
logger.onTrustManagedChanged(isTrustManaged, userId)
trySendWithFailureLogging(
TrustManagedModel(userId, isTrustManaged),
TrustRepositoryLogger.TAG,
"onTrustManagedChanged"
)
}
}
trustManager.registerTrustListener(callback)
logger.trustListenerRegistered()
@@ -91,18 +104,43 @@ constructor(
}
}
.onEach {
latestTrustModelForUser[it.userId] = it
logger.trustModelEmitted(it)
when (it) {
is TrustModel -> {
latestTrustModelForUser[it.userId] = it
logger.trustModelEmitted(it)
}
is TrustManagedModel -> {
trustManagedForUser[it.userId] = it
logger.trustManagedModelEmitted(it)
}
}
}
.shareIn(applicationScope, started = SharingStarted.Eagerly, replay = 1)
override val isCurrentUserTrusted: Flow<Boolean> =
combine(trust, userRepository.selectedUserInfo, ::Pair)
.map { latestTrustModelForUser[it.second.id]?.isTrusted ?: false }
.distinctUntilChanged()
.onEach { logger.isCurrentUserTrusted(it) }
.onStart { emit(false) }
// TODO: Implement based on TrustManager callback b/267322286
override val isCurrentUserActiveUnlockAvailable: StateFlow<Boolean> = MutableStateFlow(true)
override val isCurrentUserTrustManaged: StateFlow<Boolean>
get() =
combine(trust, userRepository.selectedUserInfo, ::Pair)
.map { isUserTrustManaged(it.second.id) }
.distinctUntilChanged()
.onEach { logger.isCurrentUserTrustManaged(it) }
.onStart { emit(false) }
.stateIn(
scope = applicationScope,
started = SharingStarted.WhileSubscribed(),
initialValue = false
)
private fun isUserTrustManaged(userId: Int) =
trustManagedForUser[userId]?.isTrustManaged ?: false
override val isCurrentUserTrusted: Flow<Boolean>
get() =
combine(trust, userRepository.selectedUserInfo, ::Pair)
.map { latestTrustModelForUser[it.second.id]?.isTrusted ?: false }
.distinctUntilChanged()
.onEach { logger.isCurrentUserTrusted(it) }
.onStart { emit(false) }
}

View File

@@ -16,10 +16,18 @@
package com.android.systemui.keyguard.shared.model
sealed class TrustMessage
/** Represents the trust state */
data class TrustModel(
/** If true, the system believes the environment to be trusted. */
val isTrusted: Boolean,
/** The user, for which the trust changed. */
val userId: Int,
)
) : TrustMessage()
/** Represents where trust agents are enabled for a particular user. */
data class TrustManagedModel(
val userId: Int,
val isTrustManaged: Boolean,
) : TrustMessage()

View File

@@ -23,6 +23,7 @@ import androidx.test.filters.SmallTest
import com.android.keyguard.logging.TrustRepositoryLogger
import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.FlowValue
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogcatEchoTracker
@@ -48,12 +49,14 @@ import org.mockito.MockitoAnnotations
@RunWith(AndroidJUnit4::class)
class TrustRepositoryTest : SysuiTestCase() {
@Mock private lateinit var trustManager: TrustManager
@Captor private lateinit var listenerCaptor: ArgumentCaptor<TrustManager.TrustListener>
@Captor private lateinit var listener: ArgumentCaptor<TrustManager.TrustListener>
private lateinit var userRepository: FakeUserRepository
private lateinit var testScope: TestScope
private val users = listOf(UserInfo(1, "user 1", 0), UserInfo(2, "user 1", 0))
private lateinit var underTest: TrustRepository
private lateinit var isCurrentUserTrusted: FlowValue<Boolean?>
private lateinit var isCurrentUserTrustManaged: FlowValue<Boolean?>
@Before
fun setUp() {
@@ -70,21 +73,90 @@ class TrustRepositoryTest : SysuiTestCase() {
TrustRepositoryImpl(testScope.backgroundScope, userRepository, trustManager, logger)
}
fun TestScope.init() {
runCurrent()
verify(trustManager).registerTrustListener(listener.capture())
isCurrentUserTrustManaged = collectLastValue(underTest.isCurrentUserTrustManaged)
isCurrentUserTrusted = collectLastValue(underTest.isCurrentUserTrusted)
}
@Test
fun isCurrentUserTrusted_whenTrustChanges_emitsLatestValue() =
fun isCurrentUserTrustManaged_whenItChanges_emitsLatestValue() =
testScope.runTest {
runCurrent()
verify(trustManager).registerTrustListener(listenerCaptor.capture())
val listener = listenerCaptor.value
init()
val currentUserId = users[0].id
userRepository.setSelectedUserInfo(users[0])
val isCurrentUserTrusted = collectLastValue(underTest.isCurrentUserTrusted)
listener.onTrustChanged(true, false, currentUserId, 0, emptyList())
listener.value.onTrustManagedChanged(true, currentUserId)
assertThat(isCurrentUserTrustManaged()).isTrue()
listener.value.onTrustManagedChanged(false, currentUserId)
assertThat(isCurrentUserTrustManaged()).isFalse()
}
@Test
fun isCurrentUserTrustManaged_isFalse_byDefault() =
testScope.runTest {
runCurrent()
assertThat(collectLastValue(underTest.isCurrentUserTrustManaged)()).isFalse()
}
@Test
fun isCurrentUserTrustManaged_whenItChangesForDifferentUser_noops() =
testScope.runTest {
init()
userRepository.setSelectedUserInfo(users[0])
// current user's trust is managed.
listener.value.onTrustManagedChanged(true, users[0].id)
// some other user's trust is not managed.
listener.value.onTrustManagedChanged(false, users[1].id)
assertThat(isCurrentUserTrustManaged()).isTrue()
}
@Test
fun isCurrentUserTrustManaged_whenUserChangesWithoutRecentTrustChange_defaultsToFalse() =
testScope.runTest {
init()
userRepository.setSelectedUserInfo(users[0])
listener.value.onTrustManagedChanged(true, users[0].id)
userRepository.setSelectedUserInfo(users[1])
assertThat(isCurrentUserTrustManaged()).isFalse()
}
@Test
fun isCurrentUserTrustManaged_itChangesFirstBeforeUserInfoChanges_emitsCorrectValue() =
testScope.runTest {
init()
userRepository.setSelectedUserInfo(users[1])
listener.value.onTrustManagedChanged(true, users[0].id)
assertThat(isCurrentUserTrustManaged()).isFalse()
userRepository.setSelectedUserInfo(users[0])
assertThat(isCurrentUserTrustManaged()).isTrue()
}
@Test
fun isCurrentUserTrusted_whenTrustChanges_emitsLatestValue() =
testScope.runTest {
init()
val currentUserId = users[0].id
userRepository.setSelectedUserInfo(users[0])
listener.value.onTrustChanged(true, false, currentUserId, 0, emptyList())
assertThat(isCurrentUserTrusted()).isTrue()
listener.onTrustChanged(false, false, currentUserId, 0, emptyList())
listener.value.onTrustChanged(false, false, currentUserId, 0, emptyList())
assertThat(isCurrentUserTrusted()).isFalse()
}
@@ -102,16 +174,14 @@ class TrustRepositoryTest : SysuiTestCase() {
@Test
fun isCurrentUserTrusted_whenTrustChangesForDifferentUser_noop() =
testScope.runTest {
runCurrent()
verify(trustManager).registerTrustListener(listenerCaptor.capture())
userRepository.setSelectedUserInfo(users[0])
val listener = listenerCaptor.value
init()
userRepository.setSelectedUserInfo(users[0])
val isCurrentUserTrusted = collectLastValue(underTest.isCurrentUserTrusted)
// current user is trusted.
listener.onTrustChanged(true, true, users[0].id, 0, emptyList())
listener.value.onTrustChanged(true, true, users[0].id, 0, emptyList())
// some other user is not trusted.
listener.onTrustChanged(false, false, users[1].id, 0, emptyList())
listener.value.onTrustChanged(false, false, users[1].id, 0, emptyList())
assertThat(isCurrentUserTrusted()).isTrue()
}
@@ -119,29 +189,24 @@ class TrustRepositoryTest : SysuiTestCase() {
@Test
fun isCurrentUserTrusted_whenTrustChangesForCurrentUser_emitsNewValue() =
testScope.runTest {
runCurrent()
verify(trustManager).registerTrustListener(listenerCaptor.capture())
val listener = listenerCaptor.value
init()
userRepository.setSelectedUserInfo(users[0])
val isCurrentUserTrusted = collectLastValue(underTest.isCurrentUserTrusted)
listener.onTrustChanged(true, true, users[0].id, 0, emptyList())
listener.value.onTrustChanged(true, true, users[0].id, 0, emptyList())
assertThat(isCurrentUserTrusted()).isTrue()
listener.onTrustChanged(false, true, users[0].id, 0, emptyList())
listener.value.onTrustChanged(false, true, users[0].id, 0, emptyList())
assertThat(isCurrentUserTrusted()).isFalse()
}
@Test
fun isCurrentUserTrusted_whenUserChangesWithoutRecentTrustChange_defaultsToFalse() =
testScope.runTest {
runCurrent()
verify(trustManager).registerTrustListener(listenerCaptor.capture())
val listener = listenerCaptor.value
userRepository.setSelectedUserInfo(users[0])
listener.onTrustChanged(true, true, users[0].id, 0, emptyList())
init()
userRepository.setSelectedUserInfo(users[0])
listener.value.onTrustChanged(true, true, users[0].id, 0, emptyList())
val isCurrentUserTrusted = collectLastValue(underTest.isCurrentUserTrusted)
userRepository.setSelectedUserInfo(users[1])
assertThat(isCurrentUserTrusted()).isFalse()
@@ -150,12 +215,9 @@ class TrustRepositoryTest : SysuiTestCase() {
@Test
fun isCurrentUserTrusted_trustChangesFirstBeforeUserInfoChanges_emitsCorrectValue() =
testScope.runTest {
runCurrent()
verify(trustManager).registerTrustListener(listenerCaptor.capture())
val listener = listenerCaptor.value
val isCurrentUserTrusted = collectLastValue(underTest.isCurrentUserTrusted)
init()
listener.onTrustChanged(true, true, users[0].id, 0, emptyList())
listener.value.onTrustChanged(true, true, users[0].id, 0, emptyList())
assertThat(isCurrentUserTrusted()).isFalse()
userRepository.setSelectedUserInfo(users[0])

View File

@@ -31,10 +31,18 @@ class FakeTrustRepository : TrustRepository {
override val isCurrentUserActiveUnlockAvailable: StateFlow<Boolean> =
_isCurrentUserActiveUnlockAvailable.asStateFlow()
private val _isCurrentUserTrustManaged = MutableStateFlow(false)
override val isCurrentUserTrustManaged: StateFlow<Boolean>
get() = _isCurrentUserTrustManaged
fun setCurrentUserTrusted(trust: Boolean) {
_isCurrentUserTrusted.value = trust
}
fun setCurrentUserTrustManaged(value: Boolean) {
_isCurrentUserTrustManaged.value = value
}
fun setCurrentUserActiveUnlockAvailable(available: Boolean) {
_isCurrentUserActiveUnlockAvailable.value = available
}