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