Merge "Read weather data from smartspace extras" into tm-qpr-dev am: 41b93c6eea
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21274075 Change-Id: I77b38628ec43bc7cb10fb6df29e976cb87757958 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) {}
|
fun onColorPaletteChanged(resources: Resources) {}
|
||||||
|
|
||||||
/** Call whenever the weather data should update */
|
/** Call whenever the weather data should update */
|
||||||
fun onWeatherDataChanged(data: Weather) {}
|
fun onWeatherDataChanged(data: WeatherData) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Methods which trigger various clock animations */
|
/** 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.LogBuffer
|
||||||
import com.android.systemui.plugins.log.LogLevel.DEBUG
|
import com.android.systemui.plugins.log.LogLevel.DEBUG
|
||||||
import com.android.systemui.shared.regionsampling.RegionSampler
|
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
|
||||||
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
|
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||||
@@ -291,10 +291,8 @@ constructor(
|
|||||||
clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
|
clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onWeatherDataChanged(data: Weather?) {
|
override fun onWeatherDataChanged(data: WeatherData) {
|
||||||
if (data != null) {
|
clock?.events?.onWeatherDataChanged(data)
|
||||||
clock?.events?.onWeatherDataChanged(data)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ import com.android.systemui.dagger.qualifiers.Main;
|
|||||||
import com.android.systemui.dump.DumpManager;
|
import com.android.systemui.dump.DumpManager;
|
||||||
import com.android.systemui.dump.DumpsysTableLogger;
|
import com.android.systemui.dump.DumpsysTableLogger;
|
||||||
import com.android.systemui.log.SessionTracker;
|
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.plugins.statusbar.StatusBarStateController;
|
||||||
import com.android.systemui.settings.UserTracker;
|
import com.android.systemui.settings.UserTracker;
|
||||||
import com.android.systemui.shared.system.TaskStackChangeListener;
|
import com.android.systemui.shared.system.TaskStackChangeListener;
|
||||||
@@ -3286,12 +3286,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
/**
|
/**
|
||||||
* @param data the weather data (temp, conditions, unit) for weather clock to use
|
* @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(()-> {
|
mHandler.post(()-> {
|
||||||
handleWeatherDataUpdate(data); });
|
handleWeatherDataUpdate(data); });
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleWeatherDataUpdate(Weather data) {
|
private void handleWeatherDataUpdate(WeatherData data) {
|
||||||
Assert.isMainThread();
|
Assert.isMainThread();
|
||||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||||
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.settingslib.fuelgauge.BatteryStatus;
|
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 com.android.systemui.statusbar.KeyguardIndicationController;
|
||||||
|
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
@@ -61,7 +61,7 @@ public class KeyguardUpdateMonitorCallback {
|
|||||||
/**
|
/**
|
||||||
* Called when receive new weather data.
|
* Called when receive new weather data.
|
||||||
*/
|
*/
|
||||||
public void onWeatherDataChanged(Weather data) { }
|
public void onWeatherDataChanged(WeatherData data) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the carrier PLMN or SPN changes.
|
* 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.SmartspaceTargetListener
|
||||||
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
|
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
|
||||||
import com.android.systemui.plugins.FalsingManager
|
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
|
||||||
import com.android.systemui.settings.UserTracker
|
import com.android.systemui.settings.UserTracker
|
||||||
import com.android.systemui.shared.regionsampling.RegionSampler
|
import com.android.systemui.shared.regionsampling.RegionSampler
|
||||||
import com.android.systemui.shared.regionsampling.UpdateColorCallback
|
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.DATE_SMARTSPACE_DATA_PLUGIN
|
||||||
import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.WEATHER_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.phone.KeyguardBypassController
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController
|
import com.android.systemui.statusbar.policy.DeviceProvisionedController
|
||||||
import com.android.systemui.util.concurrency.Execution
|
import com.android.systemui.util.concurrency.Execution
|
||||||
import com.android.systemui.util.settings.SecureSettings
|
import com.android.systemui.util.settings.SecureSettings
|
||||||
|
import com.android.systemui.util.time.SystemClock
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.Optional
|
import java.util.Optional
|
||||||
@@ -81,6 +82,7 @@ constructor(
|
|||||||
private val smartspaceManager: SmartspaceManager,
|
private val smartspaceManager: SmartspaceManager,
|
||||||
private val activityStarter: ActivityStarter,
|
private val activityStarter: ActivityStarter,
|
||||||
private val falsingManager: FalsingManager,
|
private val falsingManager: FalsingManager,
|
||||||
|
private val systemClock: SystemClock,
|
||||||
private val secureSettings: SecureSettings,
|
private val secureSettings: SecureSettings,
|
||||||
private val userTracker: UserTracker,
|
private val userTracker: UserTracker,
|
||||||
private val contentResolver: ContentResolver,
|
private val contentResolver: ContentResolver,
|
||||||
@@ -152,6 +154,18 @@ constructor(
|
|||||||
|
|
||||||
// The weather data plugin takes unfiltered targets and performs the filtering internally.
|
// The weather data plugin takes unfiltered targets and performs the filtering internally.
|
||||||
weatherPlugin?.onTargetsAvailable(targets)
|
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)
|
val filteredTargets = targets.filter(::filterSmartspaceTarget)
|
||||||
plugin?.onTargetsAvailable(filteredTargets)
|
plugin?.onTargetsAvailable(filteredTargets)
|
||||||
@@ -173,17 +187,6 @@ constructor(
|
|||||||
}
|
}
|
||||||
isContentUpdatedOnce = true
|
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 {
|
private val userTrackerCallback = object : UserTracker.Callback {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.lockscreen
|
package com.android.systemui.statusbar.lockscreen
|
||||||
|
|
||||||
|
import android.app.smartspace.SmartspaceAction
|
||||||
import android.app.smartspace.SmartspaceManager
|
import android.app.smartspace.SmartspaceManager
|
||||||
import android.app.smartspace.SmartspaceSession
|
import android.app.smartspace.SmartspaceSession
|
||||||
import android.app.smartspace.SmartspaceSession.OnTargetsAvailableListener
|
import android.app.smartspace.SmartspaceSession.OnTargetsAvailableListener
|
||||||
@@ -26,6 +27,7 @@ import android.content.pm.UserInfo
|
|||||||
import android.database.ContentObserver
|
import android.database.ContentObserver
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.UserHandle
|
import android.os.UserHandle
|
||||||
import android.provider.Settings
|
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.SmartspaceTargetListener
|
||||||
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
|
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
|
||||||
import com.android.systemui.plugins.FalsingManager
|
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
|
||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener
|
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener
|
||||||
import com.android.systemui.settings.UserTracker
|
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.FakeExecution
|
||||||
import com.android.systemui.util.concurrency.FakeExecutor
|
import com.android.systemui.util.concurrency.FakeExecutor
|
||||||
import com.android.systemui.util.mockito.any
|
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.capture
|
||||||
import com.android.systemui.util.mockito.eq
|
import com.android.systemui.util.mockito.eq
|
||||||
import com.android.systemui.util.settings.SecureSettings
|
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.mock
|
||||||
import org.mockito.Mockito.never
|
import org.mockito.Mockito.never
|
||||||
import org.mockito.Mockito.spy
|
import org.mockito.Mockito.spy
|
||||||
|
import org.mockito.Mockito.times
|
||||||
import org.mockito.Mockito.verify
|
import org.mockito.Mockito.verify
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
import java.util.Optional
|
import java.util.Optional
|
||||||
@@ -76,6 +81,13 @@ import java.util.concurrent.Executor
|
|||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
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
|
@Mock
|
||||||
private lateinit var featureFlags: FeatureFlags
|
private lateinit var featureFlags: FeatureFlags
|
||||||
@Mock
|
@Mock
|
||||||
@@ -224,6 +236,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
|||||||
smartspaceManager,
|
smartspaceManager,
|
||||||
activityStarter,
|
activityStarter,
|
||||||
falsingManager,
|
falsingManager,
|
||||||
|
clock,
|
||||||
secureSettings,
|
secureSettings,
|
||||||
userTracker,
|
userTracker,
|
||||||
contentResolver,
|
contentResolver,
|
||||||
@@ -528,6 +541,190 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
|||||||
verify(datePlugin, never()).onTargetsAvailable(any())
|
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
|
@Test
|
||||||
fun testSettingsAreReloaded() {
|
fun testSettingsAreReloaded() {
|
||||||
// GIVEN a connected session where the privacy settings later flip to false
|
// GIVEN a connected session where the privacy settings later flip to false
|
||||||
@@ -740,7 +937,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
|||||||
return userInfo
|
return userInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
fun makeTarget(
|
private fun makeTarget(
|
||||||
id: Int,
|
id: Int,
|
||||||
userHandle: UserHandle,
|
userHandle: UserHandle,
|
||||||
isSensitive: Boolean = false,
|
isSensitive: Boolean = false,
|
||||||
@@ -755,6 +952,38 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
|
|||||||
.build()
|
.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) {
|
private fun setAllowPrivateNotifications(user: UserHandle, value: Boolean) {
|
||||||
`when`(secureSettings.getIntForUser(
|
`when`(secureSettings.getIntForUser(
|
||||||
eq(PRIVATE_LOCKSCREEN_SETTING),
|
eq(PRIVATE_LOCKSCREEN_SETTING),
|
||||||
|
|||||||
Reference in New Issue
Block a user