Home | History | Annotate | Download | only in media
      1 /*
      2  * Copyright (C) 2007 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 android.media;
     18 
     19 import android.hardware.Camera;
     20 import android.os.Handler;
     21 import android.os.Looper;
     22 import android.os.Message;
     23 import android.util.Log;
     24 import android.view.Surface;
     25 
     26 import java.io.FileDescriptor;
     27 import java.io.FileOutputStream;
     28 import java.io.IOException;
     29 import java.lang.ref.WeakReference;
     30 
     31 /**
     32  * Used to record audio and video. The recording control is based on a
     33  * simple state machine (see below).
     34  *
     35  * <p><img src="{@docRoot}images/mediarecorder_state_diagram.gif" border="0" />
     36  * </p>
     37  *
     38  * <p>A common case of using MediaRecorder to record audio works as follows:
     39  *
     40  * <pre>MediaRecorder recorder = new MediaRecorder();
     41  * recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
     42  * recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
     43  * recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
     44  * recorder.setOutputFile(PATH_NAME);
     45  * recorder.prepare();
     46  * recorder.start();   // Recording is now started
     47  * ...
     48  * recorder.stop();
     49  * recorder.reset();   // You can reuse the object by going back to setAudioSource() step
     50  * recorder.release(); // Now the object cannot be reused
     51  * </pre>
     52  *
     53  * <p>Applications may want to register for informational and error
     54  * events in order to be informed of some internal update and possible
     55  * runtime errors during recording. Registration for such events is
     56  * done by setting the appropriate listeners (via calls
     57  * (to {@link #setOnInfoListener(OnInfoListener)}setOnInfoListener and/or
     58  * {@link #setOnErrorListener(OnErrorListener)}setOnErrorListener).
     59  * In order to receive the respective callback associated with these listeners,
     60  * applications are required to create MediaRecorder objects on threads with a
     61  * Looper running (the main UI thread by default already has a Looper running).
     62  *
     63  * <p><strong>Note:</strong> Currently, MediaRecorder does not work on the emulator.
     64  *
     65  * <div class="special reference">
     66  * <h3>Developer Guides</h3>
     67  * <p>For more information about how to use MediaRecorder for recording video, read the
     68  * <a href="{@docRoot}guide/topics/media/camera.html#capture-video">Camera</a> developer guide.
     69  * For more information about how to use MediaRecorder for recording sound, read the
     70  * <a href="{@docRoot}guide/topics/media/audio-capture.html">Audio Capture</a> developer guide.</p>
     71  * </div>
     72  */
     73 public class MediaRecorder
     74 {
     75     static {
     76         System.loadLibrary("media_jni");
     77         native_init();
     78     }
     79     private final static String TAG = "MediaRecorder";
     80 
     81     // The two fields below are accessed by native methods
     82     @SuppressWarnings("unused")
     83     private int mNativeContext;
     84 
     85     @SuppressWarnings("unused")
     86     private Surface mSurface;
     87 
     88     private String mPath;
     89     private FileDescriptor mFd;
     90     private EventHandler mEventHandler;
     91     private OnErrorListener mOnErrorListener;
     92     private OnInfoListener mOnInfoListener;
     93 
     94     /**
     95      * Default constructor.
     96      */
     97     public MediaRecorder() {
     98 
     99         Looper looper;
    100         if ((looper = Looper.myLooper()) != null) {
    101             mEventHandler = new EventHandler(this, looper);
    102         } else if ((looper = Looper.getMainLooper()) != null) {
    103             mEventHandler = new EventHandler(this, looper);
    104         } else {
    105             mEventHandler = null;
    106         }
    107 
    108         /* Native setup requires a weak reference to our object.
    109          * It's easier to create it here than in C++.
    110          */
    111         native_setup(new WeakReference<MediaRecorder>(this));
    112     }
    113 
    114     /**
    115      * Sets a Camera to use for recording. Use this function to switch
    116      * quickly between preview and capture mode without a teardown of
    117      * the camera object. {@link android.hardware.Camera#unlock()} should be
    118      * called before this. Must call before prepare().
    119      *
    120      * @param c the Camera to use for recording
    121      */
    122     public native void setCamera(Camera c);
    123 
    124     /**
    125      * Sets a Surface to show a preview of recorded media (video). Calls this
    126      * before prepare() to make sure that the desirable preview display is
    127      * set. If {@link #setCamera(Camera)} is used and the surface has been
    128      * already set to the camera, application do not need to call this. If
    129      * this is called with non-null surface, the preview surface of the camera
    130      * will be replaced by the new surface. If this method is called with null
    131      * surface or not called at all, media recorder will not change the preview
    132      * surface of the camera.
    133      *
    134      * @param sv the Surface to use for the preview
    135      * @see android.hardware.Camera#setPreviewDisplay(android.view.SurfaceHolder)
    136      */
    137     public void setPreviewDisplay(Surface sv) {
    138         mSurface = sv;
    139     }
    140 
    141     /**
    142      * Defines the audio source. These constants are used with
    143      * {@link MediaRecorder#setAudioSource(int)}.
    144      */
    145     public final class AudioSource {
    146       /* Do not change these values without updating their counterparts
    147        * in system/core/include/system/audio.h!
    148        */
    149         private AudioSource() {}
    150 
    151         /** Default audio source **/
    152         public static final int DEFAULT = 0;
    153 
    154         /** Microphone audio source */
    155         public static final int MIC = 1;
    156 
    157         /** Voice call uplink (Tx) audio source */
    158         public static final int VOICE_UPLINK = 2;
    159 
    160         /** Voice call downlink (Rx) audio source */
    161         public static final int VOICE_DOWNLINK = 3;
    162 
    163         /** Voice call uplink + downlink audio source */
    164         public static final int VOICE_CALL = 4;
    165 
    166         /** Microphone audio source with same orientation as camera if available, the main
    167          *  device microphone otherwise */
    168         public static final int CAMCORDER = 5;
    169 
    170         /** Microphone audio source tuned for voice recognition if available, behaves like
    171          *  {@link #DEFAULT} otherwise. */
    172         public static final int VOICE_RECOGNITION = 6;
    173 
    174         /** Microphone audio source tuned for voice communications such as VoIP. It
    175          *  will for instance take advantage of echo cancellation or automatic gain control
    176          *  if available. It otherwise behaves like {@link #DEFAULT} if no voice processing
    177          *  is applied.
    178          */
    179         public static final int VOICE_COMMUNICATION = 7;
    180     }
    181 
    182     /**
    183      * Defines the video source. These constants are used with
    184      * {@link MediaRecorder#setVideoSource(int)}.
    185      */
    186     public final class VideoSource {
    187       /* Do not change these values without updating their counterparts
    188        * in include/media/mediarecorder.h!
    189        */
    190         private VideoSource() {}
    191         public static final int DEFAULT = 0;
    192         /** Camera video source */
    193         public static final int CAMERA = 1;
    194         /** @hide */
    195         public static final int GRALLOC_BUFFER = 2;
    196     }
    197 
    198     /**
    199      * Defines the output format. These constants are used with
    200      * {@link MediaRecorder#setOutputFormat(int)}.
    201      */
    202     public final class OutputFormat {
    203       /* Do not change these values without updating their counterparts
    204        * in include/media/mediarecorder.h!
    205        */
    206         private OutputFormat() {}
    207         public static final int DEFAULT = 0;
    208         /** 3GPP media file format*/
    209         public static final int THREE_GPP = 1;
    210         /** MPEG4 media file format*/
    211         public static final int MPEG_4 = 2;
    212 
    213         /** The following formats are audio only .aac or .amr formats */
    214 
    215         /**
    216          * AMR NB file format
    217          * @deprecated  Deprecated in favor of MediaRecorder.OutputFormat.AMR_NB
    218          */
    219         public static final int RAW_AMR = 3;
    220 
    221         /** AMR NB file format */
    222         public static final int AMR_NB = 3;
    223 
    224         /** AMR WB file format */
    225         public static final int AMR_WB = 4;
    226 
    227         /** @hide AAC ADIF file format */
    228         public static final int AAC_ADIF = 5;
    229 
    230         /** AAC ADTS file format */
    231         public static final int AAC_ADTS = 6;
    232 
    233         /** @hide Stream over a socket, limited to a single stream */
    234         public static final int OUTPUT_FORMAT_RTP_AVP = 7;
    235 
    236         /** @hide H.264/AAC data encapsulated in MPEG2/TS */
    237         public static final int OUTPUT_FORMAT_MPEG2TS = 8;
    238     };
    239 
    240     /**
    241      * Defines the audio encoding. These constants are used with
    242      * {@link MediaRecorder#setAudioEncoder(int)}.
    243      */
    244     public final class AudioEncoder {
    245       /* Do not change these values without updating their counterparts
    246        * in include/media/mediarecorder.h!
    247        */
    248         private AudioEncoder() {}
    249         public static final int DEFAULT = 0;
    250         /** AMR (Narrowband) audio codec */
    251         public static final int AMR_NB = 1;
    252         /** AMR (Wideband) audio codec */
    253         public static final int AMR_WB = 2;
    254         /** AAC Low Complexity (AAC-LC) audio codec */
    255         public static final int AAC = 3;
    256         /** High Efficiency AAC (HE-AAC) audio codec */
    257         public static final int HE_AAC = 4;
    258         /** Enhanced Low Delay AAC (AAC-ELD) audio codec */
    259         public static final int AAC_ELD = 5;
    260     }
    261 
    262     /**
    263      * Defines the video encoding. These constants are used with
    264      * {@link MediaRecorder#setVideoEncoder(int)}.
    265      */
    266     public final class VideoEncoder {
    267       /* Do not change these values without updating their counterparts
    268        * in include/media/mediarecorder.h!
    269        */
    270         private VideoEncoder() {}
    271         public static final int DEFAULT = 0;
    272         public static final int H263 = 1;
    273         public static final int H264 = 2;
    274         public static final int MPEG_4_SP = 3;
    275     }
    276 
    277     /**
    278      * Sets the audio source to be used for recording. If this method is not
    279      * called, the output file will not contain an audio track. The source needs
    280      * to be specified before setting recording-parameters or encoders. Call
    281      * this only before setOutputFormat().
    282      *
    283      * @param audio_source the audio source to use
    284      * @throws IllegalStateException if it is called after setOutputFormat()
    285      * @see android.media.MediaRecorder.AudioSource
    286      */
    287     public native void setAudioSource(int audio_source)
    288             throws IllegalStateException;
    289 
    290     /**
    291      * Gets the maximum value for audio sources.
    292      * @see android.media.MediaRecorder.AudioSource
    293      */
    294     public static final int getAudioSourceMax() { return AudioSource.VOICE_COMMUNICATION; }
    295 
    296     /**
    297      * Sets the video source to be used for recording. If this method is not
    298      * called, the output file will not contain an video track. The source needs
    299      * to be specified before setting recording-parameters or encoders. Call
    300      * this only before setOutputFormat().
    301      *
    302      * @param video_source the video source to use
    303      * @throws IllegalStateException if it is called after setOutputFormat()
    304      * @see android.media.MediaRecorder.VideoSource
    305      */
    306     public native void setVideoSource(int video_source)
    307             throws IllegalStateException;
    308 
    309     /**
    310      * Uses the settings from a CamcorderProfile object for recording. This method should
    311      * be called after the video AND audio sources are set, and before setOutputFile().
    312      * If a time lapse CamcorderProfile is used, audio related source or recording
    313      * parameters are ignored.
    314      *
    315      * @param profile the CamcorderProfile to use
    316      * @see android.media.CamcorderProfile
    317      */
    318     public void setProfile(CamcorderProfile profile) {
    319         setOutputFormat(profile.fileFormat);
    320         setVideoFrameRate(profile.videoFrameRate);
    321         setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
    322         setVideoEncodingBitRate(profile.videoBitRate);
    323         setVideoEncoder(profile.videoCodec);
    324         if (profile.quality >= CamcorderProfile.QUALITY_TIME_LAPSE_LOW &&
    325              profile.quality <= CamcorderProfile.QUALITY_TIME_LAPSE_QVGA) {
    326             // Nothing needs to be done. Call to setCaptureRate() enables
    327             // time lapse video recording.
    328         } else {
    329             setAudioEncodingBitRate(profile.audioBitRate);
    330             setAudioChannels(profile.audioChannels);
    331             setAudioSamplingRate(profile.audioSampleRate);
    332             setAudioEncoder(profile.audioCodec);
    333         }
    334     }
    335 
    336     /**
    337      * Set video frame capture rate. This can be used to set a different video frame capture
    338      * rate than the recorded video's playback rate. This method also sets the recording mode
    339      * to time lapse. In time lapse video recording, only video is recorded. Audio related
    340      * parameters are ignored when a time lapse recording session starts, if an application
    341      * sets them.
    342      *
    343      * @param fps Rate at which frames should be captured in frames per second.
    344      * The fps can go as low as desired. However the fastest fps will be limited by the hardware.
    345      * For resolutions that can be captured by the video camera, the fastest fps can be computed using
    346      * {@link android.hardware.Camera.Parameters#getPreviewFpsRange(int[])}. For higher
    347      * resolutions the fastest fps may be more restrictive.
    348      * Note that the recorder cannot guarantee that frames will be captured at the
    349      * given rate due to camera/encoder limitations. However it tries to be as close as
    350      * possible.
    351      */
    352     public void setCaptureRate(double fps) {
    353         // Make sure that time lapse is enabled when this method is called.
    354         setParameter(String.format("time-lapse-enable=1"));
    355 
    356         double timeBetweenFrameCapture = 1 / fps;
    357         int timeBetweenFrameCaptureMs = (int) (1000 * timeBetweenFrameCapture);
    358         setParameter(String.format("time-between-time-lapse-frame-capture=%d",
    359                     timeBetweenFrameCaptureMs));
    360     }
    361 
    362     /**
    363      * Sets the orientation hint for output video playback.
    364      * This method should be called before prepare(). This method will not
    365      * trigger the source video frame to rotate during video recording, but to
    366      * add a composition matrix containing the rotation angle in the output
    367      * video if the output format is OutputFormat.THREE_GPP or
    368      * OutputFormat.MPEG_4 so that a video player can choose the proper
    369      * orientation for playback. Note that some video players may choose
    370      * to ignore the compostion matrix in a video during playback.
    371      *
    372      * @param degrees the angle to be rotated clockwise in degrees.
    373      * The supported angles are 0, 90, 180, and 270 degrees.
    374      * @throws IllegalArgumentException if the angle is not supported.
    375      *
    376      */
    377     public void setOrientationHint(int degrees) {
    378         if (degrees != 0   &&
    379             degrees != 90  &&
    380             degrees != 180 &&
    381             degrees != 270) {
    382             throw new IllegalArgumentException("Unsupported angle: " + degrees);
    383         }
    384         setParameter("video-param-rotation-angle-degrees=" + degrees);
    385     }
    386 
    387     /**
    388      * Set and store the geodata (latitude and longitude) in the output file.
    389      * This method should be called before prepare(). The geodata is
    390      * stored in udta box if the output format is OutputFormat.THREE_GPP
    391      * or OutputFormat.MPEG_4, and is ignored for other output formats.
    392      * The geodata is stored according to ISO-6709 standard.
    393      *
    394      * @param latitude latitude in degrees. Its value must be in the
    395      * range [-90, 90].
    396      * @param longitude longitude in degrees. Its value must be in the
    397      * range [-180, 180].
    398      *
    399      * @throws IllegalArgumentException if the given latitude or
    400      * longitude is out of range.
    401      *
    402      */
    403     public void setLocation(float latitude, float longitude) {
    404         int latitudex10000  = (int) (latitude * 10000 + 0.5);
    405         int longitudex10000 = (int) (longitude * 10000 + 0.5);
    406 
    407         if (latitudex10000 > 900000 || latitudex10000 < -900000) {
    408             String msg = "Latitude: " + latitude + " out of range.";
    409             throw new IllegalArgumentException(msg);
    410         }
    411         if (longitudex10000 > 1800000 || longitudex10000 < -1800000) {
    412             String msg = "Longitude: " + longitude + " out of range";
    413             throw new IllegalArgumentException(msg);
    414         }
    415 
    416         setParameter("param-geotag-latitude=" + latitudex10000);
    417         setParameter("param-geotag-longitude=" + longitudex10000);
    418     }
    419 
    420     /**
    421      * Sets the format of the output file produced during recording. Call this
    422      * after setAudioSource()/setVideoSource() but before prepare().
    423      *
    424      * <p>It is recommended to always use 3GP format when using the H.263
    425      * video encoder and AMR audio encoder. Using an MPEG-4 container format
    426      * may confuse some desktop players.</p>
    427      *
    428      * @param output_format the output format to use. The output format
    429      * needs to be specified before setting recording-parameters or encoders.
    430      * @throws IllegalStateException if it is called after prepare() or before
    431      * setAudioSource()/setVideoSource().
    432      * @see android.media.MediaRecorder.OutputFormat
    433      */
    434     public native void setOutputFormat(int output_format)
    435             throws IllegalStateException;
    436 
    437     /**
    438      * Sets the width and height of the video to be captured.  Must be called
    439      * after setVideoSource(). Call this after setOutFormat() but before
    440      * prepare().
    441      *
    442      * @param width the width of the video to be captured
    443      * @param height the height of the video to be captured
    444      * @throws IllegalStateException if it is called after
    445      * prepare() or before setOutputFormat()
    446      */
    447     public native void setVideoSize(int width, int height)
    448             throws IllegalStateException;
    449 
    450     /**
    451      * Sets the frame rate of the video to be captured.  Must be called
    452      * after setVideoSource(). Call this after setOutFormat() but before
    453      * prepare().
    454      *
    455      * @param rate the number of frames per second of video to capture
    456      * @throws IllegalStateException if it is called after
    457      * prepare() or before setOutputFormat().
    458      *
    459      * NOTE: On some devices that have auto-frame rate, this sets the
    460      * maximum frame rate, not a constant frame rate. Actual frame rate
    461      * will vary according to lighting conditions.
    462      */
    463     public native void setVideoFrameRate(int rate) throws IllegalStateException;
    464 
    465     /**
    466      * Sets the maximum duration (in ms) of the recording session.
    467      * Call this after setOutFormat() but before prepare().
    468      * After recording reaches the specified duration, a notification
    469      * will be sent to the {@link android.media.MediaRecorder.OnInfoListener}
    470      * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED}
    471      * and recording will be stopped. Stopping happens asynchronously, there
    472      * is no guarantee that the recorder will have stopped by the time the
    473      * listener is notified.
    474      *
    475      * @param max_duration_ms the maximum duration in ms (if zero or negative, disables the duration limit)
    476      *
    477      */
    478     public native void setMaxDuration(int max_duration_ms) throws IllegalArgumentException;
    479 
    480     /**
    481      * Sets the maximum filesize (in bytes) of the recording session.
    482      * Call this after setOutFormat() but before prepare().
    483      * After recording reaches the specified filesize, a notification
    484      * will be sent to the {@link android.media.MediaRecorder.OnInfoListener}
    485      * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}
    486      * and recording will be stopped. Stopping happens asynchronously, there
    487      * is no guarantee that the recorder will have stopped by the time the
    488      * listener is notified.
    489      *
    490      * @param max_filesize_bytes the maximum filesize in bytes (if zero or negative, disables the limit)
    491      *
    492      */
    493     public native void setMaxFileSize(long max_filesize_bytes) throws IllegalArgumentException;
    494 
    495     /**
    496      * Sets the audio encoder to be used for recording. If this method is not
    497      * called, the output file will not contain an audio track. Call this after
    498      * setOutputFormat() but before prepare().
    499      *
    500      * @param audio_encoder the audio encoder to use.
    501      * @throws IllegalStateException if it is called before
    502      * setOutputFormat() or after prepare().
    503      * @see android.media.MediaRecorder.AudioEncoder
    504      */
    505     public native void setAudioEncoder(int audio_encoder)
    506             throws IllegalStateException;
    507 
    508     /**
    509      * Sets the video encoder to be used for recording. If this method is not
    510      * called, the output file will not contain an video track. Call this after
    511      * setOutputFormat() and before prepare().
    512      *
    513      * @param video_encoder the video encoder to use.
    514      * @throws IllegalStateException if it is called before
    515      * setOutputFormat() or after prepare()
    516      * @see android.media.MediaRecorder.VideoEncoder
    517      */
    518     public native void setVideoEncoder(int video_encoder)
    519             throws IllegalStateException;
    520 
    521     /**
    522      * Sets the audio sampling rate for recording. Call this method before prepare().
    523      * Prepare() may perform additional checks on the parameter to make sure whether
    524      * the specified audio sampling rate is applicable. The sampling rate really depends
    525      * on the format for the audio recording, as well as the capabilities of the platform.
    526      * For instance, the sampling rate supported by AAC audio coding standard ranges
    527      * from 8 to 96 kHz, the sampling rate supported by AMRNB is 8kHz, and the sampling
    528      * rate supported by AMRWB is 16kHz. Please consult with the related audio coding
    529      * standard for the supported audio sampling rate.
    530      *
    531      * @param samplingRate the sampling rate for audio in samples per second.
    532      */
    533     public void setAudioSamplingRate(int samplingRate) {
    534         if (samplingRate <= 0) {
    535             throw new IllegalArgumentException("Audio sampling rate is not positive");
    536         }
    537         setParameter("audio-param-sampling-rate=" + samplingRate);
    538     }
    539 
    540     /**
    541      * Sets the number of audio channels for recording. Call this method before prepare().
    542      * Prepare() may perform additional checks on the parameter to make sure whether the
    543      * specified number of audio channels are applicable.
    544      *
    545      * @param numChannels the number of audio channels. Usually it is either 1 (mono) or 2
    546      * (stereo).
    547      */
    548     public void setAudioChannels(int numChannels) {
    549         if (numChannels <= 0) {
    550             throw new IllegalArgumentException("Number of channels is not positive");
    551         }
    552         setParameter("audio-param-number-of-channels=" + numChannels);
    553     }
    554 
    555     /**
    556      * Sets the audio encoding bit rate for recording. Call this method before prepare().
    557      * Prepare() may perform additional checks on the parameter to make sure whether the
    558      * specified bit rate is applicable, and sometimes the passed bitRate will be clipped
    559      * internally to ensure the audio recording can proceed smoothly based on the
    560      * capabilities of the platform.
    561      *
    562      * @param bitRate the audio encoding bit rate in bits per second.
    563      */
    564     public void setAudioEncodingBitRate(int bitRate) {
    565         if (bitRate <= 0) {
    566             throw new IllegalArgumentException("Audio encoding bit rate is not positive");
    567         }
    568         setParameter("audio-param-encoding-bitrate=" + bitRate);
    569     }
    570 
    571     /**
    572      * Sets the video encoding bit rate for recording. Call this method before prepare().
    573      * Prepare() may perform additional checks on the parameter to make sure whether the
    574      * specified bit rate is applicable, and sometimes the passed bitRate will be
    575      * clipped internally to ensure the video recording can proceed smoothly based on
    576      * the capabilities of the platform.
    577      *
    578      * @param bitRate the video encoding bit rate in bits per second.
    579      */
    580     public void setVideoEncodingBitRate(int bitRate) {
    581         if (bitRate <= 0) {
    582             throw new IllegalArgumentException("Video encoding bit rate is not positive");
    583         }
    584         setParameter("video-param-encoding-bitrate=" + bitRate);
    585     }
    586 
    587     /**
    588      * Currently not implemented. It does nothing.
    589      * @deprecated Time lapse mode video recording using camera still image capture
    590      * is not desirable, and will not be supported.
    591      * @hide
    592      */
    593     public void setAuxiliaryOutputFile(FileDescriptor fd)
    594     {
    595         Log.w(TAG, "setAuxiliaryOutputFile(FileDescriptor) is no longer supported.");
    596     }
    597 
    598     /**
    599      * Currently not implemented. It does nothing.
    600      * @deprecated Time lapse mode video recording using camera still image capture
    601      * is not desirable, and will not be supported.
    602      * @hide
    603      */
    604     public void setAuxiliaryOutputFile(String path)
    605     {
    606         Log.w(TAG, "setAuxiliaryOutputFile(String) is no longer supported.");
    607     }
    608 
    609     /**
    610      * Pass in the file descriptor of the file to be written. Call this after
    611      * setOutputFormat() but before prepare().
    612      *
    613      * @param fd an open file descriptor to be written into.
    614      * @throws IllegalStateException if it is called before
    615      * setOutputFormat() or after prepare()
    616      */
    617     public void setOutputFile(FileDescriptor fd) throws IllegalStateException
    618     {
    619         mPath = null;
    620         mFd = fd;
    621     }
    622 
    623     /**
    624      * Sets the path of the output file to be produced. Call this after
    625      * setOutputFormat() but before prepare().
    626      *
    627      * @param path The pathname to use.
    628      * @throws IllegalStateException if it is called before
    629      * setOutputFormat() or after prepare()
    630      */
    631     public void setOutputFile(String path) throws IllegalStateException
    632     {
    633         mFd = null;
    634         mPath = path;
    635     }
    636 
    637     // native implementation
    638     private native void _setOutputFile(FileDescriptor fd, long offset, long length)
    639         throws IllegalStateException, IOException;
    640     private native void _prepare() throws IllegalStateException, IOException;
    641 
    642     /**
    643      * Prepares the recorder to begin capturing and encoding data. This method
    644      * must be called after setting up the desired audio and video sources,
    645      * encoders, file format, etc., but before start().
    646      *
    647      * @throws IllegalStateException if it is called after
    648      * start() or before setOutputFormat().
    649      * @throws IOException if prepare fails otherwise.
    650      */
    651     public void prepare() throws IllegalStateException, IOException
    652     {
    653         if (mPath != null) {
    654             FileOutputStream fos = new FileOutputStream(mPath);
    655             try {
    656                 _setOutputFile(fos.getFD(), 0, 0);
    657             } finally {
    658                 fos.close();
    659             }
    660         } else if (mFd != null) {
    661             _setOutputFile(mFd, 0, 0);
    662         } else {
    663             throw new IOException("No valid output file");
    664         }
    665 
    666         _prepare();
    667     }
    668 
    669     /**
    670      * Begins capturing and encoding data to the file specified with
    671      * setOutputFile(). Call this after prepare().
    672      *
    673      * <p>Since API level 13, if applications set a camera via
    674      * {@link #setCamera(Camera)}, the apps can use the camera after this method
    675      * call. The apps do not need to lock the camera again. However, if this
    676      * method fails, the apps should still lock the camera back. The apps should
    677      * not start another recording session during recording.
    678      *
    679      * @throws IllegalStateException if it is called before
    680      * prepare().
    681      */
    682     public native void start() throws IllegalStateException;
    683 
    684     /**
    685      * Stops recording. Call this after start(). Once recording is stopped,
    686      * you will have to configure it again as if it has just been constructed.
    687      * Note that a RuntimeException is intentionally thrown to the
    688      * application, if no valid audio/video data has been received when stop()
    689      * is called. This happens if stop() is called immediately after
    690      * start(). The failure lets the application take action accordingly to
    691      * clean up the output file (delete the output file, for instance), since
    692      * the output file is not properly constructed when this happens.
    693      *
    694      * @throws IllegalStateException if it is called before start()
    695      */
    696     public native void stop() throws IllegalStateException;
    697 
    698     /**
    699      * Restarts the MediaRecorder to its idle state. After calling
    700      * this method, you will have to configure it again as if it had just been
    701      * constructed.
    702      */
    703     public void reset() {
    704         native_reset();
    705 
    706         // make sure none of the listeners get called anymore
    707         mEventHandler.removeCallbacksAndMessages(null);
    708     }
    709 
    710     private native void native_reset();
    711 
    712     /**
    713      * Returns the maximum absolute amplitude that was sampled since the last
    714      * call to this method. Call this only after the setAudioSource().
    715      *
    716      * @return the maximum absolute amplitude measured since the last call, or
    717      * 0 when called for the first time
    718      * @throws IllegalStateException if it is called before
    719      * the audio source has been set.
    720      */
    721     public native int getMaxAmplitude() throws IllegalStateException;
    722 
    723     /* Do not change this value without updating its counterpart
    724      * in include/media/mediarecorder.h!
    725      */
    726     /** Unspecified media recorder error.
    727      * @see android.media.MediaRecorder.OnErrorListener
    728      */
    729     public static final int MEDIA_RECORDER_ERROR_UNKNOWN = 1;
    730 
    731     /**
    732      * Interface definition for a callback to be invoked when an error
    733      * occurs while recording.
    734      */
    735     public interface OnErrorListener
    736     {
    737         /**
    738          * Called when an error occurs while recording.
    739          *
    740          * @param mr the MediaRecorder that encountered the error
    741          * @param what    the type of error that has occurred:
    742          * <ul>
    743          * <li>{@link #MEDIA_RECORDER_ERROR_UNKNOWN}
    744          * </ul>
    745          * @param extra   an extra code, specific to the error type
    746          */
    747         void onError(MediaRecorder mr, int what, int extra);
    748     }
    749 
    750     /**
    751      * Register a callback to be invoked when an error occurs while
    752      * recording.
    753      *
    754      * @param l the callback that will be run
    755      */
    756     public void setOnErrorListener(OnErrorListener l)
    757     {
    758         mOnErrorListener = l;
    759     }
    760 
    761     /* Do not change these values without updating their counterparts
    762      * in include/media/mediarecorder.h!
    763      */
    764     /** Unspecified media recorder error.
    765      * @see android.media.MediaRecorder.OnInfoListener
    766      */
    767     public static final int MEDIA_RECORDER_INFO_UNKNOWN              = 1;
    768     /** A maximum duration had been setup and has now been reached.
    769      * @see android.media.MediaRecorder.OnInfoListener
    770      */
    771     public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800;
    772     /** A maximum filesize had been setup and has now been reached.
    773      * @see android.media.MediaRecorder.OnInfoListener
    774      */
    775     public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801;
    776 
    777     /** informational events for individual tracks, for testing purpose.
    778      * The track informational event usually contains two parts in the ext1
    779      * arg of the onInfo() callback: bit 31-28 contains the track id; and
    780      * the rest of the 28 bits contains the informational event defined here.
    781      * For example, ext1 = (1 << 28 | MEDIA_RECORDER_TRACK_INFO_TYPE) if the
    782      * track id is 1 for informational event MEDIA_RECORDER_TRACK_INFO_TYPE;
    783      * while ext1 = (0 << 28 | MEDIA_RECORDER_TRACK_INFO_TYPE) if the track
    784      * id is 0 for informational event MEDIA_RECORDER_TRACK_INFO_TYPE. The
    785      * application should extract the track id and the type of informational
    786      * event from ext1, accordingly.
    787      *
    788      * FIXME:
    789      * Please update the comment for onInfo also when these
    790      * events are unhidden so that application knows how to extract the track
    791      * id and the informational event type from onInfo callback.
    792      *
    793      * {@hide}
    794      */
    795     public static final int MEDIA_RECORDER_TRACK_INFO_LIST_START        = 1000;
    796     /** Signal the completion of the track for the recording session.
    797      * {@hide}
    798      */
    799     public static final int MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS = 1000;
    800     /** Indicate the recording progress in time (ms) during recording.
    801      * {@hide}
    802      */
    803     public static final int MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME  = 1001;
    804     /** Indicate the track type: 0 for Audio and 1 for Video.
    805      * {@hide}
    806      */
    807     public static final int MEDIA_RECORDER_TRACK_INFO_TYPE              = 1002;
    808     /** Provide the track duration information.
    809      * {@hide}
    810      */
    811     public static final int MEDIA_RECORDER_TRACK_INFO_DURATION_MS       = 1003;
    812     /** Provide the max chunk duration in time (ms) for the given track.
    813      * {@hide}
    814      */
    815     public static final int MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS  = 1004;
    816     /** Provide the total number of recordd frames.
    817      * {@hide}
    818      */
    819     public static final int MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES    = 1005;
    820     /** Provide the max spacing between neighboring chunks for the given track.
    821      * {@hide}
    822      */
    823     public static final int MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS    = 1006;
    824     /** Provide the elapsed time measuring from the start of the recording
    825      * till the first output frame of the given track is received, excluding
    826      * any intentional start time offset of a recording session for the
    827      * purpose of eliminating the recording sound in the recorded file.
    828      * {@hide}
    829      */
    830     public static final int MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS  = 1007;
    831     /** Provide the start time difference (delay) betweeen this track and
    832      * the start of the movie.
    833      * {@hide}
    834      */
    835     public static final int MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS   = 1008;
    836     /** Provide the total number of data (in kilo-bytes) encoded.
    837      * {@hide}
    838      */
    839     public static final int MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES       = 1009;
    840     /**
    841      * {@hide}
    842      */
    843     public static final int MEDIA_RECORDER_TRACK_INFO_LIST_END          = 2000;
    844 
    845 
    846     /**
    847      * Interface definition for a callback to be invoked when an error
    848      * occurs while recording.
    849      */
    850     public interface OnInfoListener
    851     {
    852         /**
    853          * Called when an error occurs while recording.
    854          *
    855          * @param mr the MediaRecorder that encountered the error
    856          * @param what    the type of error that has occurred:
    857          * <ul>
    858          * <li>{@link #MEDIA_RECORDER_INFO_UNKNOWN}
    859          * <li>{@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED}
    860          * <li>{@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}
    861          * </ul>
    862          * @param extra   an extra code, specific to the error type
    863          */
    864         void onInfo(MediaRecorder mr, int what, int extra);
    865     }
    866 
    867     /**
    868      * Register a callback to be invoked when an informational event occurs while
    869      * recording.
    870      *
    871      * @param listener the callback that will be run
    872      */
    873     public void setOnInfoListener(OnInfoListener listener)
    874     {
    875         mOnInfoListener = listener;
    876     }
    877 
    878     private class EventHandler extends Handler
    879     {
    880         private MediaRecorder mMediaRecorder;
    881 
    882         public EventHandler(MediaRecorder mr, Looper looper) {
    883             super(looper);
    884             mMediaRecorder = mr;
    885         }
    886 
    887         /* Do not change these values without updating their counterparts
    888          * in include/media/mediarecorder.h!
    889          */
    890         private static final int MEDIA_RECORDER_EVENT_LIST_START = 1;
    891         private static final int MEDIA_RECORDER_EVENT_ERROR      = 1;
    892         private static final int MEDIA_RECORDER_EVENT_INFO       = 2;
    893         private static final int MEDIA_RECORDER_EVENT_LIST_END   = 99;
    894 
    895         /* Events related to individual tracks */
    896         private static final int MEDIA_RECORDER_TRACK_EVENT_LIST_START = 100;
    897         private static final int MEDIA_RECORDER_TRACK_EVENT_ERROR      = 100;
    898         private static final int MEDIA_RECORDER_TRACK_EVENT_INFO       = 101;
    899         private static final int MEDIA_RECORDER_TRACK_EVENT_LIST_END   = 1000;
    900 
    901 
    902         @Override
    903         public void handleMessage(Message msg) {
    904             if (mMediaRecorder.mNativeContext == 0) {
    905                 Log.w(TAG, "mediarecorder went away with unhandled events");
    906                 return;
    907             }
    908             switch(msg.what) {
    909             case MEDIA_RECORDER_EVENT_ERROR:
    910             case MEDIA_RECORDER_TRACK_EVENT_ERROR:
    911                 if (mOnErrorListener != null)
    912                     mOnErrorListener.onError(mMediaRecorder, msg.arg1, msg.arg2);
    913 
    914                 return;
    915 
    916             case MEDIA_RECORDER_EVENT_INFO:
    917             case MEDIA_RECORDER_TRACK_EVENT_INFO:
    918                 if (mOnInfoListener != null)
    919                     mOnInfoListener.onInfo(mMediaRecorder, msg.arg1, msg.arg2);
    920 
    921                 return;
    922 
    923             default:
    924                 Log.e(TAG, "Unknown message type " + msg.what);
    925                 return;
    926             }
    927         }
    928     }
    929 
    930     /**
    931      * Called from native code when an interesting event happens.  This method
    932      * just uses the EventHandler system to post the event back to the main app thread.
    933      * We use a weak reference to the original MediaRecorder object so that the native
    934      * code is safe from the object disappearing from underneath it.  (This is
    935      * the cookie passed to native_setup().)
    936      */
    937     private static void postEventFromNative(Object mediarecorder_ref,
    938                                             int what, int arg1, int arg2, Object obj)
    939     {
    940         MediaRecorder mr = (MediaRecorder)((WeakReference)mediarecorder_ref).get();
    941         if (mr == null) {
    942             return;
    943         }
    944 
    945         if (mr.mEventHandler != null) {
    946             Message m = mr.mEventHandler.obtainMessage(what, arg1, arg2, obj);
    947             mr.mEventHandler.sendMessage(m);
    948         }
    949     }
    950 
    951     /**
    952      * Releases resources associated with this MediaRecorder object.
    953      * It is good practice to call this method when you're done
    954      * using the MediaRecorder. In particular, whenever an Activity
    955      * of an application is paused (its onPause() method is called),
    956      * or stopped (its onStop() method is called), this method should be
    957      * invoked to release the MediaRecorder object, unless the application
    958      * has a special need to keep the object around. In addition to
    959      * unnecessary resources (such as memory and instances of codecs)
    960      * being held, failure to call this method immediately if a
    961      * MediaRecorder object is no longer needed may also lead to
    962      * continuous battery consumption for mobile devices, and recording
    963      * failure for other applications if no multiple instances of the
    964      * same codec are supported on a device. Even if multiple instances
    965      * of the same codec are supported, some performance degradation
    966      * may be expected when unnecessary multiple instances are used
    967      * at the same time.
    968      */
    969     public native void release();
    970 
    971     private static native final void native_init();
    972 
    973     private native final void native_setup(Object mediarecorder_this) throws IllegalStateException;
    974 
    975     private native final void native_finalize();
    976 
    977     private native void setParameter(String nameValuePair);
    978 
    979     @Override
    980     protected void finalize() { native_finalize(); }
    981 }
    982