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.annotation.AddedInOrBefore; 24 import android.car.hardware.CarPropertyConfig; 25 import android.car.hardware.CarPropertyValue; 26 import android.car.hardware.property.CarPropertyManager; 27 import android.car.hardware.property.CarPropertyManager.CarPropertyEventCallback; 28 import android.car.hardware.property.ICarProperty; 29 import android.os.IBinder; 30 import android.util.ArraySet; 31 import android.util.Log; 32 33 import com.android.internal.annotations.GuardedBy; 34 35 import java.lang.annotation.Retention; 36 import java.lang.annotation.RetentionPolicy; 37 import java.lang.ref.WeakReference; 38 import java.util.Arrays; 39 import java.util.Collection; 40 import java.util.List; 41 42 /** 43 * @deprecated Use {@link CarPropertyManager} instead. 44 * 45 * API for controlling HVAC system in cars 46 * @hide 47 */ 48 @Deprecated 49 @SystemApi 50 public final class CarHvacManager extends CarManagerBase { 51 private static final String TAG = "CarHvacManager"; 52 private final CarPropertyManager mCarPropertyMgr; 53 @GuardedBy("mLock") 54 private CarPropertyEventListenerToBase mListenerToBase = null; 55 56 private final Object mLock = new Object(); 57 58 @GuardedBy("mLock") 59 private final ArraySet<CarHvacEventCallback> mCallbacks = new ArraySet<>(); 60 61 /** 62 * HVAC property IDs for get/set methods 63 */ 64 /** 65 * Mirror defrosters state, int type 66 * Positive values indicate mirror defroster is on 67 */ 68 @AddedInOrBefore(majorVersion = 33) 69 public static final int ID_MIRROR_DEFROSTER_ON = 0x1440050c; 70 /** 71 * Steering wheel temp, int type 72 * Positive values indicate heating. 73 * Negative values indicate cooling 74 */ 75 @AddedInOrBefore(majorVersion = 33) 76 public static final int ID_STEERING_WHEEL_HEAT = 0x1140050d; 77 /** 78 * Outside air temperature, float type 79 * Value is in degrees Celsius 80 */ 81 @AddedInOrBefore(majorVersion = 33) 82 public static final int ID_OUTSIDE_AIR_TEMP = 0x11600703; 83 /** 84 * Temperature units being used, int type 85 * 0x30 = Celsius 86 * 0x31 = Fahrenheit 87 */ 88 @AddedInOrBefore(majorVersion = 33) 89 public static final int ID_TEMPERATURE_DISPLAY_UNITS = 0x1140050e; 90 91 /** 92 * Temperature setpoint, float type 93 * Temperature set by the user, units are in degrees Celsius. 94 */ 95 @AddedInOrBefore(majorVersion = 33) 96 public static final int ID_ZONED_TEMP_SETPOINT = 0x15600503; 97 /** 98 * Actual temperature, float type 99 * Actual zone temperature is read only value, in terms of F or C. 100 */ 101 @AddedInOrBefore(majorVersion = 33) 102 public static final int ID_ZONED_TEMP_ACTUAL = 0x15600502; 103 /** 104 * HVAC system powered on / off, bool type 105 * In many vehicles, if the HVAC system is powered off, the SET and GET command will 106 * throw an IllegalStateException. To correct this, need to turn on the HVAC module first 107 * before manipulating a parameter. 108 */ 109 @AddedInOrBefore(majorVersion = 33) 110 public static final int ID_ZONED_HVAC_POWER_ON = 0x15200510; 111 /** 112 * Fan speed setpoint, int type 113 * Fan speed is an integer from 0-n, depending on number of fan speeds available. 114 */ 115 @AddedInOrBefore(majorVersion = 33) 116 public static final int ID_ZONED_FAN_SPEED_SETPOINT = 0x15400500; 117 /** 118 * Actual fan speed, int type 119 * Actual fan speed is a read-only value, expressed in RPM. 120 */ 121 @AddedInOrBefore(majorVersion = 33) 122 public static final int ID_ZONED_FAN_SPEED_RPM = 0x1540050f; 123 /** 124 * Fan direction available, int vector type 125 * Fan direction is a bitmask of directions available for each zone. 126 */ 127 @AddedInOrBefore(majorVersion = 33) 128 public static final int ID_ZONED_FAN_DIRECTION_AVAILABLE = 0x15410511; 129 /** 130 * Current fan direction setting, int type. The value must be one of the FAN_DIRECTION_AVAILABLE 131 * values declared above. 132 */ 133 @AddedInOrBefore(majorVersion = 33) 134 public static final int ID_ZONED_FAN_DIRECTION = 0x15400501; 135 /** 136 * Seat temperature, int type 137 * Seat temperature is negative for cooling, positive for heating. Temperature is a 138 * setting, i.e. -3 to 3 for 3 levels of cooling and 3 levels of heating. 139 */ 140 @AddedInOrBefore(majorVersion = 33) 141 public static final int ID_ZONED_SEAT_TEMP = 0x1540050b; 142 /** 143 * Air ON, bool type 144 * true indicates AC is ON. 145 */ 146 @AddedInOrBefore(majorVersion = 33) 147 public static final int ID_ZONED_AC_ON = 0x15200505; 148 /** 149 * Automatic Mode ON, bool type 150 * true indicates HVAC is in automatic mode 151 */ 152 @AddedInOrBefore(majorVersion = 33) 153 public static final int ID_ZONED_AUTOMATIC_MODE_ON = 0x1520050A; 154 /** 155 * Air recirculation ON, bool type 156 * true indicates recirculation is active. 157 */ 158 @AddedInOrBefore(majorVersion = 33) 159 public static final int ID_ZONED_AIR_RECIRCULATION_ON = 0x15200508; 160 /** 161 * Max AC ON, bool type 162 * true indicates MAX AC is ON 163 */ 164 @AddedInOrBefore(majorVersion = 33) 165 public static final int ID_ZONED_MAX_AC_ON = 0x15200506; 166 /** Dual zone ON, bool type 167 * true indicates dual zone mode is ON 168 */ 169 @AddedInOrBefore(majorVersion = 33) 170 public static final int ID_ZONED_DUAL_ZONE_ON = 0x15200509; 171 /** 172 * Max Defrost ON, bool type 173 * true indicates max defrost is active. 174 */ 175 @AddedInOrBefore(majorVersion = 33) 176 public static final int ID_ZONED_MAX_DEFROST_ON = 0x15200507; 177 /** 178 * Automatic recirculation mode ON 179 * true indicates recirculation is in automatic mode 180 */ 181 @AddedInOrBefore(majorVersion = 33) 182 public static final int ID_ZONED_HVAC_AUTO_RECIRC_ON = 0x15200512; 183 /** 184 * Defroster ON, bool type 185 * Defroster controls are based on window position. 186 * True indicates the defroster is ON. 187 */ 188 @AddedInOrBefore(majorVersion = 33) 189 public static final int ID_WINDOW_DEFROSTER_ON = 0x13200504; 190 191 /** @hide */ 192 @IntDef({ 193 ID_MIRROR_DEFROSTER_ON, 194 ID_STEERING_WHEEL_HEAT, 195 ID_OUTSIDE_AIR_TEMP, 196 ID_TEMPERATURE_DISPLAY_UNITS, 197 ID_ZONED_TEMP_SETPOINT, 198 ID_ZONED_TEMP_ACTUAL, 199 ID_ZONED_FAN_SPEED_SETPOINT, 200 ID_ZONED_FAN_SPEED_RPM, 201 ID_ZONED_FAN_DIRECTION_AVAILABLE, 202 ID_ZONED_FAN_DIRECTION, 203 ID_ZONED_SEAT_TEMP, 204 ID_ZONED_AC_ON, 205 ID_ZONED_AUTOMATIC_MODE_ON, 206 ID_ZONED_AIR_RECIRCULATION_ON, 207 ID_ZONED_MAX_AC_ON, 208 ID_ZONED_DUAL_ZONE_ON, 209 ID_ZONED_MAX_DEFROST_ON, 210 ID_ZONED_HVAC_POWER_ON, 211 ID_ZONED_HVAC_AUTO_RECIRC_ON, 212 ID_WINDOW_DEFROSTER_ON 213 }) 214 @Retention(RetentionPolicy.SOURCE) 215 public @interface PropertyId {} 216 private final ArraySet<Integer> mHvacPropertyIds = new ArraySet<>(Arrays.asList(new Integer [] { 217 ID_MIRROR_DEFROSTER_ON, 218 ID_STEERING_WHEEL_HEAT, 219 ID_OUTSIDE_AIR_TEMP, 220 ID_TEMPERATURE_DISPLAY_UNITS, 221 ID_ZONED_TEMP_SETPOINT, 222 ID_ZONED_TEMP_ACTUAL, 223 ID_ZONED_FAN_SPEED_SETPOINT, 224 ID_ZONED_FAN_SPEED_RPM, 225 ID_ZONED_FAN_DIRECTION_AVAILABLE, 226 ID_ZONED_FAN_DIRECTION, 227 ID_ZONED_SEAT_TEMP, 228 ID_ZONED_AC_ON, 229 ID_ZONED_AUTOMATIC_MODE_ON, 230 ID_ZONED_AIR_RECIRCULATION_ON, 231 ID_ZONED_MAX_AC_ON, 232 ID_ZONED_DUAL_ZONE_ON, 233 ID_ZONED_MAX_DEFROST_ON, 234 ID_ZONED_HVAC_POWER_ON, 235 ID_ZONED_HVAC_AUTO_RECIRC_ON, 236 ID_WINDOW_DEFROSTER_ON 237 })); 238 239 240 /** 241 * Use {@link android.car.hardware.CarHvacFanDirection#FACE} instead. 242 * Represents fan direction when air flows through face directed vents. 243 * This constant must be used with {@link #ID_ZONED_FAN_DIRECTION} property. 244 */ 245 @AddedInOrBefore(majorVersion = 33) 246 public static final int FAN_DIRECTION_FACE = 0x1; 247 /** 248 * Use {@link android.car.hardware.CarHvacFanDirection#FLOOR} instead. 249 * Represents fan direction when air flows through floor directed vents. 250 * This constant must be used with {@link #ID_ZONED_FAN_DIRECTION} property. 251 */ 252 @AddedInOrBefore(majorVersion = 33) 253 public static final int FAN_DIRECTION_FLOOR = 0x2; 254 /** 255 * Use {@link android.car.hardware.CarHvacFanDirection#DEFROST} instead. 256 * Represents fan direction when air flows through defrost vents. 257 * This constant must be used with {@link #ID_ZONED_FAN_DIRECTION} property. 258 */ 259 @AddedInOrBefore(majorVersion = 33) 260 public static final int FAN_DIRECTION_DEFROST = 0x4; 261 262 /** 263 * Application registers {@link CarHvacEventCallback} object to receive updates and changes to 264 * subscribed Car HVAC properties. 265 */ 266 public interface CarHvacEventCallback { 267 /** 268 * Called when a property is updated 269 * @param value Property that has been updated. 270 */ 271 @AddedInOrBefore(majorVersion = 33) onChangeEvent(CarPropertyValue value)272 void onChangeEvent(CarPropertyValue value); 273 274 /** 275 * Called when an error is detected with a property 276 * @param propertyId 277 * @param zone 278 */ 279 @AddedInOrBefore(majorVersion = 33) onErrorEvent(@ropertyId int propertyId, int zone)280 void onErrorEvent(@PropertyId int propertyId, int zone); 281 } 282 283 private static class CarPropertyEventListenerToBase implements CarPropertyEventCallback { 284 private final WeakReference<CarHvacManager> mManager; 285 CarPropertyEventListenerToBase(CarHvacManager manager)286 CarPropertyEventListenerToBase(CarHvacManager manager) { 287 mManager = new WeakReference<>(manager); 288 } 289 290 @Override onChangeEvent(CarPropertyValue value)291 public void onChangeEvent(CarPropertyValue value) { 292 CarHvacManager manager = mManager.get(); 293 if (manager != null) { 294 manager.handleOnChangeEvent(value); 295 } 296 } 297 298 @Override onErrorEvent(int propertyId, int zone)299 public void onErrorEvent(int propertyId, int zone) { 300 CarHvacManager manager = mManager.get(); 301 if (manager != null) { 302 manager.handleOnErrorEvent(propertyId, zone); 303 } 304 } 305 } 306 handleOnChangeEvent(CarPropertyValue value)307 private void handleOnChangeEvent(CarPropertyValue value) { 308 Collection<CarHvacEventCallback> callbacks; 309 synchronized (mLock) { 310 callbacks = new ArraySet<>(mCallbacks); 311 } 312 if (!callbacks.isEmpty()) { 313 for (CarHvacEventCallback l: callbacks) { 314 l.onChangeEvent(value); 315 } 316 } 317 } 318 handleOnErrorEvent(int propertyId, int zone)319 private void handleOnErrorEvent(int propertyId, int zone) { 320 Collection<CarHvacEventCallback> callbacks; 321 synchronized (mLock) { 322 callbacks = new ArraySet<>(mCallbacks); 323 } 324 if (!callbacks.isEmpty()) { 325 for (CarHvacEventCallback l: callbacks) { 326 l.onErrorEvent(propertyId, zone); 327 } 328 } 329 } 330 331 /** 332 * Get an instance of the CarHvacManager. 333 * 334 * Should not be obtained directly by clients, use {@link Car#getCarManager(String)} instead. 335 * @param service 336 * 337 * @hide 338 */ CarHvacManager(Car car, IBinder service)339 public CarHvacManager(Car car, IBinder service) { 340 super(car); 341 ICarProperty mCarPropertyService = ICarProperty.Stub.asInterface(service); 342 mCarPropertyMgr = new CarPropertyManager(car, mCarPropertyService); 343 } 344 345 /** 346 * Implement wrappers for contained CarPropertyManager object 347 * @param callback 348 */ 349 @AddedInOrBefore(majorVersion = 33) registerCallback(CarHvacEventCallback callback)350 public void registerCallback(CarHvacEventCallback callback) { 351 synchronized (mLock) { 352 if (mCallbacks.isEmpty()) { 353 mListenerToBase = new CarPropertyEventListenerToBase(this); 354 } 355 List<CarPropertyConfig> configs = getPropertyList(); 356 for (CarPropertyConfig c : configs) { 357 // Register each individual propertyId 358 mCarPropertyMgr.registerCallback(mListenerToBase, c.getPropertyId(), 0); 359 } 360 mCallbacks.add(callback); 361 } 362 } 363 364 /** 365 * Stop getting property updates for the given callback. If there are multiple registrations for 366 * this listener, all listening will be stopped. 367 * @param callback 368 */ 369 @AddedInOrBefore(majorVersion = 33) unregisterCallback(CarHvacEventCallback callback)370 public void unregisterCallback(CarHvacEventCallback callback) { 371 synchronized (mLock) { 372 mCallbacks.remove(callback); 373 try { 374 List<CarPropertyConfig> configs = getPropertyList(); 375 for (CarPropertyConfig c : configs) { 376 // Register each individual propertyId 377 mCarPropertyMgr.unregisterCallback(mListenerToBase, c.getPropertyId()); 378 379 } 380 } catch (RuntimeException e) { 381 Log.e(TAG, "getPropertyList exception ", e); 382 } 383 if (mCallbacks.isEmpty()) { 384 mCarPropertyMgr.unregisterCallback(mListenerToBase); 385 mListenerToBase = null; 386 } 387 } 388 } 389 390 /** 391 * Get list of properties represented by Car Hvac Manager for this car. 392 * @return List of CarPropertyConfig objects available via Car Hvac Manager. 393 */ 394 @AddedInOrBefore(majorVersion = 33) getPropertyList()395 public List<CarPropertyConfig> getPropertyList() { 396 return mCarPropertyMgr.getPropertyList(mHvacPropertyIds); 397 } 398 399 /** 400 * Check whether a given property is available or disabled based on the cars current state. 401 * @return true if the property is AVAILABLE, false otherwise 402 */ 403 @AddedInOrBefore(majorVersion = 33) isPropertyAvailable(@ropertyId int propertyId, int area)404 public boolean isPropertyAvailable(@PropertyId int propertyId, int area) { 405 return mCarPropertyMgr.isPropertyAvailable(propertyId, area); 406 } 407 408 /** 409 * Get value of boolean property 410 * @param propertyId 411 * @param area 412 * @return value of requested boolean property 413 */ 414 @AddedInOrBefore(majorVersion = 33) getBooleanProperty(@ropertyId int propertyId, int area)415 public boolean getBooleanProperty(@PropertyId int propertyId, int area) { 416 return mCarPropertyMgr.getBooleanProperty(propertyId, area); 417 } 418 419 /** 420 * Get value of float property 421 * @param propertyId 422 * @param area 423 * @return value of requested float property 424 */ 425 @AddedInOrBefore(majorVersion = 33) getFloatProperty(@ropertyId int propertyId, int area)426 public float getFloatProperty(@PropertyId int propertyId, int area) { 427 return mCarPropertyMgr.getFloatProperty(propertyId, area); 428 } 429 430 /** 431 * Get value of integer property 432 * @param propertyId 433 * @param area 434 * @return value of requested integer property 435 */ 436 @AddedInOrBefore(majorVersion = 33) getIntProperty(@ropertyId int propertyId, int area)437 public int getIntProperty(@PropertyId int propertyId, int area) { 438 return mCarPropertyMgr.getIntProperty(propertyId, area); 439 } 440 441 /** 442 * Set the value of a boolean property 443 * @param propertyId 444 * @param area 445 * @param val 446 */ 447 @AddedInOrBefore(majorVersion = 33) setBooleanProperty(@ropertyId int propertyId, int area, boolean val)448 public void setBooleanProperty(@PropertyId int propertyId, int area, boolean val) { 449 if (mHvacPropertyIds.contains(propertyId)) { 450 mCarPropertyMgr.setBooleanProperty(propertyId, area, val); 451 } 452 } 453 454 /** 455 * Set the value of a float property 456 * @param propertyId 457 * @param area 458 * @param val 459 */ 460 @AddedInOrBefore(majorVersion = 33) setFloatProperty(@ropertyId int propertyId, int area, float val)461 public void setFloatProperty(@PropertyId int propertyId, int area, float val) { 462 if (mHvacPropertyIds.contains(propertyId)) { 463 mCarPropertyMgr.setFloatProperty(propertyId, area, val); 464 } 465 } 466 467 /** 468 * Set the value of an integer property 469 * @param propertyId 470 * @param area 471 * @param val 472 */ 473 @AddedInOrBefore(majorVersion = 33) setIntProperty(@ropertyId int propertyId, int area, int val)474 public void setIntProperty(@PropertyId int propertyId, int area, int val) { 475 if (mHvacPropertyIds.contains(propertyId)) { 476 mCarPropertyMgr.setIntProperty(propertyId, area, val); 477 } 478 } 479 480 /** @hide */ 481 @AddedInOrBefore(majorVersion = 33) onCarDisconnected()482 public void onCarDisconnected() { 483 synchronized (mLock) { 484 mCallbacks.clear(); 485 } 486 mCarPropertyMgr.onCarDisconnected(); 487 } 488 } 489