• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.junit.Assume.assumeTrue;
22 
23 import android.car.Car;
24 import android.car.evs.CarEvsBufferDescriptor;
25 import android.car.evs.CarEvsManager;
26 import android.car.evs.CarEvsManager.CarEvsServiceState;
27 import android.car.evs.CarEvsManager.CarEvsServiceType;
28 import android.car.evs.CarEvsManager.CarEvsStreamEvent;
29 import android.car.evs.CarEvsStatus;
30 import android.content.Context;
31 import android.os.SystemClock;
32 import android.test.suitebuilder.annotation.MediumTest;
33 
34 import androidx.test.core.app.ApplicationProvider;
35 import androidx.test.runner.AndroidJUnit4;
36 
37 import org.junit.After;
38 import org.junit.Before;
39 import org.junit.Test;
40 import org.junit.runner.RunWith;
41 
42 import java.util.ArrayList;
43 import java.util.concurrent.CountDownLatch;
44 import java.util.concurrent.ExecutorService;
45 import java.util.concurrent.Executors;
46 import java.util.concurrent.Semaphore;
47 import java.util.concurrent.TimeUnit;
48 
49 /*
50  * IMPORTANT NOTE:
51  * This test assumes that EVS HAL is running at the time of test.  Depending on the test target, the
52  * reference EVS HAL ($ANDROID_BUILD_TOP/packages/services/Car/evs/sampleDriver) may be needed.
53  * Please add below line to the target's build script to add the reference EVS HAL to the build:
54  * ENABLE_EVS_SAMPLE := true
55  *
56  * The test will likely fail if no EVS HAL is running on the target device.
57  */
58 @RunWith(AndroidJUnit4.class)
59 @MediumTest
60 public final class CarEvsManagerTest extends MockedCarTestBase {
61     private static final String TAG = CarEvsManagerTest.class.getSimpleName();
62 
63     // We'd expect that underlying stream runs @10fps at least.
64     private static final int NUMBER_OF_FRAMES_TO_WAIT = 10;
65     private static final int FRAME_TIMEOUT_MS = 1000;
66     private static final int SMALL_NAP_MS = 500;
67     private static final int ACTIVITY_REQUEST_TIMEOUT_SEC = 3;
68     private static final int STREAM_REQUEST_TIMEOUT_SEC = 1;
69 
70     // Will return frame buffers in the order they arrived.
71     private static final int INDEX_TO_FIRST_ELEM = 0;
72 
73     private final ArrayList<CarEvsBufferDescriptor> mReceivedBuffers = new ArrayList<>();
74     private final ExecutorService mCallbackExecutor = Executors.newFixedThreadPool(1);
75     private final Semaphore mFrameReceivedSignal = new Semaphore(0);
76     private final Semaphore mServiceInRequestedState = new Semaphore(0);
77     private final Semaphore mServiceInActiveState = new Semaphore(0);
78 
79     private final Car mCar = Car.createCar(ApplicationProvider.getApplicationContext());
80     private final CarEvsManager mEvsManager =
81             (CarEvsManager) mCar.getCarManager(Car.CAR_EVS_SERVICE);
82     private final EvsStreamCallbackImpl mStreamCallback = new EvsStreamCallbackImpl();
83     private final EvsStatusListenerImpl mStatusListener = new EvsStatusListenerImpl();
84 
85     @Before
setUp()86     public void setUp() {
87         assumeTrue(mCar.isFeatureEnabled(Car.CAR_EVS_SERVICE));
88         assertThat(mEvsManager).isNotNull();
89         assumeTrue(mEvsManager.isSupported(CarEvsManager.SERVICE_TYPE_REARVIEW));
90         assertThat(mStreamCallback).isNotNull();
91         assertThat(mStatusListener).isNotNull();
92 
93         // Drains all permits
94         mFrameReceivedSignal.drainPermits();
95         mServiceInRequestedState.drainPermits();
96         mServiceInActiveState.drainPermits();
97 
98         // Ensures no stream is active
99         mEvsManager.stopVideoStream();
100     }
101 
102     @After
tearDown()103     public void tearDown() throws Exception {
104         if (mEvsManager != null) {
105             mEvsManager.stopVideoStream();
106         }
107     }
108 
109     @Test
testSessionTokenGeneration()110     public void testSessionTokenGeneration() throws Exception {
111         assertThat(mEvsManager.generateSessionToken()).isNotNull();
112     }
113 
114     @Test
testSetStatusListener()115     public void testSetStatusListener() throws Exception {
116         // Registers a status listener and start monitoring the CarEvsService's state changes.
117         mEvsManager.setStatusListener(mCallbackExecutor, mStatusListener);
118 
119         // Requests to start the rearview activity.
120         assertThat(
121                 mEvsManager.startActivity(CarEvsManager.SERVICE_TYPE_REARVIEW)
122         ).isEqualTo(CarEvsManager.ERROR_NONE);
123 
124         // Waits until the CarEvsService enters the REQUESTED state.
125         assertThat(
126                 mServiceInRequestedState.tryAcquire(ACTIVITY_REQUEST_TIMEOUT_SEC, TimeUnit.SECONDS)
127         ).isTrue();
128 
129         // Waits until the CarEvsService starts a video stream; it enters the ACTIVE state.
130         assertThat(
131                 mServiceInActiveState.tryAcquire(STREAM_REQUEST_TIMEOUT_SEC, TimeUnit.SECONDS)
132         ).isTrue();
133 
134         // Requests to stop the rearview activity.
135         mEvsManager.stopActivity();
136 
137         // Unregisters a status listener.
138         mEvsManager.clearStatusListener();
139     }
140 
141     @Test
testStartAndStopVideoStream()142     public void testStartAndStopVideoStream() throws Exception {
143         // Registers a status listener and start monitoring the CarEvsService's state changes.
144         mEvsManager.setStatusListener(mCallbackExecutor, mStatusListener);
145 
146         // Requests to start a video stream.
147         assertThat(
148                 mEvsManager.startVideoStream(CarEvsManager.SERVICE_TYPE_REARVIEW,
149                         /* token = */ null, mCallbackExecutor, mStreamCallback)
150         ).isEqualTo(CarEvsManager.ERROR_NONE);
151 
152         // Waits until the service starts the video stream.
153         assertThat(
154                 mServiceInActiveState.tryAcquire(STREAM_REQUEST_TIMEOUT_SEC, TimeUnit.SECONDS)
155         ).isTrue();
156 
157         // Then, waits for a few frames frame buffers
158         for (int i = 0; i < NUMBER_OF_FRAMES_TO_WAIT; ++i) {
159             assertThat(
160                     mFrameReceivedSignal.tryAcquire(FRAME_TIMEOUT_MS, TimeUnit.MILLISECONDS)
161             ).isTrue();
162 
163             // Nothing to do; returns a buffer immediately
164             CarEvsBufferDescriptor toBeReturned = mReceivedBuffers.get(INDEX_TO_FIRST_ELEM);
165             mReceivedBuffers.remove(INDEX_TO_FIRST_ELEM);
166             mEvsManager.returnFrameBuffer(toBeReturned);
167         }
168 
169         // Checks a current status
170         CarEvsStatus status = mEvsManager.getCurrentStatus();
171         assertThat(status).isNotNull();
172         assertThat(status.getState()).isEqualTo(CarEvsManager.SERVICE_STATE_ACTIVE);
173         assertThat(status.getServiceType()).isEqualTo(CarEvsManager.SERVICE_TYPE_REARVIEW);
174 
175         // Then, requests to stop a video stream
176         mEvsManager.stopVideoStream();
177 
178         // Checks a current status a few hundreds milliseconds after.  CarEvsService will move into
179         // the inactive state when it gets a stream-stopped event from the EVS manager.
180         SystemClock.sleep(SMALL_NAP_MS);
181         status = mEvsManager.getCurrentStatus();
182         assertThat(status).isNotNull();
183         assertThat(status.getState()).isEqualTo(CarEvsManager.SERVICE_STATE_INACTIVE);
184 
185         // Unregister a listener
186         mEvsManager.clearStatusListener();
187     }
188 
189     @Test
testIsSupported()190     public void testIsSupported() throws Exception {
191         assertThat(mEvsManager.isSupported(CarEvsManager.SERVICE_TYPE_REARVIEW)).isTrue();
192         // TODO(b/179029031): Fix below test when the Surround View service is integrated into
193         // CarEvsService.
194         assertThat(mEvsManager.isSupported(CarEvsManager.SERVICE_TYPE_SURROUNDVIEW)).isFalse();
195     }
196 
197     /**
198      * Class that implements the listener interface and gets called back from
199      * {@link android.car.evs.CarEvsManager.CarEvsStatusListener}.
200      */
201     private final class EvsStatusListenerImpl implements CarEvsManager.CarEvsStatusListener {
202         @Override
onStatusChanged(CarEvsStatus status)203         public void onStatusChanged(CarEvsStatus status) {
204             switch (status.getState()) {
205                 case CarEvsManager.SERVICE_STATE_REQUESTED:
206                     mServiceInRequestedState.release();
207                     break;
208 
209                 case CarEvsManager.SERVICE_STATE_ACTIVE:
210                     mServiceInActiveState.release();
211                     break;
212 
213                 case CarEvsManager.SERVICE_STATE_UNAVAILABLE:
214                     // Nothing to do
215                     break;
216 
217                 default:
218                     // Nothing to do
219                     break;
220             }
221         }
222     }
223 
224     /**
225      * Class that implements the listener interface and gets called back from
226      * {@link android.hardware.automotive.evs.IEvsCameraStream}.
227      */
228     private final class EvsStreamCallbackImpl implements CarEvsManager.CarEvsStreamCallback {
229         @Override
onStreamEvent(@arEvsStreamEvent int event)230         public void onStreamEvent(@CarEvsStreamEvent int event) {
231             switch(event) {
232                 case CarEvsManager.STREAM_EVENT_STREAM_STARTED:
233                     // Ignores this event for now because our reference EVS HAL does not send this
234                     // event.
235                     break;
236 
237                 case CarEvsManager.STREAM_EVENT_STREAM_STOPPED:
238                     break;
239 
240                 default:
241                     // Ignores other stream events in this test.
242                     break;
243             }
244         }
245 
246         @Override
onNewFrame(CarEvsBufferDescriptor buffer)247         public void onNewFrame(CarEvsBufferDescriptor buffer) {
248             // Enqueues a new frame
249             mReceivedBuffers.add(buffer);
250 
251             // Notifies a new frame's arrival
252             mFrameReceivedSignal.release();
253         }
254     }
255 }
256