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