1/*
2 * Copyright (C) 2012 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
17package com.android.mediaframeworktest.stress;
18
19import com.android.mediaframeworktest.MediaFrameworkTest;
20import com.android.mediaframeworktest.helpers.CameraTestHelper;
21
22import java.io.BufferedWriter;
23import java.io.File;
24import java.io.FileWriter;
25import java.io.Writer;
26import java.util.concurrent.Semaphore;
27import java.util.concurrent.TimeUnit;
28import java.util.List;
29
30import android.hardware.Camera.Parameters;
31import android.os.Environment;
32import android.os.Handler;
33import android.os.Looper;
34import android.test.ActivityInstrumentationTestCase2;
35import android.test.suitebuilder.annotation.LargeTest;
36import android.util.Log;
37import android.view.SurfaceHolder;
38
39/**
40 * Junit / Instrumentation test case for the following camera APIs:
41 *  - camera zoom
42 *  - scene mode
43 *
44 * adb shell am instrument
45 *  -e class com.android.mediaframeworktest.stress.CameraStressTest
46 *  -w com.android.mediaframeworktest/.CameraStressTestRunner
47 */
48public class CameraStressTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
49
50    private static final int NUMBER_OF_SCENE_MODE_LOOPS = 10;
51    private static final int NUMBER_OF_ZOOM_LOOPS = 100;
52    private static final long WAIT_TIMEOUT = 10 * 1000; // 10 seconds
53    private static final String CAMERA_STRESS_OUTPUT = "cameraStressOutput.txt";
54
55    private CameraTestHelper mCameraTestHelper;
56    private Handler mHandler;
57    private Thread mLooperThread;
58    private Writer mOutput;
59
60    private String TAG = "CameraStressTest";
61
62    public CameraStressTest() {
63        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
64    }
65
66    protected void setUp() throws Exception {
67        final Semaphore sem = new Semaphore(0);
68        mLooperThread = new Thread() {
69            @Override
70            public void run() {
71                Log.v(TAG, "starting looper");
72                Looper.prepare();
73                mHandler = new Handler();
74                sem.release();
75                Looper.loop();
76                Log.v(TAG, "quit looper");
77            }
78        };
79        mLooperThread.start();
80        if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
81            fail("Failed to start the looper.");
82        }
83        getActivity();
84        super.setUp();
85
86        mCameraTestHelper = new CameraTestHelper();
87        File stressOutFile = new File(String.format("%s/%s",
88                Environment.getExternalStorageDirectory(), CAMERA_STRESS_OUTPUT));
89        mOutput = new BufferedWriter(new FileWriter(stressOutFile, true));
90        mOutput.write(this.getName() + "\n");
91    }
92
93    @Override
94    protected void tearDown() throws Exception {
95        if (mHandler != null) {
96            mHandler.getLooper().quit();
97            mHandler = null;
98        }
99        if (mLooperThread != null) {
100            mLooperThread.join(WAIT_TIMEOUT);
101            if (mLooperThread.isAlive()) {
102                fail("Failed to stop the looper.");
103            }
104            mLooperThread = null;
105        }
106        mOutput.write("\n\n");
107        mOutput.close();
108        super.tearDown();
109    }
110
111    private void runOnLooper(final Runnable command) throws InterruptedException {
112        final Semaphore sem = new Semaphore(0);
113        mHandler.post(new Runnable() {
114            @Override
115            public void run() {
116                try {
117                    command.run();
118                } finally {
119                    sem.release();
120                }
121            }
122        });
123        if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
124            fail("Failed to run the command on the looper.");
125        }
126    }
127
128    /**
129     * Stress test iterating on the various scene modes (action, night, party, etc.)
130     */
131    @LargeTest
132    public void testStressCameraSceneModes() throws Exception {
133        try {
134            SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
135            Parameters params = mCameraTestHelper.getCameraParameters();
136            List<String> supportedSceneModes = params.getSupportedSceneModes();
137            assertNotNull("No scene modes supported", supportedSceneModes);
138
139            mOutput.write("Total number of loops: " +
140                    (NUMBER_OF_SCENE_MODE_LOOPS * supportedSceneModes.size()) + "\n");
141            Log.v(TAG, "Start preview");
142            mOutput.write("No of loop: ");
143
144            for (int i = 0; i < supportedSceneModes.size(); i++) {
145                for (int j = 0; j < NUMBER_OF_SCENE_MODE_LOOPS; j++) {
146                    runOnLooper(new Runnable() {
147                        @Override
148                        public void run() {
149                            mCameraTestHelper.setupCameraTest();
150                        }
151                    });
152                    Log.v(TAG, "Setting scene mode to " + supportedSceneModes.get(i));
153                    params.setSceneMode(supportedSceneModes.get(i));
154                    mCameraTestHelper.setParameters(params);
155                    mCameraTestHelper.startCameraPreview(surfaceHolder);
156                    mCameraTestHelper.capturePhoto();
157
158                    if (i == 0 && j == 0) {
159                        mOutput.write(Integer.toString(j + i * NUMBER_OF_SCENE_MODE_LOOPS));
160                    } else {
161                        mOutput.write(", " + (j + i * NUMBER_OF_SCENE_MODE_LOOPS));
162                    }
163                }
164            }
165            mCameraTestHelper.cleanupTestImages();
166        } catch (Exception e) {
167            Log.e(TAG, e.toString());
168            fail("Camera scene mode test Exception");
169        }
170    }
171
172    /**
173     * Stress test iterating on the range of supported camera zoom levels
174     */
175    @LargeTest
176    public void testStressCameraZoom() throws Exception {
177        try {
178            SurfaceHolder surfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
179            Parameters params = mCameraTestHelper.getCameraParameters();
180
181            if (!params.isSmoothZoomSupported() && !params.isZoomSupported()) {
182                Log.v(TAG, "Device camera does not support zoom");
183                fail("Camera zoom stress test failed due to unsupported feature");
184            } else {
185                Log.v(TAG, "Device camera does support zoom");
186                Log.v(TAG, "Start preview");
187                mOutput.write("Total number of loops: " + NUMBER_OF_ZOOM_LOOPS + "\n");
188                mOutput.write("No of loops: ");
189
190                int nextZoomLevel = 0;
191
192                for (int i = 0; i < NUMBER_OF_ZOOM_LOOPS; i++) {
193                    runOnLooper(new Runnable() {
194                        @Override
195                        public void run() {
196                            mCameraTestHelper.setupCameraTest();
197                        }
198                    });
199
200                    mCameraTestHelper.startCameraPreview(surfaceHolder);
201                    params = mCameraTestHelper.mCamera.getParameters();
202                    int currentZoomLevel = params.getZoom();
203
204                    if (nextZoomLevel >= params.getMaxZoom()) {
205                        nextZoomLevel = 0;
206                    }
207                    ++nextZoomLevel;
208
209                    if (params.isSmoothZoomSupported()) {
210                        mCameraTestHelper.mCamera.startSmoothZoom(nextZoomLevel);
211                    } else {
212                        params.setZoom(nextZoomLevel);
213                        mCameraTestHelper.setParameters(params);
214                    }
215                    mCameraTestHelper.capturePhoto();
216
217                    if (i == 0) {
218                        mOutput.write(Integer.toString(i));
219                    } else {
220                        mOutput.write(", " + i);
221                    }
222                }
223            }
224            mCameraTestHelper.cleanupTestImages();
225        } catch (Exception e) {
226            Log.e(TAG, e.toString());
227            fail("Camera zoom stress test Exception");
228        }
229    }
230}
231