Merge "KeyguardBottomAreaView new impl. - domain layer" into tm-qpr-dev

This commit is contained in:
TreeHugger Robot
2022-08-01 21:38:06 +00:00
committed by Android (Google) Code Review
17 changed files with 878 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
/*
* 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.common.domain.model
import com.android.systemui.common.data.model.Position as DataLayerPosition
/** Models a two-dimensional position */
data class Position(
val x: Int,
val y: Int,
) {
companion object {
fun DataLayerPosition.toDomainLayer(): Position {
return Position(
x = x,
y = y,
)
}
}
}

View File

@@ -43,6 +43,7 @@ import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.data.repository.KeyguardRepositoryModule;
import com.android.systemui.keyguard.domain.usecase.KeyguardUseCaseModule;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -70,6 +71,7 @@ import dagger.Provides;
includes = {
FalsingModule.class,
KeyguardRepositoryModule.class,
KeyguardUseCaseModule.class,
})
public class KeyguardModule {
/**

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.keyguard.domain.usecase
import dagger.Binds
import dagger.Module
@Module
interface KeyguardUseCaseModule {
@Binds
fun launchQuickAffordance(
impl: LaunchKeyguardQuickAffordanceUseCaseImpl
): LaunchKeyguardQuickAffordanceUseCase
}

View File

@@ -0,0 +1,76 @@
/*
* 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.domain.usecase
import android.content.Intent
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.StrongAuthFlags
import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.policy.KeyguardStateController
import javax.inject.Inject
/** Defines interface for classes that can launch a quick affordance. */
interface LaunchKeyguardQuickAffordanceUseCase {
operator fun invoke(
intent: Intent,
canShowWhileLocked: Boolean,
animationController: ActivityLaunchAnimator.Controller?,
)
}
/** Real implementation of [LaunchKeyguardQuickAffordanceUseCase] */
class LaunchKeyguardQuickAffordanceUseCaseImpl
@Inject
constructor(
private val lockPatternUtils: LockPatternUtils,
private val keyguardStateController: KeyguardStateController,
private val userTracker: UserTracker,
private val activityStarter: ActivityStarter,
) : LaunchKeyguardQuickAffordanceUseCase {
override operator fun invoke(
intent: Intent,
canShowWhileLocked: Boolean,
animationController: ActivityLaunchAnimator.Controller?,
) {
@StrongAuthFlags
val strongAuthFlags =
lockPatternUtils.getStrongAuthForUser(userTracker.userHandle.identifier)
val needsToUnlockFirst =
when {
strongAuthFlags ==
LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT -> true
!canShowWhileLocked && !keyguardStateController.isUnlocked -> true
else -> false
}
if (needsToUnlockFirst) {
activityStarter.postStartActivityDismissingKeyguard(
intent,
0 /* delay */,
animationController
)
} else {
activityStarter.startActivity(
intent,
true /* dismissShade */,
animationController,
true /* showOverLockscreenWhenLocked */,
)
}
}
}

View File

@@ -0,0 +1,32 @@
/*
* 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.domain.usecase
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
/** Use-case for observing whether doze state transitions should animate the bottom area */
class ObserveAnimateBottomAreaTransitionsUseCase
@Inject
constructor(
private val repository: KeyguardRepository,
) {
operator fun invoke(): Flow<Boolean> {
return repository.animateBottomAreaDozingTransitions
}
}

View File

@@ -0,0 +1,32 @@
/*
* 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.domain.usecase
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
/** Use-case for observing the alpha of the bottom area */
class ObserveBottomAreaAlphaUseCase
@Inject
constructor(
private val repository: KeyguardRepository,
) {
operator fun invoke(): Flow<Float> {
return repository.bottomAreaAlpha
}
}

View File

@@ -0,0 +1,35 @@
/*
* 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.domain.usecase
import com.android.systemui.common.domain.model.Position
import com.android.systemui.common.domain.model.Position.Companion.toDomainLayer
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
/** Use-case for observing the position of the clock. */
class ObserveClockPositionUseCase
@Inject
constructor(
private val repository: KeyguardRepository,
) {
operator fun invoke(): Flow<Position> {
return repository.clockPosition.map { it.toDomainLayer() }
}
}

View File

@@ -0,0 +1,32 @@
/*
* 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.domain.usecase
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
/** Use-case for observing the amount of doze the system is in. */
class ObserveDozeAmountUseCase
@Inject
constructor(
private val repository: KeyguardRepository,
) {
operator fun invoke(): Flow<Float> {
return repository.dozeAmount
}
}

View File

@@ -0,0 +1,32 @@
/*
* 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.domain.usecase
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
/** Use-case for observing whether we are dozing. */
class ObserveIsDozingUseCase
@Inject
constructor(
private val repository: KeyguardRepository,
) {
operator fun invoke(): Flow<Boolean> {
return repository.isDozing
}
}

View File

@@ -0,0 +1,49 @@
/*
* 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.domain.usecase
import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordanceModel
import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePosition
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
/** Use-case for observing the model of a quick affordance in the keyguard. */
class ObserveKeyguardQuickAffordanceUseCase
@Inject
constructor(
private val repository: KeyguardQuickAffordanceRepository,
private val isDozingUseCase: ObserveIsDozingUseCase,
private val dozeAmountUseCase: ObserveDozeAmountUseCase,
) {
operator fun invoke(
position: KeyguardQuickAffordancePosition
): Flow<KeyguardQuickAffordanceModel> {
return combine(
repository.affordance(position),
isDozingUseCase(),
dozeAmountUseCase(),
) { affordance, isDozing, dozeAmount ->
if (!isDozing && dozeAmount == 0f) {
affordance
} else {
KeyguardQuickAffordanceModel.Hidden
}
}
}
}

View File

@@ -0,0 +1,49 @@
/*
* 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.domain.usecase
import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.keyguard.data.config.KeyguardQuickAffordanceConfigs
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.OnClickedResult
import javax.inject.Inject
import kotlin.reflect.KClass
/** Use-case for handling a click on a keyguard quick affordance (e.g. bottom button). */
class OnKeyguardQuickAffordanceClickedUseCase
@Inject
constructor(
private val configs: KeyguardQuickAffordanceConfigs,
private val launchAffordanceUseCase: LaunchKeyguardQuickAffordanceUseCase,
) {
operator fun invoke(
configKey: KClass<*>,
animationController: ActivityLaunchAnimator.Controller?,
) {
@Suppress("UNCHECKED_CAST")
val config = configs.get(configKey as KClass<out KeyguardQuickAffordanceConfig>)
when (val result = config.onQuickAffordanceClicked(animationController)) {
is OnClickedResult.StartActivity ->
launchAffordanceUseCase(
intent = result.intent,
canShowWhileLocked = result.canShowWhileLocked,
animationController = animationController
)
is OnClickedResult.Handled -> Unit
}
}
}

View File

@@ -0,0 +1,31 @@
/*
* 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.domain.usecase
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import javax.inject.Inject
/** Use-case for setting the updated clock position. */
class SetClockPositionUseCase
@Inject
constructor(
private val keyguardRepository: KeyguardRepository,
) {
operator fun invoke(x: Int, y: Int) {
keyguardRepository.setClockPosition(x, y)
}
}

View File

@@ -0,0 +1,31 @@
/*
* 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.domain.usecase
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import javax.inject.Inject
/** Use-case for setting the alpha that the keyguard bottom area should use */
class SetKeyguardBottomAreaAlphaUseCase
@Inject
constructor(
private val repository: KeyguardRepository,
) {
operator fun invoke(alpha: Float) {
repository.setBottomAreaAlpha(alpha)
}
}

View File

@@ -0,0 +1,33 @@
/*
* 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.domain.usecase
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import javax.inject.Inject
/**
* Use-case for setting whether the keyguard bottom area should animate the next doze transitions
*/
class SetKeyguardBottomAreaAnimateDozingTransitionsUseCase
@Inject
constructor(
private val repository: KeyguardRepository,
) {
operator fun invoke(animate: Boolean) {
repository.setAnimateDozingTransitions(animate)
}
}

View File

@@ -0,0 +1,47 @@
/*
* 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.domain.usecase
import android.content.Intent
import com.android.systemui.animation.ActivityLaunchAnimator
/** Fake implementation of [LaunchKeyguardQuickAffordanceUseCase], for tests. */
class FakeLaunchKeyguardQuickAffordanceUseCase : LaunchKeyguardQuickAffordanceUseCase {
data class Invocation(
val intent: Intent,
val canShowWhileLocked: Boolean,
val animationController: ActivityLaunchAnimator.Controller?
)
private val _invocations = mutableListOf<Invocation>()
val invocations: List<Invocation> = _invocations
override fun invoke(
intent: Intent,
canShowWhileLocked: Boolean,
animationController: ActivityLaunchAnimator.Controller?
) {
_invocations.add(
Invocation(
intent = intent,
canShowWhileLocked = canShowWhileLocked,
animationController = animationController,
)
)
}
}

View File

@@ -0,0 +1,178 @@
/*
* 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.domain.usecase
import android.content.Intent
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameter
import org.junit.runners.Parameterized.Parameters
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(Parameterized::class)
class LaunchKeyguardQuickAffordanceUseCaseImplTest : SysuiTestCase() {
companion object {
private val INTENT = Intent("some.intent.action")
@Parameters(
name =
"needStrongAuthAfterBoot={0}, canShowWhileLocked={1}," +
" keyguardIsUnlocked={2}, needsToUnlockFirst={3}"
)
@JvmStatic
fun data() =
listOf(
arrayOf(
/* needStrongAuthAfterBoot= */ false,
/* canShowWhileLocked= */ false,
/* keyguardIsUnlocked= */ false,
/* needsToUnlockFirst= */ true,
),
arrayOf(
/* needStrongAuthAfterBoot= */ false,
/* canShowWhileLocked= */ false,
/* keyguardIsUnlocked= */ true,
/* needsToUnlockFirst= */ false,
),
arrayOf(
/* needStrongAuthAfterBoot= */ false,
/* canShowWhileLocked= */ true,
/* keyguardIsUnlocked= */ false,
/* needsToUnlockFirst= */ false,
),
arrayOf(
/* needStrongAuthAfterBoot= */ false,
/* canShowWhileLocked= */ true,
/* keyguardIsUnlocked= */ true,
/* needsToUnlockFirst= */ false,
),
arrayOf(
/* needStrongAuthAfterBoot= */ true,
/* canShowWhileLocked= */ false,
/* keyguardIsUnlocked= */ false,
/* needsToUnlockFirst= */ true,
),
arrayOf(
/* needStrongAuthAfterBoot= */ true,
/* canShowWhileLocked= */ false,
/* keyguardIsUnlocked= */ true,
/* needsToUnlockFirst= */ true,
),
arrayOf(
/* needStrongAuthAfterBoot= */ true,
/* canShowWhileLocked= */ true,
/* keyguardIsUnlocked= */ false,
/* needsToUnlockFirst= */ true,
),
arrayOf(
/* needStrongAuthAfterBoot= */ true,
/* canShowWhileLocked= */ true,
/* keyguardIsUnlocked= */ true,
/* needsToUnlockFirst= */ true,
),
)
}
@Mock private lateinit var lockPatternUtils: LockPatternUtils
@Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var userTracker: UserTracker
@Mock private lateinit var activityStarter: ActivityStarter
@Mock private lateinit var animationController: ActivityLaunchAnimator.Controller
private lateinit var underTest: LaunchKeyguardQuickAffordanceUseCase
@JvmField @Parameter(0) var needStrongAuthAfterBoot: Boolean = false
@JvmField @Parameter(1) var canShowWhileLocked: Boolean = false
@JvmField @Parameter(2) var keyguardIsUnlocked: Boolean = false
@JvmField @Parameter(3) var needsToUnlockFirst: Boolean = false
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
underTest =
LaunchKeyguardQuickAffordanceUseCaseImpl(
lockPatternUtils = lockPatternUtils,
keyguardStateController = keyguardStateController,
userTracker = userTracker,
activityStarter = activityStarter,
)
}
@Test
fun invoke() {
setUpMocks(
needStrongAuthAfterBoot = needStrongAuthAfterBoot,
keyguardIsUnlocked = keyguardIsUnlocked,
)
underTest(
intent = INTENT,
canShowWhileLocked = canShowWhileLocked,
animationController = animationController,
)
if (needsToUnlockFirst) {
verify(activityStarter)
.postStartActivityDismissingKeyguard(
INTENT,
/* delay= */ 0,
animationController,
)
} else {
verify(activityStarter)
.startActivity(
INTENT,
/* dismissShade= */ true,
animationController,
/* showOverLockscreenWhenLocked= */ true,
)
}
}
private fun setUpMocks(
needStrongAuthAfterBoot: Boolean = true,
keyguardIsUnlocked: Boolean = false,
) {
whenever(userTracker.userHandle).thenReturn(mock())
whenever(lockPatternUtils.getStrongAuthForUser(any()))
.thenReturn(
if (needStrongAuthAfterBoot) {
LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
} else {
LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED
}
)
whenever(keyguardStateController.isUnlocked).thenReturn(keyguardIsUnlocked)
}
}

View File

@@ -0,0 +1,156 @@
/*
* 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.domain.usecase
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.containeddrawable.ContainedDrawable
import com.android.systemui.keyguard.data.quickaffordance.HomeControlsKeyguardQuickAffordanceConfig
import com.android.systemui.keyguard.data.repository.FakeKeyguardQuickAffordanceRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordanceModel
import com.android.systemui.keyguard.shared.model.KeyguardQuickAffordancePosition
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@SmallTest
@RunWith(JUnit4::class)
class ObserveKeyguardQuickAffordanceUseCaseTest : SysuiTestCase() {
private lateinit var underTest: ObserveKeyguardQuickAffordanceUseCase
private lateinit var repository: FakeKeyguardRepository
private lateinit var quickAffordanceRepository: FakeKeyguardQuickAffordanceRepository
private lateinit var isDozingUseCase: ObserveIsDozingUseCase
private lateinit var dozeAmountUseCase: ObserveDozeAmountUseCase
@Before
fun setUp() {
repository = FakeKeyguardRepository()
isDozingUseCase = ObserveIsDozingUseCase(repository)
dozeAmountUseCase = ObserveDozeAmountUseCase(repository)
quickAffordanceRepository = FakeKeyguardQuickAffordanceRepository()
underTest =
ObserveKeyguardQuickAffordanceUseCase(
repository = quickAffordanceRepository,
isDozingUseCase = isDozingUseCase,
dozeAmountUseCase = dozeAmountUseCase,
)
}
@Test
fun `invoke - affordance is visible`() = runBlockingTest {
val configKey = HomeControlsKeyguardQuickAffordanceConfig::class
val model =
KeyguardQuickAffordanceModel.Visible(
configKey = configKey,
icon = ICON,
contentDescriptionResourceId = CONTENT_DESCRIPTION_RESOURCE_ID,
)
quickAffordanceRepository.setModel(
KeyguardQuickAffordancePosition.BOTTOM_END,
model,
)
var latest: KeyguardQuickAffordanceModel? = null
val job = underTest(KeyguardQuickAffordancePosition.BOTTOM_END)
.onEach { latest = it }
.launchIn(this)
assertThat(latest).isInstanceOf(KeyguardQuickAffordanceModel.Visible::class.java)
val visibleModel = latest as KeyguardQuickAffordanceModel.Visible
assertThat(visibleModel.configKey).isEqualTo(configKey)
assertThat(visibleModel.icon).isEqualTo(ICON)
assertThat(visibleModel.contentDescriptionResourceId)
.isEqualTo(CONTENT_DESCRIPTION_RESOURCE_ID)
job.cancel()
}
@Test
fun `invoke - affordance not visible while dozing`() = runBlockingTest {
repository.setDozing(true)
val configKey = HomeControlsKeyguardQuickAffordanceConfig::class
val model =
KeyguardQuickAffordanceModel.Visible(
configKey = configKey,
icon = ICON,
contentDescriptionResourceId = CONTENT_DESCRIPTION_RESOURCE_ID,
)
quickAffordanceRepository.setModel(
KeyguardQuickAffordancePosition.BOTTOM_END,
model,
)
var latest: KeyguardQuickAffordanceModel? = null
val job = underTest(KeyguardQuickAffordancePosition.BOTTOM_END)
.onEach { latest = it }
.launchIn(this)
assertThat(latest).isEqualTo(KeyguardQuickAffordanceModel.Hidden)
job.cancel()
}
@Test
fun `invoke - affordance not visible doze amount is not 0`() = runBlockingTest {
repository.setDozeAmount(0.3f)
val configKey = HomeControlsKeyguardQuickAffordanceConfig::class
val model =
KeyguardQuickAffordanceModel.Visible(
configKey = configKey,
icon = ICON,
contentDescriptionResourceId = CONTENT_DESCRIPTION_RESOURCE_ID,
)
quickAffordanceRepository.setModel(
KeyguardQuickAffordancePosition.BOTTOM_END,
model,
)
var latest: KeyguardQuickAffordanceModel? = null
val job = underTest(KeyguardQuickAffordancePosition.BOTTOM_END)
.onEach { latest = it }
.launchIn(this)
assertThat(latest).isEqualTo(KeyguardQuickAffordanceModel.Hidden)
job.cancel()
}
@Test
fun `invoke - affordance is none`() = runBlockingTest {
quickAffordanceRepository.setModel(
KeyguardQuickAffordancePosition.BOTTOM_START,
KeyguardQuickAffordanceModel.Hidden,
)
var latest: KeyguardQuickAffordanceModel? = null
val job = underTest(KeyguardQuickAffordancePosition.BOTTOM_START)
.onEach { latest = it }
.launchIn(this)
assertThat(latest).isEqualTo(KeyguardQuickAffordanceModel.Hidden)
job.cancel()
}
companion object {
private val ICON: ContainedDrawable = mock()
private const val CONTENT_DESCRIPTION_RESOURCE_ID = 1337
}
}