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.test; 18 19 import android.car.Car; 20 import android.car.hardware.CarPropertyValue; 21 import android.car.hardware.hvac.CarHvacManager; 22 import android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback; 23 import android.car.hardware.hvac.CarHvacManager.PropertyId; 24 import android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow; 25 import android.hardware.automotive.vehicle.V2_0.VehicleAreaZone; 26 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue; 27 import android.hardware.automotive.vehicle.V2_0.VehicleProperty; 28 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess; 29 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode; 30 import android.os.SystemClock; 31 import android.test.suitebuilder.annotation.MediumTest; 32 import android.util.Log; 33 import android.util.MutableInt; 34 35 import com.android.car.vehiclehal.VehiclePropValueBuilder; 36 import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler; 37 38 import java.util.HashMap; 39 import java.util.concurrent.CountDownLatch; 40 import java.util.concurrent.Semaphore; 41 import java.util.concurrent.TimeUnit; 42 43 @MediumTest 44 public 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