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