AudioRecord.cpp revision 1879fff068422852c1483dcf8365c2ff0e2fadfc
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 // no need to check mActive, because if inactive this will return 0, which is what we want 436 return AudioSystem::getInputFramesLost(mInput); 437} 438 439// ------------------------------------------------------------------------- 440 441// must be called with mLock held 442status_t AudioRecord::openRecord_l( 443 uint32_t sampleRate, 444 audio_format_t format, 445 audio_channel_mask_t channelMask, 446 int frameCount, 447 audio_io_handle_t input) 448{ 449 status_t status; 450 const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); 451 if (audioFlinger == 0) { 452 return NO_INIT; 453 } 454 455 pid_t tid = -1; 456 // FIXME see similar logic at AudioTrack 457 458 sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input, 459 sampleRate, format, 460 channelMask, 461 frameCount, 462 IAudioFlinger::TRACK_DEFAULT, 463 tid, 464 &mSessionId, 465 &status); 466 467 if (record == 0) { 468 ALOGE("AudioFlinger could not create record track, status: %d", status); 469 return status; 470 } 471 sp<IMemory> cblk = record->getCblk(); 472 if (cblk == 0) { 473 ALOGE("Could not get control block"); 474 return NO_INIT; 475 } 476 mAudioRecord.clear(); 477 mAudioRecord = record; 478 mCblkMemory.clear(); 479 mCblkMemory = cblk; 480 mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); 481 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); 482 android_atomic_and(~CBLK_DIRECTION_MSK, &mCblk->flags); 483 mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; 484 mCblk->waitTimeMs = 0; 485 return NO_ERROR; 486} 487 488status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) 489{ 490 AutoMutex lock(mLock); 491 int active; 492 status_t result = NO_ERROR; 493 audio_track_cblk_t* cblk = mCblk; 494 uint32_t framesReq = audioBuffer->frameCount; 495 uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS; 496 497 audioBuffer->frameCount = 0; 498 audioBuffer->size = 0; 499 500 uint32_t framesReady = cblk->framesReady(); 501 502 if (framesReady == 0) { 503 cblk->lock.lock(); 504 goto start_loop_here; 505 while (framesReady == 0) { 506 active = mActive; 507 if (CC_UNLIKELY(!active)) { 508 cblk->lock.unlock(); 509 return NO_MORE_BUFFERS; 510 } 511 if (CC_UNLIKELY(!waitCount)) { 512 cblk->lock.unlock(); 513 return WOULD_BLOCK; 514 } 515 if (!(cblk->flags & CBLK_INVALID_MSK)) { 516 mLock.unlock(); 517 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); 518 cblk->lock.unlock(); 519 mLock.lock(); 520 if (mActive == 0) { 521 return status_t(STOPPED); 522 } 523 cblk->lock.lock(); 524 } 525 if (cblk->flags & CBLK_INVALID_MSK) { 526 goto create_new_record; 527 } 528 if (CC_UNLIKELY(result != NO_ERROR)) { 529 cblk->waitTimeMs += waitTimeMs; 530 if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { 531 ALOGW( "obtainBuffer timed out (is the CPU pegged?) " 532 "user=%08x, server=%08x", cblk->user, cblk->server); 533 cblk->lock.unlock(); 534 // callback thread or sync event hasn't changed 535 result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0); 536 cblk->lock.lock(); 537 if (result == DEAD_OBJECT) { 538 android_atomic_or(CBLK_INVALID_ON, &cblk->flags); 539create_new_record: 540 result = AudioRecord::restoreRecord_l(cblk); 541 } 542 if (result != NO_ERROR) { 543 ALOGW("obtainBuffer create Track error %d", result); 544 cblk->lock.unlock(); 545 return result; 546 } 547 cblk->waitTimeMs = 0; 548 } 549 if (--waitCount == 0) { 550 cblk->lock.unlock(); 551 return TIMED_OUT; 552 } 553 } 554 // read the server count again 555 start_loop_here: 556 framesReady = cblk->framesReady(); 557 } 558 cblk->lock.unlock(); 559 } 560 561 cblk->waitTimeMs = 0; 562 // reset time out to running value after obtaining a buffer 563 cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; 564 565 if (framesReq > framesReady) { 566 framesReq = framesReady; 567 } 568 569 uint32_t u = cblk->user; 570 uint32_t bufferEnd = cblk->userBase + cblk->frameCount; 571 572 if (framesReq > bufferEnd - u) { 573 framesReq = bufferEnd - u; 574 } 575 576 audioBuffer->flags = 0; 577 audioBuffer->channelCount= mChannelCount; 578 audioBuffer->format = mFormat; 579 audioBuffer->frameCount = framesReq; 580 audioBuffer->size = framesReq*cblk->frameSize; 581 audioBuffer->raw = (int8_t*)cblk->buffer(u); 582 active = mActive; 583 return active ? status_t(NO_ERROR) : status_t(STOPPED); 584} 585 586void AudioRecord::releaseBuffer(Buffer* audioBuffer) 587{ 588 AutoMutex lock(mLock); 589 mCblk->stepUser(audioBuffer->frameCount); 590} 591 592audio_io_handle_t AudioRecord::getInput() const 593{ 594 AutoMutex lock(mLock); 595 return mInput; 596} 597 598// must be called with mLock held 599audio_io_handle_t AudioRecord::getInput_l() 600{ 601 mInput = AudioSystem::getInput(mInputSource, 602 mCblk->sampleRate, 603 mFormat, 604 mChannelMask, 605 mSessionId); 606 return mInput; 607} 608 609int AudioRecord::getSessionId() const 610{ 611 return mSessionId; 612} 613 614// ------------------------------------------------------------------------- 615 616ssize_t AudioRecord::read(void* buffer, size_t userSize) 617{ 618 ssize_t read = 0; 619 Buffer audioBuffer; 620 int8_t *dst = static_cast<int8_t*>(buffer); 621 622 if (ssize_t(userSize) < 0) { 623 // sanity-check. user is most-likely passing an error code. 624 ALOGE("AudioRecord::read(buffer=%p, size=%u (%d)", 625 buffer, userSize, userSize); 626 return BAD_VALUE; 627 } 628 629 mLock.lock(); 630 // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed 631 // while we are accessing the cblk 632 sp<IAudioRecord> audioRecord = mAudioRecord; 633 sp<IMemory> iMem = mCblkMemory; 634 mLock.unlock(); 635 636 do { 637 638 audioBuffer.frameCount = userSize/frameSize(); 639 640 // By using a wait count corresponding to twice the timeout period in 641 // obtainBuffer() we give a chance to recover once for a read timeout 642 // (if media_server crashed for instance) before returning a length of 643 // 0 bytes read to the client 644 status_t err = obtainBuffer(&audioBuffer, ((2 * MAX_RUN_TIMEOUT_MS) / WAIT_PERIOD_MS)); 645 if (err < 0) { 646 // out of buffers, return #bytes written 647 if (err == status_t(NO_MORE_BUFFERS)) 648 break; 649 if (err == status_t(TIMED_OUT)) 650 err = 0; 651 return ssize_t(err); 652 } 653 654 size_t bytesRead = audioBuffer.size; 655 memcpy(dst, audioBuffer.i8, bytesRead); 656 657 dst += bytesRead; 658 userSize -= bytesRead; 659 read += bytesRead; 660 661 releaseBuffer(&audioBuffer); 662 } while (userSize); 663 664 return read; 665} 666 667// ------------------------------------------------------------------------- 668 669bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) 670{ 671 Buffer audioBuffer; 672 uint32_t frames = mRemainingFrames; 673 size_t readSize; 674 675 mLock.lock(); 676 // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed 677 // while we are accessing the cblk 678 sp<IAudioRecord> audioRecord = mAudioRecord; 679 sp<IMemory> iMem = mCblkMemory; 680 audio_track_cblk_t* cblk = mCblk; 681 mLock.unlock(); 682 683 // Manage marker callback 684 if (!mMarkerReached && (mMarkerPosition > 0)) { 685 if (cblk->user >= mMarkerPosition) { 686 mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition); 687 mMarkerReached = true; 688 } 689 } 690 691 // Manage new position callback 692 if (mUpdatePeriod > 0) { 693 while (cblk->user >= mNewPosition) { 694 mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition); 695 mNewPosition += mUpdatePeriod; 696 } 697 } 698 699 do { 700 audioBuffer.frameCount = frames; 701 // Calling obtainBuffer() with a wait count of 1 702 // limits wait time to WAIT_PERIOD_MS. This prevents from being 703 // stuck here not being able to handle timed events (position, markers). 704 status_t err = obtainBuffer(&audioBuffer, 1); 705 if (err < NO_ERROR) { 706 if (err != TIMED_OUT) { 707 ALOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up."); 708 return false; 709 } 710 break; 711 } 712 if (err == status_t(STOPPED)) return false; 713 714 size_t reqSize = audioBuffer.size; 715 mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); 716 readSize = audioBuffer.size; 717 718 // Sanity check on returned size 719 if (ssize_t(readSize) <= 0) { 720 // The callback is done filling buffers 721 // Keep this thread going to handle timed events and 722 // still try to get more data in intervals of WAIT_PERIOD_MS 723 // but don't just loop and block the CPU, so wait 724 usleep(WAIT_PERIOD_MS*1000); 725 break; 726 } 727 if (readSize > reqSize) readSize = reqSize; 728 729 audioBuffer.size = readSize; 730 audioBuffer.frameCount = readSize/frameSize(); 731 frames -= audioBuffer.frameCount; 732 733 releaseBuffer(&audioBuffer); 734 735 } while (frames); 736 737 738 // Manage overrun callback 739 if (mActive && (cblk->framesAvailable() == 0)) { 740 ALOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); 741 if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) { 742 mCbf(EVENT_OVERRUN, mUserData, 0); 743 } 744 } 745 746 if (frames == 0) { 747 mRemainingFrames = mNotificationFrames; 748 } else { 749 mRemainingFrames = frames; 750 } 751 return true; 752} 753 754// must be called with mLock and cblk.lock held. Callers must also hold strong references on 755// the IAudioRecord and IMemory in case they are recreated here. 756// If the IAudioRecord is successfully restored, the cblk pointer is updated 757status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk) 758{ 759 status_t result; 760 761 if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) { 762 ALOGW("dead IAudioRecord, creating a new one"); 763 // signal old cblk condition so that other threads waiting for available buffers stop 764 // waiting now 765 cblk->cv.broadcast(); 766 cblk->lock.unlock(); 767 768 // if the new IAudioRecord is created, openRecord_l() will modify the 769 // following member variables: mAudioRecord, mCblkMemory and mCblk. 770 // It will also delete the strong references on previous IAudioRecord and IMemory 771 result = openRecord_l(cblk->sampleRate, mFormat, mChannelMask, 772 mFrameCount, getInput_l()); 773 if (result == NO_ERROR) { 774 // callback thread or sync event hasn't changed 775 result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0); 776 } 777 if (result != NO_ERROR) { 778 mActive = false; 779 } 780 781 // signal old cblk condition for other threads waiting for restore completion 782 android_atomic_or(CBLK_RESTORED_ON, &cblk->flags); 783 cblk->cv.broadcast(); 784 } else { 785 if (!(cblk->flags & CBLK_RESTORED_MSK)) { 786 ALOGW("dead IAudioRecord, waiting for a new one to be created"); 787 mLock.unlock(); 788 result = cblk->cv.waitRelative(cblk->lock, milliseconds(RESTORE_TIMEOUT_MS)); 789 cblk->lock.unlock(); 790 mLock.lock(); 791 } else { 792 ALOGW("dead IAudioRecord, already restored"); 793 result = NO_ERROR; 794 cblk->lock.unlock(); 795 } 796 if (result != NO_ERROR || mActive == 0) { 797 result = status_t(STOPPED); 798 } 799 } 800 ALOGV("restoreRecord_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x", 801 result, mActive, mCblk, cblk, mCblk->flags, cblk->flags); 802 803 if (result == NO_ERROR) { 804 // from now on we switch to the newly created cblk 805 cblk = mCblk; 806 } 807 cblk->lock.lock(); 808 809 ALOGW_IF(result != NO_ERROR, "restoreRecord_l() error %d", result); 810 811 return result; 812} 813 814// ========================================================================= 815 816AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava) 817 : Thread(bCanCallJava), mReceiver(receiver) 818{ 819} 820 821bool AudioRecord::ClientRecordThread::threadLoop() 822{ 823 return mReceiver.processAudioBuffer(this); 824} 825 826status_t AudioRecord::ClientRecordThread::readyToRun() 827{ 828 AutoMutex(mReceiver.mLock); 829 while (mReceiver.mReadyToRun == WOULD_BLOCK) { 830 mReceiver.mCondition.wait(mReceiver.mLock); 831 } 832 return mReceiver.mReadyToRun; 833} 834 835// ------------------------------------------------------------------------- 836 837}; // namespace android 838