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 
audioRecorder_setPreset(CAudioRecorder * ar,SLuint32 recordPreset)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 
audioRecorder_getPreset(CAudioRecorder * ar,SLuint32 * pPreset)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 
audioRecorder_handleNewPos_lockRecord(CAudioRecorder * ar)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 
audioRecorder_handleMarker_lockRecord(CAudioRecorder * ar)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 
audioRecorder_handleOverrun_lockRecord(CAudioRecorder * ar)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 //-----------------------------------------------------------------------------
android_audioRecorder_checkSourceSink(CAudioRecorder * ar)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 //-----------------------------------------------------------------------------
audioRecorder_callback(int event,void * user,void * info)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 //-----------------------------------------------------------------------------
android_audioRecorder_create(CAudioRecorder * ar)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 //-----------------------------------------------------------------------------
android_audioRecorder_setConfig(CAudioRecorder * ar,const SLchar * configKey,const void * pConfigValue,SLuint32 valueSize)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 //-----------------------------------------------------------------------------
android_audioRecorder_getConfig(CAudioRecorder * ar,const SLchar * configKey,SLuint32 * pValueSize,void * pConfigValue)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 //-----------------------------------------------------------------------------
android_audioRecorder_realize(CAudioRecorder * ar,SLboolean async)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  */
android_audioRecorder_preDestroy(CAudioRecorder * ar)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 //-----------------------------------------------------------------------------
android_audioRecorder_destroy(CAudioRecorder * ar)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 //-----------------------------------------------------------------------------
android_audioRecorder_setRecordState(CAudioRecorder * ar,SLuint32 state)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 //-----------------------------------------------------------------------------
android_audioRecorder_useRecordEventMask(CAudioRecorder * ar)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 //-----------------------------------------------------------------------------
android_audioRecorder_getPosition(CAudioRecorder * ar,SLmillisecond * pPosMsec)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