Home | History | Annotate | Download | only in media
      1 /*
      2  * Copyright (C) 2008 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 java.lang.annotation.Retention;
     20 import java.lang.annotation.RetentionPolicy;
     21 import java.lang.ref.WeakReference;
     22 import java.nio.ByteBuffer;
     23 import java.util.Collection;
     24 import java.util.Iterator;
     25 
     26 import android.annotation.IntDef;
     27 import android.annotation.NonNull;
     28 import android.annotation.SystemApi;
     29 import android.app.ActivityThread;
     30 import android.os.Binder;
     31 import android.os.Handler;
     32 import android.os.IBinder;
     33 import android.os.Looper;
     34 import android.os.Message;
     35 import android.os.RemoteException;
     36 import android.os.ServiceManager;
     37 import android.util.ArrayMap;
     38 import android.util.Log;
     39 
     40 import com.android.internal.annotations.GuardedBy;
     41 
     42 /**
     43  * The AudioRecord class manages the audio resources for Java applications
     44  * to record audio from the audio input hardware of the platform. This is
     45  * achieved by "pulling" (reading) the data from the AudioRecord object. The
     46  * application is responsible for polling the AudioRecord object in time using one of
     47  * the following three methods:  {@link #read(byte[],int, int)}, {@link #read(short[], int, int)}
     48  * or {@link #read(ByteBuffer, int)}. The choice of which method to use will be based
     49  * on the audio data storage format that is the most convenient for the user of AudioRecord.
     50  * <p>Upon creation, an AudioRecord object initializes its associated audio buffer that it will
     51  * fill with the new audio data. The size of this buffer, specified during the construction,
     52  * determines how long an AudioRecord can record before "over-running" data that has not
     53  * been read yet. Data should be read from the audio hardware in chunks of sizes inferior to
     54  * the total recording buffer size.
     55  */
     56 public class AudioRecord implements AudioRouting
     57 {
     58     //---------------------------------------------------------
     59     // Constants
     60     //--------------------
     61 
     62 
     63     /**
     64      *  indicates AudioRecord state is not successfully initialized.
     65      */
     66     public static final int STATE_UNINITIALIZED = 0;
     67     /**
     68      *  indicates AudioRecord state is ready to be used
     69      */
     70     public static final int STATE_INITIALIZED   = 1;
     71 
     72     /**
     73      * indicates AudioRecord recording state is not recording
     74      */
     75     public static final int RECORDSTATE_STOPPED = 1;  // matches SL_RECORDSTATE_STOPPED
     76     /**
     77      * indicates AudioRecord recording state is recording
     78      */
     79     public static final int RECORDSTATE_RECORDING = 3;// matches SL_RECORDSTATE_RECORDING
     80 
     81     /**
     82      * Denotes a successful operation.
     83      */
     84     public  static final int SUCCESS                               = AudioSystem.SUCCESS;
     85     /**
     86      * Denotes a generic operation failure.
     87      */
     88     public  static final int ERROR                                 = AudioSystem.ERROR;
     89     /**
     90      * Denotes a failure due to the use of an invalid value.
     91      */
     92     public  static final int ERROR_BAD_VALUE                       = AudioSystem.BAD_VALUE;
     93     /**
     94      * Denotes a failure due to the improper use of a method.
     95      */
     96     public  static final int ERROR_INVALID_OPERATION               = AudioSystem.INVALID_OPERATION;
     97     /**
     98      * An error code indicating that the object reporting it is no longer valid and needs to
     99      * be recreated.
    100      */
    101     public  static final int ERROR_DEAD_OBJECT                     = AudioSystem.DEAD_OBJECT;
    102 
    103     // Error codes:
    104     // to keep in sync with frameworks/base/core/jni/android_media_AudioRecord.cpp
    105     private static final int AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT      = -16;
    106     private static final int AUDIORECORD_ERROR_SETUP_INVALIDCHANNELMASK  = -17;
    107     private static final int AUDIORECORD_ERROR_SETUP_INVALIDFORMAT       = -18;
    108     private static final int AUDIORECORD_ERROR_SETUP_INVALIDSOURCE       = -19;
    109     private static final int AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED    = -20;
    110 
    111     // Events:
    112     // to keep in sync with frameworks/av/include/media/AudioRecord.h
    113     /**
    114      * Event id denotes when record head has reached a previously set marker.
    115      */
    116     private static final int NATIVE_EVENT_MARKER  = 2;
    117     /**
    118      * Event id denotes when previously set update period has elapsed during recording.
    119      */
    120     private static final int NATIVE_EVENT_NEW_POS = 3;
    121 
    122     private final static String TAG = "android.media.AudioRecord";
    123 
    124     /** @hide */
    125     public final static String SUBMIX_FIXED_VOLUME = "fixedVolume";
    126 
    127     /** @hide */
    128     @IntDef({
    129         READ_BLOCKING,
    130         READ_NON_BLOCKING
    131     })
    132     @Retention(RetentionPolicy.SOURCE)
    133     public @interface ReadMode {}
    134 
    135     /**
    136      * The read mode indicating the read operation will block until all data
    137      * requested has been read.
    138      */
    139     public final static int READ_BLOCKING = 0;
    140 
    141     /**
    142      * The read mode indicating the read operation will return immediately after
    143      * reading as much audio data as possible without blocking.
    144      */
    145     public final static int READ_NON_BLOCKING = 1;
    146 
    147     //---------------------------------------------------------
    148     // Used exclusively by native code
    149     //--------------------
    150     /**
    151      * Accessed by native methods: provides access to C++ AudioRecord object
    152      */
    153     @SuppressWarnings("unused")
    154     private long mNativeRecorderInJavaObj;
    155 
    156     /**
    157      * Accessed by native methods: provides access to the callback data.
    158      */
    159     @SuppressWarnings("unused")
    160     private long mNativeCallbackCookie;
    161 
    162     /**
    163      * Accessed by native methods: provides access to the JNIDeviceCallback instance.
    164      */
    165     @SuppressWarnings("unused")
    166     private long mNativeDeviceCallback;
    167 
    168 
    169     //---------------------------------------------------------
    170     // Member variables
    171     //--------------------
    172     /**
    173      * The audio data sampling rate in Hz.
    174      * Never {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED}.
    175      */
    176     private int mSampleRate; // initialized by all constructors via audioParamCheck()
    177     /**
    178      * The number of input audio channels (1 is mono, 2 is stereo)
    179      */
    180     private int mChannelCount;
    181     /**
    182      * The audio channel position mask
    183      */
    184     private int mChannelMask;
    185     /**
    186      * The audio channel index mask
    187      */
    188     private int mChannelIndexMask;
    189     /**
    190      * The encoding of the audio samples.
    191      * @see AudioFormat#ENCODING_PCM_8BIT
    192      * @see AudioFormat#ENCODING_PCM_16BIT
    193      * @see AudioFormat#ENCODING_PCM_FLOAT
    194      */
    195     private int mAudioFormat;
    196     /**
    197      * Where the audio data is recorded from.
    198      */
    199     private int mRecordSource;
    200     /**
    201      * Indicates the state of the AudioRecord instance.
    202      */
    203     private int mState = STATE_UNINITIALIZED;
    204     /**
    205      * Indicates the recording state of the AudioRecord instance.
    206      */
    207     private int mRecordingState = RECORDSTATE_STOPPED;
    208     /**
    209      * Lock to make sure mRecordingState updates are reflecting the actual state of the object.
    210      */
    211     private final Object mRecordingStateLock = new Object();
    212     /**
    213      * The listener the AudioRecord notifies when the record position reaches a marker
    214      * or for periodic updates during the progression of the record head.
    215      *  @see #setRecordPositionUpdateListener(OnRecordPositionUpdateListener)
    216      *  @see #setRecordPositionUpdateListener(OnRecordPositionUpdateListener, Handler)
    217      */
    218     private OnRecordPositionUpdateListener mPositionListener = null;
    219     /**
    220      * Lock to protect position listener updates against event notifications
    221      */
    222     private final Object mPositionListenerLock = new Object();
    223     /**
    224      * Handler for marker events coming from the native code
    225      */
    226     private NativeEventHandler mEventHandler = null;
    227     /**
    228      * Looper associated with the thread that creates the AudioRecord instance
    229      */
    230     private Looper mInitializationLooper = null;
    231     /**
    232      * Size of the native audio buffer.
    233      */
    234     private int mNativeBufferSizeInBytes = 0;
    235     /**
    236      * Audio session ID
    237      */
    238     private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
    239     /**
    240      * AudioAttributes
    241      */
    242     private AudioAttributes mAudioAttributes;
    243     private boolean mIsSubmixFullVolume = false;
    244 
    245     //---------------------------------------------------------
    246     // Constructor, Finalize
    247     //--------------------
    248     /**
    249      * Class constructor.
    250      * Though some invalid parameters will result in an {@link IllegalArgumentException} exception,
    251      * other errors do not.  Thus you should call {@link #getState()} immediately after construction
    252      * to confirm that the object is usable.
    253      * @param audioSource the recording source.
    254      *   See {@link MediaRecorder.AudioSource} for the recording source definitions.
    255      * @param sampleRateInHz the sample rate expressed in Hertz. 44100Hz is currently the only
    256      *   rate that is guaranteed to work on all devices, but other rates such as 22050,
    257      *   16000, and 11025 may work on some devices.
    258      *   {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} means to use a route-dependent value
    259      *   which is usually the sample rate of the source.
    260      *   {@link #getSampleRate()} can be used to retrieve the actual sample rate chosen.
    261      * @param channelConfig describes the configuration of the audio channels.
    262      *   See {@link AudioFormat#CHANNEL_IN_MONO} and
    263      *   {@link AudioFormat#CHANNEL_IN_STEREO}.  {@link AudioFormat#CHANNEL_IN_MONO} is guaranteed
    264      *   to work on all devices.
    265      * @param audioFormat the format in which the audio data is to be returned.
    266      *   See {@link AudioFormat#ENCODING_PCM_8BIT}, {@link AudioFormat#ENCODING_PCM_16BIT},
    267      *   and {@link AudioFormat#ENCODING_PCM_FLOAT}.
    268      * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is written
    269      *   to during the recording. New audio data can be read from this buffer in smaller chunks
    270      *   than this size. See {@link #getMinBufferSize(int, int, int)} to determine the minimum
    271      *   required buffer size for the successful creation of an AudioRecord instance. Using values
    272      *   smaller than getMinBufferSize() will result in an initialization failure.
    273      * @throws java.lang.IllegalArgumentException
    274      */
    275     public AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat,
    276             int bufferSizeInBytes)
    277     throws IllegalArgumentException {
    278         this((new AudioAttributes.Builder())
    279                     .setInternalCapturePreset(audioSource)
    280                     .build(),
    281                 (new AudioFormat.Builder())
    282                     .setChannelMask(getChannelMaskFromLegacyConfig(channelConfig,
    283                                         true/*allow legacy configurations*/))
    284                     .setEncoding(audioFormat)
    285                     .setSampleRate(sampleRateInHz)
    286                     .build(),
    287                 bufferSizeInBytes,
    288                 AudioManager.AUDIO_SESSION_ID_GENERATE);
    289     }
    290 
    291     /**
    292      * @hide
    293      * Class constructor with {@link AudioAttributes} and {@link AudioFormat}.
    294      * @param attributes a non-null {@link AudioAttributes} instance. Use
    295      *     {@link AudioAttributes.Builder#setAudioSource(int)} for configuring the audio
    296      *     source for this instance.
    297      * @param format a non-null {@link AudioFormat} instance describing the format of the data
    298      *     that will be recorded through this AudioRecord. See {@link AudioFormat.Builder} for
    299      *     configuring the audio format parameters such as encoding, channel mask and sample rate.
    300      * @param bufferSizeInBytes the total size (in bytes) of the buffer where audio data is written
    301      *   to during the recording. New audio data can be read from this buffer in smaller chunks
    302      *   than this size. See {@link #getMinBufferSize(int, int, int)} to determine the minimum
    303      *   required buffer size for the successful creation of an AudioRecord instance. Using values
    304      *   smaller than getMinBufferSize() will result in an initialization failure.
    305      * @param sessionId ID of audio session the AudioRecord must be attached to, or
    306      *   {@link AudioManager#AUDIO_SESSION_ID_GENERATE} if the session isn't known at construction
    307      *   time. See also {@link AudioManager#generateAudioSessionId()} to obtain a session ID before
    308      *   construction.
    309      * @throws IllegalArgumentException
    310      */
    311     @SystemApi
    312     public AudioRecord(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,
    313             int sessionId) throws IllegalArgumentException {
    314         mRecordingState = RECORDSTATE_STOPPED;
    315 
    316         if (attributes == null) {
    317             throw new IllegalArgumentException("Illegal null AudioAttributes");
    318         }
    319         if (format == null) {
    320             throw new IllegalArgumentException("Illegal null AudioFormat");
    321         }
    322 
    323         // remember which looper is associated with the AudioRecord instanciation
    324         if ((mInitializationLooper = Looper.myLooper()) == null) {
    325             mInitializationLooper = Looper.getMainLooper();
    326         }
    327 
    328         // is this AudioRecord using REMOTE_SUBMIX at full volume?
    329         if (attributes.getCapturePreset() == MediaRecorder.AudioSource.REMOTE_SUBMIX) {
    330             final AudioAttributes.Builder filteredAttr = new AudioAttributes.Builder();
    331             final Iterator<String> tagsIter = attributes.getTags().iterator();
    332             while (tagsIter.hasNext()) {
    333                 final String tag = tagsIter.next();
    334                 if (tag.equalsIgnoreCase(SUBMIX_FIXED_VOLUME)) {
    335                     mIsSubmixFullVolume = true;
    336                     Log.v(TAG, "Will record from REMOTE_SUBMIX at full fixed volume");
    337                 } else { // SUBMIX_FIXED_VOLUME: is not to be propagated to the native layers
    338                     filteredAttr.addTag(tag);
    339                 }
    340             }
    341             filteredAttr.setInternalCapturePreset(attributes.getCapturePreset());
    342             mAudioAttributes = filteredAttr.build();
    343         } else {
    344             mAudioAttributes = attributes;
    345         }
    346 
    347         int rate = format.getSampleRate();
    348         if (rate == AudioFormat.SAMPLE_RATE_UNSPECIFIED) {
    349             rate = 0;
    350         }
    351 
    352         int encoding = AudioFormat.ENCODING_DEFAULT;
    353         if ((format.getPropertySetMask() & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_ENCODING) != 0)
    354         {
    355             encoding = format.getEncoding();
    356         }
    357 
    358         audioParamCheck(attributes.getCapturePreset(), rate, encoding);
    359 
    360         if ((format.getPropertySetMask()
    361                 & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_INDEX_MASK) != 0) {
    362             mChannelIndexMask = format.getChannelIndexMask();
    363             mChannelCount = format.getChannelCount();
    364         }
    365         if ((format.getPropertySetMask()
    366                 & AudioFormat.AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK) != 0) {
    367             mChannelMask = getChannelMaskFromLegacyConfig(format.getChannelMask(), false);
    368             mChannelCount = format.getChannelCount();
    369         } else if (mChannelIndexMask == 0) {
    370             mChannelMask = getChannelMaskFromLegacyConfig(AudioFormat.CHANNEL_IN_DEFAULT, false);
    371             mChannelCount =  AudioFormat.channelCountFromInChannelMask(mChannelMask);
    372         }
    373 
    374         audioBuffSizeCheck(bufferSizeInBytes);
    375 
    376         int[] sampleRate = new int[] {mSampleRate};
    377         int[] session = new int[1];
    378         session[0] = sessionId;
    379         //TODO: update native initialization when information about hardware init failure
    380         //      due to capture device already open is available.
    381         int initResult = native_setup( new WeakReference<AudioRecord>(this),
    382                 mAudioAttributes, sampleRate, mChannelMask, mChannelIndexMask,
    383                 mAudioFormat, mNativeBufferSizeInBytes,
    384                 session, ActivityThread.currentOpPackageName(), 0 /*nativeRecordInJavaObj*/);
    385         if (initResult != SUCCESS) {
    386             loge("Error code "+initResult+" when initializing native AudioRecord object.");
    387             return; // with mState == STATE_UNINITIALIZED
    388         }
    389 
    390         mSampleRate = sampleRate[0];
    391         mSessionId = session[0];
    392 
    393         mState = STATE_INITIALIZED;
    394     }
    395 
    396     /**
    397      * A constructor which explicitly connects a Native (C++) AudioRecord. For use by
    398      * the AudioRecordRoutingProxy subclass.
    399      * @param nativeRecordInJavaObj A C/C++ pointer to a native AudioRecord
    400      * (associated with an OpenSL ES recorder). Note: the caller must ensure a correct
    401      * value here as no error checking is or can be done.
    402      */
    403     /*package*/ AudioRecord(long nativeRecordInJavaObj) {
    404         mNativeRecorderInJavaObj = 0;
    405         mNativeCallbackCookie = 0;
    406         mNativeDeviceCallback = 0;
    407 
    408         // other initialization...
    409         if (nativeRecordInJavaObj != 0) {
    410             deferred_connect(nativeRecordInJavaObj);
    411         } else {
    412             mState = STATE_UNINITIALIZED;
    413         }
    414     }
    415 
    416     /**
    417      * @hide
    418      */
    419     /* package */ void deferred_connect(long  nativeRecordInJavaObj) {
    420         if (mState != STATE_INITIALIZED) {
    421             int[] session = { 0 };
    422             int[] rates = { 0 };
    423             //TODO: update native initialization when information about hardware init failure
    424             //      due to capture device already open is available.
    425             // Note that for this native_setup, we are providing an already created/initialized
    426             // *Native* AudioRecord, so the attributes parameters to native_setup() are ignored.
    427             int initResult = native_setup(new WeakReference<AudioRecord>(this),
    428                     null /*mAudioAttributes*/,
    429                     rates /*mSampleRates*/,
    430                     0 /*mChannelMask*/,
    431                     0 /*mChannelIndexMask*/,
    432                     0 /*mAudioFormat*/,
    433                     0 /*mNativeBufferSizeInBytes*/,
    434                     session,
    435                     ActivityThread.currentOpPackageName(),
    436                     nativeRecordInJavaObj);
    437             if (initResult != SUCCESS) {
    438                 loge("Error code "+initResult+" when initializing native AudioRecord object.");
    439                 return; // with mState == STATE_UNINITIALIZED
    440             }
    441 
    442             mSessionId = session[0];
    443 
    444             mState = STATE_INITIALIZED;
    445         }
    446     }
    447 
    448     /**
    449      * Builder class for {@link AudioRecord} objects.
    450      * Use this class to configure and create an <code>AudioRecord</code> instance. By setting the
    451      * recording source and audio format parameters, you indicate which of
    452      * those vary from the default behavior on the device.
    453      * <p> Here is an example where <code>Builder</code> is used to specify all {@link AudioFormat}
    454      * parameters, to be used by a new <code>AudioRecord</code> instance:
    455      *
    456      * <pre class="prettyprint">
    457      * AudioRecord recorder = new AudioRecord.Builder()
    458      *         .setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION)
    459      *         .setAudioFormat(new AudioFormat.Builder()
    460      *                 .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
    461      *                 .setSampleRate(32000)
    462      *                 .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
    463      *                 .build())
    464      *         .setBufferSize(2*minBuffSize)
    465      *         .build();
    466      * </pre>
    467      * <p>
    468      * If the audio source is not set with {@link #setAudioSource(int)},
    469      * {@link MediaRecorder.AudioSource#DEFAULT} is used.
    470      * <br>If the audio format is not specified or is incomplete, its channel configuration will be
    471      * {@link AudioFormat#CHANNEL_IN_MONO}, and the encoding will be
    472      * {@link AudioFormat#ENCODING_PCM_16BIT}.
    473      * The sample rate will depend on the device actually selected for capture and can be queried
    474      * with {@link #getSampleRate()} method.
    475      * <br>If the buffer size is not specified with {@link #setBufferSizeInBytes(int)},
    476      * the minimum buffer size for the source is used.
    477      */
    478     public static class Builder {
    479         private AudioAttributes mAttributes;
    480         private AudioFormat mFormat;
    481         private int mBufferSizeInBytes;
    482         private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
    483 
    484         /**
    485          * Constructs a new Builder with the default values as described above.
    486          */
    487         public Builder() {
    488         }
    489 
    490         /**
    491          * @param source the audio source.
    492          * See {@link MediaRecorder.AudioSource} for the supported audio source definitions.
    493          * @return the same Builder instance.
    494          * @throws IllegalArgumentException
    495          */
    496         public Builder setAudioSource(int source) throws IllegalArgumentException {
    497             if ( (source < MediaRecorder.AudioSource.DEFAULT) ||
    498                     (source > MediaRecorder.getAudioSourceMax()) ) {
    499                 throw new IllegalArgumentException("Invalid audio source " + source);
    500             }
    501             mAttributes = new AudioAttributes.Builder()
    502                     .setInternalCapturePreset(source)
    503                     .build();
    504             return this;
    505         }
    506 
    507         /**
    508          * @hide
    509          * To be only used by system components. Allows specifying non-public capture presets
    510          * @param attributes a non-null {@link AudioAttributes} instance that contains the capture
    511          *     preset to be used.
    512          * @return the same Builder instance.
    513          * @throws IllegalArgumentException
    514          */
    515         @SystemApi
    516         public Builder setAudioAttributes(@NonNull AudioAttributes attributes)
    517                 throws IllegalArgumentException {
    518             if (attributes == null) {
    519                 throw new IllegalArgumentException("Illegal null AudioAttributes argument");
    520             }
    521             if (attributes.getCapturePreset() == MediaRecorder.AudioSource.AUDIO_SOURCE_INVALID) {
    522                 throw new IllegalArgumentException(
    523                         "No valid capture preset in AudioAttributes argument");
    524             }
    525             // keep reference, we only copy the data when building
    526             mAttributes = attributes;
    527             return this;
    528         }
    529 
    530         /**
    531          * Sets the format of the audio data to be captured.
    532          * @param format a non-null {@link AudioFormat} instance
    533          * @return the same Builder instance.
    534          * @throws IllegalArgumentException
    535          */
    536         public Builder setAudioFormat(@NonNull AudioFormat format) throws IllegalArgumentException {
    537             if (format == null) {
    538                 throw new IllegalArgumentException("Illegal null AudioFormat argument");
    539             }
    540             // keep reference, we only copy the data when building
    541             mFormat = format;
    542             return this;
    543         }
    544 
    545         /**
    546          * Sets the total size (in bytes) of the buffer where audio data is written
    547          * during the recording. New audio data can be read from this buffer in smaller chunks
    548          * than this size. See {@link #getMinBufferSize(int, int, int)} to determine the minimum
    549          * required buffer size for the successful creation of an AudioRecord instance.
    550          * Since bufferSizeInBytes may be internally increased to accommodate the source
    551          * requirements, use {@link #getBufferSizeInFrames()} to determine the actual buffer size
    552          * in frames.
    553          * @param bufferSizeInBytes a value strictly greater than 0
    554          * @return the same Builder instance.
    555          * @throws IllegalArgumentException
    556          */
    557         public Builder setBufferSizeInBytes(int bufferSizeInBytes) throws IllegalArgumentException {
    558             if (bufferSizeInBytes <= 0) {
    559                 throw new IllegalArgumentException("Invalid buffer size " + bufferSizeInBytes);
    560             }
    561             mBufferSizeInBytes = bufferSizeInBytes;
    562             return this;
    563         }
    564 
    565         /**
    566          * @hide
    567          * To be only used by system components.
    568          * @param sessionId ID of audio session the AudioRecord must be attached to, or
    569          *     {@link AudioManager#AUDIO_SESSION_ID_GENERATE} if the session isn't known at
    570          *     construction time.
    571          * @return the same Builder instance.
    572          * @throws IllegalArgumentException
    573          */
    574         @SystemApi
    575         public Builder setSessionId(int sessionId) throws IllegalArgumentException {
    576             if (sessionId < 0) {
    577                 throw new IllegalArgumentException("Invalid session ID " + sessionId);
    578             }
    579             mSessionId = sessionId;
    580             return this;
    581         }
    582 
    583         /**
    584          * @return a new {@link AudioRecord} instance successfully initialized with all
    585          *     the parameters set on this <code>Builder</code>.
    586          * @throws UnsupportedOperationException if the parameters set on the <code>Builder</code>
    587          *     were incompatible, or if they are not supported by the device,
    588          *     or if the device was not available.
    589          */
    590         public AudioRecord build() throws UnsupportedOperationException {
    591             if (mFormat == null) {
    592                 mFormat = new AudioFormat.Builder()
    593                         .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
    594                         .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
    595                         .build();
    596             } else {
    597                 if (mFormat.getEncoding() == AudioFormat.ENCODING_INVALID) {
    598                     mFormat = new AudioFormat.Builder(mFormat)
    599                             .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
    600                             .build();
    601                 }
    602                 if (mFormat.getChannelMask() == AudioFormat.CHANNEL_INVALID
    603                         && mFormat.getChannelIndexMask() == AudioFormat.CHANNEL_INVALID) {
    604                     mFormat = new AudioFormat.Builder(mFormat)
    605                             .setChannelMask(AudioFormat.CHANNEL_IN_MONO)
    606                             .build();
    607                 }
    608             }
    609             if (mAttributes == null) {
    610                 mAttributes = new AudioAttributes.Builder()
    611                         .setInternalCapturePreset(MediaRecorder.AudioSource.DEFAULT)
    612                         .build();
    613             }
    614             try {
    615                 // If the buffer size is not specified,
    616                 // use a single frame for the buffer size and let the
    617                 // native code figure out the minimum buffer size.
    618                 if (mBufferSizeInBytes == 0) {
    619                     mBufferSizeInBytes = mFormat.getChannelCount()
    620                             * mFormat.getBytesPerSample(mFormat.getEncoding());
    621                 }
    622                 final AudioRecord record = new AudioRecord(
    623                         mAttributes, mFormat, mBufferSizeInBytes, mSessionId);
    624                 if (record.getState() == STATE_UNINITIALIZED) {
    625                     // release is not necessary
    626                     throw new UnsupportedOperationException("Cannot create AudioRecord");
    627                 }
    628                 return record;
    629             } catch (IllegalArgumentException e) {
    630                 throw new UnsupportedOperationException(e.getMessage());
    631             }
    632         }
    633     }
    634 
    635     // Convenience method for the constructor's parameter checks.
    636     // This, getChannelMaskFromLegacyConfig and audioBuffSizeCheck are where constructor
    637     // IllegalArgumentException-s are thrown
    638     private static int getChannelMaskFromLegacyConfig(int inChannelConfig,
    639             boolean allowLegacyConfig) {
    640         int mask;
    641         switch (inChannelConfig) {
    642         case AudioFormat.CHANNEL_IN_DEFAULT: // AudioFormat.CHANNEL_CONFIGURATION_DEFAULT
    643         case AudioFormat.CHANNEL_IN_MONO:
    644         case AudioFormat.CHANNEL_CONFIGURATION_MONO:
    645             mask = AudioFormat.CHANNEL_IN_MONO;
    646             break;
    647         case AudioFormat.CHANNEL_IN_STEREO:
    648         case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
    649             mask = AudioFormat.CHANNEL_IN_STEREO;
    650             break;
    651         case (AudioFormat.CHANNEL_IN_FRONT | AudioFormat.CHANNEL_IN_BACK):
    652             mask = inChannelConfig;
    653             break;
    654         default:
    655             throw new IllegalArgumentException("Unsupported channel configuration.");
    656         }
    657 
    658         if (!allowLegacyConfig && ((inChannelConfig == AudioFormat.CHANNEL_CONFIGURATION_MONO)
    659                 || (inChannelConfig == AudioFormat.CHANNEL_CONFIGURATION_STEREO))) {
    660             // only happens with the constructor that uses AudioAttributes and AudioFormat
    661             throw new IllegalArgumentException("Unsupported deprecated configuration.");
    662         }
    663 
    664         return mask;
    665     }
    666 
    667     // postconditions:
    668     //    mRecordSource is valid
    669     //    mAudioFormat is valid
    670     //    mSampleRate is valid
    671     private void audioParamCheck(int audioSource, int sampleRateInHz, int audioFormat)
    672             throws IllegalArgumentException {
    673 
    674         //--------------
    675         // audio source
    676         if ( (audioSource < MediaRecorder.AudioSource.DEFAULT) ||
    677              ((audioSource > MediaRecorder.getAudioSourceMax()) &&
    678               (audioSource != MediaRecorder.AudioSource.RADIO_TUNER) &&
    679               (audioSource != MediaRecorder.AudioSource.HOTWORD)) )  {
    680             throw new IllegalArgumentException("Invalid audio source " + audioSource);
    681         }
    682         mRecordSource = audioSource;
    683 
    684         //--------------
    685         // sample rate
    686         if ((sampleRateInHz < AudioFormat.SAMPLE_RATE_HZ_MIN ||
    687                 sampleRateInHz > AudioFormat.SAMPLE_RATE_HZ_MAX) &&
    688                 sampleRateInHz != AudioFormat.SAMPLE_RATE_UNSPECIFIED) {
    689             throw new IllegalArgumentException(sampleRateInHz
    690                     + "Hz is not a supported sample rate.");
    691         }
    692         mSampleRate = sampleRateInHz;
    693 
    694         //--------------
    695         // audio format
    696         switch (audioFormat) {
    697         case AudioFormat.ENCODING_DEFAULT:
    698             mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
    699             break;
    700         case AudioFormat.ENCODING_PCM_FLOAT:
    701         case AudioFormat.ENCODING_PCM_16BIT:
    702         case AudioFormat.ENCODING_PCM_8BIT:
    703             mAudioFormat = audioFormat;
    704             break;
    705         default:
    706             throw new IllegalArgumentException("Unsupported sample encoding " + audioFormat
    707                     + ". Should be ENCODING_PCM_8BIT, ENCODING_PCM_16BIT, or ENCODING_PCM_FLOAT.");
    708         }
    709     }
    710 
    711 
    712     // Convenience method for the contructor's audio buffer size check.
    713     // preconditions:
    714     //    mChannelCount is valid
    715     //    mAudioFormat is AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT,
    716     //                 or AudioFormat.ENCODING_PCM_FLOAT
    717     // postcondition:
    718     //    mNativeBufferSizeInBytes is valid (multiple of frame size, positive)
    719     private void audioBuffSizeCheck(int audioBufferSize) throws IllegalArgumentException {
    720         // NB: this section is only valid with PCM data.
    721         // To update when supporting compressed formats
    722         int frameSizeInBytes = mChannelCount
    723             * (AudioFormat.getBytesPerSample(mAudioFormat));
    724         if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) {
    725             throw new IllegalArgumentException("Invalid audio buffer size " + audioBufferSize
    726                     + " (frame size " + frameSizeInBytes + ")");
    727         }
    728 
    729         mNativeBufferSizeInBytes = audioBufferSize;
    730     }
    731 
    732 
    733 
    734     /**
    735      * Releases the native AudioRecord resources.
    736      * The object can no longer be used and the reference should be set to null
    737      * after a call to release()
    738      */
    739     public void release() {
    740         try {
    741             stop();
    742         } catch(IllegalStateException ise) {
    743             // don't raise an exception, we're releasing the resources.
    744         }
    745         native_release();
    746         mState = STATE_UNINITIALIZED;
    747     }
    748 
    749 
    750     @Override
    751     protected void finalize() {
    752         // will cause stop() to be called, and if appropriate, will handle fixed volume recording
    753         release();
    754     }
    755 
    756 
    757     //--------------------------------------------------------------------------
    758     // Getters
    759     //--------------------
    760     /**
    761      * Returns the configured audio sink sample rate in Hz.
    762      * The sink sample rate never changes after construction.
    763      * If the constructor had a specific sample rate, then the sink sample rate is that value.
    764      * If the constructor had {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED},
    765      * then the sink sample rate is a route-dependent default value based on the source [sic].
    766      */
    767     public int getSampleRate() {
    768         return mSampleRate;
    769     }
    770 
    771     /**
    772      * Returns the audio recording source.
    773      * @see MediaRecorder.AudioSource
    774      */
    775     public int getAudioSource() {
    776         return mRecordSource;
    777     }
    778 
    779     /**
    780      * Returns the configured audio data encoding. See {@link AudioFormat#ENCODING_PCM_8BIT},
    781      * {@link AudioFormat#ENCODING_PCM_16BIT}, and {@link AudioFormat#ENCODING_PCM_FLOAT}.
    782      */
    783     public int getAudioFormat() {
    784         return mAudioFormat;
    785     }
    786 
    787     /**
    788      * Returns the configured channel position mask.
    789      * <p> See {@link AudioFormat#CHANNEL_IN_MONO}
    790      * and {@link AudioFormat#CHANNEL_IN_STEREO}.
    791      * This method may return {@link AudioFormat#CHANNEL_INVALID} if
    792      * a channel index mask is used.
    793      * Consider {@link #getFormat()} instead, to obtain an {@link AudioFormat},
    794      * which contains both the channel position mask and the channel index mask.
    795      */
    796     public int getChannelConfiguration() {
    797         return mChannelMask;
    798     }
    799 
    800     /**
    801      * Returns the configured <code>AudioRecord</code> format.
    802      * @return an {@link AudioFormat} containing the
    803      * <code>AudioRecord</code> parameters at the time of configuration.
    804      */
    805     public @NonNull AudioFormat getFormat() {
    806         AudioFormat.Builder builder = new AudioFormat.Builder()
    807             .setSampleRate(mSampleRate)
    808             .setEncoding(mAudioFormat);
    809         if (mChannelMask != AudioFormat.CHANNEL_INVALID) {
    810             builder.setChannelMask(mChannelMask);
    811         }
    812         if (mChannelIndexMask != AudioFormat.CHANNEL_INVALID  /* 0 */) {
    813             builder.setChannelIndexMask(mChannelIndexMask);
    814         }
    815         return builder.build();
    816     }
    817 
    818     /**
    819      * Returns the configured number of channels.
    820      */
    821     public int getChannelCount() {
    822         return mChannelCount;
    823     }
    824 
    825     /**
    826      * Returns the state of the AudioRecord instance. This is useful after the
    827      * AudioRecord instance has been created to check if it was initialized
    828      * properly. This ensures that the appropriate hardware resources have been
    829      * acquired.
    830      * @see AudioRecord#STATE_INITIALIZED
    831      * @see AudioRecord#STATE_UNINITIALIZED
    832      */
    833     public int getState() {
    834         return mState;
    835     }
    836 
    837     /**
    838      * Returns the recording state of the AudioRecord instance.
    839      * @see AudioRecord#RECORDSTATE_STOPPED
    840      * @see AudioRecord#RECORDSTATE_RECORDING
    841      */
    842     public int getRecordingState() {
    843         synchronized (mRecordingStateLock) {
    844             return mRecordingState;
    845         }
    846     }
    847 
    848     /**
    849      *  Returns the frame count of the native <code>AudioRecord</code> buffer.
    850      *  This is greater than or equal to the bufferSizeInBytes converted to frame units
    851      *  specified in the <code>AudioRecord</code> constructor or Builder.
    852      *  The native frame count may be enlarged to accommodate the requirements of the
    853      *  source on creation or if the <code>AudioRecord</code>
    854      *  is subsequently rerouted.
    855      *  @return current size in frames of the <code>AudioRecord</code> buffer.
    856      *  @throws IllegalStateException
    857      */
    858     public int getBufferSizeInFrames() {
    859         return native_get_buffer_size_in_frames();
    860     }
    861 
    862     /**
    863      * Returns the notification marker position expressed in frames.
    864      */
    865     public int getNotificationMarkerPosition() {
    866         return native_get_marker_pos();
    867     }
    868 
    869     /**
    870      * Returns the notification update period expressed in frames.
    871      */
    872     public int getPositionNotificationPeriod() {
    873         return native_get_pos_update_period();
    874     }
    875 
    876     /**
    877      * Poll for an {@link AudioTimestamp} on demand.
    878      * <p>
    879      * The AudioTimestamp reflects the frame delivery information at
    880      * the earliest point available in the capture pipeline.
    881      * <p>
    882      * Calling {@link #startRecording()} following a {@link #stop()} will reset
    883      * the frame count to 0.
    884      *
    885      * @param outTimestamp a caller provided non-null AudioTimestamp instance,
    886      *        which is updated with the AudioRecord frame delivery information upon success.
    887      * @param timebase one of
    888      *        {@link AudioTimestamp#TIMEBASE_BOOTTIME AudioTimestamp.TIMEBASE_BOOTTIME} or
    889      *        {@link AudioTimestamp#TIMEBASE_MONOTONIC AudioTimestamp.TIMEBASE_MONOTONIC},
    890      *        used to select the clock for the AudioTimestamp time.
    891      * @return {@link #SUCCESS} if a timestamp is available,
    892      *         or {@link #ERROR_INVALID_OPERATION} if a timestamp not available.
    893      */
    894      public int getTimestamp(@NonNull AudioTimestamp outTimestamp,
    895              @AudioTimestamp.Timebase int timebase)
    896      {
    897          if (outTimestamp == null ||
    898                  (timebase != AudioTimestamp.TIMEBASE_BOOTTIME
    899                  && timebase != AudioTimestamp.TIMEBASE_MONOTONIC)) {
    900              throw new IllegalArgumentException();
    901          }
    902          return native_get_timestamp(outTimestamp, timebase);
    903      }
    904 
    905     /**
    906      * Returns the minimum buffer size required for the successful creation of an AudioRecord
    907      * object, in byte units.
    908      * Note that this size doesn't guarantee a smooth recording under load, and higher values
    909      * should be chosen according to the expected frequency at which the AudioRecord instance
    910      * will be polled for new data.
    911      * See {@link #AudioRecord(int, int, int, int, int)} for more information on valid
    912      * configuration values.
    913      * @param sampleRateInHz the sample rate expressed in Hertz.
    914      *   {@link AudioFormat#SAMPLE_RATE_UNSPECIFIED} is not permitted.
    915      * @param channelConfig describes the configuration of the audio channels.
    916      *   See {@link AudioFormat#CHANNEL_IN_MONO} and
    917      *   {@link AudioFormat#CHANNEL_IN_STEREO}
    918      * @param audioFormat the format in which the audio data is represented.
    919      *   See {@link AudioFormat#ENCODING_PCM_16BIT}.
    920      * @return {@link #ERROR_BAD_VALUE} if the recording parameters are not supported by the
    921      *  hardware, or an invalid parameter was passed,
    922      *  or {@link #ERROR} if the implementation was unable to query the hardware for its
    923      *  input properties,
    924      *   or the minimum buffer size expressed in bytes.
    925      * @see #AudioRecord(int, int, int, int, int)
    926      */
    927     static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) {
    928         int channelCount = 0;
    929         switch (channelConfig) {
    930         case AudioFormat.CHANNEL_IN_DEFAULT: // AudioFormat.CHANNEL_CONFIGURATION_DEFAULT
    931         case AudioFormat.CHANNEL_IN_MONO:
    932         case AudioFormat.CHANNEL_CONFIGURATION_MONO:
    933             channelCount = 1;
    934             break;
    935         case AudioFormat.CHANNEL_IN_STEREO:
    936         case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
    937         case (AudioFormat.CHANNEL_IN_FRONT | AudioFormat.CHANNEL_IN_BACK):
    938             channelCount = 2;
    939             break;
    940         case AudioFormat.CHANNEL_INVALID:
    941         default:
    942             loge("getMinBufferSize(): Invalid channel configuration.");
    943             return ERROR_BAD_VALUE;
    944         }
    945 
    946         int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat);
    947         if (size == 0) {
    948             return ERROR_BAD_VALUE;
    949         }
    950         else if (size == -1) {
    951             return ERROR;
    952         }
    953         else {
    954             return size;
    955         }
    956     }
    957 
    958     /**
    959      * Returns the audio session ID.
    960      *
    961      * @return the ID of the audio session this AudioRecord belongs to.
    962      */
    963     public int getAudioSessionId() {
    964         return mSessionId;
    965     }
    966 
    967     //---------------------------------------------------------
    968     // Transport control methods
    969     //--------------------
    970     /**
    971      * Starts recording from the AudioRecord instance.
    972      * @throws IllegalStateException
    973      */
    974     public void startRecording()
    975     throws IllegalStateException {
    976         if (mState != STATE_INITIALIZED) {
    977             throw new IllegalStateException("startRecording() called on an "
    978                     + "uninitialized AudioRecord.");
    979         }
    980 
    981         // start recording
    982         synchronized(mRecordingStateLock) {
    983             if (native_start(MediaSyncEvent.SYNC_EVENT_NONE, 0) == SUCCESS) {
    984                 handleFullVolumeRec(true);
    985                 mRecordingState = RECORDSTATE_RECORDING;
    986             }
    987         }
    988     }
    989 
    990     /**
    991      * Starts recording from the AudioRecord instance when the specified synchronization event
    992      * occurs on the specified audio session.
    993      * @throws IllegalStateException
    994      * @param syncEvent event that triggers the capture.
    995      * @see MediaSyncEvent
    996      */
    997     public void startRecording(MediaSyncEvent syncEvent)
    998     throws IllegalStateException {
    999         if (mState != STATE_INITIALIZED) {
   1000             throw new IllegalStateException("startRecording() called on an "
   1001                     + "uninitialized AudioRecord.");
   1002         }
   1003 
   1004         // start recording
   1005         synchronized(mRecordingStateLock) {
   1006             if (native_start(syncEvent.getType(), syncEvent.getAudioSessionId()) == SUCCESS) {
   1007                 handleFullVolumeRec(true);
   1008                 mRecordingState = RECORDSTATE_RECORDING;
   1009             }
   1010         }
   1011     }
   1012 
   1013     /**
   1014      * Stops recording.
   1015      * @throws IllegalStateException
   1016      */
   1017     public void stop()
   1018     throws IllegalStateException {
   1019         if (mState != STATE_INITIALIZED) {
   1020             throw new IllegalStateException("stop() called on an uninitialized AudioRecord.");
   1021         }
   1022 
   1023         // stop recording
   1024         synchronized(mRecordingStateLock) {
   1025             handleFullVolumeRec(false);
   1026             native_stop();
   1027             mRecordingState = RECORDSTATE_STOPPED;
   1028         }
   1029     }
   1030 
   1031     private final IBinder mICallBack = new Binder();
   1032     private void handleFullVolumeRec(boolean starting) {
   1033         if (!mIsSubmixFullVolume) {
   1034             return;
   1035         }
   1036         final IBinder b = ServiceManager.getService(android.content.Context.AUDIO_SERVICE);
   1037         final IAudioService ias = IAudioService.Stub.asInterface(b);
   1038         try {
   1039             ias.forceRemoteSubmixFullVolume(starting, mICallBack);
   1040         } catch (RemoteException e) {
   1041             Log.e(TAG, "Error talking to AudioService when handling full submix volume", e);
   1042         }
   1043     }
   1044 
   1045     //---------------------------------------------------------
   1046     // Audio data supply
   1047     //--------------------
   1048     /**
   1049      * Reads audio data from the audio hardware for recording into a byte array.
   1050      * The format specified in the AudioRecord constructor should be
   1051      * {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array.
   1052      * @param audioData the array to which the recorded audio data is written.
   1053      * @param offsetInBytes index in audioData from which the data is written expressed in bytes.
   1054      * @param sizeInBytes the number of requested bytes.
   1055      * @return zero or the positive number of bytes that were read, or one of the following
   1056      *    error codes. The number of bytes will not exceed sizeInBytes.
   1057      * <ul>
   1058      * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
   1059      * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
   1060      * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
   1061      *    needs to be recreated. The dead object error code is not returned if some data was
   1062      *    successfully transferred. In this case, the error is returned at the next read()</li>
   1063      * <li>{@link #ERROR} in case of other error</li>
   1064      * </ul>
   1065      */
   1066     public int read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes) {
   1067         return read(audioData, offsetInBytes, sizeInBytes, READ_BLOCKING);
   1068     }
   1069 
   1070     /**
   1071      * Reads audio data from the audio hardware for recording into a byte array.
   1072      * The format specified in the AudioRecord constructor should be
   1073      * {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array.
   1074      * The format can be {@link AudioFormat#ENCODING_PCM_16BIT}, but this is deprecated.
   1075      * @param audioData the array to which the recorded audio data is written.
   1076      * @param offsetInBytes index in audioData to which the data is written expressed in bytes.
   1077      *        Must not be negative, or cause the data access to go out of bounds of the array.
   1078      * @param sizeInBytes the number of requested bytes.
   1079      *        Must not be negative, or cause the data access to go out of bounds of the array.
   1080      * @param readMode one of {@link #READ_BLOCKING}, {@link #READ_NON_BLOCKING}.
   1081      *     <br>With {@link #READ_BLOCKING}, the read will block until all the requested data
   1082      *     is read.
   1083      *     <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after
   1084      *     reading as much audio data as possible without blocking.
   1085      * @return zero or the positive number of bytes that were read, or one of the following
   1086      *    error codes. The number of bytes will be a multiple of the frame size in bytes
   1087      *    not to exceed sizeInBytes.
   1088      * <ul>
   1089      * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
   1090      * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
   1091      * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
   1092      *    needs to be recreated. The dead object error code is not returned if some data was
   1093      *    successfully transferred. In this case, the error is returned at the next read()</li>
   1094      * <li>{@link #ERROR} in case of other error</li>
   1095      * </ul>
   1096      */
   1097     public int read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes,
   1098             @ReadMode int readMode) {
   1099         if (mState != STATE_INITIALIZED  || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
   1100             return ERROR_INVALID_OPERATION;
   1101         }
   1102 
   1103         if ((readMode != READ_BLOCKING) && (readMode != READ_NON_BLOCKING)) {
   1104             Log.e(TAG, "AudioRecord.read() called with invalid blocking mode");
   1105             return ERROR_BAD_VALUE;
   1106         }
   1107 
   1108         if ( (audioData == null) || (offsetInBytes < 0 ) || (sizeInBytes < 0)
   1109                 || (offsetInBytes + sizeInBytes < 0)  // detect integer overflow
   1110                 || (offsetInBytes + sizeInBytes > audioData.length)) {
   1111             return ERROR_BAD_VALUE;
   1112         }
   1113 
   1114         return native_read_in_byte_array(audioData, offsetInBytes, sizeInBytes,
   1115                 readMode == READ_BLOCKING);
   1116     }
   1117 
   1118     /**
   1119      * Reads audio data from the audio hardware for recording into a short array.
   1120      * The format specified in the AudioRecord constructor should be
   1121      * {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array.
   1122      * @param audioData the array to which the recorded audio data is written.
   1123      * @param offsetInShorts index in audioData to which the data is written expressed in shorts.
   1124      *        Must not be negative, or cause the data access to go out of bounds of the array.
   1125      * @param sizeInShorts the number of requested shorts.
   1126      *        Must not be negative, or cause the data access to go out of bounds of the array.
   1127      * @return zero or the positive number of shorts that were read, or one of the following
   1128      *    error codes. The number of shorts will be a multiple of the channel count not to exceed
   1129      *    sizeInShorts.
   1130      * <ul>
   1131      * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
   1132      * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
   1133      * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
   1134      *    needs to be recreated. The dead object error code is not returned if some data was
   1135      *    successfully transferred. In this case, the error is returned at the next read()</li>
   1136      * <li>{@link #ERROR} in case of other error</li>
   1137      * </ul>
   1138      */
   1139     public int read(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts) {
   1140         return read(audioData, offsetInShorts, sizeInShorts, READ_BLOCKING);
   1141     }
   1142 
   1143     /**
   1144      * Reads audio data from the audio hardware for recording into a short array.
   1145      * The format specified in the AudioRecord constructor should be
   1146      * {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array.
   1147      * @param audioData the array to which the recorded audio data is written.
   1148      * @param offsetInShorts index in audioData from which the data is written expressed in shorts.
   1149      *        Must not be negative, or cause the data access to go out of bounds of the array.
   1150      * @param sizeInShorts the number of requested shorts.
   1151      *        Must not be negative, or cause the data access to go out of bounds of the array.
   1152      * @param readMode one of {@link #READ_BLOCKING}, {@link #READ_NON_BLOCKING}.
   1153      *     <br>With {@link #READ_BLOCKING}, the read will block until all the requested data
   1154      *     is read.
   1155      *     <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after
   1156      *     reading as much audio data as possible without blocking.
   1157      * @return zero or the positive number of shorts that were read, or one of the following
   1158      *    error codes. The number of shorts will be a multiple of the channel count not to exceed
   1159      *    sizeInShorts.
   1160      * <ul>
   1161      * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
   1162      * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
   1163      * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
   1164      *    needs to be recreated. The dead object error code is not returned if some data was
   1165      *    successfully transferred. In this case, the error is returned at the next read()</li>
   1166      * <li>{@link #ERROR} in case of other error</li>
   1167      * </ul>
   1168      */
   1169     public int read(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts,
   1170             @ReadMode int readMode) {
   1171         if (mState != STATE_INITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
   1172             return ERROR_INVALID_OPERATION;
   1173         }
   1174 
   1175         if ((readMode != READ_BLOCKING) && (readMode != READ_NON_BLOCKING)) {
   1176             Log.e(TAG, "AudioRecord.read() called with invalid blocking mode");
   1177             return ERROR_BAD_VALUE;
   1178         }
   1179 
   1180         if ( (audioData == null) || (offsetInShorts < 0 ) || (sizeInShorts < 0)
   1181                 || (offsetInShorts + sizeInShorts < 0)  // detect integer overflow
   1182                 || (offsetInShorts + sizeInShorts > audioData.length)) {
   1183             return ERROR_BAD_VALUE;
   1184         }
   1185 
   1186         return native_read_in_short_array(audioData, offsetInShorts, sizeInShorts,
   1187                 readMode == READ_BLOCKING);
   1188     }
   1189 
   1190     /**
   1191      * Reads audio data from the audio hardware for recording into a float array.
   1192      * The format specified in the AudioRecord constructor should be
   1193      * {@link AudioFormat#ENCODING_PCM_FLOAT} to correspond to the data in the array.
   1194      * @param audioData the array to which the recorded audio data is written.
   1195      * @param offsetInFloats index in audioData from which the data is written.
   1196      *        Must not be negative, or cause the data access to go out of bounds of the array.
   1197      * @param sizeInFloats the number of requested floats.
   1198      *        Must not be negative, or cause the data access to go out of bounds of the array.
   1199      * @param readMode one of {@link #READ_BLOCKING}, {@link #READ_NON_BLOCKING}.
   1200      *     <br>With {@link #READ_BLOCKING}, the read will block until all the requested data
   1201      *     is read.
   1202      *     <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after
   1203      *     reading as much audio data as possible without blocking.
   1204      * @return zero or the positive number of floats that were read, or one of the following
   1205      *    error codes. The number of floats will be a multiple of the channel count not to exceed
   1206      *    sizeInFloats.
   1207      * <ul>
   1208      * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
   1209      * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
   1210      * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
   1211      *    needs to be recreated. The dead object error code is not returned if some data was
   1212      *    successfully transferred. In this case, the error is returned at the next read()</li>
   1213      * <li>{@link #ERROR} in case of other error</li>
   1214      * </ul>
   1215      */
   1216     public int read(@NonNull float[] audioData, int offsetInFloats, int sizeInFloats,
   1217             @ReadMode int readMode) {
   1218         if (mState == STATE_UNINITIALIZED) {
   1219             Log.e(TAG, "AudioRecord.read() called in invalid state STATE_UNINITIALIZED");
   1220             return ERROR_INVALID_OPERATION;
   1221         }
   1222 
   1223         if (mAudioFormat != AudioFormat.ENCODING_PCM_FLOAT) {
   1224             Log.e(TAG, "AudioRecord.read(float[] ...) requires format ENCODING_PCM_FLOAT");
   1225             return ERROR_INVALID_OPERATION;
   1226         }
   1227 
   1228         if ((readMode != READ_BLOCKING) && (readMode != READ_NON_BLOCKING)) {
   1229             Log.e(TAG, "AudioRecord.read() called with invalid blocking mode");
   1230             return ERROR_BAD_VALUE;
   1231         }
   1232 
   1233         if ((audioData == null) || (offsetInFloats < 0) || (sizeInFloats < 0)
   1234                 || (offsetInFloats + sizeInFloats < 0)  // detect integer overflow
   1235                 || (offsetInFloats + sizeInFloats > audioData.length)) {
   1236             return ERROR_BAD_VALUE;
   1237         }
   1238 
   1239         return native_read_in_float_array(audioData, offsetInFloats, sizeInFloats,
   1240                 readMode == READ_BLOCKING);
   1241     }
   1242 
   1243     /**
   1244      * Reads audio data from the audio hardware for recording into a direct buffer. If this buffer
   1245      * is not a direct buffer, this method will always return 0.
   1246      * Note that the value returned by {@link java.nio.Buffer#position()} on this buffer is
   1247      * unchanged after a call to this method.
   1248      * The representation of the data in the buffer will depend on the format specified in
   1249      * the AudioRecord constructor, and will be native endian.
   1250      * @param audioBuffer the direct buffer to which the recorded audio data is written.
   1251      * Data is written to audioBuffer.position().
   1252      * @param sizeInBytes the number of requested bytes. It is recommended but not enforced
   1253      *    that the number of bytes requested be a multiple of the frame size (sample size in
   1254      *    bytes multiplied by the channel count).
   1255      * @return zero or the positive number of bytes that were read, or one of the following
   1256      *    error codes. The number of bytes will not exceed sizeInBytes and will be truncated to be
   1257      *    a multiple of the frame size.
   1258      * <ul>
   1259      * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
   1260      * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
   1261      * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
   1262      *    needs to be recreated. The dead object error code is not returned if some data was
   1263      *    successfully transferred. In this case, the error is returned at the next read()</li>
   1264      * <li>{@link #ERROR} in case of other error</li>
   1265      * </ul>
   1266      */
   1267     public int read(@NonNull ByteBuffer audioBuffer, int sizeInBytes) {
   1268         return read(audioBuffer, sizeInBytes, READ_BLOCKING);
   1269     }
   1270 
   1271     /**
   1272      * Reads audio data from the audio hardware for recording into a direct buffer. If this buffer
   1273      * is not a direct buffer, this method will always return 0.
   1274      * Note that the value returned by {@link java.nio.Buffer#position()} on this buffer is
   1275      * unchanged after a call to this method.
   1276      * The representation of the data in the buffer will depend on the format specified in
   1277      * the AudioRecord constructor, and will be native endian.
   1278      * @param audioBuffer the direct buffer to which the recorded audio data is written.
   1279      * Data is written to audioBuffer.position().
   1280      * @param sizeInBytes the number of requested bytes. It is recommended but not enforced
   1281      *    that the number of bytes requested be a multiple of the frame size (sample size in
   1282      *    bytes multiplied by the channel count).
   1283      * @param readMode one of {@link #READ_BLOCKING}, {@link #READ_NON_BLOCKING}.
   1284      *     <br>With {@link #READ_BLOCKING}, the read will block until all the requested data
   1285      *     is read.
   1286      *     <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after
   1287      *     reading as much audio data as possible without blocking.
   1288      * @return zero or the positive number of bytes that were read, or one of the following
   1289      *    error codes. The number of bytes will not exceed sizeInBytes and will be truncated to be
   1290      *    a multiple of the frame size.
   1291      * <ul>
   1292      * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
   1293      * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
   1294      * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
   1295      *    needs to be recreated. The dead object error code is not returned if some data was
   1296      *    successfully transferred. In this case, the error is returned at the next read()</li>
   1297      * <li>{@link #ERROR} in case of other error</li>
   1298      * </ul>
   1299      */
   1300     public int read(@NonNull ByteBuffer audioBuffer, int sizeInBytes, @ReadMode int readMode) {
   1301         if (mState != STATE_INITIALIZED) {
   1302             return ERROR_INVALID_OPERATION;
   1303         }
   1304 
   1305         if ((readMode != READ_BLOCKING) && (readMode != READ_NON_BLOCKING)) {
   1306             Log.e(TAG, "AudioRecord.read() called with invalid blocking mode");
   1307             return ERROR_BAD_VALUE;
   1308         }
   1309 
   1310         if ( (audioBuffer == null) || (sizeInBytes < 0) ) {
   1311             return ERROR_BAD_VALUE;
   1312         }
   1313 
   1314         return native_read_in_direct_buffer(audioBuffer, sizeInBytes, readMode == READ_BLOCKING);
   1315     }
   1316 
   1317     //--------------------------------------------------------------------------
   1318     // Initialization / configuration
   1319     //--------------------
   1320     /**
   1321      * Sets the listener the AudioRecord notifies when a previously set marker is reached or
   1322      * for each periodic record head position update.
   1323      * @param listener
   1324      */
   1325     public void setRecordPositionUpdateListener(OnRecordPositionUpdateListener listener) {
   1326         setRecordPositionUpdateListener(listener, null);
   1327     }
   1328 
   1329     /**
   1330      * Sets the listener the AudioRecord notifies when a previously set marker is reached or
   1331      * for each periodic record head position update.
   1332      * Use this method to receive AudioRecord events in the Handler associated with another
   1333      * thread than the one in which you created the AudioRecord instance.
   1334      * @param listener
   1335      * @param handler the Handler that will receive the event notification messages.
   1336      */
   1337     public void setRecordPositionUpdateListener(OnRecordPositionUpdateListener listener,
   1338                                                     Handler handler) {
   1339         synchronized (mPositionListenerLock) {
   1340 
   1341             mPositionListener = listener;
   1342 
   1343             if (listener != null) {
   1344                 if (handler != null) {
   1345                     mEventHandler = new NativeEventHandler(this, handler.getLooper());
   1346                 } else {
   1347                     // no given handler, use the looper the AudioRecord was created in
   1348                     mEventHandler = new NativeEventHandler(this, mInitializationLooper);
   1349                 }
   1350             } else {
   1351                 mEventHandler = null;
   1352             }
   1353         }
   1354 
   1355     }
   1356 
   1357 
   1358     /**
   1359      * Sets the marker position at which the listener is called, if set with
   1360      * {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener)} or
   1361      * {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener, Handler)}.
   1362      * @param markerInFrames marker position expressed in frames
   1363      * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_BAD_VALUE},
   1364      *  {@link #ERROR_INVALID_OPERATION}
   1365      */
   1366     public int setNotificationMarkerPosition(int markerInFrames) {
   1367         if (mState == STATE_UNINITIALIZED) {
   1368             return ERROR_INVALID_OPERATION;
   1369         }
   1370         return native_set_marker_pos(markerInFrames);
   1371     }
   1372 
   1373     /**
   1374      * Returns an {@link AudioDeviceInfo} identifying the current routing of this AudioRecord.
   1375      * Note: The query is only valid if the AudioRecord is currently recording. If it is not,
   1376      * <code>getRoutedDevice()</code> will return null.
   1377      */
   1378     @Override
   1379     public AudioDeviceInfo getRoutedDevice() {
   1380         int deviceId = native_getRoutedDeviceId();
   1381         if (deviceId == 0) {
   1382             return null;
   1383         }
   1384         AudioDeviceInfo[] devices =
   1385                 AudioManager.getDevicesStatic(AudioManager.GET_DEVICES_INPUTS);
   1386         for (int i = 0; i < devices.length; i++) {
   1387             if (devices[i].getId() == deviceId) {
   1388                 return devices[i];
   1389             }
   1390         }
   1391         return null;
   1392     }
   1393 
   1394     /*
   1395      * Call BEFORE adding a routing callback handler.
   1396      */
   1397     private void testEnableNativeRoutingCallbacksLocked() {
   1398         if (mRoutingChangeListeners.size() == 0) {
   1399             native_enableDeviceCallback();
   1400         }
   1401     }
   1402 
   1403     /*
   1404      * Call AFTER removing a routing callback handler.
   1405      */
   1406     private void testDisableNativeRoutingCallbacksLocked() {
   1407         if (mRoutingChangeListeners.size() == 0) {
   1408             native_disableDeviceCallback();
   1409         }
   1410     }
   1411 
   1412     //--------------------------------------------------------------------------
   1413     // (Re)Routing Info
   1414     //--------------------
   1415     /**
   1416      * The list of AudioRouting.OnRoutingChangedListener interfaces added (with
   1417      * {@link AudioRecord#addOnRoutingChangedListener} by an app to receive
   1418      * (re)routing notifications.
   1419      */
   1420     @GuardedBy("mRoutingChangeListeners")
   1421     private ArrayMap<AudioRouting.OnRoutingChangedListener,
   1422             NativeRoutingEventHandlerDelegate> mRoutingChangeListeners = new ArrayMap<>();
   1423 
   1424     /**
   1425      * Adds an {@link AudioRouting.OnRoutingChangedListener} to receive notifications of
   1426      * routing changes on this AudioRecord.
   1427      * @param listener The {@link AudioRouting.OnRoutingChangedListener} interface to receive
   1428      * notifications of rerouting events.
   1429      * @param handler  Specifies the {@link Handler} object for the thread on which to execute
   1430      * the callback. If <code>null</code>, the {@link Handler} associated with the main
   1431      * {@link Looper} will be used.
   1432      */
   1433     @Override
   1434     public void addOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener,
   1435             android.os.Handler handler) {
   1436         synchronized (mRoutingChangeListeners) {
   1437             if (listener != null && !mRoutingChangeListeners.containsKey(listener)) {
   1438                 testEnableNativeRoutingCallbacksLocked();
   1439                 mRoutingChangeListeners.put(
   1440                         listener, new NativeRoutingEventHandlerDelegate(this, listener,
   1441                                 handler != null ? handler : new Handler(mInitializationLooper)));
   1442             }
   1443         }
   1444     }
   1445 
   1446     /**
   1447      * Removes an {@link AudioRouting.OnRoutingChangedListener} which has been previously added
   1448     * to receive rerouting notifications.
   1449     * @param listener The previously added {@link AudioRouting.OnRoutingChangedListener} interface
   1450     * to remove.
   1451     */
   1452     @Override
   1453     public void removeOnRoutingChangedListener(AudioRouting.OnRoutingChangedListener listener) {
   1454         synchronized (mRoutingChangeListeners) {
   1455             if (mRoutingChangeListeners.containsKey(listener)) {
   1456                 mRoutingChangeListeners.remove(listener);
   1457                 testDisableNativeRoutingCallbacksLocked();
   1458             }
   1459         }
   1460     }
   1461 
   1462     //--------------------------------------------------------------------------
   1463     // (Re)Routing Info
   1464     //--------------------
   1465     /**
   1466      * Defines the interface by which applications can receive notifications of
   1467      * routing changes for the associated {@link AudioRecord}.
   1468      *
   1469      * @deprecated users should switch to the general purpose
   1470      *             {@link AudioRouting.OnRoutingChangedListener} class instead.
   1471      */
   1472     @Deprecated
   1473     public interface OnRoutingChangedListener extends AudioRouting.OnRoutingChangedListener {
   1474         /**
   1475          * Called when the routing of an AudioRecord changes from either and
   1476          * explicit or policy rerouting. Use {@link #getRoutedDevice()} to
   1477          * retrieve the newly routed-from device.
   1478          */
   1479         public void onRoutingChanged(AudioRecord audioRecord);
   1480 
   1481         @Override
   1482         default public void onRoutingChanged(AudioRouting router) {
   1483             if (router instanceof AudioRecord) {
   1484                 onRoutingChanged((AudioRecord) router);
   1485             }
   1486         }
   1487     }
   1488 
   1489     /**
   1490      * Adds an {@link OnRoutingChangedListener} to receive notifications of routing changes
   1491      * on this AudioRecord.
   1492      * @param listener The {@link OnRoutingChangedListener} interface to receive notifications
   1493      * of rerouting events.
   1494      * @param handler  Specifies the {@link Handler} object for the thread on which to execute
   1495      * the callback. If <code>null</code>, the {@link Handler} associated with the main
   1496      * {@link Looper} will be used.
   1497      * @deprecated users should switch to the general purpose
   1498      *             {@link AudioRouting.OnRoutingChangedListener} class instead.
   1499      */
   1500     @Deprecated
   1501     public void addOnRoutingChangedListener(OnRoutingChangedListener listener,
   1502             android.os.Handler handler) {
   1503         addOnRoutingChangedListener((AudioRouting.OnRoutingChangedListener) listener, handler);
   1504     }
   1505 
   1506     /**
   1507       * Removes an {@link OnRoutingChangedListener} which has been previously added
   1508      * to receive rerouting notifications.
   1509      * @param listener The previously added {@link OnRoutingChangedListener} interface to remove.
   1510      * @deprecated users should switch to the general purpose
   1511      *             {@link AudioRouting.OnRoutingChangedListener} class instead.
   1512      */
   1513     @Deprecated
   1514     public void removeOnRoutingChangedListener(OnRoutingChangedListener listener) {
   1515         removeOnRoutingChangedListener((AudioRouting.OnRoutingChangedListener) listener);
   1516     }
   1517 
   1518     /**
   1519      * Helper class to handle the forwarding of native events to the appropriate listener
   1520      * (potentially) handled in a different thread
   1521      */
   1522     private class NativeRoutingEventHandlerDelegate {
   1523         private final Handler mHandler;
   1524 
   1525         NativeRoutingEventHandlerDelegate(final AudioRecord record,
   1526                                    final AudioRouting.OnRoutingChangedListener listener,
   1527                                    Handler handler) {
   1528             // find the looper for our new event handler
   1529             Looper looper;
   1530             if (handler != null) {
   1531                 looper = handler.getLooper();
   1532             } else {
   1533                 // no given handler, use the looper the AudioRecord was created in
   1534                 looper = mInitializationLooper;
   1535             }
   1536 
   1537             // construct the event handler with this looper
   1538             if (looper != null) {
   1539                 // implement the event handler delegate
   1540                 mHandler = new Handler(looper) {
   1541                     @Override
   1542                     public void handleMessage(Message msg) {
   1543                         if (record == null) {
   1544                             return;
   1545                         }
   1546                         switch(msg.what) {
   1547                         case AudioSystem.NATIVE_EVENT_ROUTING_CHANGE:
   1548                             if (listener != null) {
   1549                                 listener.onRoutingChanged(record);
   1550                             }
   1551                             break;
   1552                         default:
   1553                             loge("Unknown native event type: " + msg.what);
   1554                             break;
   1555                         }
   1556                     }
   1557                 };
   1558             } else {
   1559                 mHandler = null;
   1560             }
   1561         }
   1562 
   1563         Handler getHandler() {
   1564             return mHandler;
   1565         }
   1566     }
   1567 
   1568     /**
   1569      * Sends device list change notification to all listeners.
   1570      */
   1571     private void broadcastRoutingChange() {
   1572         AudioManager.resetAudioPortGeneration();
   1573         synchronized (mRoutingChangeListeners) {
   1574             for (NativeRoutingEventHandlerDelegate delegate : mRoutingChangeListeners.values()) {
   1575                 Handler handler = delegate.getHandler();
   1576                 if (handler != null) {
   1577                     handler.sendEmptyMessage(AudioSystem.NATIVE_EVENT_ROUTING_CHANGE);
   1578                 }
   1579             }
   1580         }
   1581     }
   1582 
   1583     /**
   1584      * Sets the period at which the listener is called, if set with
   1585      * {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener)} or
   1586      * {@link #setRecordPositionUpdateListener(OnRecordPositionUpdateListener, Handler)}.
   1587      * It is possible for notifications to be lost if the period is too small.
   1588      * @param periodInFrames update period expressed in frames
   1589      * @return error code or success, see {@link #SUCCESS}, {@link #ERROR_INVALID_OPERATION}
   1590      */
   1591     public int setPositionNotificationPeriod(int periodInFrames) {
   1592         if (mState == STATE_UNINITIALIZED) {
   1593             return ERROR_INVALID_OPERATION;
   1594         }
   1595         return native_set_pos_update_period(periodInFrames);
   1596     }
   1597 
   1598     //--------------------------------------------------------------------------
   1599     // Explicit Routing
   1600     //--------------------
   1601     private AudioDeviceInfo mPreferredDevice = null;
   1602 
   1603     /**
   1604      * Specifies an audio device (via an {@link AudioDeviceInfo} object) to route
   1605      * the input to this AudioRecord.
   1606      * @param deviceInfo The {@link AudioDeviceInfo} specifying the audio source.
   1607      *  If deviceInfo is null, default routing is restored.
   1608      * @return true if successful, false if the specified {@link AudioDeviceInfo} is non-null and
   1609      * does not correspond to a valid audio input device.
   1610      */
   1611     @Override
   1612     public boolean setPreferredDevice(AudioDeviceInfo deviceInfo) {
   1613         // Do some validation....
   1614         if (deviceInfo != null && !deviceInfo.isSource()) {
   1615             return false;
   1616         }
   1617 
   1618         int preferredDeviceId = deviceInfo != null ? deviceInfo.getId() : 0;
   1619         boolean status = native_setInputDevice(preferredDeviceId);
   1620         if (status == true) {
   1621             synchronized (this) {
   1622                 mPreferredDevice = deviceInfo;
   1623             }
   1624         }
   1625         return status;
   1626     }
   1627 
   1628     /**
   1629      * Returns the selected input specified by {@link #setPreferredDevice}. Note that this
   1630      * is not guarenteed to correspond to the actual device being used for recording.
   1631      */
   1632     @Override
   1633     public AudioDeviceInfo getPreferredDevice() {
   1634         synchronized (this) {
   1635             return mPreferredDevice;
   1636         }
   1637     }
   1638 
   1639     //---------------------------------------------------------
   1640     // Interface definitions
   1641     //--------------------
   1642     /**
   1643      * Interface definition for a callback to be invoked when an AudioRecord has
   1644      * reached a notification marker set by {@link AudioRecord#setNotificationMarkerPosition(int)}
   1645      * or for periodic updates on the progress of the record head, as set by
   1646      * {@link AudioRecord#setPositionNotificationPeriod(int)}.
   1647      */
   1648     public interface OnRecordPositionUpdateListener  {
   1649         /**
   1650          * Called on the listener to notify it that the previously set marker has been reached
   1651          * by the recording head.
   1652          */
   1653         void onMarkerReached(AudioRecord recorder);
   1654 
   1655         /**
   1656          * Called on the listener to periodically notify it that the record head has reached
   1657          * a multiple of the notification period.
   1658          */
   1659         void onPeriodicNotification(AudioRecord recorder);
   1660     }
   1661 
   1662 
   1663 
   1664     //---------------------------------------------------------
   1665     // Inner classes
   1666     //--------------------
   1667 
   1668     /**
   1669      * Helper class to handle the forwarding of native events to the appropriate listener
   1670      * (potentially) handled in a different thread
   1671      */
   1672     private class NativeEventHandler extends Handler {
   1673         private final AudioRecord mAudioRecord;
   1674 
   1675         NativeEventHandler(AudioRecord recorder, Looper looper) {
   1676             super(looper);
   1677             mAudioRecord = recorder;
   1678         }
   1679 
   1680         @Override
   1681         public void handleMessage(Message msg) {
   1682             OnRecordPositionUpdateListener listener = null;
   1683             synchronized (mPositionListenerLock) {
   1684                 listener = mAudioRecord.mPositionListener;
   1685             }
   1686 
   1687             switch (msg.what) {
   1688             case NATIVE_EVENT_MARKER:
   1689                 if (listener != null) {
   1690                     listener.onMarkerReached(mAudioRecord);
   1691                 }
   1692                 break;
   1693             case NATIVE_EVENT_NEW_POS:
   1694                 if (listener != null) {
   1695                     listener.onPeriodicNotification(mAudioRecord);
   1696                 }
   1697                 break;
   1698             default:
   1699                 loge("Unknown native event type: " + msg.what);
   1700                 break;
   1701             }
   1702         }
   1703     }
   1704 
   1705     //---------------------------------------------------------
   1706     // Java methods called from the native side
   1707     //--------------------
   1708     @SuppressWarnings("unused")
   1709     private static void postEventFromNative(Object audiorecord_ref,
   1710             int what, int arg1, int arg2, Object obj) {
   1711         //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2);
   1712         AudioRecord recorder = (AudioRecord)((WeakReference)audiorecord_ref).get();
   1713         if (recorder == null) {
   1714             return;
   1715         }
   1716 
   1717         if (what == AudioSystem.NATIVE_EVENT_ROUTING_CHANGE) {
   1718             recorder.broadcastRoutingChange();
   1719             return;
   1720         }
   1721 
   1722         if (recorder.mEventHandler != null) {
   1723             Message m =
   1724                 recorder.mEventHandler.obtainMessage(what, arg1, arg2, obj);
   1725             recorder.mEventHandler.sendMessage(m);
   1726         }
   1727 
   1728     }
   1729 
   1730 
   1731     //---------------------------------------------------------
   1732     // Native methods called from the Java side
   1733     //--------------------
   1734 
   1735     private native final int native_setup(Object audiorecord_this,
   1736             Object /*AudioAttributes*/ attributes,
   1737             int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
   1738             int buffSizeInBytes, int[] sessionId, String opPackageName,
   1739             long nativeRecordInJavaObj);
   1740 
   1741     // TODO remove: implementation calls directly into implementation of native_release()
   1742     private native final void native_finalize();
   1743 
   1744     /**
   1745      * @hide
   1746      */
   1747     public native final void native_release();
   1748 
   1749     private native final int native_start(int syncEvent, int sessionId);
   1750 
   1751     private native final void native_stop();
   1752 
   1753     private native final int native_read_in_byte_array(byte[] audioData,
   1754             int offsetInBytes, int sizeInBytes, boolean isBlocking);
   1755 
   1756     private native final int native_read_in_short_array(short[] audioData,
   1757             int offsetInShorts, int sizeInShorts, boolean isBlocking);
   1758 
   1759     private native final int native_read_in_float_array(float[] audioData,
   1760             int offsetInFloats, int sizeInFloats, boolean isBlocking);
   1761 
   1762     private native final int native_read_in_direct_buffer(Object jBuffer,
   1763             int sizeInBytes, boolean isBlocking);
   1764 
   1765     private native final int native_get_buffer_size_in_frames();
   1766 
   1767     private native final int native_set_marker_pos(int marker);
   1768     private native final int native_get_marker_pos();
   1769 
   1770     private native final int native_set_pos_update_period(int updatePeriod);
   1771     private native final int native_get_pos_update_period();
   1772 
   1773     static private native final int native_get_min_buff_size(
   1774             int sampleRateInHz, int channelCount, int audioFormat);
   1775 
   1776     private native final boolean native_setInputDevice(int deviceId);
   1777     private native final int native_getRoutedDeviceId();
   1778     private native final void native_enableDeviceCallback();
   1779     private native final void native_disableDeviceCallback();
   1780 
   1781     private native final int native_get_timestamp(@NonNull AudioTimestamp outTimestamp,
   1782             @AudioTimestamp.Timebase int timebase);
   1783 
   1784     //---------------------------------------------------------
   1785     // Utility methods
   1786     //------------------
   1787 
   1788     private static void logd(String msg) {
   1789         Log.d(TAG, msg);
   1790     }
   1791 
   1792     private static void loge(String msg) {
   1793         Log.e(TAG, msg);
   1794     }
   1795 }
   1796