1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.controls.ui
18 
19 import android.annotation.ColorRes
20 import android.annotation.MainThread
21 import android.content.ComponentName
22 import android.content.Context
23 import android.graphics.drawable.Drawable
24 import android.service.controls.DeviceTypes
25 import android.service.controls.templates.TemperatureControlTemplate
26 import android.util.ArrayMap
27 import android.util.SparseArray
28 
29 import com.android.systemui.res.R
30 
31 data class RenderInfo(
32     val icon: Drawable,
33     val foreground: Int,
34     @ColorRes val enabledBackground: Int
35 ) {
36     companion object {
37         const val APP_ICON_ID = -1
38         const val ERROR_ICON = -1000
39         private val iconMap = SparseArray<Drawable>()
40         private val appIconMap = ArrayMap<ComponentName, Drawable>()
41 
42         @MainThread
lookupnull43         fun lookup(
44             context: Context,
45             componentName: ComponentName,
46             deviceType: Int,
47             offset: Int = 0
48         ): RenderInfo {
49             val key = if (offset > 0) {
50                 deviceType * BUCKET_SIZE + offset
51             } else deviceType
52 
53             val (fg, bg) = deviceColorMap.getValue(key)
54             val resourceId = deviceIconMap.getValue(key)
55             var icon: Drawable?
56             if (resourceId == APP_ICON_ID) {
57                 icon = appIconMap.get(componentName)
58                 if (icon == null) {
59                     icon = context.resources
60                         .getDrawable(R.drawable.ic_device_unknown_on, null)
61                     appIconMap.put(componentName, icon)
62                 }
63             } else {
64                 icon = iconMap.get(resourceId)
65                 if (icon == null) {
66                     icon = context.resources.getDrawable(resourceId, null)
67                     iconMap.put(resourceId, icon)
68                 }
69             }
70             return RenderInfo(
71                 checkNotNull(icon?.constantState).newDrawable(context.resources), fg, bg)
72         }
73 
registerComponentIconnull74         fun registerComponentIcon(componentName: ComponentName, icon: Drawable) {
75             appIconMap.put(componentName, icon)
76         }
77 
clearCachenull78         fun clearCache() {
79             iconMap.clear()
80             appIconMap.clear()
81         }
82     }
83 }
84 
85 private const val BUCKET_SIZE = 1000
86 private const val THERMOSTAT_RANGE = DeviceTypes.TYPE_THERMOSTAT * BUCKET_SIZE
87 
88 private val deviceColorMap = mapOf<Int, Pair<Int, Int>>(
89     (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_OFF) to
90         Pair(R.color.control_default_foreground, R.color.control_default_background),
91     (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_HEAT) to
92         Pair(R.color.thermo_heat_foreground, R.color.control_enabled_thermo_heat_background),
93     (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_COOL) to
94         Pair(R.color.thermo_cool_foreground, R.color.control_enabled_thermo_cool_background),
95     DeviceTypes.TYPE_LIGHT
96         to Pair(R.color.light_foreground, R.color.control_enabled_light_background),
97     DeviceTypes.TYPE_CAMERA
98         to Pair(R.color.camera_foreground, R.color.control_enabled_default_background)
<lambda>null99 ).withDefault {
100         Pair(R.color.control_foreground, R.color.control_enabled_default_background)
101 }
102 
103 private val deviceIconMap = mapOf<Int, Int>(
104     (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_OFF) to
105         R.drawable.ic_device_thermostat_off,
106     (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_HEAT) to
107         R.drawable.ic_device_thermostat,
108     (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_COOL) to
109         R.drawable.ic_device_thermostat,
110     (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_HEAT_COOL) to
111         R.drawable.ic_device_thermostat,
112     (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_ECO) to
113         R.drawable.ic_device_thermostat_off,
114     DeviceTypes.TYPE_THERMOSTAT to R.drawable.ic_device_thermostat,
115     DeviceTypes.TYPE_LIGHT to R.drawable.ic_device_light,
116     DeviceTypes.TYPE_CAMERA to R.drawable.ic_device_camera,
117     DeviceTypes.TYPE_LOCK to R.drawable.ic_device_lock,
118     DeviceTypes.TYPE_SWITCH to R.drawable.ic_device_switch,
119     DeviceTypes.TYPE_OUTLET to R.drawable.ic_device_outlet,
120     DeviceTypes.TYPE_VACUUM to R.drawable.ic_device_vacuum,
121     DeviceTypes.TYPE_MOP to R.drawable.ic_device_mop,
122     DeviceTypes.TYPE_AIR_FRESHENER to R.drawable.ic_device_air_freshener,
123     DeviceTypes.TYPE_AIR_PURIFIER to R.drawable.ic_device_air_purifier,
124     DeviceTypes.TYPE_FAN to R.drawable.ic_device_fan,
125     DeviceTypes.TYPE_HOOD to R.drawable.ic_device_hood,
126     DeviceTypes.TYPE_KETTLE to R.drawable.ic_device_kettle,
127     DeviceTypes.TYPE_MICROWAVE to R.drawable.ic_device_microwave,
128     DeviceTypes.TYPE_REMOTE_CONTROL to R.drawable.ic_device_remote_control,
129     DeviceTypes.TYPE_SET_TOP to R.drawable.ic_device_set_top,
130     DeviceTypes.TYPE_STYLER to R.drawable.ic_device_styler,
131     DeviceTypes.TYPE_TV to R.drawable.ic_device_tv,
132     DeviceTypes.TYPE_WATER_HEATER to R.drawable.ic_device_water_heater,
133     DeviceTypes.TYPE_DISHWASHER to R.drawable.ic_device_dishwasher,
134     DeviceTypes.TYPE_MULTICOOKER to R.drawable.ic_device_multicooker,
135     DeviceTypes.TYPE_SPRINKLER to R.drawable.ic_device_sprinkler,
136     DeviceTypes.TYPE_WASHER to R.drawable.ic_device_washer,
137     DeviceTypes.TYPE_BLINDS to R.drawable.ic_device_blinds,
138     DeviceTypes.TYPE_DRAWER to R.drawable.ic_device_drawer,
139     DeviceTypes.TYPE_GARAGE to R.drawable.ic_device_garage,
140     DeviceTypes.TYPE_GATE to R.drawable.ic_device_gate,
141     DeviceTypes.TYPE_PERGOLA to R.drawable.ic_device_pergola,
142     DeviceTypes.TYPE_WINDOW to R.drawable.ic_device_window,
143     DeviceTypes.TYPE_VALVE to R.drawable.ic_device_valve,
144     DeviceTypes.TYPE_SECURITY_SYSTEM to R.drawable.ic_device_security_system,
145     DeviceTypes.TYPE_REFRIGERATOR to R.drawable.ic_device_refrigerator,
146     DeviceTypes.TYPE_DOORBELL to R.drawable.ic_device_doorbell,
147     DeviceTypes.TYPE_ROUTINE to RenderInfo.APP_ICON_ID,
148     DeviceTypes.TYPE_AC_HEATER to R.drawable.ic_device_thermostat,
149     DeviceTypes.TYPE_AC_UNIT to R.drawable.ic_device_thermostat,
150     DeviceTypes.TYPE_COFFEE_MAKER to R.drawable.ic_device_kettle,
151     DeviceTypes.TYPE_DEHUMIDIFIER to R.drawable.ic_device_air_freshener,
152     DeviceTypes.TYPE_RADIATOR to R.drawable.ic_device_thermostat,
153     DeviceTypes.TYPE_STANDMIXER to R.drawable.ic_device_cooking,
154     DeviceTypes.TYPE_DISPLAY to R.drawable.ic_device_display,
155     DeviceTypes.TYPE_DRYER to R.drawable.ic_device_washer,
156     DeviceTypes.TYPE_MOWER to R.drawable.ic_device_outdoor_garden,
157     DeviceTypes.TYPE_SHOWER to R.drawable.ic_device_water,
158     DeviceTypes.TYPE_AWNING to R.drawable.ic_device_pergola,
159     DeviceTypes.TYPE_CLOSET to R.drawable.ic_device_drawer,
160     DeviceTypes.TYPE_CURTAIN to R.drawable.ic_device_blinds,
161     DeviceTypes.TYPE_DOOR to R.drawable.ic_device_door,
162     DeviceTypes.TYPE_SHUTTER to R.drawable.ic_device_window,
163     DeviceTypes.TYPE_HEATER to R.drawable.ic_device_thermostat,
164     RenderInfo.ERROR_ICON to R.drawable.ic_error_outline
<lambda>null165 ).withDefault {
166     R.drawable.ic_device_unknown
167 }
168