CarSensorManagerTest.java revision 0d07c76bbc788fba8c77d8e932330ab22ec6ba27
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.CarSensorEvent; 21import android.car.hardware.CarSensorManager; 22import android.hardware.vehicle.V2_0.VehiclePropValue; 23import android.hardware.vehicle.V2_0.VehicleProperty; 24import android.os.SystemClock; 25import android.test.suitebuilder.annotation.MediumTest; 26import android.util.Log; 27 28import com.android.car.vehiclehal.VehiclePropValueBuilder; 29 30/** 31 * Test the public entry points for the CarSensorManager 32 */ 33@MediumTest 34public class CarSensorManagerTest extends MockedCarTestBase { 35 private static final String TAG = CarSensorManagerTest.class.getSimpleName(); 36 37 private CarSensorManager mCarSensorManager; 38 39 @Override 40 protected synchronized void configureMockedHal() { 41 addProperty(VehicleProperty.NIGHT_MODE, 42 VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) 43 .addIntValue(0) 44 .build()); 45 addProperty(VehicleProperty.PERF_VEHICLE_SPEED, 46 VehiclePropValueBuilder.newBuilder(VehicleProperty.PERF_VEHICLE_SPEED) 47 .addFloatValue(0f) 48 .build()); 49 addProperty(VehicleProperty.FUEL_LEVEL_LOW, 50 VehiclePropValueBuilder.newBuilder(VehicleProperty.FUEL_LEVEL_LOW) 51 .setBooleanValue(false) 52 .build()); 53 addProperty(VehicleProperty.PARKING_BRAKE_ON, 54 VehiclePropValueBuilder.newBuilder(VehicleProperty.PARKING_BRAKE_ON) 55 .setBooleanValue(true) 56 .build()); 57 addProperty(VehicleProperty.CURRENT_GEAR, 58 VehiclePropValueBuilder.newBuilder(VehicleProperty.CURRENT_GEAR) 59 .addIntValue(0) 60 .build()); 61 addProperty(VehicleProperty.GEAR_SELECTION, 62 VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION) 63 .addIntValue(0) 64 .build()); 65 addProperty(VehicleProperty.DRIVING_STATUS, 66 VehiclePropValueBuilder.newBuilder(VehicleProperty.DRIVING_STATUS) 67 .addIntValue(0) 68 .build()); 69 } 70 71 @Override 72 protected void setUp() throws Exception { 73 super.setUp(); 74 // Start the HAL layer and set up the sensor manager service 75 mCarSensorManager = (CarSensorManager) getCar().getCarManager(Car.SENSOR_SERVICE); 76 } 77 78 /** 79 * Test single sensor availability entry point 80 * @throws Exception 81 */ 82 public void testSensorAvailability() throws Exception { 83 // NOTE: Update this test if/when the reserved values put into use. For now, we 84 // expect them to never be supported. 85 assertFalse(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_RESERVED1)); 86 assertFalse(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_RESERVED13)); 87 assertFalse(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_RESERVED21)); 88 89 // We expect these sensors to always be available 90 assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_CAR_SPEED)); 91 assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_FUEL_LEVEL)); 92 assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_PARKING_BRAKE)); 93 assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_GEAR)); 94 assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_NIGHT)); 95 assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_DRIVING_STATUS)); 96 } 97 98 /** 99 * Test sensor enumeration entry point 100 * @throws Exception 101 */ 102 public void testSensorEnumeration() throws Exception { 103 int[] supportedSensors = mCarSensorManager.getSupportedSensors(); 104 assertNotNull(supportedSensors); 105 106 Log.i(TAG, "Found " + supportedSensors.length + " supported sensors."); 107 108 // Unfortunately, we don't have a definitive range for legal sensor values, 109 // so we have set a "reasonable" range here. The ending value, in particular, 110 // will need to be updated if/when new sensor types are allowed. 111 // Here we are ensuring that all the enumerated sensors also return supported. 112 for (int candidate = 0; candidate <= CarSensorManager.SENSOR_TYPE_RESERVED21; ++candidate) { 113 boolean supported = mCarSensorManager.isSensorSupported(candidate); 114 boolean found = false; 115 for (int sensor : supportedSensors) { 116 if (candidate == sensor) { 117 found = true; 118 Log.i(TAG, "Sensor type " + sensor + " is supported."); 119 break; 120 } 121 } 122 123 // Make sure the individual query on a sensor type is consistent 124 assertEquals(found, supported); 125 } 126 127 // Here we simply ensure that one specific expected sensor is always available to help 128 // ensure we don't have a trivially broken test finding nothing. 129 boolean found = false; 130 for (int sensor : supportedSensors) { 131 if (sensor == CarSensorManager.SENSOR_TYPE_DRIVING_STATUS) { 132 found = true; 133 break; 134 } 135 } 136 assertTrue("We expect at least DRIVING_STATUS to be available", found); 137 } 138 139 /** 140 * Test senor notification registration, delivery, and unregistration 141 * @throws Exception 142 */ 143 public void testEvents() throws Exception { 144 // Set up our listener callback 145 SensorListener listener = new SensorListener(); 146 mCarSensorManager.registerListener(listener, 147 CarSensorManager.SENSOR_TYPE_NIGHT, 148 CarSensorManager.SENSOR_RATE_NORMAL); 149 150 VehiclePropValue value; 151 CarSensorEvent event; 152 CarSensorEvent.NightData data = null; 153 154 listener.reset(); 155 156 // Set the value TRUE and wait for the event to arrive 157 getMockedVehicleHal().injectEvent( 158 VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) 159 .setBooleanValue(true) 160 .setTimestamp(1L) 161 .build()); 162 assertTrue(listener.waitForSensorChange(1L)); 163 164 // Ensure we got the expected event 165 assertEquals(listener.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); 166 167 // Ensure we got the expected value in our callback 168 data = listener.getLastEvent().getNightData(data); 169 Log.d(TAG, "NightMode " + data.isNightMode + " at " + data.timestamp); 170 assertTrue(data.isNightMode); 171 172 // Ensure we have the expected value in the sensor manager's cache 173 event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT); 174 assertNotNull(event); 175 data = event.getNightData(data); 176 assertEquals("Unexpected event timestamp", data.timestamp, 1); 177 assertTrue("Unexpected value", data.isNightMode); 178 179 listener.reset(); 180 // Set the value FALSE 181 getMockedVehicleHal().injectEvent( 182 VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) 183 .setTimestamp(1001) 184 .setBooleanValue(false) 185 .build()); 186 assertTrue(listener.waitForSensorChange(1001)); 187 188 // Ensure we got the expected event 189 assertEquals(listener.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); 190 191 // Ensure we got the expected value in our callback 192 data = listener.getLastEvent().getNightData(data); 193 assertEquals("Unexpected event timestamp", 1001, data.timestamp); 194 assertFalse("Unexpected value", data.isNightMode); 195 196 // Ensure we have the expected value in the sensor manager's cache 197 event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT); 198 assertNotNull(event); 199 data = event.getNightData(data); 200 assertFalse(data.isNightMode); 201 202 // Unregister our handler (from all sensor types) 203 mCarSensorManager.unregisterListener(listener); 204 205 listener.reset(); 206 // Set the value TRUE again 207 value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) 208 .setTimestamp(2001) 209 .setBooleanValue(true) 210 .build(); 211 getMockedVehicleHal().injectEvent(value); 212 213 // Ensure we did not get a callback (should timeout) 214 Log.i(TAG, "waiting for unexpected callback -- should timeout."); 215 assertFalse(listener.waitForSensorChange(2001)); 216 217 // Despite us not having a callback registered, the Sensor Manager should see the update 218 event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT); 219 assertNotNull(event); 220 data = event.getNightData(data); 221 assertEquals("Unexpected event timestamp", data.timestamp, 2001); 222 assertTrue("Unexpected value", data.isNightMode); 223 } 224 225 226 /** 227 * Test senor multiple liseners notification registration, delivery and unregistration. 228 * @throws Exception 229 */ 230 public void testEventsWithMultipleListeners() throws Exception { 231 // Set up our listeners callback 232 SensorListener listener1 = new SensorListener(); 233 SensorListener listener2 = new SensorListener(); 234 SensorListener listener3 = new SensorListener(); 235 236 mCarSensorManager.registerListener(listener1, 237 CarSensorManager.SENSOR_TYPE_NIGHT, 238 CarSensorManager.SENSOR_RATE_NORMAL); 239 240 mCarSensorManager.registerListener(listener2, 241 CarSensorManager.SENSOR_TYPE_NIGHT, 242 CarSensorManager.SENSOR_RATE_NORMAL); 243 244 mCarSensorManager.registerListener(listener3, 245 CarSensorManager.SENSOR_TYPE_NIGHT, 246 CarSensorManager.SENSOR_RATE_FASTEST); 247 248 CarSensorEvent.NightData data = null; 249 VehiclePropValue value; 250 CarSensorEvent event; 251 252 listener1.reset(); 253 listener2.reset(); 254 listener3.reset(); 255 256 // Set the value TRUE and wait for the event to arrive 257 value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) 258 .setTimestamp(42L) 259 .setBooleanValue(true) 260 .build(); 261 262 getMockedVehicleHal().injectEvent(value); 263 264 assertTrue(listener1.waitForSensorChange(42L)); 265 assertTrue(listener2.waitForSensorChange(42L)); 266 assertTrue(listener3.waitForSensorChange(42L)); 267 268 // Ensure we got the expected event 269 assertEquals(listener1.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); 270 assertEquals(listener2.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); 271 assertEquals(listener3.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); 272 273 // Ensure we got the expected value in our callback 274 data = listener1.getLastEvent().getNightData(data); 275 Log.d(TAG, "NightMode " + data.isNightMode + " at " + data.timestamp); 276 assertTrue(data.isNightMode); 277 278 data = listener2.getLastEvent().getNightData(data); 279 Log.d(TAG, "NightMode " + data.isNightMode + " at " + data.timestamp); 280 assertTrue(data.isNightMode); 281 282 data = listener3.getLastEvent().getNightData(data); 283 Log.d(TAG, "NightMode " + data.isNightMode + " at " + data.timestamp); 284 assertTrue(data.isNightMode); 285 286 // Ensure we have the expected value in the sensor manager's cache 287 event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT); 288 data = event.getNightData(data); 289 assertEquals("Unexpected event timestamp", 42, data.timestamp); 290 assertTrue("Unexpected value", data.isNightMode); 291 292 listener1.reset(); 293 listener2.reset(); 294 listener3.reset(); 295 // Set the value FALSE 296 value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) 297 .setTimestamp(1001) 298 .setBooleanValue(false) 299 .build(); 300 getMockedVehicleHal().injectEvent(value); 301 assertTrue(listener1.waitForSensorChange(1001)); 302 assertTrue(listener2.waitForSensorChange(1001)); 303 assertTrue(listener3.waitForSensorChange(1001)); 304 305 // Ensure we got the expected event 306 assertEquals(listener1.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); 307 assertEquals(listener2.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); 308 assertEquals(listener3.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); 309 310 // Ensure we got the expected value in our callback 311 data = listener1.getLastEvent().getNightData(data); 312 assertEquals("Unexpected event timestamp", 1001, data.timestamp); 313 assertFalse("Unexpected value", data.isNightMode); 314 315 data = listener2.getLastEvent().getNightData(data); 316 assertEquals("Unexpected event timestamp", 1001, data.timestamp); 317 assertFalse("Unexpected value", data.isNightMode); 318 319 data = listener3.getLastEvent().getNightData(data); 320 listener3.reset(); 321 assertEquals("Unexpected event timestamp", 1001, data.timestamp); 322 assertFalse("Unexpected value", data.isNightMode); 323 324 // Ensure we have the expected value in the sensor manager's cache 325 event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT); 326 data = event.getNightData(data); 327 assertFalse(data.isNightMode); 328 329 Log.d(TAG, "Unregistering listener3"); 330 mCarSensorManager.unregisterListener(listener3); 331 332 Log.d(TAG, "Rate changed - expect sensor restart and change event sent."); 333 assertTrue(listener1.waitForSensorChange()); 334 assertTrue(listener2.waitForSensorChange()); 335 assertFalse(listener3.waitForSensorChange()); 336 337 listener1.reset(); 338 listener2.reset(); 339 listener3.reset(); 340 // Set the value TRUE again 341 value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) 342 .setTimestamp() 343 .setBooleanValue(true) 344 .build(); 345 getMockedVehicleHal().injectEvent(value); 346 347 assertTrue(listener1.waitForSensorChange()); 348 assertTrue(listener2.waitForSensorChange()); 349 350 listener1.reset(); 351 listener2.reset(); 352 353 // Ensure we did not get a callback (should timeout) 354 Log.i(TAG, "waiting for unexpected callback -- should timeout."); 355 assertFalse(listener3.waitForSensorChange()); 356 357 Log.d(TAG, "Unregistering listener2"); 358 mCarSensorManager.unregisterListener(listener3); 359 360 Log.d(TAG, "Rate did nor change - dont expect sensor restart and change event sent."); 361 assertFalse(listener1.waitForSensorChange()); 362 assertFalse(listener2.waitForSensorChange()); 363 assertFalse(listener3.waitForSensorChange()); 364 } 365 366 367 /** 368 * Callback function we register for sensor update notifications. 369 * This tracks the number of times it has been called via the mAvailable semaphore, 370 * and keeps a reference to the most recent event delivered. 371 */ 372 class SensorListener implements CarSensorManager.OnSensorChangedListener { 373 private final Object mSync = new Object(); 374 375 private CarSensorEvent mLastEvent = null; 376 377 CarSensorEvent getLastEvent() { 378 return mLastEvent; 379 } 380 381 void reset() { 382 synchronized (mSync) { 383 mLastEvent = null; 384 } 385 } 386 387 boolean waitForSensorChange() throws InterruptedException { 388 return waitForSensorChange(0); 389 } 390 391 // Returns True to indicate receipt of a sensor event. False indicates a timeout. 392 boolean waitForSensorChange(long eventTimeStamp) throws InterruptedException { 393 long start = SystemClock.elapsedRealtime(); 394 boolean matchTimeStamp = eventTimeStamp != 0; 395 synchronized (mSync) { 396 Log.d(TAG, "waitForSensorChange, mLastEvent: " + mLastEvent); 397 while ((mLastEvent == null 398 || (matchTimeStamp && mLastEvent.timestamp != eventTimeStamp)) 399 && (start + SHORT_WAIT_TIMEOUT_MS > SystemClock.elapsedRealtime())) { 400 mSync.wait(10L); 401 } 402 return mLastEvent != null && 403 (!matchTimeStamp || mLastEvent.timestamp == eventTimeStamp); 404 } 405 } 406 407 @Override 408 public void onSensorChanged(CarSensorEvent event) { 409 Log.d(TAG, "onSensorChanged, event: " + event); 410 synchronized (mSync) { 411 // We're going to hold a reference to this object 412 mLastEvent = event; 413 mSync.notify(); 414 } 415 } 416 } 417 418} 419