blob: 4a234e207e3c6e0659536a3a31bea96394a78457 [file] [log] [blame]
/*
* Copyright (c) 2016, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.car.hvac;
import android.os.SystemClock;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.SparseLongArray;
import java.util.concurrent.TimeUnit;
import javax.annotation.concurrent.GuardedBy;
/**
* The hvac unit can be controller from two places, the ui and the hardware buttons. Each of these
* request updates to the current state from different threads. Moreover, there can be conditions
* where the hvac could send spurious updates so this class routes everything through and coalesces
* them, keeping the application's view of the world sane.
*/
public class DataStore {
private static final long COALESCE_TIME_MS = TimeUnit.SECONDS.toMillis(2);
@GuardedBy("mTemperature")
private SparseArray<Float> mTemperature = new SparseArray<Float>();
@GuardedBy("mTemperatureAvailable")
private SparseBooleanArray mTemperatureAvailable = new SparseBooleanArray();
@GuardedBy("mFanSpeed")
private Integer mFanSpeed = 0;
@GuardedBy("mAirflow")
private SparseIntArray mAirflow = new SparseIntArray();
@GuardedBy("mDefrosterState")
private SparseBooleanArray mDefrosterState = new SparseBooleanArray();
@GuardedBy("mAcState")
private Boolean mAcState = false;
@GuardedBy("mSeatWarmerLevel")
private SparseIntArray mSeatWarmerLevel = new SparseIntArray();
@GuardedBy("mAirCirculationState")
private Boolean mAirCirculationState = false;
@GuardedBy("mAutoModeState")
private Boolean mAutoModeState = false;
@GuardedBy("mHvacPowerState")
private Boolean mHvacPowerState = false;
@GuardedBy("mTemperature")
private SparseLongArray mLastTemperatureSet = new SparseLongArray();
@GuardedBy("mFanSpeed")
private long mLastFanSpeedSet;
@GuardedBy("mAirflow")
private SparseLongArray mLastAirflowSet = new SparseLongArray();
@GuardedBy("mDefrosterState")
private SparseLongArray mLastDefrosterSet = new SparseLongArray();
@GuardedBy("mAcState")
private long mLastAcSet;
@GuardedBy("mSeatWarmerLevel")
private SparseLongArray mLastSeatWarmerLevel = new SparseLongArray();
@GuardedBy("mAirCirculationState")
private long mAirCirculationLastSet;
@GuardedBy("mAutoModeState")
private long mAutoModeLastSet;
@GuardedBy("mHvacPowerState")
private long mHvacPowerLastSet;
public float getTemperature(int zone) {
synchronized (mTemperature) {
return mTemperature.get(zone);
}
}
public void setTemperature(int zone, float temperature, boolean available) {
synchronized (mTemperature) {
synchronized (mTemperatureAvailable) {
Log.d("HvacDataStore", "setTemperature(" + zone + ", " + temperature + ")");
mTemperature.put(zone, temperature);
mTemperatureAvailable.put(zone, available);
mLastTemperatureSet.put(zone, SystemClock.uptimeMillis());
}
}
}
public boolean shouldPropagateTempUpdate(int zone, float temperature, boolean available) {
synchronized (mTemperature) {
synchronized (mTemperatureAvailable) {
if (SystemClock.uptimeMillis() - mLastTemperatureSet.get(zone) < COALESCE_TIME_MS) {
if (available == mTemperatureAvailable.get(zone)) {
return false;
}
}
}
setTemperature(zone, temperature, available);
}
return true;
}
public boolean getDefrosterState(int zone) {
synchronized (mDefrosterState) {
return mDefrosterState.get(zone);
}
}
public void setDefrosterState(int zone, boolean state) {
synchronized (mDefrosterState) {
mDefrosterState.put(zone, state);
mLastDefrosterSet.put(zone, SystemClock.uptimeMillis());
}
}
public boolean shouldPropagateDefrosterUpdate(int zone, boolean defrosterState) {
synchronized (mDefrosterState) {
if (SystemClock.uptimeMillis() - mLastDefrosterSet.get(zone) < COALESCE_TIME_MS) {
return false;
}
mDefrosterState.put(zone, defrosterState);
}
return true;
}
public int getFanSpeed() {
synchronized (mFanSpeed) {
return mFanSpeed;
}
}
public void setFanSpeed(int speed) {
synchronized (mFanSpeed) {
mFanSpeed = speed;
mLastFanSpeedSet = SystemClock.uptimeMillis();
}
}
public boolean shouldPropagateFanSpeedUpdate(int zone, int speed) {
// TODO: We ignore fan speed zones for now because we dont have a multi zone car.
synchronized (mFanSpeed) {
if (SystemClock.uptimeMillis() - mLastFanSpeedSet < COALESCE_TIME_MS) {
return false;
}
mFanSpeed = speed;
}
return true;
}
public boolean getAcState() {
synchronized (mAcState) {
return mAcState;
}
}
public void setAcState(boolean acState) {
synchronized (mAcState) {
mAcState = acState;
mLastAcSet = SystemClock.uptimeMillis();
}
}
public boolean shouldPropagateAcUpdate(boolean acState) {
synchronized (mAcState) {
if (SystemClock.uptimeMillis() - mLastAcSet < COALESCE_TIME_MS) {
return false;
}
mAcState = acState;
}
return true;
}
public int getAirflow(int zone) {
synchronized (mAirflow) {
return mAirflow.get(zone);
}
}
public void setAirflow(int zone, int index) {
synchronized (mAirflow) {
mAirflow.put(zone, index);
mLastAirflowSet.put(zone, SystemClock.uptimeMillis());
}
}
public boolean shouldPropagateFanPositionUpdate(int zone, int index) {
synchronized (mAirflow) {
if (SystemClock.uptimeMillis() - mLastAirflowSet.get(zone) < COALESCE_TIME_MS) {
return false;
}
mAirflow.put(zone, index);
}
return true;
}
public float getSeatWarmerLevel(int zone) {
synchronized (mSeatWarmerLevel) {
return mSeatWarmerLevel.get(zone);
}
}
public void setSeatWarmerLevel(int zone, int level) {
synchronized (mSeatWarmerLevel) {
mSeatWarmerLevel.put(zone, level);
mLastSeatWarmerLevel.put(zone, SystemClock.uptimeMillis());
}
}
public boolean shouldPropagateSeatWarmerLevelUpdate(int zone, int level) {
synchronized (mSeatWarmerLevel) {
if (SystemClock.uptimeMillis() - mLastSeatWarmerLevel.get(zone) < COALESCE_TIME_MS) {
return false;
}
mSeatWarmerLevel.put(zone, level);
}
return true;
}
public boolean getAirCirculationState() {
synchronized (mAirCirculationState) {
return mAirCirculationState;
}
}
public void setAirCirculationState(boolean airCirculationState) {
synchronized (mAirCirculationState) {
mAirCirculationState = airCirculationState;
mAirCirculationLastSet = SystemClock.uptimeMillis();
}
}
public boolean shouldPropagateAirCirculationUpdate(boolean airCirculationState) {
synchronized (mAirCirculationState) {
if (SystemClock.uptimeMillis() - mAirCirculationLastSet < COALESCE_TIME_MS) {
return false;
}
mAcState = airCirculationState;
}
return true;
}
public boolean getAutoModeState() {
synchronized (mAutoModeState) {
return mAutoModeState;
}
}
public void setAutoModeState(boolean autoModeState) {
synchronized (mAutoModeState) {
mAutoModeState = autoModeState;
mAutoModeLastSet = SystemClock.uptimeMillis();
}
}
public boolean shouldPropagateAutoModeUpdate(boolean autoModeState) {
synchronized (mAutoModeState) {
if (SystemClock.uptimeMillis() - mAutoModeLastSet < COALESCE_TIME_MS) {
return false;
}
mAcState = autoModeState;
}
return true;
}
public boolean getHvacPowerState() {
synchronized (mHvacPowerState) {
return mHvacPowerState;
}
}
public void setHvacPowerState(boolean hvacPowerState) {
synchronized (mHvacPowerState) {
mHvacPowerState = hvacPowerState;
mHvacPowerLastSet = SystemClock.uptimeMillis();
}
}
public boolean shouldPropagateHvacPowerUpdate(boolean hvacPowerState) {
synchronized (mHvacPowerState) {
if (SystemClock.uptimeMillis() - mHvacPowerLastSet < COALESCE_TIME_MS) {
return false;
}
mHvacPowerState = hvacPowerState;
}
return true;
}
}