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