| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.car; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertTrue; |
| |
| import android.car.Car; |
| import android.car.CarNotConnectedException; |
| import android.car.hardware.CarSensorEvent; |
| import android.car.hardware.CarSensorManager; |
| import android.hardware.automotive.vehicle.V2_0.VehicleGear; |
| import android.hardware.automotive.vehicle.V2_0.VehicleIgnitionState; |
| import android.hardware.automotive.vehicle.V2_0.VehiclePropValue; |
| import android.hardware.automotive.vehicle.V2_0.VehicleProperty; |
| import android.os.SystemClock; |
| import android.test.suitebuilder.annotation.MediumTest; |
| import android.util.Log; |
| |
| import com.android.car.vehiclehal.VehiclePropValueBuilder; |
| |
| import org.junit.Test; |
| |
| /** |
| * Test the public entry points for the CarSensorManager |
| */ |
| @MediumTest |
| public class CarSensorManagerTest extends MockedCarTestBase { |
| private static final String TAG = CarSensorManagerTest.class.getSimpleName(); |
| |
| private CarSensorManager mCarSensorManager; |
| |
| @Override |
| protected synchronized void configureMockedHal() { |
| addProperty(VehicleProperty.NIGHT_MODE, |
| VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) |
| .addIntValue(0) |
| .build()); |
| addProperty(VehicleProperty.PERF_VEHICLE_SPEED, |
| VehiclePropValueBuilder.newBuilder(VehicleProperty.PERF_VEHICLE_SPEED) |
| .addFloatValue(0f) |
| .build()); |
| addProperty(VehicleProperty.FUEL_LEVEL, |
| VehiclePropValueBuilder.newBuilder(VehicleProperty.FUEL_LEVEL) |
| .addFloatValue(20000) // ml |
| .build()); |
| addProperty(VehicleProperty.PARKING_BRAKE_ON, |
| VehiclePropValueBuilder.newBuilder(VehicleProperty.PARKING_BRAKE_ON) |
| .setBooleanValue(true) |
| .build()); |
| addProperty(VehicleProperty.CURRENT_GEAR, |
| VehiclePropValueBuilder.newBuilder(VehicleProperty.CURRENT_GEAR) |
| .addIntValue(0) |
| .build()); |
| addProperty(VehicleProperty.GEAR_SELECTION, |
| VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION) |
| .addIntValue(0) |
| .build()); |
| addProperty(VehicleProperty.DRIVING_STATUS, |
| VehiclePropValueBuilder.newBuilder(VehicleProperty.DRIVING_STATUS) |
| .addIntValue(0) |
| .build()); |
| addProperty(VehicleProperty.IGNITION_STATE, |
| VehiclePropValueBuilder.newBuilder(VehicleProperty.IGNITION_STATE) |
| .addIntValue(CarSensorEvent.IGNITION_STATE_ACC) |
| .build()); |
| } |
| |
| @Override |
| public void setUp() throws Exception { |
| super.setUp(); |
| // Start the HAL layer and set up the sensor manager service |
| mCarSensorManager = (CarSensorManager) getCar().getCarManager(Car.SENSOR_SERVICE); |
| } |
| |
| /** |
| * Test single sensor availability entry point |
| * @throws Exception |
| */ |
| @Test |
| public void testSensorAvailability() throws Exception { |
| // NOTE: Update this test if/when the reserved values put into use. For now, we |
| // expect them to never be supported. |
| assertFalse(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_RESERVED1)); |
| assertFalse(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_RESERVED13)); |
| assertFalse(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_RESERVED21)); |
| |
| // We expect these sensors to always be available |
| assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_CAR_SPEED)); |
| assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_FUEL_LEVEL)); |
| assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_PARKING_BRAKE)); |
| assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_GEAR)); |
| assertTrue(mCarSensorManager.isSensorSupported(CarSensorManager.SENSOR_TYPE_NIGHT)); |
| assertTrue(mCarSensorManager.isSensorSupported( |
| CarSensorManager.SENSOR_TYPE_DRIVING_STATUS)); |
| assertTrue(mCarSensorManager.isSensorSupported( |
| CarSensorManager.SENSOR_TYPE_IGNITION_STATE)); |
| } |
| |
| /** |
| * Test sensor enumeration entry point |
| * @throws Exception |
| */ |
| @Test |
| public void testSensorEnumeration() throws Exception { |
| int[] supportedSensors = mCarSensorManager.getSupportedSensors(); |
| assertNotNull(supportedSensors); |
| |
| Log.i(TAG, "Found " + supportedSensors.length + " supported sensors."); |
| |
| // Unfortunately, we don't have a definitive range for legal sensor values, |
| // so we have set a "reasonable" range here. The ending value, in particular, |
| // will need to be updated if/when new sensor types are allowed. |
| // Here we are ensuring that all the enumerated sensors also return supported. |
| for (int candidate = 0; candidate <= CarSensorManager.SENSOR_TYPE_RESERVED21; ++candidate) { |
| boolean supported = mCarSensorManager.isSensorSupported(candidate); |
| boolean found = false; |
| for (int sensor : supportedSensors) { |
| if (candidate == sensor) { |
| found = true; |
| Log.i(TAG, "Sensor type " + sensor + " is supported."); |
| break; |
| } |
| } |
| |
| // Make sure the individual query on a sensor type is consistent |
| assertEquals(found, supported); |
| } |
| |
| // Here we simply ensure that one specific expected sensor is always available to help |
| // ensure we don't have a trivially broken test finding nothing. |
| boolean found = false; |
| for (int sensor : supportedSensors) { |
| if (sensor == CarSensorManager.SENSOR_TYPE_DRIVING_STATUS) { |
| found = true; |
| break; |
| } |
| } |
| assertTrue("We expect at least DRIVING_STATUS to be available", found); |
| } |
| |
| /** |
| * Test senor notification registration, delivery, and unregistration |
| * @throws Exception |
| */ |
| @Test |
| public void testEvents() throws Exception { |
| // Set up our listener callback |
| SensorListener listener = new SensorListener(); |
| mCarSensorManager.registerListener(listener, |
| CarSensorManager.SENSOR_TYPE_NIGHT, |
| CarSensorManager.SENSOR_RATE_NORMAL); |
| |
| VehiclePropValue value; |
| CarSensorEvent event; |
| CarSensorEvent.NightData data = null; |
| |
| listener.reset(); |
| |
| // Set the value TRUE and wait for the event to arrive |
| getMockedVehicleHal().injectEvent( |
| VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) |
| .setBooleanValue(true) |
| .setTimestamp(1L) |
| .build()); |
| assertTrue(listener.waitForSensorChange(1L)); |
| |
| // Ensure we got the expected event |
| assertEquals(listener.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); |
| |
| // Ensure we got the expected value in our callback |
| data = listener.getLastEvent().getNightData(data); |
| Log.d(TAG, "NightMode " + data.isNightMode + " at " + data.timestamp); |
| assertTrue(data.isNightMode); |
| |
| // Ensure we have the expected value in the sensor manager's cache |
| event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT); |
| assertNotNull(event); |
| data = event.getNightData(data); |
| assertEquals("Unexpected event timestamp", data.timestamp, 1); |
| assertTrue("Unexpected value", data.isNightMode); |
| |
| listener.reset(); |
| // Set the value FALSE |
| getMockedVehicleHal().injectEvent( |
| VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) |
| .setTimestamp(1001) |
| .setBooleanValue(false) |
| .build()); |
| assertTrue(listener.waitForSensorChange(1001)); |
| |
| // Ensure we got the expected event |
| assertEquals(listener.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); |
| |
| // Ensure we got the expected value in our callback |
| data = listener.getLastEvent().getNightData(data); |
| assertEquals("Unexpected event timestamp", 1001, data.timestamp); |
| assertFalse("Unexpected value", data.isNightMode); |
| |
| // Ensure we have the expected value in the sensor manager's cache |
| event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT); |
| assertNotNull(event); |
| data = event.getNightData(data); |
| assertFalse(data.isNightMode); |
| |
| // Unregister our handler (from all sensor types) |
| mCarSensorManager.unregisterListener(listener); |
| |
| listener.reset(); |
| // Set the value TRUE again |
| value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) |
| .setTimestamp(2001) |
| .setBooleanValue(true) |
| .build(); |
| getMockedVehicleHal().injectEvent(value); |
| |
| // Ensure we did not get a callback (should timeout) |
| Log.i(TAG, "waiting for unexpected callback -- should timeout."); |
| assertFalse(listener.waitForSensorChange(2001)); |
| |
| // Despite us not having a callback registered, the Sensor Manager should see the update |
| event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT); |
| assertNotNull(event); |
| data = event.getNightData(data); |
| assertEquals("Unexpected event timestamp", data.timestamp, 2001); |
| assertTrue("Unexpected value", data.isNightMode); |
| } |
| |
| @Test |
| public void testIgnitionState() throws CarNotConnectedException { |
| CarSensorEvent event = mCarSensorManager.getLatestSensorEvent( |
| CarSensorManager.SENSOR_TYPE_IGNITION_STATE); |
| assertNotNull(event); |
| assertEquals(CarSensorEvent.IGNITION_STATE_ACC, event.intValues[0]); |
| } |
| |
| @Test |
| public void testIgnitionEvents() throws Exception { |
| SensorListener listener = new SensorListener(); |
| mCarSensorManager.registerListener(listener, CarSensorManager.SENSOR_TYPE_IGNITION_STATE, |
| CarSensorManager.SENSOR_RATE_NORMAL); |
| |
| |
| // Mapping of HAL -> Manager ignition states. |
| int[] ignitionStates = new int[] { |
| VehicleIgnitionState.UNDEFINED, CarSensorEvent.IGNITION_STATE_UNDEFINED, |
| VehicleIgnitionState.LOCK, CarSensorEvent.IGNITION_STATE_LOCK, |
| VehicleIgnitionState.OFF, CarSensorEvent.IGNITION_STATE_OFF, |
| VehicleIgnitionState.ACC, CarSensorEvent.IGNITION_STATE_ACC, |
| VehicleIgnitionState.ON, CarSensorEvent.IGNITION_STATE_ON, |
| VehicleIgnitionState.START, CarSensorEvent.IGNITION_STATE_START, |
| VehicleIgnitionState.ON, CarSensorEvent.IGNITION_STATE_ON, |
| VehicleIgnitionState.LOCK, CarSensorEvent.IGNITION_STATE_LOCK, |
| }; |
| |
| for (int i = 0; i < ignitionStates.length; i += 2) { |
| injectIgnitionStateAndAssert(listener, ignitionStates[i], ignitionStates[i + 1]); |
| } |
| } |
| |
| private void injectIgnitionStateAndAssert(SensorListener listener, int halIgnitionState, |
| int mgrIgnitionState) throws Exception{ |
| listener.reset(); |
| long time = SystemClock.elapsedRealtimeNanos(); |
| getMockedVehicleHal().injectEvent( |
| VehiclePropValueBuilder.newBuilder(VehicleProperty.IGNITION_STATE) |
| .addIntValue(halIgnitionState) |
| .setTimestamp(time) |
| .build()); |
| assertTrue(listener.waitForSensorChange(time)); |
| |
| CarSensorEvent eventReceived = listener.getLastEvent(); |
| assertEquals(CarSensorManager.SENSOR_TYPE_IGNITION_STATE, eventReceived.sensorType); |
| assertEquals(mgrIgnitionState, eventReceived.intValues[0]); |
| } |
| |
| @Test |
| public void testIgnitionEvents_Bad() throws Exception { |
| SensorListener listener = new SensorListener(); |
| mCarSensorManager.registerListener(listener, CarSensorManager.SENSOR_TYPE_IGNITION_STATE, |
| CarSensorManager.SENSOR_RATE_NORMAL); |
| |
| listener.reset(); |
| long time = SystemClock.elapsedRealtimeNanos(); |
| getMockedVehicleHal().injectEvent( |
| VehiclePropValueBuilder.newBuilder(VehicleProperty.IGNITION_STATE) |
| .addIntValue(0xdeadbeef) |
| .setTimestamp(time) |
| .build()); |
| |
| // Make sure invalid events are never propagated to clients. |
| assertFalse(listener.waitForSensorChange(time)); |
| } |
| |
| @Test |
| public void testGear() throws Exception { |
| SensorListener listener = new SensorListener(); |
| mCarSensorManager.registerListener(listener, CarSensorManager.SENSOR_TYPE_GEAR, |
| CarSensorManager.SENSOR_RATE_NORMAL); |
| |
| // Mapping of HAL -> Manager gear selection states. |
| int[] gears = new int[] { |
| VehicleGear.GEAR_PARK, CarSensorEvent.GEAR_PARK, |
| VehicleGear.GEAR_DRIVE, CarSensorEvent.GEAR_DRIVE, |
| VehicleGear.GEAR_NEUTRAL, CarSensorEvent.GEAR_NEUTRAL, |
| VehicleGear.GEAR_REVERSE, CarSensorEvent.GEAR_REVERSE, |
| VehicleGear.GEAR_LOW, CarSensorEvent.GEAR_FIRST, |
| VehicleGear.GEAR_1, CarSensorEvent.GEAR_FIRST, |
| VehicleGear.GEAR_2, CarSensorEvent.GEAR_SECOND, |
| VehicleGear.GEAR_3, CarSensorEvent.GEAR_THIRD, |
| VehicleGear.GEAR_4, CarSensorEvent.GEAR_FOURTH, |
| VehicleGear.GEAR_5, CarSensorEvent.GEAR_FIFTH, |
| VehicleGear.GEAR_6, CarSensorEvent.GEAR_SIXTH, |
| VehicleGear.GEAR_7, CarSensorEvent.GEAR_SEVENTH, |
| VehicleGear.GEAR_8, CarSensorEvent.GEAR_EIGHTH, |
| VehicleGear.GEAR_9, CarSensorEvent.GEAR_NINTH, |
| }; |
| |
| for (int i = 0; i < gears.length; i += 2) { |
| injectGearEventAndAssert(listener, gears[i], gears[i + 1]); |
| } |
| |
| // invalid input should not be forwarded |
| long time = SystemClock.elapsedRealtimeNanos(); |
| getMockedVehicleHal().injectEvent( |
| VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION) |
| .addIntValue(0xdeadbeef) |
| .setTimestamp(time) |
| .build()); |
| assertFalse(listener.waitForSensorChange(time)); |
| CarSensorEvent event = mCarSensorManager.getLatestSensorEvent( |
| CarSensorManager.SENSOR_TYPE_GEAR); |
| assertNotNull(event); // Still holds an old event. |
| assertEquals(CarSensorEvent.GEAR_NINTH, event.intValues[0]); |
| } |
| |
| private void injectGearEventAndAssert(SensorListener listener, int halValue, |
| int carSensorValue) throws Exception { |
| listener.reset(); |
| long time = SystemClock.elapsedRealtimeNanos(); |
| getMockedVehicleHal().injectEvent( |
| VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION) |
| .addIntValue(halValue) |
| .setTimestamp(time) |
| .build()); |
| assertTrue(listener.waitForSensorChange(time)); |
| CarSensorEvent event = mCarSensorManager.getLatestSensorEvent( |
| CarSensorManager.SENSOR_TYPE_GEAR); |
| assertNotNull(event); |
| assertEquals(carSensorValue, event.intValues[0]); |
| } |
| |
| /** |
| * Test senor multiple liseners notification registration, delivery and unregistration. |
| * @throws Exception |
| */ |
| @Test |
| public void testEventsWithMultipleListeners() throws Exception { |
| // Set up our listeners callback |
| SensorListener listener1 = new SensorListener(); |
| SensorListener listener2 = new SensorListener(); |
| SensorListener listener3 = new SensorListener(); |
| |
| mCarSensorManager.registerListener(listener1, |
| CarSensorManager.SENSOR_TYPE_NIGHT, |
| CarSensorManager.SENSOR_RATE_NORMAL); |
| |
| mCarSensorManager.registerListener(listener2, |
| CarSensorManager.SENSOR_TYPE_NIGHT, |
| CarSensorManager.SENSOR_RATE_NORMAL); |
| |
| mCarSensorManager.registerListener(listener3, |
| CarSensorManager.SENSOR_TYPE_NIGHT, |
| CarSensorManager.SENSOR_RATE_FASTEST); |
| |
| CarSensorEvent.NightData data = null; |
| VehiclePropValue value; |
| CarSensorEvent event; |
| |
| listener1.reset(); |
| listener2.reset(); |
| listener3.reset(); |
| |
| // Set the value TRUE and wait for the event to arrive |
| value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) |
| .setTimestamp(42L) |
| .setBooleanValue(true) |
| .build(); |
| |
| getMockedVehicleHal().injectEvent(value); |
| |
| assertTrue(listener1.waitForSensorChange(42L)); |
| assertTrue(listener2.waitForSensorChange(42L)); |
| assertTrue(listener3.waitForSensorChange(42L)); |
| |
| // Ensure we got the expected event |
| assertEquals(listener1.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); |
| assertEquals(listener2.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); |
| assertEquals(listener3.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); |
| |
| // Ensure we got the expected value in our callback |
| data = listener1.getLastEvent().getNightData(data); |
| Log.d(TAG, "NightMode " + data.isNightMode + " at " + data.timestamp); |
| assertTrue(data.isNightMode); |
| |
| data = listener2.getLastEvent().getNightData(data); |
| Log.d(TAG, "NightMode " + data.isNightMode + " at " + data.timestamp); |
| assertTrue(data.isNightMode); |
| |
| data = listener3.getLastEvent().getNightData(data); |
| Log.d(TAG, "NightMode " + data.isNightMode + " at " + data.timestamp); |
| assertTrue(data.isNightMode); |
| |
| // Ensure we have the expected value in the sensor manager's cache |
| event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT); |
| data = event.getNightData(data); |
| assertEquals("Unexpected event timestamp", 42, data.timestamp); |
| assertTrue("Unexpected value", data.isNightMode); |
| |
| listener1.reset(); |
| listener2.reset(); |
| listener3.reset(); |
| // Set the value FALSE |
| value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) |
| .setTimestamp(1001) |
| .setBooleanValue(false) |
| .build(); |
| getMockedVehicleHal().injectEvent(value); |
| assertTrue(listener1.waitForSensorChange(1001)); |
| assertTrue(listener2.waitForSensorChange(1001)); |
| assertTrue(listener3.waitForSensorChange(1001)); |
| |
| // Ensure we got the expected event |
| assertEquals(listener1.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); |
| assertEquals(listener2.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); |
| assertEquals(listener3.getLastEvent().sensorType, CarSensorManager.SENSOR_TYPE_NIGHT); |
| |
| // Ensure we got the expected value in our callback |
| data = listener1.getLastEvent().getNightData(data); |
| assertEquals("Unexpected event timestamp", 1001, data.timestamp); |
| assertFalse("Unexpected value", data.isNightMode); |
| |
| data = listener2.getLastEvent().getNightData(data); |
| assertEquals("Unexpected event timestamp", 1001, data.timestamp); |
| assertFalse("Unexpected value", data.isNightMode); |
| |
| data = listener3.getLastEvent().getNightData(data); |
| listener3.reset(); |
| assertEquals("Unexpected event timestamp", 1001, data.timestamp); |
| assertFalse("Unexpected value", data.isNightMode); |
| |
| // Ensure we have the expected value in the sensor manager's cache |
| event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT); |
| data = event.getNightData(data); |
| assertFalse(data.isNightMode); |
| |
| Log.d(TAG, "Unregistering listener3"); |
| mCarSensorManager.unregisterListener(listener3); |
| |
| Log.d(TAG, "Rate changed - expect sensor restart and change event sent."); |
| assertTrue(listener1.waitForSensorChange()); |
| assertTrue(listener2.waitForSensorChange()); |
| assertFalse(listener3.waitForSensorChange()); |
| |
| listener1.reset(); |
| listener2.reset(); |
| listener3.reset(); |
| // Set the value TRUE again |
| value = VehiclePropValueBuilder.newBuilder(VehicleProperty.NIGHT_MODE) |
| .setTimestamp() |
| .setBooleanValue(true) |
| .build(); |
| getMockedVehicleHal().injectEvent(value); |
| |
| assertTrue(listener1.waitForSensorChange()); |
| assertTrue(listener2.waitForSensorChange()); |
| |
| listener1.reset(); |
| listener2.reset(); |
| |
| // Ensure we did not get a callback (should timeout) |
| Log.i(TAG, "waiting for unexpected callback -- should timeout."); |
| assertFalse(listener3.waitForSensorChange()); |
| |
| Log.d(TAG, "Unregistering listener2"); |
| mCarSensorManager.unregisterListener(listener3); |
| |
| Log.d(TAG, "Rate did nor change - dont expect sensor restart and change event sent."); |
| assertFalse(listener1.waitForSensorChange()); |
| assertFalse(listener2.waitForSensorChange()); |
| assertFalse(listener3.waitForSensorChange()); |
| } |
| |
| |
| /** |
| * Callback function we register for sensor update notifications. |
| * This tracks the number of times it has been called via the mAvailable semaphore, |
| * and keeps a reference to the most recent event delivered. |
| */ |
| class SensorListener implements CarSensorManager.OnSensorChangedListener { |
| private final Object mSync = new Object(); |
| |
| private CarSensorEvent mLastEvent = null; |
| |
| CarSensorEvent getLastEvent() { |
| return mLastEvent; |
| } |
| |
| void reset() { |
| synchronized (mSync) { |
| mLastEvent = null; |
| } |
| } |
| |
| boolean waitForSensorChange() throws InterruptedException { |
| return waitForSensorChange(0); |
| } |
| |
| // Returns True to indicate receipt of a sensor event. False indicates a timeout. |
| boolean waitForSensorChange(long eventTimeStamp) throws InterruptedException { |
| long start = SystemClock.elapsedRealtime(); |
| boolean matchTimeStamp = eventTimeStamp != 0; |
| synchronized (mSync) { |
| Log.d(TAG, "waitForSensorChange, mLastEvent: " + mLastEvent); |
| while ((mLastEvent == null |
| || (matchTimeStamp && mLastEvent.timestamp != eventTimeStamp)) |
| && (start + SHORT_WAIT_TIMEOUT_MS > SystemClock.elapsedRealtime())) { |
| mSync.wait(10L); |
| } |
| return mLastEvent != null && |
| (!matchTimeStamp || mLastEvent.timestamp == eventTimeStamp); |
| } |
| } |
| |
| @Override |
| public void onSensorChanged(CarSensorEvent event) { |
| Log.d(TAG, "onSensorChanged, event: " + event); |
| synchronized (mSync) { |
| // We're going to hold a reference to this object |
| mLastEvent = event; |
| mSync.notify(); |
| } |
| } |
| } |
| |
| } |