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