CameraStressTest.java revision a784b3dea15dd0dfedfe25552b87fbb92a5eea52
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;
20
21import java.io.BufferedWriter;
22import java.io.File;
23import java.io.FilenameFilter;
24import java.io.FileWriter;
25import java.io.FileNotFoundException;
26import java.io.FileOutputStream;
27import java.io.IOException;
28import java.io.Writer;
29import java.util.concurrent.Semaphore;
30import java.util.concurrent.TimeUnit;
31
32import android.hardware.Camera;
33import android.hardware.Camera.PictureCallback;
34import android.hardware.Camera.ShutterCallback;
35import android.os.Environment;
36import android.os.Handler;
37import android.os.Looper;
38import android.test.ActivityInstrumentationTestCase2;
39import android.test.suitebuilder.annotation.LargeTest;
40import android.util.Log;
41import android.view.SurfaceHolder;
42import com.android.mediaframeworktest.CameraStressTestRunner;
43
44import junit.framework.Assert;
45
46/**
47 * Junit / Instrumentation test case for the camera zoom api
48 *
49 * adb shell am instrument
50 *  -e class com.android.mediaframeworktest.stress.CameraStressTest
51 *  -w com.android.mediaframeworktest/.CameraStressTestRunner
52 */
53public class CameraStressTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
54    private String TAG = "CameraStressTest";
55    private Camera mCamera;
56
57    private static final int NUMBER_OF_ZOOM_LOOPS = 100;
58    private static final long WAIT_GENERIC = 3 * 1000; // 3 seconds
59    private static final long WAIT_TIMEOUT = 10 * 1000; // 10 seconds
60    private static final long WAIT_ZOOM_ANIMATION = 5 * 1000; // 5 seconds
61    private static final String CAMERA_STRESS_OUTPUT =
62            "/sdcard/cameraStressOutput.txt";
63    private final CameraErrorCallback mCameraErrorCallback = new CameraErrorCallback();
64
65    private Thread mLooperThread;
66    private Handler mHandler;
67
68    public CameraStressTest() {
69        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
70    }
71
72    protected void setUp() throws Exception {
73        final Semaphore sem = new Semaphore(0);
74        mLooperThread = new Thread() {
75            @Override
76            public void run() {
77                Log.v(TAG, "starting looper");
78                Looper.prepare();
79                mHandler = new Handler();
80                sem.release();
81                Looper.loop();
82                Log.v(TAG, "quit looper");
83            }
84        };
85        mLooperThread.start();
86        if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
87            fail("Failed to start the looper.");
88        }
89        getActivity();
90        super.setUp();
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
107        super.tearDown();
108    }
109
110    private void runOnLooper(final Runnable command) throws InterruptedException {
111        final Semaphore sem = new Semaphore(0);
112        mHandler.post(new Runnable() {
113            @Override
114            public void run() {
115                try {
116                    command.run();
117                } finally {
118                    sem.release();
119                }
120            }
121        });
122        if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
123            fail("Failed to run the command on the looper.");
124        }
125    }
126
127    private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
128        public void onError(int error, android.hardware.Camera camera) {
129            if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) {
130                assertTrue("Camera test mediaserver died", false);
131            }
132        }
133    }
134
135    private ShutterCallback shutterCallback = new ShutterCallback() {
136        @Override
137        public void onShutter() {
138            Log.v(TAG, "Shutter");
139        }
140    };
141
142    private PictureCallback rawCallback = new PictureCallback() {
143        @Override
144        public void onPictureTaken(byte[] data, Camera camera) {
145            Log.v(TAG, "Raw picture taken");
146        }
147    };
148
149    private PictureCallback jpegCallback = new PictureCallback() {
150        @Override
151        public void onPictureTaken(byte[] data, Camera camera) {
152            FileOutputStream fos = null;
153
154            try {
155                Log.v(TAG, "JPEG picture taken");
156                fos = new FileOutputStream(String.format("%s/zoom-test-%d.jpg",
157                        Environment.getExternalStorageDirectory(), System.currentTimeMillis()));
158                fos.write(data);
159            }
160            catch (FileNotFoundException e) {
161                Log.v(TAG, "File not found: " + e.toString());
162            }
163            catch (IOException e) {
164                Log.v(TAG, "Error accessing file: " + e.toString());
165            }
166            finally {
167                try {
168                    if (fos != null) {
169                        fos.close();
170                    }
171                }
172                catch (IOException e) {
173                    Log.v(TAG, "Error closing file: " + e.toString());
174                }
175            }
176        }
177    };
178
179    // Helper method for cleaning up pics taken during testStressCameraZoom
180    private void cleanupZoomImages() {
181        try {
182            File sdcard = Environment.getExternalStorageDirectory();
183            File[] zoomImages = null;
184
185            FilenameFilter filter = new FilenameFilter() {
186                public boolean accept(File dir, String name) {
187                    return name.startsWith("zoom-test-");
188                }
189            };
190
191            zoomImages = sdcard.listFiles(filter);
192
193            for (File f : zoomImages) {
194                f.delete();
195            }
196        }
197        catch (SecurityException e) {
198            Log.v(TAG, "Security manager access violation: " + e.toString());
199        }
200    }
201
202    // Test case for stressing the camera zoom in/out feature
203    @LargeTest
204    public void testStressCameraZoom() throws Exception {
205        SurfaceHolder mSurfaceHolder;
206        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
207        File stressOutFile = new File(CAMERA_STRESS_OUTPUT);
208        Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
209        output.write("Camera zoom stress:\n");
210        output.write("Total number of loops: " +  NUMBER_OF_ZOOM_LOOPS + "\n");
211
212        try {
213            Log.v(TAG, "Start preview");
214            output.write("No of loop: ");
215
216            mCamera = Camera.open();
217            Camera.Parameters params = mCamera.getParameters();
218            mCamera.release();
219
220            if (!params.isSmoothZoomSupported() && !params.isZoomSupported()) {
221                Log.v(TAG, "Device camera does not support zoom");
222                assertTrue("Camera zoom stress test", false);
223            }
224            else {
225                Log.v(TAG, "Device camera does support zoom");
226
227                int nextZoomLevel = 0;
228
229                for (int i = 0; i < NUMBER_OF_ZOOM_LOOPS; i++) {
230                    runOnLooper(new Runnable() {
231                        @Override
232                        public void run() {
233                            mCamera = Camera.open();
234                        }
235                    });
236
237                    mCamera.setErrorCallback(mCameraErrorCallback);
238                    mCamera.setPreviewDisplay(mSurfaceHolder);
239                    mCamera.startPreview();
240                    Thread.sleep(WAIT_GENERIC);
241
242                    params = mCamera.getParameters();
243                    int currentZoomLevel = params.getZoom();
244
245                    if (nextZoomLevel >= params.getMaxZoom()) {
246                        nextZoomLevel = 0;
247                    }
248                    ++nextZoomLevel;
249
250                    if (params.isSmoothZoomSupported()) {
251                        mCamera.startSmoothZoom(nextZoomLevel);
252                    }
253                    else {
254                        params.setZoom(nextZoomLevel);
255                        mCamera.setParameters(params);
256                    }
257                    Log.v(TAG, "Zooming from " + currentZoomLevel + " to " + nextZoomLevel);
258
259                    // sleep allows for zoom animation to finish
260                    Thread.sleep(WAIT_ZOOM_ANIMATION);
261
262                    // take picture
263                    mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
264                    Thread.sleep(WAIT_GENERIC);
265                    mCamera.stopPreview();
266                    mCamera.release();
267                    output.write(" ," + i);
268                }
269            }
270
271            cleanupZoomImages();
272        }
273        catch (Exception e) {
274            assertTrue("Camera zoom stress test Exception", false);
275            Log.v(TAG, e.toString());
276        }
277        output.write("\n\n");
278        output.close();
279    }
280}
281