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");
native_init()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      */
MediaRecorder()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
setCamera(Camera c)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      */
getSurface()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      */
setInputSurface(@onNull Surface surface)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 
native_setInputSurface(@onNull Surface surface)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      */
setPreviewDisplay(Surface sv)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 
AudioSource()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      */
isSystemOnlyAudioSource(int source)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        */
VideoSource()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        */
OutputFormat()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        */
AudioEncoder()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        */
VideoEncoder()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      */
setAudioSource(int audio_source)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      */
getAudioSourceMax()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      */
setVideoSource(int video_source)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      */
setProfile(CamcorderProfile profile)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      */
setCaptureRate(double fps)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      */
setOrientationHint(int degrees)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      */
setLocation(float latitude, float longitude)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      */
setOutputFormat(int output_format)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      */
setVideoSize(int width, int height)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      */
setVideoFrameRate(int rate)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      */
setMaxDuration(int max_duration_ms)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      */
setMaxFileSize(long max_filesize_bytes)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      */
setAudioEncoder(int audio_encoder)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      */
setVideoEncoder(int video_encoder)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      */
setAudioSamplingRate(int samplingRate)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      */
setAudioChannels(int numChannels)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      */
setAudioEncodingBitRate(int bitRate)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      */
setVideoEncodingBitRate(int bitRate)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      */
setVideoEncodingProfileLevel(int profile, int level)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      */
setAuxiliaryOutputFile(FileDescriptor fd)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      */
setAuxiliaryOutputFile(String path)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      */
setOutputFile(FileDescriptor fd)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      */
setOutputFile(File file)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      */
setNextOutputFile(FileDescriptor fd)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      */
setOutputFile(String path)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      */
setNextOutputFile(File file)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
_setOutputFile(FileDescriptor fd)895     private native void _setOutputFile(FileDescriptor fd) throws IllegalStateException, IOException;
_setNextOutputFile(FileDescriptor fd)896     private native void _setNextOutputFile(FileDescriptor fd) throws IllegalStateException, IOException;
_prepare()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      */
prepare()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      */
start()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      */
stop()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      */
pause()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      */
resume()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      */
reset()991     public void reset() {
992         native_reset();
993 
994         // make sure none of the listeners get called anymore
995         mEventHandler.removeCallbacksAndMessages(null);
996     }
997 
native_reset()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      */
getMaxAmplitude()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          */
onError(MediaRecorder mr, int what, int extra)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      */
setOnErrorListener(OnErrorListener l)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          */
onInfo(MediaRecorder mr, int what, int extra)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      */
setOnInfoListener(OnInfoListener listener)1184     public void setOnInfoListener(OnInfoListener listener)
1185     {
1186         mOnInfoListener = listener;
1187     }
1188 
1189     private class EventHandler extends Handler
1190     {
1191         private MediaRecorder mMediaRecorder;
1192 
EventHandler(MediaRecorder mr, Looper looper)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
handleMessage(Message msg)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      */
postEventFromNative(Object mediarecorder_ref, int what, int arg1, int arg2, Object obj)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      */
release()1280     public native void release();
1281 
native_init()1282     private static native final void native_init();
1283 
native_setup(Object mediarecorder_this, String clientName, String opPackageName)1284     private native final void native_setup(Object mediarecorder_this,
1285             String clientName, String opPackageName) throws IllegalStateException;
1286 
native_finalize()1287     private native final void native_finalize();
1288 
setParameter(String nameValuePair)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      */
getMetrics()1302     public PersistableBundle getMetrics() {
1303         PersistableBundle bundle = native_getMetrics();
1304         return bundle;
1305     }
1306 
native_getMetrics()1307     private native PersistableBundle native_getMetrics();
1308 
1309     @Override
finalize()1310     protected void finalize() { native_finalize(); }
1311 
1312     public final static class MetricsConstants
1313     {
MetricsConstants()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