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