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 static final int CAMERA_ID = 0; 64 private final CameraErrorCallback mCameraErrorCallback = new CameraErrorCallback(); 65 66 private Thread mLooperThread; 67 private Handler mHandler; 68 69 public CameraStressTest() { 70 super("com.android.mediaframeworktest", MediaFrameworkTest.class); 71 } 72 73 protected void setUp() throws Exception { 74 final Semaphore sem = new Semaphore(0); 75 mLooperThread = new Thread() { 76 @Override 77 public void run() { 78 Log.v(TAG, "starting looper"); 79 Looper.prepare(); 80 mHandler = new Handler(); 81 sem.release(); 82 Looper.loop(); 83 Log.v(TAG, "quit looper"); 84 } 85 }; 86 mLooperThread.start(); 87 if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) { 88 fail("Failed to start the looper."); 89 } 90 getActivity(); 91 super.setUp(); 92 } 93 94 @Override 95 protected void tearDown() throws Exception { 96 if (mHandler != null) { 97 mHandler.getLooper().quit(); 98 mHandler = null; 99 } 100 if (mLooperThread != null) { 101 mLooperThread.join(WAIT_TIMEOUT); 102 if (mLooperThread.isAlive()) { 103 fail("Failed to stop the looper."); 104 } 105 mLooperThread = null; 106 } 107 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 private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback { 129 public void onError(int error, android.hardware.Camera camera) { 130 if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) { 131 assertTrue("Camera test mediaserver died", false); 132 } 133 } 134 } 135 136 private ShutterCallback shutterCallback = new ShutterCallback() { 137 @Override 138 public void onShutter() { 139 Log.v(TAG, "Shutter"); 140 } 141 }; 142 143 private PictureCallback rawCallback = new PictureCallback() { 144 @Override 145 public void onPictureTaken(byte[] data, Camera camera) { 146 Log.v(TAG, "Raw picture taken"); 147 } 148 }; 149 150 private PictureCallback jpegCallback = new PictureCallback() { 151 @Override 152 public void onPictureTaken(byte[] data, Camera camera) { 153 FileOutputStream fos = null; 154 155 try { 156 Log.v(TAG, "JPEG picture taken"); 157 fos = new FileOutputStream(String.format("%s/zoom-test-%d.jpg", 158 Environment.getExternalStorageDirectory(), System.currentTimeMillis())); 159 fos.write(data); 160 } 161 catch (FileNotFoundException e) { 162 Log.v(TAG, "File not found: " + e.toString()); 163 } 164 catch (IOException e) { 165 Log.v(TAG, "Error accessing file: " + e.toString()); 166 } 167 finally { 168 try { 169 if (fos != null) { 170 fos.close(); 171 } 172 } 173 catch (IOException e) { 174 Log.v(TAG, "Error closing file: " + e.toString()); 175 } 176 } 177 } 178 }; 179 180 // Helper method for cleaning up pics taken during testStressCameraZoom 181 private void cleanupZoomImages() { 182 try { 183 File sdcard = Environment.getExternalStorageDirectory(); 184 File[] zoomImages = null; 185 186 FilenameFilter filter = new FilenameFilter() { 187 public boolean accept(File dir, String name) { 188 return name.startsWith("zoom-test-"); 189 } 190 }; 191 192 zoomImages = sdcard.listFiles(filter); 193 194 for (File f : zoomImages) { 195 f.delete(); 196 } 197 } 198 catch (SecurityException e) { 199 Log.v(TAG, "Security manager access violation: " + e.toString()); 200 } 201 } 202 203 // Test case for stressing the camera zoom in/out feature 204 @LargeTest 205 public void testStressCameraZoom() throws Exception { 206 SurfaceHolder mSurfaceHolder; 207 mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder(); 208 File stressOutFile = new File(CAMERA_STRESS_OUTPUT); 209 Writer output = new BufferedWriter(new FileWriter(stressOutFile, true)); 210 output.write("Camera zoom stress:\n"); 211 output.write("Total number of loops: " + NUMBER_OF_ZOOM_LOOPS + "\n"); 212 213 try { 214 Log.v(TAG, "Start preview"); 215 output.write("No of loop: "); 216 217 mCamera = Camera.open(CAMERA_ID); 218 Camera.Parameters params = mCamera.getParameters(); 219 mCamera.release(); 220 221 if (!params.isSmoothZoomSupported() && !params.isZoomSupported()) { 222 Log.v(TAG, "Device camera does not support zoom"); 223 assertTrue("Camera zoom stress test", false); 224 } 225 else { 226 Log.v(TAG, "Device camera does support zoom"); 227 228 int nextZoomLevel = 0; 229 230 for (int i = 0; i < NUMBER_OF_ZOOM_LOOPS; i++) { 231 runOnLooper(new Runnable() { 232 @Override 233 public void run() { 234 mCamera = Camera.open(CAMERA_ID); 235 } 236 }); 237 238 mCamera.setErrorCallback(mCameraErrorCallback); 239 mCamera.setPreviewDisplay(mSurfaceHolder); 240 mCamera.startPreview(); 241 Thread.sleep(WAIT_GENERIC); 242 243 params = mCamera.getParameters(); 244 int currentZoomLevel = params.getZoom(); 245 246 if (nextZoomLevel >= params.getMaxZoom()) { 247 nextZoomLevel = 0; 248 } 249 ++nextZoomLevel; 250 251 if (params.isSmoothZoomSupported()) { 252 mCamera.startSmoothZoom(nextZoomLevel); 253 } 254 else { 255 params.setZoom(nextZoomLevel); 256 mCamera.setParameters(params); 257 } 258 Log.v(TAG, "Zooming from " + currentZoomLevel + " to " + nextZoomLevel); 259 260 // sleep allows for zoom animation to finish 261 Thread.sleep(WAIT_ZOOM_ANIMATION); 262 263 // take picture 264 mCamera.takePicture(shutterCallback, rawCallback, jpegCallback); 265 Thread.sleep(WAIT_GENERIC); 266 mCamera.stopPreview(); 267 mCamera.release(); 268 output.write(" ," + i); 269 } 270 } 271 272 cleanupZoomImages(); 273 } 274 catch (Exception e) { 275 assertTrue("Camera zoom stress test Exception", false); 276 Log.v(TAG, e.toString()); 277 } 278 output.write("\n\n"); 279 output.close(); 280 } 281} 282