Listen to change of notification stack bottom to pass correct bounds to magic portrait shape effects
Bug: 364534860
Flag: com.android.systemui.magic_portrait_wallpapers
Test: atest WallpaperRepositoryImplTest
Change-Id: Ic3e59c8fb5916eacb3b3f030dc126abaf4b5b1a3
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index c6238e8..1f5d0f5 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1483,3 +1483,11 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "magic_portrait_wallpapers"
+ namespace: "systemui"
+ description: "Magic Portrait related changes in systemui"
+ bug: "370863642"
+}
+
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt
index fe5024f..59676ce 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt
@@ -17,10 +17,17 @@
package com.android.systemui.wallpapers.data.repository
import android.app.WallpaperInfo
+import android.view.View
import kotlinx.coroutines.flow.MutableStateFlow
/** Fake implementation of the wallpaper repository. */
class FakeWallpaperRepository : WallpaperRepository {
override val wallpaperInfo = MutableStateFlow<WallpaperInfo?>(null)
override val wallpaperSupportsAmbientMode = MutableStateFlow(false)
+ override var rootView: View? = null
+ private val _notificationStackAbsoluteBottom = MutableStateFlow(0F)
+
+ override fun setNotificationStackAbsoluteBottom(bottom: Float) {
+ _notificationStackAbsoluteBottom.value = bottom
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt
index ec52055..95d1b5d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardClockRepository.kt
@@ -68,11 +68,16 @@
val previewClock: Flow<ClockController>
+ /** top of notifications without bcsmartspace in small clock settings */
+ val notificationDefaultTop: StateFlow<Float>
+
val clockEventController: ClockEventController
val shouldForceSmallClock: Boolean
fun setClockSize(size: ClockSize)
+
+ fun setNotificationDefaultTop(top: Float)
}
@SysUISingleton
@@ -108,7 +113,7 @@
.stateIn(
scope = applicationScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = getClockSize()
+ initialValue = getClockSize(),
)
override val currentClockId: Flow<ClockId> =
@@ -138,7 +143,7 @@
.stateIn(
scope = applicationScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = clockRegistry.createCurrentClock()
+ initialValue = clockRegistry.createCurrentClock(),
)
override val previewClock: Flow<ClockController> =
@@ -149,6 +154,14 @@
clockRegistry.createCurrentClock()
}
+ private val _notificationDefaultTop: MutableStateFlow<Float> = MutableStateFlow(0F)
+
+ override val notificationDefaultTop: StateFlow<Float> = _notificationDefaultTop.asStateFlow()
+
+ override fun setNotificationDefaultTop(top: Float) {
+ _notificationDefaultTop.value = top
+ }
+
override val shouldForceSmallClock: Boolean
get() =
featureFlags.isEnabled(Flags.LOCKSCREEN_ENABLE_LANDSCAPE) &&
@@ -160,7 +173,7 @@
secureSettings.getIntForUser(
Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK,
/* defaultValue= */ 1,
- UserHandle.USER_CURRENT
+ UserHandle.USER_CURRENT,
)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index 130242f..8210174 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -269,6 +269,9 @@
*/
val isEncryptedOrLockdown: Flow<Boolean>
+ /** The top of shortcut in screen, used by wallpaper to find remaining space in lockscreen */
+ val shortcutAbsoluteTop: StateFlow<Float>
+
/**
* Returns `true` if the keyguard is showing; `false` otherwise.
*
@@ -339,6 +342,8 @@
* otherwise.
*/
fun isShowKeyguardWhenReenabled(): Boolean
+
+ fun setShortcutAbsoluteTop(top: Float)
}
/** Encapsulates application state for the keyguard. */
@@ -503,7 +508,7 @@
trySendWithFailureLogging(
statusBarStateController.dozeAmount,
TAG,
- "initial dozeAmount"
+ "initial dozeAmount",
)
awaitClose { statusBarStateController.removeCallback(callback) }
@@ -521,7 +526,7 @@
object : DozeTransitionCallback {
override fun onDozeTransition(
oldState: DozeMachine.State,
- newState: DozeMachine.State
+ newState: DozeMachine.State,
) {
trySendWithFailureLogging(
DozeTransitionModel(
@@ -529,7 +534,7 @@
to = dozeMachineStateToModel(newState),
),
TAG,
- "doze transition model"
+ "doze transition model",
)
}
}
@@ -541,7 +546,7 @@
to = dozeMachineStateToModel(dozeTransitionListener.newState),
),
TAG,
- "initial doze transition model"
+ "initial doze transition model",
)
awaitClose { dozeTransitionListener.removeCallback(callback) }
@@ -579,7 +584,7 @@
trySendWithFailureLogging(
statusBarStateIntToObject(state),
TAG,
- "state"
+ "state",
)
}
}
@@ -590,7 +595,7 @@
.stateIn(
scope,
SharingStarted.Eagerly,
- statusBarStateIntToObject(statusBarStateController.state)
+ statusBarStateIntToObject(statusBarStateController.state),
)
private val _biometricUnlockState: MutableStateFlow<BiometricUnlockModel> =
@@ -610,7 +615,7 @@
trySendWithFailureLogging(
authController.fingerprintSensorLocation,
TAG,
- "AuthController.Callback#onFingerprintLocationChanged"
+ "AuthController.Callback#onFingerprintLocationChanged",
)
}
@@ -635,6 +640,9 @@
private val _isActiveDreamLockscreenHosted = MutableStateFlow(false)
override val isActiveDreamLockscreenHosted = _isActiveDreamLockscreenHosted.asStateFlow()
+ private val _shortcutAbsoluteTop = MutableStateFlow(0F)
+ override val shortcutAbsoluteTop = _shortcutAbsoluteTop.asStateFlow()
+
init {
val callback =
object : KeyguardStateController.Callback {
@@ -721,6 +729,10 @@
}
}
+ override fun setShortcutAbsoluteTop(top: Float) {
+ _shortcutAbsoluteTop.value = top
+ }
+
private fun dozeMachineStateToModel(state: DozeMachine.State): DozeStateModel {
return when (state) {
DozeMachine.State.UNINITIALIZED -> DozeStateModel.UNINITIALIZED
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
index c0049d4..5b7eedd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
@@ -94,7 +94,7 @@
.stateIn(
scope = applicationScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = ClockSize.LARGE
+ initialValue = ClockSize.LARGE,
)
} else {
keyguardClockRepository.clockSize
@@ -152,4 +152,8 @@
clock.largeClock.animations.fold(foldFraction)
}
}
+
+ fun setNotificationStackDefaultTop(top: Float) {
+ keyguardClockRepository.setNotificationDefaultTop(top)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index e6ee112..d7f96b5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -526,6 +526,10 @@
repository.showDismissibleKeyguard()
}
+ fun setShortcutAbsoluteTop(top: Float) {
+ repository.setShortcutAbsoluteTop(top)
+ }
+
companion object {
private const val TAG = "KeyguardInteractor"
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
index a1c963b..0b10c8a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
@@ -44,6 +44,7 @@
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockFaceLayout
import com.android.systemui.res.R
+import com.android.systemui.shade.LargeScreenHeaderHelper
import com.android.systemui.shared.R as sharedR
import com.android.systemui.util.ui.value
import dagger.Lazy
@@ -70,6 +71,7 @@
val blueprintInteractor: Lazy<KeyguardBlueprintInteractor>,
private val rootViewModel: KeyguardRootViewModel,
private val aodBurnInViewModel: AodBurnInViewModel,
+ private val largeScreenHeaderHelperLazy: Lazy<LargeScreenHeaderHelper>,
) : KeyguardSection() {
private var disposableHandle: DisposableHandle? = null
@@ -172,7 +174,7 @@
}
}
- open fun applyDefaultConstraints(constraints: ConstraintSet) {
+ fun applyDefaultConstraints(constraints: ConstraintSet) {
val guideline =
if (keyguardClockViewModel.clockShouldBeCentered.value) PARENT_ID
else R.id.split_shade_guideline
@@ -211,6 +213,28 @@
// Explicitly clear pivot to force recalculate pivot instead of using legacy value
setTransformPivot(R.id.lockscreen_clock_view_large, Float.NaN, Float.NaN)
+
+ val smallClockBottom =
+ keyguardClockViewModel.getSmallClockTopMargin() +
+ context.resources.getDimensionPixelSize(
+ com.android.systemui.customization.R.dimen.small_clock_height
+ )
+ val dateWeatherSmartspaceHeight = getDimen(context, DATE_WEATHER_VIEW_HEIGHT).toFloat()
+ val marginBetweenSmartspaceAndNotification =
+ context.resources.getDimensionPixelSize(
+ R.dimen.keyguard_status_view_bottom_margin
+ ) +
+ if (context.resources.getBoolean(R.bool.config_use_large_screen_shade_header)) {
+ largeScreenHeaderHelperLazy.get().getLargeScreenHeaderHeight()
+ } else {
+ 0
+ }
+
+ clockInteractor.setNotificationStackDefaultTop(
+ smallClockBottom +
+ dateWeatherSmartspaceHeight +
+ marginBetweenSmartspaceAndNotification
+ )
}
constrainWeatherClockDateIconsBarrier(constraints)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
index 6c6e14c..d3895de 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultShortcutsSection.kt
@@ -30,6 +30,7 @@
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.KeyguardBottomAreaRefactor
import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.ui.binder.KeyguardQuickAffordanceViewBinder
import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition
import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordancesCombinedViewModel
@@ -52,6 +53,7 @@
private val indicationController: KeyguardIndicationController,
private val keyguardBlueprintInteractor: Lazy<KeyguardBlueprintInteractor>,
private val keyguardQuickAffordanceViewBinder: KeyguardQuickAffordanceViewBinder,
+ private val keyguardInteractor: KeyguardInteractor,
) : BaseShortcutSection() {
// Amount to increase the bottom margin by to avoid colliding with inset
@@ -117,7 +119,7 @@
BOTTOM,
PARENT_ID,
BOTTOM,
- verticalOffsetMargin + safeInsetBottom
+ verticalOffsetMargin + safeInsetBottom,
)
constrainWidth(R.id.end_button, width)
@@ -128,7 +130,7 @@
BOTTOM,
PARENT_ID,
BOTTOM,
- verticalOffsetMargin + safeInsetBottom
+ verticalOffsetMargin + safeInsetBottom,
)
// The constraint set visibility for start and end button are default visible, set to
@@ -136,5 +138,13 @@
setVisibilityMode(R.id.start_button, VISIBILITY_MODE_IGNORE)
setVisibilityMode(R.id.end_button, VISIBILITY_MODE_IGNORE)
}
+
+ val shortcutAbsoluteTopInScreen =
+ (resources.displayMetrics.heightPixels -
+ (verticalOffsetMargin + safeInsetBottom) -
+ height)
+ .toFloat()
+
+ keyguardInteractor.setShortcutAbsoluteTop(shortcutAbsoluteTopInScreen)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index b466bf0..43989a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -129,6 +129,7 @@
import com.android.systemui.util.ColorUtilKt;
import com.android.systemui.util.DumpUtilsKt;
import com.android.systemui.util.ListenerSet;
+import com.android.systemui.wallpapers.domain.interactor.WallpaperInteractor;
import com.google.errorprone.annotations.CompileTimeConstant;
@@ -627,6 +628,9 @@
@Nullable
private OnClickListener mManageButtonClickListener;
+ @Nullable
+ private WallpaperInteractor mWallpaperInteractor;
+
public NotificationStackScrollLayout(Context context, AttributeSet attrs) {
super(context, attrs, 0, 0);
Resources res = getResources();
@@ -1189,6 +1193,7 @@
if (!SceneContainerFlag.isEnabled()) {
setMaxLayoutHeight(getHeight());
updateContentHeight();
+ mWallpaperInteractor.setNotificationStackAbsoluteBottom(mContentHeight);
}
clampScrollPosition();
requestChildrenUpdate();
@@ -1248,6 +1253,7 @@
if (mAmbientState.getStackTop() != stackTop) {
mAmbientState.setStackTop(stackTop);
onTopPaddingChanged(/* animate = */ isAddOrRemoveAnimationPending());
+ mWallpaperInteractor.setNotificationStackAbsoluteBottom((int) stackTop);
}
}
@@ -5875,6 +5881,10 @@
mController.getNotificationRoundnessManager().setAnimatedChildren(mChildrenToAddAnimated);
}
+ public void setWallpaperInteractor(WallpaperInteractor wallpaperInteractor) {
+ mWallpaperInteractor = wallpaperInteractor;
+ }
+
void addSwipedOutView(View v) {
mSwipedOutViews.add(v);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 7b02d0c..00c5c40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -145,6 +145,7 @@
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.Compile;
import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.wallpapers.domain.interactor.WallpaperInteractor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -226,6 +227,8 @@
private final SensitiveNotificationProtectionController
mSensitiveNotificationProtectionController;
+ private final WallpaperInteractor mWallpaperInteractor;
+
private View mLongPressedView;
private final NotificationListContainerImpl mNotificationListContainer =
@@ -756,7 +759,8 @@
NotificationDismissibilityProvider dismissibilityProvider,
ActivityStarter activityStarter,
SplitShadeStateController splitShadeStateController,
- SensitiveNotificationProtectionController sensitiveNotificationProtectionController) {
+ SensitiveNotificationProtectionController sensitiveNotificationProtectionController,
+ WallpaperInteractor wallpaperInteractor) {
mView = view;
mKeyguardTransitionRepo = keyguardTransitionRepo;
mViewBinder = viewBinder;
@@ -812,6 +816,7 @@
mDismissibilityProvider = dismissibilityProvider;
mActivityStarter = activityStarter;
mSensitiveNotificationProtectionController = sensitiveNotificationProtectionController;
+ mWallpaperInteractor = wallpaperInteractor;
mView.passSplitShadeStateController(splitShadeStateController);
if (SceneContainerFlag.isEnabled()) {
mWakeUpCoordinator.setStackScroller(this);
@@ -948,6 +953,8 @@
collectFlow(mView, mKeyguardTransitionRepo.getTransitions(),
this::onKeyguardTransitionChanged);
}
+
+ mView.setWallpaperInteractor(mWallpaperInteractor);
}
private boolean isInVisibleLocation(NotificationEntry entry) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt b/packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt
index 65a0218..0744b5a 100644
--- a/packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt
@@ -32,19 +32,24 @@
* Note: New logic should be added to [WallpaperRepository], not this class.
*/
@SysUISingleton
-class WallpaperController @Inject constructor(
+class WallpaperController
+@Inject
+constructor(
private val wallpaperManager: WallpaperManager,
private val wallpaperRepository: WallpaperRepository,
) {
var rootView: View? = null
+ set(value) {
+ field = value
+ wallpaperRepository.rootView = value
+ }
private var notificationShadeZoomOut: Float = 0f
private var unfoldTransitionZoomOut: Float = 0f
private val shouldUseDefaultUnfoldTransition: Boolean
- get() = wallpaperRepository.wallpaperInfo.value?.shouldUseDefaultUnfoldTransition()
- ?: true
+ get() = wallpaperRepository.wallpaperInfo.value?.shouldUseDefaultUnfoldTransition() ?: true
fun setNotificationShadeZoom(zoomOut: Float) {
notificationShadeZoomOut = zoomOut
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt
index b45b8cd..54953c9 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt
@@ -17,6 +17,7 @@
package com.android.systemui.wallpapers.data.repository
import android.app.WallpaperInfo
+import android.view.View
import com.android.systemui.dagger.SysUISingleton
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
@@ -33,4 +34,7 @@
class NoopWallpaperRepository @Inject constructor() : WallpaperRepository {
override val wallpaperInfo: StateFlow<WallpaperInfo?> = MutableStateFlow(null).asStateFlow()
override val wallpaperSupportsAmbientMode = MutableStateFlow(false).asStateFlow()
+ override var rootView: View? = null
+
+ override fun setNotificationStackAbsoluteBottom(bottom: Float) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
index 041b6f9..203e1da 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
@@ -21,10 +21,16 @@
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
+import android.os.Bundle
import android.os.UserHandle
+import android.view.View
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.Flags
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.keyguard.data.repository.KeyguardClockRepository
+import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.user.data.model.SelectedUserModel
import com.android.systemui.user.data.model.SelectionStatus
import com.android.systemui.user.data.repository.UserRepository
@@ -32,16 +38,19 @@
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
/** A repository storing information about the current wallpaper. */
@@ -51,6 +60,15 @@
/** Emits true if the current user's current wallpaper supports ambient mode. */
val wallpaperSupportsAmbientMode: StateFlow<Boolean>
+
+ /** Set rootView to get its windowToken afterwards */
+ var rootView: View?
+
+ /**
+ * Set bottom of notifications from notification stack, and Magic Portrait will layout base on
+ * this value
+ */
+ fun setNotificationStackAbsoluteBottom(bottom: Float)
}
@SysUISingleton
@@ -61,6 +79,8 @@
@Background private val bgDispatcher: CoroutineDispatcher,
broadcastDispatcher: BroadcastDispatcher,
userRepository: UserRepository,
+ keyguardRepository: KeyguardRepository,
+ keyguardClockRepository: KeyguardClockRepository,
private val wallpaperManager: WallpaperManager,
context: Context,
) : WallpaperRepository {
@@ -69,10 +89,7 @@
private val wallpaperChanged: Flow<Unit> =
broadcastDispatcher
- .broadcastFlow(
- IntentFilter(Intent.ACTION_WALLPAPER_CHANGED),
- user = UserHandle.ALL,
- )
+ .broadcastFlow(IntentFilter(Intent.ACTION_WALLPAPER_CHANGED), user = UserHandle.ALL)
// The `combine` defining `wallpaperSupportsAmbientMode` will not run until both of the
// input flows emit at least once. Since this flow is an input flow, it needs to emit
// when it starts up to ensure that the `combine` will run if the user changes before we
@@ -87,6 +104,27 @@
// Only update the wallpaper status once the user selection has finished.
.filter { it.selectionStatus == SelectionStatus.SELECTION_COMPLETE }
+ /** The bottom of notification stack respect to the top of screen. */
+ private val notificationStackAbsoluteBottom: MutableStateFlow<Float> = MutableStateFlow(0F)
+
+ /** The top of shortcut respect to the top of screen. */
+ private val shortcutAbsoluteTop: StateFlow<Float> = keyguardRepository.shortcutAbsoluteTop
+
+ /**
+ * The top of notification stack to give a default state of lockscreen remaining space for
+ * states with notifications to compare with. It's the bottom of smartspace date and weather
+ * smartspace in small clock state, plus proper bottom margin.
+ */
+ private val notificationStackDefaultTop = keyguardClockRepository.notificationDefaultTop
+ @VisibleForTesting var sendLockscreenLayoutJob: Job? = null
+ private val lockscreenRemainingSpaceWithNotification: Flow<Triple<Float, Float, Float>> =
+ combine(
+ notificationStackAbsoluteBottom,
+ notificationStackDefaultTop,
+ shortcutAbsoluteTop,
+ ::Triple,
+ )
+
override val wallpaperInfo: StateFlow<WallpaperInfo?> =
if (!wallpaperManager.isWallpaperSupported || !deviceSupportsAodWallpaper) {
MutableStateFlow(null).asStateFlow()
@@ -116,9 +154,70 @@
initialValue = wallpaperInfo.value?.supportsAmbientMode() == true,
)
+ override var rootView: View? = null
+
+ val shouldSendNotificationLayout =
+ wallpaperInfo
+ .map {
+ val shouldSendNotificationLayout = shouldSendNotificationLayout(it)
+ if (shouldSendNotificationLayout) {
+ sendLockscreenLayoutJob =
+ scope.launch {
+ lockscreenRemainingSpaceWithNotification.collect {
+ (notificationBottom, notificationDefaultTop, shortcutTop) ->
+ wallpaperManager.sendWallpaperCommand(
+ /* windowToken = */ rootView?.windowToken,
+ /* action = */ WallpaperManager
+ .COMMAND_LOCKSCREEN_LAYOUT_CHANGED,
+ /* x = */ 0,
+ /* y = */ 0,
+ /* z = */ 0,
+ /* extras = */ Bundle().apply {
+ putFloat("screenLeft", 0F)
+ putFloat("smartspaceBottom", notificationDefaultTop)
+ putFloat("notificationBottom", notificationBottom)
+ putFloat(
+ "screenRight",
+ context.resources.displayMetrics.widthPixels.toFloat(),
+ )
+ putFloat("shortCutTop", shortcutTop)
+ },
+ )
+ }
+ }
+ } else {
+ sendLockscreenLayoutJob?.cancel()
+ }
+ shouldSendNotificationLayout
+ }
+ .stateIn(
+ scope,
+ // Always be listening for wallpaper changes.
+ if (Flags.magicPortraitWallpapers()) SharingStarted.Eagerly
+ else SharingStarted.Lazily,
+ initialValue = false,
+ )
+
+ override fun setNotificationStackAbsoluteBottom(bottom: Float) {
+ notificationStackAbsoluteBottom.value = bottom
+ }
+
private suspend fun getWallpaper(selectedUser: SelectedUserModel): WallpaperInfo? {
return withContext(bgDispatcher) {
wallpaperManager.getWallpaperInfoForUser(selectedUser.userInfo.id)
}
}
+
+ private fun shouldSendNotificationLayout(wallpaperInfo: WallpaperInfo?): Boolean {
+ return if (wallpaperInfo != null && wallpaperInfo.component != null) {
+ wallpaperInfo.component!!.className == MAGIC_PORTRAIT_CLASSNAME
+ } else {
+ false
+ }
+ }
+
+ companion object {
+ const val MAGIC_PORTRAIT_CLASSNAME =
+ "com.google.android.apps.magicportrait.service.MagicPortraitWallpaperService"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractor.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractor.kt
new file mode 100644
index 0000000..79ebf01
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractor.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2024 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.wallpapers.domain.interactor
+
+import com.android.systemui.wallpapers.data.repository.WallpaperRepository
+import javax.inject.Inject
+
+class WallpaperInteractor @Inject constructor(val wallpaperRepository: WallpaperRepository) {
+ fun setNotificationStackAbsoluteBottom(bottom: Float) {
+ wallpaperRepository.setNotificationStackAbsoluteBottom(bottom)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
index 0b944f0..96a0aad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
@@ -39,13 +39,13 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
+import com.android.systemui.shade.LargeScreenHeaderHelper
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationsKeyguardInteractor
import com.android.systemui.statusbar.policy.fakeConfigurationController
import com.android.systemui.statusbar.ui.fakeSystemBarUtilsProxy
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.eq
-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
@@ -57,6 +57,7 @@
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyString
import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.mock
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
@@ -122,6 +123,7 @@
{ keyguardBlueprintInteractor },
keyguardRootViewModel,
aodBurnInViewModel,
+ largeScreenHeaderHelperLazy = { mock<LargeScreenHeaderHelper>() },
)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 7cd306e..6425da4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -83,6 +83,7 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.ColorUpdateLogger;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.HeadsUpTouchHelper;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -103,7 +104,6 @@
import com.android.systemui.statusbar.notification.stack.NotificationSwipeHelper.NotificationCallback;
import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationListViewBinder;
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
-import com.android.systemui.statusbar.notification.HeadsUpTouchHelper;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -113,6 +113,7 @@
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.wallpapers.domain.interactor.WallpaperInteractor;
import org.junit.Before;
import org.junit.Test;
@@ -154,6 +155,7 @@
@Mock private KeyguardBypassController mKeyguardBypassController;
@Mock private PowerInteractor mPowerInteractor;
@Mock private PrimaryBouncerInteractor mPrimaryBouncerInteractor;
+ @Mock private WallpaperInteractor mWallpaperInteractor;
@Mock private NotificationLockscreenUserManager mNotificationLockscreenUserManager;
@Mock private MetricsLogger mMetricsLogger;
@Mock private ColorUpdateLogger mColorUpdateLogger;
@@ -1070,7 +1072,8 @@
mock(NotificationDismissibilityProvider.class),
mActivityStarter,
new ResourcesSplitShadeStateController(),
- mSensitiveNotificationProtectionController);
+ mSensitiveNotificationProtectionController,
+ mWallpaperInteractor);
}
static class LogMatcher implements ArgumentMatcher<LogMaker> {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 8a3e551..59fc0d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -102,6 +102,7 @@
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.AvalancheController;
import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController;
+import com.android.systemui.wallpapers.domain.interactor.WallpaperInteractor;
import kotlin.Unit;
@@ -146,6 +147,7 @@
@Mock private NotificationStackScrollLayoutController mStackScrollLayoutController;
@Mock private ScreenOffAnimationController mScreenOffAnimationController;
@Mock private NotificationShelf mNotificationShelf;
+ @Mock private WallpaperInteractor mWallpaperInteractor;
@Mock private NotificationStackSizeCalculator mStackSizeCalculator;
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Mock private LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
@@ -208,6 +210,7 @@
.thenReturn(mNotificationRoundnessManager);
mStackScroller.setController(mStackScrollLayoutController);
mStackScroller.setShelf(mNotificationShelf);
+ mStackScroller.setWallpaperInteractor(mWallpaperInteractor);
when(mStackScroller.getExpandHelper()).thenReturn(mExpandHelper);
doNothing().when(mGroupExpansionManager).collapseGroups();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt
index bdecf2b..b8dd334 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt
@@ -18,18 +18,21 @@
import android.app.WallpaperInfo
import android.app.WallpaperManager
+import android.content.ComponentName
import android.content.Intent
import android.content.pm.UserInfo
+import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.repository.FakeKeyguardClockRepository
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.user.data.model.SelectedUserModel
import com.android.systemui.user.data.model.SelectionStatus
import com.android.systemui.user.data.repository.FakeUserRepository
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
+import com.android.systemui.wallpapers.data.repository.WallpaperRepositoryImpl.Companion.MAGIC_PORTRAIT_CLASSNAME
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
@@ -39,6 +42,9 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
@@ -48,6 +54,8 @@
private val testDispatcher = StandardTestDispatcher()
private val testScope = TestScope(testDispatcher)
private val userRepository = FakeUserRepository()
+ private val keyguardClockRepository = FakeKeyguardClockRepository()
+ private val keyguardRepository = FakeKeyguardRepository()
private val wallpaperManager: WallpaperManager = mock()
private val underTest: WallpaperRepositoryImpl by lazy {
@@ -56,6 +64,8 @@
testDispatcher,
fakeBroadcastDispatcher,
userRepository,
+ keyguardRepository,
+ keyguardClockRepository,
wallpaperManager,
context,
)
@@ -219,7 +229,7 @@
testScope.runTest {
context.orCreateTestableResources.addOverride(
com.android.internal.R.bool.config_dozeSupportsAodWallpaper,
- false
+ false,
)
val latest by collectLastValue(underTest.wallpaperInfo)
@@ -407,7 +417,7 @@
testScope.runTest {
context.orCreateTestableResources.addOverride(
com.android.internal.R.bool.config_dozeSupportsAodWallpaper,
- false
+ false,
)
val latest by collectLastValue(underTest.wallpaperSupportsAmbientMode)
@@ -425,6 +435,54 @@
assertThat(latest).isFalse()
}
+ @Test
+ @EnableFlags(Flags.FLAG_MAGIC_PORTRAIT_WALLPAPERS)
+ fun shouldSendNotificationLayout_setMagicPortraitWallpaper_launchSendLayoutJob() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.shouldSendNotificationLayout)
+ val magicPortraitWallpaper =
+ mock<WallpaperInfo>().apply {
+ whenever(this.component)
+ .thenReturn(ComponentName(context, MAGIC_PORTRAIT_CLASSNAME))
+ }
+ whenever(wallpaperManager.getWallpaperInfoForUser(any()))
+ .thenReturn(magicPortraitWallpaper)
+ fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
+ context,
+ Intent(Intent.ACTION_WALLPAPER_CHANGED),
+ )
+ assertThat(latest).isTrue()
+ assertThat(underTest.sendLockscreenLayoutJob).isNotNull()
+ assertThat(underTest.sendLockscreenLayoutJob!!.isActive).isEqualTo(true)
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_MAGIC_PORTRAIT_WALLPAPERS)
+ fun shouldSendNotificationLayout_setNotMagicPortraitWallpaper_cancelSendLayoutJob() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.shouldSendNotificationLayout)
+ val magicPortraitWallpaper = MAGIC_PORTRAIT_WP
+ whenever(wallpaperManager.getWallpaperInfoForUser(any()))
+ .thenReturn(magicPortraitWallpaper)
+ fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
+ context,
+ Intent(Intent.ACTION_WALLPAPER_CHANGED),
+ )
+ assertThat(latest).isTrue()
+ assertThat(underTest.sendLockscreenLayoutJob).isNotNull()
+ assertThat(underTest.sendLockscreenLayoutJob!!.isActive).isEqualTo(true)
+
+ val nonMagicPortraitWallpaper = UNSUPPORTED_WP
+ whenever(wallpaperManager.getWallpaperInfoForUser(any()))
+ .thenReturn(nonMagicPortraitWallpaper)
+ fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly(
+ context,
+ Intent(Intent.ACTION_WALLPAPER_CHANGED),
+ )
+ assertThat(latest).isFalse()
+ assertThat(underTest.sendLockscreenLayoutJob?.isCancelled).isEqualTo(true)
+ }
+
private companion object {
val USER_WITH_UNSUPPORTED_WP = UserInfo(/* id= */ 3, /* name= */ "user3", /* flags= */ 0)
val UNSUPPORTED_WP =
@@ -433,5 +491,10 @@
val USER_WITH_SUPPORTED_WP = UserInfo(/* id= */ 4, /* name= */ "user4", /* flags= */ 0)
val SUPPORTED_WP =
mock<WallpaperInfo>().apply { whenever(this.supportsAmbientMode()).thenReturn(true) }
+
+ val MAGIC_PORTRAIT_WP =
+ mock<WallpaperInfo>().apply {
+ whenever(this.component).thenReturn(ComponentName("", MAGIC_PORTRAIT_CLASSNAME))
+ }
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/app/WallpaperManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/app/WallpaperManagerKosmos.kt
new file mode 100644
index 0000000..2850ab7
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/app/WallpaperManagerKosmos.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 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.app
+
+import android.app.WallpaperManager
+import android.content.applicationContext
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+@OptIn(ExperimentalCoroutinesApi::class)
+val Kosmos.wallpaperManager: WallpaperManager by Fixture {
+ WallpaperManager.getInstance(applicationContext)
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt
index 5e5f8cb..159dd34 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardClockRepository.kt
@@ -46,16 +46,27 @@
private val _previewClock = MutableStateFlow(Mockito.mock(ClockController::class.java))
override val previewClock: Flow<ClockController>
get() = _previewClock
+
+ private val _notificationDefaultTop = MutableStateFlow(0F)
+ override val notificationDefaultTop: StateFlow<Float>
+ get() = _notificationDefaultTop
+
override val clockEventController: ClockEventController
get() = mock()
+
override val shouldForceSmallClock: Boolean
get() = _shouldForceSmallClock
+
private var _shouldForceSmallClock: Boolean = false
override fun setClockSize(size: ClockSize) {
_clockSize.value = size
}
+ override fun setNotificationDefaultTop(top: Float) {
+ _notificationDefaultTop.value = top
+ }
+
fun setSelectedClockSize(size: ClockSizeSetting) {
_selectedClockSize.value = size
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 54a6c0c..e513e8d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -131,6 +131,10 @@
private val _isEncryptedOrLockdown = MutableStateFlow(true)
override val isEncryptedOrLockdown: Flow<Boolean> = _isEncryptedOrLockdown
+ private val _shortcutAbsoluteTop = MutableStateFlow(0F)
+ override val shortcutAbsoluteTop: StateFlow<Float>
+ get() = _shortcutAbsoluteTop.asStateFlow()
+
private val _isKeyguardEnabled = MutableStateFlow(true)
override val isKeyguardEnabled: StateFlow<Boolean> = _isKeyguardEnabled.asStateFlow()
@@ -241,7 +245,7 @@
override fun setBiometricUnlockState(
mode: BiometricUnlockMode,
- source: BiometricUnlockSource?
+ source: BiometricUnlockSource?,
) {
_biometricUnlockState.tryEmit(BiometricUnlockModel(mode, source))
}
@@ -294,6 +298,10 @@
return isShowKeyguardWhenReenabled
}
+ override fun setShortcutAbsoluteTop(top: Float) {
+ _shortcutAbsoluteTop.value = top
+ }
+
override fun setCanIgnoreAuthAndReturnToGone(canWake: Boolean) {
_canIgnoreAuthAndReturnToGone.value = canWake
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
index 12d7c49..49a8c18 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepositoryKosmos.kt
@@ -29,9 +29,10 @@
import com.android.systemui.keyguard.ui.viewmodel.keyguardRootViewModel
import com.android.systemui.keyguard.ui.viewmodel.keyguardSmartspaceViewModel
import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.util.mockito.mock
+import com.android.systemui.shade.LargeScreenHeaderHelper
import java.util.Optional
import org.mockito.Mockito.spy
+import org.mockito.kotlin.mock
val Kosmos.keyguardClockSection: ClockSection by
Kosmos.Fixture {
@@ -43,6 +44,7 @@
blueprintInteractor = { keyguardBlueprintInteractor },
rootViewModel = keyguardRootViewModel,
aodBurnInViewModel = aodBurnInViewModel,
+ largeScreenHeaderHelperLazy = { mock<LargeScreenHeaderHelper>() },
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt
index d52883e..bdb9abb 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorKosmos.kt
@@ -27,13 +27,13 @@
val Kosmos.keyguardClockInteractor by
Kosmos.Fixture {
KeyguardClockInteractor(
- keyguardClockRepository = keyguardClockRepository,
- applicationScope = applicationCoroutineScope,
mediaCarouselInteractor = mediaCarouselInteractor,
activeNotificationsInteractor = activeNotificationsInteractor,
shadeInteractor = shadeInteractor,
keyguardInteractor = keyguardInteractor,
keyguardTransitionInteractor = keyguardTransitionInteractor,
headsUpNotificationInteractor = headsUpNotificationInteractor,
+ applicationScope = applicationCoroutineScope,
+ keyguardClockRepository = keyguardClockRepository,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryKosmos.kt
new file mode 100644
index 0000000..1d8c891
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryKosmos.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 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.wallpapers.data.repository
+
+import android.content.applicationContext
+import com.android.app.wallpaperManager
+import com.android.systemui.broadcast.broadcastDispatcher
+import com.android.systemui.keyguard.data.repository.keyguardClockRepository
+import com.android.systemui.keyguard.data.repository.keyguardRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.user.data.repository.userRepository
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+@OptIn(ExperimentalCoroutinesApi::class)
+val Kosmos.wallpaperRepository by Fixture {
+ WallpaperRepositoryImpl(
+ context = applicationContext,
+ scope = testScope,
+ bgDispatcher = testDispatcher,
+ broadcastDispatcher = broadcastDispatcher,
+ userRepository = userRepository,
+ wallpaperManager = wallpaperManager,
+ keyguardClockRepository = keyguardClockRepository,
+ keyguardRepository = keyguardRepository,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractorKosmos.kt
new file mode 100644
index 0000000..5278351
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractorKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 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.wallpapers.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.wallpapers.data.repository.wallpaperRepository
+
+val Kosmos.wallpaperInteractor by
+ Kosmos.Fixture { WallpaperInteractor(wallpaperRepository = wallpaperRepository) }