import android.util.Log;
import android.view.SurfaceHolder;
+import android.os.ConditionVariable;
import android.os.Looper;
import android.test.suitebuilder.annotation.LargeTest;
private boolean mInitialized = false;
private Looper mLooper = null;
- private final Object lock = new Object();
- private final Object previewDone = new Object();
+ private final ConditionVariable mPreviewDone = new ConditionVariable();
+ private final ConditionVariable mSnapshotDone = new ConditionVariable();
Camera mCamera;
Context mContext;
* receive the callback messages.
*/
private void initializeMessageLooper() {
+ final ConditionVariable startDone = new ConditionVariable();
Log.v(TAG, "start looper");
new Thread() {
@Override
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();
- synchronized (lock) {
- mInitialized = true;
- lock.notify();
- }
+ mLooper = Looper.myLooper();
+ mCamera = Camera.open();
+ 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() {
+ private void terminateMessageLooper() throws Exception {
mLooper.quit();
- //TODO yslau : take out the sleep until bug#1693519 fix
- try {
- Thread.sleep(1000);
- } catch (Exception e){
- Log.v(TAG, e.toString());
- }
+ // 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();
}
} else {
rawPreviewCallbackResult = false;
}
- synchronized (previewDone) {
- Log.v(TAG, "notify the preview callback");
- previewDone.notify();
- }
-
+ mPreviewDone.open();
Log.v(TAG, "Preview callback stop");
}
};
//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;
- //if (rawData != null) {
- // rawPictureCallbackResult = true;
- //} else {
- // rawPictureCallbackResult = false;
- //}
+ // no support for raw data - success if we get the callback
+ rawPictureCallbackResult = true;
Log.v(TAG, "RawPictureCallback callback");
}
};
} 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 {
mCamera.setPreviewDisplay(mSurfaceHolder);
Log.v(TAG, "Start preview");
mCamera.startPreview();
- synchronized (previewDone) {
- try {
- previewDone.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
- Log.v(TAG, "Preview Done");
- } catch (Exception e) {
- Log.v(TAG, "wait was interrupted.");
- }
- }
+ waitForPreviewDone();
mCamera.setPreviewCallback(null);
mCamera.takePicture(mShutterCallback, mRawPictureCallback, mJpegPictureCallback);
- Thread.sleep(MediaNames.WAIT_SNAPSHOT_TIME);
+ waitForSnapshotDone();
} catch (Exception e) {
Log.v(TAG, e.toString());
}
mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
mCamera.setPreviewDisplay(mSurfaceHolder);
Log.v(TAG, "start preview");
- mCamera.startPreview();
- synchronized (previewDone) {
- try {
- previewDone.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
- Log.v(TAG, "setPreview done");
- } catch (Exception e) {
- Log.v(TAG, "wait was interrupted.");
- }
- }
+ mCamera.startPreview();
+ waitForPreviewDone();
mCamera.setPreviewCallback(null);
} catch (Exception e) {
Log.v(TAG, e.toString());
*/
@LargeTest
public void testTakePicture() throws Exception {
- synchronized (lock) {
- initializeMessageLooper();
- try {
- lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
- } catch(Exception e) {
- Log.v(TAG, "runTestOnMethod: wait was interrupted.");
- }
- }
+ initializeMessageLooper();
mCamera.setPreviewCallback(mRawPreviewCallback);
checkTakePicture();
terminateMessageLooper();
*/
@LargeTest
public void testCheckPreview() throws Exception {
- synchronized (lock) {
- initializeMessageLooper();
- try {
- lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
- } catch(Exception e) {
- Log.v(TAG, "wait was interrupted.");
- }
- }
+ initializeMessageLooper();
mCamera.setPreviewCallback(mRawPreviewCallback);
checkPreviewCallback();
terminateMessageLooper();
import android.hardware.Camera.PreviewCallback;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
+import android.os.ConditionVariable;
import android.os.Looper;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase;
private static int mStartPid = 0;
private static int mEndPid = 0;
- private boolean mInitialized = false;
private Looper mLooper = null;
private RawPreviewCallback mRawPreviewCallback = new RawPreviewCallback();
- private final Object lock = new Object();
- private final Object previewDone = new Object();
+ private final ConditionVariable mPreviewDone = new ConditionVariable();
private static int WAIT_FOR_COMMAND_TO_COMPLETE = 10000; // Milliseconds.
//the tolerant memory leak
}
private void initializeMessageLooper() {
+ final ConditionVariable startDone = new ConditionVariable();
new Thread() {
@Override
public void run() {
Log.v(TAG, "start loopRun");
mLooper = Looper.myLooper();
mCamera = Camera.open();
- synchronized (lock) {
- mInitialized = true;
- lock.notify();
- }
+ startDone.open();
Looper.loop();
Log.v(TAG, "initializeMessageLooper: quit.");
}
}.start();
- }
- private void terminateMessageLooper() {
- try {
- mLooper.quit();
- mCamera.release();
- Thread.sleep(1500);
- } catch (Exception e) {
- Log.v(TAG, e.toString());
+ if (!startDone.block(WAIT_FOR_COMMAND_TO_COMPLETE)) {
+ fail("initializeMessageLooper: start timeout");
}
}
+ 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();
+ }
+
private final class RawPreviewCallback implements PreviewCallback {
public void onPreviewFrame(byte[] rawData, Camera camera) {
- synchronized (previewDone) {
- previewDone.notify();
- }
+ mPreviewDone.open();
}
}
+ private void waitForPreviewDone() {
+ if (!mPreviewDone.block(WAIT_FOR_COMMAND_TO_COMPLETE)) {
+ Log.v(TAG, "waitForPreviewDone: timeout");
+ }
+ mPreviewDone.close();
+ }
+
public void stressCameraPreview() {
try {
- synchronized (lock) {
- initializeMessageLooper();
- try {
- lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
- } catch (Exception e) {
- Log.v(TAG, "runTestOnMethod: wait was interrupted.");
- }
- }
+ initializeMessageLooper();
mCamera.setPreviewCallback(mRawPreviewCallback);
mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
- synchronized (previewDone) {
- try {
- previewDone.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
- Log.v(TAG, "Preview Done");
- } catch (Exception e) {
- Log.v(TAG, "wait was interrupted.");
- }
- }
+ waitForPreviewDone();
Thread.sleep(1000);
mCamera.stopPreview();
terminateMessageLooper();