MediaRecorder.java revision 66ffacf42a7dde6fac867605aaa47d555b960ee4
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.os.Bundle;
24import android.os.Handler;
25import android.os.Looper;
26import android.os.Message;
27import android.os.PersistableBundle;
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    /** @hide */
328    public static final String toLogFriendlyAudioSource(int source) {
329        switch(source) {
330        case AudioSource.DEFAULT:
331            return "DEFAULT";
332        case AudioSource.MIC:
333            return "MIC";
334        case AudioSource.VOICE_UPLINK:
335            return "VOICE_UPLINK";
336        case AudioSource.VOICE_DOWNLINK:
337            return "VOICE_DOWNLINK";
338        case AudioSource.VOICE_CALL:
339            return "VOICE_CALL";
340        case AudioSource.CAMCORDER:
341            return "CAMCORDER";
342        case AudioSource.VOICE_RECOGNITION:
343            return "VOICE_RECOGNITION";
344        case AudioSource.VOICE_COMMUNICATION:
345            return "VOICE_COMMUNICATION";
346        case AudioSource.REMOTE_SUBMIX:
347            return "REMOTE_SUBMIX";
348        case AudioSource.UNPROCESSED:
349            return "UNPROCESSED";
350        case AudioSource.RADIO_TUNER:
351            return "RADIO_TUNER";
352        case AudioSource.HOTWORD:
353            return "HOTWORD";
354        case AudioSource.AUDIO_SOURCE_INVALID:
355            return "AUDIO_SOURCE_INVALID";
356        default:
357            return "unknown source " + source;
358        }
359    }
360
361    /**
362     * Defines the video source. These constants are used with
363     * {@link MediaRecorder#setVideoSource(int)}.
364     */
365    public final class VideoSource {
366      /* Do not change these values without updating their counterparts
367       * in include/media/mediarecorder.h!
368       */
369        private VideoSource() {}
370        public static final int DEFAULT = 0;
371        /** Camera video source
372         * <p>
373         * Using the {@link android.hardware.Camera} API as video source.
374         * </p>
375         */
376        public static final int CAMERA = 1;
377        /** Surface video source
378         * <p>
379         * Using a Surface as video source.
380         * </p><p>
381         * This flag must be used when recording from an
382         * {@link android.hardware.camera2} API source.
383         * </p><p>
384         * When using this video source type, use {@link MediaRecorder#getSurface()}
385         * to retrieve the surface created by MediaRecorder.
386         */
387        public static final int SURFACE = 2;
388    }
389
390    /**
391     * Defines the output format. These constants are used with
392     * {@link MediaRecorder#setOutputFormat(int)}.
393     */
394    public final class OutputFormat {
395      /* Do not change these values without updating their counterparts
396       * in include/media/mediarecorder.h!
397       */
398        private OutputFormat() {}
399        public static final int DEFAULT = 0;
400        /** 3GPP media file format*/
401        public static final int THREE_GPP = 1;
402        /** MPEG4 media file format*/
403        public static final int MPEG_4 = 2;
404
405        /** The following formats are audio only .aac or .amr formats */
406
407        /**
408         * AMR NB file format
409         * @deprecated  Deprecated in favor of MediaRecorder.OutputFormat.AMR_NB
410         */
411        public static final int RAW_AMR = 3;
412
413        /** AMR NB file format */
414        public static final int AMR_NB = 3;
415
416        /** AMR WB file format */
417        public static final int AMR_WB = 4;
418
419        /** @hide AAC ADIF file format */
420        public static final int AAC_ADIF = 5;
421
422        /** AAC ADTS file format */
423        public static final int AAC_ADTS = 6;
424
425        /** @hide Stream over a socket, limited to a single stream */
426        public static final int OUTPUT_FORMAT_RTP_AVP = 7;
427
428        /** H.264/AAC data encapsulated in MPEG2/TS */
429        public static final int MPEG_2_TS = 8;
430
431        /** VP8/VORBIS data in a WEBM container */
432        public static final int WEBM = 9;
433    };
434
435    /**
436     * Defines the audio encoding. These constants are used with
437     * {@link MediaRecorder#setAudioEncoder(int)}.
438     */
439    public final class AudioEncoder {
440      /* Do not change these values without updating their counterparts
441       * in include/media/mediarecorder.h!
442       */
443        private AudioEncoder() {}
444        public static final int DEFAULT = 0;
445        /** AMR (Narrowband) audio codec */
446        public static final int AMR_NB = 1;
447        /** AMR (Wideband) audio codec */
448        public static final int AMR_WB = 2;
449        /** AAC Low Complexity (AAC-LC) audio codec */
450        public static final int AAC = 3;
451        /** High Efficiency AAC (HE-AAC) audio codec */
452        public static final int HE_AAC = 4;
453        /** Enhanced Low Delay AAC (AAC-ELD) audio codec */
454        public static final int AAC_ELD = 5;
455        /** Ogg Vorbis audio codec */
456        public static final int VORBIS = 6;
457    }
458
459    /**
460     * Defines the video encoding. These constants are used with
461     * {@link MediaRecorder#setVideoEncoder(int)}.
462     */
463    public final class VideoEncoder {
464      /* Do not change these values without updating their counterparts
465       * in include/media/mediarecorder.h!
466       */
467        private VideoEncoder() {}
468        public static final int DEFAULT = 0;
469        public static final int H263 = 1;
470        public static final int H264 = 2;
471        public static final int MPEG_4_SP = 3;
472        public static final int VP8 = 4;
473        public static final int HEVC = 5;
474    }
475
476    /**
477     * Sets the audio source to be used for recording. If this method is not
478     * called, the output file will not contain an audio track. The source needs
479     * to be specified before setting recording-parameters or encoders. Call
480     * this only before setOutputFormat().
481     *
482     * @param audio_source the audio source to use
483     * @throws IllegalStateException if it is called after setOutputFormat()
484     * @see android.media.MediaRecorder.AudioSource
485     */
486    public native void setAudioSource(int audio_source)
487            throws IllegalStateException;
488
489    /**
490     * Gets the maximum value for audio sources.
491     * @see android.media.MediaRecorder.AudioSource
492     */
493    public static final int getAudioSourceMax() {
494        return AudioSource.UNPROCESSED;
495    }
496
497    /**
498     * Sets the video source to be used for recording. If this method is not
499     * called, the output file will not contain an video track. The source needs
500     * to be specified before setting recording-parameters or encoders. Call
501     * this only before setOutputFormat().
502     *
503     * @param video_source the video source to use
504     * @throws IllegalStateException if it is called after setOutputFormat()
505     * @see android.media.MediaRecorder.VideoSource
506     */
507    public native void setVideoSource(int video_source)
508            throws IllegalStateException;
509
510    /**
511     * Uses the settings from a CamcorderProfile object for recording. This method should
512     * be called after the video AND audio sources are set, and before setOutputFile().
513     * If a time lapse CamcorderProfile is used, audio related source or recording
514     * parameters are ignored.
515     *
516     * @param profile the CamcorderProfile to use
517     * @see android.media.CamcorderProfile
518     */
519    public void setProfile(CamcorderProfile profile) {
520        setOutputFormat(profile.fileFormat);
521        setVideoFrameRate(profile.videoFrameRate);
522        setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
523        setVideoEncodingBitRate(profile.videoBitRate);
524        setVideoEncoder(profile.videoCodec);
525        if (profile.quality >= CamcorderProfile.QUALITY_TIME_LAPSE_LOW &&
526             profile.quality <= CamcorderProfile.QUALITY_TIME_LAPSE_QVGA) {
527            // Nothing needs to be done. Call to setCaptureRate() enables
528            // time lapse video recording.
529        } else {
530            setAudioEncodingBitRate(profile.audioBitRate);
531            setAudioChannels(profile.audioChannels);
532            setAudioSamplingRate(profile.audioSampleRate);
533            setAudioEncoder(profile.audioCodec);
534        }
535    }
536
537    /**
538     * Set video frame capture rate. This can be used to set a different video frame capture
539     * rate than the recorded video's playback rate. This method also sets the recording mode
540     * to time lapse. In time lapse video recording, only video is recorded. Audio related
541     * parameters are ignored when a time lapse recording session starts, if an application
542     * sets them.
543     *
544     * @param fps Rate at which frames should be captured in frames per second.
545     * The fps can go as low as desired. However the fastest fps will be limited by the hardware.
546     * For resolutions that can be captured by the video camera, the fastest fps can be computed using
547     * {@link android.hardware.Camera.Parameters#getPreviewFpsRange(int[])}. For higher
548     * resolutions the fastest fps may be more restrictive.
549     * Note that the recorder cannot guarantee that frames will be captured at the
550     * given rate due to camera/encoder limitations. However it tries to be as close as
551     * possible.
552     */
553    public void setCaptureRate(double fps) {
554        // Make sure that time lapse is enabled when this method is called.
555        setParameter("time-lapse-enable=1");
556        setParameter("time-lapse-fps=" + fps);
557    }
558
559    /**
560     * Sets the orientation hint for output video playback.
561     * This method should be called before prepare(). This method will not
562     * trigger the source video frame to rotate during video recording, but to
563     * add a composition matrix containing the rotation angle in the output
564     * video if the output format is OutputFormat.THREE_GPP or
565     * OutputFormat.MPEG_4 so that a video player can choose the proper
566     * orientation for playback. Note that some video players may choose
567     * to ignore the compostion matrix in a video during playback.
568     *
569     * @param degrees the angle to be rotated clockwise in degrees.
570     * The supported angles are 0, 90, 180, and 270 degrees.
571     * @throws IllegalArgumentException if the angle is not supported.
572     *
573     */
574    public void setOrientationHint(int degrees) {
575        if (degrees != 0   &&
576            degrees != 90  &&
577            degrees != 180 &&
578            degrees != 270) {
579            throw new IllegalArgumentException("Unsupported angle: " + degrees);
580        }
581        setParameter("video-param-rotation-angle-degrees=" + degrees);
582    }
583
584    /**
585     * Set and store the geodata (latitude and longitude) in the output file.
586     * This method should be called before prepare(). The geodata is
587     * stored in udta box if the output format is OutputFormat.THREE_GPP
588     * or OutputFormat.MPEG_4, and is ignored for other output formats.
589     * The geodata is stored according to ISO-6709 standard.
590     *
591     * @param latitude latitude in degrees. Its value must be in the
592     * range [-90, 90].
593     * @param longitude longitude in degrees. Its value must be in the
594     * range [-180, 180].
595     *
596     * @throws IllegalArgumentException if the given latitude or
597     * longitude is out of range.
598     *
599     */
600    public void setLocation(float latitude, float longitude) {
601        int latitudex10000  = (int) (latitude * 10000 + 0.5);
602        int longitudex10000 = (int) (longitude * 10000 + 0.5);
603
604        if (latitudex10000 > 900000 || latitudex10000 < -900000) {
605            String msg = "Latitude: " + latitude + " out of range.";
606            throw new IllegalArgumentException(msg);
607        }
608        if (longitudex10000 > 1800000 || longitudex10000 < -1800000) {
609            String msg = "Longitude: " + longitude + " out of range";
610            throw new IllegalArgumentException(msg);
611        }
612
613        setParameter("param-geotag-latitude=" + latitudex10000);
614        setParameter("param-geotag-longitude=" + longitudex10000);
615    }
616
617    /**
618     * Sets the format of the output file produced during recording. Call this
619     * after setAudioSource()/setVideoSource() but before prepare().
620     *
621     * <p>It is recommended to always use 3GP format when using the H.263
622     * video encoder and AMR audio encoder. Using an MPEG-4 container format
623     * may confuse some desktop players.</p>
624     *
625     * @param output_format the output format to use. The output format
626     * needs to be specified before setting recording-parameters or encoders.
627     * @throws IllegalStateException if it is called after prepare() or before
628     * setAudioSource()/setVideoSource().
629     * @see android.media.MediaRecorder.OutputFormat
630     */
631    public native void setOutputFormat(int output_format)
632            throws IllegalStateException;
633
634    /**
635     * Sets the width and height of the video to be captured.  Must be called
636     * after setVideoSource(). Call this after setOutFormat() but before
637     * prepare().
638     *
639     * @param width the width of the video to be captured
640     * @param height the height of the video to be captured
641     * @throws IllegalStateException if it is called after
642     * prepare() or before setOutputFormat()
643     */
644    public native void setVideoSize(int width, int height)
645            throws IllegalStateException;
646
647    /**
648     * Sets the frame rate of the video to be captured.  Must be called
649     * after setVideoSource(). Call this after setOutFormat() but before
650     * prepare().
651     *
652     * @param rate the number of frames per second of video to capture
653     * @throws IllegalStateException if it is called after
654     * prepare() or before setOutputFormat().
655     *
656     * NOTE: On some devices that have auto-frame rate, this sets the
657     * maximum frame rate, not a constant frame rate. Actual frame rate
658     * will vary according to lighting conditions.
659     */
660    public native void setVideoFrameRate(int rate) throws IllegalStateException;
661
662    /**
663     * Sets the maximum duration (in ms) of the recording session.
664     * Call this after setOutFormat() but before prepare().
665     * After recording reaches the specified duration, a notification
666     * will be sent to the {@link android.media.MediaRecorder.OnInfoListener}
667     * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED}
668     * and recording will be stopped. Stopping happens asynchronously, there
669     * is no guarantee that the recorder will have stopped by the time the
670     * listener is notified.
671     *
672     * @param max_duration_ms the maximum duration in ms (if zero or negative, disables the duration limit)
673     *
674     */
675    public native void setMaxDuration(int max_duration_ms) throws IllegalArgumentException;
676
677    /**
678     * Sets the maximum filesize (in bytes) of the recording session.
679     * Call this after setOutFormat() but before prepare().
680     * After recording reaches the specified filesize, a notification
681     * will be sent to the {@link android.media.MediaRecorder.OnInfoListener}
682     * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}
683     * and recording will be stopped. Stopping happens asynchronously, there
684     * is no guarantee that the recorder will have stopped by the time the
685     * listener is notified.
686     *
687     * @param max_filesize_bytes the maximum filesize in bytes (if zero or negative, disables the limit)
688     *
689     */
690    public native void setMaxFileSize(long max_filesize_bytes) throws IllegalArgumentException;
691
692    /**
693     * Sets the audio encoder to be used for recording. If this method is not
694     * called, the output file will not contain an audio track. Call this after
695     * setOutputFormat() but before prepare().
696     *
697     * @param audio_encoder the audio encoder to use.
698     * @throws IllegalStateException if it is called before
699     * setOutputFormat() or after prepare().
700     * @see android.media.MediaRecorder.AudioEncoder
701     */
702    public native void setAudioEncoder(int audio_encoder)
703            throws IllegalStateException;
704
705    /**
706     * Sets the video encoder to be used for recording. If this method is not
707     * called, the output file will not contain an video track. Call this after
708     * setOutputFormat() and before prepare().
709     *
710     * @param video_encoder the video encoder to use.
711     * @throws IllegalStateException if it is called before
712     * setOutputFormat() or after prepare()
713     * @see android.media.MediaRecorder.VideoEncoder
714     */
715    public native void setVideoEncoder(int video_encoder)
716            throws IllegalStateException;
717
718    /**
719     * Sets the audio sampling rate for recording. Call this method before prepare().
720     * Prepare() may perform additional checks on the parameter to make sure whether
721     * the specified audio sampling rate is applicable. The sampling rate really depends
722     * on the format for the audio recording, as well as the capabilities of the platform.
723     * For instance, the sampling rate supported by AAC audio coding standard ranges
724     * from 8 to 96 kHz, the sampling rate supported by AMRNB is 8kHz, and the sampling
725     * rate supported by AMRWB is 16kHz. Please consult with the related audio coding
726     * standard for the supported audio sampling rate.
727     *
728     * @param samplingRate the sampling rate for audio in samples per second.
729     */
730    public void setAudioSamplingRate(int samplingRate) {
731        if (samplingRate <= 0) {
732            throw new IllegalArgumentException("Audio sampling rate is not positive");
733        }
734        setParameter("audio-param-sampling-rate=" + samplingRate);
735    }
736
737    /**
738     * Sets the number of audio channels for recording. Call this method before prepare().
739     * Prepare() may perform additional checks on the parameter to make sure whether the
740     * specified number of audio channels are applicable.
741     *
742     * @param numChannels the number of audio channels. Usually it is either 1 (mono) or 2
743     * (stereo).
744     */
745    public void setAudioChannels(int numChannels) {
746        if (numChannels <= 0) {
747            throw new IllegalArgumentException("Number of channels is not positive");
748        }
749        setParameter("audio-param-number-of-channels=" + numChannels);
750    }
751
752    /**
753     * Sets the audio encoding bit rate for recording. Call this method before prepare().
754     * Prepare() may perform additional checks on the parameter to make sure whether the
755     * specified bit rate is applicable, and sometimes the passed bitRate will be clipped
756     * internally to ensure the audio recording can proceed smoothly based on the
757     * capabilities of the platform.
758     *
759     * @param bitRate the audio encoding bit rate in bits per second.
760     */
761    public void setAudioEncodingBitRate(int bitRate) {
762        if (bitRate <= 0) {
763            throw new IllegalArgumentException("Audio encoding bit rate is not positive");
764        }
765        setParameter("audio-param-encoding-bitrate=" + bitRate);
766    }
767
768    /**
769     * Sets the video encoding bit rate for recording. Call this method before prepare().
770     * Prepare() may perform additional checks on the parameter to make sure whether the
771     * specified bit rate is applicable, and sometimes the passed bitRate will be
772     * clipped internally to ensure the video recording can proceed smoothly based on
773     * the capabilities of the platform.
774     *
775     * @param bitRate the video encoding bit rate in bits per second.
776     */
777    public void setVideoEncodingBitRate(int bitRate) {
778        if (bitRate <= 0) {
779            throw new IllegalArgumentException("Video encoding bit rate is not positive");
780        }
781        setParameter("video-param-encoding-bitrate=" + bitRate);
782    }
783
784    /**
785     * Sets the desired video encoding profile and level for recording. The profile and level
786     * must be valid for the video encoder set by {@link #setVideoEncoder}. This method can
787     * called before or after {@link #setVideoEncoder} but it must be called before {@link #prepare}.
788     * {@code prepare()} may perform additional checks on the parameter to make sure that the specified
789     * profile and level are applicable, and sometimes the passed profile or level will be
790     * discarded due to codec capablity or to ensure the video recording can proceed smoothly
791     * based on the capabilities of the platform. <br>Application can also use the
792     * {@link MediaCodecInfo.CodecCapabilities#profileLevels} to query applicable combination of profile
793     * and level for the corresponding format. Note that the requested profile/level may not be supported by
794     * the codec that is actually being used by this MediaRecorder instance.
795     * @param profile declared in {@link MediaCodecInfo.CodecProfileLevel}.
796     * @param level declared in {@link MediaCodecInfo.CodecProfileLevel}.
797     * @throws IllegalArgumentException when an invalid profile or level value is used.
798     */
799    public void setVideoEncodingProfileLevel(int profile, int level) {
800        if (profile <= 0)  {
801            throw new IllegalArgumentException("Video encoding profile is not positive");
802        }
803        if (level <= 0)  {
804            throw new IllegalArgumentException("Video encoding level is not positive");
805        }
806        setParameter("video-param-encoder-profile=" + profile);
807        setParameter("video-param-encoder-level=" + level);
808    }
809
810    /**
811     * Currently not implemented. It does nothing.
812     * @deprecated Time lapse mode video recording using camera still image capture
813     * is not desirable, and will not be supported.
814     * @hide
815     */
816    public void setAuxiliaryOutputFile(FileDescriptor fd)
817    {
818        Log.w(TAG, "setAuxiliaryOutputFile(FileDescriptor) is no longer supported.");
819    }
820
821    /**
822     * Currently not implemented. It does nothing.
823     * @deprecated Time lapse mode video recording using camera still image capture
824     * is not desirable, and will not be supported.
825     * @hide
826     */
827    public void setAuxiliaryOutputFile(String path)
828    {
829        Log.w(TAG, "setAuxiliaryOutputFile(String) is no longer supported.");
830    }
831
832    /**
833     * Pass in the file descriptor of the file to be written. Call this after
834     * setOutputFormat() but before prepare().
835     *
836     * @param fd an open file descriptor to be written into.
837     * @throws IllegalStateException if it is called before
838     * setOutputFormat() or after prepare()
839     */
840    public void setOutputFile(FileDescriptor fd) throws IllegalStateException
841    {
842        mPath = null;
843        mFile = null;
844        mFd = fd;
845    }
846
847    /**
848     * Pass in the file object to be written. Call this after setOutputFormat() but before prepare().
849     * File should be seekable. After setting the next output file, application should not use the
850     * file until {@link #stop}. Application is responsible for cleaning up unused files after
851     * {@link #stop} is called.
852     *
853     * @param file the file object to be written into.
854     */
855    public void setOutputFile(File file)
856    {
857        mPath = null;
858        mFd = null;
859        mFile = file;
860    }
861
862    /**
863     * Sets the next output file descriptor to be used when the maximum filesize is reached
864     * on the prior output {@link #setOutputFile} or {@link #setNextOutputFile}). File descriptor
865     * must be seekable and writable. After setting the next output file, application should not
866     * use the file referenced by this file descriptor until {@link #stop}. It is the application's
867     * responsibility to close the file descriptor. It is safe to do so as soon as this call returns.
868     * Application must call this after receiving on the
869     * {@link android.media.MediaRecorder.OnInfoListener} a "what" code of
870     * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING} and before receiving a "what" code of
871     * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}. The file is not used until switching to
872     * that output. Application will receive{@link #MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED}
873     * when the next output file is used. Application will not be able to set a new output file if
874     * the previous one has not been used. Application is responsible for cleaning up unused files
875     * after {@link #stop} is called.
876     *
877     * @param fd an open file descriptor to be written into.
878     * @throws IllegalStateException if it is called before prepare().
879     * @throws IOException if setNextOutputFile fails otherwise.
880     */
881    public void setNextOutputFile(FileDescriptor fd) throws IOException
882    {
883        _setNextOutputFile(fd);
884    }
885
886    /**
887     * Sets the path of the output file to be produced. Call this after
888     * setOutputFormat() but before prepare().
889     *
890     * @param path The pathname to use.
891     * @throws IllegalStateException if it is called before
892     * setOutputFormat() or after prepare()
893     */
894    public void setOutputFile(String path) throws IllegalStateException
895    {
896        mFd = null;
897        mFile = null;
898        mPath = path;
899    }
900
901    /**
902     * Sets the next output file to be used when the maximum filesize is reached on the prior
903     * output {@link #setOutputFile} or {@link #setNextOutputFile}). File should be seekable.
904     * After setting the next output file, application should not use the file until {@link #stop}.
905     * Application must call this after receiving on the
906     * {@link android.media.MediaRecorder.OnInfoListener} a "what" code of
907     * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING} and before receiving a "what" code of
908     * {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}. The file is not used until switching to
909     * that output. Application will receive {@link #MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED}
910     * when the next output file is used. Application will not be able to set a new output file if
911     * the previous one has not been used. Application is responsible for cleaning up unused files
912     * after {@link #stop} is called.
913     *
914     * @param  file The file to use.
915     * @throws IllegalStateException if it is called before prepare().
916     * @throws IOException if setNextOutputFile fails otherwise.
917     */
918    public void setNextOutputFile(File file) throws IOException
919    {
920        RandomAccessFile f = new RandomAccessFile(file, "rws");
921        try {
922            _setNextOutputFile(f.getFD());
923        } finally {
924            f.close();
925        }
926    }
927
928    // native implementation
929    private native void _setOutputFile(FileDescriptor fd) throws IllegalStateException, IOException;
930    private native void _setNextOutputFile(FileDescriptor fd) throws IllegalStateException, IOException;
931    private native void _prepare() throws IllegalStateException, IOException;
932
933    /**
934     * Prepares the recorder to begin capturing and encoding data. This method
935     * must be called after setting up the desired audio and video sources,
936     * encoders, file format, etc., but before start().
937     *
938     * @throws IllegalStateException if it is called after
939     * start() or before setOutputFormat().
940     * @throws IOException if prepare fails otherwise.
941     */
942    public void prepare() throws IllegalStateException, IOException
943    {
944        if (mPath != null) {
945            RandomAccessFile file = new RandomAccessFile(mPath, "rws");
946            try {
947                _setOutputFile(file.getFD());
948            } finally {
949                file.close();
950            }
951        } else if (mFd != null) {
952            _setOutputFile(mFd);
953        } else if (mFile != null) {
954            RandomAccessFile file = new RandomAccessFile(mFile, "rws");
955            try {
956                _setOutputFile(file.getFD());
957            } finally {
958                file.close();
959            }
960        } else {
961            throw new IOException("No valid output file");
962        }
963
964        _prepare();
965    }
966
967    /**
968     * Begins capturing and encoding data to the file specified with
969     * setOutputFile(). Call this after prepare().
970     *
971     * <p>Since API level 13, if applications set a camera via
972     * {@link #setCamera(Camera)}, the apps can use the camera after this method
973     * call. The apps do not need to lock the camera again. However, if this
974     * method fails, the apps should still lock the camera back. The apps should
975     * not start another recording session during recording.
976     *
977     * @throws IllegalStateException if it is called before
978     * prepare() or when the camera is already in use by another app.
979     */
980    public native void start() throws IllegalStateException;
981
982    /**
983     * Stops recording. Call this after start(). Once recording is stopped,
984     * you will have to configure it again as if it has just been constructed.
985     * Note that a RuntimeException is intentionally thrown to the
986     * application, if no valid audio/video data has been received when stop()
987     * is called. This happens if stop() is called immediately after
988     * start(). The failure lets the application take action accordingly to
989     * clean up the output file (delete the output file, for instance), since
990     * the output file is not properly constructed when this happens.
991     *
992     * @throws IllegalStateException if it is called before start()
993     */
994    public native void stop() throws IllegalStateException;
995
996    /**
997     * Pauses recording. Call this after start(). You may resume recording
998     * with resume() without reconfiguration, as opposed to stop(). It does
999     * nothing if the recording is already paused.
1000     *
1001     * When the recording is paused and resumed, the resulting output would
1002     * be as if nothing happend during paused period, immediately switching
1003     * to the resumed scene.
1004     *
1005     * @throws IllegalStateException if it is called before start() or after
1006     * stop()
1007     */
1008    public native void pause() throws IllegalStateException;
1009
1010    /**
1011     * Resumes recording. Call this after start(). It does nothing if the
1012     * recording is not paused.
1013     *
1014     * @throws IllegalStateException if it is called before start() or after
1015     * stop()
1016     * @see android.media.MediaRecorder#pause
1017     */
1018    public native void resume() throws IllegalStateException;
1019
1020    /**
1021     * Restarts the MediaRecorder to its idle state. After calling
1022     * this method, you will have to configure it again as if it had just been
1023     * constructed.
1024     */
1025    public void reset() {
1026        native_reset();
1027
1028        // make sure none of the listeners get called anymore
1029        mEventHandler.removeCallbacksAndMessages(null);
1030    }
1031
1032    private native void native_reset();
1033
1034    /**
1035     * Returns the maximum absolute amplitude that was sampled since the last
1036     * call to this method. Call this only after the setAudioSource().
1037     *
1038     * @return the maximum absolute amplitude measured since the last call, or
1039     * 0 when called for the first time
1040     * @throws IllegalStateException if it is called before
1041     * the audio source has been set.
1042     */
1043    public native int getMaxAmplitude() throws IllegalStateException;
1044
1045    /* Do not change this value without updating its counterpart
1046     * in include/media/mediarecorder.h or mediaplayer.h!
1047     */
1048    /** Unspecified media recorder error.
1049     * @see android.media.MediaRecorder.OnErrorListener
1050     */
1051    public static final int MEDIA_RECORDER_ERROR_UNKNOWN = 1;
1052    /** Media server died. In this case, the application must release the
1053     * MediaRecorder object and instantiate a new one.
1054     * @see android.media.MediaRecorder.OnErrorListener
1055     */
1056    public static final int MEDIA_ERROR_SERVER_DIED = 100;
1057
1058    /**
1059     * Interface definition for a callback to be invoked when an error
1060     * occurs while recording.
1061     */
1062    public interface OnErrorListener
1063    {
1064        /**
1065         * Called when an error occurs while recording.
1066         *
1067         * @param mr the MediaRecorder that encountered the error
1068         * @param what    the type of error that has occurred:
1069         * <ul>
1070         * <li>{@link #MEDIA_RECORDER_ERROR_UNKNOWN}
1071         * <li>{@link #MEDIA_ERROR_SERVER_DIED}
1072         * </ul>
1073         * @param extra   an extra code, specific to the error type
1074         */
1075        void onError(MediaRecorder mr, int what, int extra);
1076    }
1077
1078    /**
1079     * Register a callback to be invoked when an error occurs while
1080     * recording.
1081     *
1082     * @param l the callback that will be run
1083     */
1084    public void setOnErrorListener(OnErrorListener l)
1085    {
1086        mOnErrorListener = l;
1087    }
1088
1089    /* Do not change these values without updating their counterparts
1090     * in include/media/mediarecorder.h!
1091     */
1092    /** Unspecified media recorder info.
1093     * @see android.media.MediaRecorder.OnInfoListener
1094     */
1095    public static final int MEDIA_RECORDER_INFO_UNKNOWN              = 1;
1096    /** A maximum duration had been setup and has now been reached.
1097     * @see android.media.MediaRecorder.OnInfoListener
1098     */
1099    public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800;
1100    /** A maximum filesize had been setup and has now been reached.
1101     * Note: This event will not be sent if application already set
1102     * next output file through {@link #setNextOutputFile}.
1103     * @see android.media.MediaRecorder.OnInfoListener
1104     */
1105    public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801;
1106    /** A maximum filesize had been setup and current recorded file size
1107     * has reached 90% of the limit. This is sent once per file upon
1108     * reaching/passing the 90% limit. To continue the recording, applicaiton
1109     * should use {@link #setNextOutputFile} to set the next output file.
1110     * Otherwise, recording will stop when reaching maximum file size.
1111     * @see android.media.MediaRecorder.OnInfoListener
1112     */
1113    public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING = 802;
1114    /** A maximum filesize had been reached and MediaRecorder has switched
1115     * output to a new file set by application {@link #setNextOutputFile}.
1116     * For best practice, application should use this event to keep track
1117     * of whether the file previously set has been used or not.
1118     * @see android.media.MediaRecorder.OnInfoListener
1119     */
1120    public static final int MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED = 803;
1121
1122    /** informational events for individual tracks, for testing purpose.
1123     * The track informational event usually contains two parts in the ext1
1124     * arg of the onInfo() callback: bit 31-28 contains the track id; and
1125     * the rest of the 28 bits contains the informational event defined here.
1126     * For example, ext1 = (1 << 28 | MEDIA_RECORDER_TRACK_INFO_TYPE) if the
1127     * track id is 1 for informational event MEDIA_RECORDER_TRACK_INFO_TYPE;
1128     * while ext1 = (0 << 28 | MEDIA_RECORDER_TRACK_INFO_TYPE) if the track
1129     * id is 0 for informational event MEDIA_RECORDER_TRACK_INFO_TYPE. The
1130     * application should extract the track id and the type of informational
1131     * event from ext1, accordingly.
1132     *
1133     * FIXME:
1134     * Please update the comment for onInfo also when these
1135     * events are unhidden so that application knows how to extract the track
1136     * id and the informational event type from onInfo callback.
1137     *
1138     * {@hide}
1139     */
1140    public static final int MEDIA_RECORDER_TRACK_INFO_LIST_START        = 1000;
1141    /** Signal the completion of the track for the recording session.
1142     * {@hide}
1143     */
1144    public static final int MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS = 1000;
1145    /** Indicate the recording progress in time (ms) during recording.
1146     * {@hide}
1147     */
1148    public static final int MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME  = 1001;
1149    /** Indicate the track type: 0 for Audio and 1 for Video.
1150     * {@hide}
1151     */
1152    public static final int MEDIA_RECORDER_TRACK_INFO_TYPE              = 1002;
1153    /** Provide the track duration information.
1154     * {@hide}
1155     */
1156    public static final int MEDIA_RECORDER_TRACK_INFO_DURATION_MS       = 1003;
1157    /** Provide the max chunk duration in time (ms) for the given track.
1158     * {@hide}
1159     */
1160    public static final int MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS  = 1004;
1161    /** Provide the total number of recordd frames.
1162     * {@hide}
1163     */
1164    public static final int MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES    = 1005;
1165    /** Provide the max spacing between neighboring chunks for the given track.
1166     * {@hide}
1167     */
1168    public static final int MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS    = 1006;
1169    /** Provide the elapsed time measuring from the start of the recording
1170     * till the first output frame of the given track is received, excluding
1171     * any intentional start time offset of a recording session for the
1172     * purpose of eliminating the recording sound in the recorded file.
1173     * {@hide}
1174     */
1175    public static final int MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS  = 1007;
1176    /** Provide the start time difference (delay) betweeen this track and
1177     * the start of the movie.
1178     * {@hide}
1179     */
1180    public static final int MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS   = 1008;
1181    /** Provide the total number of data (in kilo-bytes) encoded.
1182     * {@hide}
1183     */
1184    public static final int MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES       = 1009;
1185    /**
1186     * {@hide}
1187     */
1188    public static final int MEDIA_RECORDER_TRACK_INFO_LIST_END          = 2000;
1189
1190
1191    /**
1192     * Interface definition of a callback to be invoked to communicate some
1193     * info and/or warning about the recording.
1194     */
1195    public interface OnInfoListener
1196    {
1197        /**
1198         * Called to indicate an info or a warning during recording.
1199         *
1200         * @param mr   the MediaRecorder the info pertains to
1201         * @param what the type of info or warning that has occurred
1202         * <ul>
1203         * <li>{@link #MEDIA_RECORDER_INFO_UNKNOWN}
1204         * <li>{@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED}
1205         * <li>{@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}
1206         * </ul>
1207         * @param extra   an extra code, specific to the info type
1208         */
1209        void onInfo(MediaRecorder mr, int what, int extra);
1210    }
1211
1212    /**
1213     * Register a callback to be invoked when an informational event occurs while
1214     * recording.
1215     *
1216     * @param listener the callback that will be run
1217     */
1218    public void setOnInfoListener(OnInfoListener listener)
1219    {
1220        mOnInfoListener = listener;
1221    }
1222
1223    private class EventHandler extends Handler
1224    {
1225        private MediaRecorder mMediaRecorder;
1226
1227        public EventHandler(MediaRecorder mr, Looper looper) {
1228            super(looper);
1229            mMediaRecorder = mr;
1230        }
1231
1232        /* Do not change these values without updating their counterparts
1233         * in include/media/mediarecorder.h!
1234         */
1235        private static final int MEDIA_RECORDER_EVENT_LIST_START = 1;
1236        private static final int MEDIA_RECORDER_EVENT_ERROR      = 1;
1237        private static final int MEDIA_RECORDER_EVENT_INFO       = 2;
1238        private static final int MEDIA_RECORDER_EVENT_LIST_END   = 99;
1239
1240        /* Events related to individual tracks */
1241        private static final int MEDIA_RECORDER_TRACK_EVENT_LIST_START = 100;
1242        private static final int MEDIA_RECORDER_TRACK_EVENT_ERROR      = 100;
1243        private static final int MEDIA_RECORDER_TRACK_EVENT_INFO       = 101;
1244        private static final int MEDIA_RECORDER_TRACK_EVENT_LIST_END   = 1000;
1245
1246
1247        @Override
1248        public void handleMessage(Message msg) {
1249            if (mMediaRecorder.mNativeContext == 0) {
1250                Log.w(TAG, "mediarecorder went away with unhandled events");
1251                return;
1252            }
1253            switch(msg.what) {
1254            case MEDIA_RECORDER_EVENT_ERROR:
1255            case MEDIA_RECORDER_TRACK_EVENT_ERROR:
1256                if (mOnErrorListener != null)
1257                    mOnErrorListener.onError(mMediaRecorder, msg.arg1, msg.arg2);
1258
1259                return;
1260
1261            case MEDIA_RECORDER_EVENT_INFO:
1262            case MEDIA_RECORDER_TRACK_EVENT_INFO:
1263                if (mOnInfoListener != null)
1264                    mOnInfoListener.onInfo(mMediaRecorder, msg.arg1, msg.arg2);
1265
1266                return;
1267
1268            default:
1269                Log.e(TAG, "Unknown message type " + msg.what);
1270                return;
1271            }
1272        }
1273    }
1274
1275    /**
1276     * Called from native code when an interesting event happens.  This method
1277     * just uses the EventHandler system to post the event back to the main app thread.
1278     * We use a weak reference to the original MediaRecorder object so that the native
1279     * code is safe from the object disappearing from underneath it.  (This is
1280     * the cookie passed to native_setup().)
1281     */
1282    private static void postEventFromNative(Object mediarecorder_ref,
1283                                            int what, int arg1, int arg2, Object obj)
1284    {
1285        MediaRecorder mr = (MediaRecorder)((WeakReference)mediarecorder_ref).get();
1286        if (mr == null) {
1287            return;
1288        }
1289
1290        if (mr.mEventHandler != null) {
1291            Message m = mr.mEventHandler.obtainMessage(what, arg1, arg2, obj);
1292            mr.mEventHandler.sendMessage(m);
1293        }
1294    }
1295
1296    /**
1297     * Releases resources associated with this MediaRecorder object.
1298     * It is good practice to call this method when you're done
1299     * using the MediaRecorder. In particular, whenever an Activity
1300     * of an application is paused (its onPause() method is called),
1301     * or stopped (its onStop() method is called), this method should be
1302     * invoked to release the MediaRecorder object, unless the application
1303     * has a special need to keep the object around. In addition to
1304     * unnecessary resources (such as memory and instances of codecs)
1305     * being held, failure to call this method immediately if a
1306     * MediaRecorder object is no longer needed may also lead to
1307     * continuous battery consumption for mobile devices, and recording
1308     * failure for other applications if no multiple instances of the
1309     * same codec are supported on a device. Even if multiple instances
1310     * of the same codec are supported, some performance degradation
1311     * may be expected when unnecessary multiple instances are used
1312     * at the same time.
1313     */
1314    public native void release();
1315
1316    private static native final void native_init();
1317
1318    private native final void native_setup(Object mediarecorder_this,
1319            String clientName, String opPackageName) throws IllegalStateException;
1320
1321    private native final void native_finalize();
1322
1323    private native void setParameter(String nameValuePair);
1324
1325    /**
1326     *  Return Metrics data about the current Mediarecorder instance.
1327     *
1328     * @return a {@link PersistableBundle} containing the set of attributes and values
1329     * available for the media being generated by this instance of
1330     * MediaRecorder.
1331     * The attributes are descibed in {@link MetricsConstants}.
1332     *
1333     *  Additional vendor-specific fields may also be present in
1334     *  the return value.
1335     */
1336    public PersistableBundle getMetrics() {
1337        PersistableBundle bundle = native_getMetrics();
1338        return bundle;
1339    }
1340
1341    private native PersistableBundle native_getMetrics();
1342
1343    @Override
1344    protected void finalize() { native_finalize(); }
1345
1346    public final static class MetricsConstants
1347    {
1348        private MetricsConstants() {}
1349
1350        /**
1351         * Key to extract the audio bitrate
1352         * from the {@link MediaRecorder#getMetrics} return.
1353         * The value is an integer.
1354         */
1355        public static final String AUDIO_BITRATE = "android.media.mediarecorder.audio-bitrate";
1356
1357        /**
1358         * Key to extract the number of audio channels
1359         * from the {@link MediaRecorder#getMetrics} return.
1360         * The value is an integer.
1361         */
1362        public static final String AUDIO_CHANNELS = "android.media.mediarecorder.audio-channels";
1363
1364        /**
1365         * Key to extract the audio samplerate
1366         * from the {@link MediaRecorder#getMetrics} return.
1367         * The value is an integer.
1368         */
1369        public static final String AUDIO_SAMPLERATE = "android.media.mediarecorder.audio-samplerate";
1370
1371        /**
1372         * Key to extract the audio timescale
1373         * from the {@link MediaRecorder#getMetrics} return.
1374         * The value is an integer.
1375         */
1376        public static final String AUDIO_TIMESCALE = "android.media.mediarecorder.audio-timescale";
1377
1378        /**
1379         * Key to extract the video capture frame rate
1380         * from the {@link MediaRecorder#getMetrics} return.
1381         * The value is a double.
1382         */
1383        public static final String CAPTURE_FPS = "android.media.mediarecorder.capture-fps";
1384
1385        /**
1386         * Key to extract the video capture framerate enable value
1387         * from the {@link MediaRecorder#getMetrics} return.
1388         * The value is an integer.
1389         */
1390        public static final String CAPTURE_FPS_ENABLE = "android.media.mediarecorder.capture-fpsenable";
1391
1392        /**
1393         * Key to extract the intended playback frame rate
1394         * from the {@link MediaRecorder#getMetrics} return.
1395         * The value is an integer.
1396         */
1397        public static final String FRAMERATE = "android.media.mediarecorder.frame-rate";
1398
1399        /**
1400         * Key to extract the height (in pixels) of the captured video
1401         * from the {@link MediaRecorder#getMetrics} return.
1402         * The value is an integer.
1403         */
1404        public static final String HEIGHT = "android.media.mediarecorder.height";
1405
1406        /**
1407         * Key to extract the recorded movies time units
1408         * from the {@link MediaRecorder#getMetrics} return.
1409         * The value is an integer.
1410         * A value of 1000 indicates that the movie's timing is in milliseconds.
1411         */
1412        public static final String MOVIE_TIMESCALE = "android.media.mediarecorder.movie-timescale";
1413
1414        /**
1415         * Key to extract the rotation (in degrees) to properly orient the video
1416         * from the {@link MediaRecorder#getMetrics} return.
1417         * The value is an integer.
1418         */
1419        public static final String ROTATION = "android.media.mediarecorder.rotation";
1420
1421        /**
1422         * Key to extract the video bitrate from being used
1423         * from the {@link MediaRecorder#getMetrics} return.
1424         * The value is an integer.
1425         */
1426        public static final String VIDEO_BITRATE = "android.media.mediarecorder.video-bitrate";
1427
1428        /**
1429         * Key to extract the value for how often video iframes are generated
1430         * from the {@link MediaRecorder#getMetrics} return.
1431         * The value is an integer.
1432         */
1433        public static final String VIDEO_IFRAME_INTERVAL = "android.media.mediarecorder.video-iframe-interval";
1434
1435        /**
1436         * Key to extract the video encoding level
1437         * from the {@link MediaRecorder#getMetrics} return.
1438         * The value is an integer.
1439         */
1440        public static final String VIDEO_LEVEL = "android.media.mediarecorder.video-encoder-level";
1441
1442        /**
1443         * Key to extract the video encoding profile
1444         * from the {@link MediaRecorder#getMetrics} return.
1445         * The value is an integer.
1446         */
1447        public static final String VIDEO_PROFILE = "android.media.mediarecorder.video-encoder-profile";
1448
1449        /**
1450         * Key to extract the recorded video time units
1451         * from the {@link MediaRecorder#getMetrics} return.
1452         * The value is an integer.
1453         * A value of 1000 indicates that the video's timing is in milliseconds.
1454         */
1455        public static final String VIDEO_TIMESCALE = "android.media.mediarecorder.video-timescale";
1456
1457        /**
1458         * Key to extract the width (in pixels) of the captured video
1459         * from the {@link MediaRecorder#getMetrics} return.
1460         * The value is an integer.
1461         */
1462        public static final String WIDTH = "android.media.mediarecorder.width";
1463
1464    }
1465}
1466
1467