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