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