Merge "Add standalone weather view to lockscreen if decoupling isenabled." into tm-qpr-dev
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 -> {
|
||||
|
||||
@@ -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?) {
|
||||
|
||||
Reference in New Issue
Block a user