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