blob: 7f23ba576fbbc89eabf73b99a9e9b9ea7ddc9c13 [file] [log] [blame]
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.mediaframeworktest.functional;
import com.android.mediaframeworktest.MediaFrameworkTest;
import com.android.mediaframeworktest.MediaNames;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.ShutterCallback;
import android.os.ConditionVariable;
import android.os.Environment;
import android.os.Looper;
import android.test.ActivityInstrumentationTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
import android.view.SurfaceHolder;
import java.io.*;
/**
* Junit / Instrumentation test case for the camera api
*
* To run only tests in this class:
*
* adb shell am instrument \
* -e class com.android.mediaframeworktest.functional.CameraTest \
* -w com.android.mediaframeworktest/.MediaFrameworkTestRunner
*/
public class CameraTest extends ActivityInstrumentationTestCase<MediaFrameworkTest> {
private String TAG = "CameraTest";
private boolean rawPreviewCallbackResult = false;
private boolean shutterCallbackResult = false;
private boolean rawPictureCallbackResult = false;
private boolean jpegPictureCallbackResult = false;
private static int WAIT_FOR_COMMAND_TO_COMPLETE = 10000; // Milliseconds.
private static final int CAMERA_ID = 0;
private RawPreviewCallback mRawPreviewCallback = new RawPreviewCallback();
private TestShutterCallback mShutterCallback = new TestShutterCallback();
private RawPictureCallback mRawPictureCallback = new RawPictureCallback();
private JpegPictureCallback mJpegPictureCallback = new JpegPictureCallback();
private boolean mInitialized = false;
private Looper mLooper = null;
private final ConditionVariable mPreviewDone = new ConditionVariable();
private final ConditionVariable mSnapshotDone = new ConditionVariable();
Camera mCamera;
Context mContext;
public CameraTest() {
super("com.android.mediaframeworktest", MediaFrameworkTest.class);
}
protected void setUp() throws Exception {
super.setUp();
}
/*
* Initializes the message looper so that the Camera object can
* receive the callback messages.
*/
private void initializeMessageLooper() {
final ConditionVariable startDone = new ConditionVariable();
Log.v(TAG, "start looper");
new Thread() {
@Override
public void run() {
// Set up a looper to be used by camera.
Looper.prepare();
Log.v(TAG, "start loopRun");
// Save the looper so that we can terminate this thread
// after we are done with it.
mLooper = Looper.myLooper();
mCamera = Camera.open(CAMERA_ID);
startDone.open();
Looper.loop(); // Blocks forever until Looper.quit() is called.
Log.v(TAG, "initializeMessageLooper: quit.");
}
}.start();
if (!startDone.block(WAIT_FOR_COMMAND_TO_COMPLETE)) {
fail("initializeMessageLooper: start timeout");
}
}
/*
* Terminates the message looper thread.
*/
private void terminateMessageLooper() throws Exception {
mLooper.quit();
// Looper.quit() is asynchronous. The looper may still has some
// preview callbacks in the queue after quit is called. The preview
// callback still uses the camera object (setHasPreviewCallback).
// After camera is released, RuntimeException will be thrown from
// the method. So we need to join the looper thread here.
mLooper.getThread().join();
mCamera.release();
}
//Implement the previewCallback
private final class RawPreviewCallback implements PreviewCallback {
public void onPreviewFrame(byte [] rawData, Camera camera) {
Log.v(TAG, "Preview callback start");
int rawDataLength = 0;
if (rawData != null) {
rawDataLength = rawData.length;
}
if (rawDataLength > 0) {
rawPreviewCallbackResult = true;
} else {
rawPreviewCallbackResult = false;
}
mPreviewDone.open();
Log.v(TAG, "Preview callback stop");
}
};
//Implement the shutterCallback
private final class TestShutterCallback implements ShutterCallback {
public void onShutter() {
shutterCallbackResult = true;
Log.v(TAG, "onShutter called");
}
};
//Implement the RawPictureCallback
private final class RawPictureCallback implements PictureCallback {
public void onPictureTaken(byte [] rawData, Camera camera) {
// no support for raw data - success if we get the callback
rawPictureCallbackResult = true;
Log.v(TAG, "RawPictureCallback callback");
}
};
//Implement the JpegPictureCallback
private final class JpegPictureCallback implements PictureCallback {
public void onPictureTaken(byte [] rawData, Camera camera) {
try {
if (rawData != null) {
int rawDataLength = rawData.length;
File rawoutput = new File(
Environment.getExternalStorageDirectory().toString(), "/test.bmp");
FileOutputStream outstream = new FileOutputStream(rawoutput);
outstream.write(rawData);
Log.v(TAG, "JpegPictureCallback rawDataLength = " + rawDataLength);
jpegPictureCallbackResult = true;
} else {
jpegPictureCallbackResult = false;
}
mSnapshotDone.open();
Log.v(TAG, "Jpeg Picture callback");
} catch (Exception e) {
Log.v(TAG, e.toString());
}
}
};
private void waitForPreviewDone() {
if (!mPreviewDone.block(WAIT_FOR_COMMAND_TO_COMPLETE)) {
Log.v(TAG, "waitForPreviewDone: timeout");
}
mPreviewDone.close();
}
private void waitForSnapshotDone() {
if (!mSnapshotDone.block(MediaNames.WAIT_SNAPSHOT_TIME)) {
// timeout could be expected or unexpected. The caller will decide.
Log.v(TAG, "waitForSnapshotDone: timeout");
}
mSnapshotDone.close();
}
private void checkTakePicture() {
SurfaceHolder mSurfaceHolder;
try {
mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
mCamera.setPreviewDisplay(mSurfaceHolder);
Log.v(TAG, "Start preview");
mCamera.startPreview();
waitForPreviewDone();
mCamera.setPreviewCallback(null);
mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
waitForSnapshotDone();
} catch (Exception e) {
Log.v(TAG, e.toString());
}
}
private void checkPreviewCallback() {
SurfaceHolder mSurfaceHolder;
try {
mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
mCamera.setPreviewDisplay(mSurfaceHolder);
Log.v(TAG, "start preview");
mCamera.startPreview();
waitForPreviewDone();
mCamera.setPreviewCallback(null);
} catch (Exception e) {
Log.v(TAG, e.toString());
}
}
/*
* TODO(yslau): Need to setup the golden rawData and compare the
* the new captured rawData with the golden one.
*
* Test case 1: Take a picture and verify all the callback
* functions are called properly.
*/
@LargeTest
public void testTakePicture() throws Exception {
initializeMessageLooper();
mCamera.setPreviewCallback(mRawPreviewCallback);
checkTakePicture();
terminateMessageLooper();
assertTrue("shutterCallbackResult", shutterCallbackResult);
assertTrue("rawPictureCallbackResult", rawPictureCallbackResult);
assertTrue("jpegPictureCallbackResult", jpegPictureCallbackResult);
}
/*
* Test case 2: Set the preview and
* verify the RawPreviewCallback is called
*/
@LargeTest
public void testCheckPreview() throws Exception {
initializeMessageLooper();
mCamera.setPreviewCallback(mRawPreviewCallback);
checkPreviewCallback();
terminateMessageLooper();
assertTrue("RawPreviewCallbackResult", rawPreviewCallbackResult);
}
}