1/* 2 * Copyright (C) 2008 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.functional; 18 19import com.android.mediaframeworktest.MediaFrameworkTest; 20import com.android.mediaframeworktest.MediaNames; 21 22import android.content.Context; 23import android.hardware.Camera; 24import android.hardware.Camera.PictureCallback; 25import android.hardware.Camera.PreviewCallback; 26import android.hardware.Camera.ShutterCallback; 27import android.os.ConditionVariable; 28import android.os.Environment; 29import android.os.Looper; 30import android.test.ActivityInstrumentationTestCase; 31import android.test.suitebuilder.annotation.LargeTest; 32import android.util.Log; 33import android.view.SurfaceHolder; 34 35import java.io.*; 36 37/** 38 * Junit / Instrumentation test case for the camera api 39 40 */ 41public class CameraTest extends ActivityInstrumentationTestCase<MediaFrameworkTest> { 42 private String TAG = "CameraTest"; 43 44 private boolean rawPreviewCallbackResult = false; 45 private boolean shutterCallbackResult = false; 46 private boolean rawPictureCallbackResult = false; 47 private boolean jpegPictureCallbackResult = false; 48 49 private static int WAIT_FOR_COMMAND_TO_COMPLETE = 10000; // Milliseconds. 50 private static final int CAMERA_ID = 0; 51 52 private RawPreviewCallback mRawPreviewCallback = new RawPreviewCallback(); 53 private TestShutterCallback mShutterCallback = new TestShutterCallback(); 54 private RawPictureCallback mRawPictureCallback = new RawPictureCallback(); 55 private JpegPictureCallback mJpegPictureCallback = new JpegPictureCallback(); 56 57 private boolean mInitialized = false; 58 private Looper mLooper = null; 59 private final ConditionVariable mPreviewDone = new ConditionVariable(); 60 private final ConditionVariable mSnapshotDone = new ConditionVariable(); 61 62 Camera mCamera; 63 Context mContext; 64 65 public CameraTest() { 66 super("com.android.mediaframeworktest", MediaFrameworkTest.class); 67 } 68 69 protected void setUp() throws Exception { 70 super.setUp(); 71 } 72 73 /* 74 * Initializes the message looper so that the Camera object can 75 * receive the callback messages. 76 */ 77 private void initializeMessageLooper() { 78 final ConditionVariable startDone = new ConditionVariable(); 79 Log.v(TAG, "start looper"); 80 new Thread() { 81 @Override 82 public void run() { 83 // Set up a looper to be used by camera. 84 Looper.prepare(); 85 Log.v(TAG, "start loopRun"); 86 // Save the looper so that we can terminate this thread 87 // after we are done with it. 88 mLooper = Looper.myLooper(); 89 mCamera = Camera.open(CAMERA_ID); 90 startDone.open(); 91 Looper.loop(); // Blocks forever until Looper.quit() is called. 92 Log.v(TAG, "initializeMessageLooper: quit."); 93 } 94 }.start(); 95 96 if (!startDone.block(WAIT_FOR_COMMAND_TO_COMPLETE)) { 97 fail("initializeMessageLooper: start timeout"); 98 } 99 } 100 101 /* 102 * Terminates the message looper thread. 103 */ 104 private void terminateMessageLooper() throws Exception { 105 mLooper.quit(); 106 // Looper.quit() is asynchronous. The looper may still has some 107 // preview callbacks in the queue after quit is called. The preview 108 // callback still uses the camera object (setHasPreviewCallback). 109 // After camera is released, RuntimeException will be thrown from 110 // the method. So we need to join the looper thread here. 111 mLooper.getThread().join(); 112 mCamera.release(); 113 } 114 115 //Implement the previewCallback 116 private final class RawPreviewCallback implements PreviewCallback { 117 public void onPreviewFrame(byte [] rawData, Camera camera) { 118 Log.v(TAG, "Preview callback start"); 119 int rawDataLength = 0; 120 if (rawData != null) { 121 rawDataLength = rawData.length; 122 } 123 if (rawDataLength > 0) { 124 rawPreviewCallbackResult = true; 125 } else { 126 rawPreviewCallbackResult = false; 127 } 128 mPreviewDone.open(); 129 Log.v(TAG, "Preview callback stop"); 130 } 131 }; 132 133 //Implement the shutterCallback 134 private final class TestShutterCallback implements ShutterCallback { 135 public void onShutter() { 136 shutterCallbackResult = true; 137 Log.v(TAG, "onShutter called"); 138 } 139 }; 140 141 //Implement the RawPictureCallback 142 private final class RawPictureCallback implements PictureCallback { 143 public void onPictureTaken(byte [] rawData, Camera camera) { 144 // no support for raw data - success if we get the callback 145 rawPictureCallbackResult = true; 146 Log.v(TAG, "RawPictureCallback callback"); 147 } 148 }; 149 150 //Implement the JpegPictureCallback 151 private final class JpegPictureCallback implements PictureCallback { 152 public void onPictureTaken(byte [] rawData, Camera camera) { 153 try { 154 if (rawData != null) { 155 int rawDataLength = rawData.length; 156 File rawoutput = new File( 157 Environment.getExternalStorageDirectory().toString(), "/test.bmp"); 158 FileOutputStream outstream = new FileOutputStream(rawoutput); 159 outstream.write(rawData); 160 Log.v(TAG, "JpegPictureCallback rawDataLength = " + rawDataLength); 161 jpegPictureCallbackResult = true; 162 } else { 163 jpegPictureCallbackResult = false; 164 } 165 mSnapshotDone.open(); 166 Log.v(TAG, "Jpeg Picture callback"); 167 } catch (Exception e) { 168 Log.v(TAG, e.toString()); 169 } 170 } 171 }; 172 173 private void waitForPreviewDone() { 174 if (!mPreviewDone.block(WAIT_FOR_COMMAND_TO_COMPLETE)) { 175 Log.v(TAG, "waitForPreviewDone: timeout"); 176 } 177 mPreviewDone.close(); 178 } 179 180 private void waitForSnapshotDone() { 181 if (!mSnapshotDone.block(MediaNames.WAIT_SNAPSHOT_TIME)) { 182 // timeout could be expected or unexpected. The caller will decide. 183 Log.v(TAG, "waitForSnapshotDone: timeout"); 184 } 185 mSnapshotDone.close(); 186 } 187 188 189 private void checkTakePicture() { 190 SurfaceHolder mSurfaceHolder; 191 try { 192 mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder(); 193 mCamera.setPreviewDisplay(mSurfaceHolder); 194 Log.v(TAG, "Start preview"); 195 mCamera.startPreview(); 196 waitForPreviewDone(); 197 mCamera.setPreviewCallback(null); 198 mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback); 199 waitForSnapshotDone(); 200 } catch (Exception e) { 201 Log.v(TAG, e.toString()); 202 } 203 } 204 205 private void checkPreviewCallback() { 206 SurfaceHolder mSurfaceHolder; 207 try { 208 mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder(); 209 mCamera.setPreviewDisplay(mSurfaceHolder); 210 Log.v(TAG, "start preview"); 211 mCamera.startPreview(); 212 waitForPreviewDone(); 213 mCamera.setPreviewCallback(null); 214 } catch (Exception e) { 215 Log.v(TAG, e.toString()); 216 } 217 } 218 219 /* 220 * TODO(yslau): Need to setup the golden rawData and compare the 221 * the new captured rawData with the golden one. 222 * 223 * Test case 1: Take a picture and verify all the callback 224 * functions are called properly. 225 */ 226 @LargeTest 227 public void testTakePicture() throws Exception { 228 initializeMessageLooper(); 229 mCamera.setPreviewCallback(mRawPreviewCallback); 230 checkTakePicture(); 231 terminateMessageLooper(); 232 assertTrue("shutterCallbackResult", shutterCallbackResult); 233 assertTrue("rawPictureCallbackResult", rawPictureCallbackResult); 234 assertTrue("jpegPictureCallbackResult", jpegPictureCallbackResult); 235 } 236 237 /* 238 * Test case 2: Set the preview and 239 * verify the RawPreviewCallback is called 240 */ 241 @LargeTest 242 public void testCheckPreview() throws Exception { 243 initializeMessageLooper(); 244 mCamera.setPreviewCallback(mRawPreviewCallback); 245 checkPreviewCallback(); 246 terminateMessageLooper(); 247 assertTrue("RawPreviewCallbackResult", rawPreviewCallbackResult); 248 } 249 250} 251 252