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