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