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