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