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