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