1 /*
2 **
3 ** Copyright 2008, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 //#define LOG_NDEBUG 0
19 #define LOG_TAG "AudioRecord"
20
21 #include <inttypes.h>
22 #include <android-base/macros.h>
23 #include <sys/resource.h>
24
25 #include <audiomanager/AudioManager.h>
26 #include <audiomanager/IAudioManager.h>
27 #include <binder/Binder.h>
28 #include <binder/IPCThreadState.h>
29 #include <binder/IServiceManager.h>
30 #include <media/AudioRecord.h>
31 #include <utils/Log.h>
32 #include <private/media/AudioTrackShared.h>
33 #include <processgroup/sched_policy.h>
34 #include <media/IAudioFlinger.h>
35 #include <media/MediaMetricsItem.h>
36 #include <media/TypeConverter.h>
37
38 #define WAIT_PERIOD_MS 10
39
40 namespace android {
41
42 using android::content::AttributionSourceState;
43 using aidl_utils::statusTFromBinderStatus;
44
45 // ---------------------------------------------------------------------------
46
47 // static
getMinFrameCount(size_t * frameCount,uint32_t sampleRate,audio_format_t format,audio_channel_mask_t channelMask)48 status_t AudioRecord::getMinFrameCount(
49 size_t* frameCount,
50 uint32_t sampleRate,
51 audio_format_t format,
52 audio_channel_mask_t channelMask)
53 {
54 if (frameCount == NULL) {
55 return BAD_VALUE;
56 }
57
58 size_t size;
59 status_t status = AudioSystem::getInputBufferSize(sampleRate, format, channelMask, &size);
60 if (status != NO_ERROR) {
61 ALOGE("%s(): AudioSystem could not query the input buffer size for"
62 " sampleRate %u, format %#x, channelMask %#x; status %d",
63 __func__, sampleRate, format, channelMask, status);
64 return status;
65 }
66
67 // We double the size of input buffer for ping pong use of record buffer.
68 // Assumes audio_is_linear_pcm(format)
69 if ((*frameCount = (size * 2) / (audio_channel_count_from_in_mask(channelMask) *
70 audio_bytes_per_sample(format))) == 0) {
71 ALOGE("%s(): Unsupported configuration: sampleRate %u, format %#x, channelMask %#x",
72 __func__, sampleRate, format, channelMask);
73 return BAD_VALUE;
74 }
75
76 return NO_ERROR;
77 }
78
79 // ---------------------------------------------------------------------------
80
gather(const AudioRecord * record)81 void AudioRecord::MediaMetrics::gather(const AudioRecord *record)
82 {
83 #define MM_PREFIX "android.media.audiorecord." // avoid cut-n-paste errors.
84
85 // Java API 28 entries, do not change.
86 mMetricsItem->setCString(MM_PREFIX "encoding", toString(record->mFormat).c_str());
87 mMetricsItem->setCString(MM_PREFIX "source", toString(record->mAttributes.source).c_str());
88 mMetricsItem->setInt32(MM_PREFIX "latency", (int32_t)record->mLatency); // bad estimate.
89 mMetricsItem->setInt32(MM_PREFIX "samplerate", (int32_t)record->mSampleRate);
90 mMetricsItem->setInt32(MM_PREFIX "channels", (int32_t)record->mChannelCount);
91
92 // Non-API entries, these can change.
93 mMetricsItem->setInt32(MM_PREFIX "portId", (int32_t)record->mPortId);
94 mMetricsItem->setInt32(MM_PREFIX "frameCount", (int32_t)record->mFrameCount);
95 mMetricsItem->setCString(MM_PREFIX "attributes", toString(record->mAttributes).c_str());
96 mMetricsItem->setInt64(MM_PREFIX "channelMask", (int64_t)record->mChannelMask);
97
98 // log total duration recording, including anything currently running.
99 int64_t activeNs = 0;
100 if (mStartedNs != 0) {
101 activeNs = systemTime() - mStartedNs;
102 }
103 mMetricsItem->setDouble(MM_PREFIX "durationMs", (mDurationNs + activeNs) * 1e-6);
104 mMetricsItem->setInt64(MM_PREFIX "startCount", (int64_t)mCount);
105
106 if (mLastError != NO_ERROR) {
107 mMetricsItem->setInt32(MM_PREFIX "lastError.code", (int32_t)mLastError);
108 mMetricsItem->setCString(MM_PREFIX "lastError.at", mLastErrorFunc.c_str());
109 }
110 mMetricsItem->setCString(MM_PREFIX "logSessionId", record->mLogSessionId.c_str());
111 }
112
stateToString(bool active)113 static const char *stateToString(bool active) {
114 return active ? "ACTIVE" : "STOPPED";
115 }
116
117 // hand the user a snapshot of the metrics.
getMetrics(mediametrics::Item * & item)118 status_t AudioRecord::getMetrics(mediametrics::Item * &item)
119 {
120 mMediaMetrics.gather(this);
121 mediametrics::Item *tmp = mMediaMetrics.dup();
122 if (tmp == nullptr) {
123 return BAD_VALUE;
124 }
125 item = tmp;
126 return NO_ERROR;
127 }
128
AudioRecord(const AttributionSourceState & client)129 AudioRecord::AudioRecord(const AttributionSourceState &client)
130 : mActive(false), mStatus(NO_INIT), mClientAttributionSource(client),
131 mSessionId(AUDIO_SESSION_ALLOCATE), mPreviousPriority(ANDROID_PRIORITY_NORMAL),
132 mPreviousSchedulingGroup(SP_DEFAULT), mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
133 mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE), mSelectedMicDirection(MIC_DIRECTION_UNSPECIFIED),
134 mSelectedMicFieldDimension(MIC_FIELD_DIMENSION_DEFAULT)
135 {
136 }
137
AudioRecord(audio_source_t inputSource,uint32_t sampleRate,audio_format_t format,audio_channel_mask_t channelMask,const AttributionSourceState & client,size_t frameCount,callback_t cbf,void * user,uint32_t notificationFrames,audio_session_t sessionId,transfer_type transferType,audio_input_flags_t flags,const audio_attributes_t * pAttributes,audio_port_handle_t selectedDeviceId,audio_microphone_direction_t selectedMicDirection,float microphoneFieldDimension)138 AudioRecord::AudioRecord(
139 audio_source_t inputSource,
140 uint32_t sampleRate,
141 audio_format_t format,
142 audio_channel_mask_t channelMask,
143 const AttributionSourceState& client,
144 size_t frameCount,
145 callback_t cbf,
146 void* user,
147 uint32_t notificationFrames,
148 audio_session_t sessionId,
149 transfer_type transferType,
150 audio_input_flags_t flags,
151 const audio_attributes_t* pAttributes,
152 audio_port_handle_t selectedDeviceId,
153 audio_microphone_direction_t selectedMicDirection,
154 float microphoneFieldDimension)
155 : mActive(false),
156 mStatus(NO_INIT),
157 mClientAttributionSource(client),
158 mSessionId(AUDIO_SESSION_ALLOCATE),
159 mPreviousPriority(ANDROID_PRIORITY_NORMAL),
160 mPreviousSchedulingGroup(SP_DEFAULT),
161 mProxy(NULL)
162 {
163 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(mClientAttributionSource.uid));
164 pid_t pid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mClientAttributionSource.pid));
165 (void)set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
166 notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags,
167 uid, pid, pAttributes, selectedDeviceId, selectedMicDirection,
168 microphoneFieldDimension);
169 }
170
~AudioRecord()171 AudioRecord::~AudioRecord()
172 {
173 mMediaMetrics.gather(this);
174
175 mediametrics::LogItem(mMetricsId)
176 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DTOR)
177 .set(AMEDIAMETRICS_PROP_CALLERNAME,
178 mCallerName.empty()
179 ? AMEDIAMETRICS_PROP_CALLERNAME_VALUE_UNKNOWN
180 : mCallerName.c_str())
181 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)mStatus)
182 .record();
183
184 stopAndJoinCallbacks(); // checks mStatus
185
186 if (mStatus == NO_ERROR) {
187 IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this);
188 mAudioRecord.clear();
189 mCblkMemory.clear();
190 mBufferMemory.clear();
191 IPCThreadState::self()->flushCommands();
192 ALOGV("%s(%d): releasing session id %d",
193 __func__, mPortId, mSessionId);
194 pid_t pid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mClientAttributionSource.pid));
195 AudioSystem::releaseAudioSessionId(mSessionId, pid);
196 }
197 }
198
stopAndJoinCallbacks()199 void AudioRecord::stopAndJoinCallbacks() {
200 // Prevent nullptr crash if it did not open properly.
201 if (mStatus != NO_ERROR) return;
202
203 // Make sure that callback function exits in the case where
204 // it is looping on buffer empty condition in obtainBuffer().
205 // Otherwise the callback thread will never exit.
206 stop();
207 if (mAudioRecordThread != 0) {
208 mProxy->interrupt();
209 mAudioRecordThread->requestExit(); // see comment in AudioRecord.h
210 mAudioRecordThread->requestExitAndWait();
211 mAudioRecordThread.clear();
212 }
213 // No lock here: worst case we remove a NULL callback which will be a nop
214 if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) {
215 // This may not stop all of these device callbacks!
216 // TODO: Add some sort of protection.
217 AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId);
218 }
219 }
set(audio_source_t inputSource,uint32_t sampleRate,audio_format_t format,audio_channel_mask_t channelMask,size_t frameCount,callback_t cbf,void * user,uint32_t notificationFrames,bool threadCanCallJava,audio_session_t sessionId,transfer_type transferType,audio_input_flags_t flags,uid_t uid,pid_t pid,const audio_attributes_t * pAttributes,audio_port_handle_t selectedDeviceId,audio_microphone_direction_t selectedMicDirection,float microphoneFieldDimension,int32_t maxSharedAudioHistoryMs)220 status_t AudioRecord::set(
221 audio_source_t inputSource,
222 uint32_t sampleRate,
223 audio_format_t format,
224 audio_channel_mask_t channelMask,
225 size_t frameCount,
226 callback_t cbf,
227 void* user,
228 uint32_t notificationFrames,
229 bool threadCanCallJava,
230 audio_session_t sessionId,
231 transfer_type transferType,
232 audio_input_flags_t flags,
233 uid_t uid,
234 pid_t pid,
235 const audio_attributes_t* pAttributes,
236 audio_port_handle_t selectedDeviceId,
237 audio_microphone_direction_t selectedMicDirection,
238 float microphoneFieldDimension,
239 int32_t maxSharedAudioHistoryMs)
240 {
241 status_t status = NO_ERROR;
242 uint32_t channelCount;
243
244 // Note mPortId is not valid until the track is created, so omit mPortId in ALOG for set.
245 ALOGV("%s(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
246 "notificationFrames %u, sessionId %d, transferType %d, flags %#x, attributionSource %s"
247 "uid %d, pid %d",
248 __func__,
249 inputSource, sampleRate, format, channelMask, frameCount, notificationFrames,
250 sessionId, transferType, flags, mClientAttributionSource.toString().c_str(), uid, pid);
251
252 // TODO b/182392553: refactor or remove
253 pid_t callingPid = IPCThreadState::self()->getCallingPid();
254 pid_t myPid = getpid();
255 pid_t adjPid = pid;
256 if (pid == -1 || (callingPid != myPid)) {
257 adjPid = callingPid;
258 }
259 mClientAttributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(adjPid));
260
261 uid_t adjUid = uid;
262 if (uid == -1 || (callingPid != myPid)) {
263 adjUid = IPCThreadState::self()->getCallingUid();
264 }
265 mClientAttributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(adjUid));
266
267 mTracker.reset(new RecordingActivityTracker());
268
269 mSelectedDeviceId = selectedDeviceId;
270 mSelectedMicDirection = selectedMicDirection;
271 mSelectedMicFieldDimension = microphoneFieldDimension;
272 mMaxSharedAudioHistoryMs = maxSharedAudioHistoryMs;
273
274 switch (transferType) {
275 case TRANSFER_DEFAULT:
276 if (cbf == NULL || threadCanCallJava) {
277 transferType = TRANSFER_SYNC;
278 } else {
279 transferType = TRANSFER_CALLBACK;
280 }
281 break;
282 case TRANSFER_CALLBACK:
283 if (cbf == NULL) {
284 ALOGE("%s(): Transfer type TRANSFER_CALLBACK but cbf == NULL", __func__);
285 status = BAD_VALUE;
286 goto exit;
287 }
288 break;
289 case TRANSFER_OBTAIN:
290 case TRANSFER_SYNC:
291 break;
292 default:
293 ALOGE("%s(): Invalid transfer type %d", __func__, transferType);
294 status = BAD_VALUE;
295 goto exit;
296 }
297 mTransfer = transferType;
298
299 // invariant that mAudioRecord != 0 is true only after set() returns successfully
300 if (mAudioRecord != 0) {
301 ALOGE("%s(): Track already in use", __func__);
302 status = INVALID_OPERATION;
303 goto exit;
304 }
305
306 if (pAttributes == NULL) {
307 mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
308 mAttributes.source = inputSource;
309 if (inputSource == AUDIO_SOURCE_VOICE_COMMUNICATION
310 || inputSource == AUDIO_SOURCE_CAMCORDER) {
311 mAttributes.flags = static_cast<audio_flags_mask_t>(
312 mAttributes.flags | AUDIO_FLAG_CAPTURE_PRIVATE);
313 }
314 } else {
315 // stream type shouldn't be looked at, this track has audio attributes
316 memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
317 ALOGV("%s(): Building AudioRecord with attributes: source=%d flags=0x%x tags=[%s]",
318 __func__, mAttributes.source, mAttributes.flags, mAttributes.tags);
319 }
320
321 mSampleRate = sampleRate;
322
323 // these below should probably come from the audioFlinger too...
324 if (format == AUDIO_FORMAT_DEFAULT) {
325 format = AUDIO_FORMAT_PCM_16_BIT;
326 }
327
328 // validate parameters
329 // AudioFlinger capture only supports linear PCM
330 if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) {
331 ALOGE("%s(): Format %#x is not linear pcm", __func__, format);
332 status = BAD_VALUE;
333 goto exit;
334 }
335 mFormat = format;
336
337 if (!audio_is_input_channel(channelMask)) {
338 ALOGE("%s(): Invalid channel mask %#x", __func__, channelMask);
339 status = BAD_VALUE;
340 goto exit;
341 }
342 mChannelMask = channelMask;
343 channelCount = audio_channel_count_from_in_mask(channelMask);
344 mChannelCount = channelCount;
345
346 if (audio_is_linear_pcm(format)) {
347 mFrameSize = channelCount * audio_bytes_per_sample(format);
348 } else {
349 mFrameSize = sizeof(uint8_t);
350 }
351
352 // mFrameCount is initialized in createRecord_l
353 mReqFrameCount = frameCount;
354
355 mNotificationFramesReq = notificationFrames;
356 // mNotificationFramesAct is initialized in createRecord_l
357
358 mSessionId = sessionId;
359 ALOGV("%s(): mSessionId %d", __func__, mSessionId);
360
361 mOrigFlags = mFlags = flags;
362 mCbf = cbf;
363
364 if (cbf != NULL) {
365 mAudioRecordThread = new AudioRecordThread(*this);
366 mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO);
367 // thread begins in paused state, and will not reference us until start()
368 }
369
370 // create the IAudioRecord
371 {
372 AutoMutex lock(mLock);
373 status = createRecord_l(0 /*epoch*/);
374 }
375
376 ALOGV("%s(%d): status %d", __func__, mPortId, status);
377
378 if (status != NO_ERROR) {
379 if (mAudioRecordThread != 0) {
380 mAudioRecordThread->requestExit(); // see comment in AudioRecord.h
381 mAudioRecordThread->requestExitAndWait();
382 mAudioRecordThread.clear();
383 }
384 goto exit;
385 }
386
387 mUserData = user;
388 // TODO: add audio hardware input latency here
389 mLatency = (1000LL * mFrameCount) / mSampleRate;
390 mMarkerPosition = 0;
391 mMarkerReached = false;
392 mNewPosition = 0;
393 mUpdatePeriod = 0;
394 AudioSystem::acquireAudioSessionId(mSessionId, adjPid, adjUid);
395 mSequence = 1;
396 mObservedSequence = mSequence;
397 mInOverrun = false;
398 mFramesRead = 0;
399 mFramesReadServerOffset = 0;
400
401 exit:
402 mStatus = status;
403 if (status != NO_ERROR) {
404 mMediaMetrics.markError(status, __FUNCTION__);
405 }
406 return status;
407 }
408
409 // -------------------------------------------------------------------------
410
start(AudioSystem::sync_event_t event,audio_session_t triggerSession)411 status_t AudioRecord::start(AudioSystem::sync_event_t event, audio_session_t triggerSession)
412 {
413 const int64_t beginNs = systemTime();
414 ALOGV("%s(%d): sync event %d trigger session %d", __func__, mPortId, event, triggerSession);
415 AutoMutex lock(mLock);
416
417 status_t status = NO_ERROR;
418 mediametrics::Defer defer([&] {
419 mediametrics::LogItem(mMetricsId)
420 .set(AMEDIAMETRICS_PROP_CALLERNAME,
421 mCallerName.empty()
422 ? AMEDIAMETRICS_PROP_CALLERNAME_VALUE_UNKNOWN
423 : mCallerName.c_str())
424 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_START)
425 .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs))
426 .set(AMEDIAMETRICS_PROP_STATE, stateToString(mActive))
427 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)status)
428 .record(); });
429
430 if (mActive) {
431 return status;
432 }
433
434 // discard data in buffer
435 const uint32_t framesFlushed = mProxy->flush();
436 mFramesReadServerOffset -= mFramesRead + framesFlushed;
437 mFramesRead = 0;
438 mProxy->clearTimestamp(); // timestamp is invalid until next server push
439 mPreviousTimestamp.clear();
440 mTimestampRetrogradePositionReported = false;
441 mTimestampRetrogradeTimeReported = false;
442
443 // reset current position as seen by client to 0
444 mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition());
445 // force refresh of remaining frames by processAudioBuffer() as last
446 // read before stop could be partial.
447 mRefreshRemaining = true;
448
449 mNewPosition = mProxy->getPosition() + mUpdatePeriod;
450 int32_t flags = android_atomic_acquire_load(&mCblk->mFlags);
451
452 // we reactivate markers (mMarkerPosition != 0) as the position is reset to 0.
453 // This is legacy behavior. This is not done in stop() to avoid a race condition
454 // where the last marker event is issued twice.
455 mMarkerReached = false;
456 // mActive is checked by restoreRecord_l
457 mActive = true;
458
459 if (!(flags & CBLK_INVALID)) {
460 status = statusTFromBinderStatus(mAudioRecord->start(event, triggerSession));
461 if (status == DEAD_OBJECT) {
462 flags |= CBLK_INVALID;
463 }
464 }
465 if (flags & CBLK_INVALID) {
466 status = restoreRecord_l("start");
467 }
468
469 // Call these directly because we are already holding the lock.
470 mAudioRecord->setPreferredMicrophoneDirection(mSelectedMicDirection);
471 mAudioRecord->setPreferredMicrophoneFieldDimension(mSelectedMicFieldDimension);
472
473 if (status != NO_ERROR) {
474 mActive = false;
475 ALOGE("%s(%d): status %d", __func__, mPortId, status);
476 mMediaMetrics.markError(status, __FUNCTION__);
477 } else {
478 mTracker->recordingStarted();
479 sp<AudioRecordThread> t = mAudioRecordThread;
480 if (t != 0) {
481 t->resume();
482 } else {
483 mPreviousPriority = getpriority(PRIO_PROCESS, 0);
484 get_sched_policy(0, &mPreviousSchedulingGroup);
485 androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
486 }
487
488 // we've successfully started, log that time
489 mMediaMetrics.logStart(systemTime());
490 }
491 return status;
492 }
493
stop()494 void AudioRecord::stop()
495 {
496 const int64_t beginNs = systemTime();
497 AutoMutex lock(mLock);
498 mediametrics::Defer defer([&] {
499 mediametrics::LogItem(mMetricsId)
500 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_STOP)
501 .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs))
502 .set(AMEDIAMETRICS_PROP_STATE, stateToString(mActive))
503 .record(); });
504
505 ALOGV("%s(%d): mActive:%d\n", __func__, mPortId, mActive);
506 if (!mActive) {
507 return;
508 }
509
510 mActive = false;
511 mProxy->interrupt();
512 mAudioRecord->stop();
513 mTracker->recordingStopped();
514
515 // Note: legacy handling - stop does not clear record marker and
516 // periodic update position; we update those on start().
517
518 sp<AudioRecordThread> t = mAudioRecordThread;
519 if (t != 0) {
520 t->pause();
521 } else {
522 setpriority(PRIO_PROCESS, 0, mPreviousPriority);
523 set_sched_policy(0, mPreviousSchedulingGroup);
524 }
525
526 // we've successfully started, log that time
527 mMediaMetrics.logStop(systemTime());
528 }
529
stopped() const530 bool AudioRecord::stopped() const
531 {
532 AutoMutex lock(mLock);
533 return !mActive;
534 }
535
setMarkerPosition(uint32_t marker)536 status_t AudioRecord::setMarkerPosition(uint32_t marker)
537 {
538 // The only purpose of setting marker position is to get a callback
539 if (mCbf == NULL) {
540 return INVALID_OPERATION;
541 }
542
543 AutoMutex lock(mLock);
544 mMarkerPosition = marker;
545 mMarkerReached = false;
546
547 sp<AudioRecordThread> t = mAudioRecordThread;
548 if (t != 0) {
549 t->wake();
550 }
551 return NO_ERROR;
552 }
553
getMarkerPosition(uint32_t * marker) const554 status_t AudioRecord::getMarkerPosition(uint32_t *marker) const
555 {
556 if (marker == NULL) {
557 return BAD_VALUE;
558 }
559
560 AutoMutex lock(mLock);
561 mMarkerPosition.getValue(marker);
562
563 return NO_ERROR;
564 }
565
setPositionUpdatePeriod(uint32_t updatePeriod)566 status_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod)
567 {
568 // The only purpose of setting position update period is to get a callback
569 if (mCbf == NULL) {
570 return INVALID_OPERATION;
571 }
572
573 AutoMutex lock(mLock);
574 mNewPosition = mProxy->getPosition() + updatePeriod;
575 mUpdatePeriod = updatePeriod;
576
577 sp<AudioRecordThread> t = mAudioRecordThread;
578 if (t != 0) {
579 t->wake();
580 }
581 return NO_ERROR;
582 }
583
getPositionUpdatePeriod(uint32_t * updatePeriod) const584 status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const
585 {
586 if (updatePeriod == NULL) {
587 return BAD_VALUE;
588 }
589
590 AutoMutex lock(mLock);
591 *updatePeriod = mUpdatePeriod;
592
593 return NO_ERROR;
594 }
595
getPosition(uint32_t * position) const596 status_t AudioRecord::getPosition(uint32_t *position) const
597 {
598 if (position == NULL) {
599 return BAD_VALUE;
600 }
601
602 AutoMutex lock(mLock);
603 mProxy->getPosition().getValue(position);
604
605 return NO_ERROR;
606 }
607
getInputFramesLost() const608 uint32_t AudioRecord::getInputFramesLost() const
609 {
610 // no need to check mActive, because if inactive this will return 0, which is what we want
611 return AudioSystem::getInputFramesLost(getInputPrivate());
612 }
613
getTimestamp(ExtendedTimestamp * timestamp)614 status_t AudioRecord::getTimestamp(ExtendedTimestamp *timestamp)
615 {
616 if (timestamp == nullptr) {
617 return BAD_VALUE;
618 }
619 AutoMutex lock(mLock);
620 status_t status = mProxy->getTimestamp(timestamp);
621 if (status == OK) {
622 timestamp->mPosition[ExtendedTimestamp::LOCATION_CLIENT] = mFramesRead;
623 timestamp->mTimeNs[ExtendedTimestamp::LOCATION_CLIENT] = 0;
624 // server side frame offset in case AudioRecord has been restored.
625 for (int i = ExtendedTimestamp::LOCATION_SERVER;
626 i < ExtendedTimestamp::LOCATION_MAX; ++i) {
627 if (timestamp->mTimeNs[i] >= 0) {
628 timestamp->mPosition[i] += mFramesReadServerOffset;
629 }
630 }
631
632 bool timestampRetrogradeTimeReported = false;
633 bool timestampRetrogradePositionReported = false;
634 for (int i = 0; i < ExtendedTimestamp::LOCATION_MAX; ++i) {
635 if (timestamp->mTimeNs[i] >= 0 && mPreviousTimestamp.mTimeNs[i] >= 0) {
636 if (timestamp->mTimeNs[i] < mPreviousTimestamp.mTimeNs[i]) {
637 if (!mTimestampRetrogradeTimeReported) {
638 ALOGD("%s: retrograde time adjusting [%d] current:%lld to previous:%lld",
639 __func__, i, (long long)timestamp->mTimeNs[i],
640 (long long)mPreviousTimestamp.mTimeNs[i]);
641 timestampRetrogradeTimeReported = true;
642 }
643 timestamp->mTimeNs[i] = mPreviousTimestamp.mTimeNs[i];
644 }
645 if (timestamp->mPosition[i] < mPreviousTimestamp.mPosition[i]) {
646 if (!mTimestampRetrogradePositionReported) {
647 ALOGD("%s: retrograde position"
648 " adjusting [%d] current:%lld to previous:%lld",
649 __func__, i, (long long)timestamp->mPosition[i],
650 (long long)mPreviousTimestamp.mPosition[i]);
651 timestampRetrogradePositionReported = true;
652 }
653 timestamp->mPosition[i] = mPreviousTimestamp.mPosition[i];
654 }
655 }
656 }
657 mPreviousTimestamp = *timestamp;
658 if (timestampRetrogradeTimeReported) {
659 mTimestampRetrogradeTimeReported = true;
660 }
661 if (timestampRetrogradePositionReported) {
662 mTimestampRetrogradePositionReported = true;
663 }
664 }
665 return status;
666 }
667
668 // ---- Explicit Routing ---------------------------------------------------
setInputDevice(audio_port_handle_t deviceId)669 status_t AudioRecord::setInputDevice(audio_port_handle_t deviceId) {
670 AutoMutex lock(mLock);
671 if (mSelectedDeviceId != deviceId) {
672 mSelectedDeviceId = deviceId;
673 if (mStatus == NO_ERROR) {
674 // stop capture so that audio policy manager does not reject the new instance start request
675 // as only one capture can be active at a time.
676 if (mAudioRecord != 0 && mActive) {
677 mAudioRecord->stop();
678 }
679 android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
680 mProxy->interrupt();
681 }
682 }
683 return NO_ERROR;
684 }
685
getInputDevice()686 audio_port_handle_t AudioRecord::getInputDevice() {
687 AutoMutex lock(mLock);
688 return mSelectedDeviceId;
689 }
690
691 // must be called with mLock held
updateRoutedDeviceId_l()692 void AudioRecord::updateRoutedDeviceId_l()
693 {
694 // if the record is inactive, do not update actual device as the input stream maybe routed
695 // from a device not relevant to this client because of other active use cases.
696 if (!mActive) {
697 return;
698 }
699 if (mInput != AUDIO_IO_HANDLE_NONE) {
700 audio_port_handle_t deviceId = AudioSystem::getDeviceIdForIo(mInput);
701 if (deviceId != AUDIO_PORT_HANDLE_NONE) {
702 mRoutedDeviceId = deviceId;
703 }
704 }
705 }
706
getRoutedDeviceId()707 audio_port_handle_t AudioRecord::getRoutedDeviceId() {
708 AutoMutex lock(mLock);
709 updateRoutedDeviceId_l();
710 return mRoutedDeviceId;
711 }
712
dump(int fd,const Vector<String16> & args __unused) const713 status_t AudioRecord::dump(int fd, const Vector<String16>& args __unused) const
714 {
715 String8 result;
716
717 result.append(" AudioRecord::dump\n");
718 result.appendFormat(" id(%d) status(%d), active(%d), session Id(%d)\n",
719 mPortId, mStatus, mActive, mSessionId);
720 result.appendFormat(" flags(%#x), req. flags(%#x), audio source(%d)\n",
721 mFlags, mOrigFlags, mAttributes.source);
722 result.appendFormat(" format(%#x), channel mask(%#x), channel count(%u), sample rate(%u)\n",
723 mFormat, mChannelMask, mChannelCount, mSampleRate);
724 result.appendFormat(" frame count(%zu), req. frame count(%zu)\n",
725 mFrameCount, mReqFrameCount);
726 result.appendFormat(" notif. frame count(%u), req. notif. frame count(%u)\n",
727 mNotificationFramesAct, mNotificationFramesReq);
728 result.appendFormat(" input(%d), latency(%u), selected device Id(%d), routed device Id(%d)\n",
729 mInput, mLatency, mSelectedDeviceId, mRoutedDeviceId);
730 result.appendFormat(" mic direction(%d) mic field dimension(%f)",
731 mSelectedMicDirection, mSelectedMicFieldDimension);
732 ::write(fd, result.string(), result.size());
733 return NO_ERROR;
734 }
735
736 // -------------------------------------------------------------------------
737 // TODO Move this macro to a common header file for enum to string conversion in audio framework.
738 #define MEDIA_CASE_ENUM(name) case name: return #name
convertTransferToText(transfer_type transferType)739 const char * AudioRecord::convertTransferToText(transfer_type transferType) {
740 switch (transferType) {
741 MEDIA_CASE_ENUM(TRANSFER_DEFAULT);
742 MEDIA_CASE_ENUM(TRANSFER_CALLBACK);
743 MEDIA_CASE_ENUM(TRANSFER_OBTAIN);
744 MEDIA_CASE_ENUM(TRANSFER_SYNC);
745 default:
746 return "UNRECOGNIZED";
747 }
748 }
749
750 // must be called with mLock held
createRecord_l(const Modulo<uint32_t> & epoch)751 status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch)
752 {
753 const int64_t beginNs = systemTime();
754 const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
755 IAudioFlinger::CreateRecordInput input;
756 IAudioFlinger::CreateRecordOutput output;
757 audio_session_t originalSessionId;
758 void *iMemPointer;
759 audio_track_cblk_t* cblk;
760 status_t status;
761 static const int32_t kMaxCreateAttempts = 3;
762 int32_t remainingAttempts = kMaxCreateAttempts;
763
764 if (audioFlinger == 0) {
765 ALOGE("%s(%d): Could not get audioflinger", __func__, mPortId);
766 status = NO_INIT;
767 goto exit;
768 }
769
770 // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted.
771 // After fast request is denied, we will request again if IAudioRecord is re-created.
772
773 // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger,
774 // we must release it ourselves if anything goes wrong.
775
776 // Client can only express a preference for FAST. Server will perform additional tests.
777 if (mFlags & AUDIO_INPUT_FLAG_FAST) {
778 bool useCaseAllowed =
779 // any of these use cases:
780 // use case 1: callback transfer mode
781 (mTransfer == TRANSFER_CALLBACK) ||
782 // use case 2: blocking read mode
783 // The default buffer capacity at 48 kHz is 2048 frames, or ~42.6 ms.
784 // That's enough for double-buffering with our standard 20 ms rule of thumb for
785 // the minimum period of a non-SCHED_FIFO thread.
786 // This is needed so that AAudio apps can do a low latency non-blocking read from a
787 // callback running with SCHED_FIFO.
788 (mTransfer == TRANSFER_SYNC) ||
789 // use case 3: obtain/release mode
790 (mTransfer == TRANSFER_OBTAIN);
791 if (!useCaseAllowed) {
792 ALOGD("%s(%d): AUDIO_INPUT_FLAG_FAST denied, incompatible transfer = %s",
793 __func__, mPortId,
794 convertTransferToText(mTransfer));
795 mFlags = (audio_input_flags_t) (mFlags & ~(AUDIO_INPUT_FLAG_FAST |
796 AUDIO_INPUT_FLAG_RAW));
797 }
798 }
799
800 input.attr = mAttributes;
801 input.config.sample_rate = mSampleRate;
802 input.config.channel_mask = mChannelMask;
803 input.config.format = mFormat;
804 input.clientInfo.attributionSource = mClientAttributionSource;
805 input.clientInfo.clientTid = -1;
806 if (mFlags & AUDIO_INPUT_FLAG_FAST) {
807 if (mAudioRecordThread != 0) {
808 input.clientInfo.clientTid = mAudioRecordThread->getTid();
809 }
810 }
811 input.riid = mTracker->getRiid();
812
813 input.flags = mFlags;
814 // The notification frame count is the period between callbacks, as suggested by the client
815 // but moderated by the server. For record, the calculations are done entirely on server side.
816 input.frameCount = mReqFrameCount;
817 input.notificationFrameCount = mNotificationFramesReq;
818 input.selectedDeviceId = mSelectedDeviceId;
819 input.sessionId = mSessionId;
820 originalSessionId = mSessionId;
821 input.maxSharedAudioHistoryMs = mMaxSharedAudioHistoryMs;
822
823 do {
824 media::CreateRecordResponse response;
825 status = audioFlinger->createRecord(VALUE_OR_FATAL(input.toAidl()), response);
826 output = VALUE_OR_FATAL(IAudioFlinger::CreateRecordOutput::fromAidl(response));
827 if (status == NO_ERROR) {
828 break;
829 }
830 if (status != FAILED_TRANSACTION || --remainingAttempts <= 0) {
831 ALOGE("%s(%d): AudioFlinger could not create record track, status: %d",
832 __func__, mPortId, status);
833 goto exit;
834 }
835 // FAILED_TRANSACTION happens under very specific conditions causing a state mismatch
836 // between audio policy manager and audio flinger during the input stream open sequence
837 // and can be recovered by retrying.
838 // Leave time for race condition to clear before retrying and randomize delay
839 // to reduce the probability of concurrent retries in locked steps.
840 usleep((20 + rand() % 30) * 10000);
841 } while (1);
842
843 ALOG_ASSERT(output.audioRecord != 0);
844
845 // AudioFlinger now owns the reference to the I/O handle,
846 // so we are no longer responsible for releasing it.
847
848 mAwaitBoost = false;
849 if (output.flags & AUDIO_INPUT_FLAG_FAST) {
850 ALOGI("%s(%d): AUDIO_INPUT_FLAG_FAST successful; frameCount %zu -> %zu",
851 __func__, mPortId,
852 mReqFrameCount, output.frameCount);
853 mAwaitBoost = true;
854 }
855 mFlags = output.flags;
856 mRoutedDeviceId = output.selectedDeviceId;
857 mSessionId = output.sessionId;
858 mSampleRate = output.sampleRate;
859
860 if (output.cblk == 0) {
861 ALOGE("%s(%d): Could not get control block", __func__, mPortId);
862 status = NO_INIT;
863 goto exit;
864 }
865 // TODO: Using unsecurePointer() has some associated security pitfalls
866 // (see declaration for details).
867 // Either document why it is safe in this case or address the
868 // issue (e.g. by copying).
869 iMemPointer = output.cblk ->unsecurePointer();
870 if (iMemPointer == NULL) {
871 ALOGE("%s(%d): Could not get control block pointer", __func__, mPortId);
872 status = NO_INIT;
873 goto exit;
874 }
875 cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
876
877 // Starting address of buffers in shared memory.
878 // The buffers are either immediately after the control block,
879 // or in a separate area at discretion of server.
880 void *buffers;
881 if (output.buffers == 0) {
882 buffers = cblk + 1;
883 } else {
884 // TODO: Using unsecurePointer() has some associated security pitfalls
885 // (see declaration for details).
886 // Either document why it is safe in this case or address the
887 // issue (e.g. by copying).
888 buffers = output.buffers->unsecurePointer();
889 if (buffers == NULL) {
890 ALOGE("%s(%d): Could not get buffer pointer", __func__, mPortId);
891 status = NO_INIT;
892 goto exit;
893 }
894 }
895
896 // invariant that mAudioRecord != 0 is true only after set() returns successfully
897 if (mAudioRecord != 0) {
898 IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this);
899 mDeathNotifier.clear();
900 }
901 mAudioRecord = output.audioRecord;
902 mCblkMemory = output.cblk;
903 mBufferMemory = output.buffers;
904 IPCThreadState::self()->flushCommands();
905
906 mCblk = cblk;
907 // note that output.frameCount is the (possibly revised) value of mReqFrameCount
908 if (output.frameCount < mReqFrameCount || (mReqFrameCount == 0 && output.frameCount == 0)) {
909 ALOGW("%s(%d): Requested frameCount %zu but received frameCount %zu",
910 __func__, output.portId,
911 mReqFrameCount, output.frameCount);
912 }
913
914 // Make sure that application is notified with sufficient margin before overrun.
915 // The computation is done on server side.
916 if (mNotificationFramesReq > 0 && output.notificationFrameCount != mNotificationFramesReq) {
917 ALOGW("%s(%d): Server adjusted notificationFrames from %u to %zu for frameCount %zu",
918 __func__, output.portId,
919 mNotificationFramesReq, output.notificationFrameCount, output.frameCount);
920 }
921 mNotificationFramesAct = (uint32_t)output.notificationFrameCount;
922
923 //mInput != input includes the case where mInput == AUDIO_IO_HANDLE_NONE for first creation
924 if (mDeviceCallback != 0) {
925 if (mInput != AUDIO_IO_HANDLE_NONE) {
926 AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId);
927 }
928 AudioSystem::addAudioDeviceCallback(this, output.inputId, output.portId);
929 }
930
931 if (!mSharedAudioPackageName.empty()) {
932 mAudioRecord->shareAudioHistory(mSharedAudioPackageName, mSharedAudioStartMs);
933 }
934
935 mPortId = output.portId;
936 // We retain a copy of the I/O handle, but don't own the reference
937 mInput = output.inputId;
938 mRefreshRemaining = true;
939
940 mFrameCount = output.frameCount;
941 // If IAudioRecord is re-created, don't let the requested frameCount
942 // decrease. This can confuse clients that cache frameCount().
943 if (mFrameCount > mReqFrameCount) {
944 mReqFrameCount = mFrameCount;
945 }
946
947 // update proxy
948 mProxy = new AudioRecordClientProxy(cblk, buffers, mFrameCount, mFrameSize);
949 mProxy->setEpoch(epoch);
950 mProxy->setMinimum(mNotificationFramesAct);
951
952 mDeathNotifier = new DeathNotifier(this);
953 IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this);
954
955 mMetricsId = std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(mPortId);
956 mediametrics::LogItem(mMetricsId)
957 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE)
958 .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs))
959 // the following are immutable (at least until restore)
960 .set(AMEDIAMETRICS_PROP_FLAGS, toString(mFlags).c_str())
961 .set(AMEDIAMETRICS_PROP_ORIGINALFLAGS, toString(mOrigFlags).c_str())
962 .set(AMEDIAMETRICS_PROP_SESSIONID, (int32_t)mSessionId)
963 .set(AMEDIAMETRICS_PROP_TRACKID, mPortId)
964 .set(AMEDIAMETRICS_PROP_LOGSESSIONID, mLogSessionId)
965 .set(AMEDIAMETRICS_PROP_SOURCE, toString(mAttributes.source).c_str())
966 .set(AMEDIAMETRICS_PROP_THREADID, (int32_t)output.inputId)
967 .set(AMEDIAMETRICS_PROP_SELECTEDDEVICEID, (int32_t)mSelectedDeviceId)
968 .set(AMEDIAMETRICS_PROP_ROUTEDDEVICEID, (int32_t)mRoutedDeviceId)
969 .set(AMEDIAMETRICS_PROP_ENCODING, toString(mFormat).c_str())
970 .set(AMEDIAMETRICS_PROP_CHANNELMASK, (int32_t)mChannelMask)
971 .set(AMEDIAMETRICS_PROP_FRAMECOUNT, (int32_t)mFrameCount)
972 .set(AMEDIAMETRICS_PROP_SAMPLERATE, (int32_t)mSampleRate)
973 // the following are NOT immutable
974 .set(AMEDIAMETRICS_PROP_STATE, stateToString(mActive))
975 .set(AMEDIAMETRICS_PROP_SELECTEDMICDIRECTION, (int32_t)mSelectedMicDirection)
976 .set(AMEDIAMETRICS_PROP_SELECTEDMICFIELDDIRECTION, (double)mSelectedMicFieldDimension)
977 .record();
978
979 exit:
980 mStatus = status;
981 // sp<IAudioTrack> track destructor will cause releaseOutput() to be called by AudioFlinger
982 return status;
983 }
984
obtainBuffer(Buffer * audioBuffer,int32_t waitCount,size_t * nonContig)985 status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount, size_t *nonContig)
986 {
987 if (audioBuffer == NULL) {
988 if (nonContig != NULL) {
989 *nonContig = 0;
990 }
991 return BAD_VALUE;
992 }
993 if (mTransfer != TRANSFER_OBTAIN) {
994 audioBuffer->frameCount = 0;
995 audioBuffer->size = 0;
996 audioBuffer->raw = NULL;
997 if (nonContig != NULL) {
998 *nonContig = 0;
999 }
1000 return INVALID_OPERATION;
1001 }
1002
1003 const struct timespec *requested;
1004 struct timespec timeout;
1005 if (waitCount == -1) {
1006 requested = &ClientProxy::kForever;
1007 } else if (waitCount == 0) {
1008 requested = &ClientProxy::kNonBlocking;
1009 } else if (waitCount > 0) {
1010 time_t ms = WAIT_PERIOD_MS * (time_t) waitCount;
1011 timeout.tv_sec = ms / 1000;
1012 timeout.tv_nsec = (long) (ms % 1000) * 1000000;
1013 requested = &timeout;
1014 } else {
1015 ALOGE("%s(%d): invalid waitCount %d", __func__, mPortId, waitCount);
1016 requested = NULL;
1017 }
1018 return obtainBuffer(audioBuffer, requested, NULL /*elapsed*/, nonContig);
1019 }
1020
obtainBuffer(Buffer * audioBuffer,const struct timespec * requested,struct timespec * elapsed,size_t * nonContig)1021 status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *requested,
1022 struct timespec *elapsed, size_t *nonContig)
1023 {
1024 // previous and new IAudioRecord sequence numbers are used to detect track re-creation
1025 uint32_t oldSequence = 0;
1026
1027 Proxy::Buffer buffer;
1028 status_t status = NO_ERROR;
1029
1030 static const int32_t kMaxTries = 5;
1031 int32_t tryCounter = kMaxTries;
1032
1033 do {
1034 // obtainBuffer() is called with mutex unlocked, so keep extra references to these fields to
1035 // keep them from going away if another thread re-creates the track during obtainBuffer()
1036 sp<AudioRecordClientProxy> proxy;
1037 sp<IMemory> iMem;
1038 sp<IMemory> bufferMem;
1039 {
1040 // start of lock scope
1041 AutoMutex lock(mLock);
1042
1043 uint32_t newSequence = mSequence;
1044 // did previous obtainBuffer() fail due to media server death or voluntary invalidation?
1045 if (status == DEAD_OBJECT) {
1046 // re-create track, unless someone else has already done so
1047 if (newSequence == oldSequence) {
1048 status = restoreRecord_l("obtainBuffer");
1049 if (status != NO_ERROR) {
1050 buffer.mFrameCount = 0;
1051 buffer.mRaw = NULL;
1052 buffer.mNonContig = 0;
1053 break;
1054 }
1055 }
1056 }
1057 oldSequence = newSequence;
1058
1059 // Keep the extra references
1060 proxy = mProxy;
1061 iMem = mCblkMemory;
1062 bufferMem = mBufferMemory;
1063
1064 // Non-blocking if track is stopped
1065 if (!mActive) {
1066 requested = &ClientProxy::kNonBlocking;
1067 }
1068
1069 } // end of lock scope
1070
1071 buffer.mFrameCount = audioBuffer->frameCount;
1072 // FIXME starts the requested timeout and elapsed over from scratch
1073 status = proxy->obtainBuffer(&buffer, requested, elapsed);
1074
1075 } while ((status == DEAD_OBJECT) && (tryCounter-- > 0));
1076
1077 audioBuffer->frameCount = buffer.mFrameCount;
1078 audioBuffer->size = buffer.mFrameCount * mFrameSize;
1079 audioBuffer->raw = buffer.mRaw;
1080 audioBuffer->sequence = oldSequence;
1081 if (nonContig != NULL) {
1082 *nonContig = buffer.mNonContig;
1083 }
1084 return status;
1085 }
1086
releaseBuffer(const Buffer * audioBuffer)1087 void AudioRecord::releaseBuffer(const Buffer* audioBuffer)
1088 {
1089 // FIXME add error checking on mode, by adding an internal version
1090
1091 size_t stepCount = audioBuffer->size / mFrameSize;
1092 if (stepCount == 0) {
1093 return;
1094 }
1095
1096 Proxy::Buffer buffer;
1097 buffer.mFrameCount = stepCount;
1098 buffer.mRaw = audioBuffer->raw;
1099
1100 AutoMutex lock(mLock);
1101 if (audioBuffer->sequence != mSequence) {
1102 // This Buffer came from a different IAudioRecord instance, so ignore the releaseBuffer
1103 ALOGD("%s is no-op due to IAudioRecord sequence mismatch %u != %u",
1104 __func__, audioBuffer->sequence, mSequence);
1105 return;
1106 }
1107 mInOverrun = false;
1108 mProxy->releaseBuffer(&buffer);
1109
1110 // the server does not automatically disable recorder on overrun, so no need to restart
1111 }
1112
getInputPrivate() const1113 audio_io_handle_t AudioRecord::getInputPrivate() const
1114 {
1115 AutoMutex lock(mLock);
1116 return mInput;
1117 }
1118
1119 // -------------------------------------------------------------------------
1120
read(void * buffer,size_t userSize,bool blocking)1121 ssize_t AudioRecord::read(void* buffer, size_t userSize, bool blocking)
1122 {
1123 if (mTransfer != TRANSFER_SYNC) {
1124 return INVALID_OPERATION;
1125 }
1126
1127 if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) {
1128 // Validation. user is most-likely passing an error code, and it would
1129 // make the return value ambiguous (actualSize vs error).
1130 ALOGE("%s(%d) (buffer=%p, size=%zu (%zu)",
1131 __func__, mPortId, buffer, userSize, userSize);
1132 return BAD_VALUE;
1133 }
1134
1135 ssize_t read = 0;
1136 Buffer audioBuffer;
1137
1138 while (userSize >= mFrameSize) {
1139 audioBuffer.frameCount = userSize / mFrameSize;
1140
1141 status_t err = obtainBuffer(&audioBuffer,
1142 blocking ? &ClientProxy::kForever : &ClientProxy::kNonBlocking);
1143 if (err < 0) {
1144 if (read > 0) {
1145 break;
1146 }
1147 if (err == TIMED_OUT || err == -EINTR) {
1148 err = WOULD_BLOCK;
1149 }
1150 return ssize_t(err);
1151 }
1152
1153 size_t bytesRead = audioBuffer.size;
1154 memcpy(buffer, audioBuffer.i8, bytesRead);
1155 buffer = ((char *) buffer) + bytesRead;
1156 userSize -= bytesRead;
1157 read += bytesRead;
1158
1159 releaseBuffer(&audioBuffer);
1160 }
1161 if (read > 0) {
1162 mFramesRead += read / mFrameSize;
1163 // mFramesReadTime = systemTime(SYSTEM_TIME_MONOTONIC); // not provided at this time.
1164 }
1165 return read;
1166 }
1167
1168 // -------------------------------------------------------------------------
1169
processAudioBuffer()1170 nsecs_t AudioRecord::processAudioBuffer()
1171 {
1172 mLock.lock();
1173 if (mAwaitBoost) {
1174 mAwaitBoost = false;
1175 mLock.unlock();
1176 static const int32_t kMaxTries = 5;
1177 int32_t tryCounter = kMaxTries;
1178 uint32_t pollUs = 10000;
1179 do {
1180 int policy = sched_getscheduler(0) & ~SCHED_RESET_ON_FORK;
1181 if (policy == SCHED_FIFO || policy == SCHED_RR) {
1182 break;
1183 }
1184 usleep(pollUs);
1185 pollUs <<= 1;
1186 } while (tryCounter-- > 0);
1187 if (tryCounter < 0) {
1188 ALOGE("%s(%d): did not receive expected priority boost on time", __func__, mPortId);
1189 }
1190 // Run again immediately
1191 return 0;
1192 }
1193
1194 // Can only reference mCblk while locked
1195 int32_t flags = android_atomic_and(~CBLK_OVERRUN, &mCblk->mFlags);
1196
1197 // Check for track invalidation
1198 if (flags & CBLK_INVALID) {
1199 (void) restoreRecord_l("processAudioBuffer");
1200 mLock.unlock();
1201 // Run again immediately, but with a new IAudioRecord
1202 return 0;
1203 }
1204
1205 bool active = mActive;
1206
1207 // Manage overrun callback, must be done under lock to avoid race with releaseBuffer()
1208 bool newOverrun = false;
1209 if (flags & CBLK_OVERRUN) {
1210 if (!mInOverrun) {
1211 mInOverrun = true;
1212 newOverrun = true;
1213 }
1214 }
1215
1216 // Get current position of server
1217 Modulo<uint32_t> position(mProxy->getPosition());
1218
1219 // Manage marker callback
1220 bool markerReached = false;
1221 Modulo<uint32_t> markerPosition(mMarkerPosition);
1222 // FIXME fails for wraparound, need 64 bits
1223 if (!mMarkerReached && markerPosition.value() > 0 && position >= markerPosition) {
1224 mMarkerReached = markerReached = true;
1225 }
1226
1227 // Determine the number of new position callback(s) that will be needed, while locked
1228 size_t newPosCount = 0;
1229 Modulo<uint32_t> newPosition(mNewPosition);
1230 uint32_t updatePeriod = mUpdatePeriod;
1231 // FIXME fails for wraparound, need 64 bits
1232 if (updatePeriod > 0 && position >= newPosition) {
1233 newPosCount = ((position - newPosition).value() / updatePeriod) + 1;
1234 mNewPosition += updatePeriod * newPosCount;
1235 }
1236
1237 // Cache other fields that will be needed soon
1238 uint32_t notificationFrames = mNotificationFramesAct;
1239 if (mRefreshRemaining) {
1240 mRefreshRemaining = false;
1241 mRemainingFrames = notificationFrames;
1242 mRetryOnPartialBuffer = false;
1243 }
1244 size_t misalignment = mProxy->getMisalignment();
1245 uint32_t sequence = mSequence;
1246
1247 // These fields don't need to be cached, because they are assigned only by set():
1248 // mTransfer, mCbf, mUserData, mSampleRate, mFrameSize
1249
1250 mLock.unlock();
1251
1252 // perform callbacks while unlocked
1253 if (newOverrun) {
1254 mCbf(EVENT_OVERRUN, mUserData, NULL);
1255 }
1256 if (markerReached) {
1257 mCbf(EVENT_MARKER, mUserData, &markerPosition);
1258 }
1259 while (newPosCount > 0) {
1260 size_t temp = newPosition.value(); // FIXME size_t != uint32_t
1261 mCbf(EVENT_NEW_POS, mUserData, &temp);
1262 newPosition += updatePeriod;
1263 newPosCount--;
1264 }
1265 if (mObservedSequence != sequence) {
1266 mObservedSequence = sequence;
1267 mCbf(EVENT_NEW_IAUDIORECORD, mUserData, NULL);
1268 }
1269
1270 // if inactive, then don't run me again until re-started
1271 if (!active) {
1272 return NS_INACTIVE;
1273 }
1274
1275 // Compute the estimated time until the next timed event (position, markers)
1276 uint32_t minFrames = ~0;
1277 if (!markerReached && position < markerPosition) {
1278 minFrames = (markerPosition - position).value();
1279 }
1280 if (updatePeriod > 0) {
1281 uint32_t remaining = (newPosition - position).value();
1282 if (remaining < minFrames) {
1283 minFrames = remaining;
1284 }
1285 }
1286
1287 // If > 0, poll periodically to recover from a stuck server. A good value is 2.
1288 static const uint32_t kPoll = 0;
1289 if (kPoll > 0 && mTransfer == TRANSFER_CALLBACK && kPoll * notificationFrames < minFrames) {
1290 minFrames = kPoll * notificationFrames;
1291 }
1292
1293 // Convert frame units to time units
1294 nsecs_t ns = NS_WHENEVER;
1295 if (minFrames != (uint32_t) ~0) {
1296 // This "fudge factor" avoids soaking CPU, and compensates for late progress by server
1297 static const nsecs_t kFudgeNs = 10000000LL; // 10 ms
1298 ns = ((minFrames * 1000000000LL) / mSampleRate) + kFudgeNs;
1299 }
1300
1301 // If not supplying data by EVENT_MORE_DATA, then we're done
1302 if (mTransfer != TRANSFER_CALLBACK) {
1303 return ns;
1304 }
1305
1306 struct timespec timeout;
1307 const struct timespec *requested = &ClientProxy::kForever;
1308 if (ns != NS_WHENEVER) {
1309 timeout.tv_sec = ns / 1000000000LL;
1310 timeout.tv_nsec = ns % 1000000000LL;
1311 ALOGV("%s(%d): timeout %ld.%03d",
1312 __func__, mPortId, timeout.tv_sec, (int) timeout.tv_nsec / 1000000);
1313 requested = &timeout;
1314 }
1315
1316 size_t readFrames = 0;
1317 while (mRemainingFrames > 0) {
1318
1319 Buffer audioBuffer;
1320 audioBuffer.frameCount = mRemainingFrames;
1321 size_t nonContig;
1322 status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig);
1323 LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0),
1324 "%s(%d): obtainBuffer() err=%d frameCount=%zu",
1325 __func__, mPortId, err, audioBuffer.frameCount);
1326 requested = &ClientProxy::kNonBlocking;
1327 size_t avail = audioBuffer.frameCount + nonContig;
1328 ALOGV("%s(%d): obtainBuffer(%u) returned %zu = %zu + %zu err %d",
1329 __func__, mPortId, mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err);
1330 if (err != NO_ERROR) {
1331 if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR) {
1332 break;
1333 }
1334 ALOGE("%s(%d): Error %d obtaining an audio buffer, giving up.",
1335 __func__, mPortId, err);
1336 return NS_NEVER;
1337 }
1338
1339 if (mRetryOnPartialBuffer) {
1340 mRetryOnPartialBuffer = false;
1341 if (avail < mRemainingFrames) {
1342 int64_t myns = ((mRemainingFrames - avail) *
1343 1100000000LL) / mSampleRate;
1344 if (ns < 0 || myns < ns) {
1345 ns = myns;
1346 }
1347 return ns;
1348 }
1349 }
1350
1351 size_t reqSize = audioBuffer.size;
1352 mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
1353 size_t readSize = audioBuffer.size;
1354
1355 // Validate on returned size
1356 if (ssize_t(readSize) < 0 || readSize > reqSize) {
1357 ALOGE("%s(%d): EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes",
1358 __func__, mPortId, reqSize, ssize_t(readSize));
1359 return NS_NEVER;
1360 }
1361
1362 if (readSize == 0) {
1363 // The callback is done consuming buffers
1364 // Keep this thread going to handle timed events and
1365 // still try to provide more data in intervals of WAIT_PERIOD_MS
1366 // but don't just loop and block the CPU, so wait
1367 return WAIT_PERIOD_MS * 1000000LL;
1368 }
1369
1370 size_t releasedFrames = readSize / mFrameSize;
1371 audioBuffer.frameCount = releasedFrames;
1372 mRemainingFrames -= releasedFrames;
1373 if (misalignment >= releasedFrames) {
1374 misalignment -= releasedFrames;
1375 } else {
1376 misalignment = 0;
1377 }
1378
1379 releaseBuffer(&audioBuffer);
1380 readFrames += releasedFrames;
1381
1382 // FIXME here is where we would repeat EVENT_MORE_DATA again on same advanced buffer
1383 // if callback doesn't like to accept the full chunk
1384 if (readSize < reqSize) {
1385 continue;
1386 }
1387
1388 // There could be enough non-contiguous frames available to satisfy the remaining request
1389 if (mRemainingFrames <= nonContig) {
1390 continue;
1391 }
1392
1393 #if 0
1394 // This heuristic tries to collapse a series of EVENT_MORE_DATA that would total to a
1395 // sum <= notificationFrames. It replaces that series by at most two EVENT_MORE_DATA
1396 // that total to a sum == notificationFrames.
1397 if (0 < misalignment && misalignment <= mRemainingFrames) {
1398 mRemainingFrames = misalignment;
1399 return (mRemainingFrames * 1100000000LL) / mSampleRate;
1400 }
1401 #endif
1402
1403 }
1404 if (readFrames > 0) {
1405 AutoMutex lock(mLock);
1406 mFramesRead += readFrames;
1407 // mFramesReadTime = systemTime(SYSTEM_TIME_MONOTONIC); // not provided at this time.
1408 }
1409 mRemainingFrames = notificationFrames;
1410 mRetryOnPartialBuffer = true;
1411
1412 // A lot has transpired since ns was calculated, so run again immediately and re-calculate
1413 return 0;
1414 }
1415
restoreRecord_l(const char * from)1416 status_t AudioRecord::restoreRecord_l(const char *from)
1417 {
1418 status_t result = NO_ERROR; // logged: make sure to set this before returning.
1419 const int64_t beginNs = systemTime();
1420 mediametrics::Defer defer([&] {
1421 mediametrics::LogItem(mMetricsId)
1422 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_RESTORE)
1423 .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs))
1424 .set(AMEDIAMETRICS_PROP_STATE, stateToString(mActive))
1425 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result)
1426 .set(AMEDIAMETRICS_PROP_WHERE, from)
1427 .record(); });
1428
1429 ALOGW("%s(%d): dead IAudioRecord, creating a new one from %s()", __func__, mPortId, from);
1430 ++mSequence;
1431
1432 const int INITIAL_RETRIES = 3;
1433 int retries = INITIAL_RETRIES;
1434 retry:
1435 if (retries < INITIAL_RETRIES) {
1436 // refresh the audio configuration cache in this process to make sure we get new
1437 // input parameters and new IAudioRecord in createRecord_l()
1438 AudioSystem::clearAudioConfigCache();
1439 }
1440 mFlags = mOrigFlags;
1441
1442 // if the new IAudioRecord is created, createRecord_l() will modify the
1443 // following member variables: mAudioRecord, mCblkMemory, mCblk, mBufferMemory.
1444 // It will also delete the strong references on previous IAudioRecord and IMemory
1445 Modulo<uint32_t> position(mProxy->getPosition());
1446 mNewPosition = position + mUpdatePeriod;
1447 result = createRecord_l(position);
1448
1449 if (result == NO_ERROR) {
1450 if (mActive) {
1451 // callback thread or sync event hasn't changed
1452 // FIXME this fails if we have a new AudioFlinger instance
1453 result = statusTFromBinderStatus(mAudioRecord->start(
1454 AudioSystem::SYNC_EVENT_SAME, AUDIO_SESSION_NONE));
1455 }
1456 mFramesReadServerOffset = mFramesRead; // server resets to zero so we need an offset.
1457 }
1458
1459 if (result != NO_ERROR) {
1460 ALOGW("%s(%d): failed status %d, retries %d", __func__, mPortId, result, retries);
1461 if (--retries > 0) {
1462 // leave time for an eventual race condition to clear before retrying
1463 usleep(500000);
1464 goto retry;
1465 }
1466 // if no retries left, set invalid bit to force restoring at next occasion
1467 // and avoid inconsistent active state on client and server sides
1468 if (mCblk != nullptr) {
1469 android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
1470 }
1471 }
1472
1473 return result;
1474 }
1475
addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback> & callback)1476 status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback)
1477 {
1478 if (callback == 0) {
1479 ALOGW("%s(%d): adding NULL callback!", __func__, mPortId);
1480 return BAD_VALUE;
1481 }
1482 AutoMutex lock(mLock);
1483 if (mDeviceCallback.unsafe_get() == callback.get()) {
1484 ALOGW("%s(%d): adding same callback!", __func__, mPortId);
1485 return INVALID_OPERATION;
1486 }
1487 status_t status = NO_ERROR;
1488 if (mInput != AUDIO_IO_HANDLE_NONE) {
1489 if (mDeviceCallback != 0) {
1490 ALOGW("%s(%d): callback already present!", __func__, mPortId);
1491 AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId);
1492 }
1493 status = AudioSystem::addAudioDeviceCallback(this, mInput, mPortId);
1494 }
1495 mDeviceCallback = callback;
1496 return status;
1497 }
1498
removeAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback> & callback)1499 status_t AudioRecord::removeAudioDeviceCallback(
1500 const sp<AudioSystem::AudioDeviceCallback>& callback)
1501 {
1502 if (callback == 0) {
1503 ALOGW("%s(%d): removing NULL callback!", __func__, mPortId);
1504 return BAD_VALUE;
1505 }
1506 AutoMutex lock(mLock);
1507 if (mDeviceCallback.unsafe_get() != callback.get()) {
1508 ALOGW("%s(%d): removing different callback!", __func__, mPortId);
1509 return INVALID_OPERATION;
1510 }
1511 mDeviceCallback.clear();
1512 if (mInput != AUDIO_IO_HANDLE_NONE) {
1513 AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId);
1514 }
1515 return NO_ERROR;
1516 }
1517
onAudioDeviceUpdate(audio_io_handle_t audioIo,audio_port_handle_t deviceId)1518 void AudioRecord::onAudioDeviceUpdate(audio_io_handle_t audioIo,
1519 audio_port_handle_t deviceId)
1520 {
1521 sp<AudioSystem::AudioDeviceCallback> callback;
1522 {
1523 AutoMutex lock(mLock);
1524 if (audioIo != mInput) {
1525 return;
1526 }
1527 callback = mDeviceCallback.promote();
1528 // only update device if the record is active as route changes due to other use cases are
1529 // irrelevant for this client
1530 if (mActive) {
1531 mRoutedDeviceId = deviceId;
1532 }
1533 }
1534 if (callback.get() != nullptr) {
1535 callback->onAudioDeviceUpdate(mInput, mRoutedDeviceId);
1536 }
1537 }
1538
1539 // -------------------------------------------------------------------------
1540
getActiveMicrophones(std::vector<media::MicrophoneInfo> * activeMicrophones)1541 status_t AudioRecord::getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones)
1542 {
1543 AutoMutex lock(mLock);
1544 std::vector<media::MicrophoneInfoData> mics;
1545 status_t status = statusTFromBinderStatus(mAudioRecord->getActiveMicrophones(&mics));
1546 activeMicrophones->resize(mics.size());
1547 for (size_t i = 0; status == OK && i < mics.size(); ++i) {
1548 status = activeMicrophones->at(i).readFromParcelable(mics[i]);
1549 }
1550 return status;
1551 }
1552
setPreferredMicrophoneDirection(audio_microphone_direction_t direction)1553 status_t AudioRecord::setPreferredMicrophoneDirection(audio_microphone_direction_t direction)
1554 {
1555 AutoMutex lock(mLock);
1556 if (mSelectedMicDirection == direction) {
1557 // NOP
1558 return OK;
1559 }
1560
1561 mSelectedMicDirection = direction;
1562 if (mAudioRecord == 0) {
1563 // the internal AudioRecord hasn't be created yet, so just stash the attribute.
1564 return OK;
1565 } else {
1566 return statusTFromBinderStatus(mAudioRecord->setPreferredMicrophoneDirection(direction));
1567 }
1568 }
1569
setPreferredMicrophoneFieldDimension(float zoom)1570 status_t AudioRecord::setPreferredMicrophoneFieldDimension(float zoom) {
1571 AutoMutex lock(mLock);
1572 if (mSelectedMicFieldDimension == zoom) {
1573 // NOP
1574 return OK;
1575 }
1576
1577 mSelectedMicFieldDimension = zoom;
1578 if (mAudioRecord == 0) {
1579 // the internal AudioRecord hasn't be created yet, so just stash the attribute.
1580 return OK;
1581 } else {
1582 return statusTFromBinderStatus(mAudioRecord->setPreferredMicrophoneFieldDimension(zoom));
1583 }
1584 }
1585
setLogSessionId(const char * logSessionId)1586 void AudioRecord::setLogSessionId(const char *logSessionId)
1587 {
1588 AutoMutex lock(mLock);
1589 if (logSessionId == nullptr) logSessionId = ""; // an empty string is an unset session id.
1590 if (mLogSessionId == logSessionId) return;
1591
1592 mLogSessionId = logSessionId;
1593 mediametrics::LogItem(mMetricsId)
1594 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_SETLOGSESSIONID)
1595 .set(AMEDIAMETRICS_PROP_LOGSESSIONID, logSessionId)
1596 .record();
1597 }
1598
shareAudioHistory(const std::string & sharedPackageName,int64_t sharedStartMs)1599 status_t AudioRecord::shareAudioHistory(const std::string& sharedPackageName,
1600 int64_t sharedStartMs)
1601 {
1602 AutoMutex lock(mLock);
1603 if (mAudioRecord == 0) {
1604 return NO_INIT;
1605 }
1606 status_t status = statusTFromBinderStatus(
1607 mAudioRecord->shareAudioHistory(sharedPackageName, sharedStartMs));
1608 if (status == NO_ERROR) {
1609 mSharedAudioPackageName = sharedPackageName;
1610 mSharedAudioStartMs = sharedStartMs;
1611 }
1612 return status;
1613 }
1614
1615 // =========================================================================
1616
binderDied(const wp<IBinder> & who __unused)1617 void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
1618 {
1619 sp<AudioRecord> audioRecord = mAudioRecord.promote();
1620 if (audioRecord != 0) {
1621 AutoMutex lock(audioRecord->mLock);
1622 audioRecord->mProxy->binderDied();
1623 }
1624 }
1625
1626 // =========================================================================
1627
AudioRecordThread(AudioRecord & receiver)1628 AudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver)
1629 : Thread(true /* bCanCallJava */) // binder recursion on restoreRecord_l() may call Java.
1630 , mReceiver(receiver), mPaused(true), mPausedInt(false), mPausedNs(0LL),
1631 mIgnoreNextPausedInt(false)
1632 {
1633 }
1634
~AudioRecordThread()1635 AudioRecord::AudioRecordThread::~AudioRecordThread()
1636 {
1637 }
1638
threadLoop()1639 bool AudioRecord::AudioRecordThread::threadLoop()
1640 {
1641 {
1642 AutoMutex _l(mMyLock);
1643 if (mPaused) {
1644 // TODO check return value and handle or log
1645 mMyCond.wait(mMyLock);
1646 // caller will check for exitPending()
1647 return true;
1648 }
1649 if (mIgnoreNextPausedInt) {
1650 mIgnoreNextPausedInt = false;
1651 mPausedInt = false;
1652 }
1653 if (mPausedInt) {
1654 if (mPausedNs > 0) {
1655 // TODO check return value and handle or log
1656 (void) mMyCond.waitRelative(mMyLock, mPausedNs);
1657 } else {
1658 // TODO check return value and handle or log
1659 mMyCond.wait(mMyLock);
1660 }
1661 mPausedInt = false;
1662 return true;
1663 }
1664 }
1665 if (exitPending()) {
1666 return false;
1667 }
1668 nsecs_t ns = mReceiver.processAudioBuffer();
1669 switch (ns) {
1670 case 0:
1671 return true;
1672 case NS_INACTIVE:
1673 pauseInternal();
1674 return true;
1675 case NS_NEVER:
1676 return false;
1677 case NS_WHENEVER:
1678 // Event driven: call wake() when callback notifications conditions change.
1679 ns = INT64_MAX;
1680 FALLTHROUGH_INTENDED;
1681 default:
1682 LOG_ALWAYS_FATAL_IF(ns < 0, "%s() returned %lld", __func__, (long long)ns);
1683 pauseInternal(ns);
1684 return true;
1685 }
1686 }
1687
requestExit()1688 void AudioRecord::AudioRecordThread::requestExit()
1689 {
1690 // must be in this order to avoid a race condition
1691 Thread::requestExit();
1692 resume();
1693 }
1694
pause()1695 void AudioRecord::AudioRecordThread::pause()
1696 {
1697 AutoMutex _l(mMyLock);
1698 mPaused = true;
1699 }
1700
resume()1701 void AudioRecord::AudioRecordThread::resume()
1702 {
1703 AutoMutex _l(mMyLock);
1704 mIgnoreNextPausedInt = true;
1705 if (mPaused || mPausedInt) {
1706 mPaused = false;
1707 mPausedInt = false;
1708 mMyCond.signal();
1709 }
1710 }
1711
wake()1712 void AudioRecord::AudioRecordThread::wake()
1713 {
1714 AutoMutex _l(mMyLock);
1715 if (!mPaused) {
1716 // wake() might be called while servicing a callback - ignore the next
1717 // pause time and call processAudioBuffer.
1718 mIgnoreNextPausedInt = true;
1719 if (mPausedInt && mPausedNs > 0) {
1720 // audio record is active and internally paused with timeout.
1721 mPausedInt = false;
1722 mMyCond.signal();
1723 }
1724 }
1725 }
1726
pauseInternal(nsecs_t ns)1727 void AudioRecord::AudioRecordThread::pauseInternal(nsecs_t ns)
1728 {
1729 AutoMutex _l(mMyLock);
1730 mPausedInt = true;
1731 mPausedNs = ns;
1732 }
1733
1734 // -------------------------------------------------------------------------
1735
1736 } // namespace android
1737