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