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_STATUS, (int32_t)status)
976 .set(AMEDIAMETRICS_PROP_SELECTEDMICDIRECTION, (int32_t)mSelectedMicDirection)
977 .set(AMEDIAMETRICS_PROP_SELECTEDMICFIELDDIRECTION, (double)mSelectedMicFieldDimension)
978 .record();
979
980 exit:
981 mStatus = status;
982 // sp<IAudioTrack> track destructor will cause releaseOutput() to be called by AudioFlinger
983 return status;
984 }
985
obtainBuffer(Buffer * audioBuffer,int32_t waitCount,size_t * nonContig)986 status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount, size_t *nonContig)
987 {
988 if (audioBuffer == NULL) {
989 if (nonContig != NULL) {
990 *nonContig = 0;
991 }
992 return BAD_VALUE;
993 }
994 if (mTransfer != TRANSFER_OBTAIN) {
995 audioBuffer->frameCount = 0;
996 audioBuffer->size = 0;
997 audioBuffer->raw = NULL;
998 if (nonContig != NULL) {
999 *nonContig = 0;
1000 }
1001 return INVALID_OPERATION;
1002 }
1003
1004 const struct timespec *requested;
1005 struct timespec timeout;
1006 if (waitCount == -1) {
1007 requested = &ClientProxy::kForever;
1008 } else if (waitCount == 0) {
1009 requested = &ClientProxy::kNonBlocking;
1010 } else if (waitCount > 0) {
1011 time_t ms = WAIT_PERIOD_MS * (time_t) waitCount;
1012 timeout.tv_sec = ms / 1000;
1013 timeout.tv_nsec = (long) (ms % 1000) * 1000000;
1014 requested = &timeout;
1015 } else {
1016 ALOGE("%s(%d): invalid waitCount %d", __func__, mPortId, waitCount);
1017 requested = NULL;
1018 }
1019 return obtainBuffer(audioBuffer, requested, NULL /*elapsed*/, nonContig);
1020 }
1021
obtainBuffer(Buffer * audioBuffer,const struct timespec * requested,struct timespec * elapsed,size_t * nonContig)1022 status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *requested,
1023 struct timespec *elapsed, size_t *nonContig)
1024 {
1025 // previous and new IAudioRecord sequence numbers are used to detect track re-creation
1026 uint32_t oldSequence = 0;
1027
1028 Proxy::Buffer buffer;
1029 status_t status = NO_ERROR;
1030
1031 static const int32_t kMaxTries = 5;
1032 int32_t tryCounter = kMaxTries;
1033
1034 do {
1035 // obtainBuffer() is called with mutex unlocked, so keep extra references to these fields to
1036 // keep them from going away if another thread re-creates the track during obtainBuffer()
1037 sp<AudioRecordClientProxy> proxy;
1038 sp<IMemory> iMem;
1039 sp<IMemory> bufferMem;
1040 {
1041 // start of lock scope
1042 AutoMutex lock(mLock);
1043
1044 uint32_t newSequence = mSequence;
1045 // did previous obtainBuffer() fail due to media server death or voluntary invalidation?
1046 if (status == DEAD_OBJECT) {
1047 // re-create track, unless someone else has already done so
1048 if (newSequence == oldSequence) {
1049 status = restoreRecord_l("obtainBuffer");
1050 if (status != NO_ERROR) {
1051 buffer.mFrameCount = 0;
1052 buffer.mRaw = NULL;
1053 buffer.mNonContig = 0;
1054 break;
1055 }
1056 }
1057 }
1058 oldSequence = newSequence;
1059
1060 // Keep the extra references
1061 proxy = mProxy;
1062 iMem = mCblkMemory;
1063 bufferMem = mBufferMemory;
1064
1065 // Non-blocking if track is stopped
1066 if (!mActive) {
1067 requested = &ClientProxy::kNonBlocking;
1068 }
1069
1070 } // end of lock scope
1071
1072 buffer.mFrameCount = audioBuffer->frameCount;
1073 // FIXME starts the requested timeout and elapsed over from scratch
1074 status = proxy->obtainBuffer(&buffer, requested, elapsed);
1075
1076 } while ((status == DEAD_OBJECT) && (tryCounter-- > 0));
1077
1078 audioBuffer->frameCount = buffer.mFrameCount;
1079 audioBuffer->size = buffer.mFrameCount * mFrameSize;
1080 audioBuffer->raw = buffer.mRaw;
1081 audioBuffer->sequence = oldSequence;
1082 if (nonContig != NULL) {
1083 *nonContig = buffer.mNonContig;
1084 }
1085 return status;
1086 }
1087
releaseBuffer(const Buffer * audioBuffer)1088 void AudioRecord::releaseBuffer(const Buffer* audioBuffer)
1089 {
1090 // FIXME add error checking on mode, by adding an internal version
1091
1092 size_t stepCount = audioBuffer->size / mFrameSize;
1093 if (stepCount == 0) {
1094 return;
1095 }
1096
1097 Proxy::Buffer buffer;
1098 buffer.mFrameCount = stepCount;
1099 buffer.mRaw = audioBuffer->raw;
1100
1101 AutoMutex lock(mLock);
1102 if (audioBuffer->sequence != mSequence) {
1103 // This Buffer came from a different IAudioRecord instance, so ignore the releaseBuffer
1104 ALOGD("%s is no-op due to IAudioRecord sequence mismatch %u != %u",
1105 __func__, audioBuffer->sequence, mSequence);
1106 return;
1107 }
1108 mInOverrun = false;
1109 mProxy->releaseBuffer(&buffer);
1110
1111 // the server does not automatically disable recorder on overrun, so no need to restart
1112 }
1113
getInputPrivate() const1114 audio_io_handle_t AudioRecord::getInputPrivate() const
1115 {
1116 AutoMutex lock(mLock);
1117 return mInput;
1118 }
1119
1120 // -------------------------------------------------------------------------
1121
read(void * buffer,size_t userSize,bool blocking)1122 ssize_t AudioRecord::read(void* buffer, size_t userSize, bool blocking)
1123 {
1124 if (mTransfer != TRANSFER_SYNC) {
1125 return INVALID_OPERATION;
1126 }
1127
1128 if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) {
1129 // Validation. user is most-likely passing an error code, and it would
1130 // make the return value ambiguous (actualSize vs error).
1131 ALOGE("%s(%d) (buffer=%p, size=%zu (%zu)",
1132 __func__, mPortId, buffer, userSize, userSize);
1133 return BAD_VALUE;
1134 }
1135
1136 ssize_t read = 0;
1137 Buffer audioBuffer;
1138
1139 while (userSize >= mFrameSize) {
1140 audioBuffer.frameCount = userSize / mFrameSize;
1141
1142 status_t err = obtainBuffer(&audioBuffer,
1143 blocking ? &ClientProxy::kForever : &ClientProxy::kNonBlocking);
1144 if (err < 0) {
1145 if (read > 0) {
1146 break;
1147 }
1148 if (err == TIMED_OUT || err == -EINTR) {
1149 err = WOULD_BLOCK;
1150 }
1151 return ssize_t(err);
1152 }
1153
1154 size_t bytesRead = audioBuffer.size;
1155 memcpy(buffer, audioBuffer.i8, bytesRead);
1156 buffer = ((char *) buffer) + bytesRead;
1157 userSize -= bytesRead;
1158 read += bytesRead;
1159
1160 releaseBuffer(&audioBuffer);
1161 }
1162 if (read > 0) {
1163 mFramesRead += read / mFrameSize;
1164 // mFramesReadTime = systemTime(SYSTEM_TIME_MONOTONIC); // not provided at this time.
1165 }
1166 return read;
1167 }
1168
1169 // -------------------------------------------------------------------------
1170
processAudioBuffer()1171 nsecs_t AudioRecord::processAudioBuffer()
1172 {
1173 mLock.lock();
1174 if (mAwaitBoost) {
1175 mAwaitBoost = false;
1176 mLock.unlock();
1177 static const int32_t kMaxTries = 5;
1178 int32_t tryCounter = kMaxTries;
1179 uint32_t pollUs = 10000;
1180 do {
1181 int policy = sched_getscheduler(0) & ~SCHED_RESET_ON_FORK;
1182 if (policy == SCHED_FIFO || policy == SCHED_RR) {
1183 break;
1184 }
1185 usleep(pollUs);
1186 pollUs <<= 1;
1187 } while (tryCounter-- > 0);
1188 if (tryCounter < 0) {
1189 ALOGE("%s(%d): did not receive expected priority boost on time", __func__, mPortId);
1190 }
1191 // Run again immediately
1192 return 0;
1193 }
1194
1195 // Can only reference mCblk while locked
1196 int32_t flags = android_atomic_and(~CBLK_OVERRUN, &mCblk->mFlags);
1197
1198 // Check for track invalidation
1199 if (flags & CBLK_INVALID) {
1200 (void) restoreRecord_l("processAudioBuffer");
1201 mLock.unlock();
1202 // Run again immediately, but with a new IAudioRecord
1203 return 0;
1204 }
1205
1206 bool active = mActive;
1207
1208 // Manage overrun callback, must be done under lock to avoid race with releaseBuffer()
1209 bool newOverrun = false;
1210 if (flags & CBLK_OVERRUN) {
1211 if (!mInOverrun) {
1212 mInOverrun = true;
1213 newOverrun = true;
1214 }
1215 }
1216
1217 // Get current position of server
1218 Modulo<uint32_t> position(mProxy->getPosition());
1219
1220 // Manage marker callback
1221 bool markerReached = false;
1222 Modulo<uint32_t> markerPosition(mMarkerPosition);
1223 // FIXME fails for wraparound, need 64 bits
1224 if (!mMarkerReached && markerPosition.value() > 0 && position >= markerPosition) {
1225 mMarkerReached = markerReached = true;
1226 }
1227
1228 // Determine the number of new position callback(s) that will be needed, while locked
1229 size_t newPosCount = 0;
1230 Modulo<uint32_t> newPosition(mNewPosition);
1231 uint32_t updatePeriod = mUpdatePeriod;
1232 // FIXME fails for wraparound, need 64 bits
1233 if (updatePeriod > 0 && position >= newPosition) {
1234 newPosCount = ((position - newPosition).value() / updatePeriod) + 1;
1235 mNewPosition += updatePeriod * newPosCount;
1236 }
1237
1238 // Cache other fields that will be needed soon
1239 uint32_t notificationFrames = mNotificationFramesAct;
1240 if (mRefreshRemaining) {
1241 mRefreshRemaining = false;
1242 mRemainingFrames = notificationFrames;
1243 mRetryOnPartialBuffer = false;
1244 }
1245 size_t misalignment = mProxy->getMisalignment();
1246 uint32_t sequence = mSequence;
1247
1248 // These fields don't need to be cached, because they are assigned only by set():
1249 // mTransfer, mCbf, mUserData, mSampleRate, mFrameSize
1250
1251 mLock.unlock();
1252
1253 // perform callbacks while unlocked
1254 if (newOverrun) {
1255 mCbf(EVENT_OVERRUN, mUserData, NULL);
1256 }
1257 if (markerReached) {
1258 mCbf(EVENT_MARKER, mUserData, &markerPosition);
1259 }
1260 while (newPosCount > 0) {
1261 size_t temp = newPosition.value(); // FIXME size_t != uint32_t
1262 mCbf(EVENT_NEW_POS, mUserData, &temp);
1263 newPosition += updatePeriod;
1264 newPosCount--;
1265 }
1266 if (mObservedSequence != sequence) {
1267 mObservedSequence = sequence;
1268 mCbf(EVENT_NEW_IAUDIORECORD, mUserData, NULL);
1269 }
1270
1271 // if inactive, then don't run me again until re-started
1272 if (!active) {
1273 return NS_INACTIVE;
1274 }
1275
1276 // Compute the estimated time until the next timed event (position, markers)
1277 uint32_t minFrames = ~0;
1278 if (!markerReached && position < markerPosition) {
1279 minFrames = (markerPosition - position).value();
1280 }
1281 if (updatePeriod > 0) {
1282 uint32_t remaining = (newPosition - position).value();
1283 if (remaining < minFrames) {
1284 minFrames = remaining;
1285 }
1286 }
1287
1288 // If > 0, poll periodically to recover from a stuck server. A good value is 2.
1289 static const uint32_t kPoll = 0;
1290 if (kPoll > 0 && mTransfer == TRANSFER_CALLBACK && kPoll * notificationFrames < minFrames) {
1291 minFrames = kPoll * notificationFrames;
1292 }
1293
1294 // Convert frame units to time units
1295 nsecs_t ns = NS_WHENEVER;
1296 if (minFrames != (uint32_t) ~0) {
1297 // This "fudge factor" avoids soaking CPU, and compensates for late progress by server
1298 static const nsecs_t kFudgeNs = 10000000LL; // 10 ms
1299 ns = ((minFrames * 1000000000LL) / mSampleRate) + kFudgeNs;
1300 }
1301
1302 // If not supplying data by EVENT_MORE_DATA, then we're done
1303 if (mTransfer != TRANSFER_CALLBACK) {
1304 return ns;
1305 }
1306
1307 struct timespec timeout;
1308 const struct timespec *requested = &ClientProxy::kForever;
1309 if (ns != NS_WHENEVER) {
1310 timeout.tv_sec = ns / 1000000000LL;
1311 timeout.tv_nsec = ns % 1000000000LL;
1312 ALOGV("%s(%d): timeout %ld.%03d",
1313 __func__, mPortId, timeout.tv_sec, (int) timeout.tv_nsec / 1000000);
1314 requested = &timeout;
1315 }
1316
1317 size_t readFrames = 0;
1318 while (mRemainingFrames > 0) {
1319
1320 Buffer audioBuffer;
1321 audioBuffer.frameCount = mRemainingFrames;
1322 size_t nonContig;
1323 status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig);
1324 LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0),
1325 "%s(%d): obtainBuffer() err=%d frameCount=%zu",
1326 __func__, mPortId, err, audioBuffer.frameCount);
1327 requested = &ClientProxy::kNonBlocking;
1328 size_t avail = audioBuffer.frameCount + nonContig;
1329 ALOGV("%s(%d): obtainBuffer(%u) returned %zu = %zu + %zu err %d",
1330 __func__, mPortId, mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err);
1331 if (err != NO_ERROR) {
1332 if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR) {
1333 break;
1334 }
1335 ALOGE("%s(%d): Error %d obtaining an audio buffer, giving up.",
1336 __func__, mPortId, err);
1337 return NS_NEVER;
1338 }
1339
1340 if (mRetryOnPartialBuffer) {
1341 mRetryOnPartialBuffer = false;
1342 if (avail < mRemainingFrames) {
1343 int64_t myns = ((mRemainingFrames - avail) *
1344 1100000000LL) / mSampleRate;
1345 if (ns < 0 || myns < ns) {
1346 ns = myns;
1347 }
1348 return ns;
1349 }
1350 }
1351
1352 size_t reqSize = audioBuffer.size;
1353 mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
1354 size_t readSize = audioBuffer.size;
1355
1356 // Validate on returned size
1357 if (ssize_t(readSize) < 0 || readSize > reqSize) {
1358 ALOGE("%s(%d): EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes",
1359 __func__, mPortId, reqSize, ssize_t(readSize));
1360 return NS_NEVER;
1361 }
1362
1363 if (readSize == 0) {
1364 // The callback is done consuming buffers
1365 // Keep this thread going to handle timed events and
1366 // still try to provide more data in intervals of WAIT_PERIOD_MS
1367 // but don't just loop and block the CPU, so wait
1368 return WAIT_PERIOD_MS * 1000000LL;
1369 }
1370
1371 size_t releasedFrames = readSize / mFrameSize;
1372 audioBuffer.frameCount = releasedFrames;
1373 mRemainingFrames -= releasedFrames;
1374 if (misalignment >= releasedFrames) {
1375 misalignment -= releasedFrames;
1376 } else {
1377 misalignment = 0;
1378 }
1379
1380 releaseBuffer(&audioBuffer);
1381 readFrames += releasedFrames;
1382
1383 // FIXME here is where we would repeat EVENT_MORE_DATA again on same advanced buffer
1384 // if callback doesn't like to accept the full chunk
1385 if (readSize < reqSize) {
1386 continue;
1387 }
1388
1389 // There could be enough non-contiguous frames available to satisfy the remaining request
1390 if (mRemainingFrames <= nonContig) {
1391 continue;
1392 }
1393
1394 #if 0
1395 // This heuristic tries to collapse a series of EVENT_MORE_DATA that would total to a
1396 // sum <= notificationFrames. It replaces that series by at most two EVENT_MORE_DATA
1397 // that total to a sum == notificationFrames.
1398 if (0 < misalignment && misalignment <= mRemainingFrames) {
1399 mRemainingFrames = misalignment;
1400 return (mRemainingFrames * 1100000000LL) / mSampleRate;
1401 }
1402 #endif
1403
1404 }
1405 if (readFrames > 0) {
1406 AutoMutex lock(mLock);
1407 mFramesRead += readFrames;
1408 // mFramesReadTime = systemTime(SYSTEM_TIME_MONOTONIC); // not provided at this time.
1409 }
1410 mRemainingFrames = notificationFrames;
1411 mRetryOnPartialBuffer = true;
1412
1413 // A lot has transpired since ns was calculated, so run again immediately and re-calculate
1414 return 0;
1415 }
1416
restoreRecord_l(const char * from)1417 status_t AudioRecord::restoreRecord_l(const char *from)
1418 {
1419 status_t result = NO_ERROR; // logged: make sure to set this before returning.
1420 const int64_t beginNs = systemTime();
1421 mediametrics::Defer defer([&] {
1422 mediametrics::LogItem(mMetricsId)
1423 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_RESTORE)
1424 .set(AMEDIAMETRICS_PROP_EXECUTIONTIMENS, (int64_t)(systemTime() - beginNs))
1425 .set(AMEDIAMETRICS_PROP_STATE, stateToString(mActive))
1426 .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)result)
1427 .set(AMEDIAMETRICS_PROP_WHERE, from)
1428 .record(); });
1429
1430 ALOGW("%s(%d): dead IAudioRecord, creating a new one from %s()", __func__, mPortId, from);
1431 ++mSequence;
1432
1433 const int INITIAL_RETRIES = 3;
1434 int retries = INITIAL_RETRIES;
1435 retry:
1436 if (retries < INITIAL_RETRIES) {
1437 // refresh the audio configuration cache in this process to make sure we get new
1438 // input parameters and new IAudioRecord in createRecord_l()
1439 AudioSystem::clearAudioConfigCache();
1440 }
1441 mFlags = mOrigFlags;
1442
1443 // if the new IAudioRecord is created, createRecord_l() will modify the
1444 // following member variables: mAudioRecord, mCblkMemory, mCblk, mBufferMemory.
1445 // It will also delete the strong references on previous IAudioRecord and IMemory
1446 Modulo<uint32_t> position(mProxy->getPosition());
1447 mNewPosition = position + mUpdatePeriod;
1448 result = createRecord_l(position);
1449
1450 if (result == NO_ERROR) {
1451 if (mActive) {
1452 // callback thread or sync event hasn't changed
1453 // FIXME this fails if we have a new AudioFlinger instance
1454 result = statusTFromBinderStatus(mAudioRecord->start(
1455 AudioSystem::SYNC_EVENT_SAME, AUDIO_SESSION_NONE));
1456 }
1457 mFramesReadServerOffset = mFramesRead; // server resets to zero so we need an offset.
1458 }
1459
1460 if (result != NO_ERROR) {
1461 ALOGW("%s(%d): failed status %d, retries %d", __func__, mPortId, result, retries);
1462 if (--retries > 0) {
1463 // leave time for an eventual race condition to clear before retrying
1464 usleep(500000);
1465 goto retry;
1466 }
1467 // if no retries left, set invalid bit to force restoring at next occasion
1468 // and avoid inconsistent active state on client and server sides
1469 if (mCblk != nullptr) {
1470 android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
1471 }
1472 }
1473
1474 return result;
1475 }
1476
addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback> & callback)1477 status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback)
1478 {
1479 if (callback == 0) {
1480 ALOGW("%s(%d): adding NULL callback!", __func__, mPortId);
1481 return BAD_VALUE;
1482 }
1483 AutoMutex lock(mLock);
1484 if (mDeviceCallback.unsafe_get() == callback.get()) {
1485 ALOGW("%s(%d): adding same callback!", __func__, mPortId);
1486 return INVALID_OPERATION;
1487 }
1488 status_t status = NO_ERROR;
1489 if (mInput != AUDIO_IO_HANDLE_NONE) {
1490 if (mDeviceCallback != 0) {
1491 ALOGW("%s(%d): callback already present!", __func__, mPortId);
1492 AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId);
1493 }
1494 status = AudioSystem::addAudioDeviceCallback(this, mInput, mPortId);
1495 }
1496 mDeviceCallback = callback;
1497 return status;
1498 }
1499
removeAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback> & callback)1500 status_t AudioRecord::removeAudioDeviceCallback(
1501 const sp<AudioSystem::AudioDeviceCallback>& callback)
1502 {
1503 if (callback == 0) {
1504 ALOGW("%s(%d): removing NULL callback!", __func__, mPortId);
1505 return BAD_VALUE;
1506 }
1507 AutoMutex lock(mLock);
1508 if (mDeviceCallback.unsafe_get() != callback.get()) {
1509 ALOGW("%s(%d): removing different callback!", __func__, mPortId);
1510 return INVALID_OPERATION;
1511 }
1512 mDeviceCallback.clear();
1513 if (mInput != AUDIO_IO_HANDLE_NONE) {
1514 AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId);
1515 }
1516 return NO_ERROR;
1517 }
1518
onAudioDeviceUpdate(audio_io_handle_t audioIo,audio_port_handle_t deviceId)1519 void AudioRecord::onAudioDeviceUpdate(audio_io_handle_t audioIo,
1520 audio_port_handle_t deviceId)
1521 {
1522 sp<AudioSystem::AudioDeviceCallback> callback;
1523 {
1524 AutoMutex lock(mLock);
1525 if (audioIo != mInput) {
1526 return;
1527 }
1528 callback = mDeviceCallback.promote();
1529 // only update device if the record is active as route changes due to other use cases are
1530 // irrelevant for this client
1531 if (mActive) {
1532 mRoutedDeviceId = deviceId;
1533 }
1534 }
1535 if (callback.get() != nullptr) {
1536 callback->onAudioDeviceUpdate(mInput, mRoutedDeviceId);
1537 }
1538 }
1539
1540 // -------------------------------------------------------------------------
1541
getActiveMicrophones(std::vector<media::MicrophoneInfo> * activeMicrophones)1542 status_t AudioRecord::getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones)
1543 {
1544 AutoMutex lock(mLock);
1545 std::vector<media::MicrophoneInfoData> mics;
1546 status_t status = statusTFromBinderStatus(mAudioRecord->getActiveMicrophones(&mics));
1547 activeMicrophones->resize(mics.size());
1548 for (size_t i = 0; status == OK && i < mics.size(); ++i) {
1549 status = activeMicrophones->at(i).readFromParcelable(mics[i]);
1550 }
1551 return status;
1552 }
1553
setPreferredMicrophoneDirection(audio_microphone_direction_t direction)1554 status_t AudioRecord::setPreferredMicrophoneDirection(audio_microphone_direction_t direction)
1555 {
1556 AutoMutex lock(mLock);
1557 if (mSelectedMicDirection == direction) {
1558 // NOP
1559 return OK;
1560 }
1561
1562 mSelectedMicDirection = direction;
1563 if (mAudioRecord == 0) {
1564 // the internal AudioRecord hasn't be created yet, so just stash the attribute.
1565 return OK;
1566 } else {
1567 return statusTFromBinderStatus(mAudioRecord->setPreferredMicrophoneDirection(direction));
1568 }
1569 }
1570
setPreferredMicrophoneFieldDimension(float zoom)1571 status_t AudioRecord::setPreferredMicrophoneFieldDimension(float zoom) {
1572 AutoMutex lock(mLock);
1573 if (mSelectedMicFieldDimension == zoom) {
1574 // NOP
1575 return OK;
1576 }
1577
1578 mSelectedMicFieldDimension = zoom;
1579 if (mAudioRecord == 0) {
1580 // the internal AudioRecord hasn't be created yet, so just stash the attribute.
1581 return OK;
1582 } else {
1583 return statusTFromBinderStatus(mAudioRecord->setPreferredMicrophoneFieldDimension(zoom));
1584 }
1585 }
1586
setLogSessionId(const char * logSessionId)1587 void AudioRecord::setLogSessionId(const char *logSessionId)
1588 {
1589 AutoMutex lock(mLock);
1590 if (logSessionId == nullptr) logSessionId = ""; // an empty string is an unset session id.
1591 if (mLogSessionId == logSessionId) return;
1592
1593 mLogSessionId = logSessionId;
1594 mediametrics::LogItem(mMetricsId)
1595 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_SETLOGSESSIONID)
1596 .set(AMEDIAMETRICS_PROP_LOGSESSIONID, logSessionId)
1597 .record();
1598 }
1599
shareAudioHistory(const std::string & sharedPackageName,int64_t sharedStartMs)1600 status_t AudioRecord::shareAudioHistory(const std::string& sharedPackageName,
1601 int64_t sharedStartMs)
1602 {
1603 AutoMutex lock(mLock);
1604 if (mAudioRecord == 0) {
1605 return NO_INIT;
1606 }
1607 status_t status = statusTFromBinderStatus(
1608 mAudioRecord->shareAudioHistory(sharedPackageName, sharedStartMs));
1609 if (status == NO_ERROR) {
1610 mSharedAudioPackageName = sharedPackageName;
1611 mSharedAudioStartMs = sharedStartMs;
1612 }
1613 return status;
1614 }
1615
1616 // =========================================================================
1617
binderDied(const wp<IBinder> & who __unused)1618 void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
1619 {
1620 sp<AudioRecord> audioRecord = mAudioRecord.promote();
1621 if (audioRecord != 0) {
1622 AutoMutex lock(audioRecord->mLock);
1623 audioRecord->mProxy->binderDied();
1624 }
1625 }
1626
1627 // =========================================================================
1628
AudioRecordThread(AudioRecord & receiver)1629 AudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver)
1630 : Thread(true /* bCanCallJava */) // binder recursion on restoreRecord_l() may call Java.
1631 , mReceiver(receiver), mPaused(true), mPausedInt(false), mPausedNs(0LL),
1632 mIgnoreNextPausedInt(false)
1633 {
1634 }
1635
~AudioRecordThread()1636 AudioRecord::AudioRecordThread::~AudioRecordThread()
1637 {
1638 }
1639
threadLoop()1640 bool AudioRecord::AudioRecordThread::threadLoop()
1641 {
1642 {
1643 AutoMutex _l(mMyLock);
1644 if (mPaused) {
1645 // TODO check return value and handle or log
1646 mMyCond.wait(mMyLock);
1647 // caller will check for exitPending()
1648 return true;
1649 }
1650 if (mIgnoreNextPausedInt) {
1651 mIgnoreNextPausedInt = false;
1652 mPausedInt = false;
1653 }
1654 if (mPausedInt) {
1655 if (mPausedNs > 0) {
1656 // TODO check return value and handle or log
1657 (void) mMyCond.waitRelative(mMyLock, mPausedNs);
1658 } else {
1659 // TODO check return value and handle or log
1660 mMyCond.wait(mMyLock);
1661 }
1662 mPausedInt = false;
1663 return true;
1664 }
1665 }
1666 if (exitPending()) {
1667 return false;
1668 }
1669 nsecs_t ns = mReceiver.processAudioBuffer();
1670 switch (ns) {
1671 case 0:
1672 return true;
1673 case NS_INACTIVE:
1674 pauseInternal();
1675 return true;
1676 case NS_NEVER:
1677 return false;
1678 case NS_WHENEVER:
1679 // Event driven: call wake() when callback notifications conditions change.
1680 ns = INT64_MAX;
1681 FALLTHROUGH_INTENDED;
1682 default:
1683 LOG_ALWAYS_FATAL_IF(ns < 0, "%s() returned %lld", __func__, (long long)ns);
1684 pauseInternal(ns);
1685 return true;
1686 }
1687 }
1688
requestExit()1689 void AudioRecord::AudioRecordThread::requestExit()
1690 {
1691 // must be in this order to avoid a race condition
1692 Thread::requestExit();
1693 resume();
1694 }
1695
pause()1696 void AudioRecord::AudioRecordThread::pause()
1697 {
1698 AutoMutex _l(mMyLock);
1699 mPaused = true;
1700 }
1701
resume()1702 void AudioRecord::AudioRecordThread::resume()
1703 {
1704 AutoMutex _l(mMyLock);
1705 mIgnoreNextPausedInt = true;
1706 if (mPaused || mPausedInt) {
1707 mPaused = false;
1708 mPausedInt = false;
1709 mMyCond.signal();
1710 }
1711 }
1712
wake()1713 void AudioRecord::AudioRecordThread::wake()
1714 {
1715 AutoMutex _l(mMyLock);
1716 if (!mPaused) {
1717 // wake() might be called while servicing a callback - ignore the next
1718 // pause time and call processAudioBuffer.
1719 mIgnoreNextPausedInt = true;
1720 if (mPausedInt && mPausedNs > 0) {
1721 // audio record is active and internally paused with timeout.
1722 mPausedInt = false;
1723 mMyCond.signal();
1724 }
1725 }
1726 }
1727
pauseInternal(nsecs_t ns)1728 void AudioRecord::AudioRecordThread::pauseInternal(nsecs_t ns)
1729 {
1730 AutoMutex _l(mMyLock);
1731 mPausedInt = true;
1732 mPausedNs = ns;
1733 }
1734
1735 // -------------------------------------------------------------------------
1736
1737 } // namespace android
1738