Merge "Read weather data from smartspace extras" into tm-qpr-dev am: 41b93c6eea am: e6022ac3b7
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21274075 Change-Id: I59c10bde18b1156e31e20753b694ae49635c30c2 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -113,7 +113,7 @@ interface ClockEvents {
|
||||
fun onColorPaletteChanged(resources: Resources) {}
|
||||
|
||||
/** Call whenever the weather data should update */
|
||||
fun onWeatherDataChanged(data: Weather) {}
|
||||
fun onWeatherDataChanged(data: WeatherData) {}
|
||||
}
|
||||
|
||||
/** Methods which trigger various clock animations */
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
package com.android.systemui.plugins
|
||||
|
||||
import android.os.Bundle
|
||||
|
||||
class Weather(val conditions: WeatherStateIcon, val temperature: Int, val isCelsius: Boolean) {
|
||||
companion object {
|
||||
private const val TAG = "Weather"
|
||||
private const val WEATHER_STATE_ICON_KEY = "weather_state_icon_extra_key"
|
||||
private const val TEMPERATURE_VALUE_KEY = "temperature_value_extra_key"
|
||||
private const val TEMPERATURE_UNIT_KEY = "temperature_unit_extra_key"
|
||||
private const val INVALID_TEMPERATURE = Int.MIN_VALUE
|
||||
|
||||
fun fromBundle(extras: Bundle): Weather? {
|
||||
val icon =
|
||||
WeatherStateIcon.fromInt(
|
||||
extras.getInt(WEATHER_STATE_ICON_KEY, WeatherStateIcon.UNKNOWN_ICON.id)
|
||||
)
|
||||
if (icon == null || icon == WeatherStateIcon.UNKNOWN_ICON) {
|
||||
return null
|
||||
}
|
||||
val temperature = extras.getInt(TEMPERATURE_VALUE_KEY, INVALID_TEMPERATURE)
|
||||
if (temperature == INVALID_TEMPERATURE) {
|
||||
return null
|
||||
}
|
||||
return Weather(icon, temperature, extras.getBoolean(TEMPERATURE_UNIT_KEY))
|
||||
}
|
||||
}
|
||||
|
||||
enum class WeatherStateIcon(val id: Int) {
|
||||
UNKNOWN_ICON(0),
|
||||
|
||||
// Clear, day & night.
|
||||
SUNNY(1),
|
||||
CLEAR_NIGHT(2),
|
||||
|
||||
// Mostly clear, day & night.
|
||||
MOSTLY_SUNNY(3),
|
||||
MOSTLY_CLEAR_NIGHT(4),
|
||||
|
||||
// Partly cloudy, day & night.
|
||||
PARTLY_CLOUDY(5),
|
||||
PARTLY_CLOUDY_NIGHT(6),
|
||||
|
||||
// Mostly cloudy, day & night.
|
||||
MOSTLY_CLOUDY_DAY(7),
|
||||
MOSTLY_CLOUDY_NIGHT(8),
|
||||
CLOUDY(9),
|
||||
HAZE_FOG_DUST_SMOKE(10),
|
||||
DRIZZLE(11),
|
||||
HEAVY_RAIN(12),
|
||||
SHOWERS_RAIN(13),
|
||||
|
||||
// Scattered showers, day & night.
|
||||
SCATTERED_SHOWERS_DAY(14),
|
||||
SCATTERED_SHOWERS_NIGHT(15),
|
||||
|
||||
// Isolated scattered thunderstorms, day & night.
|
||||
ISOLATED_SCATTERED_TSTORMS_DAY(16),
|
||||
ISOLATED_SCATTERED_TSTORMS_NIGHT(17),
|
||||
STRONG_TSTORMS(18),
|
||||
BLIZZARD(19),
|
||||
BLOWING_SNOW(20),
|
||||
FLURRIES(21),
|
||||
HEAVY_SNOW(22),
|
||||
|
||||
// Scattered snow showers, day & night.
|
||||
SCATTERED_SNOW_SHOWERS_DAY(23),
|
||||
SCATTERED_SNOW_SHOWERS_NIGHT(24),
|
||||
SNOW_SHOWERS_SNOW(25),
|
||||
MIXED_RAIN_HAIL_RAIN_SLEET(26),
|
||||
SLEET_HAIL(27),
|
||||
TORNADO(28),
|
||||
TROPICAL_STORM_HURRICANE(29),
|
||||
WINDY_BREEZY(30),
|
||||
WINTRY_MIX_RAIN_SNOW(31);
|
||||
|
||||
companion object {
|
||||
fun fromInt(value: Int) = values().firstOrNull { it.id == value }
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "$conditions $temperature${if (isCelsius) "C" else "F"}"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package com.android.systemui.plugins
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.VisibleForTesting
|
||||
|
||||
class WeatherData
|
||||
private constructor(
|
||||
val description: String,
|
||||
val state: WeatherStateIcon,
|
||||
val useCelsius: Boolean,
|
||||
val temperature: Int,
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "WeatherData"
|
||||
@VisibleForTesting const val DESCRIPTION_KEY = "description"
|
||||
@VisibleForTesting const val STATE_KEY = "state"
|
||||
@VisibleForTesting const val USE_CELSIUS_KEY = "use_celsius"
|
||||
@VisibleForTesting const val TEMPERATURE_KEY = "temperature"
|
||||
private const val INVALID_WEATHER_ICON_STATE = -1
|
||||
|
||||
fun fromBundle(extras: Bundle): WeatherData? {
|
||||
val description = extras.getString(DESCRIPTION_KEY)
|
||||
val state =
|
||||
WeatherStateIcon.fromInt(extras.getInt(STATE_KEY, INVALID_WEATHER_ICON_STATE))
|
||||
val temperature = readIntFromBundle(extras, TEMPERATURE_KEY)
|
||||
return if (
|
||||
description == null ||
|
||||
state == null ||
|
||||
!extras.containsKey(USE_CELSIUS_KEY) ||
|
||||
temperature == null
|
||||
)
|
||||
null
|
||||
else
|
||||
WeatherData(
|
||||
description = description,
|
||||
state = state,
|
||||
useCelsius = extras.getBoolean(USE_CELSIUS_KEY),
|
||||
temperature = temperature
|
||||
)
|
||||
}
|
||||
|
||||
private fun readIntFromBundle(extras: Bundle, key: String): Int? =
|
||||
try {
|
||||
extras.getString(key).toInt()
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
enum class WeatherStateIcon(val id: Int) {
|
||||
UNKNOWN_ICON(0),
|
||||
|
||||
// Clear, day & night.
|
||||
SUNNY(1),
|
||||
CLEAR_NIGHT(2),
|
||||
|
||||
// Mostly clear, day & night.
|
||||
MOSTLY_SUNNY(3),
|
||||
MOSTLY_CLEAR_NIGHT(4),
|
||||
|
||||
// Partly cloudy, day & night.
|
||||
PARTLY_CLOUDY(5),
|
||||
PARTLY_CLOUDY_NIGHT(6),
|
||||
|
||||
// Mostly cloudy, day & night.
|
||||
MOSTLY_CLOUDY_DAY(7),
|
||||
MOSTLY_CLOUDY_NIGHT(8),
|
||||
CLOUDY(9),
|
||||
HAZE_FOG_DUST_SMOKE(10),
|
||||
DRIZZLE(11),
|
||||
HEAVY_RAIN(12),
|
||||
SHOWERS_RAIN(13),
|
||||
|
||||
// Scattered showers, day & night.
|
||||
SCATTERED_SHOWERS_DAY(14),
|
||||
SCATTERED_SHOWERS_NIGHT(15),
|
||||
|
||||
// Isolated scattered thunderstorms, day & night.
|
||||
ISOLATED_SCATTERED_TSTORMS_DAY(16),
|
||||
ISOLATED_SCATTERED_TSTORMS_NIGHT(17),
|
||||
STRONG_TSTORMS(18),
|
||||
BLIZZARD(19),
|
||||
BLOWING_SNOW(20),
|
||||
FLURRIES(21),
|
||||
HEAVY_SNOW(22),
|
||||
|
||||
// Scattered snow showers, day & night.
|
||||
SCATTERED_SNOW_SHOWERS_DAY(23),
|
||||
SCATTERED_SNOW_SHOWERS_NIGHT(24),
|
||||
SNOW_SHOWERS_SNOW(25),
|
||||
MIXED_RAIN_HAIL_RAIN_SLEET(26),
|
||||
SLEET_HAIL(27),
|
||||
TORNADO(28),
|
||||
TROPICAL_STORM_HURRICANE(29),
|
||||
WINDY_BREEZY(30),
|
||||
WINTRY_MIX_RAIN_SNOW(31);
|
||||
|
||||
companion object {
|
||||
fun fromInt(value: Int) = values().firstOrNull { it.id == value }
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val unit = if (useCelsius) "C" else "F"
|
||||
return "$state (\"$description\") $temperature°$unit"
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ import com.android.systemui.plugins.ClockTickRate
|
||||
import com.android.systemui.plugins.log.LogBuffer
|
||||
import com.android.systemui.plugins.log.LogLevel.DEBUG
|
||||
import com.android.systemui.shared.regionsampling.RegionSampler
|
||||
import com.android.systemui.plugins.Weather
|
||||
import com.android.systemui.plugins.WeatherData
|
||||
import com.android.systemui.statusbar.policy.BatteryController
|
||||
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
@@ -291,10 +291,8 @@ constructor(
|
||||
clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
|
||||
}
|
||||
|
||||
override fun onWeatherDataChanged(data: Weather?) {
|
||||
if (data != null) {
|
||||
clock?.events?.onWeatherDataChanged(data)
|
||||
}
|
||||
override fun onWeatherDataChanged(data: WeatherData) {
|
||||
clock?.events?.onWeatherDataChanged(data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.dump.DumpManager;
|
||||
import com.android.systemui.dump.DumpsysTableLogger;
|
||||
import com.android.systemui.log.SessionTracker;
|
||||
import com.android.systemui.plugins.Weather;
|
||||
import com.android.systemui.plugins.WeatherData;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.settings.UserTracker;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListener;
|
||||
@@ -3303,12 +3303,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
/**
|
||||
* @param data the weather data (temp, conditions, unit) for weather clock to use
|
||||
*/
|
||||
public void sendWeatherData(Weather data) {
|
||||
public void sendWeatherData(WeatherData data) {
|
||||
mHandler.post(()-> {
|
||||
handleWeatherDataUpdate(data); });
|
||||
}
|
||||
|
||||
private void handleWeatherDataUpdate(Weather data) {
|
||||
private void handleWeatherDataUpdate(WeatherData data) {
|
||||
Assert.isMainThread();
|
||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
||||
|
||||
@@ -23,7 +23,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.settingslib.fuelgauge.BatteryStatus;
|
||||
import com.android.systemui.plugins.Weather;
|
||||
import com.android.systemui.plugins.WeatherData;
|
||||
import com.android.systemui.statusbar.KeyguardIndicationController;
|
||||
|
||||
import java.util.TimeZone;
|
||||
@@ -61,7 +61,7 @@ public class KeyguardUpdateMonitorCallback {
|
||||
/**
|
||||
* Called when receive new weather data.
|
||||
*/
|
||||
public void onWeatherDataChanged(Weather data) { }
|
||||
public void onWeatherDataChanged(WeatherData data) { }
|
||||
|
||||
/**
|
||||
* Called when the carrier PLMN or SPN changes.
|
||||
|
||||
@@ -52,18 +52,19 @@ import com.android.systemui.plugins.BcSmartspaceDataPlugin
|
||||
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener
|
||||
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
|
||||
import com.android.systemui.plugins.FalsingManager
|
||||
import com.android.systemui.plugins.WeatherData
|
||||
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.DATE_SMARTSPACE_DATA_PLUGIN
|
||||
import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.WEATHER_SMARTSPACE_DATA_PLUGIN
|
||||
import com.android.systemui.plugins.Weather
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController
|
||||
import com.android.systemui.util.concurrency.Execution
|
||||
import com.android.systemui.util.settings.SecureSettings
|
||||
import com.android.systemui.util.time.SystemClock
|
||||
import java.io.PrintWriter
|
||||
import java.time.Instant
|
||||
import java.util.Optional
|
||||
@@ -81,6 +82,7 @@ constructor(
|
||||
private val smartspaceManager: SmartspaceManager,
|
||||
private val activityStarter: ActivityStarter,
|
||||
private val falsingManager: FalsingManager,
|
||||
private val systemClock: SystemClock,
|
||||
private val secureSettings: SecureSettings,
|
||||
private val userTracker: UserTracker,
|
||||
private val contentResolver: ContentResolver,
|
||||
@@ -153,6 +155,18 @@ constructor(
|
||||
|
||||
// The weather data plugin takes unfiltered targets and performs the filtering internally.
|
||||
weatherPlugin?.onTargetsAvailable(targets)
|
||||
val now = Instant.ofEpochMilli(systemClock.currentTimeMillis())
|
||||
val weatherTarget = targets.find { t ->
|
||||
t.featureType == SmartspaceTarget.FEATURE_WEATHER &&
|
||||
now.isAfter(Instant.ofEpochMilli(t.creationTimeMillis)) &&
|
||||
now.isBefore(Instant.ofEpochMilli(t.expiryTimeMillis))
|
||||
}
|
||||
if (weatherTarget != null) {
|
||||
val weatherData = WeatherData.fromBundle(weatherTarget.baseAction.extras)
|
||||
if (weatherData != null) {
|
||||
keyguardUpdateMonitor.sendWeatherData(weatherData)
|
||||
}
|
||||
}
|
||||
|
||||
val filteredTargets = targets.filter(::filterSmartspaceTarget)
|
||||
plugin?.onTargetsAvailable(filteredTargets)
|
||||
@@ -174,17 +188,6 @@ constructor(
|
||||
}
|
||||
isContentUpdatedOnce = true
|
||||
}
|
||||
|
||||
val now = Instant.now()
|
||||
val weatherTarget = targets.find { t ->
|
||||
t.featureType == SmartspaceTarget.FEATURE_WEATHER &&
|
||||
now.isAfter(Instant.ofEpochMilli(t.creationTimeMillis)) &&
|
||||
now.isBefore(Instant.ofEpochMilli(t.expiryTimeMillis))
|
||||
}
|
||||
if (weatherTarget != null) {
|
||||
val weatherData = Weather.fromBundle(weatherTarget.baseAction.extras)
|
||||
keyguardUpdateMonitor.sendWeatherData(weatherData)
|
||||
}
|
||||
}
|
||||
|
||||
private val userTrackerCallback = object : UserTracker.Callback {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.systemui.statusbar.lockscreen
|
||||
|
||||
import android.app.smartspace.SmartspaceAction
|
||||
import android.app.smartspace.SmartspaceManager
|
||||
import android.app.smartspace.SmartspaceSession
|
||||
import android.app.smartspace.SmartspaceSession.OnTargetsAvailableListener
|
||||
@@ -26,6 +27,7 @@ import android.content.pm.UserInfo
|
||||
import android.database.ContentObserver
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.UserHandle
|
||||
import android.provider.Settings
|
||||
@@ -43,6 +45,7 @@ import com.android.systemui.plugins.BcSmartspaceDataPlugin
|
||||
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener
|
||||
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
|
||||
import com.android.systemui.plugins.FalsingManager
|
||||
import com.android.systemui.plugins.WeatherData
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener
|
||||
import com.android.systemui.settings.UserTracker
|
||||
@@ -54,6 +57,7 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceP
|
||||
import com.android.systemui.util.concurrency.FakeExecution
|
||||
import com.android.systemui.util.concurrency.FakeExecutor
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.argThat
|
||||
import com.android.systemui.util.mockito.capture
|
||||
import com.android.systemui.util.mockito.eq
|
||||
import com.android.systemui.util.settings.SecureSettings
|
||||
@@ -69,6 +73,7 @@ import org.mockito.Mockito.clearInvocations
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.spy
|
||||
import org.mockito.Mockito.times
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations
|
||||
import java.util.Optional
|
||||
@@ -76,6 +81,13 @@ import java.util.concurrent.Executor
|
||||
|
||||
@SmallTest
|
||||
class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
companion object {
|
||||
const val SMARTSPACE_TIME_TOO_EARLY = 1000L
|
||||
const val SMARTSPACE_TIME_JUST_RIGHT = 4000L
|
||||
const val SMARTSPACE_TIME_TOO_LATE = 9000L
|
||||
const val SMARTSPACE_CREATION_TIME = 1234L
|
||||
const val SMARTSPACE_EXPIRY_TIME = 5678L
|
||||
}
|
||||
@Mock
|
||||
private lateinit var featureFlags: FeatureFlags
|
||||
@Mock
|
||||
@@ -224,6 +236,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
smartspaceManager,
|
||||
activityStarter,
|
||||
falsingManager,
|
||||
clock,
|
||||
secureSettings,
|
||||
userTracker,
|
||||
contentResolver,
|
||||
@@ -528,6 +541,190 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
verify(datePlugin, never()).onTargetsAvailable(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSessionListener_ifWeatherExtraMissing_thenWeatherDataNotSent() {
|
||||
connectSession()
|
||||
clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
|
||||
// WHEN we receive a list of targets
|
||||
val targets = listOf(
|
||||
makeTarget(1, userHandlePrimary, isSensitive = true),
|
||||
makeTarget(2, userHandlePrimary, featureType = SmartspaceTarget.FEATURE_WEATHER)
|
||||
|
||||
)
|
||||
sessionListener.onTargetsAvailable(targets)
|
||||
verify(keyguardUpdateMonitor, times(0)).sendWeatherData(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSessionListener_ifWeatherExtraIsMissingValues_thenWeatherDataNotSent() {
|
||||
connectSession()
|
||||
|
||||
clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
|
||||
// WHEN we receive a list of targets
|
||||
val targets = listOf(
|
||||
makeTarget(1, userHandlePrimary, isSensitive = true),
|
||||
makeWeatherTargetWithExtras(
|
||||
id = 2,
|
||||
userHandle = userHandlePrimary,
|
||||
description = null,
|
||||
state = WeatherData.WeatherStateIcon.SUNNY.id,
|
||||
temperature = "32",
|
||||
useCelsius = null)
|
||||
|
||||
)
|
||||
|
||||
sessionListener.onTargetsAvailable(targets)
|
||||
|
||||
verify(keyguardUpdateMonitor, times(0)).sendWeatherData(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSessionListener_ifTooEarly_thenWeatherDataNotSent() {
|
||||
connectSession()
|
||||
|
||||
clock.setCurrentTimeMillis(SMARTSPACE_TIME_TOO_EARLY)
|
||||
// WHEN we receive a list of targets
|
||||
val targets = listOf(
|
||||
makeWeatherTargetWithExtras(
|
||||
id = 1,
|
||||
userHandle = userHandleManaged,
|
||||
description = "Sunny",
|
||||
state = WeatherData.WeatherStateIcon.SUNNY.id,
|
||||
temperature = "32",
|
||||
useCelsius = false)
|
||||
)
|
||||
sessionListener.onTargetsAvailable(targets)
|
||||
verify(keyguardUpdateMonitor, times(0)).sendWeatherData(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSessionListener_ifOnTime_thenWeatherDataSent() {
|
||||
connectSession()
|
||||
|
||||
clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
|
||||
// WHEN we receive a list of targets
|
||||
val targets = listOf(
|
||||
makeWeatherTargetWithExtras(
|
||||
id = 1,
|
||||
userHandle = userHandleManaged,
|
||||
description = "Snow Showers",
|
||||
state = WeatherData.WeatherStateIcon.SNOW_SHOWERS_SNOW.id,
|
||||
temperature = "-1",
|
||||
useCelsius = false)
|
||||
)
|
||||
sessionListener.onTargetsAvailable(targets)
|
||||
verify(keyguardUpdateMonitor).sendWeatherData(argThat { w ->
|
||||
w.description == "Snow Showers" &&
|
||||
w.state == WeatherData.WeatherStateIcon.SNOW_SHOWERS_SNOW &&
|
||||
w.temperature == -1 && !w.useCelsius
|
||||
})
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSessionListener_ifTooLate_thenWeatherDataNotSent() {
|
||||
connectSession()
|
||||
|
||||
clock.setCurrentTimeMillis(SMARTSPACE_TIME_TOO_LATE)
|
||||
// WHEN we receive a list of targets
|
||||
val targets = listOf(
|
||||
makeWeatherTargetWithExtras(
|
||||
id = 1,
|
||||
userHandle = userHandleManaged,
|
||||
description = "Sunny",
|
||||
state = WeatherData.WeatherStateIcon.SUNNY.id,
|
||||
temperature = "72",
|
||||
useCelsius = false)
|
||||
)
|
||||
sessionListener.onTargetsAvailable(targets)
|
||||
verify(keyguardUpdateMonitor, times(0)).sendWeatherData(any())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSessionListener_onlyFirstWeatherDataSent() {
|
||||
connectSession()
|
||||
|
||||
clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
|
||||
// WHEN we receive a list of targets
|
||||
val targets = listOf(
|
||||
makeWeatherTargetWithExtras(
|
||||
id = 1,
|
||||
userHandle = userHandleManaged,
|
||||
description = "Sunny",
|
||||
state = WeatherData.WeatherStateIcon.SUNNY.id,
|
||||
temperature = "72",
|
||||
useCelsius = false),
|
||||
makeWeatherTargetWithExtras(
|
||||
id = 2,
|
||||
userHandle = userHandleManaged,
|
||||
description = "Showers",
|
||||
state = WeatherData.WeatherStateIcon.SHOWERS_RAIN.id,
|
||||
temperature = "62",
|
||||
useCelsius = true)
|
||||
)
|
||||
sessionListener.onTargetsAvailable(targets)
|
||||
verify(keyguardUpdateMonitor).sendWeatherData(argThat { w ->
|
||||
w.description == "Sunny" &&
|
||||
w.state == WeatherData.WeatherStateIcon.SUNNY &&
|
||||
w.temperature == 72 && !w.useCelsius
|
||||
})
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSessionListener_ifDecouplingEnabled_weatherDataUpdates() {
|
||||
`when`(featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED)).thenReturn(true)
|
||||
connectSession()
|
||||
|
||||
clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
|
||||
// WHEN we receive a list of targets
|
||||
val targets = listOf(
|
||||
makeTarget(1, userHandlePrimary, isSensitive = true),
|
||||
makeTarget(2, userHandlePrimary),
|
||||
makeTarget(3, userHandleManaged),
|
||||
makeWeatherTargetWithExtras(
|
||||
id = 4,
|
||||
userHandle = userHandlePrimary,
|
||||
description = "Flurries",
|
||||
state = WeatherData.WeatherStateIcon.FLURRIES.id,
|
||||
temperature = "0",
|
||||
useCelsius = true)
|
||||
)
|
||||
|
||||
sessionListener.onTargetsAvailable(targets)
|
||||
|
||||
verify(keyguardUpdateMonitor).sendWeatherData(argThat { w ->
|
||||
w.description == "Flurries" &&
|
||||
w.state == WeatherData.WeatherStateIcon.FLURRIES &&
|
||||
w.temperature == 0 && w.useCelsius
|
||||
})
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSessionListener_ifDecouplingDisabled_weatherDataUpdates() {
|
||||
`when`(featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED)).thenReturn(false)
|
||||
connectSession()
|
||||
|
||||
clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
|
||||
// WHEN we receive a list of targets
|
||||
val targets = listOf(
|
||||
makeWeatherTargetWithExtras(
|
||||
id = 1,
|
||||
userHandle = userHandlePrimary,
|
||||
description = "Sunny",
|
||||
state = WeatherData.WeatherStateIcon.SUNNY.id,
|
||||
temperature = "32",
|
||||
useCelsius = false),
|
||||
makeTarget(2, userHandlePrimary, isSensitive = true)
|
||||
)
|
||||
|
||||
sessionListener.onTargetsAvailable(targets)
|
||||
|
||||
verify(keyguardUpdateMonitor).sendWeatherData(argThat { w ->
|
||||
w.description == "Sunny" &&
|
||||
w.state == WeatherData.WeatherStateIcon.SUNNY &&
|
||||
w.temperature == 32 && !w.useCelsius
|
||||
})
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSettingsAreReloaded() {
|
||||
// GIVEN a connected session where the privacy settings later flip to false
|
||||
@@ -740,7 +937,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
return userInfo
|
||||
}
|
||||
|
||||
fun makeTarget(
|
||||
private fun makeTarget(
|
||||
id: Int,
|
||||
userHandle: UserHandle,
|
||||
isSensitive: Boolean = false,
|
||||
@@ -755,6 +952,38 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun makeWeatherTargetWithExtras(
|
||||
id: Int,
|
||||
userHandle: UserHandle,
|
||||
description: String?,
|
||||
state: Int?,
|
||||
temperature: String?,
|
||||
useCelsius: Boolean?
|
||||
): SmartspaceTarget {
|
||||
val mockWeatherBundle = mock(Bundle::class.java).apply {
|
||||
`when`(getString(WeatherData.DESCRIPTION_KEY)).thenReturn(description)
|
||||
if (state != null)
|
||||
`when`(getInt(eq(WeatherData.STATE_KEY), any())).thenReturn(state)
|
||||
`when`(getString(WeatherData.TEMPERATURE_KEY)).thenReturn(temperature)
|
||||
`when`(containsKey(WeatherData.USE_CELSIUS_KEY)).thenReturn(useCelsius != null)
|
||||
if (useCelsius != null)
|
||||
`when`(getBoolean(WeatherData.USE_CELSIUS_KEY)).thenReturn(useCelsius)
|
||||
}
|
||||
|
||||
val mockBaseAction = mock(SmartspaceAction::class.java)
|
||||
`when`(mockBaseAction.extras).thenReturn(mockWeatherBundle)
|
||||
return SmartspaceTarget.Builder(
|
||||
"targetWithWeatherExtras$id",
|
||||
ComponentName("testpackage", "testclass$id"),
|
||||
userHandle)
|
||||
.setSensitive(false)
|
||||
.setFeatureType(SmartspaceTarget.FEATURE_WEATHER)
|
||||
.setBaseAction(mockBaseAction)
|
||||
.setExpiryTimeMillis(SMARTSPACE_EXPIRY_TIME)
|
||||
.setCreationTimeMillis(SMARTSPACE_CREATION_TIME)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun setAllowPrivateNotifications(user: UserHandle, value: Boolean) {
|
||||
`when`(secureSettings.getIntForUser(
|
||||
eq(PRIVATE_LOCKSCREEN_SETTING),
|
||||
|
||||
Reference in New Issue
Block a user