Merge "Keyguard - Migrate indication area" into udc-qpr-dev am: 7fbd2d37e7

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23414816

Change-Id: I830e07026e955e5a8e75fd61fdcc774e7417e7c7
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Matt Pietal
2023-05-30 15:46:39 +00:00
committed by Automerger Merge Worker
36 changed files with 842 additions and 339 deletions

View File

@@ -23,7 +23,7 @@
android:outlineProvider="none" >
<LinearLayout
android:id="@+id/keyguard_indication_area"
android:id="@id/keyguard_indication_area"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom"
@@ -31,7 +31,7 @@
android:orientation="vertical">
<com.android.systemui.statusbar.phone.KeyguardIndicationTextView
android:id="@+id/keyguard_indication_text"
android:id="@id/keyguard_indication_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
@@ -41,13 +41,12 @@
android:accessibilityLiveRegion="polite"/>
<com.android.systemui.statusbar.phone.KeyguardIndicationTextView
android:id="@+id/keyguard_indication_text_bottom"
android:id="@id/keyguard_indication_text_bottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:minHeight="48dp"
android:minHeight="@dimen/keyguard_indication_text_min_height"
android:layout_gravity="center_horizontal"
android:layout_centerHorizontal="true"
android:paddingStart="@dimen/keyguard_indication_text_padding"
android:paddingEnd="@dimen/keyguard_indication_text_padding"
android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"

View File

@@ -70,6 +70,12 @@
android:layout_height="match_parent"
android:visibility="invisible" />
<!-- Root for all keyguard content. It was previously located within the shade. -->
<com.android.systemui.keyguard.ui.view.KeyguardRootView
android:id="@id/keyguard_root_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include layout="@layout/brightness_mirror_container" />
<com.android.systemui.scrim.ScrimView

View File

@@ -275,6 +275,9 @@
<!-- The padding at start and end of indication text shown on AOD -->
<dimen name="keyguard_indication_text_padding">16dp</dimen>
<!-- The min height on the indication text shown on AOD -->
<dimen name="keyguard_indication_text_min_height">48dp</dimen>
<!-- Shadows under the clock, date and other keyguard text fields -->
<dimen name="keyguard_shadow_radius">5</dimen>

View File

@@ -206,5 +206,9 @@
<!-- keyboard backlight indicator-->
<item type="id" name="backlight_icon" />
</resources>
<item type="id" name="keyguard_root_view" />
<item type="id" name="keyguard_indication_area" />
<item type="id" name="keyguard_indication_text" />
<item type="id" name="keyguard_indication_text_bottom" />
</resources>

View File

@@ -34,6 +34,7 @@ import com.android.systemui.globalactions.GlobalActionsComponent
import com.android.systemui.keyboard.KeyboardUI
import com.android.systemui.keyboard.PhysicalKeyboardCoreStartable
import com.android.systemui.keyguard.KeyguardViewMediator
import com.android.systemui.keyguard.KeyguardViewConfigurator
import com.android.systemui.keyguard.data.quickaffordance.MuteQuickAffordanceCoreStartable
import com.android.systemui.log.SessionTracker
import com.android.systemui.media.RingtonePlayer
@@ -295,4 +296,9 @@ abstract class SystemUICoreStartableModule {
@IntoMap
@ClassKey(AssistantAttentionMonitor::class)
abstract fun bindAssistantAttentionMonitor(sysui: AssistantAttentionMonitor): CoreStartable
@Binds
@IntoMap
@ClassKey(KeyguardViewConfigurator::class)
abstract fun bindKeyguardViewConfigurator(impl: KeyguardViewConfigurator): CoreStartable
}

View File

@@ -0,0 +1,77 @@
/*
* 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.keyguard
import android.view.View
import android.view.ViewGroup
import com.android.systemui.CoreStartable
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.ui.binder.KeyguardIndicationAreaBinder
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel
import com.android.systemui.shade.NotificationShadeWindowView
import com.android.systemui.statusbar.KeyguardIndicationController
import javax.inject.Inject
import kotlinx.coroutines.DisposableHandle
/** Binds keyguard views on startup, and also exposes methods to allow rebinding if views change */
@SysUISingleton
class KeyguardViewConfigurator
@Inject
constructor(
private val keyguardRootView: KeyguardRootView,
private val keyguardIndicationAreaViewModel: KeyguardIndicationAreaViewModel,
private val notificationShadeWindowView: NotificationShadeWindowView,
private val featureFlags: FeatureFlags,
private val indicationController: KeyguardIndicationController,
) : CoreStartable {
private var indicationAreaHandle: DisposableHandle? = null
override fun start() {
bindIndicationArea(
notificationShadeWindowView.requireViewById(R.id.notification_panel) as ViewGroup
)
}
fun bindIndicationArea(legacyParent: ViewGroup) {
indicationAreaHandle?.dispose()
// At startup, 2 views with the ID `R.id.keyguard_indication_area` will be available.
// Disable one of them
if (featureFlags.isEnabled(Flags.MIGRATE_INDICATION_AREA)) {
legacyParent.requireViewById<View>(R.id.keyguard_indication_area).let {
legacyParent.removeView(it)
}
} else {
keyguardRootView.findViewById<View?>(R.id.keyguard_indication_area)?.let {
keyguardRootView.removeView(it)
}
}
indicationAreaHandle =
KeyguardIndicationAreaBinder.bind(
notificationShadeWindowView,
keyguardIndicationAreaViewModel,
indicationController
)
}
}

View File

@@ -21,6 +21,7 @@ import android.app.StatusBarManager
import android.graphics.Point
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.common.ui.data.repository.ConfigurationRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
@@ -59,6 +60,7 @@ constructor(
private val commandQueue: CommandQueue,
featureFlags: FeatureFlags,
bouncerRepository: KeyguardBouncerRepository,
configurationRepository: ConfigurationRepository,
) {
/**
* The amount of doze the system is in, where `1.0` is fully dozing and `0.0` is not dozing at
@@ -172,6 +174,9 @@ constructor(
/** The approximate location on the screen of the face unlock sensor, if one is available. */
val faceSensorLocation: Flow<Point?> = repository.faceSensorLocation
/** Notifies when a new configuration is set */
val configurationChange: Flow<Unit> = configurationRepository.onAnyConfigurationChange
fun dozeTransitionTo(vararg states: DozeStateModel): Flow<DozeTransitionModel> {
return dozeTransitionModel.filter { states.contains(it.to) }
}

View File

@@ -21,12 +21,10 @@ import android.content.Intent
import android.graphics.Rect
import android.graphics.drawable.Animatable2
import android.util.Size
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import android.view.ViewPropertyAnimator
import android.widget.ImageView
import android.widget.TextView
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
@@ -108,14 +106,10 @@ object KeyguardBottomAreaViewBinder {
activityStarter: ActivityStarter?,
messageDisplayer: (Int) -> Unit,
): Binding {
val indicationArea: View = view.requireViewById(R.id.keyguard_indication_area)
val ambientIndicationArea: View? = view.findViewById(R.id.ambient_indication_container)
val startButton: ImageView = view.requireViewById(R.id.start_button)
val endButton: ImageView = view.requireViewById(R.id.end_button)
val overlayContainer: View = view.requireViewById(R.id.overlay_container)
val indicationText: TextView = view.requireViewById(R.id.keyguard_indication_text)
val indicationTextBottom: TextView =
view.requireViewById(R.id.keyguard_indication_text_bottom)
val settingsMenu: LaunchableLinearLayout =
view.requireViewById(R.id.keyguard_settings_button)
@@ -183,7 +177,6 @@ object KeyguardBottomAreaViewBinder {
}
ambientIndicationArea?.alpha = alpha
indicationArea.alpha = alpha
}
}
@@ -205,27 +198,10 @@ object KeyguardBottomAreaViewBinder {
launch {
viewModel.indicationAreaTranslationX.collect { translationX ->
indicationArea.translationX = translationX
ambientIndicationArea?.translationX = translationX
}
}
launch {
combine(
viewModel.isIndicationAreaPadded,
configurationBasedDimensions.map { it.indicationAreaPaddingPx },
) { isPadded, paddingIfPaddedPx ->
if (isPadded) {
paddingIfPaddedPx
} else {
0
}
}
.collect { paddingPx ->
indicationArea.setPadding(paddingPx, 0, paddingPx, 0)
}
}
launch {
configurationBasedDimensions
.map { it.defaultBurnInPreventionYOffsetPx }
@@ -233,22 +209,12 @@ object KeyguardBottomAreaViewBinder {
viewModel.indicationAreaTranslationY(defaultBurnInOffsetY)
}
.collect { translationY ->
indicationArea.translationY = translationY
ambientIndicationArea?.translationY = translationY
}
}
launch {
configurationBasedDimensions.collect { dimensions ->
indicationText.setTextSize(
TypedValue.COMPLEX_UNIT_PX,
dimensions.indicationTextSizePx.toFloat(),
)
indicationTextBottom.setTextSize(
TypedValue.COMPLEX_UNIT_PX,
dimensions.indicationTextSizePx.toFloat(),
)
startButton.updateLayoutParams<ViewGroup.LayoutParams> {
width = dimensions.buttonSizePx.width
height = dimensions.buttonSizePx.height
@@ -305,7 +271,7 @@ object KeyguardBottomAreaViewBinder {
return object : Binding {
override fun getIndicationAreaAnimators(): List<ViewPropertyAnimator> {
return listOf(indicationArea, ambientIndicationArea).mapNotNull { it?.animate() }
return listOf(ambientIndicationArea).mapNotNull { it?.animate() }
}
override fun onConfigurationChanged() {
@@ -517,12 +483,6 @@ object KeyguardBottomAreaViewBinder {
return ConfigurationBasedDimensions(
defaultBurnInPreventionYOffsetPx =
view.resources.getDimensionPixelOffset(R.dimen.default_burn_in_prevention_offset),
indicationAreaPaddingPx =
view.resources.getDimensionPixelOffset(R.dimen.keyguard_indication_area_padding),
indicationTextSizePx =
view.resources.getDimensionPixelSize(
com.android.internal.R.dimen.text_size_small_material,
),
buttonSizePx =
Size(
view.resources.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width),
@@ -552,8 +512,6 @@ object KeyguardBottomAreaViewBinder {
private data class ConfigurationBasedDimensions(
val defaultBurnInPreventionYOffsetPx: Int,
val indicationAreaPaddingPx: Int,
val indicationTextSizePx: Int,
val buttonSizePx: Size,
)
}

View File

@@ -0,0 +1,153 @@
/*
* 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.keyguard.ui.binder
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.R
import com.android.systemui.keyguard.ui.viewmodel.KeyguardIndicationAreaViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.statusbar.KeyguardIndicationController
import kotlinx.coroutines.DisposableHandle
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
/**
* Binds a keyguard indication area view to its view-model.
*
* To use this properly, users should maintain a one-to-one relationship between the [View] and the
* view-binding, binding each view only once. It is okay and expected for the same instance of the
* view-model to be reused for multiple view/view-binder bindings.
*/
@OptIn(ExperimentalCoroutinesApi::class)
object KeyguardIndicationAreaBinder {
/** Binds the view to the view-model, continuing to update the former based on the latter. */
@JvmStatic
fun bind(
view: ViewGroup,
viewModel: KeyguardIndicationAreaViewModel,
indicationController: KeyguardIndicationController,
): DisposableHandle {
val indicationArea: ViewGroup = view.requireViewById(R.id.keyguard_indication_area)
indicationController.setIndicationArea(indicationArea)
val indicationText: TextView = indicationArea.requireViewById(R.id.keyguard_indication_text)
val indicationTextBottom: TextView =
indicationArea.requireViewById(R.id.keyguard_indication_text_bottom)
view.clipChildren = false
view.clipToPadding = false
val configurationBasedDimensions = MutableStateFlow(loadFromResources(view))
val disposableHandle =
view.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.STARTED) {
launch {
viewModel.alpha.collect { alpha ->
view.importantForAccessibility =
if (alpha == 0f) {
View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
} else {
View.IMPORTANT_FOR_ACCESSIBILITY_AUTO
}
indicationArea.alpha = alpha
}
}
launch {
viewModel.indicationAreaTranslationX.collect { translationX ->
indicationArea.translationX = translationX
}
}
launch {
combine(
viewModel.isIndicationAreaPadded,
configurationBasedDimensions.map { it.indicationAreaPaddingPx },
) { isPadded, paddingIfPaddedPx ->
if (isPadded) {
paddingIfPaddedPx
} else {
0
}
}
.collect { paddingPx ->
indicationArea.setPadding(paddingPx, 0, paddingPx, 0)
}
}
launch {
configurationBasedDimensions
.map { it.defaultBurnInPreventionYOffsetPx }
.flatMapLatest { defaultBurnInOffsetY ->
viewModel.indicationAreaTranslationY(defaultBurnInOffsetY)
}
.collect { translationY -> indicationArea.translationY = translationY }
}
launch {
configurationBasedDimensions.collect { dimensions ->
indicationText.setTextSize(
TypedValue.COMPLEX_UNIT_PX,
dimensions.indicationTextSizePx.toFloat(),
)
indicationTextBottom.setTextSize(
TypedValue.COMPLEX_UNIT_PX,
dimensions.indicationTextSizePx.toFloat(),
)
}
}
launch {
viewModel.configurationChange.collect {
configurationBasedDimensions.value = loadFromResources(view)
}
}
}
}
return disposableHandle
}
private fun loadFromResources(view: View): ConfigurationBasedDimensions {
return ConfigurationBasedDimensions(
defaultBurnInPreventionYOffsetPx =
view.resources.getDimensionPixelOffset(R.dimen.default_burn_in_prevention_offset),
indicationAreaPaddingPx =
view.resources.getDimensionPixelOffset(R.dimen.keyguard_indication_area_padding),
indicationTextSizePx =
view.resources.getDimensionPixelSize(
com.android.internal.R.dimen.text_size_small_material,
),
)
}
private data class ConfigurationBasedDimensions(
val defaultBurnInPreventionYOffsetPx: Int,
val indicationAreaPaddingPx: Int,
val indicationTextSizePx: Int,
)
}

View File

@@ -0,0 +1,86 @@
/*
* 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.keyguard.ui.view
import android.content.Context
import android.text.TextUtils
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.LinearLayout
import com.android.systemui.R
import com.android.systemui.statusbar.phone.KeyguardIndicationTextView
class KeyguardIndicationArea(
context: Context,
private val attrs: AttributeSet?,
) :
LinearLayout(
context,
attrs,
) {
init {
setId(R.id.keyguard_indication_area)
orientation = LinearLayout.VERTICAL
addView(indicationTopRow(), LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT))
addView(
indicationBottomRow(),
LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).apply {
gravity = Gravity.CENTER_HORIZONTAL
}
)
}
private fun indicationTopRow(): KeyguardIndicationTextView {
return KeyguardIndicationTextView(context, attrs).apply {
id = R.id.keyguard_indication_text
gravity = Gravity.CENTER
accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_POLITE
setTextAppearance(R.style.TextAppearance_Keyguard_BottomArea)
val padding = R.dimen.keyguard_indication_text_padding.dp()
setPaddingRelative(padding, 0, padding, 0)
}
}
private fun indicationBottomRow(): KeyguardIndicationTextView {
return KeyguardIndicationTextView(context, attrs).apply {
id = R.id.keyguard_indication_text_bottom
gravity = Gravity.CENTER
accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_POLITE
setTextAppearance(R.style.TextAppearance_Keyguard_BottomArea)
setEllipsize(TextUtils.TruncateAt.END)
setAlpha(0.8f)
setMinHeight(R.dimen.keyguard_indication_text_min_height.dp())
setMaxLines(2)
setVisibility(View.GONE)
val padding = R.dimen.keyguard_indication_text_padding.dp()
setPaddingRelative(padding, 0, padding, 0)
}
}
private fun Int.dp(): Int {
return context.resources.getDimensionPixelSize(this)
}
}

View File

@@ -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.keyguard.ui.view
import android.content.Context
import android.util.AttributeSet
import android.view.Gravity
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.FrameLayout
import com.android.systemui.R
/** Provides a container for all keyguard ui content. */
class KeyguardRootView(
context: Context,
private val attrs: AttributeSet?,
) :
FrameLayout(
context,
attrs,
) {
init {
addIndicationTextArea()
}
private fun addIndicationTextArea() {
val view = KeyguardIndicationArea(context, attrs)
addView(
view,
FrameLayout.LayoutParams(
MATCH_PARENT,
WRAP_CONTENT,
)
.apply {
gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL
bottomMargin = R.dimen.keyguard_indication_margin_bottom.dp()
}
)
}
private fun Int.dp(): Int {
return context.resources.getDimensionPixelSize(this)
}
}

View File

@@ -57,7 +57,7 @@ constructor(
* in the wallpaper picker application. This should _always_ be `false` for the real lock screen
* experience.
*/
private val previewMode = MutableStateFlow(PreviewMode())
val previewMode = MutableStateFlow(PreviewMode())
/**
* ID of the slot that's currently selected in the preview that renders exclusively in the
@@ -101,12 +101,6 @@ constructor(
bottomAreaInteractor.alpha.distinctUntilChanged()
}
}
/** An observable for whether the indication area should be padded. */
val isIndicationAreaPadded: Flow<Boolean> =
combine(startButton, endButton) { startButtonModel, endButtonModel ->
startButtonModel.isVisible || endButtonModel.isVisible
}
.distinctUntilChanged()
/** An observable for the x-offset by which the indication area should be translated. */
val indicationAreaTranslationX: Flow<Float> =
bottomAreaInteractor.clockPosition.map { it.x.toFloat() }.distinctUntilChanged()

View File

@@ -0,0 +1,70 @@
/*
* 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.keyguard.ui.viewmodel
import com.android.systemui.doze.util.BurnInHelperWrapper
import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
/** View-model for the keyguard indication area view */
@OptIn(ExperimentalCoroutinesApi::class)
class KeyguardIndicationAreaViewModel
@Inject
constructor(
private val keyguardInteractor: KeyguardInteractor,
private val bottomAreaInteractor: KeyguardBottomAreaInteractor,
private val keyguardBottomAreaViewModel: KeyguardBottomAreaViewModel,
private val burnInHelperWrapper: BurnInHelperWrapper,
) {
/** Notifies when a new configuration is set */
val configurationChange: Flow<Unit> = keyguardInteractor.configurationChange
/** An observable for the alpha level for the entire bottom area. */
val alpha: Flow<Float> = keyguardBottomAreaViewModel.alpha
/** An observable for whether the indication area should be padded. */
val isIndicationAreaPadded: Flow<Boolean> =
combine(keyguardBottomAreaViewModel.startButton, keyguardBottomAreaViewModel.endButton) {
startButtonModel,
endButtonModel ->
startButtonModel.isVisible || endButtonModel.isVisible
}
.distinctUntilChanged()
/** An observable for the x-offset by which the indication area should be translated. */
val indicationAreaTranslationX: Flow<Float> =
bottomAreaInteractor.clockPosition.map { it.x.toFloat() }.distinctUntilChanged()
/** Returns an observable for the y-offset by which the indication area should be translated. */
fun indicationAreaTranslationY(defaultBurnInOffset: Int): Flow<Float> {
return keyguardInteractor.dozeAmount
.map { dozeAmount ->
dozeAmount *
(burnInHelperWrapper.burnInOffset(
/* amplitude = */ defaultBurnInOffset * 2,
/* xAxis= */ false,
) - defaultBurnInOffset)
}
.distinctUntilChanged()
}
}

View File

@@ -125,6 +125,7 @@ import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardViewConfigurator;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
@@ -598,6 +599,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
private final KeyguardInteractor mKeyguardInteractor;
private final KeyguardViewConfigurator mKeyguardViewConfigurator;
private final @Nullable MultiShadeInteractor mMultiShadeInteractor;
private final CoroutineDispatcher mMainDispatcher;
private boolean mIsAnyMultiShadeExpanded;
@@ -740,6 +742,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
KeyguardLongPressViewModel keyguardLongPressViewModel,
KeyguardInteractor keyguardInteractor,
ActivityStarter activityStarter,
KeyguardViewConfigurator keyguardViewConfigurator,
KeyguardFaceAuthInteractor keyguardFaceAuthInteractor) {
mInteractionJankMonitor = interactionJankMonitor;
keyguardStateController.addCallback(new KeyguardStateController.Callback() {
@@ -762,6 +765,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
mLockscreenToOccludedTransitionViewModel = lockscreenToOccludedTransitionViewModel;
mKeyguardTransitionInteractor = keyguardTransitionInteractor;
mKeyguardInteractor = keyguardInteractor;
mKeyguardViewConfigurator = keyguardViewConfigurator;
mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
@@ -1319,7 +1323,6 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
mKeyguardBottomArea.initFrom(oldBottomArea);
mView.addView(mKeyguardBottomArea, index);
initBottomArea();
mKeyguardIndicationController.setIndicationArea(mKeyguardBottomArea);
mStatusBarStateListener.onDozeAmountChanged(mStatusBarStateController.getDozeAmount(),
mStatusBarStateController.getInterpolatedDozeAmount());
@@ -1361,6 +1364,9 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
mKeyguardIndicationController.showTransientIndication(stringResourceId),
mVibratorHelper,
mActivityStarter);
// Rebind (for now), as a new bottom area and indication area may have been created
mKeyguardViewConfigurator.bindIndicationArea(mKeyguardBottomArea);
}
@VisibleForTesting
@@ -1398,7 +1404,6 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
private void setKeyguardBottomArea(KeyguardBottomAreaView keyguardBottomArea) {
mKeyguardBottomArea = keyguardBottomArea;
mKeyguardIndicationController.setIndicationArea(mKeyguardBottomArea);
}
void setOpenCloseListener(OpenCloseListener openCloseListener) {
@@ -3023,12 +3028,6 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
mKeyguardStatusViewController.setStatusAccessibilityImportance(mode);
}
//TODO(b/254875405): this should be removed.
@Override
public KeyguardBottomAreaView getKeyguardBottomAreaView() {
return mKeyguardBottomArea;
}
@Override
public void applyLaunchAnimationProgress(float linearProgress) {
boolean hideIcons = LaunchAnimator.getProgress(ActivityLaunchAnimator.TIMINGS,

View File

@@ -32,6 +32,7 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.ui.view.KeyguardRootView
import com.android.systemui.privacy.OngoingPrivacyChip
import com.android.systemui.scene.ui.view.WindowRootView
import com.android.systemui.settings.UserTracker
@@ -71,9 +72,9 @@ abstract class ShadeModule {
layoutInflater.inflate(R.layout.scene_window_root, null)
} else {
layoutInflater.inflate(R.layout.super_notification_shade, null)
} as WindowRootView? ?: throw IllegalStateException(
"Window root view could not be properly inflated"
)
}
as WindowRootView?
?: throw IllegalStateException("Window root view could not be properly inflated")
}
@Provides
@@ -89,9 +90,7 @@ abstract class ShadeModule {
return root.findViewById(R.id.legacy_window_root)
}
return root as NotificationShadeWindowView?
?: throw IllegalStateException(
"root view not a NotificationShadeWindowView"
)
?: throw IllegalStateException("root view not a NotificationShadeWindowView")
}
// TODO(b/277762009): Only allow this view's controller to inject the view. See above.
@@ -120,6 +119,14 @@ abstract class ShadeModule {
return notificationShadeWindowView.findViewById(R.id.light_reveal_scrim)
}
@Provides
@SysUISingleton
fun providesKeyguardRootView(
notificationShadeWindowView: NotificationShadeWindowView,
): KeyguardRootView {
return notificationShadeWindowView.findViewById(R.id.keyguard_root_view)
}
// TODO(b/277762009): Only allow this view's controller to inject the view. See above.
@Provides
@SysUISingleton

View File

@@ -21,7 +21,6 @@ import com.android.systemui.statusbar.RemoteInputController
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView
import com.android.systemui.statusbar.phone.KeyguardStatusBarView
import com.android.systemui.statusbar.phone.KeyguardStatusBarViewController
import java.util.function.Consumer
@@ -120,13 +119,6 @@ interface ShadeViewController {
/** Returns the StatusBarState. */
val barState: Int
/**
* Returns the bottom part of the keyguard, which contains quick affordances.
*
* TODO(b/275550429): this should be removed.
*/
val keyguardBottomAreaView: KeyguardBottomAreaView?
/** Returns the NSSL controller. */
val notificationStackScrollLayoutController: NotificationStackScrollLayoutController

View File

@@ -40,7 +40,6 @@ import com.android.systemui.shade.NotificationShadeWindowView;
import com.android.systemui.shade.QuickSettingsController;
import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -86,7 +85,6 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
private final HeadsUpManagerPhone mHeadsUpManager;
private final AboveShelfObserver mAboveShelfObserver;
private final DozeScrimController mDozeScrimController;
private final KeyguardIndicationController mKeyguardIndicationController;
private final CentralSurfaces mCentralSurfaces;
private final LockscreenShadeTransitionController mShadeTransitionController;
private final CommandQueue mCommandQueue;
@@ -115,7 +113,6 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
NotificationShadeWindowController notificationShadeWindowController,
DynamicPrivacyController dynamicPrivacyController,
KeyguardStateController keyguardStateController,
KeyguardIndicationController keyguardIndicationController,
CentralSurfaces centralSurfaces,
LockscreenShadeTransitionController shadeTransitionController,
CommandQueue commandQueue,
@@ -137,7 +134,6 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
mQsController = quickSettingsController;
mHeadsUpManager = headsUp;
mDynamicPrivacyController = dynamicPrivacyController;
mKeyguardIndicationController = keyguardIndicationController;
// TODO: use KeyguardStateController#isOccluded to remove this dependency
mCentralSurfaces = centralSurfaces;
mShadeTransitionController = shadeTransitionController;
@@ -173,7 +169,6 @@ class StatusBarNotificationPresenter implements NotificationPresenter,
mNotificationPanel.getShadeNotificationPresenter().createRemoteInputDelegate());
initController.addPostInitTask(() -> {
mKeyguardIndicationController.init();
mNotifShadeEventSource.setShadeEmptiedCallback(this::maybeClosePanelForShadeEmptied);
mNotifShadeEventSource.setNotifRemovedByUserCallback(this::maybeEndAmbientPulse);
notificationInterruptStateProvider.addSuppressor(mInterruptSuppressor);

View File

@@ -62,6 +62,7 @@ import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
import java.util.TimeZone
import java.util.concurrent.Executor
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import org.mockito.Mockito.`when` as whenever
@RunWith(AndroidTestingRunner::class)
@@ -117,6 +118,7 @@ class ClockEventControllerTest : SysuiTestCase() {
commandQueue = commandQueue,
featureFlags = featureFlags,
bouncerRepository = bouncerRepository,
configurationRepository = FakeConfigurationRepository(),
),
KeyguardTransitionInteractor(repository = transitionRepository),
broadcastDispatcher,

View File

@@ -18,6 +18,7 @@ package com.android.keyguard;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.systemui.flags.Flags.DOZING_MIGRATION_1;
import static com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
@@ -42,15 +43,12 @@ import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.AuthRippleController;
import com.android.systemui.doze.util.BurnInHelperKt;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository;
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -91,10 +89,9 @@ public class LockIconViewControllerBaseTest extends SysuiTestCase {
protected @Mock ConfigurationController mConfigurationController;
protected @Mock VibratorHelper mVibrator;
protected @Mock AuthRippleController mAuthRippleController;
protected @Mock FeatureFlags mFeatureFlags;
protected @Mock KeyguardTransitionRepository mTransitionRepository;
protected @Mock CommandQueue mCommandQueue;
protected FakeExecutor mDelayableExecutor = new FakeExecutor(new FakeSystemClock());
protected FakeFeatureFlags mFeatureFlags;
protected LockIconViewController mUnderTest;
@@ -144,6 +141,8 @@ public class LockIconViewControllerBaseTest extends SysuiTestCase {
when(mStatusBarStateController.isDozing()).thenReturn(false);
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
mFeatureFlags = new FakeFeatureFlags();
mFeatureFlags.set(FACE_AUTH_REFACTOR, false);
mUnderTest = new LockIconViewController(
mLockIconView,
mStatusBarStateController,
@@ -160,12 +159,7 @@ public class LockIconViewControllerBaseTest extends SysuiTestCase {
mAuthRippleController,
mResources,
new KeyguardTransitionInteractor(mTransitionRepository),
new KeyguardInteractor(
new FakeKeyguardRepository(),
mCommandQueue,
mFeatureFlags,
new FakeKeyguardBouncerRepository()
),
KeyguardInteractorFactory.create(mFeatureFlags).getKeyguardInteractor(),
mFeatureFlags
);
}
@@ -226,7 +220,7 @@ public class LockIconViewControllerBaseTest extends SysuiTestCase {
}
protected void init(boolean useMigrationFlag) {
when(mFeatureFlags.isEnabled(DOZING_MIGRATION_1)).thenReturn(useMigrationFlag);
mFeatureFlags.set(DOZING_MIGRATION_1, useMigrationFlag);
mUnderTest.init();
verify(mLockIconView, atLeast(1)).addOnAttachStateChangeListener(mAttachCaptor.capture());

View File

@@ -34,6 +34,7 @@ import com.android.systemui.R
import com.android.systemui.SystemUIAppComponentFactoryBase
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.DialogLaunchAnimator
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.dock.DockManagerFake
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
@@ -185,6 +186,7 @@ class CustomizationProviderTest : SysuiTestCase() {
commandQueue = commandQueue,
featureFlags = featureFlags,
bouncerRepository = FakeKeyguardBouncerRepository(),
configurationRepository = FakeConfigurationRepository(),
),
registry = mock(),
lockPatternUtils = lockPatternUtils,

View File

@@ -7,11 +7,9 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionStep
@@ -60,13 +58,12 @@ class ResourceTrimmerTest : SysuiTestCase() {
keyguardRepository.setDozeAmount(0f)
keyguardRepository.setKeyguardGoingAway(false)
val keyguardInteractor =
KeyguardInteractor(
keyguardRepository,
FakeCommandQueue(),
featureFlags,
FakeKeyguardBouncerRepository()
val withDeps =
KeyguardInteractorFactory.create(
repository = keyguardRepository,
featureFlags = featureFlags,
)
val keyguardInteractor = withDeps.keyguardInteractor
resourceTrimmer =
ResourceTrimmer(
keyguardInteractor,

View File

@@ -47,6 +47,7 @@ import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.AuthenticationStatus
import com.android.systemui.keyguard.shared.model.DetectionStatus
@@ -159,17 +160,16 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
biometricSettingsRepository = FakeBiometricSettingsRepository()
deviceEntryFingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository()
trustRepository = FakeTrustRepository()
keyguardRepository = FakeKeyguardRepository()
bouncerRepository = FakeKeyguardBouncerRepository()
featureFlags = FakeFeatureFlags().apply { set(FACE_AUTH_REFACTOR, true) }
fakeCommandQueue = FakeCommandQueue()
keyguardInteractor =
KeyguardInteractor(
keyguardRepository,
fakeCommandQueue,
featureFlags,
bouncerRepository
val withDeps =
KeyguardInteractorFactory.create(
featureFlags = featureFlags,
)
keyguardInteractor = withDeps.keyguardInteractor
keyguardRepository = withDeps.repository
bouncerRepository = withDeps.bouncerRepository
fakeCommandQueue = withDeps.commandQueue
alternateBouncerInteractor =
AlternateBouncerInteractor(
bouncerRepository = bouncerRepository,

View File

@@ -22,6 +22,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
@@ -50,6 +51,7 @@ class KeyguardInteractorTest : SysuiTestCase() {
private lateinit var underTest: KeyguardInteractor
private lateinit var repository: FakeKeyguardRepository
private lateinit var bouncerRepository: FakeKeyguardBouncerRepository
private lateinit var configurationRepository: FakeConfigurationRepository
@Before
fun setUp() {
@@ -59,12 +61,14 @@ class KeyguardInteractorTest : SysuiTestCase() {
testScope = TestScope()
repository = FakeKeyguardRepository()
bouncerRepository = FakeKeyguardBouncerRepository()
configurationRepository = FakeConfigurationRepository()
underTest =
KeyguardInteractor(
repository,
commandQueue,
featureFlags,
bouncerRepository,
configurationRepository,
)
}

View File

@@ -38,8 +38,6 @@ import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanc
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
import com.android.systemui.keyguard.domain.quickaffordance.FakeKeyguardQuickAffordanceRegistry
import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
@@ -48,7 +46,6 @@ import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.settings.FakeUserTracker
import com.android.systemui.settings.UserFileManager
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.FakeSharedPreferences
import com.android.systemui.util.mockito.any
@@ -225,7 +222,6 @@ class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() {
@Mock private lateinit var animationController: ActivityLaunchAnimator.Controller
@Mock private lateinit var expandable: Expandable
@Mock private lateinit var launchAnimator: DialogLaunchAnimator
@Mock private lateinit var commandQueue: CommandQueue
@Mock private lateinit var devicePolicyManager: DevicePolicyManager
@Mock private lateinit var logger: KeyguardQuickAffordancesMetricsLogger
@@ -309,12 +305,10 @@ class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() {
underTest =
KeyguardQuickAffordanceInteractor(
keyguardInteractor =
KeyguardInteractor(
repository = FakeKeyguardRepository(),
commandQueue = commandQueue,
featureFlags = featureFlags,
bouncerRepository = FakeKeyguardBouncerRepository(),
),
KeyguardInteractorFactory.create(
featureFlags = featureFlags,
)
.keyguardInteractor,
registry =
FakeKeyguardQuickAffordanceRegistry(
mapOf(
@@ -368,11 +362,11 @@ class KeyguardQuickAffordanceInteractorParameterizedTest : SysuiTestCase() {
KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled
}
underTest.onQuickAffordanceTriggered(
configKey = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS,
expandable = expandable,
slotId = "",
)
underTest.onQuickAffordanceTriggered(
configKey = BuiltInKeyguardQuickAffordanceKeys.HOME_CONTROLS,
expandable = expandable,
slotId = "",
)
if (startActivity) {
if (needsToUnlockFirst) {

View File

@@ -40,7 +40,6 @@ import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanc
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
import com.android.systemui.keyguard.domain.model.KeyguardQuickAffordanceModel
@@ -53,7 +52,6 @@ import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.settings.UserFileManager
import com.android.systemui.settings.UserTracker
import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.FakeSharedPreferences
import com.android.systemui.util.mockito.mock
@@ -84,7 +82,6 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
@Mock private lateinit var userTracker: UserTracker
@Mock private lateinit var activityStarter: ActivityStarter
@Mock private lateinit var launchAnimator: DialogLaunchAnimator
@Mock private lateinit var commandQueue: CommandQueue
@Mock private lateinit var devicePolicyManager: DevicePolicyManager
@Mock private lateinit var logger: KeyguardQuickAffordancesMetricsLogger
@@ -168,15 +165,14 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() {
set(Flags.FACE_AUTH_REFACTOR, true)
}
val withDeps =
KeyguardInteractorFactory.create(
featureFlags = featureFlags,
repository = repository,
)
underTest =
KeyguardQuickAffordanceInteractor(
keyguardInteractor =
KeyguardInteractor(
repository = repository,
commandQueue = commandQueue,
featureFlags = featureFlags,
bouncerRepository = FakeKeyguardBouncerRepository(),
),
keyguardInteractor = withDeps.keyguardInteractor,
registry =
FakeKeyguardQuickAffordanceRegistry(
mapOf(

View File

@@ -21,7 +21,6 @@ import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardSecurityModel.SecurityMode.PIN
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -39,7 +38,6 @@ import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.mockito.withArgCaptor
@@ -74,10 +72,10 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
private lateinit var bouncerRepository: FakeKeyguardBouncerRepository
private lateinit var shadeRepository: ShadeRepository
private lateinit var transitionRepository: FakeKeyguardTransitionRepository
private lateinit var featureFlags: FakeFeatureFlags
// Used to verify transition requests for test output
@Mock private lateinit var mockTransitionRepository: KeyguardTransitionRepository
@Mock private lateinit var commandQueue: CommandQueue
@Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
private lateinit var fromLockscreenTransitionInteractor: FromLockscreenTransitionInteractor
@@ -103,11 +101,11 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
whenever(keyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(PIN)
val featureFlags = FakeFeatureFlags().apply { set(Flags.FACE_AUTH_REFACTOR, true) }
featureFlags = FakeFeatureFlags().apply { set(Flags.FACE_AUTH_REFACTOR, true) }
fromLockscreenTransitionInteractor =
FromLockscreenTransitionInteractor(
scope = testScope,
keyguardInteractor = createKeyguardInteractor(featureFlags),
keyguardInteractor = createKeyguardInteractor(),
shadeRepository = shadeRepository,
keyguardTransitionRepository = mockTransitionRepository,
keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
@@ -117,7 +115,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
fromDreamingTransitionInteractor =
FromDreamingTransitionInteractor(
scope = testScope,
keyguardInteractor = createKeyguardInteractor(featureFlags),
keyguardInteractor = createKeyguardInteractor(),
keyguardTransitionRepository = mockTransitionRepository,
keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
)
@@ -126,7 +124,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
fromAodTransitionInteractor =
FromAodTransitionInteractor(
scope = testScope,
keyguardInteractor = createKeyguardInteractor(featureFlags),
keyguardInteractor = createKeyguardInteractor(),
keyguardTransitionRepository = mockTransitionRepository,
keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
)
@@ -135,7 +133,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
fromGoneTransitionInteractor =
FromGoneTransitionInteractor(
scope = testScope,
keyguardInteractor = createKeyguardInteractor(featureFlags),
keyguardInteractor = createKeyguardInteractor(),
keyguardTransitionRepository = mockTransitionRepository,
keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
)
@@ -144,7 +142,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
fromDozingTransitionInteractor =
FromDozingTransitionInteractor(
scope = testScope,
keyguardInteractor = createKeyguardInteractor(featureFlags),
keyguardInteractor = createKeyguardInteractor(),
keyguardTransitionRepository = mockTransitionRepository,
keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
)
@@ -153,7 +151,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
fromOccludedTransitionInteractor =
FromOccludedTransitionInteractor(
scope = testScope,
keyguardInteractor = createKeyguardInteractor(featureFlags),
keyguardInteractor = createKeyguardInteractor(),
keyguardTransitionRepository = mockTransitionRepository,
keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
)
@@ -162,7 +160,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
fromAlternateBouncerTransitionInteractor =
FromAlternateBouncerTransitionInteractor(
scope = testScope,
keyguardInteractor = createKeyguardInteractor(featureFlags),
keyguardInteractor = createKeyguardInteractor(),
keyguardTransitionRepository = mockTransitionRepository,
keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
)
@@ -171,7 +169,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
fromPrimaryBouncerTransitionInteractor =
FromPrimaryBouncerTransitionInteractor(
scope = testScope,
keyguardInteractor = createKeyguardInteractor(featureFlags),
keyguardInteractor = createKeyguardInteractor(),
keyguardTransitionRepository = mockTransitionRepository,
keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
keyguardSecurityModel = keyguardSecurityModel,
@@ -882,13 +880,13 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
WakeSleepReason.OTHER
)
private fun createKeyguardInteractor(featureFlags: FeatureFlags): KeyguardInteractor {
return KeyguardInteractor(
keyguardRepository,
commandQueue,
featureFlags,
bouncerRepository,
)
private fun createKeyguardInteractor(): KeyguardInteractor {
return KeyguardInteractorFactory.create(
featureFlags = featureFlags,
repository = keyguardRepository,
bouncerRepository = bouncerRepository,
)
.keyguardInteractor
}
private suspend fun TestScope.runTransition(from: KeyguardState, to: KeyguardState) {

View File

@@ -39,12 +39,11 @@ import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanc
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLegacySettingSyncer
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceLocalUserSelectionManager
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceRemoteUserSelectionManager
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.KeyguardQuickAffordanceRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
import com.android.systemui.keyguard.domain.interactor.KeyguardLongPressInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
@@ -56,7 +55,6 @@ import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.settings.UserFileManager
import com.android.systemui.settings.UserTracker
import com.android.systemui.shared.keyguard.shared.model.KeyguardQuickAffordanceSlots
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.FakeSharedPreferences
@@ -95,7 +93,6 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
@Mock private lateinit var userTracker: UserTracker
@Mock private lateinit var activityStarter: ActivityStarter
@Mock private lateinit var launchAnimator: DialogLaunchAnimator
@Mock private lateinit var commandQueue: CommandQueue
@Mock private lateinit var devicePolicyManager: DevicePolicyManager
@Mock private lateinit var logger: KeyguardQuickAffordancesMetricsLogger
@Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
@@ -140,7 +137,6 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
),
),
)
repository = FakeKeyguardRepository()
val featureFlags =
FakeFeatureFlags().apply {
set(Flags.CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES, false)
@@ -149,13 +145,10 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
set(Flags.LOCK_SCREEN_LONG_PRESS_DIRECT_TO_WPP, false)
}
val keyguardInteractor =
KeyguardInteractor(
repository = repository,
commandQueue = commandQueue,
featureFlags = featureFlags,
bouncerRepository = FakeKeyguardBouncerRepository(),
)
val withDeps = KeyguardInteractorFactory.create(featureFlags = featureFlags)
val keyguardInteractor = withDeps.keyguardInteractor
repository = withDeps.repository
whenever(userTracker.userHandle).thenReturn(mock())
whenever(userTracker.userId).thenReturn(10)
whenever(lockPatternUtils.getStrongAuthForUser(anyInt()))
@@ -549,91 +542,6 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
assertThat(value()).isEqualTo(1f)
}
@Test
fun isIndicationAreaPadded() =
testScope.runTest {
repository.setKeyguardShowing(true)
val value = collectLastValue(underTest.isIndicationAreaPadded)
assertThat(value()).isFalse()
setUpQuickAffordanceModel(
position = KeyguardQuickAffordancePosition.BOTTOM_START,
testConfig =
TestConfig(
isVisible = true,
isClickable = true,
icon = mock(),
canShowWhileLocked = true,
slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
)
)
assertThat(value()).isTrue()
setUpQuickAffordanceModel(
position = KeyguardQuickAffordancePosition.BOTTOM_END,
testConfig =
TestConfig(
isVisible = true,
isClickable = true,
icon = mock(),
canShowWhileLocked = false,
slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId(),
)
)
assertThat(value()).isTrue()
setUpQuickAffordanceModel(
position = KeyguardQuickAffordancePosition.BOTTOM_START,
testConfig =
TestConfig(
isVisible = false,
slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId(),
)
)
assertThat(value()).isTrue()
setUpQuickAffordanceModel(
position = KeyguardQuickAffordancePosition.BOTTOM_END,
testConfig =
TestConfig(
isVisible = false,
slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId(),
)
)
assertThat(value()).isFalse()
}
@Test
fun indicationAreaTranslationX() =
testScope.runTest {
val value = collectLastValue(underTest.indicationAreaTranslationX)
assertThat(value()).isEqualTo(0f)
repository.setClockPosition(100, 100)
assertThat(value()).isEqualTo(100f)
repository.setClockPosition(200, 100)
assertThat(value()).isEqualTo(200f)
repository.setClockPosition(200, 200)
assertThat(value()).isEqualTo(200f)
repository.setClockPosition(300, 100)
assertThat(value()).isEqualTo(300f)
}
@Test
fun indicationAreaTranslationY() =
testScope.runTest {
val value =
collectLastValue(underTest.indicationAreaTranslationY(DEFAULT_BURN_IN_OFFSET))
// Negative 0 - apparently there's a difference in floating point arithmetic - FML
assertThat(value()).isEqualTo(-0f)
val expected1 = setDozeAmountAndCalculateExpectedTranslationY(0.1f)
assertThat(value()).isEqualTo(expected1)
val expected2 = setDozeAmountAndCalculateExpectedTranslationY(0.2f)
assertThat(value()).isEqualTo(expected2)
val expected3 = setDozeAmountAndCalculateExpectedTranslationY(0.5f)
assertThat(value()).isEqualTo(expected3)
val expected4 = setDozeAmountAndCalculateExpectedTranslationY(1f)
assertThat(value()).isEqualTo(expected4)
}
@Test
fun isClickable_trueWhenAlphaAtThreshold() =
testScope.runTest {
@@ -757,11 +665,6 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() {
)
}
private fun setDozeAmountAndCalculateExpectedTranslationY(dozeAmount: Float): Float {
repository.setDozeAmount(dozeAmount)
return dozeAmount * (RETURNED_BURN_IN_OFFSET - DEFAULT_BURN_IN_OFFSET)
}
private suspend fun setUpQuickAffordanceModel(
position: KeyguardQuickAffordancePosition,
testConfig: TestConfig,

View File

@@ -0,0 +1,160 @@
/*
* 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.keyguard.ui.viewmodel
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.doze.util.BurnInHelperWrapper
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
import com.android.systemui.keyguard.shared.quickaffordance.KeyguardQuickAffordancePosition
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.MockitoAnnotations
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(JUnit4::class)
class KeyguardIndicationAreaViewModelTest : SysuiTestCase() {
@Mock private lateinit var burnInHelperWrapper: BurnInHelperWrapper
private lateinit var underTest: KeyguardIndicationAreaViewModel
private lateinit var repository: FakeKeyguardRepository
private val startButtonFlow =
MutableStateFlow<KeyguardQuickAffordanceViewModel>(
KeyguardQuickAffordanceViewModel(
slotId = KeyguardQuickAffordancePosition.BOTTOM_START.toSlotId()
)
)
private val endButtonFlow =
MutableStateFlow<KeyguardQuickAffordanceViewModel>(
KeyguardQuickAffordanceViewModel(
slotId = KeyguardQuickAffordancePosition.BOTTOM_END.toSlotId()
)
)
private val alphaFlow = MutableStateFlow<Float>(1f)
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
whenever(burnInHelperWrapper.burnInOffset(anyInt(), any()))
.thenReturn(RETURNED_BURN_IN_OFFSET)
val withDeps = KeyguardInteractorFactory.create()
val keyguardInteractor = withDeps.keyguardInteractor
repository = withDeps.repository
val bottomAreaViewModel: KeyguardBottomAreaViewModel = mock()
whenever(bottomAreaViewModel.startButton).thenReturn(startButtonFlow)
whenever(bottomAreaViewModel.endButton).thenReturn(endButtonFlow)
whenever(bottomAreaViewModel.alpha).thenReturn(alphaFlow)
underTest =
KeyguardIndicationAreaViewModel(
keyguardInteractor = keyguardInteractor,
bottomAreaInteractor = KeyguardBottomAreaInteractor(repository = repository),
keyguardBottomAreaViewModel = bottomAreaViewModel,
burnInHelperWrapper = burnInHelperWrapper,
)
}
@Test
fun alpha() = runTest {
val value = collectLastValue(underTest.alpha)
assertThat(value()).isEqualTo(1f)
alphaFlow.value = 0.1f
assertThat(value()).isEqualTo(0.1f)
alphaFlow.value = 0.5f
assertThat(value()).isEqualTo(0.5f)
alphaFlow.value = 0.2f
assertThat(value()).isEqualTo(0.2f)
alphaFlow.value = 0f
assertThat(value()).isEqualTo(0f)
}
@Test
fun isIndicationAreaPadded() = runTest {
repository.setKeyguardShowing(true)
val value = collectLastValue(underTest.isIndicationAreaPadded)
assertThat(value()).isFalse()
startButtonFlow.value = startButtonFlow.value.copy(isVisible = true)
assertThat(value()).isTrue()
endButtonFlow.value = endButtonFlow.value.copy(isVisible = true)
assertThat(value()).isTrue()
startButtonFlow.value = startButtonFlow.value.copy(isVisible = false)
assertThat(value()).isTrue()
endButtonFlow.value = endButtonFlow.value.copy(isVisible = false)
assertThat(value()).isFalse()
}
@Test
fun indicationAreaTranslationX() = runTest {
val value = collectLastValue(underTest.indicationAreaTranslationX)
assertThat(value()).isEqualTo(0f)
repository.setClockPosition(100, 100)
assertThat(value()).isEqualTo(100f)
repository.setClockPosition(200, 100)
assertThat(value()).isEqualTo(200f)
repository.setClockPosition(200, 200)
assertThat(value()).isEqualTo(200f)
repository.setClockPosition(300, 100)
assertThat(value()).isEqualTo(300f)
}
@Test
fun indicationAreaTranslationY() = runTest {
val value = collectLastValue(underTest.indicationAreaTranslationY(DEFAULT_BURN_IN_OFFSET))
// Negative 0 - apparently there's a difference in floating point arithmetic - FML
assertThat(value()).isEqualTo(-0f)
val expected1 = setDozeAmountAndCalculateExpectedTranslationY(0.1f)
assertThat(value()).isEqualTo(expected1)
val expected2 = setDozeAmountAndCalculateExpectedTranslationY(0.2f)
assertThat(value()).isEqualTo(expected2)
val expected3 = setDozeAmountAndCalculateExpectedTranslationY(0.5f)
assertThat(value()).isEqualTo(expected3)
val expected4 = setDozeAmountAndCalculateExpectedTranslationY(1f)
assertThat(value()).isEqualTo(expected4)
}
private fun setDozeAmountAndCalculateExpectedTranslationY(dozeAmount: Float): Float {
repository.setDozeAmount(dozeAmount)
return dozeAmount * (RETURNED_BURN_IN_OFFSET - DEFAULT_BURN_IN_OFFSET)
}
companion object {
private const val DEFAULT_BURN_IN_OFFSET = 5
private const val RETURNED_BURN_IN_OFFSET = 3
}
}

View File

@@ -89,12 +89,13 @@ import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository;
import com.android.systemui.keyguard.KeyguardViewConfigurator;
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
@@ -253,6 +254,7 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
@Mock protected UserManager mUserManager;
@Mock protected UiEventLogger mUiEventLogger;
@Mock protected LockIconViewController mLockIconViewController;
@Mock protected KeyguardViewConfigurator mKeyguardViewConfigurator;
@Mock protected KeyguardMediaController mKeyguardMediaController;
@Mock protected NavigationModeController mNavigationModeController;
@Mock protected NavigationBarController mNavigationBarController;
@@ -342,8 +344,8 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
mMainDispatcher = getMainDispatcher();
mKeyguardBottomAreaInteractor = new KeyguardBottomAreaInteractor(
new FakeKeyguardRepository());
mKeyguardInteractor = new KeyguardInteractor(new FakeKeyguardRepository(), mCommandQueue,
mFeatureFlags, new FakeKeyguardBouncerRepository());
mKeyguardInteractor = KeyguardInteractorFactory.create().getKeyguardInteractor();
SystemClock systemClock = new FakeSystemClock();
mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager,
mInteractionJankMonitor, mShadeExpansionStateManager);
@@ -611,6 +613,7 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
mKeyuardLongPressViewModel,
mKeyguardInteractor,
mActivityStarter,
mKeyguardViewConfigurator,
mKeyguardFaceAuthInteractor);
mNotificationPanelViewController.initDependencies(
mCentralSurfaces,

View File

@@ -44,7 +44,6 @@ import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeNotificationPresenter;
import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -122,7 +121,6 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase {
mock(NotificationShadeWindowController.class),
mock(DynamicPrivacyController.class),
mKeyguardStateController,
mock(KeyguardIndicationController.class),
mCentralSurfaces,
mock(LockscreenShadeTransitionController.class),
mCommandQueue,

View File

@@ -28,12 +28,10 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
import com.android.systemui.shade.ShadeFoldAnimator
import com.android.systemui.shade.ShadeViewController
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.unfold.util.FoldableDeviceStates
@@ -80,8 +78,6 @@ class FoldAodAnimationControllerTest : SysuiTestCase() {
@Mock lateinit var viewTreeObserver: ViewTreeObserver
@Mock private lateinit var commandQueue: CommandQueue
@Mock lateinit var shadeFoldAnimator: ShadeFoldAnimator
@Captor private lateinit var foldStateListenerCaptor: ArgumentCaptor<FoldStateListener>
@@ -111,15 +107,10 @@ class FoldAodAnimationControllerTest : SysuiTestCase() {
onActionStarted.run()
}
keyguardRepository = FakeKeyguardRepository()
val featureFlags = FakeFeatureFlags().apply { set(FACE_AUTH_REFACTOR, true) }
val keyguardInteractor =
KeyguardInteractor(
repository = keyguardRepository,
commandQueue = commandQueue,
featureFlags = featureFlags,
bouncerRepository = FakeKeyguardBouncerRepository(),
)
val withDeps = KeyguardInteractorFactory.create(featureFlags = featureFlags)
val keyguardInteractor = withDeps.keyguardInteractor
keyguardRepository = withDeps.repository
// Needs to be run on the main thread
runBlocking(IMMEDIATE) {

View File

@@ -39,12 +39,10 @@ import com.android.systemui.common.shared.model.Text
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.qs.user.UserSwitchDialogController
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
@@ -97,7 +95,6 @@ class UserInteractorTest : SysuiTestCase() {
@Mock private lateinit var dialogShower: UserSwitchDialogController.DialogShower
@Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
@Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
@Mock private lateinit var commandQueue: CommandQueue
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
private lateinit var underTest: UserInteractor
@@ -126,8 +123,9 @@ class UserInteractorTest : SysuiTestCase() {
set(Flags.FULL_SCREEN_USER_SWITCHER, false)
set(Flags.FACE_AUTH_REFACTOR, true)
}
val reply = KeyguardInteractorFactory.create(featureFlags = featureFlags)
keyguardRepository = reply.repository
userRepository = FakeUserRepository()
keyguardRepository = FakeKeyguardRepository()
telephonyRepository = FakeTelephonyRepository()
val testDispatcher = StandardTestDispatcher()
testScope = TestScope(testDispatcher)
@@ -142,13 +140,7 @@ class UserInteractorTest : SysuiTestCase() {
applicationContext = context,
repository = userRepository,
activityStarter = activityStarter,
keyguardInteractor =
KeyguardInteractor(
repository = keyguardRepository,
commandQueue = commandQueue,
featureFlags = featureFlags,
bouncerRepository = FakeKeyguardBouncerRepository(),
),
keyguardInteractor = reply.keyguardInteractor,
manager = manager,
headlessSystemUserMode = headlessSystemUserMode,
applicationScope = testScope.backgroundScope,

View File

@@ -32,11 +32,8 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.Text
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
@@ -80,13 +77,11 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
@Mock private lateinit var uiEventLogger: UiEventLogger
@Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
@Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
@Mock private lateinit var commandQueue: CommandQueue
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
private lateinit var underTest: StatusBarUserChipViewModel
private val userRepository = FakeUserRepository()
private val keyguardRepository = FakeKeyguardRepository()
private lateinit var guestUserInteractor: GuestUserInteractor
private lateinit var refreshUsersScheduler: RefreshUsersScheduler
@@ -250,12 +245,8 @@ class StatusBarUserChipViewModelTest : SysuiTestCase() {
repository = userRepository,
activityStarter = activityStarter,
keyguardInteractor =
KeyguardInteractor(
repository = keyguardRepository,
commandQueue = commandQueue,
featureFlags = featureFlags,
bouncerRepository = FakeKeyguardBouncerRepository(),
),
KeyguardInteractorFactory.create(featureFlags = featureFlags)
.keyguardInteractor,
featureFlags = featureFlags,
manager = manager,
headlessSystemUserMode = headlessSystemUserMode,

View File

@@ -30,11 +30,9 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.Text
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.telephony.data.repository.FakeTelephonyRepository
import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
@@ -79,7 +77,6 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
@Mock private lateinit var uiEventLogger: UiEventLogger
@Mock private lateinit var resumeSessionReceiver: GuestResumeSessionReceiver
@Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
@Mock private lateinit var commandQueue: CommandQueue
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
private lateinit var underTest: UserSwitcherViewModel
@@ -112,7 +109,6 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
)
}
keyguardRepository = FakeKeyguardRepository()
val refreshUsersScheduler =
RefreshUsersScheduler(
applicationScope = testScope.backgroundScope,
@@ -140,38 +136,35 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
set(Flags.FULL_SCREEN_USER_SWITCHER, false)
set(Flags.FACE_AUTH_REFACTOR, true)
}
val reply = KeyguardInteractorFactory.create(featureFlags = featureFlags)
keyguardRepository = reply.repository
underTest =
UserSwitcherViewModel(
userInteractor =
UserInteractor(
applicationContext = context,
repository = userRepository,
activityStarter = activityStarter,
keyguardInteractor =
KeyguardInteractor(
repository = keyguardRepository,
commandQueue = commandQueue,
featureFlags = featureFlags,
bouncerRepository = FakeKeyguardBouncerRepository(),
),
featureFlags = featureFlags,
manager = manager,
headlessSystemUserMode = headlessSystemUserMode,
applicationScope = testScope.backgroundScope,
telephonyInteractor =
TelephonyInteractor(
repository = FakeTelephonyRepository(),
),
broadcastDispatcher = fakeBroadcastDispatcher,
keyguardUpdateMonitor = keyguardUpdateMonitor,
backgroundDispatcher = testDispatcher,
activityManager = activityManager,
refreshUsersScheduler = refreshUsersScheduler,
guestUserInteractor = guestUserInteractor,
uiEventLogger = uiEventLogger,
),
guestUserInteractor = guestUserInteractor,
)
userInteractor =
UserInteractor(
applicationContext = context,
repository = userRepository,
activityStarter = activityStarter,
keyguardInteractor = reply.keyguardInteractor,
featureFlags = featureFlags,
manager = manager,
headlessSystemUserMode = headlessSystemUserMode,
applicationScope = testScope.backgroundScope,
telephonyInteractor =
TelephonyInteractor(
repository = FakeTelephonyRepository(),
),
broadcastDispatcher = fakeBroadcastDispatcher,
keyguardUpdateMonitor = keyguardUpdateMonitor,
backgroundDispatcher = testDispatcher,
activityManager = activityManager,
refreshUsersScheduler = refreshUsersScheduler,
guestUserInteractor = guestUserInteractor,
uiEventLogger = uiEventLogger,
),
guestUserInteractor = guestUserInteractor,
)
}
@Test
@@ -323,7 +316,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() {
setUsers(count = 2)
val isFinishRequested = mutableListOf<Boolean>()
val job =
launch(testDispatcher) { underTest.isFinishRequested.toList(isFinishRequested) }
launch(testDispatcher) { underTest.isFinishRequested.toList(isFinishRequested) }
assertThat(isFinishRequested.last()).isFalse()
underTest.onCancelButtonClicked()

View File

@@ -0,0 +1,71 @@
/*
* 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.keyguard.domain.interactor
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
/**
* Simply put, I got tired of adding a constructor argument and then having to tweak dozens of
* files. This should alleviate some of the burden by providing defaults for testing.
*/
object KeyguardInteractorFactory {
@JvmOverloads
@JvmStatic
fun create(
featureFlags: FakeFeatureFlags = createFakeFeatureFlags(),
repository: FakeKeyguardRepository = FakeKeyguardRepository(),
commandQueue: FakeCommandQueue = FakeCommandQueue(),
bouncerRepository: FakeKeyguardBouncerRepository = FakeKeyguardBouncerRepository(),
configurationRepository: FakeConfigurationRepository = FakeConfigurationRepository(),
): WithDependencies {
return WithDependencies(
repository = repository,
commandQueue = commandQueue,
featureFlags = featureFlags,
bouncerRepository = bouncerRepository,
configurationRepository = configurationRepository,
KeyguardInteractor(
repository = repository,
commandQueue = commandQueue,
featureFlags = featureFlags,
bouncerRepository = bouncerRepository,
configurationRepository = configurationRepository,
)
)
}
/** Provide defaults, otherwise tests will throw an error */
fun createFakeFeatureFlags(): FakeFeatureFlags {
return FakeFeatureFlags().apply { set(Flags.FACE_AUTH_REFACTOR, false) }
}
data class WithDependencies(
val repository: FakeKeyguardRepository,
val commandQueue: FakeCommandQueue,
val featureFlags: FakeFeatureFlags,
val bouncerRepository: FakeKeyguardBouncerRepository,
val configurationRepository: FakeConfigurationRepository,
val keyguardInteractor: KeyguardInteractor,
)
}