1 package com.android.systemui.plugins.clocks 2 3 import android.os.Bundle 4 import android.util.Log 5 import android.view.View 6 import androidx.annotation.VisibleForTesting 7 8 typealias WeatherTouchAction = (View) -> Unit 9 10 data class WeatherData( 11 val description: String, 12 val state: WeatherStateIcon, 13 val useCelsius: Boolean, 14 val temperature: Int, 15 val touchAction: WeatherTouchAction? = null, 16 ) { 17 companion object { 18 const val DEBUG = true 19 private const val TAG = "WeatherData" 20 @VisibleForTesting const val DESCRIPTION_KEY = "description" 21 @VisibleForTesting const val STATE_KEY = "state" 22 @VisibleForTesting const val USE_CELSIUS_KEY = "use_celsius" 23 @VisibleForTesting const val TEMPERATURE_KEY = "temperature" 24 private const val INVALID_WEATHER_ICON_STATE = -1 25 fromBundlenull26 fun fromBundle(extras: Bundle, touchAction: WeatherTouchAction? = null): WeatherData? { 27 val description = extras.getString(DESCRIPTION_KEY) 28 val state = 29 WeatherStateIcon.fromInt(extras.getInt(STATE_KEY, INVALID_WEATHER_ICON_STATE)) 30 val temperature = readIntFromBundle(extras, TEMPERATURE_KEY) 31 if ( 32 description == null || 33 state == null || 34 !extras.containsKey(USE_CELSIUS_KEY) || 35 temperature == null 36 ) { 37 if (DEBUG) { 38 Log.w(TAG, "Weather data did not parse from $extras") 39 } 40 return null 41 } else { 42 val result = 43 WeatherData( 44 description = description, 45 state = state, 46 useCelsius = extras.getBoolean(USE_CELSIUS_KEY), 47 temperature = temperature, 48 touchAction = touchAction 49 ) 50 if (DEBUG) { 51 Log.i(TAG, "Weather data parsed $result from $extras") 52 } 53 return result 54 } 55 } 56 readIntFromBundlenull57 private fun readIntFromBundle(extras: Bundle, key: String): Int? = 58 try { 59 extras.getString(key)?.toInt() 60 } catch (e: Exception) { 61 null 62 } 63 } 64 65 // Values for WeatherStateIcon must stay in sync with go/g3-WeatherStateIcon 66 enum class WeatherStateIcon(val id: Int) { 67 UNKNOWN_ICON(0), 68 69 // Clear, day & night. 70 SUNNY(1), 71 CLEAR_NIGHT(2), 72 73 // Mostly clear, day & night. 74 MOSTLY_SUNNY(3), 75 MOSTLY_CLEAR_NIGHT(4), 76 77 // Partly cloudy, day & night. 78 PARTLY_CLOUDY(5), 79 PARTLY_CLOUDY_NIGHT(6), 80 81 // Mostly cloudy, day & night. 82 MOSTLY_CLOUDY_DAY(7), 83 MOSTLY_CLOUDY_NIGHT(8), 84 CLOUDY(9), 85 HAZE_FOG_DUST_SMOKE(10), 86 DRIZZLE(11), 87 HEAVY_RAIN(12), 88 SHOWERS_RAIN(13), 89 90 // Scattered showers, day & night. 91 SCATTERED_SHOWERS_DAY(14), 92 SCATTERED_SHOWERS_NIGHT(15), 93 94 // Isolated scattered thunderstorms, day & night. 95 ISOLATED_SCATTERED_TSTORMS_DAY(16), 96 ISOLATED_SCATTERED_TSTORMS_NIGHT(17), 97 STRONG_TSTORMS(18), 98 BLIZZARD(19), 99 BLOWING_SNOW(20), 100 FLURRIES(21), 101 HEAVY_SNOW(22), 102 103 // Scattered snow showers, day & night. 104 SCATTERED_SNOW_SHOWERS_DAY(23), 105 SCATTERED_SNOW_SHOWERS_NIGHT(24), 106 SNOW_SHOWERS_SNOW(25), 107 MIXED_RAIN_HAIL_RAIN_SLEET(26), 108 SLEET_HAIL(27), 109 TORNADO(28), 110 TROPICAL_STORM_HURRICANE(29), 111 WINDY_BREEZY(30), 112 WINTRY_MIX_RAIN_SNOW(31); 113 114 companion object { <lambda>null115 fun fromInt(value: Int) = values().firstOrNull { it.id == value } 116 } 117 } 118 toStringnull119 override fun toString(): String { 120 val unit = if (useCelsius) "C" else "F" 121 return "$state (\"$description\") $temperature°$unit" 122 } 123 } 124