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