13af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi/*
23af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi * Copyright (C) 2010 The Android Open Source Project
33af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi *
43af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
53af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi * you may not use this file except in compliance with the License.
63af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi * You may obtain a copy of the License at
73af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi *
83af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
93af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi *
103af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
113af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
123af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi * See the License for the specific language governing permissions and
143af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi * limitations under the License.
153af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi */
163af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
173af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi#include "sles_allinclusive.h"
1875e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi#include "android_prompts.h"
194e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean#include "channels.h"
203af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
212523b697aa1fda376c2ccd72680394d359acbd3fSvet Ganov#include <utils/String16.h>
222523b697aa1fda376c2ccd72680394d359acbd3fSvet Ganov
2310a3840407ac3ed61e7873ee7b86d664ccc6149fDima Zavin#include <system/audio.h>
244e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean#include <SLES/OpenSLES_Android.h>
25ca39f4b4dbeb920a5b97bd65be73f2f7cac77431Dima Zavin
2615f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean#include <android_runtime/AndroidRuntime.h>
2715f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean
28b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi#define KEY_RECORDING_SOURCE_PARAMSIZE  sizeof(SLuint32)
29b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi#define KEY_RECORDING_PRESET_PARAMSIZE  sizeof(SLuint32)
308c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent#define KEY_PERFORMANCE_MODE_PARAMSIZE  sizeof(SLuint32)
31b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
32b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi//-----------------------------------------------------------------------------
33b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi// Internal utility functions
34b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi//----------------------------
35b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
36b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel TriviSLresult audioRecorder_setPreset(CAudioRecorder* ar, SLuint32 recordPreset) {
37b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    SLresult result = SL_RESULT_SUCCESS;
38b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
39adf8bd5d4360542b6b6c48c4471fdd8d855e05ccGlenn Kasten    audio_source_t newRecordSource = AUDIO_SOURCE_DEFAULT;
40b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    switch (recordPreset) {
41e214a8c49938e7356943b59db53474e5fc3ae07cJean-Michel Trivi    case SL_ANDROID_RECORDING_PRESET_GENERIC:
42ca39f4b4dbeb920a5b97bd65be73f2f7cac77431Dima Zavin        newRecordSource = AUDIO_SOURCE_DEFAULT;
43b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        break;
44b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    case SL_ANDROID_RECORDING_PRESET_CAMCORDER:
45ca39f4b4dbeb920a5b97bd65be73f2f7cac77431Dima Zavin        newRecordSource = AUDIO_SOURCE_CAMCORDER;
46b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        break;
47b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    case SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION:
48ca39f4b4dbeb920a5b97bd65be73f2f7cac77431Dima Zavin        newRecordSource = AUDIO_SOURCE_VOICE_RECOGNITION;
49b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        break;
50a4b4d478171631eaa97e933eb46c1ff01bd04daaJean-Michel Trivi    case SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION:
51ca39f4b4dbeb920a5b97bd65be73f2f7cac77431Dima Zavin        newRecordSource = AUDIO_SOURCE_VOICE_COMMUNICATION;
52a4b4d478171631eaa97e933eb46c1ff01bd04daaJean-Michel Trivi        break;
53e9b57cefb954e7c1bffc5d4b59f89aca5e050797rago    case SL_ANDROID_RECORDING_PRESET_UNPROCESSED:
54e9b57cefb954e7c1bffc5d4b59f89aca5e050797rago            newRecordSource = AUDIO_SOURCE_UNPROCESSED;
55e9b57cefb954e7c1bffc5d4b59f89aca5e050797rago            break;
56b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    case SL_ANDROID_RECORDING_PRESET_NONE:
57b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        // it is an error to set preset "none"
58b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    default:
5975e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi        SL_LOGE(ERROR_RECORDERPRESET_SET_UNKNOWN_PRESET);
60b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        result = SL_RESULT_PARAMETER_INVALID;
61b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    }
62b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
6375e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi    // recording preset needs to be set before the object is realized
64e5ede1a139fcedbf075675179d919fbe731898f0Glenn Kasten    // (ap->mAudioRecord is supposed to be 0 until then)
655f71e35da153d194d805e030ab38935599e065d2Jean-Michel Trivi    if (SL_OBJECT_STATE_UNREALIZED != ar->mObject.mState) {
6675e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi        SL_LOGE(ERROR_RECORDERPRESET_REALIZED);
6775e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi        result = SL_RESULT_PRECONDITIONS_VIOLATED;
6875e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi    } else {
6975e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi        ar->mRecordSource = newRecordSource;
7075e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi    }
7175e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi
72b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    return result;
73b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi}
74b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
75b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
768c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent//-----------------------------------------------------------------------------
778c9071f491393fadf767b6164a17b0795eba3fdaEric LaurentSLresult audioRecorder_setPerformanceMode(CAudioRecorder* ar, SLuint32 mode) {
788c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    SLresult result = SL_RESULT_SUCCESS;
798c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    SL_LOGV("performance mode set to %d", mode);
808c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
818c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    SLuint32 perfMode = ANDROID_PERFORMANCE_MODE_DEFAULT;
828c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    switch (mode) {
838c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    case SL_ANDROID_PERFORMANCE_LATENCY:
848c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        perfMode = ANDROID_PERFORMANCE_MODE_LATENCY;
858c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        break;
868c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    case SL_ANDROID_PERFORMANCE_LATENCY_EFFECTS:
878c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        perfMode = ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS;
888c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        break;
898c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    case SL_ANDROID_PERFORMANCE_NONE:
908c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        perfMode = ANDROID_PERFORMANCE_MODE_NONE;
918c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        break;
928c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    case SL_ANDROID_PERFORMANCE_POWER_SAVING:
938c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        perfMode = ANDROID_PERFORMANCE_MODE_POWER_SAVING;
948c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        break;
958c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    default:
968c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        SL_LOGE(ERROR_CONFIG_PERF_MODE_UNKNOWN);
978c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        result = SL_RESULT_PARAMETER_INVALID;
988c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        break;
998c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    }
1008c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
1018c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    // performance mode needs to be set before the object is realized
1028c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    // (ar->mAudioRecord is supposed to be NULL until then)
1038c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    if (SL_OBJECT_STATE_UNREALIZED != ar->mObject.mState) {
1048c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        SL_LOGE(ERROR_CONFIG_PERF_MODE_REALIZED);
1058c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        result = SL_RESULT_PRECONDITIONS_VIOLATED;
1068c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    } else {
1078c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        ar->mPerformanceMode = perfMode;
1088c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    }
1098c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
1108c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    return result;
1118c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent}
1128c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
1138c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
114b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel TriviSLresult audioRecorder_getPreset(CAudioRecorder* ar, SLuint32* pPreset) {
115b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    SLresult result = SL_RESULT_SUCCESS;
116b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
117b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    switch (ar->mRecordSource) {
118ca39f4b4dbeb920a5b97bd65be73f2f7cac77431Dima Zavin    case AUDIO_SOURCE_DEFAULT:
119ca39f4b4dbeb920a5b97bd65be73f2f7cac77431Dima Zavin    case AUDIO_SOURCE_MIC:
120e214a8c49938e7356943b59db53474e5fc3ae07cJean-Michel Trivi        *pPreset = SL_ANDROID_RECORDING_PRESET_GENERIC;
121b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        break;
122ca39f4b4dbeb920a5b97bd65be73f2f7cac77431Dima Zavin    case AUDIO_SOURCE_VOICE_UPLINK:
123ca39f4b4dbeb920a5b97bd65be73f2f7cac77431Dima Zavin    case AUDIO_SOURCE_VOICE_DOWNLINK:
124ca39f4b4dbeb920a5b97bd65be73f2f7cac77431Dima Zavin    case AUDIO_SOURCE_VOICE_CALL:
125b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        *pPreset = SL_ANDROID_RECORDING_PRESET_NONE;
126b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        break;
127ca39f4b4dbeb920a5b97bd65be73f2f7cac77431Dima Zavin    case AUDIO_SOURCE_VOICE_RECOGNITION:
128b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        *pPreset = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
129b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        break;
130ca39f4b4dbeb920a5b97bd65be73f2f7cac77431Dima Zavin    case AUDIO_SOURCE_CAMCORDER:
131b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        *pPreset = SL_ANDROID_RECORDING_PRESET_CAMCORDER;
132b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        break;
133ca39f4b4dbeb920a5b97bd65be73f2f7cac77431Dima Zavin    case AUDIO_SOURCE_VOICE_COMMUNICATION:
134a4b4d478171631eaa97e933eb46c1ff01bd04daaJean-Michel Trivi        *pPreset = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
135a4b4d478171631eaa97e933eb46c1ff01bd04daaJean-Michel Trivi        break;
136e9b57cefb954e7c1bffc5d4b59f89aca5e050797rago    case AUDIO_SOURCE_UNPROCESSED:
137e9b57cefb954e7c1bffc5d4b59f89aca5e050797rago        *pPreset = SL_ANDROID_RECORDING_PRESET_UNPROCESSED;
138e9b57cefb954e7c1bffc5d4b59f89aca5e050797rago        break;
139b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    default:
140b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        *pPreset = SL_ANDROID_RECORDING_PRESET_NONE;
141b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        result = SL_RESULT_INTERNAL_ERROR;
142b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        break;
143b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    }
144b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
145b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    return result;
146b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi}
147b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
1483af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
1498c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent//-----------------------------------------------------------------------------
1508c9071f491393fadf767b6164a17b0795eba3fdaEric LaurentSLresult audioRecorder_getPerformanceMode(CAudioRecorder* ar, SLuint32 *pMode) {
1518c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    SLresult result = SL_RESULT_SUCCESS;
1528c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
1538c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    switch (ar->mPerformanceMode) {
1548c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    case ANDROID_PERFORMANCE_MODE_LATENCY:
1558c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        *pMode = SL_ANDROID_PERFORMANCE_LATENCY;
1568c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        break;
1578c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    case ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS:
1588c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        *pMode = SL_ANDROID_PERFORMANCE_LATENCY_EFFECTS;
1598c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        break;
1608c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    case ANDROID_PERFORMANCE_MODE_NONE:
1618c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        *pMode = SL_ANDROID_PERFORMANCE_NONE;
1628c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        break;
1638c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    case ANDROID_PERFORMANCE_MODE_POWER_SAVING:
164677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent        *pMode = SL_ANDROID_PERFORMANCE_POWER_SAVING;
1658c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        break;
1668c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    default:
1678c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        result = SL_RESULT_INTERNAL_ERROR;
1688c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        *pMode = SL_ANDROID_PERFORMANCE_LATENCY;
1698c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        break;
1708c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    }
1718c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
1728c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    return result;
1738c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent}
1748c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
1758c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
1763b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivivoid audioRecorder_handleNewPos_lockRecord(CAudioRecorder* ar) {
1773b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    //SL_LOGV("received event EVENT_NEW_POS from AudioRecord");
1783b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    slRecordCallback callback = NULL;
1793b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    void* callbackPContext = NULL;
1803b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
1813b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    interface_lock_shared(&ar->mRecord);
1823b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    callback = ar->mRecord.mCallback;
1833b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    callbackPContext = ar->mRecord.mContext;
1843b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    interface_unlock_shared(&ar->mRecord);
1853b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
1863b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    if (NULL != callback) {
1873b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        // getting this event implies SL_RECORDEVENT_HEADATNEWPOS was set in the event mask
1883b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        (*callback)(&ar->mRecord.mItf, callbackPContext, SL_RECORDEVENT_HEADATNEWPOS);
1893b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    }
1903b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi}
1913b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
1923b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
1933b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivivoid audioRecorder_handleMarker_lockRecord(CAudioRecorder* ar) {
1943b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    //SL_LOGV("received event EVENT_MARKER from AudioRecord");
1953b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    slRecordCallback callback = NULL;
1963b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    void* callbackPContext = NULL;
1973b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
1983b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    interface_lock_shared(&ar->mRecord);
1993b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    callback = ar->mRecord.mCallback;
2003b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    callbackPContext = ar->mRecord.mContext;
2013b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    interface_unlock_shared(&ar->mRecord);
2023b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
2033b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    if (NULL != callback) {
2043b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        // getting this event implies SL_RECORDEVENT_HEADATMARKER was set in the event mask
2053b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        (*callback)(&ar->mRecord.mItf, callbackPContext, SL_RECORDEVENT_HEADATMARKER);
2063b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    }
2073b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi}
2083b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
2093b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
2103b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivivoid audioRecorder_handleOverrun_lockRecord(CAudioRecorder* ar) {
2113b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    //SL_LOGV("received event EVENT_OVERRUN from AudioRecord");
2123b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    slRecordCallback callback = NULL;
2133b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    void* callbackPContext = NULL;
2143b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
2153b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    interface_lock_shared(&ar->mRecord);
216f6cca2f731329d101651348d1b7e51ead7b1290aJean-Michel Trivi    if (ar->mRecord.mCallbackEventsMask & SL_RECORDEVENT_HEADSTALLED) {
2173b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        callback = ar->mRecord.mCallback;
2183b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        callbackPContext = ar->mRecord.mContext;
2193b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    }
2203b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    interface_unlock_shared(&ar->mRecord);
2213b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
2223b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    if (NULL != callback) {
223f6cca2f731329d101651348d1b7e51ead7b1290aJean-Michel Trivi        (*callback)(&ar->mRecord.mItf, callbackPContext, SL_RECORDEVENT_HEADSTALLED);
2243b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    }
2253b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi}
2263b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
2273af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi//-----------------------------------------------------------------------------
22800a66a027199238a93b2aa9056af126efc09fe38Glenn KastenSLresult android_audioRecorder_checkSourceSink(CAudioRecorder* ar) {
2293af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
2303af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    const SLDataSource *pAudioSrc = &ar->mDataSource.u.mSource;
2313af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    const SLDataSink   *pAudioSnk = &ar->mDataSink.u.mSink;
2323af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
233274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten    const SLuint32 sinkLocatorType = *(SLuint32 *)pAudioSnk->pLocator;
234274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten    const SLuint32 sinkFormatType = *(SLuint32 *)pAudioSnk->pFormat;
235274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten
236274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten    const SLuint32 *df_representation = NULL; // pointer to representation field, if it exists
237274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten
238274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten    // sink must be an Android simple buffer queue with PCM data format
239274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten    switch (sinkLocatorType) {
240274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten    case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE: {
241274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten        switch (sinkFormatType) {
242274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten        case SL_ANDROID_DATAFORMAT_PCM_EX: {
243274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten            const SLAndroidDataFormat_PCM_EX *df_pcm =
244274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten                    (SLAndroidDataFormat_PCM_EX *) pAudioSnk->pFormat;
245df9b397f73d8f063ff66e0fbf86ced075fe6d5aaGlenn Kasten            // checkDataFormat() already checked representation
246df9b397f73d8f063ff66e0fbf86ced075fe6d5aaGlenn Kasten            df_representation = &df_pcm->representation;
247274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten        } // SL_ANDROID_DATAFORMAT_PCM_EX - fall through to next test.
248274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten        case SL_DATAFORMAT_PCM: {
249274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten            const SLDataFormat_PCM *df_pcm = (const SLDataFormat_PCM *) pAudioSnk->pFormat;
2504e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            // checkDataFormat already checked sample rate, channels, and mask
251712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi            ar->mNumChannels = df_pcm->numChannels;
252a80a6ff9a1f80792478c9d43578afa24a07eb2f0Glenn Kasten
253a80a6ff9a1f80792478c9d43578afa24a07eb2f0Glenn Kasten            if (df_pcm->endianness != ar->mObject.mEngine->mEngine.mNativeEndianness) {
25471065fbf12abafd4c2a0dc85c81f13b564ff69fbGlenn Kasten                SL_LOGE("Cannot create audio recorder: unsupported byte order %u",
25571065fbf12abafd4c2a0dc85c81f13b564ff69fbGlenn Kasten                        df_pcm->endianness);
256a80a6ff9a1f80792478c9d43578afa24a07eb2f0Glenn Kasten                return SL_RESULT_CONTENT_UNSUPPORTED;
257a80a6ff9a1f80792478c9d43578afa24a07eb2f0Glenn Kasten            }
258a80a6ff9a1f80792478c9d43578afa24a07eb2f0Glenn Kasten
259274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten            ar->mSampleRateMilliHz = df_pcm->samplesPerSec; // Note: bad field name in SL ES
260a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten            SL_LOGV("AudioRecorder requested sample rate = %u mHz, %u channel(s)",
261712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi                    ar->mSampleRateMilliHz, ar->mNumChannels);
26271065fbf12abafd4c2a0dc85c81f13b564ff69fbGlenn Kasten
26371065fbf12abafd4c2a0dc85c81f13b564ff69fbGlenn Kasten            // we don't support container size != sample depth
26471065fbf12abafd4c2a0dc85c81f13b564ff69fbGlenn Kasten            if (df_pcm->containerSize != df_pcm->bitsPerSample) {
26571065fbf12abafd4c2a0dc85c81f13b564ff69fbGlenn Kasten                SL_LOGE("Cannot create audio recorder: unsupported container size %u bits for "
26671065fbf12abafd4c2a0dc85c81f13b564ff69fbGlenn Kasten                        "sample depth %u bits",
26771065fbf12abafd4c2a0dc85c81f13b564ff69fbGlenn Kasten                        df_pcm->containerSize, (SLuint32)df_pcm->bitsPerSample);
26871065fbf12abafd4c2a0dc85c81f13b564ff69fbGlenn Kasten                return SL_RESULT_CONTENT_UNSUPPORTED;
26971065fbf12abafd4c2a0dc85c81f13b564ff69fbGlenn Kasten            }
27071065fbf12abafd4c2a0dc85c81f13b564ff69fbGlenn Kasten
271274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten            } break;
272274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten        default:
27375e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            SL_LOGE(ERROR_RECORDER_SINK_FORMAT_MUST_BE_PCM);
274712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi            return SL_RESULT_PARAMETER_INVALID;
275274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten        }   // switch (sourceFormatType)
276274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten        } break;    // case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE
277274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten    default:
278274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten        SL_LOGE(ERROR_RECORDER_SINK_MUST_BE_ANDROIDSIMPLEBUFFERQUEUE);
279274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
280274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten    }   // switch (sourceLocatorType)
2813af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
2823af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    // Source check:
2833af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    // only input device sources are supported
2843af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    // check it's an IO device
2853af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    if (SL_DATALOCATOR_IODEVICE != *(SLuint32 *)pAudioSrc->pLocator) {
28675e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi        SL_LOGE(ERROR_RECORDER_SOURCE_MUST_BE_IODEVICE);
2873af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        return SL_RESULT_PARAMETER_INVALID;
2883af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    } else {
2893af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
2903af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        // check it's an input device
29122ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten        SLDataLocator_IODevice *dl_iod = (SLDataLocator_IODevice *) pAudioSrc->pLocator;
2923af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        if (SL_IODEVICE_AUDIOINPUT != dl_iod->deviceType) {
29375e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            SL_LOGE(ERROR_RECORDER_IODEVICE_MUST_BE_AUDIOINPUT);
2943af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi            return SL_RESULT_PARAMETER_INVALID;
2953af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        }
2963af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
2973af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        // check it's the default input device, others aren't supported here
2983af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        if (SL_DEFAULTDEVICEID_AUDIOINPUT != dl_iod->deviceID) {
29975e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            SL_LOGE(ERROR_RECORDER_INPUT_ID_MUST_BE_DEFAULT);
3003af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi            return SL_RESULT_PARAMETER_INVALID;
3013af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        }
3023af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    }
3033af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
3043af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    return SL_RESULT_SUCCESS;
3053af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi}
3063af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi//-----------------------------------------------------------------------------
3073af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivistatic void audioRecorder_callback(int event, void* user, void *info) {
3083af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    //SL_LOGV("audioRecorder_callback(%d, %p, %p) entering", event, user, info);
3093af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
3103af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    CAudioRecorder *ar = (CAudioRecorder *)user;
311460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten
312460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten    if (!android::CallbackProtector::enterCbIfOk(ar->mCallbackProtector)) {
313460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten        // it is not safe to enter the callback (the track is about to go away)
314460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten        return;
315460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten    }
316460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten
3173af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    void * callbackPContext = NULL;
3183af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
319ac28eca1df49f581d952ffbda5d3019f7e3b7be6Glenn Kasten    switch (event) {
3203af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    case android::AudioRecord::EVENT_MORE_DATA: {
3213af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        slBufferQueueCallback callback = NULL;
3223af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        android::AudioRecord::Buffer* pBuff = (android::AudioRecord::Buffer*)info;
3233af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
3243af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        // push data to the buffer queue
3253af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        interface_lock_exclusive(&ar->mBufferQueue);
3263af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
3273af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        if (ar->mBufferQueue.mState.count != 0) {
3283af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi            assert(ar->mBufferQueue.mFront != ar->mBufferQueue.mRear);
3293af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
3303af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi            BufferHeader *oldFront = ar->mBufferQueue.mFront;
3313af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi            BufferHeader *newFront = &oldFront[1];
3323af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
333274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten            size_t availSink = oldFront->mSize - ar->mBufferQueue.mSizeConsumed;
334274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten            size_t availSource = pBuff->size;
335274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten            size_t bytesToCopy = availSink < availSource ? availSink : availSource;
336274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten            void *pDest = (char *)oldFront->mBuffer + ar->mBufferQueue.mSizeConsumed;
337274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten            memcpy(pDest, pBuff->raw, bytesToCopy);
338274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten
339274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten            if (bytesToCopy < availSink) {
3403af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi                // can't consume the whole or rest of the buffer in one shot
341274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten                ar->mBufferQueue.mSizeConsumed += availSource;
342274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten                // pBuff->size is already equal to bytesToCopy in this case
3433af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi            } else {
3443af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi                // finish pushing the buffer or push the buffer in one shot
345274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten                pBuff->size = bytesToCopy;
3463af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi                ar->mBufferQueue.mSizeConsumed = 0;
34722ced1dc023dc000118e3a26517b14e9babd7c5aGlenn Kasten                if (newFront == &ar->mBufferQueue.mArray[ar->mBufferQueue.mNumBuffers + 1]) {
3483af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi                    newFront = ar->mBufferQueue.mArray;
3493af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi                }
3503af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi                ar->mBufferQueue.mFront = newFront;
3513af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
3523af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi                ar->mBufferQueue.mState.count--;
3533af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi                ar->mBufferQueue.mState.playIndex++;
354274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten
3553af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi                // data has been copied to the buffer, and the buffer queue state has been updated
3563af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi                // we will notify the client if applicable
3573af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi                callback = ar->mBufferQueue.mCallback;
3583af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi                // save callback data
3593af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi                callbackPContext = ar->mBufferQueue.mContext;
3603af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi            }
361274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten        } else { // empty queue
3623af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi            // no destination to push the data
3633af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi            pBuff->size = 0;
3643af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        }
3653af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
3663af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        interface_unlock_exclusive(&ar->mBufferQueue);
367274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten
3683af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        // notify client
3693af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        if (NULL != callback) {
3703af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi            (*callback)(&ar->mBufferQueue.mItf, callbackPContext);
3713af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        }
3723af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        }
3733af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        break;
3743af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
3753b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    case android::AudioRecord::EVENT_OVERRUN:
3763b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        audioRecorder_handleOverrun_lockRecord(ar);
3773b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        break;
3783b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
3793af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    case android::AudioRecord::EVENT_MARKER:
3803b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        audioRecorder_handleMarker_lockRecord(ar);
3813af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        break;
3823af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
3833af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    case android::AudioRecord::EVENT_NEW_POS:
3843b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        audioRecorder_handleNewPos_lockRecord(ar);
3853af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        break;
3863af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
3879f3ac83aa036a780ca901f9ff75e47a5a7cbba1fGlenn Kasten    case android::AudioRecord::EVENT_NEW_IAUDIORECORD:
3889f3ac83aa036a780ca901f9ff75e47a5a7cbba1fGlenn Kasten        // ignore for now
3899f3ac83aa036a780ca901f9ff75e47a5a7cbba1fGlenn Kasten        break;
3909f3ac83aa036a780ca901f9ff75e47a5a7cbba1fGlenn Kasten
3919f3ac83aa036a780ca901f9ff75e47a5a7cbba1fGlenn Kasten    default:
3929f3ac83aa036a780ca901f9ff75e47a5a7cbba1fGlenn Kasten        SL_LOGE("Encountered unknown AudioRecord event %d for CAudioRecord %p", event, ar);
3939f3ac83aa036a780ca901f9ff75e47a5a7cbba1fGlenn Kasten        break;
3943af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    }
395460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten
396460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten    ar->mCallbackProtector->exitCb();
3973af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi}
3983af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
3993af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
4003af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi//-----------------------------------------------------------------------------
4013af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel TriviSLresult android_audioRecorder_create(CAudioRecorder* ar) {
4023af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    SL_LOGV("android_audioRecorder_create(%p) entering", ar);
4033af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
404b2aeb0f1009555181dabb944fe05901cb6e6f632Jean-Michel Trivi    const SLDataSource *pAudioSrc = &ar->mDataSource.u.mSource;
405b2aeb0f1009555181dabb944fe05901cb6e6f632Jean-Michel Trivi    const SLDataSink *pAudioSnk = &ar->mDataSink.u.mSink;
4063af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    SLresult result = SL_RESULT_SUCCESS;
4073af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
408b2aeb0f1009555181dabb944fe05901cb6e6f632Jean-Michel Trivi    const SLuint32 sourceLocatorType = *(SLuint32 *)pAudioSrc->pLocator;
409b2aeb0f1009555181dabb944fe05901cb6e6f632Jean-Michel Trivi    const SLuint32 sinkLocatorType = *(SLuint32 *)pAudioSnk->pLocator;
410b2aeb0f1009555181dabb944fe05901cb6e6f632Jean-Michel Trivi
411b0cf731f4d81a3d6f8cac31de3cdddbbf555c305Jean-Michel Trivi    //  the following platform-independent fields have been initialized in CreateAudioRecorder()
412b0cf731f4d81a3d6f8cac31de3cdddbbf555c305Jean-Michel Trivi    //    ar->mNumChannels
413b0cf731f4d81a3d6f8cac31de3cdddbbf555c305Jean-Michel Trivi    //    ar->mSampleRateMilliHz
414b5ef0195d7b8fa1fceae5ef8a256ed19eb03cbedJean-Michel Trivi
415b2aeb0f1009555181dabb944fe05901cb6e6f632Jean-Michel Trivi    if ((SL_DATALOCATOR_IODEVICE == sourceLocatorType) &&
416b2aeb0f1009555181dabb944fe05901cb6e6f632Jean-Michel Trivi            (SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE == sinkLocatorType)) {
417b2aeb0f1009555181dabb944fe05901cb6e6f632Jean-Michel Trivi        // microphone to simple buffer queue
418b05ea38e5131001884aa226f90fd50cf594a23f3Jean-Michel Trivi        ar->mAndroidObjType = AUDIORECORDER_FROM_MIC_TO_PCM_BUFFERQUEUE;
419e5ede1a139fcedbf075675179d919fbe731898f0Glenn Kasten        ar->mAudioRecord.clear();
420460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten        ar->mCallbackProtector = new android::CallbackProtector();
421ca39f4b4dbeb920a5b97bd65be73f2f7cac77431Dima Zavin        ar->mRecordSource = AUDIO_SOURCE_DEFAULT;
4228c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        ar->mPerformanceMode = ANDROID_PERFORMANCE_MODE_DEFAULT;
423b2aeb0f1009555181dabb944fe05901cb6e6f632Jean-Michel Trivi    } else {
424b2aeb0f1009555181dabb944fe05901cb6e6f632Jean-Michel Trivi        result = SL_RESULT_CONTENT_UNSUPPORTED;
425b2aeb0f1009555181dabb944fe05901cb6e6f632Jean-Michel Trivi    }
426b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
427b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    return result;
428b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi}
429b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
430b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
431b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi//-----------------------------------------------------------------------------
432b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel TriviSLresult android_audioRecorder_setConfig(CAudioRecorder* ar, const SLchar *configKey,
433b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        const void *pConfigValue, SLuint32 valueSize) {
434b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
435c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten    SLresult result;
436b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
437c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten    assert(NULL != ar && NULL != configKey && NULL != pConfigValue);
438ca426f63e9c900ecbd28f8e3037aaf47ef739dd4Glenn Kasten    if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_RECORDING_PRESET) == 0) {
439b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
440b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        // recording preset
441b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        if (KEY_RECORDING_PRESET_PARAMSIZE > valueSize) {
44275e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW);
443c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten            result = SL_RESULT_BUFFER_INSUFFICIENT;
444b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        } else {
445b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi            result = audioRecorder_setPreset(ar, *(SLuint32*)pConfigValue);
446b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        }
447b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
4488c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    } else if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_PERFORMANCE_MODE) == 0) {
4498c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
4508c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        // performance mode
4518c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        if (KEY_PERFORMANCE_MODE_PARAMSIZE > valueSize) {
4528c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent            SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW);
4538c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent            result = SL_RESULT_BUFFER_INSUFFICIENT;
4548c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        } else {
4558c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent            result = audioRecorder_setPerformanceMode(ar, *(SLuint32*)pConfigValue);
4568c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        }
457b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    } else {
45875e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi        SL_LOGE(ERROR_CONFIG_UNKNOWN_KEY);
459b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        result = SL_RESULT_PARAMETER_INVALID;
460b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    }
461b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
462b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    return result;
463b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi}
464b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
465b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
466b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi//-----------------------------------------------------------------------------
467b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel TriviSLresult android_audioRecorder_getConfig(CAudioRecorder* ar, const SLchar *configKey,
468b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        SLuint32* pValueSize, void *pConfigValue) {
469b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
470c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten    SLresult result;
471b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
472c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten    assert(NULL != ar && NULL != configKey && NULL != pValueSize);
473ca426f63e9c900ecbd28f8e3037aaf47ef739dd4Glenn Kasten    if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_RECORDING_PRESET) == 0) {
474b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
475b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        // recording preset
476c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        if (NULL == pConfigValue) {
477c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten            result = SL_RESULT_SUCCESS;
478c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        } else if (KEY_RECORDING_PRESET_PARAMSIZE > *pValueSize) {
47975e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi            SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW);
480c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten            result = SL_RESULT_BUFFER_INSUFFICIENT;
481b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        } else {
482c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten            result = audioRecorder_getPreset(ar, (SLuint32*)pConfigValue);
483b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        }
484c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        *pValueSize = KEY_RECORDING_PRESET_PARAMSIZE;
485b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
4868c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    } else if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_PERFORMANCE_MODE) == 0) {
4878c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
4888c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        // performance mode
4898c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        if (NULL == pConfigValue) {
4908c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent            result = SL_RESULT_SUCCESS;
4918c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        } else if (KEY_PERFORMANCE_MODE_PARAMSIZE > *pValueSize) {
4928c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent            SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW);
4938c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent            result = SL_RESULT_BUFFER_INSUFFICIENT;
4948c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        } else {
4958c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent            result = audioRecorder_getPerformanceMode(ar, (SLuint32*)pConfigValue);
4968c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        }
4978c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        *pValueSize = KEY_PERFORMANCE_MODE_PARAMSIZE;
4988c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
499b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    } else {
50075e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi        SL_LOGE(ERROR_CONFIG_UNKNOWN_KEY);
501b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        result = SL_RESULT_PARAMETER_INVALID;
502b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi    }
5033af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
5043af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    return result;
5053af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi}
5063af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
5078c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent// Called from android_audioRecorder_realize for a PCM buffer queue recorder before creating the
5088c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent// AudioRecord to determine which performance modes are allowed based on effect interfaces present
5098c9071f491393fadf767b6164a17b0795eba3fdaEric Laurentstatic void checkAndSetPerformanceModePre(CAudioRecorder* ar)
5108c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent{
5118c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    SLuint32 allowedModes = ANDROID_PERFORMANCE_MODE_ALL;
5128c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    assert(ar->mAndroidObjType == AUDIORECORDER_FROM_MIC_TO_PCM_BUFFERQUEUE);
5138c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
5148c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    // no need to check the buffer queue size, application side
5158c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    // double-buffering (and more) is not a requirement for using fast tracks
5168c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
5178c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    // Check a blacklist of interfaces that are incompatible with fast tracks.
5188c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    // The alternative, to check a whitelist of compatible interfaces, is
5198c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    // more maintainable but is too slow.  As a compromise, in a debug build
5208c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    // we use both methods and warn if they produce different results.
5218c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    // In release builds, we only use the blacklist method.
5228c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    // If a blacklisted interface is added after realization using
5238c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    // DynamicInterfaceManagement::AddInterface,
5248c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    // then this won't be detected but the interface will be ineffective.
5258c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    static const unsigned blacklist[] = {
5268c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        MPH_ANDROIDACOUSTICECHOCANCELLATION,
5278c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        MPH_ANDROIDAUTOMATICGAINCONTROL,
5288c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        MPH_ANDROIDNOISESUPPRESSION,
5298c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        MPH_ANDROIDEFFECT,
5308c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        // FIXME The problem with a blacklist is remembering to add new interfaces here
5318c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    };
532677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent
5338c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    for (unsigned i = 0; i < sizeof(blacklist)/sizeof(blacklist[0]); ++i) {
5348c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        if (IsInterfaceInitialized(&ar->mObject, blacklist[i])) {
535677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent            uint32_t flags = 0;
536677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent
537677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent            allowedModes &= ~ANDROID_PERFORMANCE_MODE_LATENCY;
538677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent
539677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent            // if generic effect interface is used we don't know which effect will be used and
540677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent            // disable all low latency performance modes
541677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent            if (blacklist[i] != MPH_ANDROIDEFFECT) {
542677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                switch (blacklist[i]) {
543677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                case MPH_ANDROIDACOUSTICECHOCANCELLATION:
544677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                    SL_LOGV("checkAndSetPerformanceModePre found AEC name %s",
545677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                            ar->mAcousticEchoCancellation.mAECDescriptor.name);
546677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                    flags = ar->mAcousticEchoCancellation.mAECDescriptor.flags;
547677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                    break;
548677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                case MPH_ANDROIDAUTOMATICGAINCONTROL:
549677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                    SL_LOGV("checkAndSetPerformanceModePre found AGC name %s",
550677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                            ar->mAutomaticGainControl.mAGCDescriptor.name);
551677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                    flags = ar->mAutomaticGainControl.mAGCDescriptor.flags;
552677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                    break;
553677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                case MPH_ANDROIDNOISESUPPRESSION:
554677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                    SL_LOGV("checkAndSetPerformanceModePre found NS name %s",
555677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                            ar->mNoiseSuppression.mNSDescriptor.name);
556677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                    flags = ar->mNoiseSuppression.mNSDescriptor.flags;
557677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                    break;
558677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                default:
559677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                    break;
560677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                }
561677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent            }
562677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent            if ((flags & EFFECT_FLAG_HW_ACC_TUNNEL) == 0) {
563677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                allowedModes &= ~ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS;
564677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                break;
565677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent            }
5668c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        }
5678c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    }
5688c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent#if LOG_NDEBUG == 0
5698c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    bool blacklistResult = (
5708c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent            (allowedModes &
5718c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent                (ANDROID_PERFORMANCE_MODE_LATENCY|ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS)) != 0);
5728c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    bool whitelistResult = true;
5738c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    static const unsigned whitelist[] = {
5748c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        MPH_BUFFERQUEUE,
5758c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        MPH_DYNAMICINTERFACEMANAGEMENT,
5768c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        MPH_OBJECT,
5778c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        MPH_RECORD,
5788c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        MPH_ANDROIDCONFIGURATION,
5798c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        MPH_ANDROIDSIMPLEBUFFERQUEUE,
5808c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    };
5818c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    for (unsigned mph = MPH_MIN; mph < MPH_MAX; ++mph) {
5828c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        for (unsigned i = 0; i < sizeof(whitelist)/sizeof(whitelist[0]); ++i) {
5838c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent            if (mph == whitelist[i]) {
5848c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent                goto compatible;
5858c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent            }
5868c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        }
5878c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        if (IsInterfaceInitialized(&ar->mObject, mph)) {
5888c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent            whitelistResult = false;
5898c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent            break;
5908c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        }
5918c9071f491393fadf767b6164a17b0795eba3fdaEric Laurentcompatible: ;
5928c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    }
5938c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    if (whitelistResult != blacklistResult) {
5948c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        SL_LOGW("whitelistResult != blacklistResult");
5958c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    }
5968c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent#endif
5978c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    if (ar->mPerformanceMode == ANDROID_PERFORMANCE_MODE_LATENCY) {
5988c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        if ((allowedModes & ANDROID_PERFORMANCE_MODE_LATENCY) == 0) {
5998c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent            ar->mPerformanceMode = ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS;
6008c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        }
6018c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    }
6028c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    if (ar->mPerformanceMode == ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS) {
6038c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        if ((allowedModes & ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS) == 0) {
6048c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent            ar->mPerformanceMode = ANDROID_PERFORMANCE_MODE_NONE;
6058c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        }
6068c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    }
6078c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent}
6088c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
6098c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent// Called from android_audioRecorder_realize for a PCM buffer queue recorder after creating the
6108c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent// AudioRecord to adjust performance mode based on actual input flags
6118c9071f491393fadf767b6164a17b0795eba3fdaEric Laurentstatic void checkAndSetPerformanceModePost(CAudioRecorder* ar)
6128c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent{
6138c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    audio_input_flags_t flags = ar->mAudioRecord->getFlags();
6148c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    switch (ar->mPerformanceMode) {
6158c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    case ANDROID_PERFORMANCE_MODE_LATENCY:
6168c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        if ((flags & (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW)) ==
6178c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent                (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW)) {
6188c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent            break;
6198c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        }
6208c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        ar->mPerformanceMode = ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS;
6218c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        /* FALL THROUGH */
6228c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    case ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS:
6238c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        if ((flags & AUDIO_INPUT_FLAG_FAST) == 0) {
6248c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent            ar->mPerformanceMode = ANDROID_PERFORMANCE_MODE_NONE;
6258c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        }
6268c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        break;
6278c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    case ANDROID_PERFORMANCE_MODE_NONE:
6288c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    default:
6298c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        break;
6308c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    }
6318c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent}
6323af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi//-----------------------------------------------------------------------------
6333af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel TriviSLresult android_audioRecorder_realize(CAudioRecorder* ar, SLboolean async) {
6343af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    SL_LOGV("android_audioRecorder_realize(%p) entering", ar);
6353af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
6363af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    SLresult result = SL_RESULT_SUCCESS;
6373af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
638274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten    // already checked in created and checkSourceSink
639274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten    assert(ar->mDataSink.mLocator.mLocatorType == SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE);
640274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten
641274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten    const SLDataFormat_PCM *df_pcm = &ar->mDataSink.mFormat.mPCM;
642274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten
643b0cf731f4d81a3d6f8cac31de3cdddbbf555c305Jean-Michel Trivi    //  the following platform-independent fields have been initialized in CreateAudioRecorder()
644712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi    //    ar->mNumChannels
645712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi    //    ar->mSampleRateMilliHz
646712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi
647274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten    uint32_t sampleRate = sles_to_android_sampleRate(df_pcm->samplesPerSec);
648712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi
6498c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    checkAndSetPerformanceModePre(ar);
6508c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
6518c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    audio_input_flags_t policy;
6528c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    switch (ar->mPerformanceMode) {
6538c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    case ANDROID_PERFORMANCE_MODE_NONE:
6548c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    case ANDROID_PERFORMANCE_MODE_POWER_SAVING:
6558c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        policy = AUDIO_INPUT_FLAG_NONE;
6568c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        break;
6578c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    case ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS:
6588c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        policy = AUDIO_INPUT_FLAG_FAST;
6598c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        break;
6608c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    case ANDROID_PERFORMANCE_MODE_LATENCY:
6618c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    default:
6628c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        policy = (audio_input_flags_t)(AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW);
6638c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent        break;
6648c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    }
6655e3bcbffacc309fb2d9e002b7bc1ed131fddc6fcGlenn Kasten
6664e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    SL_LOGV("Audio Record format: %dch(0x%x), %dbit, %dKHz",
6674e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            df_pcm->numChannels,
6684e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            df_pcm->channelMask,
6694e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            df_pcm->bitsPerSample,
6704e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            df_pcm->samplesPerSec / 1000000);
67133f46b8cd9ece650736a4aa5294318c6b51b2ffdilewis
6724e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    // note that df_pcm->channelMask has already been validated during object creation.
6734e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean    audio_channel_mask_t channelMask = sles_to_audio_input_channel_mask(df_pcm->channelMask);
67433f46b8cd9ece650736a4aa5294318c6b51b2ffdilewis
67528340d1d9199b789f0db015680b008c98084f0b7ilewis    // To maintain backward compatibility with previous releases, ignore
67628340d1d9199b789f0db015680b008c98084f0b7ilewis    // channel masks that are not indexed.
67728340d1d9199b789f0db015680b008c98084f0b7ilewis    if (channelMask == AUDIO_CHANNEL_INVALID
67828340d1d9199b789f0db015680b008c98084f0b7ilewis            || audio_channel_mask_get_representation(channelMask)
67928340d1d9199b789f0db015680b008c98084f0b7ilewis                == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
68033f46b8cd9ece650736a4aa5294318c6b51b2ffdilewis        channelMask = audio_channel_in_mask_from_count(df_pcm->numChannels);
68128340d1d9199b789f0db015680b008c98084f0b7ilewis        SL_LOGI("Emulating old channel mask behavior "
68228340d1d9199b789f0db015680b008c98084f0b7ilewis                "(ignoring positional mask %#x, using default mask %#x based on "
68328340d1d9199b789f0db015680b008c98084f0b7ilewis                "channel count of %d)", df_pcm->channelMask, channelMask,
68428340d1d9199b789f0db015680b008c98084f0b7ilewis                df_pcm->numChannels);
68533f46b8cd9ece650736a4aa5294318c6b51b2ffdilewis    }
68628340d1d9199b789f0db015680b008c98084f0b7ilewis    SL_LOGV("SLES channel mask %#x converted to Android mask %#x", df_pcm->channelMask, channelMask);
6874e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean
688712b490060e4164fbe47986be1d2584d1610d8ddJean-Michel Trivi    // initialize platform-specific CAudioRecorder fields
689274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten    ar->mAudioRecord = new android::AudioRecord(
6902dc0674aba6242c677365b675795773738397ab9Glenn Kasten            ar->mRecordSource,     // source
691274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten            sampleRate,            // sample rate in Hertz
692274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten            sles_to_android_sampleFormat(df_pcm),               // format
6934e8fe8a60c3aa8085918f15f281e0979682aefdcPaul McLean            channelMask,           // channel mask
694274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten            android::String16(),   // app ops
695274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten            0,                     // frameCount
6963af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi            audioRecorder_callback,// callback_t
6973af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi            (void*)ar,             // user, callback data, here the AudioRecorder
6983af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi            0,                     // notificationFrames
699213c31153b9bda7b5a091f2996da7b655c8ed451Glenn Kasten            AUDIO_SESSION_ALLOCATE,
7005e3bcbffacc309fb2d9e002b7bc1ed131fddc6fcGlenn Kasten            android::AudioRecord::TRANSFER_CALLBACK,
7015e3bcbffacc309fb2d9e002b7bc1ed131fddc6fcGlenn Kasten                                   // transfer type
7025e3bcbffacc309fb2d9e002b7bc1ed131fddc6fcGlenn Kasten            policy);               // audio_input_flags_t
7033af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
704274c079467f6ade516771b4c721c67041243cf4bGlenn Kasten    android::status_t status = ar->mAudioRecord->initCheck();
7052dc0674aba6242c677365b675795773738397ab9Glenn Kasten    if (android::NO_ERROR != status) {
7062dc0674aba6242c677365b675795773738397ab9Glenn Kasten        SL_LOGE("android_audioRecorder_realize(%p) error creating AudioRecord object; status %d",
7072dc0674aba6242c677365b675795773738397ab9Glenn Kasten                ar, status);
7082dc0674aba6242c677365b675795773738397ab9Glenn Kasten        // FIXME should return a more specific result depending on status
7093af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        result = SL_RESULT_CONTENT_UNSUPPORTED;
7102dc0674aba6242c677365b675795773738397ab9Glenn Kasten        ar->mAudioRecord.clear();
711677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent        return result;
7123af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    }
7133af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
7148c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    // update performance mode according to actual flags granted to AudioRecord
7158c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent    checkAndSetPerformanceModePost(ar);
7168c9071f491393fadf767b6164a17b0795eba3fdaEric Laurent
71715f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean    // If there is a JavaAudioRoutingProxy associated with this recorder, hook it up...
71815f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean    JNIEnv* j_env = NULL;
71915f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean    jclass clsAudioRecord = NULL;
72015f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean    jmethodID midRoutingProxy_connect = NULL;
72115f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean    if (ar->mAndroidConfiguration.mRoutingProxy != NULL &&
72215f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean            (j_env = android::AndroidRuntime::getJNIEnv()) != NULL &&
72315f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean            (clsAudioRecord = j_env->FindClass("android/media/AudioRecord")) != NULL &&
72415f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean            (midRoutingProxy_connect =
72515f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean                j_env->GetMethodID(clsAudioRecord, "deferred_connect", "(J)V")) != NULL) {
72615f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean        j_env->ExceptionClear();
72715f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean        j_env->CallVoidMethod(ar->mAndroidConfiguration.mRoutingProxy,
72815f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean                              midRoutingProxy_connect,
72915f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean                              ar->mAudioRecord.get());
73015f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean        if (j_env->ExceptionCheck()) {
73115f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean            SL_LOGE("Java exception releasing recorder routing object.");
73215f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean            result = SL_RESULT_INTERNAL_ERROR;
733677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent            ar->mAudioRecord.clear();
734677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent            return result;
73515f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean        }
73615f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean   }
73715f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean
738677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent    if (ar->mPerformanceMode != ANDROID_PERFORMANCE_MODE_LATENCY) {
739677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent        audio_session_t sessionId = ar->mAudioRecord->getSessionId();
740677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent        // initialize AEC
741677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent        effect_descriptor_t *descriptor = &ar->mAcousticEchoCancellation.mAECDescriptor;
742677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent        if (memcmp(SL_IID_ANDROIDACOUSTICECHOCANCELLATION, &descriptor->type,
743677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                   sizeof(effect_uuid_t)) == 0) {
744677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent            if ((ar->mPerformanceMode != ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS) ||
745677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                    (descriptor->flags & EFFECT_FLAG_HW_ACC_TUNNEL)) {
746677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                SL_LOGV("Need to initialize AEC for AudioRecorder=%p", ar);
747677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                android_aec_init(sessionId, &ar->mAcousticEchoCancellation);
748677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent            }
749677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent        }
750677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent
751677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent        // initialize AGC
752677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent        descriptor = &ar->mAutomaticGainControl.mAGCDescriptor;
753677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent        if (memcmp(SL_IID_ANDROIDAUTOMATICGAINCONTROL, &descriptor->type,
754677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                   sizeof(effect_uuid_t)) == 0) {
755677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent            if ((ar->mPerformanceMode != ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS) ||
756677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                    (descriptor->flags & EFFECT_FLAG_HW_ACC_TUNNEL)) {
757677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                SL_LOGV("Need to initialize AGC for AudioRecorder=%p", ar);
758677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                android_agc_init(sessionId, &ar->mAutomaticGainControl);
759677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent            }
760677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent        }
761677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent
762677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent        // initialize NS
763677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent        descriptor = &ar->mNoiseSuppression.mNSDescriptor;
764677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent        if (memcmp(SL_IID_ANDROIDNOISESUPPRESSION, &descriptor->type,
765677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                   sizeof(effect_uuid_t)) == 0) {
766677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent            if ((ar->mPerformanceMode != ANDROID_PERFORMANCE_MODE_LATENCY_EFFECTS) ||
767677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                    (descriptor->flags & EFFECT_FLAG_HW_ACC_TUNNEL)) {
768677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                SL_LOGV("Need to initialize NS for AudioRecorder=%p", ar);
769677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent                android_ns_init(sessionId, &ar->mNoiseSuppression);
770677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent            }
771677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent        }
772677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent    }
773677c796097b542e9ee6cf43a59e754f43c2370dcEric Laurent
7743af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    return result;
7753af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi}
7763af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
7773af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
7783af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi//-----------------------------------------------------------------------------
779460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten/**
780460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten * Called with a lock on AudioRecorder, and blocks until safe to destroy
781460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten */
782460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kastenvoid android_audioRecorder_preDestroy(CAudioRecorder* ar) {
783460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten    object_unlock_exclusive(&ar->mObject);
784460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten    if (ar->mCallbackProtector != 0) {
785460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten        ar->mCallbackProtector->requestCbExitAndWait();
786460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten    }
787460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten    object_lock_exclusive(&ar->mObject);
788460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten}
789460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten
790460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten
791460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten//-----------------------------------------------------------------------------
7923af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivivoid android_audioRecorder_destroy(CAudioRecorder* ar) {
7933af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    SL_LOGV("android_audioRecorder_destroy(%p) entering", ar);
7943af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
795e5ede1a139fcedbf075675179d919fbe731898f0Glenn Kasten    if (ar->mAudioRecord != 0) {
7963af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        ar->mAudioRecord->stop();
797460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten        ar->mAudioRecord.clear();
7983af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    }
799e5ede1a139fcedbf075675179d919fbe731898f0Glenn Kasten    // explicit destructor
800e5ede1a139fcedbf075675179d919fbe731898f0Glenn Kasten    ar->mAudioRecord.~sp();
801460bdad43aaec3c6ffe7f259719e00807742ad6dGlenn Kasten    ar->mCallbackProtector.~sp();
8023af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi}
8033af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
8043af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
8053af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi//-----------------------------------------------------------------------------
8063af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivivoid android_audioRecorder_setRecordState(CAudioRecorder* ar, SLuint32 state) {
807a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten    SL_LOGV("android_audioRecorder_setRecordState(%p, %u) entering", ar, state);
8083af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
809e5ede1a139fcedbf075675179d919fbe731898f0Glenn Kasten    if (ar->mAudioRecord == 0) {
8103af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi        return;
8113af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    }
8123af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
8133af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi    switch (state) {
8143af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi     case SL_RECORDSTATE_STOPPED:
8153af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi         ar->mAudioRecord->stop();
8163af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi         break;
8173af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi     case SL_RECORDSTATE_PAUSED:
8183af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi         // Note that pausing is treated like stop as this implementation only records to a buffer
8193af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi         //  queue, so there is no notion of destination being "opened" or "closed" (See description
8203af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi         //  of SL_RECORDSTATE in specification)
8213af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi         ar->mAudioRecord->stop();
8223af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi         break;
8233af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi     case SL_RECORDSTATE_RECORDING:
8243af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi         ar->mAudioRecord->start();
8253af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi         break;
8263af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi     default:
8273af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi         break;
8283af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi     }
8293af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi
8303af2a8dd03f3113d5da1000dd79c143a9f0c4f36Jean-Michel Trivi}
8313b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
8323b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
8333b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi//-----------------------------------------------------------------------------
834bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kastenvoid android_audioRecorder_useRecordEventMask(CAudioRecorder *ar) {
8353b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    IRecord *pRecordItf = &ar->mRecord;
8363b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    SLuint32 eventFlags = pRecordItf->mCallbackEventsMask;
8373b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
838e5ede1a139fcedbf075675179d919fbe731898f0Glenn Kasten    if (ar->mAudioRecord == 0) {
8393b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        return;
8403b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    }
8413b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
8423b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    if ((eventFlags & SL_RECORDEVENT_HEADATMARKER) && (pRecordItf->mMarkerPosition != 0)) {
8433b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        ar->mAudioRecord->setMarkerPosition((uint32_t)((((int64_t)pRecordItf->mMarkerPosition
8443b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi                * sles_to_android_sampleRate(ar->mSampleRateMilliHz)))/1000));
8453b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    } else {
8463b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        // clear marker
8473b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        ar->mAudioRecord->setMarkerPosition(0);
8483b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    }
8493b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
8503b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    if (eventFlags & SL_RECORDEVENT_HEADATNEWPOS) {
851a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten        SL_LOGV("pos update period %d", pRecordItf->mPositionUpdatePeriod);
8523b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi         ar->mAudioRecord->setPositionUpdatePeriod(
8533b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi                (uint32_t)((((int64_t)pRecordItf->mPositionUpdatePeriod
8543b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi                * sles_to_android_sampleRate(ar->mSampleRateMilliHz)))/1000));
8553b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    } else {
8563b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        // clear periodic update
8573b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        ar->mAudioRecord->setPositionUpdatePeriod(0);
8583b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    }
8593b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
8603b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    if (eventFlags & SL_RECORDEVENT_HEADATLIMIT) {
8613b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        // FIXME support SL_RECORDEVENT_HEADATLIMIT
862a7b79e766ec6d95e9236168c27461c2ebaef4659Glenn Kasten        SL_LOGD("[ FIXME: IRecord_SetCallbackEventsMask(SL_RECORDEVENT_HEADATLIMIT) on an "
8633b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi                    "SL_OBJECTID_AUDIORECORDER to be implemented ]");
8643b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    }
8653b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
8663b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    if (eventFlags & SL_RECORDEVENT_HEADMOVING) {
8673b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi        // FIXME support SL_RECORDEVENT_HEADMOVING
868a7b79e766ec6d95e9236168c27461c2ebaef4659Glenn Kasten        SL_LOGD("[ FIXME: IRecord_SetCallbackEventsMask(SL_RECORDEVENT_HEADMOVING) on an "
8693b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi                "SL_OBJECTID_AUDIORECORDER to be implemented ]");
8703b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    }
8713b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
8723b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    if (eventFlags & SL_RECORDEVENT_BUFFER_FULL) {
873f6cca2f731329d101651348d1b7e51ead7b1290aJean-Michel Trivi        // nothing to do for SL_RECORDEVENT_BUFFER_FULL since this will not be encountered on
874f6cca2f731329d101651348d1b7e51ead7b1290aJean-Michel Trivi        // recording to buffer queues
8753b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    }
8763b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
8773b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    if (eventFlags & SL_RECORDEVENT_HEADSTALLED) {
878f6cca2f731329d101651348d1b7e51ead7b1290aJean-Michel Trivi        // nothing to do for SL_RECORDEVENT_HEADSTALLED, callback event will be checked against mask
879f6cca2f731329d101651348d1b7e51ead7b1290aJean-Michel Trivi        // when AudioRecord::EVENT_OVERRUN is encountered
880f6cca2f731329d101651348d1b7e51ead7b1290aJean-Michel Trivi
8813b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi    }
8823b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi
8833b142e50f4ae068f50f8e3d277e0f19910c67001Jean-Michel Trivi}
884b5ef0195d7b8fa1fceae5ef8a256ed19eb03cbedJean-Michel Trivi
885b5ef0195d7b8fa1fceae5ef8a256ed19eb03cbedJean-Michel Trivi
886b5ef0195d7b8fa1fceae5ef8a256ed19eb03cbedJean-Michel Trivi//-----------------------------------------------------------------------------
887b5ef0195d7b8fa1fceae5ef8a256ed19eb03cbedJean-Michel Trivivoid android_audioRecorder_getPosition(CAudioRecorder *ar, SLmillisecond *pPosMsec) {
888e5ede1a139fcedbf075675179d919fbe731898f0Glenn Kasten    if ((NULL == ar) || (ar->mAudioRecord == 0)) {
889b5ef0195d7b8fa1fceae5ef8a256ed19eb03cbedJean-Michel Trivi        *pPosMsec = 0;
890b5ef0195d7b8fa1fceae5ef8a256ed19eb03cbedJean-Michel Trivi    } else {
891b5ef0195d7b8fa1fceae5ef8a256ed19eb03cbedJean-Michel Trivi        uint32_t positionInFrames;
892b5ef0195d7b8fa1fceae5ef8a256ed19eb03cbedJean-Michel Trivi        ar->mAudioRecord->getPosition(&positionInFrames);
8931a9c2615d0933d183fcb1b9e34ec8f0da2a85153Glenn Kasten        if (ar->mSampleRateMilliHz == UNKNOWN_SAMPLERATE) {
894b5ef0195d7b8fa1fceae5ef8a256ed19eb03cbedJean-Michel Trivi            *pPosMsec = 0;
895b5ef0195d7b8fa1fceae5ef8a256ed19eb03cbedJean-Michel Trivi        } else {
896b5ef0195d7b8fa1fceae5ef8a256ed19eb03cbedJean-Michel Trivi            *pPosMsec = ((int64_t)positionInFrames * 1000) /
897b5ef0195d7b8fa1fceae5ef8a256ed19eb03cbedJean-Michel Trivi                    sles_to_android_sampleRate(ar->mSampleRateMilliHz);
898b5ef0195d7b8fa1fceae5ef8a256ed19eb03cbedJean-Michel Trivi        }
899b5ef0195d7b8fa1fceae5ef8a256ed19eb03cbedJean-Michel Trivi    }
900b5ef0195d7b8fa1fceae5ef8a256ed19eb03cbedJean-Michel Trivi}
901