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 case SL_DATAFORMAT_PCM: {
249 const SLDataFormat_PCM *df_pcm = (const SLDataFormat_PCM *) pAudioSnk->pFormat;
250 // checkDataFormat already checked sample rate, channels, and mask
251 ar->mNumChannels = df_pcm->numChannels;
252
253 if (df_pcm->endianness != ar->mObject.mEngine->mEngine.mNativeEndianness) {
254 SL_LOGE("Cannot create audio recorder: unsupported byte order %u",
255 df_pcm->endianness);
256 return SL_RESULT_CONTENT_UNSUPPORTED;
257 }
258
259 ar->mSampleRateMilliHz = df_pcm->samplesPerSec; // Note: bad field name in SL ES
260 SL_LOGV("AudioRecorder requested sample rate = %u mHz, %u channel(s)",
261 ar->mSampleRateMilliHz, ar->mNumChannels);
262
263 // we don't support container size != sample depth
264 if (df_pcm->containerSize != df_pcm->bitsPerSample) {
265 SL_LOGE("Cannot create audio recorder: unsupported container size %u bits for "
266 "sample depth %u bits",
267 df_pcm->containerSize, (SLuint32)df_pcm->bitsPerSample);
268 return SL_RESULT_CONTENT_UNSUPPORTED;
269 }
270
271 } break;
272 default:
273 SL_LOGE(ERROR_RECORDER_SINK_FORMAT_MUST_BE_PCM);
274 return SL_RESULT_PARAMETER_INVALID;
275 } // switch (sourceFormatType)
276 } break; // case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE
277 default:
278 SL_LOGE(ERROR_RECORDER_SINK_MUST_BE_ANDROIDSIMPLEBUFFERQUEUE);
279 return SL_RESULT_PARAMETER_INVALID;
280 } // switch (sourceLocatorType)
281
282 // Source check:
283 // only input device sources are supported
284 // check it's an IO device
285 if (SL_DATALOCATOR_IODEVICE != *(SLuint32 *)pAudioSrc->pLocator) {
286 SL_LOGE(ERROR_RECORDER_SOURCE_MUST_BE_IODEVICE);
287 return SL_RESULT_PARAMETER_INVALID;
288 } else {
289
290 // check it's an input device
291 SLDataLocator_IODevice *dl_iod = (SLDataLocator_IODevice *) pAudioSrc->pLocator;
292 if (SL_IODEVICE_AUDIOINPUT != dl_iod->deviceType) {
293 SL_LOGE(ERROR_RECORDER_IODEVICE_MUST_BE_AUDIOINPUT);
294 return SL_RESULT_PARAMETER_INVALID;
295 }
296
297 // check it's the default input device, others aren't supported here
298 if (SL_DEFAULTDEVICEID_AUDIOINPUT != dl_iod->deviceID) {
299 SL_LOGE(ERROR_RECORDER_INPUT_ID_MUST_BE_DEFAULT);
300 return SL_RESULT_PARAMETER_INVALID;
301 }
302 }
303
304 return SL_RESULT_SUCCESS;
305 }
306 //-----------------------------------------------------------------------------
audioRecorder_callback(int event,void * user,void * info)307 static void audioRecorder_callback(int event, void* user, void *info) {
308 //SL_LOGV("audioRecorder_callback(%d, %p, %p) entering", event, user, info);
309
310 CAudioRecorder *ar = (CAudioRecorder *)user;
311
312 if (!android::CallbackProtector::enterCbIfOk(ar->mCallbackProtector)) {
313 // it is not safe to enter the callback (the track is about to go away)
314 return;
315 }
316
317 void * callbackPContext = NULL;
318
319 switch (event) {
320 case android::AudioRecord::EVENT_MORE_DATA: {
321 slBufferQueueCallback callback = NULL;
322 android::AudioRecord::Buffer* pBuff = (android::AudioRecord::Buffer*)info;
323
324 // push data to the buffer queue
325 interface_lock_exclusive(&ar->mBufferQueue);
326
327 if (ar->mBufferQueue.mState.count != 0) {
328 assert(ar->mBufferQueue.mFront != ar->mBufferQueue.mRear);
329
330 BufferHeader *oldFront = ar->mBufferQueue.mFront;
331 BufferHeader *newFront = &oldFront[1];
332
333 size_t availSink = oldFront->mSize - ar->mBufferQueue.mSizeConsumed;
334 size_t availSource = pBuff->size;
335 size_t bytesToCopy = availSink < availSource ? availSink : availSource;
336 void *pDest = (char *)oldFront->mBuffer + ar->mBufferQueue.mSizeConsumed;
337 memcpy(pDest, pBuff->raw, bytesToCopy);
338
339 if (bytesToCopy < availSink) {
340 // can't consume the whole or rest of the buffer in one shot
341 ar->mBufferQueue.mSizeConsumed += availSource;
342 // pBuff->size is already equal to bytesToCopy in this case
343 } else {
344 // finish pushing the buffer or push the buffer in one shot
345 pBuff->size = bytesToCopy;
346 ar->mBufferQueue.mSizeConsumed = 0;
347 if (newFront == &ar->mBufferQueue.mArray[ar->mBufferQueue.mNumBuffers + 1]) {
348 newFront = ar->mBufferQueue.mArray;
349 }
350 ar->mBufferQueue.mFront = newFront;
351
352 ar->mBufferQueue.mState.count--;
353 ar->mBufferQueue.mState.playIndex++;
354
355 // data has been copied to the buffer, and the buffer queue state has been updated
356 // we will notify the client if applicable
357 callback = ar->mBufferQueue.mCallback;
358 // save callback data
359 callbackPContext = ar->mBufferQueue.mContext;
360 }
361 } else { // empty queue
362 // no destination to push the data
363 pBuff->size = 0;
364 }
365
366 interface_unlock_exclusive(&ar->mBufferQueue);
367
368 // notify client
369 if (NULL != callback) {
370 (*callback)(&ar->mBufferQueue.mItf, callbackPContext);
371 }
372 }
373 break;
374
375 case android::AudioRecord::EVENT_OVERRUN:
376 audioRecorder_handleOverrun_lockRecord(ar);
377 break;
378
379 case android::AudioRecord::EVENT_MARKER:
380 audioRecorder_handleMarker_lockRecord(ar);
381 break;
382
383 case android::AudioRecord::EVENT_NEW_POS:
384 audioRecorder_handleNewPos_lockRecord(ar);
385 break;
386
387 case android::AudioRecord::EVENT_NEW_IAUDIORECORD:
388 // ignore for now
389 break;
390
391 default:
392 SL_LOGE("Encountered unknown AudioRecord event %d for CAudioRecord %p", event, ar);
393 break;
394 }
395
396 ar->mCallbackProtector->exitCb();
397 }
398
399
400 //-----------------------------------------------------------------------------
android_audioRecorder_create(CAudioRecorder * ar)401 SLresult android_audioRecorder_create(CAudioRecorder* ar) {
402 SL_LOGV("android_audioRecorder_create(%p) entering", ar);
403
404 const SLDataSource *pAudioSrc = &ar->mDataSource.u.mSource;
405 const SLDataSink *pAudioSnk = &ar->mDataSink.u.mSink;
406 SLresult result = SL_RESULT_SUCCESS;
407
408 const SLuint32 sourceLocatorType = *(SLuint32 *)pAudioSrc->pLocator;
409 const SLuint32 sinkLocatorType = *(SLuint32 *)pAudioSnk->pLocator;
410
411 // the following platform-independent fields have been initialized in CreateAudioRecorder()
412 // ar->mNumChannels
413 // ar->mSampleRateMilliHz
414
415 if ((SL_DATALOCATOR_IODEVICE == sourceLocatorType) &&
416 (SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE == sinkLocatorType)) {
417 // microphone to simple buffer queue
418 ar->mAndroidObjType = AUDIORECORDER_FROM_MIC_TO_PCM_BUFFERQUEUE;
419 ar->mAudioRecord.clear();
420 ar->mCallbackProtector = new android::CallbackProtector();
421 ar->mRecordSource = AUDIO_SOURCE_DEFAULT;
422 ar->mPerformanceMode = ANDROID_PERFORMANCE_MODE_DEFAULT;
423 } else {
424 result = SL_RESULT_CONTENT_UNSUPPORTED;
425 }
426
427 return result;
428 }
429
430
431 //-----------------------------------------------------------------------------
android_audioRecorder_setConfig(CAudioRecorder * ar,const SLchar * configKey,const void * pConfigValue,SLuint32 valueSize)432 SLresult android_audioRecorder_setConfig(CAudioRecorder* ar, const SLchar *configKey,
433 const void *pConfigValue, SLuint32 valueSize) {
434
435 SLresult result;
436
437 assert(NULL != ar && NULL != configKey && NULL != pConfigValue);
438 if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_RECORDING_PRESET) == 0) {
439
440 // recording preset
441 if (KEY_RECORDING_PRESET_PARAMSIZE > valueSize) {
442 SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW);
443 result = SL_RESULT_BUFFER_INSUFFICIENT;
444 } else {
445 result = audioRecorder_setPreset(ar, *(SLuint32*)pConfigValue);
446 }
447
448 } else if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_PERFORMANCE_MODE) == 0) {
449
450 // performance mode
451 if (KEY_PERFORMANCE_MODE_PARAMSIZE > valueSize) {
452 SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW);
453 result = SL_RESULT_BUFFER_INSUFFICIENT;
454 } else {
455 result = audioRecorder_setPerformanceMode(ar, *(SLuint32*)pConfigValue);
456 }
457 } else {
458 SL_LOGE(ERROR_CONFIG_UNKNOWN_KEY);
459 result = SL_RESULT_PARAMETER_INVALID;
460 }
461
462 return result;
463 }
464
465
466 //-----------------------------------------------------------------------------
android_audioRecorder_getConfig(CAudioRecorder * ar,const SLchar * configKey,SLuint32 * pValueSize,void * pConfigValue)467 SLresult android_audioRecorder_getConfig(CAudioRecorder* ar, const SLchar *configKey,
468 SLuint32* pValueSize, void *pConfigValue) {
469
470 SLresult result;
471
472 assert(NULL != ar && NULL != configKey && NULL != pValueSize);
473 if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_RECORDING_PRESET) == 0) {
474
475 // recording preset
476 if (NULL == pConfigValue) {
477 result = SL_RESULT_SUCCESS;
478 } else if (KEY_RECORDING_PRESET_PARAMSIZE > *pValueSize) {
479 SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW);
480 result = SL_RESULT_BUFFER_INSUFFICIENT;
481 } else {
482 result = audioRecorder_getPreset(ar, (SLuint32*)pConfigValue);
483 }
484 *pValueSize = KEY_RECORDING_PRESET_PARAMSIZE;
485
486 } else if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_PERFORMANCE_MODE) == 0) {
487
488 // performance mode
489 if (NULL == pConfigValue) {
490 result = SL_RESULT_SUCCESS;
491 } else if (KEY_PERFORMANCE_MODE_PARAMSIZE > *pValueSize) {
492 SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW);
493 result = SL_RESULT_BUFFER_INSUFFICIENT;
494 } else {
495 result = audioRecorder_getPerformanceMode(ar, (SLuint32*)pConfigValue);
496 }
497 *pValueSize = KEY_PERFORMANCE_MODE_PARAMSIZE;
498
499 } else {
500 SL_LOGE(ERROR_CONFIG_UNKNOWN_KEY);
501 result = SL_RESULT_PARAMETER_INVALID;
502 }
503
504 return result;
505 }
506
507 // Called from android_audioRecorder_realize for a PCM buffer queue recorder before creating the
508 // AudioRecord to determine which performance modes are allowed based on effect interfaces present
checkAndSetPerformanceModePre(CAudioRecorder * ar)509 static void checkAndSetPerformanceModePre(CAudioRecorder* ar)
510 {
511 SLuint32 allowedModes = ANDROID_PERFORMANCE_MODE_ALL;
512 assert(ar->mAndroidObjType == AUDIORECORDER_FROM_MIC_TO_PCM_BUFFERQUEUE);
513
514 // no need to check the buffer queue size, application side
515 // double-buffering (and more) is not a requirement for using fast tracks
516
517 // Check a blacklist of interfaces that are incompatible with fast tracks.
518 // The alternative, to check a whitelist of compatible interfaces, is
519 // more maintainable but is too slow. As a compromise, in a debug build
520 // we use both methods and warn if they produce different results.
521 // In release builds, we only use the blacklist method.
522 // If a blacklisted interface is added after realization using
523 // DynamicInterfaceManagement::AddInterface,
524 // then this won't be detected but the interface will be ineffective.
525 static const unsigned blacklist[] = {
526 MPH_ANDROIDACOUSTICECHOCANCELLATION,
527 MPH_ANDROIDAUTOMATICGAINCONTROL,
528 MPH_ANDROIDNOISESUPPRESSION,
529 MPH_ANDROIDEFFECT,
530 // FIXME The problem with a blacklist is remembering to add new interfaces here
531 };
532
533 for (unsigned i = 0; i < sizeof(blacklist)/sizeof(blacklist[0]); ++i) {
534 if (IsInterfaceInitialized(&ar->mObject, blacklist[i])) {
535 uint32_t flags = 0;
536
537 allowedModes &= ~ANDROID_PERFORMANCE_MODE_LATENCY;
538
539 // if generic effect interface is used we don't know which effect will be used and
540 // disable all low latency performance modes
541 if (blacklist[i] != MPH_ANDROIDEFFECT) {
542 switch (blacklist[i]) {
543 case MPH_ANDROIDACOUSTICECHOCANCELLATION:
544 SL_LOGV("checkAndSetPerformanceModePre found AEC name %s",
545 ar->mAcousticEchoCancellation.mAECDescriptor.name);
546 flags = ar->mAcousticEchoCancellation.mAECDescriptor.flags;
547 break;
548 case MPH_ANDROIDAUTOMATICGAINCONTROL:
549 SL_LOGV("checkAndSetPerformanceModePre found AGC name %s",
550 ar->mAutomaticGainControl.mAGCDescriptor.name);
551 flags = ar->mAutomaticGainControl.mAGCDescriptor.flags;
552 break;
553 case MPH_ANDROIDNOISESUPPRESSION:
554 SL_LOGV("checkAndSetPerformanceModePre found NS name %s",
555 ar->mNoiseSuppression.mNSDescriptor.name);
556 flags = ar->mNoiseSuppression.mNSDescriptor.flags;
557 break;
558 default:
559 break;
560 }
561 }
562 if ((flags & EFFECT_FLAG_HW_ACC_TUNNEL) == 0) {
563 allowedModes &= ~ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS;
564 break;
565 }
566 }
567 }
568 #if LOG_NDEBUG == 0
569 bool blacklistResult = (
570 (allowedModes &
571 (ANDROID_PERFORMANCE_MODE_LATENCY|ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS)) != 0);
572 bool whitelistResult = true;
573 static const unsigned whitelist[] = {
574 MPH_BUFFERQUEUE,
575 MPH_DYNAMICINTERFACEMANAGEMENT,
576 MPH_OBJECT,
577 MPH_RECORD,
578 MPH_ANDROIDCONFIGURATION,
579 MPH_ANDROIDSIMPLEBUFFERQUEUE,
580 };
581 for (unsigned mph = MPH_MIN; mph < MPH_MAX; ++mph) {
582 for (unsigned i = 0; i < sizeof(whitelist)/sizeof(whitelist[0]); ++i) {
583 if (mph == whitelist[i]) {
584 goto compatible;
585 }
586 }
587 if (IsInterfaceInitialized(&ar->mObject, mph)) {
588 whitelistResult = false;
589 break;
590 }
591 compatible: ;
592 }
593 if (whitelistResult != blacklistResult) {
594 SL_LOGW("whitelistResult != blacklistResult");
595 }
596 #endif
597 if (ar->mPerformanceMode == ANDROID_PERFORMANCE_MODE_LATENCY) {
598 if ((allowedModes & ANDROID_PERFORMANCE_MODE_LATENCY) == 0) {
599 ar->mPerformanceMode = ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS;
600 }
601 }
602 if (ar->mPerformanceMode == ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS) {
603 if ((allowedModes & ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS) == 0) {
604 ar->mPerformanceMode = ANDROID_PERFORMANCE_MODE_NONE;
605 }
606 }
607 }
608
609 // Called from android_audioRecorder_realize for a PCM buffer queue recorder after creating the
610 // AudioRecord to adjust performance mode based on actual input flags
checkAndSetPerformanceModePost(CAudioRecorder * ar)611 static void checkAndSetPerformanceModePost(CAudioRecorder* ar)
612 {
613 audio_input_flags_t flags = ar->mAudioRecord->getFlags();
614 switch (ar->mPerformanceMode) {
615 case ANDROID_PERFORMANCE_MODE_LATENCY:
616 if ((flags & (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW)) ==
617 (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW)) {
618 break;
619 }
620 ar->mPerformanceMode = ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS;
621 /* FALL THROUGH */
622 case ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS:
623 if ((flags & AUDIO_INPUT_FLAG_FAST) == 0) {
624 ar->mPerformanceMode = ANDROID_PERFORMANCE_MODE_NONE;
625 }
626 break;
627 case ANDROID_PERFORMANCE_MODE_NONE:
628 default:
629 break;
630 }
631 }
632 //-----------------------------------------------------------------------------
android_audioRecorder_realize(CAudioRecorder * ar,SLboolean async)633 SLresult android_audioRecorder_realize(CAudioRecorder* ar, SLboolean async) {
634 SL_LOGV("android_audioRecorder_realize(%p) entering", ar);
635
636 SLresult result = SL_RESULT_SUCCESS;
637
638 // already checked in created and checkSourceSink
639 assert(ar->mDataSink.mLocator.mLocatorType == SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE);
640
641 const SLDataFormat_PCM *df_pcm = &ar->mDataSink.mFormat.mPCM;
642
643 // the following platform-independent fields have been initialized in CreateAudioRecorder()
644 // ar->mNumChannels
645 // ar->mSampleRateMilliHz
646
647 uint32_t sampleRate = sles_to_android_sampleRate(df_pcm->samplesPerSec);
648
649 checkAndSetPerformanceModePre(ar);
650
651 audio_input_flags_t policy;
652 switch (ar->mPerformanceMode) {
653 case ANDROID_PERFORMANCE_MODE_NONE:
654 case ANDROID_PERFORMANCE_MODE_POWER_SAVING:
655 policy = AUDIO_INPUT_FLAG_NONE;
656 break;
657 case ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS:
658 policy = AUDIO_INPUT_FLAG_FAST;
659 break;
660 case ANDROID_PERFORMANCE_MODE_LATENCY:
661 default:
662 policy = (audio_input_flags_t)(AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW);
663 break;
664 }
665
666 SL_LOGV("Audio Record format: %dch(0x%x), %dbit, %dKHz",
667 df_pcm->numChannels,
668 df_pcm->channelMask,
669 df_pcm->bitsPerSample,
670 df_pcm->samplesPerSec / 1000000);
671
672 // note that df_pcm->channelMask has already been validated during object creation.
673 audio_channel_mask_t channelMask = sles_to_audio_input_channel_mask(df_pcm->channelMask);
674
675 // To maintain backward compatibility with previous releases, ignore
676 // channel masks that are not indexed.
677 if (channelMask == AUDIO_CHANNEL_INVALID
678 || audio_channel_mask_get_representation(channelMask)
679 == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
680 channelMask = audio_channel_in_mask_from_count(df_pcm->numChannels);
681 SL_LOGI("Emulating old channel mask behavior "
682 "(ignoring positional mask %#x, using default mask %#x based on "
683 "channel count of %d)", df_pcm->channelMask, channelMask,
684 df_pcm->numChannels);
685 }
686 SL_LOGV("SLES channel mask %#x converted to Android mask %#x", df_pcm->channelMask, channelMask);
687
688 // initialize platform-specific CAudioRecorder fields
689 ar->mAudioRecord = new android::AudioRecord(
690 ar->mRecordSource, // source
691 sampleRate, // sample rate in Hertz
692 sles_to_android_sampleFormat(df_pcm), // format
693 channelMask, // channel mask
694 android::String16(), // app ops
695 0, // frameCount
696 audioRecorder_callback,// callback_t
697 (void*)ar, // user, callback data, here the AudioRecorder
698 0, // notificationFrames
699 AUDIO_SESSION_ALLOCATE,
700 android::AudioRecord::TRANSFER_CALLBACK,
701 // transfer type
702 policy); // audio_input_flags_t
703
704 android::status_t status = ar->mAudioRecord->initCheck();
705 if (android::NO_ERROR != status) {
706 SL_LOGE("android_audioRecorder_realize(%p) error creating AudioRecord object; status %d",
707 ar, status);
708 // FIXME should return a more specific result depending on status
709 result = SL_RESULT_CONTENT_UNSUPPORTED;
710 ar->mAudioRecord.clear();
711 return result;
712 }
713
714 // update performance mode according to actual flags granted to AudioRecord
715 checkAndSetPerformanceModePost(ar);
716
717 // If there is a JavaAudioRoutingProxy associated with this recorder, hook it up...
718 JNIEnv* j_env = NULL;
719 jclass clsAudioRecord = NULL;
720 jmethodID midRoutingProxy_connect = NULL;
721 if (ar->mAndroidConfiguration.mRoutingProxy != NULL &&
722 (j_env = android::AndroidRuntime::getJNIEnv()) != NULL &&
723 (clsAudioRecord = j_env->FindClass("android/media/AudioRecord")) != NULL &&
724 (midRoutingProxy_connect =
725 j_env->GetMethodID(clsAudioRecord, "deferred_connect", "(J)V")) != NULL) {
726 j_env->ExceptionClear();
727 j_env->CallVoidMethod(ar->mAndroidConfiguration.mRoutingProxy,
728 midRoutingProxy_connect,
729 ar->mAudioRecord.get());
730 if (j_env->ExceptionCheck()) {
731 SL_LOGE("Java exception releasing recorder routing object.");
732 result = SL_RESULT_INTERNAL_ERROR;
733 ar->mAudioRecord.clear();
734 return result;
735 }
736 }
737
738 if (ar->mPerformanceMode != ANDROID_PERFORMANCE_MODE_LATENCY) {
739 audio_session_t sessionId = ar->mAudioRecord->getSessionId();
740 // initialize AEC
741 effect_descriptor_t *descriptor = &ar->mAcousticEchoCancellation.mAECDescriptor;
742 if (memcmp(SL_IID_ANDROIDACOUSTICECHOCANCELLATION, &descriptor->type,
743 sizeof(effect_uuid_t)) == 0) {
744 if ((ar->mPerformanceMode != ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS) ||
745 (descriptor->flags & EFFECT_FLAG_HW_ACC_TUNNEL)) {
746 SL_LOGV("Need to initialize AEC for AudioRecorder=%p", ar);
747 android_aec_init(sessionId, &ar->mAcousticEchoCancellation);
748 }
749 }
750
751 // initialize AGC
752 descriptor = &ar->mAutomaticGainControl.mAGCDescriptor;
753 if (memcmp(SL_IID_ANDROIDAUTOMATICGAINCONTROL, &descriptor->type,
754 sizeof(effect_uuid_t)) == 0) {
755 if ((ar->mPerformanceMode != ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS) ||
756 (descriptor->flags & EFFECT_FLAG_HW_ACC_TUNNEL)) {
757 SL_LOGV("Need to initialize AGC for AudioRecorder=%p", ar);
758 android_agc_init(sessionId, &ar->mAutomaticGainControl);
759 }
760 }
761
762 // initialize NS
763 descriptor = &ar->mNoiseSuppression.mNSDescriptor;
764 if (memcmp(SL_IID_ANDROIDNOISESUPPRESSION, &descriptor->type,
765 sizeof(effect_uuid_t)) == 0) {
766 if ((ar->mPerformanceMode != ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS) ||
767 (descriptor->flags & EFFECT_FLAG_HW_ACC_TUNNEL)) {
768 SL_LOGV("Need to initialize NS for AudioRecorder=%p", ar);
769 android_ns_init(sessionId, &ar->mNoiseSuppression);
770 }
771 }
772 }
773
774 return result;
775 }
776
777
778 //-----------------------------------------------------------------------------
779 /**
780 * Called with a lock on AudioRecorder, and blocks until safe to destroy
781 */
android_audioRecorder_preDestroy(CAudioRecorder * ar)782 void android_audioRecorder_preDestroy(CAudioRecorder* ar) {
783 object_unlock_exclusive(&ar->mObject);
784 if (ar->mCallbackProtector != 0) {
785 ar->mCallbackProtector->requestCbExitAndWait();
786 }
787 object_lock_exclusive(&ar->mObject);
788 }
789
790
791 //-----------------------------------------------------------------------------
android_audioRecorder_destroy(CAudioRecorder * ar)792 void android_audioRecorder_destroy(CAudioRecorder* ar) {
793 SL_LOGV("android_audioRecorder_destroy(%p) entering", ar);
794
795 if (ar->mAudioRecord != 0) {
796 ar->mAudioRecord->stop();
797 ar->mAudioRecord.clear();
798 }
799 // explicit destructor
800 ar->mAudioRecord.~sp();
801 ar->mCallbackProtector.~sp();
802 }
803
804
805 //-----------------------------------------------------------------------------
android_audioRecorder_setRecordState(CAudioRecorder * ar,SLuint32 state)806 void android_audioRecorder_setRecordState(CAudioRecorder* ar, SLuint32 state) {
807 SL_LOGV("android_audioRecorder_setRecordState(%p, %u) entering", ar, state);
808
809 if (ar->mAudioRecord == 0) {
810 return;
811 }
812
813 switch (state) {
814 case SL_RECORDSTATE_STOPPED:
815 ar->mAudioRecord->stop();
816 break;
817 case SL_RECORDSTATE_PAUSED:
818 // Note that pausing is treated like stop as this implementation only records to a buffer
819 // queue, so there is no notion of destination being "opened" or "closed" (See description
820 // of SL_RECORDSTATE in specification)
821 ar->mAudioRecord->stop();
822 break;
823 case SL_RECORDSTATE_RECORDING:
824 ar->mAudioRecord->start();
825 break;
826 default:
827 break;
828 }
829
830 }
831
832
833 //-----------------------------------------------------------------------------
android_audioRecorder_useRecordEventMask(CAudioRecorder * ar)834 void android_audioRecorder_useRecordEventMask(CAudioRecorder *ar) {
835 IRecord *pRecordItf = &ar->mRecord;
836 SLuint32 eventFlags = pRecordItf->mCallbackEventsMask;
837
838 if (ar->mAudioRecord == 0) {
839 return;
840 }
841
842 if ((eventFlags & SL_RECORDEVENT_HEADATMARKER) && (pRecordItf->mMarkerPosition != 0)) {
843 ar->mAudioRecord->setMarkerPosition((uint32_t)((((int64_t)pRecordItf->mMarkerPosition
844 * sles_to_android_sampleRate(ar->mSampleRateMilliHz)))/1000));
845 } else {
846 // clear marker
847 ar->mAudioRecord->setMarkerPosition(0);
848 }
849
850 if (eventFlags & SL_RECORDEVENT_HEADATNEWPOS) {
851 SL_LOGV("pos update period %d", pRecordItf->mPositionUpdatePeriod);
852 ar->mAudioRecord->setPositionUpdatePeriod(
853 (uint32_t)((((int64_t)pRecordItf->mPositionUpdatePeriod
854 * sles_to_android_sampleRate(ar->mSampleRateMilliHz)))/1000));
855 } else {
856 // clear periodic update
857 ar->mAudioRecord->setPositionUpdatePeriod(0);
858 }
859
860 if (eventFlags & SL_RECORDEVENT_HEADATLIMIT) {
861 // FIXME support SL_RECORDEVENT_HEADATLIMIT
862 SL_LOGD("[ FIXME: IRecord_SetCallbackEventsMask(SL_RECORDEVENT_HEADATLIMIT) on an "
863 "SL_OBJECTID_AUDIORECORDER to be implemented ]");
864 }
865
866 if (eventFlags & SL_RECORDEVENT_HEADMOVING) {
867 // FIXME support SL_RECORDEVENT_HEADMOVING
868 SL_LOGD("[ FIXME: IRecord_SetCallbackEventsMask(SL_RECORDEVENT_HEADMOVING) on an "
869 "SL_OBJECTID_AUDIORECORDER to be implemented ]");
870 }
871
872 if (eventFlags & SL_RECORDEVENT_BUFFER_FULL) {
873 // nothing to do for SL_RECORDEVENT_BUFFER_FULL since this will not be encountered on
874 // recording to buffer queues
875 }
876
877 if (eventFlags & SL_RECORDEVENT_HEADSTALLED) {
878 // nothing to do for SL_RECORDEVENT_HEADSTALLED, callback event will be checked against mask
879 // when AudioRecord::EVENT_OVERRUN is encountered
880
881 }
882
883 }
884
885
886 //-----------------------------------------------------------------------------
android_audioRecorder_getPosition(CAudioRecorder * ar,SLmillisecond * pPosMsec)887 void android_audioRecorder_getPosition(CAudioRecorder *ar, SLmillisecond *pPosMsec) {
888 if ((NULL == ar) || (ar->mAudioRecord == 0)) {
889 *pPosMsec = 0;
890 } else {
891 uint32_t positionInFrames;
892 ar->mAudioRecord->getPosition(&positionInFrames);
893 if (ar->mSampleRateMilliHz == UNKNOWN_SAMPLERATE) {
894 *pPosMsec = 0;
895 } else {
896 *pPosMsec = ((int64_t)positionInFrames * 1000) /
897 sles_to_android_sampleRate(ar->mSampleRateMilliHz);
898 }
899 }
900 }
901