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
36SLresult 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//-----------------------------------------------------------------------------
77SLresult 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
114SLresult 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//-----------------------------------------------------------------------------
150SLresult 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
176void 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
193void 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
210void 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//-----------------------------------------------------------------------------
228SLresult 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//-----------------------------------------------------------------------------
307static 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//-----------------------------------------------------------------------------
401SLresult 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//-----------------------------------------------------------------------------
432SLresult 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//-----------------------------------------------------------------------------
467SLresult 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
509static 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        }
591compatible: ;
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
611static 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//-----------------------------------------------------------------------------
633SLresult 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 */
782void 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//-----------------------------------------------------------------------------
792void 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//-----------------------------------------------------------------------------
806void 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//-----------------------------------------------------------------------------
834void 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//-----------------------------------------------------------------------------
887void 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