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