• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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