• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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