Home | History | Annotate | Download | only in hvac
      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          */
    236         void onChangeEvent(CarPropertyValue value);
    237 
    238         /**
    239          * Called when an error is detected with a property
    240          * @param propertyId
    241          * @param zone
    242          */
    243         void onErrorEvent(@PropertyId int propertyId, int zone);
    244     }
    245 
    246     private static class CarPropertyEventListenerToBase implements CarPropertyEventCallback {
    247         private final WeakReference<CarHvacManager> mManager;
    248 
    249         public CarPropertyEventListenerToBase(CarHvacManager manager) {
    250             mManager = new WeakReference<>(manager);
    251         }
    252 
    253         @Override
    254         public void onChangeEvent(CarPropertyValue value) {
    255             CarHvacManager manager = mManager.get();
    256             if (manager != null) {
    257                 manager.handleOnChangeEvent(value);
    258             }
    259         }
    260 
    261         @Override
    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 
    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 
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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
    426     public void onCarDisconnected() {
    427         mMgr.onCarDisconnected();
    428     }
    429 }
    430