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