Home | History | Annotate | Download | only in hvac
      1 /*
      2  * Copyright (c) 2016, 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 package com.android.car.hvac;
     17 
     18 import android.os.SystemClock;
     19 import android.util.Log;
     20 import android.util.SparseArray;
     21 import android.util.SparseBooleanArray;
     22 import android.util.SparseIntArray;
     23 import android.util.SparseLongArray;
     24 
     25 import java.util.concurrent.TimeUnit;
     26 import javax.annotation.concurrent.GuardedBy;
     27 
     28 /**
     29  * The hvac unit can be controller from two places, the ui and the hardware buttons. Each of these
     30  * request updates to the current state from different threads. Moreover, there can be conditions
     31  * where the hvac could send spurious updates so this class routes everything through and coalesces
     32  * them, keeping the application's view of the world sane.
     33  */
     34 public class DataStore {
     35     private static final long COALESCE_TIME_MS = TimeUnit.SECONDS.toMillis(2);
     36 
     37     @GuardedBy("mTemperature")
     38     private SparseArray<Float> mTemperature = new SparseArray<Float>();
     39     @GuardedBy("mTemperatureAvailable")
     40     private SparseBooleanArray mTemperatureAvailable = new SparseBooleanArray();
     41     @GuardedBy("mFanSpeed")
     42     private Integer mFanSpeed = 0;
     43     @GuardedBy("mAirflow")
     44     private SparseIntArray mAirflow = new SparseIntArray();
     45     @GuardedBy("mDefrosterState")
     46     private SparseBooleanArray mDefrosterState = new SparseBooleanArray();
     47     @GuardedBy("mAcState")
     48     private Boolean mAcState = false;
     49     @GuardedBy("mSeatWarmerLevel")
     50     private SparseIntArray mSeatWarmerLevel = new SparseIntArray();
     51     @GuardedBy("mAirCirculationState")
     52     private Boolean mAirCirculationState = false;
     53     @GuardedBy("mAutoModeState")
     54     private Boolean mAutoModeState = false;
     55     @GuardedBy("mHvacPowerState")
     56     private Boolean mHvacPowerState = false;
     57 
     58     @GuardedBy("mTemperature")
     59     private SparseLongArray mLastTemperatureSet = new SparseLongArray();
     60     @GuardedBy("mFanSpeed")
     61     private long mLastFanSpeedSet;
     62     @GuardedBy("mAirflow")
     63     private SparseLongArray mLastAirflowSet = new SparseLongArray();
     64     @GuardedBy("mDefrosterState")
     65     private SparseLongArray mLastDefrosterSet = new SparseLongArray();
     66     @GuardedBy("mAcState")
     67     private long mLastAcSet;
     68     @GuardedBy("mSeatWarmerLevel")
     69     private SparseLongArray mLastSeatWarmerLevel = new SparseLongArray();
     70     @GuardedBy("mAirCirculationState")
     71     private long mAirCirculationLastSet;
     72     @GuardedBy("mAutoModeState")
     73     private long mAutoModeLastSet;
     74     @GuardedBy("mHvacPowerState")
     75     private long mHvacPowerLastSet;
     76 
     77 
     78     public float getTemperature(int zone) {
     79         synchronized (mTemperature) {
     80             return mTemperature.get(zone);
     81         }
     82     }
     83 
     84     public void setTemperature(int zone, float temperature, boolean available) {
     85         synchronized (mTemperature) {
     86             synchronized (mTemperatureAvailable) {
     87                 Log.d("HvacDataStore", "setTemperature(" + zone + ", " + temperature + ")");
     88                 mTemperature.put(zone, temperature);
     89                 mTemperatureAvailable.put(zone, available);
     90                 mLastTemperatureSet.put(zone, SystemClock.uptimeMillis());
     91             }
     92         }
     93     }
     94 
     95     public boolean shouldPropagateTempUpdate(int zone, float temperature, boolean available) {
     96         synchronized (mTemperature) {
     97             synchronized (mTemperatureAvailable) {
     98                 if (SystemClock.uptimeMillis() - mLastTemperatureSet.get(zone) < COALESCE_TIME_MS) {
     99                     if (available == mTemperatureAvailable.get(zone)) {
    100                         return false;
    101                     }
    102                 }
    103             }
    104             setTemperature(zone, temperature, available);
    105         }
    106         return true;
    107     }
    108 
    109     public boolean getDefrosterState(int zone) {
    110         synchronized (mDefrosterState) {
    111             return mDefrosterState.get(zone);
    112         }
    113     }
    114 
    115     public void setDefrosterState(int zone, boolean state) {
    116         synchronized (mDefrosterState) {
    117             mDefrosterState.put(zone, state);
    118             mLastDefrosterSet.put(zone, SystemClock.uptimeMillis());
    119         }
    120     }
    121 
    122     public boolean shouldPropagateDefrosterUpdate(int zone, boolean defrosterState) {
    123         synchronized (mDefrosterState) {
    124             if (SystemClock.uptimeMillis() - mLastDefrosterSet.get(zone) < COALESCE_TIME_MS) {
    125                 return false;
    126             }
    127             mDefrosterState.put(zone, defrosterState);
    128         }
    129         return true;
    130     }
    131 
    132     public int getFanSpeed() {
    133         synchronized (mFanSpeed) {
    134             return mFanSpeed;
    135         }
    136     }
    137 
    138     public void setFanSpeed(int speed) {
    139         synchronized (mFanSpeed) {
    140             mFanSpeed = speed;
    141             mLastFanSpeedSet = SystemClock.uptimeMillis();
    142         }
    143     }
    144 
    145     public boolean shouldPropagateFanSpeedUpdate(int zone, int speed) {
    146         // TODO: We ignore fan speed zones for now because we dont have a multi zone car.
    147         synchronized (mFanSpeed) {
    148             if (SystemClock.uptimeMillis() - mLastFanSpeedSet < COALESCE_TIME_MS) {
    149                 return false;
    150             }
    151             mFanSpeed = speed;
    152         }
    153         return true;
    154     }
    155 
    156     public boolean getAcState() {
    157         synchronized (mAcState) {
    158             return mAcState;
    159         }
    160     }
    161 
    162     public void setAcState(boolean acState) {
    163         synchronized (mAcState) {
    164             mAcState = acState;
    165             mLastAcSet = SystemClock.uptimeMillis();
    166         }
    167     }
    168 
    169     public boolean shouldPropagateAcUpdate(boolean acState) {
    170         synchronized (mAcState) {
    171             if (SystemClock.uptimeMillis() - mLastAcSet < COALESCE_TIME_MS) {
    172                 return false;
    173             }
    174             mAcState = acState;
    175         }
    176         return true;
    177     }
    178 
    179     public int getAirflow(int zone) {
    180         synchronized (mAirflow) {
    181             return mAirflow.get(zone);
    182         }
    183     }
    184 
    185     public void setAirflow(int zone, int index) {
    186         synchronized (mAirflow) {
    187             mAirflow.put(zone, index);
    188             mLastAirflowSet.put(zone, SystemClock.uptimeMillis());
    189         }
    190     }
    191 
    192     public boolean shouldPropagateFanPositionUpdate(int zone, int index) {
    193         synchronized (mAirflow) {
    194             if (SystemClock.uptimeMillis() - mLastAirflowSet.get(zone) < COALESCE_TIME_MS) {
    195                 return false;
    196             }
    197             mAirflow.put(zone, index);
    198         }
    199         return true;
    200     }
    201 
    202     public float getSeatWarmerLevel(int zone) {
    203         synchronized (mSeatWarmerLevel) {
    204             return mSeatWarmerLevel.get(zone);
    205         }
    206     }
    207 
    208     public void setSeatWarmerLevel(int zone, int level) {
    209         synchronized (mSeatWarmerLevel) {
    210             mSeatWarmerLevel.put(zone, level);
    211             mLastSeatWarmerLevel.put(zone, SystemClock.uptimeMillis());
    212         }
    213     }
    214 
    215     public boolean shouldPropagateSeatWarmerLevelUpdate(int zone, int level) {
    216         synchronized (mSeatWarmerLevel) {
    217             if (SystemClock.uptimeMillis() - mLastSeatWarmerLevel.get(zone) < COALESCE_TIME_MS) {
    218                 return false;
    219             }
    220             mSeatWarmerLevel.put(zone, level);
    221         }
    222         return true;
    223     }
    224 
    225     public boolean getAirCirculationState() {
    226         synchronized (mAirCirculationState) {
    227             return mAirCirculationState;
    228         }
    229     }
    230 
    231     public void setAirCirculationState(boolean airCirculationState) {
    232         synchronized (mAirCirculationState) {
    233             mAirCirculationState = airCirculationState;
    234             mAirCirculationLastSet = SystemClock.uptimeMillis();
    235         }
    236     }
    237 
    238     public boolean shouldPropagateAirCirculationUpdate(boolean airCirculationState) {
    239         synchronized (mAirCirculationState) {
    240             if (SystemClock.uptimeMillis() - mAirCirculationLastSet < COALESCE_TIME_MS) {
    241                 return false;
    242             }
    243             mAcState = airCirculationState;
    244         }
    245         return true;
    246     }
    247 
    248     public boolean getAutoModeState() {
    249         synchronized (mAutoModeState) {
    250             return mAutoModeState;
    251         }
    252     }
    253 
    254     public void setAutoModeState(boolean autoModeState) {
    255         synchronized (mAutoModeState) {
    256             mAutoModeState = autoModeState;
    257             mAutoModeLastSet = SystemClock.uptimeMillis();
    258         }
    259     }
    260 
    261     public boolean shouldPropagateAutoModeUpdate(boolean autoModeState) {
    262         synchronized (mAutoModeState) {
    263             if (SystemClock.uptimeMillis() - mAutoModeLastSet < COALESCE_TIME_MS) {
    264                 return false;
    265             }
    266             mAcState = autoModeState;
    267         }
    268         return true;
    269     }
    270 
    271     public boolean getHvacPowerState() {
    272         synchronized (mHvacPowerState) {
    273             return mHvacPowerState;
    274         }
    275     }
    276 
    277     public void setHvacPowerState(boolean hvacPowerState) {
    278         synchronized (mHvacPowerState) {
    279             mHvacPowerState = hvacPowerState;
    280             mHvacPowerLastSet = SystemClock.uptimeMillis();
    281         }
    282     }
    283 
    284     public boolean shouldPropagateHvacPowerUpdate(boolean hvacPowerState) {
    285         synchronized (mHvacPowerState) {
    286             if (SystemClock.uptimeMillis() - mHvacPowerLastSet < COALESCE_TIME_MS) {
    287                 return false;
    288             }
    289             mHvacPowerState = hvacPowerState;
    290         }
    291         return true;
    292     }
    293 }
    294