1 /* 2 * Copyright (C) 2015 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.car.hardware.hvac; 18 19 import android.annotation.IntDef; 20 import android.annotation.SystemApi; 21 import android.car.Car; 22 import android.car.CarManagerBase; 23 import android.car.CarNotConnectedException; 24 import android.car.hardware.CarPropertyConfig; 25 import android.car.hardware.CarPropertyValue; 26 import android.car.hardware.property.CarPropertyManagerBase; 27 import android.car.hardware.property.CarPropertyManagerBase.CarPropertyEventCallback; 28 import android.content.Context; 29 import android.os.Handler; 30 import android.os.IBinder; 31 import android.util.ArraySet; 32 33 import java.lang.annotation.Retention; 34 import java.lang.annotation.RetentionPolicy; 35 import java.lang.ref.WeakReference; 36 import java.util.Collection; 37 import java.util.List; 38 39 /** 40 * API for controlling HVAC system in cars 41 * @hide 42 */ 43 @SystemApi 44 public final class CarHvacManager implements CarManagerBase { 45 private final static boolean DBG = false; 46 private final static String TAG = "CarHvacManager"; 47 private final CarPropertyManagerBase mMgr; 48 private final ArraySet<CarHvacEventCallback> mCallbacks = new ArraySet<>(); 49 private CarPropertyEventListenerToBase mListenerToBase = null; 50 51 /** 52 * HVAC property IDs for get/set methods 53 */ 54 /** 55 * Global HVAC properties. There is only a single instance in a car. 56 * Global properties are in the range of 0-0x3FFF. 57 */ 58 /** 59 * Mirror defrosters state, bool type 60 * true indicates mirror defroster is on 61 */ 62 public static final int ID_MIRROR_DEFROSTER_ON = 0x0001; 63 /** 64 * Steering wheel temp, int type 65 * Positive values indicate heating. 66 * Negative values indicate cooling 67 */ 68 public static final int ID_STEERING_WHEEL_TEMP = 0x0002; 69 /** 70 * Outside air temperature, float type 71 * Value is in degrees of ID_TEMPERATURE_UNITS 72 */ 73 public static final int ID_OUTSIDE_AIR_TEMP = 0x0003; 74 /** 75 * Temperature units being used, int type 76 * 0x30 = Celsius 77 * 0x31 = Fahrenheit 78 */ 79 public static final int ID_TEMPERATURE_UNITS = 0x0004; 80 81 82 /** 83 * The maximum id that can be assigned to global (non-zoned) property. 84 * @hide 85 */ 86 public static final int ID_MAX_GLOBAL_PROPERTY_ID = 0x3fff; 87 88 /** 89 * ID_ZONED_* represents properties available on a per-zone basis. All zones in a car are 90 * not required to have the same properties. Zone specific properties start at 0x4000. 91 */ 92 /** 93 * Temperature setpoint, float type 94 * Temperature set by the user, units are determined by ID_TEMPERTURE_UNITS property. 95 */ 96 public static final int ID_ZONED_TEMP_SETPOINT = 0x4001; 97 /** 98 * Actual temperature, float type 99 * Actual zone temperature is read only value, in terms of F or C. 100 */ 101 public static final int ID_ZONED_TEMP_ACTUAL = 0x4002; 102 /** 103 * HVAC system powered on / off, bool type 104 * In many vehicles, if the HVAC system is powered off, the SET and GET command will 105 * throw an IllegalStateException. To correct this, need to turn on the HVAC module first 106 * before manipulating a parameter. 107 */ 108 public static final int ID_ZONED_HVAC_POWER_ON = 0x4003; 109 /** 110 * Fan speed setpoint, int type 111 * Fan speed is an integer from 0-n, depending on number of fan speeds available. 112 */ 113 public static final int ID_ZONED_FAN_SPEED_SETPOINT = 0x4004; 114 /** 115 * Actual fan speed, int type 116 * Actual fan speed is a read-only value, expressed in RPM. 117 */ 118 public static final int ID_ZONED_FAN_SPEED_RPM = 0x4005; 119 /** Fan position available, int type 120 * Fan position is a bitmask of positions available for each zone. 121 */ 122 public static final int ID_ZONED_FAN_POSITION_AVAILABLE = 0x4006; 123 /** 124 * Current fan position setting, int type. The value must be one of the FAN_POSITION_* 125 * constants declared in {@link CarHvacManager}. 126 */ 127 public static final int ID_ZONED_FAN_POSITION = 0x4007; 128 /** 129 * Seat temperature, int type 130 * Seat temperature is negative for cooling, positive for heating. Temperature is a 131 * setting, i.e. -3 to 3 for 3 levels of cooling and 3 levels of heating. 132 */ 133 public static final int ID_ZONED_SEAT_TEMP = 0x4008; 134 /** 135 * Air ON, bool type 136 * true indicates AC is ON. 137 */ 138 public static final int ID_ZONED_AC_ON = 0x4009; 139 /** 140 * Automatic Mode ON, bool type 141 * true indicates HVAC is in automatic mode 142 */ 143 public static final int ID_ZONED_AUTOMATIC_MODE_ON = 0x400A; 144 /** 145 * Air recirculation ON, bool type 146 * true indicates recirculation is active. 147 */ 148 public static final int ID_ZONED_AIR_RECIRCULATION_ON = 0x400B; 149 /** 150 * Max AC ON, bool type 151 * true indicates MAX AC is ON 152 */ 153 public static final int ID_ZONED_MAX_AC_ON = 0x400C; 154 /** Dual zone ON, bool type 155 * true indicates dual zone mode is ON 156 */ 157 public static final int ID_ZONED_DUAL_ZONE_ON = 0x400D; 158 /** 159 * Max Defrost ON, bool type 160 * true indicates max defrost is active. 161 */ 162 public static final int ID_ZONED_MAX_DEFROST_ON = 0x400E; 163 /** 164 * Automatic recirculation mode ON 165 * true indicates recirculation is in automatic mode 166 */ 167 public static final int ID_ZONED_HVAC_AUTO_RECIRC_ON = 0x400F; 168 /** 169 * Defroster ON, bool type 170 * Defroster controls are based on window position. 171 * True indicates the defroster is ON. 172 */ 173 public static final int ID_WINDOW_DEFROSTER_ON = 0x5001; 174 175 /** @hide */ 176 @IntDef({ 177 ID_MIRROR_DEFROSTER_ON, 178 ID_STEERING_WHEEL_TEMP, 179 ID_OUTSIDE_AIR_TEMP, 180 ID_TEMPERATURE_UNITS, 181 ID_ZONED_TEMP_SETPOINT, 182 ID_ZONED_TEMP_ACTUAL, 183 ID_ZONED_FAN_SPEED_SETPOINT, 184 ID_ZONED_FAN_SPEED_RPM, 185 ID_ZONED_FAN_POSITION_AVAILABLE, 186 ID_ZONED_FAN_POSITION, 187 ID_ZONED_SEAT_TEMP, 188 ID_ZONED_AC_ON, 189 ID_ZONED_AUTOMATIC_MODE_ON, 190 ID_ZONED_AIR_RECIRCULATION_ON, 191 ID_ZONED_MAX_AC_ON, 192 ID_ZONED_DUAL_ZONE_ON, 193 ID_ZONED_MAX_DEFROST_ON, 194 ID_ZONED_HVAC_POWER_ON, 195 ID_ZONED_HVAC_AUTO_RECIRC_ON, 196 ID_WINDOW_DEFROSTER_ON, 197 }) 198 @Retention(RetentionPolicy.SOURCE) 199 public @interface PropertyId {} 200 201 /** 202 * Represents fan position when air flows through face directed vents. 203 * This constant must be used with {@link #ID_ZONED_FAN_POSITION} property. 204 */ 205 public static final int FAN_POSITION_FACE = 1; 206 /** 207 * Represents fan position when air flows through floor directed vents. 208 * This constant must be used with {@link #ID_ZONED_FAN_POSITION} property. 209 */ 210 public static final int FAN_POSITION_FLOOR = 2; 211 /** 212 * Represents fan position when air flows through face and floor directed vents. 213 * This constant must be used with {@link #ID_ZONED_FAN_POSITION} property. 214 */ 215 public static final int FAN_POSITION_FACE_AND_FLOOR = 3; 216 /** 217 * Represents fan position when air flows through defrost vents. 218 * This constant must be used with {@link #ID_ZONED_FAN_POSITION} property. 219 */ 220 public static final int FAN_POSITION_DEFROST = 4; 221 /** 222 * Represents fan position when air flows through defrost and floor directed vents. 223 * This constant must be used with {@link #ID_ZONED_FAN_POSITION} property. 224 */ 225 public static final int FAN_POSITION_DEFROST_AND_FLOOR = 5; 226 227 /** 228 * Application registers {@link CarHvacEventCallback} object to receive updates and changes to 229 * subscribed Car HVAC properties. 230 */ 231 public interface CarHvacEventCallback { 232 /** 233 * Called when a property is updated 234 * @param value Property that has been updated. 235 */ onChangeEvent(CarPropertyValue value)236 void onChangeEvent(CarPropertyValue value); 237 238 /** 239 * Called when an error is detected with a property 240 * @param propertyId 241 * @param zone 242 */ onErrorEvent(@ropertyId int propertyId, int zone)243 void onErrorEvent(@PropertyId int propertyId, int zone); 244 } 245 246 private static class CarPropertyEventListenerToBase implements CarPropertyEventCallback { 247 private final WeakReference<CarHvacManager> mManager; 248 CarPropertyEventListenerToBase(CarHvacManager manager)249 public CarPropertyEventListenerToBase(CarHvacManager manager) { 250 mManager = new WeakReference<>(manager); 251 } 252 253 @Override onChangeEvent(CarPropertyValue value)254 public void onChangeEvent(CarPropertyValue value) { 255 CarHvacManager manager = mManager.get(); 256 if (manager != null) { 257 manager.handleOnChangeEvent(value); 258 } 259 } 260 261 @Override onErrorEvent(int propertyId, int zone)262 public void onErrorEvent(int propertyId, int zone) { 263 CarHvacManager manager = mManager.get(); 264 if (manager != null) { 265 manager.handleOnErrorEvent(propertyId, zone); 266 } 267 } 268 } 269 handleOnChangeEvent(CarPropertyValue value)270 private void handleOnChangeEvent(CarPropertyValue value) { 271 Collection<CarHvacEventCallback> callbacks; 272 synchronized (this) { 273 callbacks = new ArraySet<>(mCallbacks); 274 } 275 if (!callbacks.isEmpty()) { 276 for (CarHvacEventCallback l: callbacks) { 277 l.onChangeEvent(value); 278 } 279 } 280 } 281 handleOnErrorEvent(int propertyId, int zone)282 private void handleOnErrorEvent(int propertyId, int zone) { 283 Collection<CarHvacEventCallback> callbacks; 284 synchronized (this) { 285 callbacks = new ArraySet<>(mCallbacks); 286 } 287 if (!callbacks.isEmpty()) { 288 for (CarHvacEventCallback l: callbacks) { 289 l.onErrorEvent(propertyId, zone); 290 } 291 } 292 } 293 294 /** 295 * Get an instance of the CarHvacManager. 296 * 297 * Should not be obtained directly by clients, use {@link Car#getCarManager(String)} instead. 298 * @param service 299 * @param context 300 * @param handler 301 * @hide 302 */ CarHvacManager(IBinder service, Context context, Handler handler)303 public CarHvacManager(IBinder service, Context context, Handler handler) { 304 mMgr = new CarPropertyManagerBase(service, handler, DBG, TAG); 305 } 306 307 /** 308 * Determine if a property is zoned or not. 309 * @param propertyId 310 * @return true if property is a zoned type. 311 */ isZonedProperty(@ropertyId int propertyId)312 public static boolean isZonedProperty(@PropertyId int propertyId) { 313 return propertyId > ID_MAX_GLOBAL_PROPERTY_ID; 314 } 315 316 /** 317 * Implement wrappers for contained CarPropertyManagerBase object 318 * @param callback 319 * @throws CarNotConnectedException 320 */ registerCallback(CarHvacEventCallback callback)321 public synchronized void registerCallback(CarHvacEventCallback callback) throws 322 CarNotConnectedException { 323 if (mCallbacks.isEmpty()) { 324 mListenerToBase = new CarPropertyEventListenerToBase(this); 325 mMgr.registerCallback(mListenerToBase); 326 } 327 mCallbacks.add(callback); 328 } 329 330 /** 331 * Stop getting property updates for the given callback. If there are multiple registrations for 332 * this listener, all listening will be stopped. 333 * @param callback 334 */ unregisterCallback(CarHvacEventCallback callback)335 public synchronized void unregisterCallback(CarHvacEventCallback callback) { 336 mCallbacks.remove(callback); 337 if (mCallbacks.isEmpty()) { 338 mMgr.unregisterCallback(); 339 mListenerToBase = null; 340 } 341 } 342 343 /** 344 * Get list of properties available to Car Hvac Manager 345 * @return List of CarPropertyConfig objects available via Car Hvac Manager. 346 * @throws CarNotConnectedException if the connection to the car service has been lost. 347 */ getPropertyList()348 public List<CarPropertyConfig> getPropertyList() throws CarNotConnectedException { 349 return mMgr.getPropertyList(); 350 } 351 352 /** 353 * Get value of boolean property 354 * @param propertyId 355 * @param area 356 * @return value of requested boolean property 357 * @throws CarNotConnectedException 358 */ getBooleanProperty(@ropertyId int propertyId, int area)359 public boolean getBooleanProperty(@PropertyId int propertyId, int area) 360 throws CarNotConnectedException { 361 return mMgr.getBooleanProperty(propertyId, area); 362 } 363 364 /** 365 * Get value of float property 366 * @param propertyId 367 * @param area 368 * @return value of requested float property 369 * @throws CarNotConnectedException 370 */ getFloatProperty(@ropertyId int propertyId, int area)371 public float getFloatProperty(@PropertyId int propertyId, int area) 372 throws CarNotConnectedException { 373 return mMgr.getFloatProperty(propertyId, area); 374 } 375 376 /** 377 * Get value of integer property 378 * @param propertyId 379 * @param area 380 * @return value of requested integer property 381 * @throws CarNotConnectedException 382 */ getIntProperty(@ropertyId int propertyId, int area)383 public int getIntProperty(@PropertyId int propertyId, int area) 384 throws CarNotConnectedException { 385 return mMgr.getIntProperty(propertyId, area); 386 } 387 388 /** 389 * Set the value of a boolean property 390 * @param propertyId 391 * @param area 392 * @param val 393 * @throws CarNotConnectedException 394 */ setBooleanProperty(@ropertyId int propertyId, int area, boolean val)395 public void setBooleanProperty(@PropertyId int propertyId, int area, boolean val) 396 throws CarNotConnectedException { 397 mMgr.setBooleanProperty(propertyId, area, val); 398 } 399 400 /** 401 * Set the value of a float property 402 * @param propertyId 403 * @param area 404 * @param val 405 * @throws CarNotConnectedException 406 */ setFloatProperty(@ropertyId int propertyId, int area, float val)407 public void setFloatProperty(@PropertyId int propertyId, int area, float val) 408 throws CarNotConnectedException { 409 mMgr.setFloatProperty(propertyId, area, val); 410 } 411 412 /** 413 * Set the value of an integer property 414 * @param propertyId 415 * @param area 416 * @param val 417 * @throws CarNotConnectedException 418 */ setIntProperty(@ropertyId int propertyId, int area, int val)419 public void setIntProperty(@PropertyId int propertyId, int area, int val) 420 throws CarNotConnectedException { 421 mMgr.setIntProperty(propertyId, area, val); 422 } 423 424 /** @hide */ 425 @Override onCarDisconnected()426 public void onCarDisconnected() { 427 mMgr.onCarDisconnected(); 428 } 429 } 430