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