• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertTrue;
22 
23 import android.car.Car;
24 import android.car.hardware.CarPropertyValue;
25 import android.car.hardware.cabin.CarCabinManager;
26 import android.car.hardware.cabin.CarCabinManager.CarCabinEventCallback;
27 import android.car.hardware.cabin.CarCabinManager.PropertyId;
28 import android.hardware.automotive.vehicle.V2_0.VehicleAreaDoor;
29 import android.hardware.automotive.vehicle.V2_0.VehicleAreaWindow;
30 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
31 import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
32 import android.os.SystemClock;
33 import android.util.Log;
34 import android.util.MutableInt;
35 
36 import androidx.test.ext.junit.runners.AndroidJUnit4;
37 import androidx.test.filters.FlakyTest;
38 import androidx.test.filters.MediumTest;
39 
40 import com.android.car.vehiclehal.VehiclePropValueBuilder;
41 import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
42 
43 import org.junit.Test;
44 import org.junit.runner.RunWith;
45 
46 import java.util.HashMap;
47 import java.util.concurrent.CountDownLatch;
48 import java.util.concurrent.Semaphore;
49 import java.util.concurrent.TimeUnit;
50 
51 @RunWith(AndroidJUnit4.class)
52 @MediumTest
53 public class CarCabinManagerTest extends MockedCarTestBase {
54     private static final String TAG = CarCabinManagerTest.class.getSimpleName();
55 
56     // Use this semaphore to block until the callback is heard of.
57     private Semaphore mAvailable;
58 
59     private CarCabinManager mCarCabinManager;
60     private boolean mEventBoolVal;
61     private int mEventIntVal;
62     private int mEventZoneVal;
63 
64     @Override
configureMockedHal()65     protected synchronized void configureMockedHal() {
66         CabinPropertyHandler handler = new CabinPropertyHandler();
67         addProperty(VehicleProperty.DOOR_LOCK, handler)
68                 .addAreaConfig(VehicleAreaDoor.ROW_1_LEFT, 0, 0);
69         addProperty(VehicleProperty.WINDOW_POS, handler)
70                 .addAreaConfig(VehicleAreaWindow.ROW_1_LEFT, 0, 0);
71     }
72 
73     @Override
setUp()74     public void setUp() throws Exception {
75         super.setUp();
76         mAvailable = new Semaphore(0);
77         mCarCabinManager = (CarCabinManager) getCar().getCarManager(Car.CABIN_SERVICE);
78     }
79 
80     // Test a boolean property
81     @Test
testCabinDoorLockOn()82     public void testCabinDoorLockOn() throws Exception {
83         mCarCabinManager.setBooleanProperty(CarCabinManager.ID_DOOR_LOCK,
84                 VehicleAreaDoor.ROW_1_LEFT, true);
85         boolean lock = mCarCabinManager.getBooleanProperty(CarCabinManager.ID_DOOR_LOCK,
86                 VehicleAreaDoor.ROW_1_LEFT);
87         assertTrue(lock);
88 
89         mCarCabinManager.setBooleanProperty(CarCabinManager.ID_DOOR_LOCK,
90                 VehicleAreaDoor.ROW_1_LEFT, false);
91         lock = mCarCabinManager.getBooleanProperty(CarCabinManager.ID_DOOR_LOCK,
92                 VehicleAreaDoor.ROW_1_LEFT);
93         assertFalse(lock);
94     }
95 
96     // Test an integer property
97     @Test
testCabinWindowPos()98     public void testCabinWindowPos() throws Exception {
99         mCarCabinManager.setIntProperty(CarCabinManager.ID_WINDOW_POS,
100                 VehicleAreaWindow.ROW_1_LEFT, 50);
101         int windowPos = mCarCabinManager.getIntProperty(CarCabinManager.ID_WINDOW_POS,
102                 VehicleAreaWindow.ROW_1_LEFT);
103         assertEquals(50, windowPos);
104 
105         mCarCabinManager.setIntProperty(CarCabinManager.ID_WINDOW_POS,
106                 VehicleAreaWindow.ROW_1_LEFT, 25);
107         windowPos = mCarCabinManager.getIntProperty(CarCabinManager.ID_WINDOW_POS,
108                 VehicleAreaWindow.ROW_1_LEFT);
109         assertEquals(25, windowPos);
110     }
111 
112     @Test
testError()113     public void testError() throws Exception {
114         final int PROP = VehicleProperty.DOOR_LOCK;
115         final int AREA = VehicleAreaWindow.ROW_1_LEFT;
116         final int ERR_CODE = 42;
117 
118         CountDownLatch errorLatch = new CountDownLatch(1);
119         MutableInt propertyIdReceived = new MutableInt(0);
120         MutableInt areaIdReceived = new MutableInt(0);
121 
122         mCarCabinManager.registerCallback(new CarCabinEventCallback() {
123             @Override
124             public void onChangeEvent(CarPropertyValue value) {
125 
126             }
127 
128             @Override
129             public void onErrorEvent(@PropertyId int propertyId, int area) {
130                 propertyIdReceived.value = propertyId;
131                 areaIdReceived.value = area;
132                 errorLatch.countDown();
133             }
134         });
135         mCarCabinManager.setBooleanProperty(PROP, AREA, true);
136         getMockedVehicleHal().injectError(ERR_CODE, PROP, AREA);
137         assertTrue(errorLatch.await(DEFAULT_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS));
138         assertEquals(PROP, propertyIdReceived.value);
139         assertEquals(AREA, areaIdReceived.value);
140     }
141 
142 
143     // Test an event
144     @Test
145     @FlakyTest
testEvent()146     public void testEvent() throws Exception {
147         mCarCabinManager.registerCallback(new EventListener());
148         // Wait for two events generated on registration
149         assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
150         assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
151         // Inject a boolean event and wait for its callback in onPropertySet.
152         VehiclePropValue v = VehiclePropValueBuilder.newBuilder(VehicleProperty.DOOR_LOCK)
153                 .setAreaId(VehicleAreaDoor.ROW_1_LEFT)
154                 .setTimestamp(SystemClock.elapsedRealtimeNanos())
155                 .addIntValue(1)
156                 .build();
157 
158         assertEquals(0, mAvailable.availablePermits());
159         getMockedVehicleHal().injectEvent(v);
160 
161         assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
162         assertTrue(mEventBoolVal);
163         assertEquals(VehicleAreaDoor.ROW_1_LEFT, mEventZoneVal);
164 
165         // Inject an integer event and wait for its callback in onPropertySet.
166         v = VehiclePropValueBuilder.newBuilder(VehicleProperty.WINDOW_POS)
167                 .setAreaId(VehicleAreaWindow.ROW_1_LEFT)
168                 .setTimestamp(SystemClock.elapsedRealtimeNanos())
169                 .addIntValue(75)
170                 .build();
171         assertEquals(0, mAvailable.availablePermits());
172         getMockedVehicleHal().injectEvent(v);
173 
174         assertTrue(mAvailable.tryAcquire(2L, TimeUnit.SECONDS));
175         assertEquals(mEventIntVal, 75);
176         assertEquals(VehicleAreaWindow.ROW_1_LEFT, mEventZoneVal);
177     }
178 
179 
180     private class CabinPropertyHandler implements VehicleHalPropertyHandler {
181         HashMap<Integer, VehiclePropValue> mMap = new HashMap<>();
182 
183         @Override
onPropertySet(VehiclePropValue value)184         public synchronized void onPropertySet(VehiclePropValue value) {
185             mMap.put(value.prop, value);
186         }
187 
188         @Override
onPropertyGet(VehiclePropValue value)189         public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) {
190             VehiclePropValue currentValue = mMap.get(value.prop);
191             // VNS will call get method when subscribe is called, just return empty value.
192             return currentValue != null ? currentValue : value;
193         }
194 
195         @Override
onPropertySubscribe(int property, float sampleRate)196         public synchronized void onPropertySubscribe(int property, float sampleRate) {
197             Log.d(TAG, "onPropertySubscribe property " + property + " sampleRate " + sampleRate);
198             if (mMap.get(property) == null) {
199                 Log.d(TAG, "onPropertySubscribe add placeholder property: " + property);
200                 VehiclePropValue placeholderValue = VehiclePropValueBuilder.newBuilder(property)
201                         .setAreaId(VehicleAreaDoor.ROW_1_LEFT)
202                         .setTimestamp(SystemClock.elapsedRealtimeNanos())
203                         .addIntValue(1)
204                         .build();
205                 mMap.put(property, placeholderValue);
206             }
207         }
208 
209         @Override
onPropertyUnsubscribe(int property)210         public synchronized void onPropertyUnsubscribe(int property) {
211             Log.d(TAG, "onPropertyUnSubscribe property " + property);
212         }
213     }
214 
215     private class EventListener implements CarCabinEventCallback {
EventListener()216         EventListener() { }
217 
218         @Override
onChangeEvent(final CarPropertyValue value)219         public void onChangeEvent(final CarPropertyValue value) {
220             Log.d(TAG, "onChangeEvent: "  + value);
221             Object o = value.getValue();
222             mEventZoneVal = value.getAreaId();
223 
224             if (o instanceof Integer) {
225                 mEventIntVal = (Integer) o;
226             } else if (o instanceof Boolean) {
227                 mEventBoolVal = (Boolean) o;
228             } else {
229                 Log.e(TAG, "onChangeEvent:  Unknown instance type = " + o.getClass().getName());
230             }
231             mAvailable.release();
232         }
233 
234         @Override
onErrorEvent(final int propertyId, final int zone)235         public void onErrorEvent(final int propertyId, final int zone) {
236             Log.d(TAG, "Error:  propertyId=" + propertyId + "  zone=" + zone);
237         }
238     }
239 }
240