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