1 /*
2 * Copyright (C) 2010 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 #include "sles_allinclusive.h"
18 #include "android_prompts.h"
19 #include "channels.h"
20
21 #include <utils/String16.h>
22
23 #include <system/audio.h>
24 #include <SLES/OpenSLES_Android.h>
25
26 #include <android_runtime/AndroidRuntime.h>
27
28 #define KEY_RECORDING_SOURCE_PARAMSIZE sizeof(SLuint32)
29 #define KEY_RECORDING_PRESET_PARAMSIZE sizeof(SLuint32)
30 #define KEY_PERFORMANCE_MODE_PARAMSIZE sizeof(SLuint32)
31
32 //-----------------------------------------------------------------------------
33 // Internal utility functions
34 //----------------------------
35
audioRecorder_setPreset(CAudioRecorder * ar,SLuint32 recordPreset)36 SLresult audioRecorder_setPreset(CAudioRecorder* ar, SLuint32 recordPreset) {
37 SLresult result = SL_RESULT_SUCCESS;
38
39 audio_source_t newRecordSource = AUDIO_SOURCE_DEFAULT;
40 switch (recordPreset) {
41 case SL_ANDROID_RECORDING_PRESET_GENERIC:
42 newRecordSource = AUDIO_SOURCE_DEFAULT;
43 break;
44 case SL_ANDROID_RECORDING_PRESET_CAMCORDER:
45 newRecordSource = AUDIO_SOURCE_CAMCORDER;
46 break;
47 case SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION:
48 newRecordSource = AUDIO_SOURCE_VOICE_RECOGNITION;
49 break;
50 case SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION:
51 newRecordSource = AUDIO_SOURCE_VOICE_COMMUNICATION;
52 break;
53 case SL_ANDROID_RECORDING_PRESET_UNPROCESSED:
54 newRecordSource = AUDIO_SOURCE_UNPROCESSED;
55 break;
56 case SL_ANDROID_RECORDING_PRESET_NONE:
57 // it is an error to set preset "none"
58 default:
59 SL_LOGE(ERROR_RECORDERPRESET_SET_UNKNOWN_PRESET);
60 result = SL_RESULT_PARAMETER_INVALID;
61 }
62
63 // recording preset needs to be set before the object is realized
64 // (ap->mAudioRecord is supposed to be 0 until then)
65 if (SL_OBJECT_STATE_UNREALIZED != ar->mObject.mState) {
66 SL_LOGE(ERROR_RECORDERPRESET_REALIZED);
67 result = SL_RESULT_PRECONDITIONS_VIOLATED;
68 } else {
69 ar->mRecordSource = newRecordSource;
70 }
71
72 return result;
73 }
74
75
76 //-----------------------------------------------------------------------------
audioRecorder_setPerformanceMode(CAudioRecorder * ar,SLuint32 mode)77 SLresult audioRecorder_setPerformanceMode(CAudioRecorder* ar, SLuint32 mode) {
78 SLresult result = SL_RESULT_SUCCESS;
79 SL_LOGV("performance mode set to %d", mode);
80
81 SLuint32 perfMode = ANDROID_PERFORMANCE_MODE_DEFAULT;
82 switch (mode) {
83 case SL_ANDROID_PERFORMANCE_LATENCY:
84 perfMode = ANDROID_PERFORMANCE_MODE_LATENCY;
85 break;
86 case SL_ANDROID_PERFORMANCE_LATENCY_EFFECTS:
87 perfMode = ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS;
88 break;
89 case SL_ANDROID_PERFORMANCE_NONE:
90 perfMode = ANDROID_PERFORMANCE_MODE_NONE;
91 break;
92 case SL_ANDROID_PERFORMANCE_POWER_SAVING:
93 perfMode = ANDROID_PERFORMANCE_MODE_POWER_SAVING;
94 break;
95 default:
96 SL_LOGE(ERROR_CONFIG_PERF_MODE_UNKNOWN);
97 result = SL_RESULT_PARAMETER_INVALID;
98 break;
99 }
100
101 // performance mode needs to be set before the object is realized
102 // (ar->mAudioRecord is supposed to be NULL until then)
103 if (SL_OBJECT_STATE_UNREALIZED != ar->mObject.mState) {
104 SL_LOGE(ERROR_CONFIG_PERF_MODE_REALIZED);
105 result = SL_RESULT_PRECONDITIONS_VIOLATED;
106 } else {
107 ar->mPerformanceMode = perfMode;
108 }
109
110 return result;
111 }
112
113
audioRecorder_getPreset(CAudioRecorder * ar,SLuint32 * pPreset)114 SLresult audioRecorder_getPreset(CAudioRecorder* ar, SLuint32* pPreset) {
115 SLresult result = SL_RESULT_SUCCESS;
116
117 switch (ar->mRecordSource) {
118 case AUDIO_SOURCE_DEFAULT:
119 case AUDIO_SOURCE_MIC:
120 *pPreset = SL_ANDROID_RECORDING_PRESET_GENERIC;
121 break;
122 case AUDIO_SOURCE_VOICE_UPLINK:
123 case AUDIO_SOURCE_VOICE_DOWNLINK:
124 case AUDIO_SOURCE_VOICE_CALL:
125 *pPreset = SL_ANDROID_RECORDING_PRESET_NONE;
126 break;
127 case AUDIO_SOURCE_VOICE_RECOGNITION:
128 *pPreset = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
129 break;
130 case AUDIO_SOURCE_CAMCORDER:
131 *pPreset = SL_ANDROID_RECORDING_PRESET_CAMCORDER;
132 break;
133 case AUDIO_SOURCE_VOICE_COMMUNICATION:
134 *pPreset = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
135 break;
136 case AUDIO_SOURCE_UNPROCESSED:
137 *pPreset = SL_ANDROID_RECORDING_PRESET_UNPROCESSED;
138 break;
139 default:
140 *pPreset = SL_ANDROID_RECORDING_PRESET_NONE;
141 result = SL_RESULT_INTERNAL_ERROR;
142 break;
143 }
144
145 return result;
146 }
147
148
149 //-----------------------------------------------------------------------------
audioRecorder_getPerformanceMode(CAudioRecorder * ar,SLuint32 * pMode)150 SLresult audioRecorder_getPerformanceMode(CAudioRecorder* ar, SLuint32 *pMode) {
151 SLresult result = SL_RESULT_SUCCESS;
152
153 switch (ar->mPerformanceMode) {
154 case ANDROID_PERFORMANCE_MODE_LATENCY:
155 *pMode = SL_ANDROID_PERFORMANCE_LATENCY;
156 break;
157 case ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS:
158 *pMode = SL_ANDROID_PERFORMANCE_LATENCY_EFFECTS;
159 break;
160 case ANDROID_PERFORMANCE_MODE_NONE:
161 *pMode = SL_ANDROID_PERFORMANCE_NONE;
162 break;
163 case ANDROID_PERFORMANCE_MODE_POWER_SAVING:
164 *pMode = SL_ANDROID_PERFORMANCE_POWER_SAVING;
165 break;
166 default:
167 result = SL_RESULT_INTERNAL_ERROR;
168 *pMode = SL_ANDROID_PERFORMANCE_LATENCY;
169 break;
170 }
171
172 return result;
173 }
174
175
audioRecorder_handleNewPos_lockRecord(CAudioRecorder * ar)176 void audioRecorder_handleNewPos_lockRecord(CAudioRecorder* ar) {
177 //SL_LOGV("received event EVENT_NEW_POS from AudioRecord");
178 slRecordCallback callback = NULL;
179 void* callbackPContext = NULL;
180
181 interface_lock_shared(&ar->mRecord);
182 callback = ar->mRecord.mCallback;
183 callbackPContext = ar->mRecord.mContext;
184 interface_unlock_shared(&ar->mRecord);
185
186 if (NULL != callback) {
187 // getting this event implies SL_RECORDEVENT_HEADATNEWPOS was set in the event mask
188 (*callback)(&ar->mRecord.mItf, callbackPContext, SL_RECORDEVENT_HEADATNEWPOS);
189 }
190 }
191
192
audioRecorder_handleMarker_lockRecord(CAudioRecorder * ar)193 void audioRecorder_handleMarker_lockRecord(CAudioRecorder* ar) {
194 //SL_LOGV("received event EVENT_MARKER from AudioRecord");
195 slRecordCallback callback = NULL;
196 void* callbackPContext = NULL;
197
198 interface_lock_shared(&ar->mRecord);
199 callback = ar->mRecord.mCallback;
200 callbackPContext = ar->mRecord.mContext;
201 interface_unlock_shared(&ar->mRecord);
202
203 if (NULL != callback) {
204 // getting this event implies SL_RECORDEVENT_HEADATMARKER was set in the event mask
205 (*callback)(&ar->mRecord.mItf, callbackPContext, SL_RECORDEVENT_HEADATMARKER);
206 }
207 }
208
209
audioRecorder_handleOverrun_lockRecord(CAudioRecorder * ar)210 void audioRecorder_handleOverrun_lockRecord(CAudioRecorder* ar) {
211 //SL_LOGV("received event EVENT_OVERRUN from AudioRecord");
212 slRecordCallback callback = NULL;
213 void* callbackPContext = NULL;
214
215 interface_lock_shared(&ar->mRecord);
216 if (ar->mRecord.mCallbackEventsMask & SL_RECORDEVENT_HEADSTALLED) {
217 callback = ar->mRecord.mCallback;
218 callbackPContext = ar->mRecord.mContext;
219 }
220 interface_unlock_shared(&ar->mRecord);
221
222 if (NULL != callback) {
223 (*callback)(&ar->mRecord.mItf, callbackPContext, SL_RECORDEVENT_HEADSTALLED);
224 }
225 }
226
227 //-----------------------------------------------------------------------------
android_audioRecorder_checkSourceSink(CAudioRecorder * ar)228 SLresult android_audioRecorder_checkSourceSink(CAudioRecorder* ar) {
229
230 const SLDataSource *pAudioSrc = &ar->mDataSource.u.mSource;
231 const SLDataSink *pAudioSnk = &ar->mDataSink.u.mSink;
232
233 const SLuint32 sinkLocatorType = *(SLuint32 *)pAudioSnk->pLocator;
234 const SLuint32 sinkFormatType = *(SLuint32 *)pAudioSnk->pFormat;
235
236 const SLuint32 *df_representation = NULL; // pointer to representation field, if it exists
237
238 // sink must be an Android simple buffer queue with PCM data format
239 switch (sinkLocatorType) {
240 case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE: {
241 switch (sinkFormatType) {
242 case SL_ANDROID_DATAFORMAT_PCM_EX: {
243 const SLAndroidDataFormat_PCM_EX *df_pcm =
244 (SLAndroidDataFormat_PCM_EX *) pAudioSnk->pFormat;
245 // checkDataFormat() already checked representation
246 df_representation = &df_pcm->representation;
247 } // SL_ANDROID_DATAFORMAT_PCM_EX - fall through to next test.
248 FALLTHROUGH_INTENDED;
249 case SL_DATAFORMAT_PCM: {
250 const SLDataFormat_PCM *df_pcm = (const SLDataFormat_PCM *) pAudioSnk->pFormat;
251 // checkDataFormat already checked sample rate, channels, and mask
252 ar->mNumChannels = df_pcm->numChannels;
253
254 if (df_pcm->endianness != ar->mObject.mEngine->mEngine.mNativeEndianness) {
255 SL_LOGE("Cannot create audio recorder: unsupported byte order %u",
256 df_pcm->endianness);
257 return SL_RESULT_CONTENT_UNSUPPORTED;
258 }
259
260 ar->mSampleRateMilliHz = df_pcm->samplesPerSec; // Note: bad field name in SL ES
261 SL_LOGV("AudioRecorder requested sample rate = %u mHz, %u channel(s)",
262 ar->mSampleRateMilliHz, ar->mNumChannels);
263
264 // we don't support container size != sample depth
265 if (df_pcm->containerSize != df_pcm->bitsPerSample) {
266 SL_LOGE("Cannot create audio recorder: unsupported container size %u bits for "
267 "sample depth %u bits",
268 df_pcm->containerSize, (SLuint32)df_pcm->bitsPerSample);
269 return SL_RESULT_CONTENT_UNSUPPORTED;
270 }
271
272 } break;
273 default:
274 SL_LOGE(ERROR_RECORDER_SINK_FORMAT_MUST_BE_PCM);
275 return SL_RESULT_PARAMETER_INVALID;
276 } // switch (sourceFormatType)
277 } break; // case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE
278 default:
279 SL_LOGE(ERROR_RECORDER_SINK_MUST_BE_ANDROIDSIMPLEBUFFERQUEUE);
280 return SL_RESULT_PARAMETER_INVALID;
281 } // switch (sourceLocatorType)
282
283 // Source check:
284 // only input device sources are supported
285 // check it's an IO device
286 if (SL_DATALOCATOR_IODEVICE != *(SLuint32 *)pAudioSrc->pLocator) {
287 SL_LOGE(ERROR_RECORDER_SOURCE_MUST_BE_IODEVICE);
288 return SL_RESULT_PARAMETER_INVALID;
289 } else {
290
291 // check it's an input device
292 SLDataLocator_IODevice *dl_iod = (SLDataLocator_IODevice *) pAudioSrc->pLocator;
293 if (SL_IODEVICE_AUDIOINPUT != dl_iod->deviceType) {
294 SL_LOGE(ERROR_RECORDER_IODEVICE_MUST_BE_AUDIOINPUT);
295 return SL_RESULT_PARAMETER_INVALID;
296 }
297
298 // check it's the default input device, others aren't supported here
299 if (SL_DEFAULTDEVICEID_AUDIOINPUT != dl_iod->deviceID) {
300 SL_LOGE(ERROR_RECORDER_INPUT_ID_MUST_BE_DEFAULT);
301 return SL_RESULT_PARAMETER_INVALID;
302 }
303 }
304
305 return SL_RESULT_SUCCESS;
306 }
307 //-----------------------------------------------------------------------------
audioRecorder_callback(int event,void * user,void * info)308 static void audioRecorder_callback(int event, void* user, void *info) {
309 //SL_LOGV("audioRecorder_callback(%d, %p, %p) entering", event, user, info);
310
311 CAudioRecorder *ar = (CAudioRecorder *)user;
312
313 if (!android::CallbackProtector::enterCbIfOk(ar->mCallbackProtector)) {
314 // it is not safe to enter the callback (the track is about to go away)
315 return;
316 }
317
318 void * callbackPContext = NULL;
319
320 switch (event) {
321 case android::AudioRecord::EVENT_MORE_DATA: {
322 slBufferQueueCallback callback = NULL;
323 android::AudioRecord::Buffer* pBuff = (android::AudioRecord::Buffer*)info;
324
325 // push data to the buffer queue
326 interface_lock_exclusive(&ar->mBufferQueue);
327
328 if (ar->mBufferQueue.mState.count != 0) {
329 assert(ar->mBufferQueue.mFront != ar->mBufferQueue.mRear);
330
331 BufferHeader *oldFront = ar->mBufferQueue.mFront;
332 BufferHeader *newFront = &oldFront[1];
333
334 size_t availSink = oldFront->mSize - ar->mBufferQueue.mSizeConsumed;
335 size_t availSource = pBuff->size;
336 size_t bytesToCopy = availSink < availSource ? availSink : availSource;
337 void *pDest = (char *)oldFront->mBuffer + ar->mBufferQueue.mSizeConsumed;
338 memcpy(pDest, pBuff->raw, bytesToCopy);
339
340 if (bytesToCopy < availSink) {
341 // can't consume the whole or rest of the buffer in one shot
342 ar->mBufferQueue.mSizeConsumed += availSource;
343 // pBuff->size is already equal to bytesToCopy in this case
344 } else {
345 // finish pushing the buffer or push the buffer in one shot
346 pBuff->size = bytesToCopy;
347 ar->mBufferQueue.mSizeConsumed = 0;
348 if (newFront == &ar->mBufferQueue.mArray[ar->mBufferQueue.mNumBuffers + 1]) {
349 newFront = ar->mBufferQueue.mArray;
350 }
351 ar->mBufferQueue.mFront = newFront;
352
353 ar->mBufferQueue.mState.count--;
354 ar->mBufferQueue.mState.playIndex++;
355
356 // data has been copied to the buffer, and the buffer queue state has been updated
357 // we will notify the client if applicable
358 callback = ar->mBufferQueue.mCallback;
359 // save callback data
360 callbackPContext = ar->mBufferQueue.mContext;
361 }
362 } else { // empty queue
363 // no destination to push the data
364 pBuff->size = 0;
365 }
366
367 interface_unlock_exclusive(&ar->mBufferQueue);
368
369 // notify client
370 if (NULL != callback) {
371 (*callback)(&ar->mBufferQueue.mItf, callbackPContext);
372 }
373 }
374 break;
375
376 case android::AudioRecord::EVENT_OVERRUN:
377 audioRecorder_handleOverrun_lockRecord(ar);
378 break;
379
380 case android::AudioRecord::EVENT_MARKER:
381 audioRecorder_handleMarker_lockRecord(ar);
382 break;
383
384 case android::AudioRecord::EVENT_NEW_POS:
385 audioRecorder_handleNewPos_lockRecord(ar);
386 break;
387
388 case android::AudioRecord::EVENT_NEW_IAUDIORECORD:
389 // ignore for now
390 break;
391
392 default:
393 SL_LOGE("Encountered unknown AudioRecord event %d for CAudioRecord %p", event, ar);
394 break;
395 }
396
397 ar->mCallbackProtector->exitCb();
398 }
399
400
401 //-----------------------------------------------------------------------------
android_audioRecorder_create(CAudioRecorder * ar)402 SLresult android_audioRecorder_create(CAudioRecorder* ar) {
403 SL_LOGV("android_audioRecorder_create(%p) entering", ar);
404
405 const SLDataSource *pAudioSrc = &ar->mDataSource.u.mSource;
406 const SLDataSink *pAudioSnk = &ar->mDataSink.u.mSink;
407 SLresult result = SL_RESULT_SUCCESS;
408
409 const SLuint32 sourceLocatorType = *(SLuint32 *)pAudioSrc->pLocator;
410 const SLuint32 sinkLocatorType = *(SLuint32 *)pAudioSnk->pLocator;
411
412 // the following platform-independent fields have been initialized in CreateAudioRecorder()
413 // ar->mNumChannels
414 // ar->mSampleRateMilliHz
415
416 if ((SL_DATALOCATOR_IODEVICE == sourceLocatorType) &&
417 (SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE == sinkLocatorType)) {
418 // microphone to simple buffer queue
419 ar->mAndroidObjType = AUDIORECORDER_FROM_MIC_TO_PCM_BUFFERQUEUE;
420 ar->mAudioRecord.clear();
421 ar->mCallbackProtector = new android::CallbackProtector();
422 ar->mRecordSource = AUDIO_SOURCE_DEFAULT;
423 ar->mPerformanceMode = ANDROID_PERFORMANCE_MODE_DEFAULT;
424 } else {
425 result = SL_RESULT_CONTENT_UNSUPPORTED;
426 }
427
428 return result;
429 }
430
431
432 //-----------------------------------------------------------------------------
android_audioRecorder_setConfig(CAudioRecorder * ar,const SLchar * configKey,const void * pConfigValue,SLuint32 valueSize)433 SLresult android_audioRecorder_setConfig(CAudioRecorder* ar, const SLchar *configKey,
434 const void *pConfigValue, SLuint32 valueSize) {
435
436 SLresult result;
437
438 assert(NULL != ar && NULL != configKey && NULL != pConfigValue);
439 if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_RECORDING_PRESET) == 0) {
440
441 // recording preset
442 if (KEY_RECORDING_PRESET_PARAMSIZE > valueSize) {
443 SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW);
444 result = SL_RESULT_BUFFER_INSUFFICIENT;
445 } else {
446 result = audioRecorder_setPreset(ar, *(SLuint32*)pConfigValue);
447 }
448
449 } else if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_PERFORMANCE_MODE) == 0) {
450
451 // performance mode
452 if (KEY_PERFORMANCE_MODE_PARAMSIZE > valueSize) {
453 SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW);
454 result = SL_RESULT_BUFFER_INSUFFICIENT;
455 } else {
456 result = audioRecorder_setPerformanceMode(ar, *(SLuint32*)pConfigValue);
457 }
458 } else {
459 SL_LOGE(ERROR_CONFIG_UNKNOWN_KEY);
460 result = SL_RESULT_PARAMETER_INVALID;
461 }
462
463 return result;
464 }
465
466
467 //-----------------------------------------------------------------------------
android_audioRecorder_getConfig(CAudioRecorder * ar,const SLchar * configKey,SLuint32 * pValueSize,void * pConfigValue)468 SLresult android_audioRecorder_getConfig(CAudioRecorder* ar, const SLchar *configKey,
469 SLuint32* pValueSize, void *pConfigValue) {
470
471 SLresult result;
472
473 assert(NULL != ar && NULL != configKey && NULL != pValueSize);
474 if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_RECORDING_PRESET) == 0) {
475
476 // recording preset
477 if (NULL == pConfigValue) {
478 result = SL_RESULT_SUCCESS;
479 } else if (KEY_RECORDING_PRESET_PARAMSIZE > *pValueSize) {
480 SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW);
481 result = SL_RESULT_BUFFER_INSUFFICIENT;
482 } else {
483 result = audioRecorder_getPreset(ar, (SLuint32*)pConfigValue);
484 }
485 *pValueSize = KEY_RECORDING_PRESET_PARAMSIZE;
486
487 } else if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_PERFORMANCE_MODE) == 0) {
488
489 // performance mode
490 if (NULL == pConfigValue) {
491 result = SL_RESULT_SUCCESS;
492 } else if (KEY_PERFORMANCE_MODE_PARAMSIZE > *pValueSize) {
493 SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW);
494 result = SL_RESULT_BUFFER_INSUFFICIENT;
495 } else {
496 result = audioRecorder_getPerformanceMode(ar, (SLuint32*)pConfigValue);
497 }
498 *pValueSize = KEY_PERFORMANCE_MODE_PARAMSIZE;
499
500 } else {
501 SL_LOGE(ERROR_CONFIG_UNKNOWN_KEY);
502 result = SL_RESULT_PARAMETER_INVALID;
503 }
504
505 return result;
506 }
507
508 // Called from android_audioRecorder_realize for a PCM buffer queue recorder before creating the
509 // AudioRecord to determine which performance modes are allowed based on effect interfaces present
checkAndSetPerformanceModePre(CAudioRecorder * ar)510 static void checkAndSetPerformanceModePre(CAudioRecorder* ar)
511 {
512 SLuint32 allowedModes = ANDROID_PERFORMANCE_MODE_ALL;
513 assert(ar->mAndroidObjType == AUDIORECORDER_FROM_MIC_TO_PCM_BUFFERQUEUE);
514
515 // no need to check the buffer queue size, application side
516 // double-buffering (and more) is not a requirement for using fast tracks
517
518 // Check a denylist of interfaces that are incompatible with fast tracks.
519 // The alternative, to check a allowlist of compatible interfaces, is
520 // more maintainable but is too slow. As a compromise, in a debug build
521 // we use both methods and warn if they produce different results.
522 // In release builds, we only use the denylist method.
523 // If a denylisted interface is added after realization using
524 // DynamicInterfaceManagement::AddInterface,
525 // then this won't be detected but the interface will be ineffective.
526 static const unsigned denylist[] = {
527 MPH_ANDROIDACOUSTICECHOCANCELLATION,
528 MPH_ANDROIDAUTOMATICGAINCONTROL,
529 MPH_ANDROIDNOISESUPPRESSION,
530 MPH_ANDROIDEFFECT,
531 // FIXME The problem with a denylist is remembering to add new interfaces here
532 };
533
534 for (unsigned i = 0; i < sizeof(denylist)/sizeof(denylist[0]); ++i) {
535 if (IsInterfaceInitialized(&ar->mObject, denylist[i])) {
536 uint32_t flags = 0;
537
538 allowedModes &= ~ANDROID_PERFORMANCE_MODE_LATENCY;
539
540 // if generic effect interface is used we don't know which effect will be used and
541 // disable all low latency performance modes
542 if (denylist[i] != MPH_ANDROIDEFFECT) {
543 switch (denylist[i]) {
544 case MPH_ANDROIDACOUSTICECHOCANCELLATION:
545 SL_LOGV("checkAndSetPerformanceModePre found AEC name %s",
546 ar->mAcousticEchoCancellation.mAECDescriptor.name);
547 flags = ar->mAcousticEchoCancellation.mAECDescriptor.flags;
548 break;
549 case MPH_ANDROIDAUTOMATICGAINCONTROL:
550 SL_LOGV("checkAndSetPerformanceModePre found AGC name %s",
551 ar->mAutomaticGainControl.mAGCDescriptor.name);
552 flags = ar->mAutomaticGainControl.mAGCDescriptor.flags;
553 break;
554 case MPH_ANDROIDNOISESUPPRESSION:
555 SL_LOGV("checkAndSetPerformanceModePre found NS name %s",
556 ar->mNoiseSuppression.mNSDescriptor.name);
557 flags = ar->mNoiseSuppression.mNSDescriptor.flags;
558 break;
559 default:
560 break;
561 }
562 }
563 if ((flags & EFFECT_FLAG_HW_ACC_TUNNEL) == 0) {
564 allowedModes &= ~ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS;
565 break;
566 }
567 }
568 }
569 #if LOG_NDEBUG == 0
570 bool denylistResult = (
571 (allowedModes &
572 (ANDROID_PERFORMANCE_MODE_LATENCY|ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS)) != 0);
573 bool allowlistResult = true;
574 static const unsigned allowlist[] = {
575 MPH_BUFFERQUEUE,
576 MPH_DYNAMICINTERFACEMANAGEMENT,
577 MPH_OBJECT,
578 MPH_RECORD,
579 MPH_ANDROIDCONFIGURATION,
580 MPH_ANDROIDSIMPLEBUFFERQUEUE,
581 };
582 for (unsigned mph = MPH_MIN; mph < MPH_MAX; ++mph) {
583 for (unsigned i = 0; i < sizeof(allowlist)/sizeof(allowlist[0]); ++i) {
584 if (mph == allowlist[i]) {
585 goto compatible;
586 }
587 }
588 if (IsInterfaceInitialized(&ar->mObject, mph)) {
589 allowlistResult = false;
590 break;
591 }
592 compatible: ;
593 }
594 if (allowlistResult != denylistResult) {
595 SL_LOGW("allowlistResult != denylistResult");
596 }
597 #endif
598 if (ar->mPerformanceMode == ANDROID_PERFORMANCE_MODE_LATENCY) {
599 if ((allowedModes & ANDROID_PERFORMANCE_MODE_LATENCY) == 0) {
600 ar->mPerformanceMode = ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS;
601 }
602 }
603 if (ar->mPerformanceMode == ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS) {
604 if ((allowedModes & ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS) == 0) {
605 ar->mPerformanceMode = ANDROID_PERFORMANCE_MODE_NONE;
606 }
607 }
608 }
609
610 // Called from android_audioRecorder_realize for a PCM buffer queue recorder after creating the
611 // AudioRecord to adjust performance mode based on actual input flags
checkAndSetPerformanceModePost(CAudioRecorder * ar)612 static void checkAndSetPerformanceModePost(CAudioRecorder* ar)
613 {
614 audio_input_flags_t flags = ar->mAudioRecord->getFlags();
615 switch (ar->mPerformanceMode) {
616 case ANDROID_PERFORMANCE_MODE_LATENCY:
617 if ((flags & (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW)) ==
618 (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW)) {
619 break;
620 }
621 ar->mPerformanceMode = ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS;
622 FALLTHROUGH_INTENDED;
623 case ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS:
624 if ((flags & AUDIO_INPUT_FLAG_FAST) == 0) {
625 ar->mPerformanceMode = ANDROID_PERFORMANCE_MODE_NONE;
626 }
627 break;
628 case ANDROID_PERFORMANCE_MODE_NONE:
629 default:
630 break;
631 }
632 }
633 //-----------------------------------------------------------------------------
android_audioRecorder_realize(CAudioRecorder * ar,SLboolean async)634 SLresult android_audioRecorder_realize(CAudioRecorder* ar, SLboolean async) {
635 SL_LOGV("android_audioRecorder_realize(%p) entering", ar);
636
637 SLresult result = SL_RESULT_SUCCESS;
638
639 // already checked in created and checkSourceSink
640 assert(ar->mDataSink.mLocator.mLocatorType == SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE);
641
642 const SLDataFormat_PCM *df_pcm = &ar->mDataSink.mFormat.mPCM;
643
644 // the following platform-independent fields have been initialized in CreateAudioRecorder()
645 // ar->mNumChannels
646 // ar->mSampleRateMilliHz
647
648 uint32_t sampleRate = sles_to_android_sampleRate(df_pcm->samplesPerSec);
649
650 checkAndSetPerformanceModePre(ar);
651
652 audio_input_flags_t policy;
653 switch (ar->mPerformanceMode) {
654 case ANDROID_PERFORMANCE_MODE_NONE:
655 case ANDROID_PERFORMANCE_MODE_POWER_SAVING:
656 policy = AUDIO_INPUT_FLAG_NONE;
657 break;
658 case ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS:
659 policy = AUDIO_INPUT_FLAG_FAST;
660 break;
661 case ANDROID_PERFORMANCE_MODE_LATENCY:
662 default:
663 policy = (audio_input_flags_t)(AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW);
664 break;
665 }
666
667 SL_LOGV("Audio Record format: %dch(0x%x), %dbit, %dKHz",
668 df_pcm->numChannels,
669 df_pcm->channelMask,
670 df_pcm->bitsPerSample,
671 df_pcm->samplesPerSec / 1000000);
672
673 // note that df_pcm->channelMask has already been validated during object creation.
674 audio_channel_mask_t channelMask = sles_to_audio_input_channel_mask(df_pcm->channelMask);
675
676 // To maintain backward compatibility with previous releases, ignore
677 // channel masks that are not indexed.
678 if (channelMask == AUDIO_CHANNEL_INVALID
679 || audio_channel_mask_get_representation(channelMask)
680 == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
681 channelMask = audio_channel_in_mask_from_count(df_pcm->numChannels);
682 SL_LOGI("Emulating old channel mask behavior "
683 "(ignoring positional mask %#x, using default mask %#x based on "
684 "channel count of %d)", df_pcm->channelMask, channelMask,
685 df_pcm->numChannels);
686 }
687 SL_LOGV("SLES channel mask %#x converted to Android mask %#x", df_pcm->channelMask,
688 channelMask);
689
690 // initialize platform-specific CAudioRecorder fields
691 ar->mAudioRecord = new android::AudioRecord(
692 ar->mRecordSource, // source
693 sampleRate, // sample rate in Hertz
694 sles_to_android_sampleFormat(df_pcm), // format
695 channelMask, // channel mask
696 android::String16(), // app ops
697 0, // frameCount
698 audioRecorder_callback,// callback_t
699 (void*)ar, // user, callback data, here the AudioRecorder
700 0, // notificationFrames
701 AUDIO_SESSION_ALLOCATE,
702 android::AudioRecord::TRANSFER_CALLBACK,
703 // transfer type
704 policy); // audio_input_flags_t
705
706 android::status_t status = ar->mAudioRecord->initCheck();
707 if (android::NO_ERROR != status) {
708 SL_LOGE("android_audioRecorder_realize(%p) error creating AudioRecord object; status %d",
709 ar, status);
710 // FIXME should return a more specific result depending on status
711 result = SL_RESULT_CONTENT_UNSUPPORTED;
712 ar->mAudioRecord.clear();
713 return result;
714 }
715
716 // update performance mode according to actual flags granted to AudioRecord
717 checkAndSetPerformanceModePost(ar);
718
719 // If there is a JavaAudioRoutingProxy associated with this recorder, hook it up...
720 JNIEnv* j_env = NULL;
721 jclass clsAudioRecord = NULL;
722 jmethodID midRoutingProxy_connect = NULL;
723 if (ar->mAndroidConfiguration.mRoutingProxy != NULL &&
724 (j_env = android::AndroidRuntime::getJNIEnv()) != NULL &&
725 (clsAudioRecord = j_env->FindClass("android/media/AudioRecord")) != NULL &&
726 (midRoutingProxy_connect =
727 j_env->GetMethodID(clsAudioRecord, "deferred_connect", "(J)V")) != NULL) {
728 j_env->ExceptionClear();
729 j_env->CallVoidMethod(ar->mAndroidConfiguration.mRoutingProxy,
730 midRoutingProxy_connect,
731 ar->mAudioRecord.get());
732 if (j_env->ExceptionCheck()) {
733 SL_LOGE("Java exception releasing recorder routing object.");
734 result = SL_RESULT_INTERNAL_ERROR;
735 ar->mAudioRecord.clear();
736 return result;
737 }
738 }
739
740 if (ar->mPerformanceMode != ANDROID_PERFORMANCE_MODE_LATENCY) {
741 audio_session_t sessionId = ar->mAudioRecord->getSessionId();
742 // initialize AEC
743 effect_descriptor_t *descriptor = &ar->mAcousticEchoCancellation.mAECDescriptor;
744 if (memcmp(SL_IID_ANDROIDACOUSTICECHOCANCELLATION, &descriptor->type,
745 sizeof(effect_uuid_t)) == 0) {
746 if ((ar->mPerformanceMode != ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS) ||
747 (descriptor->flags & EFFECT_FLAG_HW_ACC_TUNNEL)) {
748 SL_LOGV("Need to initialize AEC for AudioRecorder=%p", ar);
749 android_aec_init(sessionId, &ar->mAcousticEchoCancellation);
750 }
751 }
752
753 // initialize AGC
754 descriptor = &ar->mAutomaticGainControl.mAGCDescriptor;
755 if (memcmp(SL_IID_ANDROIDAUTOMATICGAINCONTROL, &descriptor->type,
756 sizeof(effect_uuid_t)) == 0) {
757 if ((ar->mPerformanceMode != ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS) ||
758 (descriptor->flags & EFFECT_FLAG_HW_ACC_TUNNEL)) {
759 SL_LOGV("Need to initialize AGC for AudioRecorder=%p", ar);
760 android_agc_init(sessionId, &ar->mAutomaticGainControl);
761 }
762 }
763
764 // initialize NS
765 descriptor = &ar->mNoiseSuppression.mNSDescriptor;
766 if (memcmp(SL_IID_ANDROIDNOISESUPPRESSION, &descriptor->type,
767 sizeof(effect_uuid_t)) == 0) {
768 if ((ar->mPerformanceMode != ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS) ||
769 (descriptor->flags & EFFECT_FLAG_HW_ACC_TUNNEL)) {
770 SL_LOGV("Need to initialize NS for AudioRecorder=%p", ar);
771 android_ns_init(sessionId, &ar->mNoiseSuppression);
772 }
773 }
774 }
775
776 return result;
777 }
778
779
780 //-----------------------------------------------------------------------------
781 /**
782 * Called with a lock on AudioRecorder, and blocks until safe to destroy
783 */
android_audioRecorder_preDestroy(CAudioRecorder * ar)784 void android_audioRecorder_preDestroy(CAudioRecorder* ar) {
785 object_unlock_exclusive(&ar->mObject);
786 if (ar->mCallbackProtector != 0) {
787 ar->mCallbackProtector->requestCbExitAndWait();
788 }
789 object_lock_exclusive(&ar->mObject);
790 }
791
792
793 //-----------------------------------------------------------------------------
android_audioRecorder_destroy(CAudioRecorder * ar)794 void android_audioRecorder_destroy(CAudioRecorder* ar) {
795 SL_LOGV("android_audioRecorder_destroy(%p) entering", ar);
796
797 if (ar->mAudioRecord != 0) {
798 ar->mAudioRecord->stop();
799 ar->mAudioRecord.clear();
800 }
801 // explicit destructor
802 ar->mAudioRecord.~sp();
803 ar->mCallbackProtector.~sp();
804 }
805
806
807 //-----------------------------------------------------------------------------
android_audioRecorder_setRecordState(CAudioRecorder * ar,SLuint32 state)808 void android_audioRecorder_setRecordState(CAudioRecorder* ar, SLuint32 state) {
809 SL_LOGV("android_audioRecorder_setRecordState(%p, %u) entering", ar, state);
810
811 if (ar->mAudioRecord == 0) {
812 return;
813 }
814
815 switch (state) {
816 case SL_RECORDSTATE_STOPPED:
817 ar->mAudioRecord->stop();
818 break;
819 case SL_RECORDSTATE_PAUSED:
820 // Note that pausing is treated like stop as this implementation only records to a buffer
821 // queue, so there is no notion of destination being "opened" or "closed" (See description
822 // of SL_RECORDSTATE in specification)
823 ar->mAudioRecord->stop();
824 break;
825 case SL_RECORDSTATE_RECORDING:
826 ar->mAudioRecord->start();
827 break;
828 default:
829 break;
830 }
831
832 }
833
834
835 //-----------------------------------------------------------------------------
android_audioRecorder_useRecordEventMask(CAudioRecorder * ar)836 void android_audioRecorder_useRecordEventMask(CAudioRecorder *ar) {
837 IRecord *pRecordItf = &ar->mRecord;
838 SLuint32 eventFlags = pRecordItf->mCallbackEventsMask;
839
840 if (ar->mAudioRecord == 0) {
841 return;
842 }
843
844 if ((eventFlags & SL_RECORDEVENT_HEADATMARKER) && (pRecordItf->mMarkerPosition != 0)) {
845 ar->mAudioRecord->setMarkerPosition((uint32_t)((((int64_t)pRecordItf->mMarkerPosition
846 * sles_to_android_sampleRate(ar->mSampleRateMilliHz)))/1000));
847 } else {
848 // clear marker
849 ar->mAudioRecord->setMarkerPosition(0);
850 }
851
852 if (eventFlags & SL_RECORDEVENT_HEADATNEWPOS) {
853 SL_LOGV("pos update period %d", pRecordItf->mPositionUpdatePeriod);
854 ar->mAudioRecord->setPositionUpdatePeriod(
855 (uint32_t)((((int64_t)pRecordItf->mPositionUpdatePeriod
856 * sles_to_android_sampleRate(ar->mSampleRateMilliHz)))/1000));
857 } else {
858 // clear periodic update
859 ar->mAudioRecord->setPositionUpdatePeriod(0);
860 }
861
862 if (eventFlags & SL_RECORDEVENT_HEADATLIMIT) {
863 // FIXME support SL_RECORDEVENT_HEADATLIMIT
864 SL_LOGD("[ FIXME: IRecord_SetCallbackEventsMask(SL_RECORDEVENT_HEADATLIMIT) on an "
865 "SL_OBJECTID_AUDIORECORDER to be implemented ]");
866 }
867
868 if (eventFlags & SL_RECORDEVENT_HEADMOVING) {
869 // FIXME support SL_RECORDEVENT_HEADMOVING
870 SL_LOGD("[ FIXME: IRecord_SetCallbackEventsMask(SL_RECORDEVENT_HEADMOVING) on an "
871 "SL_OBJECTID_AUDIORECORDER to be implemented ]");
872 }
873
874 if (eventFlags & SL_RECORDEVENT_BUFFER_FULL) {
875 // nothing to do for SL_RECORDEVENT_BUFFER_FULL since this will not be encountered on
876 // recording to buffer queues
877 }
878
879 if (eventFlags & SL_RECORDEVENT_HEADSTALLED) {
880 // nothing to do for SL_RECORDEVENT_HEADSTALLED, callback event will be checked against mask
881 // when AudioRecord::EVENT_OVERRUN is encountered
882
883 }
884
885 }
886
887
888 //-----------------------------------------------------------------------------
android_audioRecorder_getPosition(CAudioRecorder * ar,SLmillisecond * pPosMsec)889 void android_audioRecorder_getPosition(CAudioRecorder *ar, SLmillisecond *pPosMsec) {
890 if ((NULL == ar) || (ar->mAudioRecord == 0)) {
891 *pPosMsec = 0;
892 } else {
893 uint32_t positionInFrames;
894 ar->mAudioRecord->getPosition(&positionInFrames);
895 if (ar->mSampleRateMilliHz == UNKNOWN_SAMPLERATE) {
896 *pPosMsec = 0;
897 } else {
898 *pPosMsec = ((int64_t)positionInFrames * 1000) /
899 sles_to_android_sampleRate(ar->mSampleRateMilliHz);
900 }
901 }
902 }
903