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