AudioRecord.cpp revision 83a0382dc17364567667a4e6135db43f5bd92efc
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 <sys/resource.h> 22#include <sys/types.h> 23 24#include <binder/IPCThreadState.h> 25#include <cutils/atomic.h> 26#include <cutils/compiler.h> 27#include <media/AudioRecord.h> 28#include <media/AudioSystem.h> 29#include <system/audio.h> 30#include <utils/Log.h> 31 32#include <private/media/AudioTrackShared.h> 33 34namespace android { 35// --------------------------------------------------------------------------- 36 37// static 38status_t AudioRecord::getMinFrameCount( 39 int* frameCount, 40 uint32_t sampleRate, 41 audio_format_t format, 42 audio_channel_mask_t channelMask) 43{ 44 if (frameCount == NULL) return BAD_VALUE; 45 46 // default to 0 in case of error 47 *frameCount = 0; 48 49 size_t size = 0; 50 if (AudioSystem::getInputBufferSize(sampleRate, format, channelMask, &size) 51 != NO_ERROR) { 52 ALOGE("AudioSystem could not query the input buffer size."); 53 return NO_INIT; 54 } 55 56 if (size == 0) { 57 ALOGE("Unsupported configuration: sampleRate %d, format %d, channelMask %#x", 58 sampleRate, format, channelMask); 59 return BAD_VALUE; 60 } 61 62 // We double the size of input buffer for ping pong use of record buffer. 63 size <<= 1; 64 65 if (audio_is_linear_pcm(format)) { 66 int channelCount = popcount(channelMask); 67 size /= channelCount * audio_bytes_per_sample(format); 68 } 69 70 *frameCount = size; 71 return NO_ERROR; 72} 73 74// --------------------------------------------------------------------------- 75 76AudioRecord::AudioRecord() 77 : mStatus(NO_INIT), mSessionId(0), 78 mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) 79{ 80} 81 82AudioRecord::AudioRecord( 83 audio_source_t inputSource, 84 uint32_t sampleRate, 85 audio_format_t format, 86 audio_channel_mask_t channelMask, 87 int frameCount, 88 callback_t cbf, 89 void* user, 90 int notificationFrames, 91 int sessionId) 92 : mStatus(NO_INIT), mSessionId(0), 93 mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) 94{ 95 mStatus = set(inputSource, sampleRate, format, channelMask, 96 frameCount, cbf, user, notificationFrames, sessionId); 97} 98 99AudioRecord::~AudioRecord() 100{ 101 if (mStatus == NO_ERROR) { 102 // Make sure that callback function exits in the case where 103 // it is looping on buffer empty condition in obtainBuffer(). 104 // Otherwise the callback thread will never exit. 105 stop(); 106 if (mAudioRecordThread != 0) { 107 mAudioRecordThread->requestExit(); // see comment in AudioRecord.h 108 mAudioRecordThread->requestExitAndWait(); 109 mAudioRecordThread.clear(); 110 } 111 mAudioRecord.clear(); 112 IPCThreadState::self()->flushCommands(); 113 AudioSystem::releaseAudioSessionId(mSessionId); 114 } 115} 116 117status_t AudioRecord::set( 118 audio_source_t inputSource, 119 uint32_t sampleRate, 120 audio_format_t format, 121 audio_channel_mask_t channelMask, 122 int frameCount, 123 callback_t cbf, 124 void* user, 125 int notificationFrames, 126 bool threadCanCallJava, 127 int sessionId) 128{ 129 130 ALOGV("set(): sampleRate %d, channelMask %#x, frameCount %d",sampleRate, channelMask, 131 frameCount); 132 133 AutoMutex lock(mLock); 134 135 if (mAudioRecord != 0) { 136 return INVALID_OPERATION; 137 } 138 139 if (inputSource == AUDIO_SOURCE_DEFAULT) { 140 inputSource = AUDIO_SOURCE_MIC; 141 } 142 143 if (sampleRate == 0) { 144 sampleRate = DEFAULT_SAMPLE_RATE; 145 } 146 // these below should probably come from the audioFlinger too... 147 if (format == AUDIO_FORMAT_DEFAULT) { 148 format = AUDIO_FORMAT_PCM_16_BIT; 149 } 150 // validate parameters 151 if (!audio_is_valid_format(format)) { 152 ALOGE("Invalid format"); 153 return BAD_VALUE; 154 } 155 156 if (!audio_is_input_channel(channelMask)) { 157 return BAD_VALUE; 158 } 159 160 int channelCount = popcount(channelMask); 161 162 if (sessionId == 0 ) { 163 mSessionId = AudioSystem::newAudioSessionId(); 164 } else { 165 mSessionId = sessionId; 166 } 167 ALOGV("set(): mSessionId %d", mSessionId); 168 169 audio_io_handle_t input = AudioSystem::getInput(inputSource, 170 sampleRate, 171 format, 172 channelMask, 173 mSessionId); 174 if (input == 0) { 175 ALOGE("Could not get audio input for record source %d", inputSource); 176 return BAD_VALUE; 177 } 178 179 // validate framecount 180 int minFrameCount = 0; 181 status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelMask); 182 if (status != NO_ERROR) { 183 return status; 184 } 185 ALOGV("AudioRecord::set() minFrameCount = %d", minFrameCount); 186 187 if (frameCount == 0) { 188 frameCount = minFrameCount; 189 } else if (frameCount < minFrameCount) { 190 return BAD_VALUE; 191 } 192 193 if (notificationFrames == 0) { 194 notificationFrames = frameCount/2; 195 } 196 197 // create the IAudioRecord 198 status = openRecord_l(sampleRate, format, channelMask, 199 frameCount, input); 200 if (status != NO_ERROR) { 201 return status; 202 } 203 204 if (cbf != NULL) { 205 mAudioRecordThread = new AudioRecordThread(*this, threadCanCallJava); 206 mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO); 207 } 208 209 mStatus = NO_ERROR; 210 211 mFormat = format; 212 // Update buffer size in case it has been limited by AudioFlinger during track creation 213 mFrameCount = mCblk->frameCount; 214 mChannelCount = (uint8_t)channelCount; 215 mChannelMask = channelMask; 216 217 if (audio_is_linear_pcm(mFormat)) { 218 mFrameSize = channelCount * audio_bytes_per_sample(format); 219 } else { 220 mFrameSize = sizeof(uint8_t); 221 } 222 223 mActive = false; 224 mCbf = cbf; 225 mNotificationFrames = notificationFrames; 226 mRemainingFrames = notificationFrames; 227 mUserData = user; 228 // TODO: add audio hardware input latency here 229 mLatency = (1000*mFrameCount) / sampleRate; 230 mMarkerPosition = 0; 231 mMarkerReached = false; 232 mNewPosition = 0; 233 mUpdatePeriod = 0; 234 mInputSource = inputSource; 235 mInput = input; 236 AudioSystem::acquireAudioSessionId(mSessionId); 237 238 return NO_ERROR; 239} 240 241status_t AudioRecord::initCheck() const 242{ 243 return mStatus; 244} 245 246// ------------------------------------------------------------------------- 247 248uint32_t AudioRecord::latency() const 249{ 250 return mLatency; 251} 252 253audio_format_t AudioRecord::format() const 254{ 255 return mFormat; 256} 257 258int AudioRecord::channelCount() const 259{ 260 return mChannelCount; 261} 262 263uint32_t AudioRecord::frameCount() const 264{ 265 return mFrameCount; 266} 267 268audio_source_t AudioRecord::inputSource() const 269{ 270 return mInputSource; 271} 272 273// ------------------------------------------------------------------------- 274 275status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession) 276{ 277 status_t ret = NO_ERROR; 278 sp<AudioRecordThread> t = mAudioRecordThread; 279 280 ALOGV("start, sync event %d trigger session %d", event, triggerSession); 281 282 AutoMutex lock(mLock); 283 // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed 284 // while we are accessing the cblk 285 sp<IAudioRecord> audioRecord = mAudioRecord; 286 sp<IMemory> iMem = mCblkMemory; 287 audio_track_cblk_t* cblk = mCblk; 288 289 if (!mActive) { 290 mActive = true; 291 292 cblk->lock.lock(); 293 if (!(cblk->flags & CBLK_INVALID)) { 294 cblk->lock.unlock(); 295 ALOGV("mAudioRecord->start()"); 296 ret = mAudioRecord->start(event, triggerSession); 297 cblk->lock.lock(); 298 if (ret == DEAD_OBJECT) { 299 android_atomic_or(CBLK_INVALID, &cblk->flags); 300 } 301 } 302 if (cblk->flags & CBLK_INVALID) { 303 ret = restoreRecord_l(cblk); 304 } 305 cblk->lock.unlock(); 306 if (ret == NO_ERROR) { 307 mNewPosition = cblk->user + mUpdatePeriod; 308 cblk->bufferTimeoutMs = (event == AudioSystem::SYNC_EVENT_NONE) ? MAX_RUN_TIMEOUT_MS : 309 AudioSystem::kSyncRecordStartTimeOutMs; 310 cblk->waitTimeMs = 0; 311 if (t != 0) { 312 t->resume(); 313 } else { 314 mPreviousPriority = getpriority(PRIO_PROCESS, 0); 315 get_sched_policy(0, &mPreviousSchedulingGroup); 316 androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 317 } 318 } else { 319 mActive = false; 320 } 321 } 322 323 return ret; 324} 325 326void AudioRecord::stop() 327{ 328 sp<AudioRecordThread> t = mAudioRecordThread; 329 330 ALOGV("stop"); 331 332 AutoMutex lock(mLock); 333 if (mActive) { 334 mActive = false; 335 mCblk->cv.signal(); 336 mAudioRecord->stop(); 337 // the record head position will reset to 0, so if a marker is set, we need 338 // to activate it again 339 mMarkerReached = false; 340 if (t != 0) { 341 t->pause(); 342 } else { 343 setpriority(PRIO_PROCESS, 0, mPreviousPriority); 344 set_sched_policy(0, mPreviousSchedulingGroup); 345 } 346 } 347} 348 349bool AudioRecord::stopped() const 350{ 351 AutoMutex lock(mLock); 352 return !mActive; 353} 354 355uint32_t AudioRecord::getSampleRate() const 356{ 357 return mCblk->sampleRate; 358} 359 360status_t AudioRecord::setMarkerPosition(uint32_t marker) 361{ 362 if (mCbf == NULL) return INVALID_OPERATION; 363 364 AutoMutex lock(mLock); 365 mMarkerPosition = marker; 366 mMarkerReached = false; 367 368 return NO_ERROR; 369} 370 371status_t AudioRecord::getMarkerPosition(uint32_t *marker) const 372{ 373 if (marker == NULL) return BAD_VALUE; 374 375 AutoMutex lock(mLock); 376 *marker = mMarkerPosition; 377 378 return NO_ERROR; 379} 380 381status_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod) 382{ 383 if (mCbf == NULL) return INVALID_OPERATION; 384 385 uint32_t curPosition; 386 getPosition(&curPosition); 387 388 AutoMutex lock(mLock); 389 mNewPosition = curPosition + updatePeriod; 390 mUpdatePeriod = updatePeriod; 391 392 return NO_ERROR; 393} 394 395status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const 396{ 397 if (updatePeriod == NULL) return BAD_VALUE; 398 399 AutoMutex lock(mLock); 400 *updatePeriod = mUpdatePeriod; 401 402 return NO_ERROR; 403} 404 405status_t AudioRecord::getPosition(uint32_t *position) const 406{ 407 if (position == NULL) return BAD_VALUE; 408 409 AutoMutex lock(mLock); 410 *position = mCblk->user; 411 412 return NO_ERROR; 413} 414 415unsigned int AudioRecord::getInputFramesLost() const 416{ 417 // no need to check mActive, because if inactive this will return 0, which is what we want 418 return AudioSystem::getInputFramesLost(mInput); 419} 420 421// ------------------------------------------------------------------------- 422 423// must be called with mLock held 424status_t AudioRecord::openRecord_l( 425 uint32_t sampleRate, 426 audio_format_t format, 427 audio_channel_mask_t channelMask, 428 int frameCount, 429 audio_io_handle_t input) 430{ 431 status_t status; 432 const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); 433 if (audioFlinger == 0) { 434 return NO_INIT; 435 } 436 437 pid_t tid = -1; 438 // FIXME see similar logic at AudioTrack 439 440 int originalSessionId = mSessionId; 441 sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input, 442 sampleRate, format, 443 channelMask, 444 frameCount, 445 IAudioFlinger::TRACK_DEFAULT, 446 tid, 447 &mSessionId, 448 &status); 449 ALOGE_IF(originalSessionId != 0 && mSessionId != originalSessionId, 450 "session ID changed from %d to %d", originalSessionId, mSessionId); 451 452 if (record == 0) { 453 ALOGE("AudioFlinger could not create record track, status: %d", status); 454 return status; 455 } 456 sp<IMemory> cblk = record->getCblk(); 457 if (cblk == 0) { 458 ALOGE("Could not get control block"); 459 return NO_INIT; 460 } 461 mAudioRecord.clear(); 462 mAudioRecord = record; 463 mCblkMemory.clear(); 464 mCblkMemory = cblk; 465 mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); 466 mBuffers = (char*)mCblk + sizeof(audio_track_cblk_t); 467 mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; 468 mCblk->waitTimeMs = 0; 469 return NO_ERROR; 470} 471 472status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) 473{ 474 AutoMutex lock(mLock); 475 bool active; 476 status_t result = NO_ERROR; 477 audio_track_cblk_t* cblk = mCblk; 478 uint32_t framesReq = audioBuffer->frameCount; 479 uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS; 480 481 audioBuffer->frameCount = 0; 482 audioBuffer->size = 0; 483 484 uint32_t framesReady = cblk->framesReadyIn(); 485 486 if (framesReady == 0) { 487 cblk->lock.lock(); 488 goto start_loop_here; 489 while (framesReady == 0) { 490 active = mActive; 491 if (CC_UNLIKELY(!active)) { 492 cblk->lock.unlock(); 493 return NO_MORE_BUFFERS; 494 } 495 if (CC_UNLIKELY(!waitCount)) { 496 cblk->lock.unlock(); 497 return WOULD_BLOCK; 498 } 499 if (!(cblk->flags & CBLK_INVALID)) { 500 mLock.unlock(); 501 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); 502 cblk->lock.unlock(); 503 mLock.lock(); 504 if (!mActive) { 505 return status_t(STOPPED); 506 } 507 cblk->lock.lock(); 508 } 509 if (cblk->flags & CBLK_INVALID) { 510 goto create_new_record; 511 } 512 if (CC_UNLIKELY(result != NO_ERROR)) { 513 cblk->waitTimeMs += waitTimeMs; 514 if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { 515 ALOGW( "obtainBuffer timed out (is the CPU pegged?) " 516 "user=%08x, server=%08x", cblk->user, cblk->server); 517 cblk->lock.unlock(); 518 // callback thread or sync event hasn't changed 519 result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0); 520 cblk->lock.lock(); 521 if (result == DEAD_OBJECT) { 522 android_atomic_or(CBLK_INVALID, &cblk->flags); 523create_new_record: 524 result = AudioRecord::restoreRecord_l(cblk); 525 } 526 if (result != NO_ERROR) { 527 ALOGW("obtainBuffer create Track error %d", result); 528 cblk->lock.unlock(); 529 return result; 530 } 531 cblk->waitTimeMs = 0; 532 } 533 if (--waitCount == 0) { 534 cblk->lock.unlock(); 535 return TIMED_OUT; 536 } 537 } 538 // read the server count again 539 start_loop_here: 540 framesReady = cblk->framesReadyIn(); 541 } 542 cblk->lock.unlock(); 543 } 544 545 cblk->waitTimeMs = 0; 546 // reset time out to running value after obtaining a buffer 547 cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; 548 549 if (framesReq > framesReady) { 550 framesReq = framesReady; 551 } 552 553 uint32_t u = cblk->user; 554 uint32_t bufferEnd = cblk->userBase + cblk->frameCount; 555 556 if (framesReq > bufferEnd - u) { 557 framesReq = bufferEnd - u; 558 } 559 560 audioBuffer->frameCount = framesReq; 561 audioBuffer->size = framesReq * mFrameSize; 562 audioBuffer->raw = cblk->buffer(mBuffers, mFrameSize, u); 563 active = mActive; 564 return active ? status_t(NO_ERROR) : status_t(STOPPED); 565} 566 567void AudioRecord::releaseBuffer(Buffer* audioBuffer) 568{ 569 AutoMutex lock(mLock); 570 mCblk->stepUserIn(audioBuffer->frameCount); 571} 572 573audio_io_handle_t AudioRecord::getInput() const 574{ 575 AutoMutex lock(mLock); 576 return mInput; 577} 578 579// must be called with mLock held 580audio_io_handle_t AudioRecord::getInput_l() 581{ 582 mInput = AudioSystem::getInput(mInputSource, 583 mCblk->sampleRate, 584 mFormat, 585 mChannelMask, 586 mSessionId); 587 return mInput; 588} 589 590int AudioRecord::getSessionId() const 591{ 592 // no lock needed because session ID doesn't change after first set() 593 return mSessionId; 594} 595 596// ------------------------------------------------------------------------- 597 598ssize_t AudioRecord::read(void* buffer, size_t userSize) 599{ 600 ssize_t read = 0; 601 Buffer audioBuffer; 602 int8_t *dst = static_cast<int8_t*>(buffer); 603 604 if (ssize_t(userSize) < 0) { 605 // sanity-check. user is most-likely passing an error code. 606 ALOGE("AudioRecord::read(buffer=%p, size=%u (%d)", 607 buffer, userSize, userSize); 608 return BAD_VALUE; 609 } 610 611 mLock.lock(); 612 // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed 613 // while we are accessing the cblk 614 sp<IAudioRecord> audioRecord = mAudioRecord; 615 sp<IMemory> iMem = mCblkMemory; 616 mLock.unlock(); 617 618 do { 619 620 audioBuffer.frameCount = userSize/frameSize(); 621 622 // By using a wait count corresponding to twice the timeout period in 623 // obtainBuffer() we give a chance to recover once for a read timeout 624 // (if media_server crashed for instance) before returning a length of 625 // 0 bytes read to the client 626 status_t err = obtainBuffer(&audioBuffer, ((2 * MAX_RUN_TIMEOUT_MS) / WAIT_PERIOD_MS)); 627 if (err < 0) { 628 // out of buffers, return #bytes written 629 if (err == status_t(NO_MORE_BUFFERS)) 630 break; 631 if (err == status_t(TIMED_OUT)) 632 err = 0; 633 return ssize_t(err); 634 } 635 636 size_t bytesRead = audioBuffer.size; 637 memcpy(dst, audioBuffer.i8, bytesRead); 638 639 dst += bytesRead; 640 userSize -= bytesRead; 641 read += bytesRead; 642 643 releaseBuffer(&audioBuffer); 644 } while (userSize); 645 646 return read; 647} 648 649// ------------------------------------------------------------------------- 650 651bool AudioRecord::processAudioBuffer(const sp<AudioRecordThread>& thread) 652{ 653 Buffer audioBuffer; 654 uint32_t frames = mRemainingFrames; 655 size_t readSize; 656 657 mLock.lock(); 658 // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed 659 // while we are accessing the cblk 660 sp<IAudioRecord> audioRecord = mAudioRecord; 661 sp<IMemory> iMem = mCblkMemory; 662 audio_track_cblk_t* cblk = mCblk; 663 bool active = mActive; 664 uint32_t markerPosition = mMarkerPosition; 665 uint32_t newPosition = mNewPosition; 666 uint32_t user = cblk->user; 667 // determine whether a marker callback will be needed, while locked 668 bool needMarker = !mMarkerReached && (mMarkerPosition > 0) && (user >= mMarkerPosition); 669 if (needMarker) { 670 mMarkerReached = true; 671 } 672 // determine the number of new position callback(s) that will be needed, while locked 673 uint32_t updatePeriod = mUpdatePeriod; 674 uint32_t needNewPos = updatePeriod > 0 && user >= newPosition ? 675 ((user - newPosition) / updatePeriod) + 1 : 0; 676 mNewPosition = newPosition + updatePeriod * needNewPos; 677 mLock.unlock(); 678 679 // perform marker callback, while unlocked 680 if (needMarker) { 681 mCbf(EVENT_MARKER, mUserData, &markerPosition); 682 } 683 684 // perform new position callback(s), while unlocked 685 for (; needNewPos > 0; --needNewPos) { 686 uint32_t temp = newPosition; 687 mCbf(EVENT_NEW_POS, mUserData, &temp); 688 newPosition += updatePeriod; 689 } 690 691 do { 692 audioBuffer.frameCount = frames; 693 // Calling obtainBuffer() with a wait count of 1 694 // limits wait time to WAIT_PERIOD_MS. This prevents from being 695 // stuck here not being able to handle timed events (position, markers). 696 status_t err = obtainBuffer(&audioBuffer, 1); 697 if (err < NO_ERROR) { 698 if (err != TIMED_OUT) { 699 ALOGE_IF(err != status_t(NO_MORE_BUFFERS), 700 "Error obtaining an audio buffer, giving up."); 701 return false; 702 } 703 break; 704 } 705 if (err == status_t(STOPPED)) return false; 706 707 size_t reqSize = audioBuffer.size; 708 mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); 709 readSize = audioBuffer.size; 710 711 // Sanity check on returned size 712 if (ssize_t(readSize) <= 0) { 713 // The callback is done filling buffers 714 // Keep this thread going to handle timed events and 715 // still try to get more data in intervals of WAIT_PERIOD_MS 716 // but don't just loop and block the CPU, so wait 717 usleep(WAIT_PERIOD_MS*1000); 718 break; 719 } 720 if (readSize > reqSize) readSize = reqSize; 721 722 audioBuffer.size = readSize; 723 audioBuffer.frameCount = readSize/frameSize(); 724 frames -= audioBuffer.frameCount; 725 726 releaseBuffer(&audioBuffer); 727 728 } while (frames); 729 730 731 // Manage overrun callback 732 if (active && (cblk->framesAvailableIn() == 0)) { 733 // The value of active is stale, but we are almost sure to be active here because 734 // otherwise we would have exited when obtainBuffer returned STOPPED earlier. 735 ALOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); 736 if (!(android_atomic_or(CBLK_UNDERRUN, &cblk->flags) & CBLK_UNDERRUN)) { 737 mCbf(EVENT_OVERRUN, mUserData, NULL); 738 } 739 } 740 741 if (frames == 0) { 742 mRemainingFrames = mNotificationFrames; 743 } else { 744 mRemainingFrames = frames; 745 } 746 return true; 747} 748 749// must be called with mLock and cblk.lock held. Callers must also hold strong references on 750// the IAudioRecord and IMemory in case they are recreated here. 751// If the IAudioRecord is successfully restored, the cblk pointer is updated 752status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk) 753{ 754 status_t result; 755 756 if (!(android_atomic_or(CBLK_RESTORING, &cblk->flags) & CBLK_RESTORING)) { 757 ALOGW("dead IAudioRecord, creating a new one"); 758 // signal old cblk condition so that other threads waiting for available buffers stop 759 // waiting now 760 cblk->cv.broadcast(); 761 cblk->lock.unlock(); 762 763 // if the new IAudioRecord is created, openRecord_l() will modify the 764 // following member variables: mAudioRecord, mCblkMemory and mCblk. 765 // It will also delete the strong references on previous IAudioRecord and IMemory 766 result = openRecord_l(cblk->sampleRate, mFormat, mChannelMask, 767 mFrameCount, getInput_l()); 768 if (result == NO_ERROR) { 769 // callback thread or sync event hasn't changed 770 result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0); 771 } 772 if (result != NO_ERROR) { 773 mActive = false; 774 } 775 776 // signal old cblk condition for other threads waiting for restore completion 777 android_atomic_or(CBLK_RESTORED, &cblk->flags); 778 cblk->cv.broadcast(); 779 } else { 780 if (!(cblk->flags & CBLK_RESTORED)) { 781 ALOGW("dead IAudioRecord, waiting for a new one to be created"); 782 mLock.unlock(); 783 result = cblk->cv.waitRelative(cblk->lock, milliseconds(RESTORE_TIMEOUT_MS)); 784 cblk->lock.unlock(); 785 mLock.lock(); 786 } else { 787 ALOGW("dead IAudioRecord, already restored"); 788 result = NO_ERROR; 789 cblk->lock.unlock(); 790 } 791 if (result != NO_ERROR || !mActive) { 792 result = status_t(STOPPED); 793 } 794 } 795 ALOGV("restoreRecord_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x", 796 result, mActive, mCblk, cblk, mCblk->flags, cblk->flags); 797 798 if (result == NO_ERROR) { 799 // from now on we switch to the newly created cblk 800 cblk = mCblk; 801 } 802 cblk->lock.lock(); 803 804 ALOGW_IF(result != NO_ERROR, "restoreRecord_l() error %d", result); 805 806 return result; 807} 808 809// ========================================================================= 810 811AudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver, bool bCanCallJava) 812 : Thread(bCanCallJava), mReceiver(receiver), mPaused(true) 813{ 814} 815 816AudioRecord::AudioRecordThread::~AudioRecordThread() 817{ 818} 819 820bool AudioRecord::AudioRecordThread::threadLoop() 821{ 822 { 823 AutoMutex _l(mMyLock); 824 if (mPaused) { 825 mMyCond.wait(mMyLock); 826 // caller will check for exitPending() 827 return true; 828 } 829 } 830 if (!mReceiver.processAudioBuffer(this)) { 831 pause(); 832 } 833 return true; 834} 835 836void AudioRecord::AudioRecordThread::requestExit() 837{ 838 // must be in this order to avoid a race condition 839 Thread::requestExit(); 840 resume(); 841} 842 843void AudioRecord::AudioRecordThread::pause() 844{ 845 AutoMutex _l(mMyLock); 846 mPaused = true; 847} 848 849void AudioRecord::AudioRecordThread::resume() 850{ 851 AutoMutex _l(mMyLock); 852 if (mPaused) { 853 mPaused = false; 854 mMyCond.signal(); 855 } 856} 857 858// ------------------------------------------------------------------------- 859 860}; // namespace android 861