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