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