Merge "Add standalone weather view to lockscreen if decoupling isenabled." into tm-qpr-dev

This commit is contained in:
Xiaowen Lei
2023-01-27 16:53:55 +00:00
committed by Android (Google) Code Review
5 changed files with 250 additions and 48 deletions

View File

@@ -88,7 +88,9 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
private final ClockRegistry.ClockChangeListener mClockChangedListener;
private ViewGroup mStatusArea;
// If set will replace keyguard_slice_view
// If the SMARTSPACE flag is set, keyguard_slice_view is replaced by the following views.
private View mWeatherView;
private View mSmartspaceView;
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
@@ -192,10 +194,17 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
if (mSmartspaceController.isEnabled()) {
View ksv = mView.findViewById(R.id.keyguard_slice_view);
int ksvIndex = mStatusArea.indexOfChild(ksv);
int viewIndex = mStatusArea.indexOfChild(ksv);
ksv.setVisibility(View.GONE);
addSmartspaceView(ksvIndex);
// TODO(b/261757708): add content observer for the Settings toggle and add/remove
// weather according to the Settings.
if (mSmartspaceController.isDateWeatherDecoupled()) {
addWeatherView(viewIndex);
viewIndex += 1;
}
addSmartspaceView(viewIndex);
}
mSecureSettings.registerContentObserverForUser(
@@ -237,6 +246,18 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
}
}
private void addWeatherView(int index) {
mWeatherView = mSmartspaceController.buildAndConnectWeatherView(mView);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
MATCH_PARENT, WRAP_CONTENT);
mStatusArea.addView(mWeatherView, index, lp);
int startPadding = getContext().getResources().getDimensionPixelSize(
R.dimen.below_clock_padding_start);
int endPadding = getContext().getResources().getDimensionPixelSize(
R.dimen.below_clock_padding_end);
mWeatherView.setPaddingRelative(startPadding, 0, endPadding, 0);
}
private void addSmartspaceView(int index) {
mSmartspaceView = mSmartspaceController.buildAndConnectView(mView);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(

View File

@@ -107,6 +107,8 @@ import com.android.wm.shell.bubbles.Bubbles;
import java.util.Optional;
import java.util.concurrent.Executor;
import javax.inject.Named;
import dagger.Binds;
import dagger.BindsOptionalOf;
import dagger.Module;
@@ -214,6 +216,10 @@ public abstract class SystemUIModule {
@BindsOptionalOf
abstract BcSmartspaceConfigPlugin optionalBcSmartspaceConfigPlugin();
@BindsOptionalOf
@Named(SmartspaceModule.WEATHER_SMARTSPACE_DATA_PLUGIN)
abstract BcSmartspaceDataPlugin optionalWeatherSmartspaceConfigPlugin();
@BindsOptionalOf
abstract Recents optionalRecents();

View File

@@ -18,7 +18,6 @@ package com.android.systemui.smartspace.dagger
import com.android.systemui.plugins.BcSmartspaceDataPlugin
import com.android.systemui.smartspace.SmartspacePrecondition
import com.android.systemui.smartspace.SmartspaceTargetFilter
import com.android.systemui.smartspace.filters.LockscreenAndDreamTargetFilter
import com.android.systemui.smartspace.preconditions.LockscreenPrecondition
import dagger.Binds
import dagger.BindsOptionalOf
@@ -34,11 +33,6 @@ abstract class SmartspaceModule {
*/
const val DREAM_SMARTSPACE_DATA_PLUGIN = "dreams_smartspace_data_plugin"
/**
* The lockscreen smartspace target filter.
*/
const val LOCKSCREEN_SMARTSPACE_TARGET_FILTER = "lockscreen_smartspace_target_filter"
/**
* The dream smartspace target filter.
*/
@@ -48,6 +42,11 @@ abstract class SmartspaceModule {
* The precondition for dream smartspace
*/
const val DREAM_SMARTSPACE_PRECONDITION = "dream_smartspace_precondition"
/**
* The BcSmartspaceDataPlugin for the standalone weather.
*/
const val WEATHER_SMARTSPACE_DATA_PLUGIN = "weather_smartspace_data_plugin"
}
@BindsOptionalOf
@@ -58,12 +57,6 @@ abstract class SmartspaceModule {
@Named(DREAM_SMARTSPACE_DATA_PLUGIN)
abstract fun optionalDreamsBcSmartspaceDataPlugin(): BcSmartspaceDataPlugin?
@Binds
@Named(LOCKSCREEN_SMARTSPACE_TARGET_FILTER)
abstract fun provideLockscreenSmartspaceTargetFilter(
filter: LockscreenAndDreamTargetFilter?
): SmartspaceTargetFilter?
@Binds
@Named(DREAM_SMARTSPACE_PRECONDITION)
abstract fun bindSmartspacePrecondition(

View File

@@ -52,6 +52,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.settings.UserTracker
import com.android.systemui.shared.regionsampling.RegionSampler
import com.android.systemui.shared.regionsampling.UpdateColorCallback
import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.WEATHER_SMARTSPACE_DATA_PLUGIN
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.DeviceProvisionedController
@@ -60,6 +61,7 @@ import com.android.systemui.util.settings.SecureSettings
import java.util.Optional
import java.util.concurrent.Executor
import javax.inject.Inject
import javax.inject.Named
/** Controller for managing the smartspace view on the lockscreen */
@SysUISingleton
@@ -82,6 +84,8 @@ constructor(
@Main private val uiExecutor: Executor,
@Background private val bgExecutor: Executor,
@Main private val handler: Handler,
@Named(WEATHER_SMARTSPACE_DATA_PLUGIN)
optionalWeatherPlugin: Optional<BcSmartspaceDataPlugin>,
optionalPlugin: Optional<BcSmartspaceDataPlugin>,
optionalConfigPlugin: Optional<BcSmartspaceConfigPlugin>,
) {
@@ -90,6 +94,7 @@ constructor(
}
private var session: SmartspaceSession? = null
private val weatherPlugin: BcSmartspaceDataPlugin? = optionalWeatherPlugin.orElse(null)
private val plugin: BcSmartspaceDataPlugin? = optionalPlugin.orElse(null)
private val configPlugin: BcSmartspaceConfigPlugin? = optionalConfigPlugin.orElse(null)
@@ -131,6 +136,10 @@ constructor(
private val sessionListener = SmartspaceSession.OnTargetsAvailableListener { targets ->
execution.assertIsMainThread()
// The weather data plugin takes unfiltered targets and performs the filtering internally.
weatherPlugin?.onTargetsAvailable(targets)
val filteredTargets = targets.filter(::filterSmartspaceTarget)
plugin?.onTargetsAvailable(filteredTargets)
if (!isContentUpdatedOnce) {
@@ -209,11 +218,37 @@ constructor(
return plugin != null
}
fun isDateWeatherDecoupled(): Boolean {
execution.assertIsMainThread()
return featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED) &&
weatherPlugin != null
}
private fun updateBypassEnabled() {
val bypassEnabled = bypassController.bypassEnabled
smartspaceViews.forEach { it.setKeyguardBypassEnabled(bypassEnabled) }
}
/**
* Constructs the weather view and connects it to the smartspace service.
*/
fun buildAndConnectWeatherView(parent: ViewGroup): View? {
execution.assertIsMainThread()
if (!isEnabled()) {
throw RuntimeException("Cannot build view when not enabled")
}
if (!isDateWeatherDecoupled()) {
throw RuntimeException("Cannot build weather view when not decoupled")
}
val view = buildView(parent, weatherPlugin)
connectSession()
return view
}
/**
* Constructs the smartspace view and connects it to the smartspace service.
*/
@@ -224,17 +259,17 @@ constructor(
throw RuntimeException("Cannot build view when not enabled")
}
val view = buildView(parent)
val view = buildView(parent, plugin, configPlugin)
connectSession()
return view
}
fun requestSmartspaceUpdate() {
session?.requestSmartspaceUpdate()
}
private fun buildView(parent: ViewGroup): View? {
private fun buildView(
parent: ViewGroup,
plugin: BcSmartspaceDataPlugin?,
configPlugin: BcSmartspaceConfigPlugin? = null
): View? {
if (plugin == null) {
return null
}
@@ -242,7 +277,7 @@ constructor(
val ssView = plugin.getView(parent)
ssView.setUiSurface(BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
ssView.registerDataProvider(plugin)
ssView.registerConfigProvider(configPlugin)
configPlugin?.let { ssView.registerConfigProvider(it) }
ssView.setIntentStarter(object : BcSmartspaceDataPlugin.IntentStarter {
override fun startIntent(view: View, intent: Intent, showOnLockscreen: Boolean) {
@@ -273,7 +308,8 @@ constructor(
}
private fun connectSession() {
if (plugin == null || session != null || smartspaceViews.isEmpty()) {
if (weatherPlugin == null && plugin == null) return
if (session != null || smartspaceViews.isEmpty()) {
return
}
@@ -310,14 +346,20 @@ constructor(
statusBarStateController.addCallback(statusBarStateListener)
bypassController.registerOnBypassStateChangedListener(bypassStateChangedListener)
plugin.registerSmartspaceEventNotifier {
e -> session?.notifySmartspaceEvent(e)
}
weatherPlugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) }
plugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) }
updateBypassEnabled()
reloadSmartspace()
}
/**
* Requests the smartspace session for an update.
*/
fun requestSmartspaceUpdate() {
session?.requestSmartspaceUpdate()
}
/**
* Disconnects the smartspace view from the smartspace service and cleans up any resources.
*/
@@ -341,9 +383,13 @@ constructor(
bypassController.unregisterOnBypassStateChangedListener(bypassStateChangedListener)
session = null
weatherPlugin?.registerSmartspaceEventNotifier(null)
weatherPlugin?.onTargetsAvailable(emptyList())
plugin?.registerSmartspaceEventNotifier(null)
plugin?.onTargetsAvailable(emptyList())
Log.d(TAG, "Ending smartspace session for lockscreen")
Log.d(TAG, "Ended smartspace session for lockscreen")
}
fun addListener(listener: SmartspaceTargetListener) {
@@ -357,8 +403,11 @@ constructor(
}
private fun filterSmartspaceTarget(t: SmartspaceTarget): Boolean {
if (isDateWeatherDecoupled()) {
return t.featureType != SmartspaceTarget.FEATURE_WEATHER
}
if (!showNotifications) {
return t.getFeatureType() == SmartspaceTarget.FEATURE_WEATHER
return t.featureType == SmartspaceTarget.FEATURE_WEATHER
}
return when (t.userHandle) {
userTracker.userHandle -> {

View File

@@ -34,6 +34,7 @@ import android.widget.FrameLayout
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.BcSmartspaceConfigPlugin
import com.android.systemui.plugins.BcSmartspaceDataPlugin
@@ -111,6 +112,9 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
@Mock
private lateinit var handler: Handler
@Mock
private lateinit var weatherPlugin: BcSmartspaceDataPlugin
@Mock
private lateinit var plugin: BcSmartspaceDataPlugin
@@ -151,6 +155,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
KeyguardBypassController.OnBypassStateChangedListener
private lateinit var deviceProvisionedListener: DeviceProvisionedListener
private lateinit var weatherSmartspaceView: SmartspaceView
private lateinit var smartspaceView: SmartspaceView
private val clock = FakeSystemClock()
@@ -176,16 +181,22 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
fun setUp() {
MockitoAnnotations.initMocks(this)
// Todo(b/261760571): flip the flag value here when feature is launched, and update relevant
// tests.
`when`(featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED)).thenReturn(false)
`when`(secureSettings.getUriFor(PRIVATE_LOCKSCREEN_SETTING))
.thenReturn(fakePrivateLockscreenSettingUri)
`when`(secureSettings.getUriFor(NOTIF_ON_LOCKSCREEN_SETTING))
.thenReturn(fakeNotifOnLockscreenSettingUri)
`when`(smartspaceManager.createSmartspaceSession(any())).thenReturn(smartspaceSession)
`when`(weatherPlugin.getView(any())).thenReturn(
createWeatherSmartspaceView(), createWeatherSmartspaceView())
`when`(plugin.getView(any())).thenReturn(createSmartspaceView(), createSmartspaceView())
`when`(userTracker.userProfiles).thenReturn(userList)
`when`(statusBarStateController.dozeAmount).thenReturn(0.5f)
`when`(deviceProvisionedController.isDeviceProvisioned()).thenReturn(true)
`when`(deviceProvisionedController.isCurrentUserSetup()).thenReturn(true)
`when`(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
`when`(deviceProvisionedController.isCurrentUserSetup).thenReturn(true)
setActiveUser(userHandlePrimary)
setAllowPrivateNotifications(userHandlePrimary, true)
@@ -210,6 +221,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
executor,
bgExecutor,
handler,
Optional.of(weatherPlugin),
Optional.of(plugin),
Optional.of(configPlugin),
)
@@ -218,11 +230,22 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
deviceProvisionedListener = deviceProvisionedCaptor.value
}
@Test(expected = RuntimeException::class)
fun testBuildAndConnectWeatherView_throwsIfDecouplingDisabled() {
// GIVEN the feature flag is disabled
`when`(featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED)).thenReturn(false)
// WHEN we try to build the view
controller.buildAndConnectWeatherView(fakeParent)
// THEN an exception is thrown
}
@Test
fun connectOnlyAfterDeviceIsProvisioned() {
fun testBuildAndConnectView_connectsOnlyAfterDeviceIsProvisioned() {
// GIVEN an unprovisioned device and an attempt to connect
`when`(deviceProvisionedController.isDeviceProvisioned()).thenReturn(false)
`when`(deviceProvisionedController.isCurrentUserSetup()).thenReturn(false)
`when`(deviceProvisionedController.isDeviceProvisioned).thenReturn(false)
`when`(deviceProvisionedController.isCurrentUserSetup).thenReturn(false)
// WHEN a connection attempt is made and view is attached
val view = controller.buildAndConnectView(fakeParent)
@@ -232,8 +255,8 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
verify(smartspaceManager, never()).createSmartspaceSession(any())
// WHEN it does become provisioned
`when`(deviceProvisionedController.isDeviceProvisioned()).thenReturn(true)
`when`(deviceProvisionedController.isCurrentUserSetup()).thenReturn(true)
`when`(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
`when`(deviceProvisionedController.isCurrentUserSetup).thenReturn(true)
deviceProvisionedListener.onUserSetupChanged()
// THEN the session is created
@@ -243,7 +266,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
}
@Test
fun testListenersAreRegistered() {
fun testAddListener_registersListenersForPlugin() {
// GIVEN a listener is added after a session is created
connectSession()
@@ -252,10 +275,12 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
// THEN the listener is registered to the underlying plugin
verify(plugin).registerListener(controllerListener)
// The listener is registered only for the plugin, not the weather plugin.
verify(weatherPlugin, never()).registerListener(any())
}
@Test
fun testEarlyRegisteredListenersAreAttachedAfterConnected() {
fun testAddListener_earlyRegisteredListenersAreAttachedAfterConnected() {
// GIVEN a listener that is registered before the session is created
controller.addListener(controllerListener)
@@ -264,10 +289,12 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
// THEN the listener is subsequently registered
verify(plugin).registerListener(controllerListener)
// The listener is registered only for the plugin, not the weather plugin.
verify(weatherPlugin, never()).registerListener(any())
}
@Test
fun testEmptyListIsEmittedAndNotifierRemovedAfterDisconnect() {
fun testDisconnect_emitsEmptyListAndRemovesNotifier() {
// GIVEN a registered listener on an active session
connectSession()
clearInvocations(plugin)
@@ -279,10 +306,12 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
// THEN the listener receives an empty list of targets and unregisters the notifier
verify(plugin).onTargetsAvailable(emptyList())
verify(plugin).registerSmartspaceEventNotifier(null)
verify(weatherPlugin).onTargetsAvailable(emptyList())
verify(weatherPlugin).registerSmartspaceEventNotifier(null)
}
@Test
fun testUserChangeReloadsSmartspace() {
fun testUserChange_reloadsSmartspace() {
// GIVEN a connected smartspace session
connectSession()
@@ -294,7 +323,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
}
@Test
fun testSettingsChangeReloadsSmartspace() {
fun testSettingsChange_reloadsSmartspace() {
// GIVEN a connected smartspace session
connectSession()
@@ -306,7 +335,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
}
@Test
fun testThemeChangeUpdatesTextColor() {
fun testThemeChange_updatesTextColor() {
// GIVEN a connected smartspace session
connectSession()
@@ -318,7 +347,22 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
}
@Test
fun testDozeAmountChangeUpdatesView() {
fun testThemeChange_ifDecouplingEnabled_updatesTextColor() {
`when`(featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED)).thenReturn(true)
// GIVEN a connected smartspace session
connectSession()
// WHEN the theme changes
configChangeListener.onThemeChanged()
// We update the new text color to match the wallpaper color
verify(weatherSmartspaceView).setPrimaryTextColor(anyInt())
verify(smartspaceView).setPrimaryTextColor(anyInt())
}
@Test
fun testDozeAmountChange_updatesView() {
// GIVEN a connected smartspace session
connectSession()
@@ -330,7 +374,22 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
}
@Test
fun testKeyguardBypassEnabledUpdatesView() {
fun testDozeAmountChange_ifDecouplingEnabled_updatesViews() {
`when`(featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED)).thenReturn(true)
// GIVEN a connected smartspace session
connectSession()
// WHEN the doze amount changes
statusBarStateListener.onDozeAmountChanged(0.1f, 0.7f)
// We pass that along to the view
verify(weatherSmartspaceView).setDozeAmount(0.7f)
verify(smartspaceView).setDozeAmount(0.7f)
}
@Test
fun testKeyguardBypassEnabled_updatesView() {
// GIVEN a connected smartspace session
connectSession()
`when`(keyguardBypassController.bypassEnabled).thenReturn(true)
@@ -424,6 +483,27 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
)))
}
@Test
fun testSessionListener_ifDecouplingEnabled_weatherTargetIsFilteredOut() {
`when`(featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED)).thenReturn(true)
connectSession()
// WHEN we receive a list of targets
val targets = listOf(
makeTarget(1, userHandlePrimary, isSensitive = true),
makeTarget(2, userHandlePrimary),
makeTarget(3, userHandleManaged),
makeTarget(4, userHandlePrimary, featureType = SmartspaceTarget.FEATURE_WEATHER)
)
sessionListener.onTargetsAvailable(targets)
// THEN all non-sensitive content is still shown
verify(plugin).onTargetsAvailable(eq(listOf(targets[0], targets[1], targets[2])))
// No filtering is applied for the weather plugin
verify(weatherPlugin).onTargetsAvailable(eq(targets))
}
@Test
fun testSettingsAreReloaded() {
// GIVEN a connected session where the privacy settings later flip to false
@@ -514,6 +594,16 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
verify(smartspaceView2).registerConfigProvider(configPlugin)
}
@Test
fun testWeatherViewUsesSameSession() {
`when`(featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED)).thenReturn(true)
// GIVEN a connected session
connectSession()
// No checks is needed here, since connectSession() already checks internally that
// createSmartspaceSession is invoked only once.
}
@Test
fun testViewGetInitializedWithBypassEnabledState() {
// GIVEN keyguard bypass is enabled.
@@ -531,8 +621,8 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
fun testConnectAttemptBeforeInitializationShouldNotCreateSession() {
// GIVEN an uninitalized smartspaceView
// WHEN the device is provisioned
`when`(deviceProvisionedController.isDeviceProvisioned()).thenReturn(true)
`when`(deviceProvisionedController.isCurrentUserSetup()).thenReturn(true)
`when`(deviceProvisionedController.isDeviceProvisioned).thenReturn(true)
`when`(deviceProvisionedController.isCurrentUserSetup).thenReturn(true)
deviceProvisionedListener.onDeviceProvisionedChanged()
// THEN no calls to createSmartspaceSession should occur
@@ -542,9 +632,23 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
}
private fun connectSession() {
if (controller.isDateWeatherDecoupled()) {
val weatherView = controller.buildAndConnectWeatherView(fakeParent)
weatherSmartspaceView = weatherView as SmartspaceView
fakeParent.addView(weatherView)
controller.stateChangeListener.onViewAttachedToWindow(weatherView)
verify(weatherSmartspaceView).setUiSurface(
BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
verify(weatherSmartspaceView).registerDataProvider(weatherPlugin)
verify(weatherSmartspaceView).setPrimaryTextColor(anyInt())
verify(weatherSmartspaceView).setDozeAmount(0.5f)
}
val view = controller.buildAndConnectView(fakeParent)
smartspaceView = view as SmartspaceView
fakeParent.addView(view)
controller.stateChangeListener.onViewAttachedToWindow(view)
verify(smartspaceView).setUiSurface(BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
@@ -554,6 +658,8 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
.addOnTargetsAvailableListener(any(), capture(sessionListenerCaptor))
sessionListener = sessionListenerCaptor.value
verify(smartspaceManager).createSmartspaceSession(any())
verify(userTracker).addCallback(capture(userTrackerCaptor), any())
userListener = userTrackerCaptor.value
@@ -578,9 +684,11 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
verify(smartspaceView).setPrimaryTextColor(anyInt())
verify(smartspaceView).setDozeAmount(0.5f)
clearInvocations(view)
fakeParent.addView(view)
if (controller.isDateWeatherDecoupled()) {
clearInvocations(weatherSmartspaceView)
}
clearInvocations(smartspaceView)
}
private fun setActiveUser(userHandle: UserHandle) {
@@ -626,6 +734,31 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
).thenReturn(if (value) 1 else 0)
}
// Separate function for the weather view, which doesn't implement all functions in interface.
private fun createWeatherSmartspaceView(): SmartspaceView {
return spy(object : View(context), SmartspaceView {
override fun registerDataProvider(plugin: BcSmartspaceDataPlugin?) {
}
override fun setPrimaryTextColor(color: Int) {
}
override fun setIsDreaming(isDreaming: Boolean) {
}
override fun setUiSurface(uiSurface: String) {
}
override fun setDozeAmount(amount: Float) {
}
override fun setIntentStarter(intentStarter: BcSmartspaceDataPlugin.IntentStarter?) {
}
override fun setFalsingManager(falsingManager: FalsingManager?) {
}
})
}
private fun createSmartspaceView(): SmartspaceView {
return spy(object : View(context), SmartspaceView {
override fun registerDataProvider(plugin: BcSmartspaceDataPlugin?) {