1 /*
2  * Copyright (C) 2021 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.hal;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.ArgumentMatchers.anyBoolean;
22 import static org.mockito.ArgumentMatchers.anyInt;
23 import static org.mockito.Mockito.doAnswer;
24 import static org.mockito.Mockito.never;
25 import static org.mockito.Mockito.reset;
26 import static org.mockito.Mockito.verify;
27 import static org.mockito.Mockito.when;
28 
29 import android.car.evs.CarEvsManager;
30 import android.hardware.automotive.vehicle.EvsServiceState;
31 import android.hardware.automotive.vehicle.EvsServiceType;
32 import android.hardware.automotive.vehicle.VehicleProperty;
33 
34 import com.android.car.hal.test.AidlVehiclePropConfigBuilder;
35 
36 import com.google.common.collect.ImmutableList;
37 import com.google.common.collect.ImmutableSet;
38 
39 import org.junit.After;
40 import org.junit.Before;
41 import org.junit.Test;
42 import org.junit.runner.RunWith;
43 import org.mockito.ArgumentCaptor;
44 import org.mockito.Captor;
45 import org.mockito.Mock;
46 import org.mockito.junit.MockitoJUnitRunner;
47 
48 import java.util.ArrayList;
49 import java.util.Collection;
50 import java.util.List;
51 import java.util.Set;
52 import java.util.stream.IntStream;
53 
54 @RunWith(MockitoJUnitRunner.class)
55 public class EvsHalServiceTest {
56     @Mock VehicleHal mVehicleHal;
57     @Mock EvsHalService.EvsHalEventListener mListener;
58     @Captor ArgumentCaptor<HalPropValue> mPropCaptor;
59 
60     private static final HalPropConfig EVS_SERVICE_REQUEST =
61             new AidlHalPropConfig(
62                     AidlVehiclePropConfigBuilder.newBuilder(VehicleProperty.EVS_SERVICE_REQUEST)
63                             .build());
64 
65     private EvsHalService mEvsHalService;
66 
67     private static final int TRUE = 1;
68     private static final int FALSE = 0;
69     private static final HalPropValueBuilder PROP_VALUE_BUILDER = new HalPropValueBuilder(
70             /*isAidl=*/true);
71 
getIntValues(HalPropValue value)72     private List<Integer> getIntValues(HalPropValue value) {
73         List<Integer> intValues = new ArrayList<Integer>();
74         for (int i = 0; i < value.getInt32ValuesSize(); i++) {
75             intValues.add(value.getInt32Value(i));
76         }
77         return intValues;
78     }
79 
80     @Before
setUp()81     public void setUp() {
82         when(mVehicleHal.getHalPropValueBuilder()).thenReturn(PROP_VALUE_BUILDER);
83         mEvsHalService = new EvsHalService(mVehicleHal);
84         mEvsHalService.init();
85     }
86 
87     @After
tearDown()88     public void tearDown() {
89         mEvsHalService.release();
90         mEvsHalService = null;
91     }
92 
93     @Test
takesEvsServiceRequestProperty()94     public void takesEvsServiceRequestProperty() {
95         Set<HalPropConfig> offeredProps = ImmutableSet.of(
96                 EVS_SERVICE_REQUEST);
97 
98         mEvsHalService.takeProperties(offeredProps);
99 
100         assertThat(mEvsHalService.isEvsServiceRequestSupported()).isTrue();
101     }
102 
103     @Test
requestToStartRearviewViaEvsServiceRequest()104     public void requestToStartRearviewViaEvsServiceRequest() {
105         subscribeListener(ImmutableSet.of(EVS_SERVICE_REQUEST));
106 
107         List<Integer> events = new ArrayList<>();
108         doAnswer(invocation -> {
109                 events.add(invocation.getArgument(0));
110                 events.add(invocation.getArgument(1) ? TRUE : FALSE);
111                 return null;
112         }).when(mListener).onEvent(anyInt(), anyBoolean());
113 
114         dispatchEvsServiceRequest(EvsServiceType.REARVIEW, EvsServiceState.ON);
115 
116         assertThat(events.get(0)).isEqualTo(CarEvsManager.SERVICE_TYPE_REARVIEW);
117         assertThat(events.get(1)).isEqualTo(TRUE);
118     }
119 
120     @Test
requestToStopRearviewViaEvsServiceRequest()121     public void requestToStopRearviewViaEvsServiceRequest() {
122         subscribeListener(ImmutableSet.of(EVS_SERVICE_REQUEST));
123 
124         List<Integer> events = new ArrayList<>();
125         doAnswer(invocation -> {
126                 events.add(invocation.getArgument(0));
127                 events.add(invocation.getArgument(1) ? TRUE : FALSE);
128                 return null;
129         }).when(mListener).onEvent(anyInt(), anyBoolean());
130 
131         dispatchEvsServiceRequest(EvsServiceType.REARVIEW, EvsServiceState.OFF);
132 
133         assertThat(events.get(0)).isEqualTo(CarEvsManager.SERVICE_TYPE_REARVIEW);
134         assertThat(events.get(1)).isEqualTo(FALSE);
135     }
136 
137     @Test
handleInvalidHalEvents()138     public void handleInvalidHalEvents() {
139         subscribeListener(ImmutableSet.of(EVS_SERVICE_REQUEST));
140         HalPropValue v = PROP_VALUE_BUILDER.build(VehicleProperty.EVS_SERVICE_REQUEST,
141                 /*areaId=*/0);
142 
143         // Not type, no state.
144         mEvsHalService.onHalEvents(ImmutableList.of(v));
145         verify(mListener, never()).onEvent(anyInt(), anyBoolean());
146 
147         // Not state.
148         v = PROP_VALUE_BUILDER.build(VehicleProperty.EVS_SERVICE_REQUEST, /*areaId=*/0,
149                 EvsServiceType.REARVIEW);
150         mEvsHalService.onHalEvents(ImmutableList.of(v));
151         verify(mListener, never()).onEvent(anyInt(), anyBoolean());
152     }
153 
154     @Test
getAllSupportedProperties()155     public void getAllSupportedProperties() {
156         subscribeListener(ImmutableSet.of(EVS_SERVICE_REQUEST));
157 
158         int[] supported = mEvsHalService.getAllSupportedProperties();
159         assertThat(supported.length > 0).isTrue();
160         assertThat(IntStream.of(supported).anyMatch(x -> x == VehicleProperty.EVS_SERVICE_REQUEST))
161                 .isTrue();
162     }
163 
164     @Test
testUpdateCameraServiceCurrentState()165     public void testUpdateCameraServiceCurrentState() {
166         int[] states = {CarEvsManager.SERVICE_STATE_ACTIVE, CarEvsManager.SERVICE_STATE_INACTIVE,
167                 CarEvsManager.SERVICE_STATE_INACTIVE, CarEvsManager.SERVICE_STATE_INACTIVE,
168                 CarEvsManager.SERVICE_STATE_INACTIVE, CarEvsManager.SERVICE_STATE_INACTIVE,
169                 CarEvsManager.SERVICE_STATE_INACTIVE, CarEvsManager.SERVICE_STATE_INACTIVE};
170 
171         mEvsHalService.reportCurrentState(states);
172 
173         verify(mVehicleHal).set(mPropCaptor.capture());
174         HalPropValue prop = mPropCaptor.getValue();
175         assertThat(prop.getPropId()).isEqualTo(VehicleProperty.CAMERA_SERVICE_CURRENT_STATE);
176         assertThat(getIntValues(prop)).containsExactly(
177                 CarEvsManager.SERVICE_STATE_ACTIVE, CarEvsManager.SERVICE_STATE_INACTIVE,
178                 CarEvsManager.SERVICE_STATE_INACTIVE, CarEvsManager.SERVICE_STATE_INACTIVE,
179                 CarEvsManager.SERVICE_STATE_INACTIVE, CarEvsManager.SERVICE_STATE_INACTIVE,
180                 CarEvsManager.SERVICE_STATE_INACTIVE, CarEvsManager.SERVICE_STATE_INACTIVE);
181     }
182 
dispatchEvsServiceRequest(int type, int state)183     private void dispatchEvsServiceRequest(int type, int state) {
184         mEvsHalService.onHalEvents(ImmutableList.of(buildEvsServiceRequestProp(type, state)));
185     }
186 
buildEvsServiceRequestProp(int type, int state)187     private HalPropValue buildEvsServiceRequestProp(int type, int state) {
188         return PROP_VALUE_BUILDER.build(VehicleProperty.EVS_SERVICE_REQUEST, /*areaId=*/0,
189                 new int[]{type, state});
190     }
191 
subscribeListener(Collection<HalPropConfig> properties)192     private void subscribeListener(Collection<HalPropConfig> properties) {
193         reset(mListener);
194         mEvsHalService.takeProperties(properties);
195         mEvsHalService.setListener(mListener);
196 
197         for (HalPropConfig config : properties) {
198             verify(mVehicleHal).subscribePropertySafe(mEvsHalService, config.getPropId());
199         }
200     }
201 }
202