• 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 com.android.car;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertTrue;
22 
23 import android.car.Car;
24 import android.car.hardware.CarPropertyValue;
25 import android.car.hardware.hvac.CarHvacManager;
26 import android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback;
27 import android.car.hardware.hvac.CarHvacManager.PropertyId;
28 import android.hardware.automotive.vehicle.V2_0.VehicleAreaSeat;
29 import android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow;
30 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
31 import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
32 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
33 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
34 import android.os.SystemClock;
35 import android.support.test.filters.MediumTest;
36 import android.support.test.runner.AndroidJUnit4;
37 import android.util.Log;
38 import android.util.MutableInt;
39 
40 import com.android.car.vehiclehal.VehiclePropValueBuilder;
41 import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
42 
43 import org.junit.Test;
44 import org.junit.runner.RunWith;
45 
46 import java.util.HashMap;
47 import java.util.concurrent.CountDownLatch;
48 import java.util.concurrent.Semaphore;
49 import java.util.concurrent.TimeUnit;
50 
51 @RunWith(AndroidJUnit4.class)
52 @MediumTest
53 public class CarHvacManagerTest extends MockedCarTestBase {
54     private static final String TAG = CarHvacManagerTest.class.getSimpleName();
55 
56     // Use this semaphore to block until the callback is heard of.
57     private Semaphore mAvailable;
58 
59     private CarHvacManager mCarHvacManager;
60     private boolean mEventBoolVal;
61     private float mEventFloatVal;
62     private int mEventIntVal;
63     private int mEventZoneVal;
64 
65     @Override
configureMockedHal()66     protected synchronized void configureMockedHal() {
67         HvacPropertyHandler handler = new HvacPropertyHandler();
68         addProperty(VehicleProperty.HVAC_DEFROSTER, handler)
69                 .addAreaConfig(VehicleAreaWindow.FRONT_WINDSHIELD, 0, 0);
70         addProperty(VehicleProperty.HVAC_FAN_SPEED, handler)
71                 .addAreaConfig(VehicleAreaSeat.ROW_1_LEFT, 0, 0);
72         addProperty(VehicleProperty.HVAC_TEMPERATURE_SET, handler)
73                 .addAreaConfig(VehicleAreaSeat.ROW_1_LEFT, 0, 0);
74         addProperty(VehicleProperty.HVAC_TEMPERATURE_CURRENT, handler)
75                 .setChangeMode(VehiclePropertyChangeMode.CONTINUOUS)
76                 .setAccess(VehiclePropertyAccess.READ)
77                 .addAreaConfig(VehicleAreaSeat.ROW_1_LEFT | VehicleAreaSeat.ROW_1_RIGHT, 0, 0);
78     }
79 
80     @Override
setUp()81     public void setUp() throws Exception {
82         super.setUp();
83         mAvailable = new Semaphore(0);
84         mCarHvacManager = (CarHvacManager) getCar().getCarManager(Car.HVAC_SERVICE);
85     }
86 
87     // Test a boolean property
88     @Test
testHvacRearDefrosterOn()89     public void testHvacRearDefrosterOn() throws Exception {
90         mCarHvacManager.setBooleanProperty(CarHvacManager.ID_WINDOW_DEFROSTER_ON,
91                 VehicleAreaWindow.FRONT_WINDSHIELD, true);
92         boolean defrost = mCarHvacManager.getBooleanProperty(CarHvacManager.ID_WINDOW_DEFROSTER_ON,
93                 VehicleAreaWindow.FRONT_WINDSHIELD);
94         assertTrue(defrost);
95 
96         mCarHvacManager.setBooleanProperty(CarHvacManager.ID_WINDOW_DEFROSTER_ON,
97                 VehicleAreaWindow.FRONT_WINDSHIELD, false);
98         defrost = mCarHvacManager.getBooleanProperty(CarHvacManager.ID_WINDOW_DEFROSTER_ON,
99                 VehicleAreaWindow.FRONT_WINDSHIELD);
100         assertFalse(defrost);
101     }
102 
103     // Test an integer property
104     @Test
testHvacFanSpeed()105     public void testHvacFanSpeed() throws Exception {
106         mCarHvacManager.setIntProperty(CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT,
107                 VehicleAreaSeat.ROW_1_LEFT, 15);
108         int speed = mCarHvacManager.getIntProperty(CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT,
109                 VehicleAreaSeat.ROW_1_LEFT);
110         assertEquals(15, speed);
111 
112         mCarHvacManager.setIntProperty(CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT,
113                 VehicleAreaSeat.ROW_1_LEFT, 23);
114         speed = mCarHvacManager.getIntProperty(CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT,
115                 VehicleAreaSeat.ROW_1_LEFT);
116         assertEquals(23, speed);
117     }
118 
119     // Test an float property
120     @Test
testHvacTempSetpoint()121     public void testHvacTempSetpoint() throws Exception {
122         mCarHvacManager.setFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT,
123                 VehicleAreaSeat.ROW_1_LEFT, 70);
124         float temp = mCarHvacManager.getFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT,
125                 VehicleAreaSeat.ROW_1_LEFT);
126         assertEquals(70.0, temp, 0);
127 
128         mCarHvacManager.setFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT,
129                 VehicleAreaSeat.ROW_1_LEFT, (float) 65.5);
130         temp = mCarHvacManager.getFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT,
131                 VehicleAreaSeat.ROW_1_LEFT);
132         assertEquals(65.5, temp, 0);
133     }
134 
135     @Test
testError()136     public void testError() throws Exception {
137         final int PROP = VehicleProperty.HVAC_DEFROSTER;
138         final int AREA = VehicleAreaWindow.FRONT_WINDSHIELD;
139         final int ERR_CODE = 42;
140 
141         CountDownLatch errorLatch = new CountDownLatch(1);
142         MutableInt propertyIdReceived = new MutableInt(0);
143         MutableInt areaIdReceived = new MutableInt(0);
144 
145         mCarHvacManager.registerCallback(new CarHvacEventCallback()  {
146             @Override
147             public void onChangeEvent(CarPropertyValue value) {
148 
149             }
150 
151             @Override
152             public void onErrorEvent(@PropertyId int propertyId, int area) {
153                 propertyIdReceived.value = propertyId;
154                 areaIdReceived.value = area;
155                 errorLatch.countDown();
156             }
157         });
158 
159         getMockedVehicleHal().injectError(ERR_CODE, PROP, AREA);
160         assertTrue(errorLatch.await(DEFAULT_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS));
161         assertEquals(PROP, propertyIdReceived.value);
162         assertEquals(AREA, areaIdReceived.value);
163     }
164 
165     // Test an event
166     @Test
testEvent()167     public void testEvent() throws Exception {
168         mCarHvacManager.registerCallback(new EventListener());
169         // Wait for events generated on registration
170         assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
171         assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
172         assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
173         assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
174 
175         // Inject a boolean event and wait for its callback in onPropertySet.
176         VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.HVAC_DEFROSTER)
177                 .setAreaId(VehicleAreaWindow.FRONT_WINDSHIELD)
178                 .setTimestamp(SystemClock.elapsedRealtimeNanos())
179                 .addIntValue(1)
180                 .build();
181         assertEquals(0, mAvailable.availablePermits());
182         getMockedVehicleHal().injectEvent(v);
183 
184         assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
185         assertTrue(mEventBoolVal);
186         assertEquals(mEventZoneVal, VehicleAreaWindow.FRONT_WINDSHIELD);
187 
188         // Inject a float event and wait for its callback in onPropertySet.
189         v = VehiclePropValueBuilder.newBuilder(VehicleProperty.HVAC_TEMPERATURE_CURRENT)
190                 .setAreaId(VehicleAreaSeat.ROW_1_LEFT | VehicleAreaSeat.ROW_1_RIGHT)
191                 .setTimestamp(SystemClock.elapsedRealtimeNanos())
192                 .addFloatValue(67f)
193                 .build();
194         assertEquals(0, mAvailable.availablePermits());
195         getMockedVehicleHal().injectEvent(v);
196 
197         assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
198         assertEquals(67, mEventFloatVal, 0);
199         assertEquals(VehicleAreaSeat.ROW_1_LEFT | VehicleAreaSeat.ROW_1_RIGHT, mEventZoneVal);
200 
201         // Inject an integer event and wait for its callback in onPropertySet.
202         v = VehiclePropValueBuilder.newBuilder(VehicleProperty.HVAC_FAN_SPEED)
203                 .setAreaId(VehicleAreaSeat.ROW_1_LEFT)
204                 .setTimestamp(SystemClock.elapsedRealtimeNanos())
205                 .addIntValue(4)
206                 .build();
207         assertEquals(0, mAvailable.availablePermits());
208         getMockedVehicleHal().injectEvent(v);
209 
210         assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
211         assertEquals(4, mEventIntVal);
212         assertEquals(VehicleAreaSeat.ROW_1_LEFT, mEventZoneVal);
213     }
214 
215     private class HvacPropertyHandler implements VehicleHalPropertyHandler {
216         HashMap<Integer, VehiclePropValue> mMap = new HashMap<>();
217 
218         @Override
onPropertySet(VehiclePropValue value)219         public synchronized void onPropertySet(VehiclePropValue value) {
220             mMap.put(value.prop, value);
221         }
222 
223         @Override
onPropertyGet(VehiclePropValue value)224         public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) {
225             VehiclePropValue currentValue = mMap.get(value.prop);
226             // VNS will call get method when subscribe is called, just return empty value.
227             return currentValue != null ? currentValue : value;
228         }
229 
230         @Override
onPropertySubscribe(int property, float sampleRate)231         public synchronized void onPropertySubscribe(int property, float sampleRate) {
232             Log.d(TAG, "onPropertySubscribe property " + property + " sampleRate " + sampleRate);
233             if (mMap.get(property) == null) {
234                 Log.d(TAG, "onPropertySubscribe add dummy property: " + property);
235                 VehiclePropValue dummyValue = VehiclePropValueBuilder.newBuilder(property)
236                         .setAreaId(0)
237                         .setTimestamp(SystemClock.elapsedRealtimeNanos())
238                         .addIntValue(1)
239                         .addFloatValue(1)
240                         .build();
241                 mMap.put(property, dummyValue);
242             }
243         }
244 
245         @Override
onPropertyUnsubscribe(int property)246         public synchronized void onPropertyUnsubscribe(int property) {
247             Log.d(TAG, "onPropertyUnSubscribe property " + property);
248         }
249     }
250 
251     private class EventListener implements CarHvacEventCallback {
EventListener()252         EventListener() { }
253 
254         @Override
onChangeEvent(final CarPropertyValue value)255         public void onChangeEvent(final CarPropertyValue value) {
256             Log.d(TAG, "onChangeEvent: "  + value);
257             Object o = value.getValue();
258             mEventZoneVal = value.getAreaId();
259 
260             if (o instanceof Integer) {
261                 mEventIntVal = (Integer) o;
262             } else if (o instanceof Float) {
263                 mEventFloatVal = (Float) o;
264             } else if (o instanceof Boolean) {
265                 mEventBoolVal = (Boolean) o;
266             }
267             mAvailable.release();
268         }
269 
270         @Override
onErrorEvent(final int propertyId, final int zone)271         public void onErrorEvent(final int propertyId, final int zone) {
272             Log.d(TAG, "Error:  propertyId=" + propertyId + "  zone=" + zone);
273         }
274     }
275 }
276