AudioRecorder_to_android.cpp revision 62496886cb4620c09bc5df0de70a883319616c25
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#define KEY_RECORDING_SOURCE_PARAMSIZE  sizeof(SLuint32)
27#define KEY_RECORDING_PRESET_PARAMSIZE  sizeof(SLuint32)
28
29//-----------------------------------------------------------------------------
30// Internal utility functions
31//----------------------------
32
33SLresult audioRecorder_setPreset(CAudioRecorder* ar, SLuint32 recordPreset) {
34    SLresult result = SL_RESULT_SUCCESS;
35
36    audio_source_t newRecordSource = AUDIO_SOURCE_DEFAULT;
37    switch (recordPreset) {
38    case SL_ANDROID_RECORDING_PRESET_GENERIC:
39        newRecordSource = AUDIO_SOURCE_DEFAULT;
40        break;
41    case SL_ANDROID_RECORDING_PRESET_CAMCORDER:
42        newRecordSource = AUDIO_SOURCE_CAMCORDER;
43        break;
44    case SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION:
45        newRecordSource = AUDIO_SOURCE_VOICE_RECOGNITION;
46        break;
47    case SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION:
48        newRecordSource = AUDIO_SOURCE_VOICE_COMMUNICATION;
49        break;
50    case SL_ANDROID_RECORDING_PRESET_UNPROCESSED:
51            newRecordSource = AUDIO_SOURCE_UNPROCESSED;
52            break;
53    case SL_ANDROID_RECORDING_PRESET_NONE:
54        // it is an error to set preset "none"
55    default:
56        SL_LOGE(ERROR_RECORDERPRESET_SET_UNKNOWN_PRESET);
57        result = SL_RESULT_PARAMETER_INVALID;
58    }
59
60    // recording preset needs to be set before the object is realized
61    // (ap->mAudioRecord is supposed to be 0 until then)
62    if (SL_OBJECT_STATE_UNREALIZED != ar->mObject.mState) {
63        SL_LOGE(ERROR_RECORDERPRESET_REALIZED);
64        result = SL_RESULT_PRECONDITIONS_VIOLATED;
65    } else {
66        ar->mRecordSource = newRecordSource;
67    }
68
69    return result;
70}
71
72
73SLresult audioRecorder_getPreset(CAudioRecorder* ar, SLuint32* pPreset) {
74    SLresult result = SL_RESULT_SUCCESS;
75
76    switch (ar->mRecordSource) {
77    case AUDIO_SOURCE_DEFAULT:
78    case AUDIO_SOURCE_MIC:
79        *pPreset = SL_ANDROID_RECORDING_PRESET_GENERIC;
80        break;
81    case AUDIO_SOURCE_VOICE_UPLINK:
82    case AUDIO_SOURCE_VOICE_DOWNLINK:
83    case AUDIO_SOURCE_VOICE_CALL:
84        *pPreset = SL_ANDROID_RECORDING_PRESET_NONE;
85        break;
86    case AUDIO_SOURCE_VOICE_RECOGNITION:
87        *pPreset = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
88        break;
89    case AUDIO_SOURCE_CAMCORDER:
90        *pPreset = SL_ANDROID_RECORDING_PRESET_CAMCORDER;
91        break;
92    case AUDIO_SOURCE_VOICE_COMMUNICATION:
93        *pPreset = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION;
94        break;
95    case AUDIO_SOURCE_UNPROCESSED:
96        *pPreset = SL_ANDROID_RECORDING_PRESET_UNPROCESSED;
97        break;
98    default:
99        *pPreset = SL_ANDROID_RECORDING_PRESET_NONE;
100        result = SL_RESULT_INTERNAL_ERROR;
101        break;
102    }
103
104    return result;
105}
106
107
108void audioRecorder_handleNewPos_lockRecord(CAudioRecorder* ar) {
109    //SL_LOGV("received event EVENT_NEW_POS from AudioRecord");
110    slRecordCallback callback = NULL;
111    void* callbackPContext = NULL;
112
113    interface_lock_shared(&ar->mRecord);
114    callback = ar->mRecord.mCallback;
115    callbackPContext = ar->mRecord.mContext;
116    interface_unlock_shared(&ar->mRecord);
117
118    if (NULL != callback) {
119        // getting this event implies SL_RECORDEVENT_HEADATNEWPOS was set in the event mask
120        (*callback)(&ar->mRecord.mItf, callbackPContext, SL_RECORDEVENT_HEADATNEWPOS);
121    }
122}
123
124
125void audioRecorder_handleMarker_lockRecord(CAudioRecorder* ar) {
126    //SL_LOGV("received event EVENT_MARKER from AudioRecord");
127    slRecordCallback callback = NULL;
128    void* callbackPContext = NULL;
129
130    interface_lock_shared(&ar->mRecord);
131    callback = ar->mRecord.mCallback;
132    callbackPContext = ar->mRecord.mContext;
133    interface_unlock_shared(&ar->mRecord);
134
135    if (NULL != callback) {
136        // getting this event implies SL_RECORDEVENT_HEADATMARKER was set in the event mask
137        (*callback)(&ar->mRecord.mItf, callbackPContext, SL_RECORDEVENT_HEADATMARKER);
138    }
139}
140
141
142void audioRecorder_handleOverrun_lockRecord(CAudioRecorder* ar) {
143    //SL_LOGV("received event EVENT_OVERRUN from AudioRecord");
144    slRecordCallback callback = NULL;
145    void* callbackPContext = NULL;
146
147    interface_lock_shared(&ar->mRecord);
148    if (ar->mRecord.mCallbackEventsMask & SL_RECORDEVENT_HEADSTALLED) {
149        callback = ar->mRecord.mCallback;
150        callbackPContext = ar->mRecord.mContext;
151    }
152    interface_unlock_shared(&ar->mRecord);
153
154    if (NULL != callback) {
155        (*callback)(&ar->mRecord.mItf, callbackPContext, SL_RECORDEVENT_HEADSTALLED);
156    }
157}
158
159//-----------------------------------------------------------------------------
160SLresult android_audioRecorder_checkSourceSink(CAudioRecorder* ar) {
161
162    const SLDataSource *pAudioSrc = &ar->mDataSource.u.mSource;
163    const SLDataSink   *pAudioSnk = &ar->mDataSink.u.mSink;
164
165    const SLuint32 sinkLocatorType = *(SLuint32 *)pAudioSnk->pLocator;
166    const SLuint32 sinkFormatType = *(SLuint32 *)pAudioSnk->pFormat;
167
168    const SLuint32 *df_representation = NULL; // pointer to representation field, if it exists
169
170    // sink must be an Android simple buffer queue with PCM data format
171    switch (sinkLocatorType) {
172    case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE: {
173        switch (sinkFormatType) {
174        case SL_ANDROID_DATAFORMAT_PCM_EX: {
175            const SLAndroidDataFormat_PCM_EX *df_pcm =
176                    (SLAndroidDataFormat_PCM_EX *) pAudioSnk->pFormat;
177            // checkDataFormat() already checked representation
178            df_representation = &df_pcm->representation;
179        } // SL_ANDROID_DATAFORMAT_PCM_EX - fall through to next test.
180        case SL_DATAFORMAT_PCM: {
181            const SLDataFormat_PCM *df_pcm = (const SLDataFormat_PCM *) pAudioSnk->pFormat;
182            // checkDataFormat already checked sample rate, channels, and mask
183            ar->mNumChannels = df_pcm->numChannels;
184
185            if (df_pcm->endianness != ar->mObject.mEngine->mEngine.mNativeEndianness) {
186                SL_LOGE("Cannot create audio recorder: unsupported byte order %u",
187                        df_pcm->endianness);
188                return SL_RESULT_CONTENT_UNSUPPORTED;
189            }
190
191            ar->mSampleRateMilliHz = df_pcm->samplesPerSec; // Note: bad field name in SL ES
192            SL_LOGV("AudioRecorder requested sample rate = %u mHz, %u channel(s)",
193                    ar->mSampleRateMilliHz, ar->mNumChannels);
194
195            // we don't support container size != sample depth
196            if (df_pcm->containerSize != df_pcm->bitsPerSample) {
197                SL_LOGE("Cannot create audio recorder: unsupported container size %u bits for "
198                        "sample depth %u bits",
199                        df_pcm->containerSize, (SLuint32)df_pcm->bitsPerSample);
200                return SL_RESULT_CONTENT_UNSUPPORTED;
201            }
202
203            } break;
204        default:
205            SL_LOGE(ERROR_RECORDER_SINK_FORMAT_MUST_BE_PCM);
206            return SL_RESULT_PARAMETER_INVALID;
207        }   // switch (sourceFormatType)
208        } break;    // case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE
209    default:
210        SL_LOGE(ERROR_RECORDER_SINK_MUST_BE_ANDROIDSIMPLEBUFFERQUEUE);
211        return SL_RESULT_PARAMETER_INVALID;
212    }   // switch (sourceLocatorType)
213
214    // Source check:
215    // only input device sources are supported
216    // check it's an IO device
217    if (SL_DATALOCATOR_IODEVICE != *(SLuint32 *)pAudioSrc->pLocator) {
218        SL_LOGE(ERROR_RECORDER_SOURCE_MUST_BE_IODEVICE);
219        return SL_RESULT_PARAMETER_INVALID;
220    } else {
221
222        // check it's an input device
223        SLDataLocator_IODevice *dl_iod = (SLDataLocator_IODevice *) pAudioSrc->pLocator;
224        if (SL_IODEVICE_AUDIOINPUT != dl_iod->deviceType) {
225            SL_LOGE(ERROR_RECORDER_IODEVICE_MUST_BE_AUDIOINPUT);
226            return SL_RESULT_PARAMETER_INVALID;
227        }
228
229        // check it's the default input device, others aren't supported here
230        if (SL_DEFAULTDEVICEID_AUDIOINPUT != dl_iod->deviceID) {
231            SL_LOGE(ERROR_RECORDER_INPUT_ID_MUST_BE_DEFAULT);
232            return SL_RESULT_PARAMETER_INVALID;
233        }
234    }
235
236    return SL_RESULT_SUCCESS;
237}
238//-----------------------------------------------------------------------------
239static void audioRecorder_callback(int event, void* user, void *info) {
240    //SL_LOGV("audioRecorder_callback(%d, %p, %p) entering", event, user, info);
241
242    CAudioRecorder *ar = (CAudioRecorder *)user;
243
244    if (!android::CallbackProtector::enterCbIfOk(ar->mCallbackProtector)) {
245        // it is not safe to enter the callback (the track is about to go away)
246        return;
247    }
248
249    void * callbackPContext = NULL;
250
251    switch (event) {
252    case android::AudioRecord::EVENT_MORE_DATA: {
253        slBufferQueueCallback callback = NULL;
254        android::AudioRecord::Buffer* pBuff = (android::AudioRecord::Buffer*)info;
255
256        // push data to the buffer queue
257        interface_lock_exclusive(&ar->mBufferQueue);
258
259        if (ar->mBufferQueue.mState.count != 0) {
260            assert(ar->mBufferQueue.mFront != ar->mBufferQueue.mRear);
261
262            BufferHeader *oldFront = ar->mBufferQueue.mFront;
263            BufferHeader *newFront = &oldFront[1];
264
265            size_t availSink = oldFront->mSize - ar->mBufferQueue.mSizeConsumed;
266            size_t availSource = pBuff->size;
267            size_t bytesToCopy = availSink < availSource ? availSink : availSource;
268            void *pDest = (char *)oldFront->mBuffer + ar->mBufferQueue.mSizeConsumed;
269            memcpy(pDest, pBuff->raw, bytesToCopy);
270
271            if (bytesToCopy < availSink) {
272                // can't consume the whole or rest of the buffer in one shot
273                ar->mBufferQueue.mSizeConsumed += availSource;
274                // pBuff->size is already equal to bytesToCopy in this case
275            } else {
276                // finish pushing the buffer or push the buffer in one shot
277                pBuff->size = bytesToCopy;
278                ar->mBufferQueue.mSizeConsumed = 0;
279                if (newFront == &ar->mBufferQueue.mArray[ar->mBufferQueue.mNumBuffers + 1]) {
280                    newFront = ar->mBufferQueue.mArray;
281                }
282                ar->mBufferQueue.mFront = newFront;
283
284                ar->mBufferQueue.mState.count--;
285                ar->mBufferQueue.mState.playIndex++;
286
287                // data has been copied to the buffer, and the buffer queue state has been updated
288                // we will notify the client if applicable
289                callback = ar->mBufferQueue.mCallback;
290                // save callback data
291                callbackPContext = ar->mBufferQueue.mContext;
292            }
293        } else { // empty queue
294            // no destination to push the data
295            pBuff->size = 0;
296        }
297
298        interface_unlock_exclusive(&ar->mBufferQueue);
299
300        // notify client
301        if (NULL != callback) {
302            (*callback)(&ar->mBufferQueue.mItf, callbackPContext);
303        }
304        }
305        break;
306
307    case android::AudioRecord::EVENT_OVERRUN:
308        audioRecorder_handleOverrun_lockRecord(ar);
309        break;
310
311    case android::AudioRecord::EVENT_MARKER:
312        audioRecorder_handleMarker_lockRecord(ar);
313        break;
314
315    case android::AudioRecord::EVENT_NEW_POS:
316        audioRecorder_handleNewPos_lockRecord(ar);
317        break;
318
319    case android::AudioRecord::EVENT_NEW_IAUDIORECORD:
320        // ignore for now
321        break;
322
323    default:
324        SL_LOGE("Encountered unknown AudioRecord event %d for CAudioRecord %p", event, ar);
325        break;
326    }
327
328    ar->mCallbackProtector->exitCb();
329}
330
331
332//-----------------------------------------------------------------------------
333SLresult android_audioRecorder_create(CAudioRecorder* ar) {
334    SL_LOGV("android_audioRecorder_create(%p) entering", ar);
335
336    const SLDataSource *pAudioSrc = &ar->mDataSource.u.mSource;
337    const SLDataSink *pAudioSnk = &ar->mDataSink.u.mSink;
338    SLresult result = SL_RESULT_SUCCESS;
339
340    const SLuint32 sourceLocatorType = *(SLuint32 *)pAudioSrc->pLocator;
341    const SLuint32 sinkLocatorType = *(SLuint32 *)pAudioSnk->pLocator;
342
343    //  the following platform-independent fields have been initialized in CreateAudioRecorder()
344    //    ar->mNumChannels
345    //    ar->mSampleRateMilliHz
346
347    if ((SL_DATALOCATOR_IODEVICE == sourceLocatorType) &&
348            (SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE == sinkLocatorType)) {
349        // microphone to simple buffer queue
350        ar->mAndroidObjType = AUDIORECORDER_FROM_MIC_TO_PCM_BUFFERQUEUE;
351        ar->mAudioRecord.clear();
352        ar->mCallbackProtector = new android::CallbackProtector();
353        ar->mRecordSource = AUDIO_SOURCE_DEFAULT;
354    } else {
355        result = SL_RESULT_CONTENT_UNSUPPORTED;
356    }
357
358    return result;
359}
360
361
362//-----------------------------------------------------------------------------
363SLresult android_audioRecorder_setConfig(CAudioRecorder* ar, const SLchar *configKey,
364        const void *pConfigValue, SLuint32 valueSize) {
365
366    SLresult result;
367
368    assert(NULL != ar && NULL != configKey && NULL != pConfigValue);
369    if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_RECORDING_PRESET) == 0) {
370
371        // recording preset
372        if (KEY_RECORDING_PRESET_PARAMSIZE > valueSize) {
373            SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW);
374            result = SL_RESULT_BUFFER_INSUFFICIENT;
375        } else {
376            result = audioRecorder_setPreset(ar, *(SLuint32*)pConfigValue);
377        }
378
379    } else {
380        SL_LOGE(ERROR_CONFIG_UNKNOWN_KEY);
381        result = SL_RESULT_PARAMETER_INVALID;
382    }
383
384    return result;
385}
386
387
388//-----------------------------------------------------------------------------
389SLresult android_audioRecorder_getConfig(CAudioRecorder* ar, const SLchar *configKey,
390        SLuint32* pValueSize, void *pConfigValue) {
391
392    SLresult result;
393
394    assert(NULL != ar && NULL != configKey && NULL != pValueSize);
395    if (strcmp((const char*)configKey, (const char*)SL_ANDROID_KEY_RECORDING_PRESET) == 0) {
396
397        // recording preset
398        if (NULL == pConfigValue) {
399            result = SL_RESULT_SUCCESS;
400        } else if (KEY_RECORDING_PRESET_PARAMSIZE > *pValueSize) {
401            SL_LOGE(ERROR_CONFIG_VALUESIZE_TOO_LOW);
402            result = SL_RESULT_BUFFER_INSUFFICIENT;
403        } else {
404            result = audioRecorder_getPreset(ar, (SLuint32*)pConfigValue);
405        }
406        *pValueSize = KEY_RECORDING_PRESET_PARAMSIZE;
407
408    } else {
409        SL_LOGE(ERROR_CONFIG_UNKNOWN_KEY);
410        result = SL_RESULT_PARAMETER_INVALID;
411    }
412
413    return result;
414}
415
416
417//-----------------------------------------------------------------------------
418SLresult android_audioRecorder_realize(CAudioRecorder* ar, SLboolean async) {
419    SL_LOGV("android_audioRecorder_realize(%p) entering", ar);
420
421    SLresult result = SL_RESULT_SUCCESS;
422
423    // already checked in created and checkSourceSink
424    assert(ar->mDataSink.mLocator.mLocatorType == SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE);
425
426    const SLDataFormat_PCM *df_pcm = &ar->mDataSink.mFormat.mPCM;
427
428    //  the following platform-independent fields have been initialized in CreateAudioRecorder()
429    //    ar->mNumChannels
430    //    ar->mSampleRateMilliHz
431
432    uint32_t sampleRate = sles_to_android_sampleRate(df_pcm->samplesPerSec);
433
434    // currently nothing analogous to canUseFastTrack() for recording
435    audio_input_flags_t policy = AUDIO_INPUT_FLAG_FAST;
436
437    SL_LOGV("Audio Record format: %dch(0x%x), %dbit, %dKHz",
438            df_pcm->numChannels,
439            df_pcm->channelMask,
440            df_pcm->bitsPerSample,
441            df_pcm->samplesPerSec / 1000000);
442
443    // note that df_pcm->channelMask has already been validated during object creation.
444    audio_channel_mask_t channelMask = sles_to_audio_input_channel_mask(df_pcm->channelMask);
445
446    // To maintain backward compatibility with previous releases, ignore
447    // channel masks that are not indexed.
448    if (channelMask == AUDIO_CHANNEL_INVALID
449            || audio_channel_mask_get_representation(channelMask)
450                == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
451        channelMask = audio_channel_in_mask_from_count(df_pcm->numChannels);
452        SL_LOGI("Emulating old channel mask behavior "
453                "(ignoring positional mask %#x, using default mask %#x based on "
454                "channel count of %d)", df_pcm->channelMask, channelMask,
455                df_pcm->numChannels);
456    }
457    SL_LOGV("SLES channel mask %#x converted to Android mask %#x", df_pcm->channelMask, channelMask);
458
459    // initialize platform-specific CAudioRecorder fields
460    ar->mAudioRecord = new android::AudioRecord(
461            ar->mRecordSource,     // source
462            sampleRate,            // sample rate in Hertz
463            sles_to_android_sampleFormat(df_pcm),               // format
464            channelMask,           // channel mask
465            android::String16(),   // app ops
466            0,                     // frameCount
467            audioRecorder_callback,// callback_t
468            (void*)ar,             // user, callback data, here the AudioRecorder
469            0,                     // notificationFrames
470            0,                     // session ID
471            android::AudioRecord::TRANSFER_CALLBACK,
472                                   // transfer type
473            policy);               // audio_input_flags_t
474
475    android::status_t status = ar->mAudioRecord->initCheck();
476    if (android::NO_ERROR != status) {
477        SL_LOGE("android_audioRecorder_realize(%p) error creating AudioRecord object; status %d",
478                ar, status);
479        // FIXME should return a more specific result depending on status
480        result = SL_RESULT_CONTENT_UNSUPPORTED;
481        ar->mAudioRecord.clear();
482    }
483
484    return result;
485}
486
487
488//-----------------------------------------------------------------------------
489/**
490 * Called with a lock on AudioRecorder, and blocks until safe to destroy
491 */
492void android_audioRecorder_preDestroy(CAudioRecorder* ar) {
493    object_unlock_exclusive(&ar->mObject);
494    if (ar->mCallbackProtector != 0) {
495        ar->mCallbackProtector->requestCbExitAndWait();
496    }
497    object_lock_exclusive(&ar->mObject);
498}
499
500
501//-----------------------------------------------------------------------------
502void android_audioRecorder_destroy(CAudioRecorder* ar) {
503    SL_LOGV("android_audioRecorder_destroy(%p) entering", ar);
504
505    if (ar->mAudioRecord != 0) {
506        ar->mAudioRecord->stop();
507        ar->mAudioRecord.clear();
508    }
509    // explicit destructor
510    ar->mAudioRecord.~sp();
511    ar->mCallbackProtector.~sp();
512}
513
514
515//-----------------------------------------------------------------------------
516void android_audioRecorder_setRecordState(CAudioRecorder* ar, SLuint32 state) {
517    SL_LOGV("android_audioRecorder_setRecordState(%p, %u) entering", ar, state);
518
519    if (ar->mAudioRecord == 0) {
520        return;
521    }
522
523    switch (state) {
524     case SL_RECORDSTATE_STOPPED:
525         ar->mAudioRecord->stop();
526         break;
527     case SL_RECORDSTATE_PAUSED:
528         // Note that pausing is treated like stop as this implementation only records to a buffer
529         //  queue, so there is no notion of destination being "opened" or "closed" (See description
530         //  of SL_RECORDSTATE in specification)
531         ar->mAudioRecord->stop();
532         break;
533     case SL_RECORDSTATE_RECORDING:
534         ar->mAudioRecord->start();
535         break;
536     default:
537         break;
538     }
539
540}
541
542
543//-----------------------------------------------------------------------------
544void android_audioRecorder_useRecordEventMask(CAudioRecorder *ar) {
545    IRecord *pRecordItf = &ar->mRecord;
546    SLuint32 eventFlags = pRecordItf->mCallbackEventsMask;
547
548    if (ar->mAudioRecord == 0) {
549        return;
550    }
551
552    if ((eventFlags & SL_RECORDEVENT_HEADATMARKER) && (pRecordItf->mMarkerPosition != 0)) {
553        ar->mAudioRecord->setMarkerPosition((uint32_t)((((int64_t)pRecordItf->mMarkerPosition
554                * sles_to_android_sampleRate(ar->mSampleRateMilliHz)))/1000));
555    } else {
556        // clear marker
557        ar->mAudioRecord->setMarkerPosition(0);
558    }
559
560    if (eventFlags & SL_RECORDEVENT_HEADATNEWPOS) {
561        SL_LOGV("pos update period %d", pRecordItf->mPositionUpdatePeriod);
562         ar->mAudioRecord->setPositionUpdatePeriod(
563                (uint32_t)((((int64_t)pRecordItf->mPositionUpdatePeriod
564                * sles_to_android_sampleRate(ar->mSampleRateMilliHz)))/1000));
565    } else {
566        // clear periodic update
567        ar->mAudioRecord->setPositionUpdatePeriod(0);
568    }
569
570    if (eventFlags & SL_RECORDEVENT_HEADATLIMIT) {
571        // FIXME support SL_RECORDEVENT_HEADATLIMIT
572        SL_LOGD("[ FIXME: IRecord_SetCallbackEventsMask(SL_RECORDEVENT_HEADATLIMIT) on an "
573                    "SL_OBJECTID_AUDIORECORDER to be implemented ]");
574    }
575
576    if (eventFlags & SL_RECORDEVENT_HEADMOVING) {
577        // FIXME support SL_RECORDEVENT_HEADMOVING
578        SL_LOGD("[ FIXME: IRecord_SetCallbackEventsMask(SL_RECORDEVENT_HEADMOVING) on an "
579                "SL_OBJECTID_AUDIORECORDER to be implemented ]");
580    }
581
582    if (eventFlags & SL_RECORDEVENT_BUFFER_FULL) {
583        // nothing to do for SL_RECORDEVENT_BUFFER_FULL since this will not be encountered on
584        // recording to buffer queues
585    }
586
587    if (eventFlags & SL_RECORDEVENT_HEADSTALLED) {
588        // nothing to do for SL_RECORDEVENT_HEADSTALLED, callback event will be checked against mask
589        // when AudioRecord::EVENT_OVERRUN is encountered
590
591    }
592
593}
594
595
596//-----------------------------------------------------------------------------
597void android_audioRecorder_getPosition(CAudioRecorder *ar, SLmillisecond *pPosMsec) {
598    if ((NULL == ar) || (ar->mAudioRecord == 0)) {
599        *pPosMsec = 0;
600    } else {
601        uint32_t positionInFrames;
602        ar->mAudioRecord->getPosition(&positionInFrames);
603        if (ar->mSampleRateMilliHz == UNKNOWN_SAMPLERATE) {
604            *pPosMsec = 0;
605        } else {
606            *pPosMsec = ((int64_t)positionInFrames * 1000) /
607                    sles_to_android_sampleRate(ar->mSampleRateMilliHz);
608        }
609    }
610}
611