1 /* 2 * Copyright (C) 2019 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 android.service.controls.templates; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.os.Bundle; 22 import android.service.controls.Control; 23 import android.util.Log; 24 25 import com.android.internal.util.Preconditions; 26 27 import java.lang.annotation.Retention; 28 import java.lang.annotation.RetentionPolicy; 29 30 /** 31 * A template for a temperature related {@link Control} that supports multiple modes. 32 * 33 * Both the current mode and the active mode for the control can be specified. The combination of 34 * the {@link Control#getDeviceType} and the current and active mode will determine colors and 35 * transitions for the UI element. 36 */ 37 public final class TemperatureControlTemplate extends ControlTemplate { 38 39 private static final String TAG = "ThermostatTemplate"; 40 41 private static final @TemplateType int TYPE = TYPE_TEMPERATURE; 42 private static final String KEY_TEMPLATE = "key_template"; 43 private static final String KEY_CURRENT_MODE = "key_current_mode"; 44 private static final String KEY_CURRENT_ACTIVE_MODE = "key_current_active_mode"; 45 private static final String KEY_MODES = "key_modes"; 46 47 /** 48 * @hide 49 */ 50 @Retention(RetentionPolicy.SOURCE) 51 @IntDef({ 52 MODE_UNKNOWN, 53 MODE_OFF, 54 MODE_HEAT, 55 MODE_COOL, 56 MODE_HEAT_COOL, 57 MODE_ECO 58 }) 59 public @interface Mode {} 60 61 private static final int NUM_MODES = 6; 62 63 /** 64 * Use when the current or active mode of the device is not known 65 */ 66 public static final @Mode int MODE_UNKNOWN = 0; 67 68 /** 69 * Indicates that the current or active mode of the device is off. 70 */ 71 public static final @Mode int MODE_OFF = 1; 72 73 /** 74 * Indicates that the current or active mode of the device is set to heat. 75 */ 76 public static final @Mode int MODE_HEAT = 2; 77 78 /** 79 * Indicates that the current or active mode of the device is set to cool. 80 */ 81 public static final @Mode int MODE_COOL = 3; 82 83 /** 84 * Indicates that the current or active mode of the device is set to heat-cool. 85 */ 86 public static final @Mode int MODE_HEAT_COOL = 4; 87 88 /** 89 * Indicates that the current or active mode of the device is set to eco. 90 */ 91 public static final @Mode int MODE_ECO = 5; 92 93 /** 94 * @hide 95 */ 96 @Retention(RetentionPolicy.SOURCE) 97 @IntDef(flag = true, value = { 98 FLAG_MODE_OFF, 99 FLAG_MODE_HEAT, 100 FLAG_MODE_COOL, 101 FLAG_MODE_HEAT_COOL, 102 FLAG_MODE_ECO 103 }) 104 public @interface ModeFlag {} 105 106 /** 107 * Flag to indicate that the device supports off mode. 108 */ 109 public static final int FLAG_MODE_OFF = 1 << MODE_OFF; 110 111 /** 112 * Flag to indicate that the device supports heat mode. 113 */ 114 public static final int FLAG_MODE_HEAT = 1 << MODE_HEAT; 115 116 /** 117 * Flag to indicate that the device supports cool mode. 118 */ 119 public static final int FLAG_MODE_COOL = 1 << MODE_COOL; 120 121 /** 122 * Flag to indicate that the device supports heat-cool mode. 123 */ 124 public static final int FLAG_MODE_HEAT_COOL = 1 << MODE_HEAT_COOL; 125 126 /** 127 * Flag to indicate that the device supports eco mode. 128 */ 129 public static final int FLAG_MODE_ECO = 1 << MODE_ECO; 130 private static final int ALL_FLAGS = 131 FLAG_MODE_OFF | 132 FLAG_MODE_HEAT | 133 FLAG_MODE_COOL | 134 FLAG_MODE_HEAT_COOL | 135 FLAG_MODE_ECO; 136 137 private static final int[] modeToFlag = new int[]{ 138 0, 139 FLAG_MODE_OFF, 140 FLAG_MODE_HEAT, 141 FLAG_MODE_COOL, 142 FLAG_MODE_HEAT_COOL, 143 FLAG_MODE_ECO 144 }; 145 146 private final @NonNull ControlTemplate mTemplate; 147 private final @Mode int mCurrentMode; 148 private final @Mode int mCurrentActiveMode; 149 private final @ModeFlag int mModes; 150 151 /** 152 * Construct a new {@link TemperatureControlTemplate}. 153 * 154 * The current and active mode have to be among the ones supported by the flags. 155 * 156 * @param templateId the identifier for this template object 157 * @param controlTemplate a template to use for interaction with the user 158 * @param currentMode the current mode for the {@link Control} 159 * @param currentActiveMode the current active mode for the {@link Control} 160 * @param modesFlag a flag representing the available modes for the {@link Control} 161 * @throws IllegalArgumentException if the parameters passed do not make a valid template. 162 */ TemperatureControlTemplate(@onNull String templateId, @NonNull ControlTemplate controlTemplate, @Mode int currentMode, @Mode int currentActiveMode, @ModeFlag int modesFlag)163 public TemperatureControlTemplate(@NonNull String templateId, 164 @NonNull ControlTemplate controlTemplate, 165 @Mode int currentMode, 166 @Mode int currentActiveMode, 167 @ModeFlag int modesFlag) { 168 super(templateId); 169 Preconditions.checkNotNull(controlTemplate); 170 mTemplate = controlTemplate; 171 172 if (currentMode < 0 || currentMode >= NUM_MODES) { 173 Log.e(TAG, "Invalid current mode:" + currentMode); 174 mCurrentMode = MODE_UNKNOWN; 175 } else { 176 mCurrentMode = currentMode; 177 } 178 179 if (currentActiveMode < 0 || currentActiveMode >= NUM_MODES) { 180 Log.e(TAG, "Invalid current active mode:" + currentActiveMode); 181 mCurrentActiveMode = MODE_UNKNOWN; 182 } else { 183 mCurrentActiveMode = currentActiveMode; 184 } 185 186 mModes = modesFlag & ALL_FLAGS; 187 if (mCurrentMode != MODE_UNKNOWN && (modeToFlag[mCurrentMode] & mModes) == 0) { 188 throw new IllegalArgumentException("Mode " + mCurrentMode + " not supported in flag."); 189 } 190 if (mCurrentActiveMode != MODE_UNKNOWN && (modeToFlag[mCurrentActiveMode] & mModes) == 0) { 191 throw new IllegalArgumentException( 192 "Mode " + currentActiveMode + " not supported in flag."); 193 } 194 } 195 196 /** 197 * @param b 198 * @hide 199 */ TemperatureControlTemplate(@onNull Bundle b)200 TemperatureControlTemplate(@NonNull Bundle b) { 201 super(b); 202 mTemplate = ControlTemplate.createTemplateFromBundle(b.getBundle(KEY_TEMPLATE)); 203 mCurrentMode = b.getInt(KEY_CURRENT_MODE); 204 mCurrentActiveMode = b.getInt(KEY_CURRENT_ACTIVE_MODE); 205 mModes = b.getInt(KEY_MODES); 206 } 207 208 /** 209 * @return 210 * @hide 211 */ 212 @Override 213 @NonNull getDataBundle()214 Bundle getDataBundle() { 215 Bundle b = super.getDataBundle(); 216 b.putBundle(KEY_TEMPLATE, mTemplate.getDataBundle()); 217 b.putInt(KEY_CURRENT_MODE, mCurrentMode); 218 b.putInt(KEY_CURRENT_ACTIVE_MODE, mCurrentActiveMode); 219 b.putInt(KEY_MODES, mModes); 220 return b; 221 } 222 223 @NonNull getTemplate()224 public ControlTemplate getTemplate() { 225 return mTemplate; 226 } 227 getCurrentMode()228 public int getCurrentMode() { 229 return mCurrentMode; 230 } 231 getCurrentActiveMode()232 public int getCurrentActiveMode() { 233 return mCurrentActiveMode; 234 } 235 getModes()236 public int getModes() { 237 return mModes; 238 } 239 240 /** 241 * @return {@link ControlTemplate#TYPE_TEMPERATURE} 242 */ 243 @Override getTemplateType()244 public int getTemplateType() { 245 return TYPE; 246 } 247 } 248