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