AudioRecord.cpp revision 868a6a357018e5872e064b7a13a9b891e2078962
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 int channelCount) 43{ 44 size_t size = 0; 45 if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &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, channelCount %d", 53 sampleRate, format, channelCount); 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 size /= channelCount * audio_bytes_per_sample(format); 62 } 63 64 *frameCount = size; 65 return NO_ERROR; 66} 67 68// --------------------------------------------------------------------------- 69 70AudioRecord::AudioRecord() 71 : mStatus(NO_INIT), mSessionId(0), 72 mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) 73{ 74} 75 76AudioRecord::AudioRecord( 77 audio_source_t inputSource, 78 uint32_t sampleRate, 79 audio_format_t format, 80 uint32_t channelMask, 81 int frameCount, 82 callback_t cbf, 83 void* user, 84 int notificationFrames, 85 int sessionId) 86 : mStatus(NO_INIT), mSessionId(0), 87 mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) 88{ 89 mStatus = set(inputSource, sampleRate, format, channelMask, 90 frameCount, cbf, user, notificationFrames, sessionId); 91} 92 93AudioRecord::~AudioRecord() 94{ 95 if (mStatus == NO_ERROR) { 96 // Make sure that callback function exits in the case where 97 // it is looping on buffer empty condition in obtainBuffer(). 98 // Otherwise the callback thread will never exit. 99 stop(); 100 if (mClientRecordThread != 0) { 101 mClientRecordThread->requestExitAndWait(); 102 mClientRecordThread.clear(); 103 } 104 mAudioRecord.clear(); 105 IPCThreadState::self()->flushCommands(); 106 AudioSystem::releaseAudioSessionId(mSessionId); 107 } 108} 109 110status_t AudioRecord::set( 111 audio_source_t inputSource, 112 uint32_t sampleRate, 113 audio_format_t format, 114 uint32_t channelMask, 115 int frameCount, 116 callback_t cbf, 117 void* user, 118 int notificationFrames, 119 bool threadCanCallJava, 120 int sessionId) 121{ 122 123 ALOGV("set(): sampleRate %d, channelMask %d, frameCount %d",sampleRate, channelMask, frameCount); 124 125 AutoMutex lock(mLock); 126 127 if (mAudioRecord != 0) { 128 return INVALID_OPERATION; 129 } 130 131 if (inputSource == AUDIO_SOURCE_DEFAULT) { 132 inputSource = AUDIO_SOURCE_MIC; 133 } 134 135 if (sampleRate == 0) { 136 sampleRate = DEFAULT_SAMPLE_RATE; 137 } 138 // these below should probably come from the audioFlinger too... 139 if (format == AUDIO_FORMAT_DEFAULT) { 140 format = AUDIO_FORMAT_PCM_16_BIT; 141 } 142 // validate parameters 143 if (!audio_is_valid_format(format)) { 144 ALOGE("Invalid format"); 145 return BAD_VALUE; 146 } 147 148 if (!audio_is_input_channel(channelMask)) { 149 return BAD_VALUE; 150 } 151 152 int channelCount = popcount(channelMask); 153 154 if (sessionId == 0 ) { 155 mSessionId = AudioSystem::newAudioSessionId(); 156 } else { 157 mSessionId = sessionId; 158 } 159 ALOGV("set(): mSessionId %d", mSessionId); 160 161 audio_io_handle_t input = AudioSystem::getInput(inputSource, 162 sampleRate, 163 format, 164 channelMask, 165 (audio_in_acoustics_t) 0, 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 uint32_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 (audio_in_acoustics_t) 0, 604 mSessionId); 605 return mInput; 606} 607 608int AudioRecord::getSessionId() const 609{ 610 return mSessionId; 611} 612 613// ------------------------------------------------------------------------- 614 615ssize_t AudioRecord::read(void* buffer, size_t userSize) 616{ 617 ssize_t read = 0; 618 Buffer audioBuffer; 619 int8_t *dst = static_cast<int8_t*>(buffer); 620 621 if (ssize_t(userSize) < 0) { 622 // sanity-check. user is most-likely passing an error code. 623 ALOGE("AudioRecord::read(buffer=%p, size=%u (%d)", 624 buffer, userSize, userSize); 625 return BAD_VALUE; 626 } 627 628 mLock.lock(); 629 // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed 630 // while we are accessing the cblk 631 sp<IAudioRecord> audioRecord = mAudioRecord; 632 sp<IMemory> iMem = mCblkMemory; 633 mLock.unlock(); 634 635 do { 636 637 audioBuffer.frameCount = userSize/frameSize(); 638 639 // By using a wait count corresponding to twice the timeout period in 640 // obtainBuffer() we give a chance to recover once for a read timeout 641 // (if media_server crashed for instance) before returning a length of 642 // 0 bytes read to the client 643 status_t err = obtainBuffer(&audioBuffer, ((2 * MAX_RUN_TIMEOUT_MS) / WAIT_PERIOD_MS)); 644 if (err < 0) { 645 // out of buffers, return #bytes written 646 if (err == status_t(NO_MORE_BUFFERS)) 647 break; 648 if (err == status_t(TIMED_OUT)) 649 err = 0; 650 return ssize_t(err); 651 } 652 653 size_t bytesRead = audioBuffer.size; 654 memcpy(dst, audioBuffer.i8, bytesRead); 655 656 dst += bytesRead; 657 userSize -= bytesRead; 658 read += bytesRead; 659 660 releaseBuffer(&audioBuffer); 661 } while (userSize); 662 663 return read; 664} 665 666// ------------------------------------------------------------------------- 667 668bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) 669{ 670 Buffer audioBuffer; 671 uint32_t frames = mRemainingFrames; 672 size_t readSize; 673 674 mLock.lock(); 675 // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed 676 // while we are accessing the cblk 677 sp<IAudioRecord> audioRecord = mAudioRecord; 678 sp<IMemory> iMem = mCblkMemory; 679 audio_track_cblk_t* cblk = mCblk; 680 mLock.unlock(); 681 682 // Manage marker callback 683 if (!mMarkerReached && (mMarkerPosition > 0)) { 684 if (cblk->user >= mMarkerPosition) { 685 mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition); 686 mMarkerReached = true; 687 } 688 } 689 690 // Manage new position callback 691 if (mUpdatePeriod > 0) { 692 while (cblk->user >= mNewPosition) { 693 mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition); 694 mNewPosition += mUpdatePeriod; 695 } 696 } 697 698 do { 699 audioBuffer.frameCount = frames; 700 // Calling obtainBuffer() with a wait count of 1 701 // limits wait time to WAIT_PERIOD_MS. This prevents from being 702 // stuck here not being able to handle timed events (position, markers). 703 status_t err = obtainBuffer(&audioBuffer, 1); 704 if (err < NO_ERROR) { 705 if (err != TIMED_OUT) { 706 ALOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up."); 707 return false; 708 } 709 break; 710 } 711 if (err == status_t(STOPPED)) return false; 712 713 size_t reqSize = audioBuffer.size; 714 mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); 715 readSize = audioBuffer.size; 716 717 // Sanity check on returned size 718 if (ssize_t(readSize) <= 0) { 719 // The callback is done filling buffers 720 // Keep this thread going to handle timed events and 721 // still try to get more data in intervals of WAIT_PERIOD_MS 722 // but don't just loop and block the CPU, so wait 723 usleep(WAIT_PERIOD_MS*1000); 724 break; 725 } 726 if (readSize > reqSize) readSize = reqSize; 727 728 audioBuffer.size = readSize; 729 audioBuffer.frameCount = readSize/frameSize(); 730 frames -= audioBuffer.frameCount; 731 732 releaseBuffer(&audioBuffer); 733 734 } while (frames); 735 736 737 // Manage overrun callback 738 if (mActive && (cblk->framesAvailable() == 0)) { 739 ALOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); 740 if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) { 741 mCbf(EVENT_OVERRUN, mUserData, 0); 742 } 743 } 744 745 if (frames == 0) { 746 mRemainingFrames = mNotificationFrames; 747 } else { 748 mRemainingFrames = frames; 749 } 750 return true; 751} 752 753// must be called with mLock and cblk.lock held. Callers must also hold strong references on 754// the IAudioRecord and IMemory in case they are recreated here. 755// If the IAudioRecord is successfully restored, the cblk pointer is updated 756status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk) 757{ 758 status_t result; 759 760 if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) { 761 ALOGW("dead IAudioRecord, creating a new one"); 762 // signal old cblk condition so that other threads waiting for available buffers stop 763 // waiting now 764 cblk->cv.broadcast(); 765 cblk->lock.unlock(); 766 767 // if the new IAudioRecord is created, openRecord_l() will modify the 768 // following member variables: mAudioRecord, mCblkMemory and mCblk. 769 // It will also delete the strong references on previous IAudioRecord and IMemory 770 result = openRecord_l(cblk->sampleRate, mFormat, mChannelMask, 771 mFrameCount, getInput_l()); 772 if (result == NO_ERROR) { 773 // callback thread or sync event hasn't changed 774 result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0); 775 } 776 if (result != NO_ERROR) { 777 mActive = false; 778 } 779 780 // signal old cblk condition for other threads waiting for restore completion 781 android_atomic_or(CBLK_RESTORED_ON, &cblk->flags); 782 cblk->cv.broadcast(); 783 } else { 784 if (!(cblk->flags & CBLK_RESTORED_MSK)) { 785 ALOGW("dead IAudioRecord, waiting for a new one to be created"); 786 mLock.unlock(); 787 result = cblk->cv.waitRelative(cblk->lock, milliseconds(RESTORE_TIMEOUT_MS)); 788 cblk->lock.unlock(); 789 mLock.lock(); 790 } else { 791 ALOGW("dead IAudioRecord, already restored"); 792 result = NO_ERROR; 793 cblk->lock.unlock(); 794 } 795 if (result != NO_ERROR || mActive == 0) { 796 result = status_t(STOPPED); 797 } 798 } 799 ALOGV("restoreRecord_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x", 800 result, mActive, mCblk, cblk, mCblk->flags, cblk->flags); 801 802 if (result == NO_ERROR) { 803 // from now on we switch to the newly created cblk 804 cblk = mCblk; 805 } 806 cblk->lock.lock(); 807 808 ALOGW_IF(result != NO_ERROR, "restoreRecord_l() error %d", result); 809 810 return result; 811} 812 813// ========================================================================= 814 815AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava) 816 : Thread(bCanCallJava), mReceiver(receiver) 817{ 818} 819 820bool AudioRecord::ClientRecordThread::threadLoop() 821{ 822 return mReceiver.processAudioBuffer(this); 823} 824 825status_t AudioRecord::ClientRecordThread::readyToRun() 826{ 827 AutoMutex(mReceiver.mLock); 828 while (mReceiver.mReadyToRun == WOULD_BLOCK) { 829 mReceiver.mCondition.wait(mReceiver.mLock); 830 } 831 return mReceiver.mReadyToRun; 832} 833 834// ------------------------------------------------------------------------- 835 836}; // namespace android 837