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.annotation.NonNull;
     20 import android.annotation.SystemApi;
     21 import android.app.ActivityThread;
     22 import android.hardware.Camera;
     23 import android.os.Bundle;
     24 import android.os.Handler;
     25 import android.os.Looper;
     26 import android.os.Message;
     27 import android.os.PersistableBundle;
     28 import android.util.Log;
     29 import android.view.Surface;
     30 
     31 import java.io.File;
     32 import java.io.FileDescriptor;
     33 import java.io.IOException;
     34 import java.io.RandomAccessFile;
     35 import java.lang.ref.WeakReference;
     36 
     37 /**
     38  * Used to record audio and video. The recording control is based on a
     39  * simple state machine (see below).
     40  *
     41  * <p><img src="{@docRoot}images/mediarecorder_state_diagram.gif" border="0" />
     42  * </p>
     43  *
     44  * <p>A common case of using MediaRecorder to record audio works as follows:
     45  *
     46  * <pre>MediaRecorder recorder = new MediaRecorder();
     47  * recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
     48  * recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
     49  * recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
     50  * recorder.setOutputFile(PATH_NAME);
     51  * recorder.prepare();
     52  * recorder.start();   // Recording is now started
     53  * ...
     54  * recorder.stop();
     55  * recorder.reset();   // You can reuse the object by going back to setAudioSource() step
     56  * recorder.release(); // Now the object cannot be reused
     57  * </pre>
     58  *
     59  * <p>Applications may want to register for informational and error
     60  * events in order to be informed of some internal update and possible
     61  * runtime errors during recording. Registration for such events is
     62  * done by setting the appropriate listeners (via calls
     63  * (to {@link #setOnInfoListener(OnInfoListener)}setOnInfoListener and/or
     64  * {@link #setOnErrorListener(OnErrorListener)}setOnErrorListener).
     65  * In order to receive the respective callback associated with these listeners,
     66  * applications are required to create MediaRecorder objects on threads with a
     67  * Looper running (the main UI thread by default already has a Looper running).
     68  *
     69  * <p><strong>Note:</strong> Currently, MediaRecorder does not work on the emulator.
     70  *
     71  * <div class="special reference">
     72  * <h3>Developer Guides</h3>
     73  * <p>For more information about how to use MediaRecorder for recording video, read the
     74  * <a href="{@docRoot}guide/topics/media/camera.html#capture-video">Camera</a> developer guide.
     75  * For more information about how to use MediaRecorder for recording sound, read the
     76  * <a href="{@docRoot}guide/topics/media/audio-capture.html">Audio Capture</a> developer guide.</p>
     77  * </div>
     78  */
     79 public class MediaRecorder
     80 {
     81     static {
     82         System.loadLibrary("media_jni");
     83         native_init();
     84     }
     85     private final static String TAG = "MediaRecorder";
     86 
     87     // The two fields below are accessed by native methods
     88     @SuppressWarnings("unused")
     89     private long mNativeContext;
     90 
     91     @SuppressWarnings("unused")
     92     private Surface mSurface;
     93 
     94     private String mPath;
     95     private FileDescriptor mFd;
     96     private File mFile;
     97     private EventHandler mEventHandler;
     98     private OnErrorListener mOnErrorListener;
     99     private OnInfoListener mOnInfoListener;
    100 
    101     /**
    102      * Default constructor.
    103      */
    104     public MediaRecorder() {
    105 
    106         Looper looper;
    107         if ((looper = Looper.myLooper()) != null) {
    108             mEventHandler = new EventHandler(this, looper);
    109         } else if ((looper = Looper.getMainLooper()) != null) {
    110             mEventHandler = new EventHandler(this, looper);
    111         } else {
    112             mEventHandler = null;
    113         }
    114 
    115         String packageName = ActivityThread.currentPackageName();
    116         /* Native setup requires a weak reference to our object.
    117          * It's easier to create it here than in C++.
    118          */
    119         native_setup(new WeakReference<MediaRecorder>(this), packageName,
    120                 ActivityThread.currentOpPackageName());
    121     }
    122 
    123     /**
    124      * Sets a {@link android.hardware.Camera} to use for recording.
    125      *
    126      * <p>Use this function to switch quickly between preview and capture mode without a teardown of
    127      * the camera object. {@link android.hardware.Camera#unlock()} should be called before
    128      * this. Must call before {@link #prepare}.</p>
    129      *
    130      * @param c the Camera to use for recording
    131      * @deprecated Use {@link #getSurface} and the {@link android.hardware.camera2} API instead.
    132      */
    133     @Deprecated
    134     public native void setCamera(Camera c);
    135 
    136     /**
    137      * Gets the surface to record from when using SURFACE video source.
    138      *
    139      * <p> May only be called after {@link #prepare}. Frames rendered to the Surface before
    140      * {@link #start} will be discarded.</p>
    141      *
    142      * @throws IllegalStateException if it is called before {@link #prepare}, after
    143      * {@link #stop}, or is called when VideoSource is not set to SURFACE.
    144      * @see android.media.MediaRecorder.VideoSource
    145      */
    146     public native Surface getSurface();
    147 
    148     /**
    149      * Configures the recorder to use a persistent surface when using SURFACE video source.
    150      * <p> May only be called before {@link #prepare}. If called, {@link #getSurface} should
    151      * not be used and will throw IllegalStateException. Frames rendered to the Surface
    152      * before {@link #start} will be discarded.</p>
    153 
    154      * @param surface a persistent input surface created by
    155      *           {@link MediaCodec#createPersistentInputSurface}
    156      * @throws IllegalStateException if it is called after {@link #prepare} and before
    157      * {@link #stop}.
    158      * @throws IllegalArgumentException if the surface was not created by
    159      *           {@link MediaCodec#createPersistentInputSurface}.
    160      * @see MediaCodec#createPersistentInputSurface
    161      * @see MediaRecorder.VideoSource
    162      */
    163     public void setInputSurface(@NonNull Surface surface) {
    164         if (!(surface instanceof MediaCodec.PersistentSurface)) {
    165             throw new IllegalArgumentException("not a PersistentSurface");
    166         }
    167         native_setInputSurface(surface);
    168     }
    169 
    170     private native final void native_setInputSurface(@NonNull Surface surface);
    171 
    172     /**
    173      * Sets a Surface to show a preview of recorded media (video). Calls this
    174      * before prepare() to make sure that the desirable preview display is
    175      * set. If {@link #setCamera(Camera)} is used and the surface has been
    176      * already set to the camera, application do not need to call this. If
    177      * this is called with non-null surface, the preview surface of the camera
    178      * will be replaced by the new surface. If this method is called with null
    179      * surface or not called at all, media recorder will not change the preview
    180      * surface of the camera.
    181      *
    182      * @param sv the Surface to use for the preview
    183      * @see android.hardware.Camera#setPreviewDisplay(android.view.SurfaceHolder)
    184      */
    185     public void setPreviewDisplay(Surface sv) {
    186         mSurface = sv;
    187     }
    188 
    189     /**
    190      * Defines the audio source.
    191      * An audio source defines both a default physical source of audio signal, and a recording
    192      * configuration. These constants are for instance used
    193      * in {@link MediaRecorder#setAudioSource(int)} or
    194      * {@link AudioRecord.Builder#setAudioSource(int)}.
    195      */
    196     public final class AudioSource {
    197 
    198         private AudioSource() {}
    199 
    200         /** @hide */
    201         public final static int AUDIO_SOURCE_INVALID = -1;
    202 
    203       /* Do not change these values without updating their counterparts
    204        * in system/media/audio/include/system/audio.h!
    205        */
    206 
    207         /** Default audio source **/
    208         public static final int DEFAULT = 0;
    209 
    210         /** Microphone audio source */
    211         public static final int MIC = 1;
    212 
    213         /** Voice call uplink (Tx) audio source.
    214          * <p>
    215          * Capturing from <code>VOICE_UPLINK</code> source requires the
    216          * {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT} permission.
    217          * This permission is reserved for use by system components and is not available to
    218          * third-party applications.
    219          * </p>
    220          */
    221         public static final int VOICE_UPLINK = 2;
    222 
    223         /** Voice call downlink (Rx) audio source.
    224          * <p>
    225          * Capturing from <code>VOICE_DOWNLINK</code> source requires the
    226          * {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT} permission.
    227          * This permission is reserved for use by system components and is not available to
    228          * third-party applications.
    229          * </p>
    230          */
    231         public static final int VOICE_DOWNLINK = 3;
    232 
    233         /** Voice call uplink + downlink audio source
    234          * <p>
    235          * Capturing from <code>VOICE_CALL</code> source requires the
    236          * {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT} permission.
    237          * This permission is reserved for use by system components and is not available to
    238          * third-party applications.
    239          * </p>
    240          */
    241         public static final int VOICE_CALL = 4;
    242 
    243         /** Microphone audio source tuned for video recording, with the same orientation
    244          *  as the camera if available. */
    245         public static final int CAMCORDER = 5;
    246 
    247         /** Microphone audio source tuned for voice recognition. */
    248         public static final int VOICE_RECOGNITION = 6;
    249 
    250         /** Microphone audio source tuned for voice communications such as VoIP. It
    251          *  will for instance take advantage of echo cancellation or automatic gain control
    252          *  if available.
    253          */
    254         public static final int VOICE_COMMUNICATION = 7;
    255 
    256         /**
    257          * Audio source for a submix of audio streams to be presented remotely.
    258          * <p>
    259          * An application can use this audio source to capture a mix of audio streams
    260          * that should be transmitted to a remote receiver such as a Wifi display.
    261          * While recording is active, these audio streams are redirected to the remote
    262          * submix instead of being played on the device speaker or headset.
    263          * </p><p>
    264          * Certain streams are excluded from the remote submix, including
    265          * {@link AudioManager#STREAM_RING}, {@link AudioManager#STREAM_ALARM},
    266          * and {@link AudioManager#STREAM_NOTIFICATION}.  These streams will continue
    267          * to be presented locally as usual.
    268          * </p><p>
    269          * Capturing the remote submix audio requires the
    270          * {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT} permission.
    271          * This permission is reserved for use by system components and is not available to
    272          * third-party applications.
    273          * </p>
    274          */
    275         public static final int REMOTE_SUBMIX = 8;
    276 
    277         /** Microphone audio source tuned for unprocessed (raw) sound if available, behaves like
    278          *  {@link #DEFAULT} otherwise. */
    279         public static final int UNPROCESSED = 9;
    280 
    281         /**
    282          * Audio source for capturing broadcast radio tuner output.
    283          * @hide
    284          */
    285         @SystemApi
    286         public static final int RADIO_TUNER = 1998;
    287 
    288         /**
    289          * Audio source for preemptible, low-priority software hotword detection
    290          * It presents the same gain and pre processing tuning as {@link #VOICE_RECOGNITION}.
    291          * <p>
    292          * An application should use this audio source when it wishes to do
    293          * always-on software hotword detection, while gracefully giving in to any other application
    294          * that might want to read from the microphone.
    295          * </p>
    296          * This is a hidden audio source.
    297          * @hide
    298          */
    299         @SystemApi
    300         public static final int HOTWORD = 1999;
    301     }
    302 
    303     // TODO make AudioSource static (API change) and move this method inside the AudioSource class
    304     /**
    305      * @hide
    306      * @param source An audio source to test
    307      * @return true if the source is only visible to system components
    308      */
    309     public static boolean isSystemOnlyAudioSource(int source) {
    310         switch(source) {
    311         case AudioSource.DEFAULT:
    312         case AudioSource.MIC:
    313         case AudioSource.VOICE_UPLINK:
    314         case AudioSource.VOICE_DOWNLINK:
    315         case AudioSource.VOICE_CALL:
    316         case AudioSource.CAMCORDER:
    317         case AudioSource.VOICE_RECOGNITION:
    318         case AudioSource.VOICE_COMMUNICATION:
    319         //case REMOTE_SUBMIX:  considered "system" as it requires system permissions
    320         case AudioSource.UNPROCESSED:
    321             return false;
    322         default:
    323             return true;
    324         }
    325     }
    326 
    327     /**
    328      * Defines the video source. These constants are used with
    329      * {@link MediaRecorder#setVideoSource(int)}.
    330      */
    331     public final class VideoSource {
    332       /* Do not change these values without updating their counterparts
    333        * in include/media/mediarecorder.h!
    334        */
    335         private VideoSource() {}
    336         public static final int DEFAULT = 0;
    337         /** Camera video source
    338          * <p>
    339          * Using the {@link android.hardware.Camera} API as video source.
    340          * </p>
    341          */
    342         public static final int CAMERA = 1;
    343         /** Surface video source
    344          * <p>
    345          * Using a Surface as video source.
    346          * </p><p>
    347          * This flag must be used when recording from an
    348          * {@link android.hardware.camera2} API source.
    349          * </p><p>
    350          * When using this video source type, use {@link MediaRecorder#getSurface()}
    351          * to retrieve the surface created by MediaRecorder.
    352          */
    353         public static final int SURFACE = 2;
    354     }
    355 
    356     /**
    357      * Defines the output format. These constants are used with
    358      * {@link MediaRecorder#setOutputFormat(int)}.
    359      */
    360     public final class OutputFormat {
    361       /* Do not change these values without updating their counterparts
    362        * in include/media/mediarecorder.h!
    363        */
    364         private OutputFormat() {}
    365         public static final int DEFAULT = 0;
    366         /** 3GPP media file format*/
    367         public static final int THREE_GPP = 1;
    368         /** MPEG4 media file format*/
    369         public static final int MPEG_4 = 2;
    370 
    371         /** The following formats are audio only .aac or .amr formats */
    372 
    373         /**
    374          * AMR NB file format
    375          * @deprecated  Deprecated in favor of MediaRecorder.OutputFormat.AMR_NB
    376          */
    377         public static final int RAW_AMR = 3;
    378 
    379         /** AMR NB file format */
    380         public static final int AMR_NB = 3;
    381 
    382         /** AMR WB file format */
    383         public static final int AMR_WB = 4;
    384 
    385         /** @hide AAC ADIF file format */
    386         public static final int AAC_ADIF = 5;
    387 
    388         /** AAC ADTS file format */
    389         public static final int AAC_ADTS = 6;
    390 
    391         /** @hide Stream over a socket, limited to a single stream */
    392         public static final int OUTPUT_FORMAT_RTP_AVP = 7;
    393 
    394         /** H.264/AAC data encapsulated in MPEG2/TS */
    395         public static final int MPEG_2_TS = 8;
    396 
    397         /** VP8/VORBIS data in a WEBM container */
    398         public static final int WEBM = 9;
    399     };
    400 
    401     /**
    402      * Defines the audio encoding. These constants are used with
    403      * {@link MediaRecorder#setAudioEncoder(int)}.
    404      */
    405     public final class AudioEncoder {
    406       /* Do not change these values without updating their counterparts
    407        * in include/media/mediarecorder.h!
    408        */
    409         private AudioEncoder() {}
    410         public static final int DEFAULT = 0;
    411         /** AMR (Narrowband) audio codec */
    412         public static final int AMR_NB = 1;
    413         /** AMR (Wideband) audio codec */
    414         public static final int AMR_WB = 2;
    415         /** AAC Low Complexity (AAC-LC) audio codec */
    416         public static final int AAC = 3;
    417         /** High Efficiency AAC (HE-AAC) audio codec */
    418         public static final int HE_AAC = 4;
    419         /** Enhanced Low Delay AAC (AAC-ELD) audio codec */
    420         public static final int AAC_ELD = 5;
    421         /** Ogg Vorbis audio codec */
    422         public static final int VORBIS = 6;
    423     }
    424 
    425     /**
    426      * Defines the video encoding. These constants are used with
    427      * {@link MediaRecorder#setVideoEncoder(int)}.
    428      */
    429     public final class VideoEncoder {
    430       /* Do not change these values without updating their counterparts
    431        * in include/media/mediarecorder.h!
    432        */
    433         private VideoEncoder() {}
    434         public static final int DEFAULT = 0;
    435         public static final int H263 = 1;
    436         public static final int H264 = 2;
    437         public static final int MPEG_4_SP = 3;
    438         public static final int VP8 = 4;
    439         public static final int HEVC = 5;
    440     }
    441 
    442     /**
    443      * Sets the audio source to be used for recording. If this method is not
    444      * called, the output file will not contain an audio track. The source needs
    445      * to be specified before setting recording-parameters or encoders. Call
    446      * this only before setOutputFormat().
    447      *
    448      * @param audio_source the audio source to use
    449      * @throws IllegalStateException if it is called after setOutputFormat()
    450      * @see android.media.MediaRecorder.AudioSource
    451      */
    452     public native void setAudioSource(int audio_source)
    453             throws IllegalStateException;
    454 
    455     /**
    456      * Gets the maximum value for audio sources.
    457      * @see android.media.MediaRecorder.AudioSource
    458      */
    459     public static final int getAudioSourceMax() {
    460         return AudioSource.UNPROCESSED;
    461     }
    462 
    463     /**
    464      * Sets the video source to be used for recording. If this method is not
    465      * called, the output file will not contain an video track. The source needs
    466      * to be specified before setting recording-parameters or encoders. Call
    467      * this only before setOutputFormat().
    468      *
    469      * @param video_source the video source to use
    470      * @throws IllegalStateException if it is called after setOutputFormat()
    471      * @see android.media.MediaRecorder.VideoSource
    472      */
    473     public native void setVideoSource(int video_source)
    474             throws IllegalStateException;
    475 
    476     /**
    477      * Uses the settings from a CamcorderProfile object for recording. This method should
    478      * be called after the video AND audio sources are set, and before setOutputFile().
    479      * If a time lapse CamcorderProfile is used, audio related source or recording
    480      * parameters are ignored.
    481      *
    482      * @param profile the CamcorderProfile to use
    483      * @see android.media.CamcorderProfile
    484      */
    485     public void setProfile(CamcorderProfile profile) {
    486         setOutputFormat(profile.fileFormat);
    487         setVideoFrameRate(profile.videoFrameRate);
    488         setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
    489         setVideoEncodingBitRate(profile.videoBitRate);
    490         setVideoEncoder(profile.videoCodec);
    491         if (profile.quality >= CamcorderProfile.QUALITY_TIME_LAPSE_LOW &&
    492              profile.quality <= CamcorderProfile.QUALITY_TIME_LAPSE_QVGA) {
    493             // Nothing needs to be done. Call to setCaptureRate() enables
    494             // time lapse video recording.
    495         } else {
    496             setAudioEncodingBitRate(profile.audioBitRate);
    497             setAudioChannels(profile.audioChannels);
    498             setAudioSamplingRate(profile.audioSampleRate);
    499             setAudioEncoder(profile.audioCodec);
    500         }
    501     }
    502 
    503     /**
    504      * Set video frame capture rate. This can be used to set a different video frame capture
    505      * rate than the recorded video's playback rate. This method also sets the recording mode
    506      * to time lapse. In time lapse video recording, only video is recorded. Audio related
    507      * parameters are ignored when a time lapse recording session starts, if an application
    508      * sets them.
    509      *
    510      * @param fps Rate at which frames should be captured in frames per second.
    511      * The fps can go as low as desired. However the fastest fps will be limited by the hardware.
    512      * For resolutions that can be captured by the video camera, the fastest fps can be computed using
    513      * {@link android.hardware.Camera.Parameters#getPreviewFpsRange(int[])}. For higher
    514      * resolutions the fastest fps may be more restrictive.
    515      * Note that the recorder cannot guarantee that frames will be captured at the
    516      * given rate due to camera/encoder limitations. However it tries to be as close as
    517      * possible.
    518      */
    519     public void setCaptureRate(double fps) {
    520         // Make sure that time lapse is enabled when this method is called.
    521         setParameter("time-lapse-enable=1");
    522         setParameter("time-lapse-fps=" + fps);
    523     }
    524 
    525     /**
    526      * Sets the orientation hint for output video playback.
    527      * This method should be called before prepare(). This method will not
    528      * trigger the source video frame to rotate during video recording, but to
    529      * add a composition matrix containing the rotation angle in the output
    530      * video if the output format is OutputFormat.THREE_GPP or
    531      * OutputFormat.MPEG_4 so that a video player can choose the proper
    532      * orientation for playback. Note that some video players may choose
    533      * to ignore the compostion matrix in a video during playback.
    534      *
    535      * @param degrees the angle to be rotated clockwise in degrees.
    536      * The supported angles are 0, 90, 180, and 270 degrees.
    537      * @throws IllegalArgumentException if the angle is not supported.
    538      *
    539      */
    540     public void setOrientationHint(int degrees) {
    541         if (degrees != 0   &&
    542             degrees != 90  &&
    543             degrees != 180 &&
    544             degrees != 270) {
    545             throw new IllegalArgumentException("Unsupported angle: " + degrees);
    546         }
    547         setParameter("video-param-rotation-angle-degrees=" + degrees);
    548     }
    549 
    550     /**
    551      * Set and store the geodata (latitude and longitude) in the output file.
    552      * This method should be called before prepare(). The geodata is
    553      * stored in udta box if the output format is OutputFormat.THREE_GPP
    554      * or OutputFormat.MPEG_4, and is ignored for other output formats.
    555      * The geodata is stored according to ISO-6709 standard.
    556      *
    557      * @param latitude latitude in degrees. Its value must be in the
    558      * range [-90, 90].
    559      * @param longitude longitude in degrees. Its value must be in the
    560      * range [-180, 180].
    561      *
    562      * @throws IllegalArgumentException if the given latitude or
    563      * longitude is out of range.
    564      *
    565      */
    566     public void setLocation(float latitude, float longitude) {
    567         int latitudex10000  = (int) (latitude * 10000 + 0.5);
    568         int longitudex10000 = (int) (longitude * 10000 + 0.5);
    569 
    570         if (latitudex10000 > 900000 || latitudex10000 < -900000) {
    571             String msg = "Latitude: " + latitude + " out of range.";
    572             throw new IllegalArgumentException(msg);
    573         }
    574         if (longitudex10000 > 1800000 || longitudex10000 < -1800000) {
    575             String msg = "Longitude: " + longitude + " out of range";
    576             throw new IllegalArgumentException(msg);
    577         }
    578 
    579         setParameter("param-geotag-latitude=" + latitudex10000);
    580         setParameter("param-geotag-longitude=" + longitudex10000);
    581     }
    582 
    583     /**
    584      * Sets the format of the output file produced during recording. Call this
    585      * after setAudioSource()/setVideoSource() but before prepare().
    586      *
    587      * <p>It is recommended to always use 3GP format when using the H.263
    588      * video encoder and AMR audio encoder. Using an MPEG-4 container format
    589      * may confuse some desktop players.</p>
    590      *
    591      * @param output_format the output format to use. The output format
    592      * needs to be specified before setting recording-parameters or encoders.
    593      * @throws IllegalStateException if it is called after prepare() or before
    594      * setAudioSource()/setVideoSource().
    595      * @see android.media.MediaRecorder.OutputFormat
    596      */
    597     public native void setOutputFormat(int output_format)
    598             throws IllegalStateException;
    599 
    600     /**
    601      * Sets the width and height of the video to be captured.  Must be called
    602      * after setVideoSource(). Call this after setOutFormat() but before
    603      * prepare().
    604      *
    605      * @param width the width of the video to be captured
    606      * @param height the height of the video to be captured
    607      * @throws IllegalStateException if it is called after
    608      * prepare() or before setOutputFormat()
    609      */
    610     public native void setVideoSize(int width, int height)
    611             throws IllegalStateException;
    612 
    613     /**
    614      * Sets the frame rate of the video to be captured.  Must be called
    615      * after setVideoSource(). Call this after setOutFormat() but before
    616      * prepare().
    617      *
    618      * @param rate the number of frames per second of video to capture
    619      * @throws IllegalStateException if it is called after
    620      * prepare() or before setOutputFormat().
    621      *
    622      * NOTE: On some devices that have auto-frame rate, this sets the
    623      * maximum frame rate, not a constant frame rate. Actual frame rate
    624      * will vary according to lighting conditions.
    625      */
    626     public native void setVideoFrameRate(int rate) throws IllegalStateException;
    627 
    628     /**
    629      * Sets the maximum duration (in ms) of the recording session.
    630      * Call this after setOutFormat() but before prepare().
    631      * After recording reaches the specified duration, a notification
    632      * will be sent to the {@link android.media.MediaRecorder.OnInfoListener}
    633      * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED}
    634      * and recording will be stopped. Stopping happens asynchronously, there
    635      * is no guarantee that the recorder will have stopped by the time the
    636      * listener is notified.
    637      *
    638      * @param max_duration_ms the maximum duration in ms (if zero or negative, disables the duration limit)
    639      *
    640      */
    641     public native void setMaxDuration(int max_duration_ms) throws IllegalArgumentException;
    642 
    643     /**
    644      * Sets the maximum filesize (in bytes) of the recording session.
    645      * Call this after setOutFormat() but before prepare().
    646      * After recording reaches the specified filesize, a notification
    647      * will be sent to the {@link android.media.MediaRecorder.OnInfoListener}
    648      * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}
    649      * and recording will be stopped. Stopping happens asynchronously, there
    650      * is no guarantee that the recorder will have stopped by the time the
    651      * listener is notified.
    652      *
    653      * @param max_filesize_bytes the maximum filesize in bytes (if zero or negative, disables the limit)
    654      *
    655      */
    656     public native void setMaxFileSize(long max_filesize_bytes) throws IllegalArgumentException;
    657 
    658     /**
    659      * Sets the audio encoder to be used for recording. If this method is not
    660      * called, the output file will not contain an audio track. Call this after
    661      * setOutputFormat() but before prepare().
    662      *
    663      * @param audio_encoder the audio encoder to use.
    664      * @throws IllegalStateException if it is called before
    665      * setOutputFormat() or after prepare().
    666      * @see android.media.MediaRecorder.AudioEncoder
    667      */
    668     public native void setAudioEncoder(int audio_encoder)
    669             throws IllegalStateException;
    670 
    671     /**
    672      * Sets the video encoder to be used for recording. If this method is not
    673      * called, the output file will not contain an video track. Call this after
    674      * setOutputFormat() and before prepare().
    675      *
    676      * @param video_encoder the video encoder to use.
    677      * @throws IllegalStateException if it is called before
    678      * setOutputFormat() or after prepare()
    679      * @see android.media.MediaRecorder.VideoEncoder
    680      */
    681     public native void setVideoEncoder(int video_encoder)
    682             throws IllegalStateException;
    683 
    684     /**
    685      * Sets the audio sampling rate for recording. Call this method before prepare().
    686      * Prepare() may perform additional checks on the parameter to make sure whether
    687      * the specified audio sampling rate is applicable. The sampling rate really depends
    688      * on the format for the audio recording, as well as the capabilities of the platform.
    689      * For instance, the sampling rate supported by AAC audio coding standard ranges
    690      * from 8 to 96 kHz, the sampling rate supported by AMRNB is 8kHz, and the sampling
    691      * rate supported by AMRWB is 16kHz. Please consult with the related audio coding
    692      * standard for the supported audio sampling rate.
    693      *
    694      * @param samplingRate the sampling rate for audio in samples per second.
    695      */
    696     public void setAudioSamplingRate(int samplingRate) {
    697         if (samplingRate <= 0) {
    698             throw new IllegalArgumentException("Audio sampling rate is not positive");
    699         }
    700         setParameter("audio-param-sampling-rate=" + samplingRate);
    701     }
    702 
    703     /**
    704      * Sets the number of audio channels for recording. Call this method before prepare().
    705      * Prepare() may perform additional checks on the parameter to make sure whether the
    706      * specified number of audio channels are applicable.
    707      *
    708      * @param numChannels the number of audio channels. Usually it is either 1 (mono) or 2
    709      * (stereo).
    710      */
    711     public void setAudioChannels(int numChannels) {
    712         if (numChannels <= 0) {
    713             throw new IllegalArgumentException("Number of channels is not positive");
    714         }
    715         setParameter("audio-param-number-of-channels=" + numChannels);
    716     }
    717 
    718     /**
    719      * Sets the audio encoding bit rate for recording. Call this method before prepare().
    720      * Prepare() may perform additional checks on the parameter to make sure whether the
    721      * specified bit rate is applicable, and sometimes the passed bitRate will be clipped
    722      * internally to ensure the audio recording can proceed smoothly based on the
    723      * capabilities of the platform.
    724      *
    725      * @param bitRate the audio encoding bit rate in bits per second.
    726      */
    727     public void setAudioEncodingBitRate(int bitRate) {
    728         if (bitRate <= 0) {
    729             throw new IllegalArgumentException("Audio encoding bit rate is not positive");
    730         }
    731         setParameter("audio-param-encoding-bitrate=" + bitRate);
    732     }
    733 
    734     /**
    735      * Sets the video encoding bit rate for recording. Call this method before prepare().
    736      * Prepare() may perform additional checks on the parameter to make sure whether the
    737      * specified bit rate is applicable, and sometimes the passed bitRate will be
    738      * clipped internally to ensure the video recording can proceed smoothly based on
    739      * the capabilities of the platform.
    740      *
    741      * @param bitRate the video encoding bit rate in bits per second.
    742      */
    743     public void setVideoEncodingBitRate(int bitRate) {
    744         if (bitRate <= 0) {
    745             throw new IllegalArgumentException("Video encoding bit rate is not positive");
    746         }
    747         setParameter("video-param-encoding-bitrate=" + bitRate);
    748     }
    749 
    750     /**
    751      * Sets the desired video encoding profile and level for recording. The profile and level
    752      * must be valid for the video encoder set by {@link #setVideoEncoder}. This method can
    753      * called before or after {@link #setVideoEncoder} but it must be called before {@link #prepare}.
    754      * {@code prepare()} may perform additional checks on the parameter to make sure that the specified
    755      * profile and level are applicable, and sometimes the passed profile or level will be
    756      * discarded due to codec capablity or to ensure the video recording can proceed smoothly
    757      * based on the capabilities of the platform. <br>Application can also use the
    758      * {@link MediaCodecInfo.CodecCapabilities#profileLevels} to query applicable combination of profile
    759      * and level for the corresponding format. Note that the requested profile/level may not be supported by
    760      * the codec that is actually being used by this MediaRecorder instance.
    761      * @param profile declared in {@link MediaCodecInfo.CodecProfileLevel}.
    762      * @param level declared in {@link MediaCodecInfo.CodecProfileLevel}.
    763      * @throws IllegalArgumentException when an invalid profile or level value is used.
    764      */
    765     public void setVideoEncodingProfileLevel(int profile, int level) {
    766         if (profile <= 0)  {
    767             throw new IllegalArgumentException("Video encoding profile is not positive");
    768         }
    769         if (level <= 0)  {
    770             throw new IllegalArgumentException("Video encoding level is not positive");
    771         }
    772         setParameter("video-param-encoder-profile=" + profile);
    773         setParameter("video-param-encoder-level=" + level);
    774     }
    775 
    776     /**
    777      * Currently not implemented. It does nothing.
    778      * @deprecated Time lapse mode video recording using camera still image capture
    779      * is not desirable, and will not be supported.
    780      * @hide
    781      */
    782     public void setAuxiliaryOutputFile(FileDescriptor fd)
    783     {
    784         Log.w(TAG, "setAuxiliaryOutputFile(FileDescriptor) is no longer supported.");
    785     }
    786 
    787     /**
    788      * Currently not implemented. It does nothing.
    789      * @deprecated Time lapse mode video recording using camera still image capture
    790      * is not desirable, and will not be supported.
    791      * @hide
    792      */
    793     public void setAuxiliaryOutputFile(String path)
    794     {
    795         Log.w(TAG, "setAuxiliaryOutputFile(String) is no longer supported.");
    796     }
    797 
    798     /**
    799      * Pass in the file descriptor of the file to be written. Call this after
    800      * setOutputFormat() but before prepare().
    801      *
    802      * @param fd an open file descriptor to be written into.
    803      * @throws IllegalStateException if it is called before
    804      * setOutputFormat() or after prepare()
    805      */
    806     public void setOutputFile(FileDescriptor fd) throws IllegalStateException
    807     {
    808         mPath = null;
    809         mFile = null;
    810         mFd = fd;
    811     }
    812 
    813     /**
    814      * Pass in the file object to be written. Call this after setOutputFormat() but before prepare().
    815      * File should be seekable. After setting the next output file, application should not use the
    816      * file until {@link #stop}. Application is responsible for cleaning up unused files after
    817      * {@link #stop} is called.
    818      *
    819      * @param file the file object to be written into.
    820      */
    821     public void setOutputFile(File file)
    822     {
    823         mPath = null;
    824         mFd = null;
    825         mFile = file;
    826     }
    827 
    828     /**
    829      * Sets the next output file descriptor to be used when the maximum filesize is reached
    830      * on the prior output {@link #setOutputFile} or {@link #setNextOutputFile}). File descriptor
    831      * must be seekable and writable. After setting the next output file, application should not
    832      * use the file referenced by this file descriptor until {@link #stop}. It is the application's
    833      * responsibility to close the file descriptor. It is safe to do so as soon as this call returns.
    834      * Application must call this after receiving on the
    835      * {@link android.media.MediaRecorder.OnInfoListener} a "what" code of
    836      * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING} and before receiving a "what" code of
    837      * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}. The file is not used until switching to
    838      * that output. Application will receive{@link #MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED}
    839      * when the next output file is used. Application will not be able to set a new output file if
    840      * the previous one has not been used. Application is responsible for cleaning up unused files
    841      * after {@link #stop} is called.
    842      *
    843      * @param fd an open file descriptor to be written into.
    844      * @throws IllegalStateException if it is called before prepare().
    845      * @throws IOException if setNextOutputFile fails otherwise.
    846      */
    847     public void setNextOutputFile(FileDescriptor fd) throws IOException
    848     {
    849         _setNextOutputFile(fd);
    850     }
    851 
    852     /**
    853      * Sets the path of the output file to be produced. Call this after
    854      * setOutputFormat() but before prepare().
    855      *
    856      * @param path The pathname to use.
    857      * @throws IllegalStateException if it is called before
    858      * setOutputFormat() or after prepare()
    859      */
    860     public void setOutputFile(String path) throws IllegalStateException
    861     {
    862         mFd = null;
    863         mFile = null;
    864         mPath = path;
    865     }
    866 
    867     /**
    868      * Sets the next output file to be used when the maximum filesize is reached on the prior
    869      * output {@link #setOutputFile} or {@link #setNextOutputFile}). File should be seekable.
    870      * After setting the next output file, application should not use the file until {@link #stop}.
    871      * Application must call this after receiving on the
    872      * {@link android.media.MediaRecorder.OnInfoListener} a "what" code of
    873      * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING} and before receiving a "what" code of
    874      * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}. The file is not used until switching to
    875      * that output. Application will receive {@link #MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED}
    876      * when the next output file is used. Application will not be able to set a new output file if
    877      * the previous one has not been used. Application is responsible for cleaning up unused files
    878      * after {@link #stop} is called.
    879      *
    880      * @param  file The file to use.
    881      * @throws IllegalStateException if it is called before prepare().
    882      * @throws IOException if setNextOutputFile fails otherwise.
    883      */
    884     public void setNextOutputFile(File file) throws IOException
    885     {
    886         RandomAccessFile f = new RandomAccessFile(file, "rws");
    887         try {
    888             _setNextOutputFile(f.getFD());
    889         } finally {
    890             f.close();
    891         }
    892     }
    893 
    894     // native implementation
    895     private native void _setOutputFile(FileDescriptor fd) throws IllegalStateException, IOException;
    896     private native void _setNextOutputFile(FileDescriptor fd) throws IllegalStateException, IOException;
    897     private native void _prepare() throws IllegalStateException, IOException;
    898 
    899     /**
    900      * Prepares the recorder to begin capturing and encoding data. This method
    901      * must be called after setting up the desired audio and video sources,
    902      * encoders, file format, etc., but before start().
    903      *
    904      * @throws IllegalStateException if it is called after
    905      * start() or before setOutputFormat().
    906      * @throws IOException if prepare fails otherwise.
    907      */
    908     public void prepare() throws IllegalStateException, IOException
    909     {
    910         if (mPath != null) {
    911             RandomAccessFile file = new RandomAccessFile(mPath, "rws");
    912             try {
    913                 _setOutputFile(file.getFD());
    914             } finally {
    915                 file.close();
    916             }
    917         } else if (mFd != null) {
    918             _setOutputFile(mFd);
    919         } else if (mFile != null) {
    920             RandomAccessFile file = new RandomAccessFile(mFile, "rws");
    921             try {
    922                 _setOutputFile(file.getFD());
    923             } finally {
    924                 file.close();
    925             }
    926         } else {
    927             throw new IOException("No valid output file");
    928         }
    929 
    930         _prepare();
    931     }
    932 
    933     /**
    934      * Begins capturing and encoding data to the file specified with
    935      * setOutputFile(). Call this after prepare().
    936      *
    937      * <p>Since API level 13, if applications set a camera via
    938      * {@link #setCamera(Camera)}, the apps can use the camera after this method
    939      * call. The apps do not need to lock the camera again. However, if this
    940      * method fails, the apps should still lock the camera back. The apps should
    941      * not start another recording session during recording.
    942      *
    943      * @throws IllegalStateException if it is called before
    944      * prepare() or when the camera is already in use by another app.
    945      */
    946     public native void start() throws IllegalStateException;
    947 
    948     /**
    949      * Stops recording. Call this after start(). Once recording is stopped,
    950      * you will have to configure it again as if it has just been constructed.
    951      * Note that a RuntimeException is intentionally thrown to the
    952      * application, if no valid audio/video data has been received when stop()
    953      * is called. This happens if stop() is called immediately after
    954      * start(). The failure lets the application take action accordingly to
    955      * clean up the output file (delete the output file, for instance), since
    956      * the output file is not properly constructed when this happens.
    957      *
    958      * @throws IllegalStateException if it is called before start()
    959      */
    960     public native void stop() throws IllegalStateException;
    961 
    962     /**
    963      * Pauses recording. Call this after start(). You may resume recording
    964      * with resume() without reconfiguration, as opposed to stop(). It does
    965      * nothing if the recording is already paused.
    966      *
    967      * When the recording is paused and resumed, the resulting output would
    968      * be as if nothing happend during paused period, immediately switching
    969      * to the resumed scene.
    970      *
    971      * @throws IllegalStateException if it is called before start() or after
    972      * stop()
    973      */
    974     public native void pause() throws IllegalStateException;
    975 
    976     /**
    977      * Resumes recording. Call this after start(). It does nothing if the
    978      * recording is not paused.
    979      *
    980      * @throws IllegalStateException if it is called before start() or after
    981      * stop()
    982      * @see android.media.MediaRecorder#pause
    983      */
    984     public native void resume() throws IllegalStateException;
    985 
    986     /**
    987      * Restarts the MediaRecorder to its idle state. After calling
    988      * this method, you will have to configure it again as if it had just been
    989      * constructed.
    990      */
    991     public void reset() {
    992         native_reset();
    993 
    994         // make sure none of the listeners get called anymore
    995         mEventHandler.removeCallbacksAndMessages(null);
    996     }
    997 
    998     private native void native_reset();
    999 
   1000     /**
   1001      * Returns the maximum absolute amplitude that was sampled since the last
   1002      * call to this method. Call this only after the setAudioSource().
   1003      *
   1004      * @return the maximum absolute amplitude measured since the last call, or
   1005      * 0 when called for the first time
   1006      * @throws IllegalStateException if it is called before
   1007      * the audio source has been set.
   1008      */
   1009     public native int getMaxAmplitude() throws IllegalStateException;
   1010 
   1011     /* Do not change this value without updating its counterpart
   1012      * in include/media/mediarecorder.h or mediaplayer.h!
   1013      */
   1014     /** Unspecified media recorder error.
   1015      * @see android.media.MediaRecorder.OnErrorListener
   1016      */
   1017     public static final int MEDIA_RECORDER_ERROR_UNKNOWN = 1;
   1018     /** Media server died. In this case, the application must release the
   1019      * MediaRecorder object and instantiate a new one.
   1020      * @see android.media.MediaRecorder.OnErrorListener
   1021      */
   1022     public static final int MEDIA_ERROR_SERVER_DIED = 100;
   1023 
   1024     /**
   1025      * Interface definition for a callback to be invoked when an error
   1026      * occurs while recording.
   1027      */
   1028     public interface OnErrorListener
   1029     {
   1030         /**
   1031          * Called when an error occurs while recording.
   1032          *
   1033          * @param mr the MediaRecorder that encountered the error
   1034          * @param what    the type of error that has occurred:
   1035          * <ul>
   1036          * <li>{@link #MEDIA_RECORDER_ERROR_UNKNOWN}
   1037          * <li>{@link #MEDIA_ERROR_SERVER_DIED}
   1038          * </ul>
   1039          * @param extra   an extra code, specific to the error type
   1040          */
   1041         void onError(MediaRecorder mr, int what, int extra);
   1042     }
   1043 
   1044     /**
   1045      * Register a callback to be invoked when an error occurs while
   1046      * recording.
   1047      *
   1048      * @param l the callback that will be run
   1049      */
   1050     public void setOnErrorListener(OnErrorListener l)
   1051     {
   1052         mOnErrorListener = l;
   1053     }
   1054 
   1055     /* Do not change these values without updating their counterparts
   1056      * in include/media/mediarecorder.h!
   1057      */
   1058     /** Unspecified media recorder info.
   1059      * @see android.media.MediaRecorder.OnInfoListener
   1060      */
   1061     public static final int MEDIA_RECORDER_INFO_UNKNOWN              = 1;
   1062     /** A maximum duration had been setup and has now been reached.
   1063      * @see android.media.MediaRecorder.OnInfoListener
   1064      */
   1065     public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800;
   1066     /** A maximum filesize had been setup and has now been reached.
   1067      * Note: This event will not be sent if application already set
   1068      * next output file through {@link #setNextOutputFile}.
   1069      * @see android.media.MediaRecorder.OnInfoListener
   1070      */
   1071     public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801;
   1072     /** A maximum filesize had been setup and current recorded file size
   1073      * has reached 90% of the limit. This is sent once per file upon
   1074      * reaching/passing the 90% limit. To continue the recording, applicaiton
   1075      * should use {@link #setNextOutputFile} to set the next output file.
   1076      * Otherwise, recording will stop when reaching maximum file size.
   1077      * @see android.media.MediaRecorder.OnInfoListener
   1078      */
   1079     public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING = 802;
   1080     /** A maximum filesize had been reached and MediaRecorder has switched
   1081      * output to a new file set by application {@link #setNextOutputFile}.
   1082      * For best practice, application should use this event to keep track
   1083      * of whether the file previously set has been used or not.
   1084      * @see android.media.MediaRecorder.OnInfoListener
   1085      */
   1086     public static final int MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED = 803;
   1087 
   1088     /** informational events for individual tracks, for testing purpose.
   1089      * The track informational event usually contains two parts in the ext1
   1090      * arg of the onInfo() callback: bit 31-28 contains the track id; and
   1091      * the rest of the 28 bits contains the informational event defined here.
   1092      * For example, ext1 = (1 << 28 | MEDIA_RECORDER_TRACK_INFO_TYPE) if the
   1093      * track id is 1 for informational event MEDIA_RECORDER_TRACK_INFO_TYPE;
   1094      * while ext1 = (0 << 28 | MEDIA_RECORDER_TRACK_INFO_TYPE) if the track
   1095      * id is 0 for informational event MEDIA_RECORDER_TRACK_INFO_TYPE. The
   1096      * application should extract the track id and the type of informational
   1097      * event from ext1, accordingly.
   1098      *
   1099      * FIXME:
   1100      * Please update the comment for onInfo also when these
   1101      * events are unhidden so that application knows how to extract the track
   1102      * id and the informational event type from onInfo callback.
   1103      *
   1104      * {@hide}
   1105      */
   1106     public static final int MEDIA_RECORDER_TRACK_INFO_LIST_START        = 1000;
   1107     /** Signal the completion of the track for the recording session.
   1108      * {@hide}
   1109      */
   1110     public static final int MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS = 1000;
   1111     /** Indicate the recording progress in time (ms) during recording.
   1112      * {@hide}
   1113      */
   1114     public static final int MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME  = 1001;
   1115     /** Indicate the track type: 0 for Audio and 1 for Video.
   1116      * {@hide}
   1117      */
   1118     public static final int MEDIA_RECORDER_TRACK_INFO_TYPE              = 1002;
   1119     /** Provide the track duration information.
   1120      * {@hide}
   1121      */
   1122     public static final int MEDIA_RECORDER_TRACK_INFO_DURATION_MS       = 1003;
   1123     /** Provide the max chunk duration in time (ms) for the given track.
   1124      * {@hide}
   1125      */
   1126     public static final int MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS  = 1004;
   1127     /** Provide the total number of recordd frames.
   1128      * {@hide}
   1129      */
   1130     public static final int MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES    = 1005;
   1131     /** Provide the max spacing between neighboring chunks for the given track.
   1132      * {@hide}
   1133      */
   1134     public static final int MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS    = 1006;
   1135     /** Provide the elapsed time measuring from the start of the recording
   1136      * till the first output frame of the given track is received, excluding
   1137      * any intentional start time offset of a recording session for the
   1138      * purpose of eliminating the recording sound in the recorded file.
   1139      * {@hide}
   1140      */
   1141     public static final int MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS  = 1007;
   1142     /** Provide the start time difference (delay) betweeen this track and
   1143      * the start of the movie.
   1144      * {@hide}
   1145      */
   1146     public static final int MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS   = 1008;
   1147     /** Provide the total number of data (in kilo-bytes) encoded.
   1148      * {@hide}
   1149      */
   1150     public static final int MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES       = 1009;
   1151     /**
   1152      * {@hide}
   1153      */
   1154     public static final int MEDIA_RECORDER_TRACK_INFO_LIST_END          = 2000;
   1155 
   1156 
   1157     /**
   1158      * Interface definition of a callback to be invoked to communicate some
   1159      * info and/or warning about the recording.
   1160      */
   1161     public interface OnInfoListener
   1162     {
   1163         /**
   1164          * Called to indicate an info or a warning during recording.
   1165          *
   1166          * @param mr   the MediaRecorder the info pertains to
   1167          * @param what the type of info or warning that has occurred
   1168          * <ul>
   1169          * <li>{@link #MEDIA_RECORDER_INFO_UNKNOWN}
   1170          * <li>{@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED}
   1171          * <li>{@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}
   1172          * </ul>
   1173          * @param extra   an extra code, specific to the info type
   1174          */
   1175         void onInfo(MediaRecorder mr, int what, int extra);
   1176     }
   1177 
   1178     /**
   1179      * Register a callback to be invoked when an informational event occurs while
   1180      * recording.
   1181      *
   1182      * @param listener the callback that will be run
   1183      */
   1184     public void setOnInfoListener(OnInfoListener listener)
   1185     {
   1186         mOnInfoListener = listener;
   1187     }
   1188 
   1189     private class EventHandler extends Handler
   1190     {
   1191         private MediaRecorder mMediaRecorder;
   1192 
   1193         public EventHandler(MediaRecorder mr, Looper looper) {
   1194             super(looper);
   1195             mMediaRecorder = mr;
   1196         }
   1197 
   1198         /* Do not change these values without updating their counterparts
   1199          * in include/media/mediarecorder.h!
   1200          */
   1201         private static final int MEDIA_RECORDER_EVENT_LIST_START = 1;
   1202         private static final int MEDIA_RECORDER_EVENT_ERROR      = 1;
   1203         private static final int MEDIA_RECORDER_EVENT_INFO       = 2;
   1204         private static final int MEDIA_RECORDER_EVENT_LIST_END   = 99;
   1205 
   1206         /* Events related to individual tracks */
   1207         private static final int MEDIA_RECORDER_TRACK_EVENT_LIST_START = 100;
   1208         private static final int MEDIA_RECORDER_TRACK_EVENT_ERROR      = 100;
   1209         private static final int MEDIA_RECORDER_TRACK_EVENT_INFO       = 101;
   1210         private static final int MEDIA_RECORDER_TRACK_EVENT_LIST_END   = 1000;
   1211 
   1212 
   1213         @Override
   1214         public void handleMessage(Message msg) {
   1215             if (mMediaRecorder.mNativeContext == 0) {
   1216                 Log.w(TAG, "mediarecorder went away with unhandled events");
   1217                 return;
   1218             }
   1219             switch(msg.what) {
   1220             case MEDIA_RECORDER_EVENT_ERROR:
   1221             case MEDIA_RECORDER_TRACK_EVENT_ERROR:
   1222                 if (mOnErrorListener != null)
   1223                     mOnErrorListener.onError(mMediaRecorder, msg.arg1, msg.arg2);
   1224 
   1225                 return;
   1226 
   1227             case MEDIA_RECORDER_EVENT_INFO:
   1228             case MEDIA_RECORDER_TRACK_EVENT_INFO:
   1229                 if (mOnInfoListener != null)
   1230                     mOnInfoListener.onInfo(mMediaRecorder, msg.arg1, msg.arg2);
   1231 
   1232                 return;
   1233 
   1234             default:
   1235                 Log.e(TAG, "Unknown message type " + msg.what);
   1236                 return;
   1237             }
   1238         }
   1239     }
   1240 
   1241     /**
   1242      * Called from native code when an interesting event happens.  This method
   1243      * just uses the EventHandler system to post the event back to the main app thread.
   1244      * We use a weak reference to the original MediaRecorder object so that the native
   1245      * code is safe from the object disappearing from underneath it.  (This is
   1246      * the cookie passed to native_setup().)
   1247      */
   1248     private static void postEventFromNative(Object mediarecorder_ref,
   1249                                             int what, int arg1, int arg2, Object obj)
   1250     {
   1251         MediaRecorder mr = (MediaRecorder)((WeakReference)mediarecorder_ref).get();
   1252         if (mr == null) {
   1253             return;
   1254         }
   1255 
   1256         if (mr.mEventHandler != null) {
   1257             Message m = mr.mEventHandler.obtainMessage(what, arg1, arg2, obj);
   1258             mr.mEventHandler.sendMessage(m);
   1259         }
   1260     }
   1261 
   1262     /**
   1263      * Releases resources associated with this MediaRecorder object.
   1264      * It is good practice to call this method when you're done
   1265      * using the MediaRecorder. In particular, whenever an Activity
   1266      * of an application is paused (its onPause() method is called),
   1267      * or stopped (its onStop() method is called), this method should be
   1268      * invoked to release the MediaRecorder object, unless the application
   1269      * has a special need to keep the object around. In addition to
   1270      * unnecessary resources (such as memory and instances of codecs)
   1271      * being held, failure to call this method immediately if a
   1272      * MediaRecorder object is no longer needed may also lead to
   1273      * continuous battery consumption for mobile devices, and recording
   1274      * failure for other applications if no multiple instances of the
   1275      * same codec are supported on a device. Even if multiple instances
   1276      * of the same codec are supported, some performance degradation
   1277      * may be expected when unnecessary multiple instances are used
   1278      * at the same time.
   1279      */
   1280     public native void release();
   1281 
   1282     private static native final void native_init();
   1283 
   1284     private native final void native_setup(Object mediarecorder_this,
   1285             String clientName, String opPackageName) throws IllegalStateException;
   1286 
   1287     private native final void native_finalize();
   1288 
   1289     private native void setParameter(String nameValuePair);
   1290 
   1291     /**
   1292      *  Return Metrics data about the current Mediarecorder instance.
   1293      *
   1294      * @return a {@link PersistableBundle} containing the set of attributes and values
   1295      * available for the media being generated by this instance of
   1296      * MediaRecorder.
   1297      * The attributes are descibed in {@link MetricsConstants}.
   1298      *
   1299      *  Additional vendor-specific fields may also be present in
   1300      *  the return value.
   1301      */
   1302     public PersistableBundle getMetrics() {
   1303         PersistableBundle bundle = native_getMetrics();
   1304         return bundle;
   1305     }
   1306 
   1307     private native PersistableBundle native_getMetrics();
   1308 
   1309     @Override
   1310     protected void finalize() { native_finalize(); }
   1311 
   1312     public final static class MetricsConstants
   1313     {
   1314         private MetricsConstants() {}
   1315 
   1316         /**
   1317          * Key to extract the audio bitrate
   1318          * from the {@link MediaRecorder#getMetrics} return.
   1319          * The value is an integer.
   1320          */
   1321         public static final String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
   1322 
   1323         /**
   1324          * Key to extract the number of audio channels
   1325          * from the {@link MediaRecorder#getMetrics} return.
   1326          * The value is an integer.
   1327          */
   1328         public static final String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
   1329 
   1330         /**
   1331          * Key to extract the audio samplerate
   1332          * from the {@link MediaRecorder#getMetrics} return.
   1333          * The value is an integer.
   1334          */
   1335         public static final String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
   1336 
   1337         /**
   1338          * Key to extract the audio timescale
   1339          * from the {@link MediaRecorder#getMetrics} return.
   1340          * The value is an integer.
   1341          */
   1342         public static final String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
   1343 
   1344         /**
   1345          * Key to extract the video capture frame rate
   1346          * from the {@link MediaRecorder#getMetrics} return.
   1347          * The value is a double.
   1348          */
   1349         public static final String CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
   1350 
   1351         /**
   1352          * Key to extract the video capture framerate enable value
   1353          * from the {@link MediaRecorder#getMetrics} return.
   1354          * The value is an integer.
   1355          */
   1356         public static final String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
   1357 
   1358         /**
   1359          * Key to extract the intended playback frame rate
   1360          * from the {@link MediaRecorder#getMetrics} return.
   1361          * The value is an integer.
   1362          */
   1363         public static final String FRAMERATE = "android.media.mediarecorder.frame-rate";
   1364 
   1365         /**
   1366          * Key to extract the height (in pixels) of the captured video
   1367          * from the {@link MediaRecorder#getMetrics} return.
   1368          * The value is an integer.
   1369          */
   1370         public static final String HEIGHT = "android.media.mediarecorder.height";
   1371 
   1372         /**
   1373          * Key to extract the recorded movies time units
   1374          * from the {@link MediaRecorder#getMetrics} return.
   1375          * The value is an integer.
   1376          * A value of 1000 indicates that the movie's timing is in milliseconds.
   1377          */
   1378         public static final String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
   1379 
   1380         /**
   1381          * Key to extract the rotation (in degrees) to properly orient the video
   1382          * from the {@link MediaRecorder#getMetrics} return.
   1383          * The value is an integer.
   1384          */
   1385         public static final String ROTATION = "android.media.mediarecorder.rotation";
   1386 
   1387         /**
   1388          * Key to extract the video bitrate from being used
   1389          * from the {@link MediaRecorder#getMetrics} return.
   1390          * The value is an integer.
   1391          */
   1392         public static final String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
   1393 
   1394         /**
   1395          * Key to extract the value for how often video iframes are generated
   1396          * from the {@link MediaRecorder#getMetrics} return.
   1397          * The value is an integer.
   1398          */
   1399         public static final String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
   1400 
   1401         /**
   1402          * Key to extract the video encoding level
   1403          * from the {@link MediaRecorder#getMetrics} return.
   1404          * The value is an integer.
   1405          */
   1406         public static final String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
   1407 
   1408         /**
   1409          * Key to extract the video encoding profile
   1410          * from the {@link MediaRecorder#getMetrics} return.
   1411          * The value is an integer.
   1412          */
   1413         public static final String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
   1414 
   1415         /**
   1416          * Key to extract the recorded video time units
   1417          * from the {@link MediaRecorder#getMetrics} return.
   1418          * The value is an integer.
   1419          * A value of 1000 indicates that the video's timing is in milliseconds.
   1420          */
   1421         public static final String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
   1422 
   1423         /**
   1424          * Key to extract the width (in pixels) of the captured video
   1425          * from the {@link MediaRecorder#getMetrics} return.
   1426          * The value is an integer.
   1427          */
   1428         public static final String WIDTH = "android.media.mediarecorder.width";
   1429 
   1430     }
   1431 }
   1432 
   1433