1 /*
2  * Copyright 2020 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 androidx.camera.camera2.internal;
18 
19 import static org.mockito.ArgumentMatchers.any;
20 import static org.mockito.Mockito.mock;
21 import static org.mockito.Mockito.times;
22 import static org.mockito.Mockito.verify;
23 
24 import android.hardware.camera2.CameraAccessException;
25 import android.hardware.camera2.CameraCaptureSession;
26 import android.hardware.camera2.CameraDevice;
27 import android.hardware.camera2.CaptureRequest;
28 import android.os.Build;
29 import android.os.Handler;
30 import android.view.Surface;
31 
32 import androidx.camera.camera2.internal.compat.params.OutputConfigurationCompat;
33 import androidx.camera.camera2.internal.compat.params.SessionConfigurationCompat;
34 import androidx.camera.core.impl.ImmediateSurface;
35 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
36 
37 import org.junit.Before;
38 import org.junit.Test;
39 import org.junit.runner.RunWith;
40 import org.robolectric.RobolectricTestRunner;
41 import org.robolectric.annotation.Config;
42 import org.robolectric.annotation.internal.DoNotInstrument;
43 
44 import java.util.ArrayList;
45 import java.util.Arrays;
46 import java.util.List;
47 import java.util.concurrent.Executors;
48 import java.util.concurrent.ScheduledExecutorService;
49 
50 @SuppressWarnings({"deprecation", "unchecked"})
51 @RunWith(RobolectricTestRunner.class)
52 @DoNotInstrument
53 @Config(minSdk = Build.VERSION_CODES.LOLLIPOP,
54         instrumentedPackages = { "androidx.camera.camera2.internal.compat.params" })
55 public class SynchronizedCaptureSessionBaseTest {
56 
57     private static final int NUM_OUTPUTS = 3;
58 
59     private CameraCaptureSession mMockCaptureSession;
60     private SynchronizedCaptureSession.StateCallback mMockStateCallback;
61     private List<OutputConfigurationCompat> mOutputs;
62     private SynchronizedCaptureSessionBaseImpl mSyncCaptureSessionBaseImpl;
63     private CaptureSessionRepository mMockCaptureSessionRepository;
64     private ScheduledExecutorService mScheduledExecutorService =
65             Executors.newSingleThreadScheduledExecutor();
66 
67     @Before
setUp()68     public void setUp() {
69         mMockCaptureSessionRepository = mock(CaptureSessionRepository.class);
70 
71         mSyncCaptureSessionBaseImpl =
72                 new SynchronizedCaptureSessionBaseImpl(mMockCaptureSessionRepository,
73                         CameraXExecutors.directExecutor(), mScheduledExecutorService,
74                         mock(Handler.class));
75 
76         mMockCaptureSession = mock(CameraCaptureSession.class);
77         mMockStateCallback = mock(SynchronizedCaptureSession.StateCallback.class);
78         mOutputs = new ArrayList<>(NUM_OUTPUTS);
79         for (int i = 0; i < NUM_OUTPUTS; ++i) {
80             mOutputs.add(mock(OutputConfigurationCompat.class));
81         }
82     }
83 
84     @Test
callbackShouldWork_onReady()85     public void callbackShouldWork_onReady() {
86         SessionConfigurationCompat sessionConfigurationCompat =
87                 mSyncCaptureSessionBaseImpl.createSessionConfigurationCompat(
88                         SessionConfigurationCompat.SESSION_REGULAR,
89                         mOutputs,
90                         mMockStateCallback);
91 
92         sessionConfigurationCompat.getStateCallback().onReady(mMockCaptureSession);
93 
94         verify(mMockStateCallback).onReady(any(SynchronizedCaptureSession.class));
95     }
96 
97     @Test
callbackShouldWork_onActive()98     public void callbackShouldWork_onActive() {
99         SessionConfigurationCompat sessionConfigurationCompat =
100                 mSyncCaptureSessionBaseImpl.createSessionConfigurationCompat(
101                         SessionConfigurationCompat.SESSION_REGULAR,
102                         mOutputs,
103                         mMockStateCallback);
104 
105         sessionConfigurationCompat.getStateCallback().onActive(mMockCaptureSession);
106 
107         verify(mMockStateCallback).onActive(any(SynchronizedCaptureSession.class));
108     }
109 
110     @Test
111     @Config(minSdk = Build.VERSION_CODES.O)
callbackShouldWork_onCaptureQueueEmpty()112     public void callbackShouldWork_onCaptureQueueEmpty() {
113         SessionConfigurationCompat sessionConfigurationCompat =
114                 mSyncCaptureSessionBaseImpl.createSessionConfigurationCompat(
115                         SessionConfigurationCompat.SESSION_REGULAR,
116                         mOutputs,
117                         mMockStateCallback);
118 
119         sessionConfigurationCompat.getStateCallback().onCaptureQueueEmpty(mMockCaptureSession);
120 
121         verify(mMockStateCallback).onCaptureQueueEmpty(any(SynchronizedCaptureSession.class));
122     }
123 
124     @Test
125     @Config(minSdk = Build.VERSION_CODES.M)
callbackShouldWork_onSurfacePrepared()126     public void callbackShouldWork_onSurfacePrepared() {
127         SessionConfigurationCompat sessionConfigurationCompat =
128                 mSyncCaptureSessionBaseImpl.createSessionConfigurationCompat(
129                         SessionConfigurationCompat.SESSION_REGULAR,
130                         mOutputs,
131                         mMockStateCallback);
132 
133         sessionConfigurationCompat.getStateCallback().onSurfacePrepared(mMockCaptureSession,
134                 mock(Surface.class));
135 
136         verify(mMockStateCallback).onSurfacePrepared(any(SynchronizedCaptureSession.class),
137                 any(Surface.class));
138     }
139 
140     @Test
callbackShouldWork_onConfigured()141     public void callbackShouldWork_onConfigured() {
142         SessionConfigurationCompat sessionConfigurationCompat =
143                 mSyncCaptureSessionBaseImpl.createSessionConfigurationCompat(
144                         SessionConfigurationCompat.SESSION_REGULAR,
145                         mOutputs,
146                         mMockStateCallback);
147 
148         mSyncCaptureSessionBaseImpl.openCaptureSession(mock(CameraDevice.class),
149                 sessionConfigurationCompat,
150                 Arrays.asList(new ImmediateSurface(mock(Surface.class))));
151         sessionConfigurationCompat.getStateCallback().onConfigured(mMockCaptureSession);
152 
153         verify(mMockStateCallback).onConfigured(any(SynchronizedCaptureSession.class));
154         verify(mMockCaptureSessionRepository, times(1)).onCaptureSessionCreated(
155                 any(SynchronizedCaptureSession.class));
156     }
157 
158     @Test
callbackShouldWork_onConfigureFailed()159     public void callbackShouldWork_onConfigureFailed() {
160         SessionConfigurationCompat sessionConfigurationCompat =
161                 mSyncCaptureSessionBaseImpl.createSessionConfigurationCompat(
162                         SessionConfigurationCompat.SESSION_REGULAR,
163                         mOutputs,
164                         mMockStateCallback);
165 
166         mSyncCaptureSessionBaseImpl.openCaptureSession(mock(CameraDevice.class),
167                 sessionConfigurationCompat,
168                 Arrays.asList(new ImmediateSurface(mock(Surface.class))));
169         sessionConfigurationCompat.getStateCallback().onConfigureFailed(mMockCaptureSession);
170 
171         verify(mMockStateCallback).onConfigureFailed(any(SynchronizedCaptureSession.class));
172     }
173 
174     @Test
callbackShouldWork_onClosed()175     public void callbackShouldWork_onClosed() {
176         SessionConfigurationCompat sessionConfigurationCompat =
177                 mSyncCaptureSessionBaseImpl.createSessionConfigurationCompat(
178                         SessionConfigurationCompat.SESSION_REGULAR,
179                         mOutputs,
180                         mMockStateCallback);
181 
182         mSyncCaptureSessionBaseImpl.openCaptureSession(mock(CameraDevice.class),
183                 sessionConfigurationCompat,
184                 Arrays.asList(new ImmediateSurface(mock(Surface.class))));
185         sessionConfigurationCompat.getStateCallback().onConfigured(mMockCaptureSession);
186         sessionConfigurationCompat.getStateCallback().onClosed(mMockCaptureSession);
187 
188         verify(mMockStateCallback).onClosed(any(SynchronizedCaptureSession.class));
189         verify(mMockCaptureSessionRepository, times(1)).onCaptureSessionClosed(
190                 any(SynchronizedCaptureSession.class));
191     }
192 
193     @Test
callClose_onSessionFinished_shouldBeCalled()194     public void callClose_onSessionFinished_shouldBeCalled() {
195         SessionConfigurationCompat sessionConfigurationCompat =
196                 mSyncCaptureSessionBaseImpl.createSessionConfigurationCompat(
197                         SessionConfigurationCompat.SESSION_REGULAR,
198                         mOutputs,
199                         mMockStateCallback);
200 
201         mSyncCaptureSessionBaseImpl.openCaptureSession(mock(CameraDevice.class),
202                 sessionConfigurationCompat,
203                 Arrays.asList(new ImmediateSurface(mock(Surface.class))));
204         sessionConfigurationCompat.getStateCallback().onConfigured(mMockCaptureSession);
205         mSyncCaptureSessionBaseImpl.close();
206 
207         verify(mMockStateCallback).onSessionFinished(
208                 any(SynchronizedCaptureSession.class));
209     }
210 
211     @Test
callbackShouldWork_onSessionFinished()212     public void callbackShouldWork_onSessionFinished() {
213         SessionConfigurationCompat sessionConfigurationCompat =
214                 mSyncCaptureSessionBaseImpl.createSessionConfigurationCompat(
215                         SessionConfigurationCompat.SESSION_REGULAR,
216                         mOutputs,
217                         mMockStateCallback);
218 
219         mSyncCaptureSessionBaseImpl.openCaptureSession(mock(CameraDevice.class),
220                 sessionConfigurationCompat,
221                 Arrays.asList(new ImmediateSurface(mock(Surface.class))));
222         sessionConfigurationCompat.getStateCallback().onConfigured(mMockCaptureSession);
223         sessionConfigurationCompat.getStateCallback().onClosed(mMockCaptureSession);
224 
225         verify(mMockStateCallback).onSessionFinished(
226                 any(SynchronizedCaptureSession.class));
227     }
228 
229     @Test
shouldForwardAfterOnConfigured()230     public void shouldForwardAfterOnConfigured() throws CameraAccessException {
231         SessionConfigurationCompat sessionConfigurationCompat =
232                 mSyncCaptureSessionBaseImpl.createSessionConfigurationCompat(
233                         SessionConfigurationCompat.SESSION_REGULAR,
234                         mOutputs,
235                         mMockStateCallback);
236 
237         mSyncCaptureSessionBaseImpl.openCaptureSession(mock(CameraDevice.class),
238                 sessionConfigurationCompat,
239                 Arrays.asList(new ImmediateSurface(mock(Surface.class))));
240         sessionConfigurationCompat.getStateCallback().onConfigured(mMockCaptureSession);
241 
242         mSyncCaptureSessionBaseImpl.captureSingleRequest(mock(CaptureRequest.class),
243                 mock(CameraCaptureSession.CaptureCallback.class));
244     }
245 
246     @Test
forwardBeforeOnConfigured_captureBurstRequests()247     public void forwardBeforeOnConfigured_captureBurstRequests() throws CameraAccessException {
248         SessionConfigurationCompat sessionConfigurationCompat =
249                 mSyncCaptureSessionBaseImpl.createSessionConfigurationCompat(
250                         SessionConfigurationCompat.SESSION_REGULAR,
251                         mOutputs,
252                         mMockStateCallback);
253 
254         mSyncCaptureSessionBaseImpl.openCaptureSession(mock(CameraDevice.class),
255                 sessionConfigurationCompat,
256                 Arrays.asList(new ImmediateSurface(mock(Surface.class))));
257         sessionConfigurationCompat.getStateCallback().onConfigured(mMockCaptureSession);
258 
259         mSyncCaptureSessionBaseImpl.captureBurstRequests(mock(List.class),
260                 mock(CameraCaptureSession.CaptureCallback.class));
261     }
262 
263     @Test
forwardBeforeOnConfigured_setRepeatingBurstRequests()264     public void forwardBeforeOnConfigured_setRepeatingBurstRequests()
265             throws CameraAccessException {
266         SessionConfigurationCompat sessionConfigurationCompat =
267                 mSyncCaptureSessionBaseImpl.createSessionConfigurationCompat(
268                         SessionConfigurationCompat.SESSION_REGULAR,
269                         mOutputs,
270                         mMockStateCallback);
271 
272         mSyncCaptureSessionBaseImpl.openCaptureSession(mock(CameraDevice.class),
273                 sessionConfigurationCompat,
274                 Arrays.asList(new ImmediateSurface(mock(Surface.class))));
275         sessionConfigurationCompat.getStateCallback().onConfigured(mMockCaptureSession);
276 
277         mSyncCaptureSessionBaseImpl.setRepeatingBurstRequests(mock(List.class),
278                 mock(CameraCaptureSession.CaptureCallback.class));
279     }
280 
281     @Test
forwardBeforeOnConfigured_setSingleRepeatingRequest()282     public void forwardBeforeOnConfigured_setSingleRepeatingRequest()
283             throws CameraAccessException {
284         SessionConfigurationCompat sessionConfigurationCompat =
285                 mSyncCaptureSessionBaseImpl.createSessionConfigurationCompat(
286                         SessionConfigurationCompat.SESSION_REGULAR,
287                         mOutputs,
288                         mMockStateCallback);
289 
290         mSyncCaptureSessionBaseImpl.openCaptureSession(mock(CameraDevice.class),
291                 sessionConfigurationCompat,
292                 Arrays.asList(new ImmediateSurface(mock(Surface.class))));
293         sessionConfigurationCompat.getStateCallback().onConfigured(mMockCaptureSession);
294 
295         mSyncCaptureSessionBaseImpl.setSingleRepeatingRequest(mock(CaptureRequest.class),
296                 mock(CameraCaptureSession.CaptureCallback.class));
297     }
298 
299     @Test
forwardBeforeOnConfigured_abortCaptures()300     public void forwardBeforeOnConfigured_abortCaptures()
301             throws CameraAccessException {
302         SessionConfigurationCompat sessionConfigurationCompat =
303                 mSyncCaptureSessionBaseImpl.createSessionConfigurationCompat(
304                         SessionConfigurationCompat.SESSION_REGULAR,
305                         mOutputs,
306                         mMockStateCallback);
307 
308         mSyncCaptureSessionBaseImpl.openCaptureSession(mock(CameraDevice.class),
309                 sessionConfigurationCompat,
310                 Arrays.asList(new ImmediateSurface(mock(Surface.class))));
311         sessionConfigurationCompat.getStateCallback().onConfigured(mMockCaptureSession);
312 
313         mSyncCaptureSessionBaseImpl.abortCaptures();
314     }
315 
316     @Test
forwardBeforeOnConfigured_stopRepeating()317     public void forwardBeforeOnConfigured_stopRepeating()
318             throws CameraAccessException {
319         SessionConfigurationCompat sessionConfigurationCompat =
320                 mSyncCaptureSessionBaseImpl.createSessionConfigurationCompat(
321                         SessionConfigurationCompat.SESSION_REGULAR,
322                         mOutputs,
323                         mMockStateCallback);
324 
325         mSyncCaptureSessionBaseImpl.openCaptureSession(mock(CameraDevice.class),
326                 sessionConfigurationCompat,
327                 Arrays.asList(new ImmediateSurface(mock(Surface.class))));
328         sessionConfigurationCompat.getStateCallback().onConfigured(mMockCaptureSession);
329 
330         mSyncCaptureSessionBaseImpl.stopRepeating();
331     }
332 
333     @Test
forwardBeforeOnConfigured_getDevice()334     public void forwardBeforeOnConfigured_getDevice() {
335         SessionConfigurationCompat sessionConfigurationCompat =
336                 mSyncCaptureSessionBaseImpl.createSessionConfigurationCompat(
337                         SessionConfigurationCompat.SESSION_REGULAR,
338                         mOutputs,
339                         mMockStateCallback);
340 
341         mSyncCaptureSessionBaseImpl.openCaptureSession(mock(CameraDevice.class),
342                 sessionConfigurationCompat,
343                 Arrays.asList(new ImmediateSurface(mock(Surface.class))));
344         sessionConfigurationCompat.getStateCallback().onConfigured(mMockCaptureSession);
345 
346         mSyncCaptureSessionBaseImpl.getDevice();
347     }
348 
349     @Test(expected = NullPointerException.class)
notForwardBeforeOnConfigured_captureSingleRequest()350     public void notForwardBeforeOnConfigured_captureSingleRequest() throws CameraAccessException {
351         mSyncCaptureSessionBaseImpl.captureSingleRequest(mock(CaptureRequest.class),
352                 mock(CameraCaptureSession.CaptureCallback.class));
353     }
354 
355     @Test(expected = NullPointerException.class)
notForwardBeforeOnConfigured_captureBurstRequests()356     public void notForwardBeforeOnConfigured_captureBurstRequests() throws CameraAccessException {
357         mSyncCaptureSessionBaseImpl.captureBurstRequests(mock(List.class),
358                 mock(CameraCaptureSession.CaptureCallback.class));
359     }
360 
361     @Test(expected = NullPointerException.class)
notForwardBeforeOnConfigured_setRepeatingBurstRequests()362     public void notForwardBeforeOnConfigured_setRepeatingBurstRequests()
363             throws CameraAccessException {
364         mSyncCaptureSessionBaseImpl.setRepeatingBurstRequests(mock(List.class),
365                 mock(CameraCaptureSession.CaptureCallback.class));
366     }
367 
368     @Test(expected = NullPointerException.class)
notForwardBeforeOnConfigured_setSingleRepeatingRequest()369     public void notForwardBeforeOnConfigured_setSingleRepeatingRequest()
370             throws CameraAccessException {
371         mSyncCaptureSessionBaseImpl.setSingleRepeatingRequest(mock(CaptureRequest.class),
372                 mock(CameraCaptureSession.CaptureCallback.class));
373     }
374 
375     @Test(expected = NullPointerException.class)
notForwardBeforeOnConfigured_abortCaptures()376     public void notForwardBeforeOnConfigured_abortCaptures()
377             throws CameraAccessException {
378         mSyncCaptureSessionBaseImpl.abortCaptures();
379     }
380 
381     @Test(expected = NullPointerException.class)
notForwardBeforeOnConfigured_stopRepeating()382     public void notForwardBeforeOnConfigured_stopRepeating()
383             throws CameraAccessException {
384         mSyncCaptureSessionBaseImpl.stopRepeating();
385     }
386 
387     @Test(expected = NullPointerException.class)
notForwardBeforeOnConfigured_getDevice()388     public void notForwardBeforeOnConfigured_getDevice() {
389         mSyncCaptureSessionBaseImpl.getDevice();
390     }
391 
392 }
393