CarSensorManagerTest.java revision 80ebb3f9f9c380b120e3e239bca25af505ec4556
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
180        // Unregister our handler (from all sensor types)
181        mCarSensorManager.unregisterListener(listener);
182
183        // Set the value TRUE again
184        value = VehiclePropValueUtil.createBooleanValue(
185                VehicleNetworkConsts.VEHICLE_PROPERTY_NIGHT_MODE, true, 2001);
186        listener.checkNoSensorChangePosted();
187        getVehicleHalEmulator().injectEvent(value);
188
189        // Ensure we did not get a callback (should timeout)
190        Log.i(TAG, "waiting for unexpected callback -- should timeout.");
191        assertFalse(listener.waitForSensorChange());
192        listener.checkNoSensorChangePosted();
193
194        // Despite us not having a callback registered, the Sensor Manager should see the update
195        event = mCarSensorManager.getLatestSensorEvent(CarSensorManager.SENSOR_TYPE_NIGHT);
196        data = event.getNightData(data);
197        assertEquals("Unexpected event timestamp", data.timestamp, 2001);
198        assertTrue("Unexpected value", data.isNightMode);
199    }
200
201
202    /**
203     * Callback function we register for sensor update notifications.
204     * This tracks the number of times it has been called via the mAvailable semaphore,
205     * and keeps a reference to the most recent event delivered.
206     */
207    class SensorListener implements CarSensorManager.OnSensorChangedListener {
208
209        // Initialize the semaphore with ZERO callback events indicated
210        private Semaphore mAvailable = new Semaphore(0);
211
212        private CarSensorEvent mLastEvent = null;
213
214        public CarSensorEvent getLastEvent() {
215            return mLastEvent;
216        }
217
218        public void checkNoSensorChangePosted() {
219            // Verify that no permits are available (ie: the callback has not fired)
220            assertEquals("No events expected at this point.", 0, mAvailable.availablePermits());
221        }
222
223        // Returns True to indicate receipt of a sensor event.  False indicates a timeout.
224        public boolean waitForSensorChange() throws InterruptedException {
225            Log.i(TAG, "Waiting to for sensor update...");
226
227            long startTime = System.currentTimeMillis();
228            boolean result = mAvailable.tryAcquire(2L, TimeUnit.SECONDS);
229            long duration  = System.currentTimeMillis() - startTime;
230
231            Log.d(TAG, "tryAcquire returned " + result + " in " + duration + "ms");
232
233            return result;
234        }
235
236        @Override
237        public void onSensorChanged(CarSensorEvent event) {
238            Log.d(TAG, "onSensorChanged: " + event);
239
240            // We're going to hold a reference to this object
241            mLastEvent = event;
242
243            // Add one to the semaphore, indicating that we have run
244            mAvailable.release();
245        }
246    }
247
248}
249