• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 package com.android.car;
17 
18 import static com.google.common.truth.Truth.assertThat;
19 
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.assertTrue;
24 
25 import android.car.Car;
26 import android.car.CarNotConnectedException;
27 import android.car.drivingstate.CarDrivingStateEvent;
28 import android.car.drivingstate.CarDrivingStateManager;
29 import android.car.drivingstate.CarUxRestrictions;
30 import android.car.drivingstate.CarUxRestrictionsManager;
31 import android.hardware.automotive.vehicle.V2_0.VehicleGear;
32 import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
33 import android.os.SystemClock;
34 import android.support.test.filters.SmallTest;
35 import android.support.test.runner.AndroidJUnit4;
36 import android.util.Log;
37 
38 import com.android.car.vehiclehal.VehiclePropValueBuilder;
39 import com.android.internal.annotations.GuardedBy;
40 
41 import org.junit.Test;
42 import org.junit.runner.RunWith;
43 
44 @RunWith(AndroidJUnit4.class)
45 @SmallTest
46 public class CarDrivingRestrictionsTest extends MockedCarTestBase {
47     private static final String TAG = CarDrivingRestrictionsTest.class
48             .getSimpleName();
49     private CarDrivingStateManager mCarDrivingStateManager;
50     private CarUxRestrictionsManager mCarUxRManager;
51 
52     @Override
configureMockedHal()53     protected synchronized void configureMockedHal() {
54         addProperty(VehicleProperty.PERF_VEHICLE_SPEED, VehiclePropValueBuilder
55                 .newBuilder(VehicleProperty.PERF_VEHICLE_SPEED)
56                 .addFloatValue(0f)
57                 .build());
58         addProperty(VehicleProperty.PARKING_BRAKE_ON, VehiclePropValueBuilder
59                 .newBuilder(VehicleProperty.PARKING_BRAKE_ON)
60                 .setBooleanValue(false)
61                 .build());
62         addProperty(VehicleProperty.GEAR_SELECTION, VehiclePropValueBuilder
63                 .newBuilder(VehicleProperty.GEAR_SELECTION)
64                 .addIntValue(0)
65                 .build());
66     }
67 
68     @Override
setUp()69     public void setUp() throws Exception {
70         super.setUp();
71         mCarDrivingStateManager = (CarDrivingStateManager) getCar()
72                 .getCarManager(Car.CAR_DRIVING_STATE_SERVICE);
73         mCarUxRManager = (CarUxRestrictionsManager) getCar()
74                 .getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);
75     }
76 
77     @Test
testDrivingStateChange()78     public void testDrivingStateChange() throws CarNotConnectedException, InterruptedException {
79         CarDrivingStateEvent drivingEvent;
80         CarUxRestrictions restrictions;
81         DrivingStateListener listener = new DrivingStateListener();
82         mCarDrivingStateManager.registerListener(listener);
83         mCarUxRManager.registerListener(listener);
84         // With no gear value available, driving state should be unknown
85         listener.reset();
86         // Test Parked state and corresponding restrictions based on car_ux_restrictions_map.xml
87         Log.d(TAG, "Injecting gear park");
88         getMockedVehicleHal().injectEvent(
89                 VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION)
90                         .addIntValue(VehicleGear.GEAR_PARK)
91                         .setTimestamp(SystemClock.elapsedRealtimeNanos())
92                         .build());
93         drivingEvent = listener.waitForDrivingStateChange();
94         assertNotNull(drivingEvent);
95         assertThat(drivingEvent.eventValue).isEqualTo(CarDrivingStateEvent.DRIVING_STATE_PARKED);
96 
97         Log.d(TAG, "Injecting speed 0");
98         getMockedVehicleHal().injectEvent(
99                 VehiclePropValueBuilder.newBuilder(VehicleProperty.PERF_VEHICLE_SPEED)
100                         .addFloatValue(0.0f)
101                         .setTimestamp(SystemClock.elapsedRealtimeNanos())
102                         .build());
103 
104         // Switch gear to drive.  Driving state changes to Idling but the UX restrictions don't
105         // change between parked and idling.
106         listener.reset();
107         Log.d(TAG, "Injecting gear drive");
108         getMockedVehicleHal().injectEvent(
109                 VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION)
110                         .addIntValue(VehicleGear.GEAR_DRIVE)
111                         .setTimestamp(SystemClock.elapsedRealtimeNanos())
112                         .build());
113         drivingEvent = listener.waitForDrivingStateChange();
114         assertNotNull(drivingEvent);
115         assertThat(drivingEvent.eventValue).isEqualTo(CarDrivingStateEvent.DRIVING_STATE_IDLING);
116 
117         // Test Moving state and corresponding restrictions based on car_ux_restrictions_map.xml
118         listener.reset();
119         Log.d(TAG, "Injecting speed 30");
120         getMockedVehicleHal().injectEvent(
121                 VehiclePropValueBuilder.newBuilder(VehicleProperty.PERF_VEHICLE_SPEED)
122                         .addFloatValue(30.0f)
123                         .setTimestamp(SystemClock.elapsedRealtimeNanos())
124                         .build());
125         drivingEvent = listener.waitForDrivingStateChange();
126         assertNotNull(drivingEvent);
127         assertThat(drivingEvent.eventValue).isEqualTo(CarDrivingStateEvent.DRIVING_STATE_MOVING);
128         restrictions = listener.waitForUxRestrictionsChange();
129         assertNotNull(restrictions);
130         assertTrue(restrictions.isRequiresDistractionOptimization());
131         assertThat(restrictions.getActiveRestrictions())
132                 .isEqualTo(CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED);
133 
134         // Test Idling state and corresponding restrictions based on car_ux_restrictions_map.xml
135         listener.reset();
136         Log.d(TAG, "Injecting speed 0");
137         getMockedVehicleHal().injectEvent(
138                 VehiclePropValueBuilder.newBuilder(VehicleProperty.PERF_VEHICLE_SPEED)
139                         .addFloatValue(0.0f)
140                         .setTimestamp(SystemClock.elapsedRealtimeNanos())
141                         .build());
142         drivingEvent = listener.waitForDrivingStateChange();
143         assertNotNull(drivingEvent);
144         assertThat(drivingEvent.eventValue).isEqualTo(CarDrivingStateEvent.DRIVING_STATE_IDLING);
145         restrictions = listener.waitForUxRestrictionsChange();
146         assertNotNull(restrictions);
147         assertFalse(restrictions.isRequiresDistractionOptimization());
148         assertThat(restrictions.getActiveRestrictions())
149                 .isEqualTo(CarUxRestrictions.UX_RESTRICTIONS_BASELINE);
150 
151         // Apply Parking brake.  Supported gears is not provided in this test and hence
152         // Automatic transmission should be assumed and hence parking brake state should not
153         // make a difference to the driving state.
154         listener.reset();
155         Log.d(TAG, "Injecting parking brake on");
156         getMockedVehicleHal().injectEvent(
157                 VehiclePropValueBuilder.newBuilder(VehicleProperty.PARKING_BRAKE_ON)
158                         .setBooleanValue(true)
159                         .setTimestamp(SystemClock.elapsedRealtimeNanos())
160                         .build());
161         drivingEvent = listener.waitForDrivingStateChange();
162         assertNull(drivingEvent);
163 
164         mCarDrivingStateManager.unregisterListener();
165         mCarUxRManager.unregisterListener();
166     }
167 
168     @Test
testDrivingStateChangeForMalformedInputs()169     public void testDrivingStateChangeForMalformedInputs()
170             throws CarNotConnectedException, InterruptedException {
171         CarDrivingStateEvent drivingEvent;
172         CarUxRestrictions restrictions;
173         DrivingStateListener listener = new DrivingStateListener();
174         mCarDrivingStateManager.registerListener(listener);
175         mCarUxRManager.registerListener(listener);
176 
177         // Start with gear = park and speed = 0 to begin with a known state.
178         listener.reset();
179         Log.d(TAG, "Injecting gear park");
180         getMockedVehicleHal().injectEvent(
181                 VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION)
182                         .addIntValue(VehicleGear.GEAR_PARK)
183                         .setTimestamp(SystemClock.elapsedRealtimeNanos())
184                         .build());
185         drivingEvent = listener.waitForDrivingStateChange();
186         assertNotNull(drivingEvent);
187         assertThat(drivingEvent.eventValue).isEqualTo(CarDrivingStateEvent.DRIVING_STATE_PARKED);
188 
189         Log.d(TAG, "Injecting speed 0");
190         getMockedVehicleHal().injectEvent(
191                 VehiclePropValueBuilder.newBuilder(VehicleProperty.PERF_VEHICLE_SPEED)
192                         .addFloatValue(0.0f)
193                         .setTimestamp(SystemClock.elapsedRealtimeNanos())
194                         .build());
195 
196         // Inject an invalid gear.  Since speed is still valid, idling will be the expected
197         // driving state
198         listener.reset();
199         Log.d(TAG, "Injecting gear -1");
200         getMockedVehicleHal().injectEvent(
201                 VehiclePropValueBuilder.newBuilder(VehicleProperty.GEAR_SELECTION)
202                         .addIntValue(-1)
203                         .setTimestamp(SystemClock.elapsedRealtimeNanos())
204                         .build());
205         drivingEvent = listener.waitForDrivingStateChange();
206         assertNotNull(drivingEvent);
207         assertThat(drivingEvent.eventValue).isEqualTo(CarDrivingStateEvent.DRIVING_STATE_IDLING);
208 
209         // Now, send in an invalid speed value as well, now the driving state will be unknown and
210         // the UX restrictions will change to fully restricted.
211         listener.reset();
212         Log.d(TAG, "Injecting speed -1");
213         getMockedVehicleHal().injectEvent(
214                 VehiclePropValueBuilder.newBuilder(VehicleProperty.PERF_VEHICLE_SPEED)
215                         .addFloatValue(-1.0f)
216                         .setTimestamp(SystemClock.elapsedRealtimeNanos())
217                         .build());
218         drivingEvent = listener.waitForDrivingStateChange();
219         assertNotNull(drivingEvent);
220         assertThat(drivingEvent.eventValue).isEqualTo(CarDrivingStateEvent.DRIVING_STATE_UNKNOWN);
221         restrictions = listener.waitForUxRestrictionsChange();
222         assertNotNull(restrictions);
223         assertTrue(restrictions.isRequiresDistractionOptimization());
224         assertThat(restrictions.getActiveRestrictions())
225                 .isEqualTo(CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED);
226         mCarDrivingStateManager.unregisterListener();
227         mCarUxRManager.unregisterListener();
228     }
229 
230     /**
231      * Callback function we register for driving state update notifications.
232      */
233     private class DrivingStateListener implements
234             CarDrivingStateManager.CarDrivingStateEventListener,
235             CarUxRestrictionsManager.OnUxRestrictionsChangedListener {
236         private final Object mDrivingStateLock = new Object();
237         @GuardedBy("mDrivingStateLock")
238         private CarDrivingStateEvent mLastEvent = null;
239         private final Object mUxRLock = new Object();
240         @GuardedBy("mUxRLock")
241         private CarUxRestrictions mLastRestrictions = null;
242 
reset()243         void reset() {
244             mLastEvent = null;
245             mLastRestrictions = null;
246         }
247 
248         // Returns True to indicate receipt of a driving state event.  False indicates a timeout.
waitForDrivingStateChange()249         CarDrivingStateEvent waitForDrivingStateChange() throws InterruptedException {
250             long start = SystemClock.elapsedRealtime();
251 
252             synchronized (mDrivingStateLock) {
253                 while (mLastEvent == null
254                         && (start + DEFAULT_WAIT_TIMEOUT_MS > SystemClock.elapsedRealtime())) {
255                     mDrivingStateLock.wait(100L);
256                 }
257                 return mLastEvent;
258             }
259         }
260 
261         @Override
onDrivingStateChanged(CarDrivingStateEvent event)262         public void onDrivingStateChanged(CarDrivingStateEvent event) {
263             Log.d(TAG, "onDrivingStateChanged, event: " + event.eventValue);
264             synchronized (mDrivingStateLock) {
265                 // We're going to hold a reference to this object
266                 mLastEvent = event;
267                 mDrivingStateLock.notify();
268             }
269         }
270 
waitForUxRestrictionsChange()271         CarUxRestrictions waitForUxRestrictionsChange() throws InterruptedException {
272             long start = SystemClock.elapsedRealtime();
273             synchronized (mUxRLock) {
274                 while (mLastRestrictions == null
275                         && (start + DEFAULT_WAIT_TIMEOUT_MS > SystemClock.elapsedRealtime())) {
276                     mUxRLock.wait(100L);
277                 }
278             }
279             return mLastRestrictions;
280         }
281 
282         @Override
onUxRestrictionsChanged(CarUxRestrictions restrictions)283         public void onUxRestrictionsChanged(CarUxRestrictions restrictions) {
284             Log.d(TAG, "onUxRestrictionsChanged, restrictions: "
285                     + restrictions.getActiveRestrictions());
286             synchronized (mUxRLock) {
287                 mLastRestrictions = restrictions;
288                 mUxRLock.notify();
289             }
290         }
291     }
292 }
293