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.CarNotConnectedException; 21 import android.car.hardware.CarSensorEvent; 22 import android.car.hardware.CarSensorManager; 23 import android.hardware.automotive.vehicle.V2_0.VehicleGear; 24 import android.hardware.automotive.vehicle.V2_0.VehicleIgnitionState; 25 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue; 26 import android.hardware.automotive.vehicle.V2_0.VehicleProperty; 27 import android.os.SystemClock; 28 import android.test.suitebuilder.annotation.MediumTest; 29 import android.util.Log; 30 31 import com.android.car.vehiclehal.VehiclePropValueBuilder; 32 33 /** 34 * Test the public entry points for the CarSensorManager 35 */ 36 @MediumTest 37 public class CarSensorManagerTest extends MockedCarTestBase { 38 private static final String TAG = CarSensorManagerTest.class.getSimpleName(); 39 40 private CarSensorManager mCarSensorManager; 41 42 @Override 43 protected synchronized void configureMockedHal() { 44 addProperty(VehicleProperty.NIGHT_MODE, 45 VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) 46 .addIntValue(0) 47 .build()); 48 addProperty(VehicleProperty.PERF_VEHICLE_SPEED, 49 VehiclePropValueBuilder.newBuilder(VehicleProperty.PERF_VEHICLE_SPEED) 50 .addFloatValue(0f) 51 .build()); 52 addProperty(VehicleProperty.FUEL_LEVEL_LOW, 53 VehiclePropValueBuilder.newBuilder(VehicleProperty.FUEL_LEVEL_LOW) 54 .setBooleanValue(false) 55 .build()); 56 addProperty(VehicleProperty.PARKING_BRAKE_ON, 57 VehiclePropValueBuilder.newBuilder(VehicleProperty.PARKING_BRAKE_ON) 58 .setBooleanValue(true) 59 .build()); 60 addProperty(VehicleProperty.CURRENT_GEAR, 61 VehiclePropValueBuilder.newBuilder(VehicleProperty.CURRENT_GEAR) 62 .addIntValue(0) 63 .build()); 64 addProperty(VehicleProperty.GEAR_SELECTION, 65 VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION) 66 .addIntValue(0) 67 .build()); 68 addProperty(VehicleProperty.DRIVING_STATUS, 69 VehiclePropValueBuilder.newBuilder(VehicleProperty.DRIVING_STATUS) 70 .addIntValue(0) 71 .build()); 72 addProperty(VehicleProperty.IGNITION_STATE, 73 VehiclePropValueBuilder.newBuilder(VehicleProperty.IGNITION_STATE) 74 .addIntValue(CarSensorEvent.IGNITION_STATE_ACC) 75 .build()); 76 } 77 78 @Override 79 protected void setUp() throws Exception { 80 super.setUp(); 81 // Start the HAL layer and set up the sensor manager service 82 mCarSensorManager = (CarSensorManager) getCar().getCarManager(Car.SENSOR_SERVICE); 83 } 84 85 /** 86 * Test single sensor availability entry point 87 * @throws Exception 88 */ 89 public void testSensorAvailability() throws Exception { 90 // NOTE: Update this test if/when the reserved values put into use. For now, we 91 // expect them to never be supported. 92 assertFalse(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_RESERVED1)); 93 assertFalse(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_RESERVED13)); 94 assertFalse(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_RESERVED21)); 95 96 // We expect these sensors to always be available 97 assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_CAR_SPEED)); 98 assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_FUEL_LEVEL)); 99 assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_PARKING_BRAKE)); 100 assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_GEAR)); 101 assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_NIGHT)); 102 assertTrue(mCarSensorManager.isSensorSupported( 103 CarSensorManager.SENSOR_TYPE_DRIVING_STATUS)); 104 assertTrue(mCarSensorManager.isSensorSupported( 105 CarSensorManager.SENSOR_TYPE_IGNITION_STATE)); 106 } 107 108 /** 109 * Test sensor enumeration entry point 110 * @throws Exception 111 */ 112 public void testSensorEnumeration() throws Exception { 113 int[] supportedSensors = mCarSensorManager.getSupportedSensors(); 114 assertNotNull(supportedSensors); 115 116 Log.i(TAG, "Found " + supportedSensors.length + " supported sensors."); 117 118 // Unfortunately, we don't have a definitive range for legal sensor values, 119 // so we have set a "reasonable" range here. The ending value, in particular, 120 // will need to be updated if/when new sensor types are allowed. 121 // Here we are ensuring that all the enumerated sensors also return supported. 122 for (int candidate = 0; candidate <= CarSensorManager.SENSOR_TYPE_RESERVED21; ++candidate) { 123 boolean supported = mCarSensorManager.isSensorSupported(candidate); 124 boolean found = false; 125 for (int sensor : supportedSensors) { 126 if (candidate == sensor) { 127 found = true; 128 Log.i(TAG, "Sensor type " + sensor + " is supported."); 129 break; 130 } 131 } 132 133 // Make sure the individual query on a sensor type is consistent 134 assertEquals(found, supported); 135 } 136 137 // Here we simply ensure that one specific expected sensor is always available to help 138 // ensure we don't have a trivially broken test finding nothing. 139 boolean found = false; 140 for (int sensor : supportedSensors) { 141 if (sensor == CarSensorManager.SENSOR_TYPE_DRIVING_STATUS) { 142 found = true; 143 break; 144 } 145 } 146 assertTrue("We expect at least DRIVING_STATUS to be available", found); 147 } 148 149 /** 150 * Test senor notification registration, delivery, and unregistration 151 * @throws Exception 152 */ 153 public void testEvents() throws Exception { 154 // Set up our listener callback 155 SensorListener listener = new SensorListener(); 156 mCarSensorManager.registerListener(listener, 157 CarSensorManager.SENSOR_TYPE_NIGHT, 158 CarSensorManager.SENSOR_RATE_NORMAL); 159 160 VehiclePropValue value; 161 CarSensorEvent event; 162 CarSensorEvent.NightData data = null; 163 164 listener.reset(); 165 166 // Set the value TRUE and wait for the event to arrive 167 getMockedVehicleHal().injectEvent( 168 VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) 169 .setBooleanValue(true) 170 .setTimestamp(1L) 171 .build()); 172 assertTrue(listener.waitForSensorChange(1L)); 173 174 // Ensure we got the expected event 175 assertEquals(listener.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); 176 177 // Ensure we got the expected value in our callback 178 data = listener.getLastEvent().getNightData(data); 179 Log.d(TAG, "NightMode " + data.isNightMode + " at " + data.timestamp); 180 assertTrue(data.isNightMode); 181 182 // Ensure we have the expected value in the sensor manager's cache 183 event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT); 184 assertNotNull(event); 185 data = event.getNightData(data); 186 assertEquals("Unexpected event timestamp", data.timestamp, 1); 187 assertTrue("Unexpected value", data.isNightMode); 188 189 listener.reset(); 190 // Set the value FALSE 191 getMockedVehicleHal().injectEvent( 192 VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) 193 .setTimestamp(1001) 194 .setBooleanValue(false) 195 .build()); 196 assertTrue(listener.waitForSensorChange(1001)); 197 198 // Ensure we got the expected event 199 assertEquals(listener.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); 200 201 // Ensure we got the expected value in our callback 202 data = listener.getLastEvent().getNightData(data); 203 assertEquals("Unexpected event timestamp", 1001, data.timestamp); 204 assertFalse("Unexpected value", data.isNightMode); 205 206 // Ensure we have the expected value in the sensor manager's cache 207 event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT); 208 assertNotNull(event); 209 data = event.getNightData(data); 210 assertFalse(data.isNightMode); 211 212 // Unregister our handler (from all sensor types) 213 mCarSensorManager.unregisterListener(listener); 214 215 listener.reset(); 216 // Set the value TRUE again 217 value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) 218 .setTimestamp(2001) 219 .setBooleanValue(true) 220 .build(); 221 getMockedVehicleHal().injectEvent(value); 222 223 // Ensure we did not get a callback (should timeout) 224 Log.i(TAG, "waiting for unexpected callback -- should timeout."); 225 assertFalse(listener.waitForSensorChange(2001)); 226 227 // Despite us not having a callback registered, the Sensor Manager should see the update 228 event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT); 229 assertNotNull(event); 230 data = event.getNightData(data); 231 assertEquals("Unexpected event timestamp", data.timestamp, 2001); 232 assertTrue("Unexpected value", data.isNightMode); 233 } 234 235 public void testIgnitionState() throws CarNotConnectedException { 236 CarSensorEvent event = mCarSensorManager.getLatestSensorEvent( 237 CarSensorManager.SENSOR_TYPE_IGNITION_STATE); 238 assertNotNull(event); 239 assertEquals(CarSensorEvent.IGNITION_STATE_ACC, event.intValues[0]); 240 } 241 242 public void testIgnitionEvents() throws Exception { 243 SensorListener listener = new SensorListener(); 244 mCarSensorManager.registerListener(listener, CarSensorManager.SENSOR_TYPE_IGNITION_STATE, 245 CarSensorManager.SENSOR_RATE_NORMAL); 246 247 248 // Mapping of HAL -> Manager ignition states. 249 int[] ignitionStates = new int[] { 250 VehicleIgnitionState.UNDEFINED, CarSensorEvent.IGNITION_STATE_UNDEFINED, 251 VehicleIgnitionState.LOCK, CarSensorEvent.IGNITION_STATE_LOCK, 252 VehicleIgnitionState.OFF, CarSensorEvent.IGNITION_STATE_OFF, 253 VehicleIgnitionState.ACC, CarSensorEvent.IGNITION_STATE_ACC, 254 VehicleIgnitionState.ON, CarSensorEvent.IGNITION_STATE_ON, 255 VehicleIgnitionState.START, CarSensorEvent.IGNITION_STATE_START, 256 VehicleIgnitionState.ON, CarSensorEvent.IGNITION_STATE_ON, 257 VehicleIgnitionState.LOCK, CarSensorEvent.IGNITION_STATE_LOCK, 258 }; 259 260 for (int i = 0; i < ignitionStates.length; i += 2) { 261 injectIgnitionStateAndAssert(listener, ignitionStates[i], ignitionStates[i + 1]); 262 } 263 } 264 265 private void injectIgnitionStateAndAssert(SensorListener listener, int halIgnitionState, 266 int mgrIgnitionState) throws Exception{ 267 listener.reset(); 268 long time = SystemClock.elapsedRealtimeNanos(); 269 getMockedVehicleHal().injectEvent( 270 VehiclePropValueBuilder.newBuilder(VehicleProperty.IGNITION_STATE) 271 .addIntValue(halIgnitionState) 272 .setTimestamp(time) 273 .build()); 274 assertTrue(listener.waitForSensorChange(time)); 275 276 CarSensorEvent eventReceived = listener.getLastEvent(); 277 assertEquals(CarSensorManager.SENSOR_TYPE_IGNITION_STATE, eventReceived.sensorType); 278 assertEquals(mgrIgnitionState, eventReceived.intValues[0]); 279 } 280 281 public void testIgnitionEvents_Bad() throws Exception { 282 SensorListener listener = new SensorListener(); 283 mCarSensorManager.registerListener(listener, CarSensorManager.SENSOR_TYPE_IGNITION_STATE, 284 CarSensorManager.SENSOR_RATE_NORMAL); 285 286 listener.reset(); 287 long time = SystemClock.elapsedRealtimeNanos(); 288 getMockedVehicleHal().injectEvent( 289 VehiclePropValueBuilder.newBuilder(VehicleProperty.IGNITION_STATE) 290 .addIntValue(0xdeadbeef) 291 .setTimestamp(time) 292 .build()); 293 294 // Make sure invalid events are never propagated to clients. 295 assertFalse(listener.waitForSensorChange(time)); 296 } 297 298 public void testGear() throws Exception { 299 SensorListener listener = new SensorListener(); 300 mCarSensorManager.registerListener(listener, CarSensorManager.SENSOR_TYPE_GEAR, 301 CarSensorManager.SENSOR_RATE_NORMAL); 302 303 // Mapping of HAL -> Manager gear selection states. 304 int[] gears = new int[] { 305 VehicleGear.GEAR_PARK, CarSensorEvent.GEAR_PARK, 306 VehicleGear.GEAR_DRIVE, CarSensorEvent.GEAR_DRIVE, 307 VehicleGear.GEAR_NEUTRAL, CarSensorEvent.GEAR_NEUTRAL, 308 VehicleGear.GEAR_REVERSE, CarSensorEvent.GEAR_REVERSE, 309 VehicleGear.GEAR_LOW, CarSensorEvent.GEAR_FIRST, 310 VehicleGear.GEAR_1, CarSensorEvent.GEAR_FIRST, 311 VehicleGear.GEAR_2, CarSensorEvent.GEAR_SECOND, 312 VehicleGear.GEAR_3, CarSensorEvent.GEAR_THIRD, 313 VehicleGear.GEAR_4, CarSensorEvent.GEAR_FOURTH, 314 VehicleGear.GEAR_5, CarSensorEvent.GEAR_FIFTH, 315 VehicleGear.GEAR_6, CarSensorEvent.GEAR_SIXTH, 316 VehicleGear.GEAR_7, CarSensorEvent.GEAR_SEVENTH, 317 VehicleGear.GEAR_8, CarSensorEvent.GEAR_EIGHTH, 318 VehicleGear.GEAR_9, CarSensorEvent.GEAR_NINTH, 319 }; 320 321 for (int i = 0; i < gears.length; i += 2) { 322 injectGearEventAndAssert(listener, gears[i], gears[i + 1]); 323 } 324 325 // invalid input should not be forwarded 326 long time = SystemClock.elapsedRealtimeNanos(); 327 getMockedVehicleHal().injectEvent( 328 VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION) 329 .addIntValue(0xdeadbeef) 330 .setTimestamp(time) 331 .build()); 332 assertFalse(listener.waitForSensorChange(time)); 333 CarSensorEvent event = mCarSensorManager.getLatestSensorEvent( 334 CarSensorManager.SENSOR_TYPE_GEAR); 335 assertNotNull(event); // Still holds an old event. 336 assertEquals(CarSensorEvent.GEAR_NINTH, event.intValues[0]); 337 } 338 339 private void injectGearEventAndAssert(SensorListener listener, int halValue, 340 int carSensorValue) throws Exception { 341 listener.reset(); 342 long time = SystemClock.elapsedRealtimeNanos(); 343 getMockedVehicleHal().injectEvent( 344 VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION) 345 .addIntValue(halValue) 346 .setTimestamp(time) 347 .build()); 348 assertTrue(listener.waitForSensorChange(time)); 349 CarSensorEvent event = mCarSensorManager.getLatestSensorEvent( 350 CarSensorManager.SENSOR_TYPE_GEAR); 351 assertNotNull(event); 352 assertEquals(carSensorValue, event.intValues[0]); 353 } 354 355 /** 356 * Test senor multiple liseners notification registration, delivery and unregistration. 357 * @throws Exception 358 */ 359 public void testEventsWithMultipleListeners() throws Exception { 360 // Set up our listeners callback 361 SensorListener listener1 = new SensorListener(); 362 SensorListener listener2 = new SensorListener(); 363 SensorListener listener3 = new SensorListener(); 364 365 mCarSensorManager.registerListener(listener1, 366 CarSensorManager.SENSOR_TYPE_NIGHT, 367 CarSensorManager.SENSOR_RATE_NORMAL); 368 369 mCarSensorManager.registerListener(listener2, 370 CarSensorManager.SENSOR_TYPE_NIGHT, 371 CarSensorManager.SENSOR_RATE_NORMAL); 372 373 mCarSensorManager.registerListener(listener3, 374 CarSensorManager.SENSOR_TYPE_NIGHT, 375 CarSensorManager.SENSOR_RATE_FASTEST); 376 377 CarSensorEvent.NightData data = null; 378 VehiclePropValue value; 379 CarSensorEvent event; 380 381 listener1.reset(); 382 listener2.reset(); 383 listener3.reset(); 384 385 // Set the value TRUE and wait for the event to arrive 386 value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) 387 .setTimestamp(42L) 388 .setBooleanValue(true) 389 .build(); 390 391 getMockedVehicleHal().injectEvent(value); 392 393 assertTrue(listener1.waitForSensorChange(42L)); 394 assertTrue(listener2.waitForSensorChange(42L)); 395 assertTrue(listener3.waitForSensorChange(42L)); 396 397 // Ensure we got the expected event 398 assertEquals(listener1.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); 399 assertEquals(listener2.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); 400 assertEquals(listener3.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); 401 402 // Ensure we got the expected value in our callback 403 data = listener1.getLastEvent().getNightData(data); 404 Log.d(TAG, "NightMode " + data.isNightMode + " at " + data.timestamp); 405 assertTrue(data.isNightMode); 406 407 data = listener2.getLastEvent().getNightData(data); 408 Log.d(TAG, "NightMode " + data.isNightMode + " at " + data.timestamp); 409 assertTrue(data.isNightMode); 410 411 data = listener3.getLastEvent().getNightData(data); 412 Log.d(TAG, "NightMode " + data.isNightMode + " at " + data.timestamp); 413 assertTrue(data.isNightMode); 414 415 // Ensure we have the expected value in the sensor manager's cache 416 event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT); 417 data = event.getNightData(data); 418 assertEquals("Unexpected event timestamp", 42, data.timestamp); 419 assertTrue("Unexpected value", data.isNightMode); 420 421 listener1.reset(); 422 listener2.reset(); 423 listener3.reset(); 424 // Set the value FALSE 425 value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) 426 .setTimestamp(1001) 427 .setBooleanValue(false) 428 .build(); 429 getMockedVehicleHal().injectEvent(value); 430 assertTrue(listener1.waitForSensorChange(1001)); 431 assertTrue(listener2.waitForSensorChange(1001)); 432 assertTrue(listener3.waitForSensorChange(1001)); 433 434 // Ensure we got the expected event 435 assertEquals(listener1.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); 436 assertEquals(listener2.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); 437 assertEquals(listener3.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); 438 439 // Ensure we got the expected value in our callback 440 data = listener1.getLastEvent().getNightData(data); 441 assertEquals("Unexpected event timestamp", 1001, data.timestamp); 442 assertFalse("Unexpected value", data.isNightMode); 443 444 data = listener2.getLastEvent().getNightData(data); 445 assertEquals("Unexpected event timestamp", 1001, data.timestamp); 446 assertFalse("Unexpected value", data.isNightMode); 447 448 data = listener3.getLastEvent().getNightData(data); 449 listener3.reset(); 450 assertEquals("Unexpected event timestamp", 1001, data.timestamp); 451 assertFalse("Unexpected value", data.isNightMode); 452 453 // Ensure we have the expected value in the sensor manager's cache 454 event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT); 455 data = event.getNightData(data); 456 assertFalse(data.isNightMode); 457 458 Log.d(TAG, "Unregistering listener3"); 459 mCarSensorManager.unregisterListener(listener3); 460 461 Log.d(TAG, "Rate changed - expect sensor restart and change event sent."); 462 assertTrue(listener1.waitForSensorChange()); 463 assertTrue(listener2.waitForSensorChange()); 464 assertFalse(listener3.waitForSensorChange()); 465 466 listener1.reset(); 467 listener2.reset(); 468 listener3.reset(); 469 // Set the value TRUE again 470 value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) 471 .setTimestamp() 472 .setBooleanValue(true) 473 .build(); 474 getMockedVehicleHal().injectEvent(value); 475 476 assertTrue(listener1.waitForSensorChange()); 477 assertTrue(listener2.waitForSensorChange()); 478 479 listener1.reset(); 480 listener2.reset(); 481 482 // Ensure we did not get a callback (should timeout) 483 Log.i(TAG, "waiting for unexpected callback -- should timeout."); 484 assertFalse(listener3.waitForSensorChange()); 485 486 Log.d(TAG, "Unregistering listener2"); 487 mCarSensorManager.unregisterListener(listener3); 488 489 Log.d(TAG, "Rate did nor change - dont expect sensor restart and change event sent."); 490 assertFalse(listener1.waitForSensorChange()); 491 assertFalse(listener2.waitForSensorChange()); 492 assertFalse(listener3.waitForSensorChange()); 493 } 494 495 496 /** 497 * Callback function we register for sensor update notifications. 498 * This tracks the number of times it has been called via the mAvailable semaphore, 499 * and keeps a reference to the most recent event delivered. 500 */ 501 class SensorListener implements CarSensorManager.OnSensorChangedListener { 502 private final Object mSync = new Object(); 503 504 private CarSensorEvent mLastEvent = null; 505 506 CarSensorEvent getLastEvent() { 507 return mLastEvent; 508 } 509 510 void reset() { 511 synchronized (mSync) { 512 mLastEvent = null; 513 } 514 } 515 516 boolean waitForSensorChange() throws InterruptedException { 517 return waitForSensorChange(0); 518 } 519 520 // Returns True to indicate receipt of a sensor event. False indicates a timeout. 521 boolean waitForSensorChange(long eventTimeStamp) throws InterruptedException { 522 long start = SystemClock.elapsedRealtime(); 523 boolean matchTimeStamp = eventTimeStamp != 0; 524 synchronized (mSync) { 525 Log.d(TAG, "waitForSensorChange, mLastEvent: " + mLastEvent); 526 while ((mLastEvent == null 527 || (matchTimeStamp && mLastEvent.timestamp != eventTimeStamp)) 528 && (start + SHORT_WAIT_TIMEOUT_MS > SystemClock.elapsedRealtime())) { 529 mSync.wait(10L); 530 } 531 return mLastEvent != null && 532 (!matchTimeStamp || mLastEvent.timestamp == eventTimeStamp); 533 } 534 } 535 536 @Override 537 public void onSensorChanged(CarSensorEvent event) { 538 Log.d(TAG, "onSensorChanged, event: " + event); 539 synchronized (mSync) { 540 // We're going to hold a reference to this object 541 mLastEvent = event; 542 mSync.notify(); 543 } 544 } 545 } 546 547 } 548