1 /*
2  * Copyright (C) 2013 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.mediaframeworktest.functional.camera;
18 
19 import android.hardware.Camera;
20 import android.os.Handler;
21 import android.os.Looper;
22 import android.test.ActivityInstrumentationTestCase2;
23 import android.util.Log;
24 import android.view.SurfaceHolder;
25 
26 import androidx.test.filters.LargeTest;
27 
28 import com.android.mediaframeworktest.MediaFrameworkTest;
29 import com.android.mediaframeworktest.helpers.CameraTestHelper;
30 
31 import java.util.List;
32 import java.util.concurrent.Semaphore;
33 import java.util.concurrent.TimeUnit;
34 
35 /**
36  * Junit / Instrumentation test case for camera API pairwise testing
37  * Settings tested against: flash mode, exposure compensation, white balance,
38  *  scene mode, picture size, and geotagging
39  *
40  * adb shell am instrument
41  *  - e class com.android.mediaframeworktest.stress.CameraPairwiseTest
42  *  - w com.android.mediaframeworktest/.CameraStressTestRunner
43  */
44 public class CameraPairwiseTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
45     private CameraTestHelper mCameraTestHelper;
46     private Handler mHandler;
47     private Thread mLooperThread;
48     private String TAG = "CameraPairwiseTest";
49 
50     private static final long WAIT_TIMEOUT = 10 * 1000; // 10 seconds
51 
52     // coordinates of the Getty Museuem in Los Angeles
53     private static final double MOCK_LATITUDE = 34.076621;
54     private static final double MOCK_LONGITUDE = -118.473215;
55 
56     // camera setting enums
57     public enum Flash { ON, OFF, AUTO };
58     public enum Exposure { MIN, MAX, NONE };
59     public enum WhiteBalance { DAYLIGHT, FLUORESCENT, CLOUDY, INCANDESCENT, AUTO };
60     public enum SceneMode { SUNSET, ACTION, PARTY, NIGHT, AUTO };
61     public enum PictureSize { SMALL, MEDIUM, LARGE };
62     public enum Geotagging { ON, OFF };
63 
CameraPairwiseTest()64     public CameraPairwiseTest() {
65         super("com.android.mediaframeworktest", MediaFrameworkTest.class);
66     }
67 
setUp()68     protected void setUp() throws Exception {
69         final Semaphore sem = new Semaphore(0);
70         mLooperThread = new Thread() {
71             @Override
72             public void run() {
73                 Log.v(TAG, "starting looper");
74                 Looper.prepare();
75                 mHandler = new Handler();
76                 sem.release();
77                 Looper.loop();
78                 Log.v(TAG, "quit looper");
79             }
80         };
81         mLooperThread.start();
82         if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
83             fail("Failed to start the looper.");
84         }
85         getActivity();
86         super.setUp();
87 
88         mCameraTestHelper = new CameraTestHelper();
89     }
90 
91     @Override
tearDown()92     protected void tearDown() throws Exception {
93         if (mHandler != null) {
94             mHandler.getLooper().quit();
95             mHandler = null;
96         }
97         if (mLooperThread != null) {
98             mLooperThread.join(WAIT_TIMEOUT);
99             if (mLooperThread.isAlive()) {
100                 fail("Failed to stop the looper.");
101             }
102             mLooperThread = null;
103         }
104         super.tearDown();
105     }
106 
runOnLooper(final Runnable command)107     private void runOnLooper(final Runnable command) throws InterruptedException {
108         final Semaphore sem = new Semaphore(0);
109         mHandler.post(new Runnable() {
110             @Override
111             public void run() {
112                 try {
113                     command.run();
114                 } finally {
115                     sem.release();
116                 }
117             }
118         });
119         if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
120             fail("Failed to run the command on the looper.");
121         }
122     }
123 
124     /**
125      * Flash: Auto / Exposure: None / WB: Daylight
126      * Scene: Sunset / Pic: Medium / Geo: off
127      */
128     @LargeTest
testCameraPairwiseScenario01()129     public void testCameraPairwiseScenario01() throws Exception {
130         genericPairwiseTestCase(Flash.AUTO, Exposure.NONE, WhiteBalance.DAYLIGHT, SceneMode.SUNSET,
131                 PictureSize.MEDIUM, Geotagging.OFF);
132     }
133 
134     /**
135      * Flash: On / Exposure: Min / WB: Fluorescent
136      * Scene: Auto / Pic: Large / Geo: on
137      */
138     @LargeTest
testCameraPairwiseScenario02()139     public void testCameraPairwiseScenario02() throws Exception {
140         genericPairwiseTestCase(Flash.ON, Exposure.MIN, WhiteBalance.FLUORESCENT, SceneMode.AUTO,
141                 PictureSize.LARGE, Geotagging.ON);
142     }
143 
144     /**
145      * Flash: Off / Exposure: Max / WB: Auto
146      * Scene: Night / Pic: Small / Geo: on
147      */
148     @LargeTest
testCameraPairwiseScenario03()149     public void testCameraPairwiseScenario03() throws Exception {
150         genericPairwiseTestCase(Flash.OFF, Exposure.MAX, WhiteBalance.AUTO, SceneMode.NIGHT,
151                 PictureSize.SMALL, Geotagging.ON);
152     }
153 
154     /**
155      * Flash: Off / Exposure: Max / WB: Cloudy
156      * Scene: Auto / Pic: Med / Geo: off
157      */
158     @LargeTest
testCameraPairwiseScenario04()159     public void testCameraPairwiseScenario04() throws Exception {
160         genericPairwiseTestCase(Flash.OFF, Exposure.MAX, WhiteBalance.CLOUDY, SceneMode.AUTO,
161                 PictureSize.MEDIUM, Geotagging.OFF);
162     }
163 
164     /**
165      * Flash: Auto / Exposure: Max / WB: Incandescent
166      * Scene: Auto / Pic: Large / Geo: off
167      */
168     @LargeTest
testCameraPairwiseScenario05()169     public void testCameraPairwiseScenario05() throws Exception {
170         genericPairwiseTestCase(Flash.AUTO, Exposure.MAX, WhiteBalance.INCANDESCENT,
171                 SceneMode.AUTO, PictureSize.LARGE, Geotagging.OFF);
172     }
173 
174     /**
175      * Flash: On / Exposure: None / WB: Cloudy
176      * Scene: Auto / Pic: Small / Geo: on
177      */
178     @LargeTest
testCameraPairwiseScenario06()179     public void testCameraPairwiseScenario06() throws Exception {
180         genericPairwiseTestCase(Flash.ON, Exposure.NONE, WhiteBalance.CLOUDY, SceneMode.AUTO,
181                 PictureSize.SMALL, Geotagging.ON);
182     }
183 
184     /**
185      * Flash: Auto / Exposure: Min / WB: Auto
186      * Scene: Action / Pic: Small / Geo: on
187      */
188     @LargeTest
testCameraPairwiseScenario07()189     public void testCameraPairwiseScenario07() throws Exception {
190         genericPairwiseTestCase(Flash.AUTO, Exposure.MIN, WhiteBalance.AUTO, SceneMode.ACTION,
191                 PictureSize.SMALL, Geotagging.ON);
192     }
193 
194     /**
195      * Flash: On / Exposure: Min / WB: Auto
196      * Scene: Action / Pic: Medium / Geo: off
197      */
198     @LargeTest
testCameraPairwiseScenario08()199     public void testCameraPairwiseScenario08() throws Exception {
200         genericPairwiseTestCase(Flash.ON, Exposure.MIN, WhiteBalance.AUTO, SceneMode.ACTION,
201                 PictureSize.MEDIUM, Geotagging.OFF);
202     }
203 
204     /**
205      * Flash: Off / Exposure: Min / WB: Auto
206      * Scene: Night / Pic: Large / Geo: off
207      */
208     @LargeTest
testCameraPairwiseScenario09()209     public void testCameraPairwiseScenario09() throws Exception {
210         genericPairwiseTestCase(Flash.OFF, Exposure.MIN, WhiteBalance.AUTO, SceneMode.NIGHT,
211                 PictureSize.LARGE, Geotagging.OFF);
212     }
213 
214     /**
215      * Flash: Off / Exposure: Min / WB: Daylight
216      * Scene: Sunset / Pic: Small / Geo: off
217      */
218     @LargeTest
testCameraPairwiseScenario10()219     public void testCameraPairwiseScenario10() throws Exception {
220         genericPairwiseTestCase(Flash.OFF, Exposure.MIN, WhiteBalance.DAYLIGHT, SceneMode.SUNSET,
221                 PictureSize.SMALL, Geotagging.OFF);
222     }
223 
224     /**
225      * Flash: On / Exposure: Max / WB: Daylight
226      * Scene: Sunset / Pic: Large / Geo: on
227      */
228     @LargeTest
testCameraPairwiseScenario11()229     public void testCameraPairwiseScenario11() throws Exception {
230         genericPairwiseTestCase(Flash.ON, Exposure.MAX, WhiteBalance.DAYLIGHT, SceneMode.SUNSET,
231                 PictureSize.LARGE, Geotagging.ON);
232     }
233 
234     /**
235      * Flash: Auto / Exposure: Min / WB: Cloudy
236      * Scene: Auto / Pic: Large / Geo: off
237      */
238     @LargeTest
testCameraPairwiseScenario12()239     public void testCameraPairwiseScenario12() throws Exception {
240         genericPairwiseTestCase(Flash.AUTO, Exposure.MIN, WhiteBalance.CLOUDY, SceneMode.AUTO,
241                 PictureSize.LARGE, Geotagging.OFF);
242     }
243 
244     /**
245      * Flash: Off / Exposure: None / WB: Auto
246      * Scene: Party / Pic: Medium / Geo: on
247      */
248     @LargeTest
testCameraPairwiseScenario13()249     public void testCameraPairwiseScenario13() throws Exception {
250         genericPairwiseTestCase(Flash.OFF, Exposure.NONE, WhiteBalance.AUTO, SceneMode.PARTY,
251                 PictureSize.MEDIUM, Geotagging.ON);
252     }
253 
254     /**
255      * Flash: Auto / Exposure: None / WB: Auto
256      * Scene: Night / Pic: Small / Geo: off
257      */
258     @LargeTest
testCameraPairwiseScenario14()259     public void testCameraPairwiseScenario14() throws Exception {
260         genericPairwiseTestCase(Flash.AUTO, Exposure.NONE, WhiteBalance.AUTO, SceneMode.NIGHT,
261                 PictureSize.SMALL, Geotagging.OFF);
262     }
263 
264     /**
265      * Flash: On / Exposure: None / WB: Incandescent
266      * Scene: Auto / Pic: Medium / Geo: on
267      */
268     @LargeTest
testCameraPairwiseScenario15()269     public void testCameraPairwiseScenario15() throws Exception {
270         genericPairwiseTestCase(Flash.ON, Exposure.NONE, WhiteBalance.INCANDESCENT, SceneMode.AUTO,
271                 PictureSize.MEDIUM, Geotagging.ON);
272     }
273 
274     /**
275      * Flash: Auto / Exposure: Min / WB: Auto
276      * Scene: Party / Pic: Small / Geo: off
277      */
278     @LargeTest
testCameraPairwiseScenario16()279     public void testCameraPairwiseScenario16() throws Exception {
280         genericPairwiseTestCase(Flash.AUTO, Exposure.MIN, WhiteBalance.AUTO, SceneMode.PARTY,
281                 PictureSize.SMALL, Geotagging.OFF);
282     }
283 
284     /**
285      * Flash: Off / Exposure: Min / WB: Incandescent
286      * Scene: Auto / Pic: Small / Geo: off
287      */
288     @LargeTest
testCameraPairwiseScenario17()289     public void testCameraPairwiseScenario17() throws Exception {
290         genericPairwiseTestCase(Flash.OFF, Exposure.MIN, WhiteBalance.INCANDESCENT, SceneMode.AUTO,
291                 PictureSize.SMALL, Geotagging.OFF);
292     }
293 
294     /**
295      * Flash: On / Exposure: None / WB: Auto
296      * Scene: Party / Pic: Large / Geo: off
297      */
298     @LargeTest
testCameraPairwiseScenario18()299     public void testCameraPairwiseScenario18() throws Exception {
300         genericPairwiseTestCase(Flash.ON, Exposure.NONE, WhiteBalance.AUTO, SceneMode.PARTY,
301                 PictureSize.LARGE, Geotagging.OFF);
302     }
303 
304     /**
305      * Flash Off / Exposure: None / WB: Auto
306      * Scene: Action / Pic: Large / Geo: off
307      */
308     @LargeTest
testCameraPairwiseScenario19()309     public void testCameraPairwiseScenario19() throws Exception {
310         genericPairwiseTestCase(Flash.OFF, Exposure.NONE, WhiteBalance.AUTO, SceneMode.ACTION,
311                 PictureSize.LARGE, Geotagging.OFF);
312     }
313 
314     /**
315      * Flash: Off / Exposure: Max / WB: Fluorescent
316      * Scene: Auto / Pic: Medium / Geo: Off
317      */
318     @LargeTest
testCameraPairwiseScenario20()319     public void testCameraPairwiseScenario20() throws Exception {
320         genericPairwiseTestCase(Flash.OFF, Exposure.MAX, WhiteBalance.FLUORESCENT, SceneMode.AUTO,
321                 PictureSize.MEDIUM, Geotagging.OFF);
322     }
323 
324     /**
325      * Flash: Off / Exposure: Min / WB: Auto
326      * Scene: Auto / Pic: Medium / Geo: off
327      */
testCameraPairwiseScenario21()328     public void testCameraPairwiseScenario21() throws Exception {
329         genericPairwiseTestCase(Flash.OFF, Exposure.MIN, WhiteBalance.AUTO, SceneMode.AUTO,
330                 PictureSize.MEDIUM, Geotagging.OFF);
331     }
332 
333     /**
334      * Flash: On / Exposure: Max / WB: Auto
335      * Scene: Action / Pic: Small / Geo: off
336      */
testCameraPairwiseScenario22()337     public void testCameraPairwiseScenario22() throws Exception {
338         genericPairwiseTestCase(Flash.ON, Exposure.MAX, WhiteBalance.AUTO, SceneMode.ACTION,
339                 PictureSize.SMALL, Geotagging.OFF);
340     }
341 
342     /**
343      * Flash: On / Exposure: Max / WB: Auto
344      * Scene: Night / Pic: Medium / Geo: on
345      */
testCameraPairwiseScenario23()346     public void testCameraPairwiseScenario23() throws Exception {
347         genericPairwiseTestCase(Flash.ON, Exposure.MAX, WhiteBalance.AUTO, SceneMode.NIGHT,
348                 PictureSize.MEDIUM, Geotagging.ON);
349     }
350 
351     /**
352      * Flash: Auto / Exposure: None / WB: Fluorescent
353      * Scene: Auto / Pic: Small / Geo: on
354      */
testCameraPairwiseScenario24()355     public void testCameraPairwiseScenario24() throws Exception {
356         genericPairwiseTestCase(Flash.AUTO, Exposure.NONE, WhiteBalance.FLUORESCENT,
357                 SceneMode.AUTO, PictureSize.SMALL, Geotagging.ON);
358     }
359 
360     /**
361      * Flash: Auto / Exposure: Max / WB: Daylight
362      * Scene: Auto / Pic: Medium / Geo: off
363      */
testCameraPairwiseScenario25()364     public void testCameraPairwiseScenario25() throws Exception {
365         genericPairwiseTestCase(Flash.AUTO, Exposure.MAX, WhiteBalance.DAYLIGHT, SceneMode.AUTO,
366                 PictureSize.MEDIUM, Geotagging.OFF);
367     }
368 
369     /**
370      * Flash: Auto / Exposure: Max / WB: Auto
371      * Scene: Party / Pic: Medium / Geo: on
372      */
testCameraPairwiseScenario26()373     public void testCameraPairwiseScenario26() throws Exception {
374         genericPairwiseTestCase(Flash.AUTO, Exposure.MAX, WhiteBalance.AUTO, SceneMode.PARTY,
375                 PictureSize.MEDIUM, Geotagging.ON);
376     }
377 
378     /**
379      * Generic pairwise test method
380      */
genericPairwiseTestCase(Flash flash, Exposure exposure, WhiteBalance whitebalance, SceneMode scenemode, PictureSize picturesize, Geotagging geotagging)381     private void genericPairwiseTestCase(Flash flash, Exposure exposure, WhiteBalance whitebalance,
382             SceneMode scenemode, PictureSize picturesize, Geotagging geotagging) throws Exception {
383         try {
384             SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
385             Camera.Parameters params = mCameraTestHelper.getCameraParameters();
386 
387             runOnLooper(new Runnable() {
388                 @Override
389                 public void run() {
390                     mCameraTestHelper.setupCameraTest();
391                 }
392             });
393 
394             // Configure flash setting
395             switch (flash) {
396                 case ON:
397                     params.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
398                     break;
399                 case OFF:
400                     params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
401                     break;
402                 case AUTO:
403                     params.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
404                     break;
405             }
406 
407             // Configure exposure setting
408             switch (exposure) {
409                 case MIN:
410                     params.setExposureCompensation(params.getMinExposureCompensation());
411                     break;
412                 case MAX:
413                     params.setExposureCompensation(params.getMaxExposureCompensation());
414                     break;
415                 case NONE:
416                     params.setExposureCompensation(0);
417                     break;
418             }
419 
420             // Configure white balance setting
421             switch (whitebalance) {
422                 case DAYLIGHT:
423                     params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_DAYLIGHT);
424                     break;
425                 case FLUORESCENT:
426                     params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_FLUORESCENT);
427                     break;
428                 case INCANDESCENT:
429                     params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_INCANDESCENT);
430                     break;
431                 case CLOUDY:
432                     params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT);
433                     break;
434                 case AUTO:
435                     params.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
436                     break;
437             }
438 
439             // Configure scene mode setting
440             switch (scenemode) {
441                 case SUNSET:
442                     params.setSceneMode(Camera.Parameters.SCENE_MODE_SUNSET);
443                     break;
444                 case ACTION:
445                     params.setSceneMode(Camera.Parameters.SCENE_MODE_ACTION);
446                     break;
447                 case PARTY:
448                     params.setSceneMode(Camera.Parameters.SCENE_MODE_PARTY);
449                     break;
450                 case NIGHT:
451                     params.setSceneMode(Camera.Parameters.SCENE_MODE_NIGHT);
452                     break;
453                 case AUTO:
454                     params.setSceneMode(Camera.Parameters.SCENE_MODE_AUTO);
455                     break;
456             }
457 
458             // Configure picture size setting
459             List<Camera.Size> supportedPictureSizes = params.getSupportedPictureSizes();
460             int mid = (int) Math.floor(supportedPictureSizes.size() / 2);
461             int low = supportedPictureSizes.size() - 1;
462             switch (picturesize) {
463                 case SMALL:
464                     params.setPictureSize(supportedPictureSizes.get(low).width,
465                             supportedPictureSizes.get(low).height);
466                     break;
467                 case MEDIUM:
468                     params.setPictureSize(supportedPictureSizes.get(mid).width,
469                             supportedPictureSizes.get(mid).height);
470                     break;
471                 case LARGE:
472                     params.setPictureSize(supportedPictureSizes.get(0).width,
473                             supportedPictureSizes.get(mid).height);
474                     break;
475             }
476 
477             // Configure geotagging setting
478             switch (geotagging) {
479                 case ON:
480                     params.setGpsLatitude(MOCK_LATITUDE);
481                     params.setGpsLongitude(MOCK_LONGITUDE);
482                     break;
483                 case OFF:
484                     break;
485             }
486 
487             mCameraTestHelper.setParameters(params);
488             mCameraTestHelper.startCameraPreview(surfaceHolder);
489             mCameraTestHelper.capturePhoto();
490             mCameraTestHelper.cleanupTestImages();
491         } catch (Exception e) {
492             Log.e(TAG, e.toString());
493             fail("Test case failed");
494         }
495     }
496 }
497