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