AudioRecord.cpp revision f6b1678f8f508b447155a81b44e214475ab634a8
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 int format, 52 int channelCount) 53{ 54 size_t size = 0; 55 if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &size) 56 != NO_ERROR) { 57 LOGE("AudioSystem could not query the input buffer size."); 58 return NO_INIT; 59 } 60 61 if (size == 0) { 62 LOGE("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 int inputSource, 88 uint32_t sampleRate, 89 int 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 int inputSource, 123 uint32_t sampleRate, 124 int 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 == 0) { 152 format = AUDIO_FORMAT_PCM_16_BIT; 153 } 154 // validate parameters 155 if (!audio_is_valid_format(format)) { 156 LOGE("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 LOGE("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 if (mClientRecordThread == 0) { 212 return NO_INIT; 213 } 214 } 215 216 mStatus = NO_ERROR; 217 218 mFormat = format; 219 // Update buffer size in case it has been limited by AudioFlinger during track creation 220 mFrameCount = mCblk->frameCount; 221 mChannelCount = (uint8_t)channelCount; 222 mChannelMask = channelMask; 223 mActive = 0; 224 mCbf = cbf; 225 mNotificationFrames = notificationFrames; 226 mRemainingFrames = notificationFrames; 227 mUserData = user; 228 // TODO: add audio hardware input latency here 229 mLatency = (1000*mFrameCount) / sampleRate; 230 mMarkerPosition = 0; 231 mMarkerReached = false; 232 mNewPosition = 0; 233 mUpdatePeriod = 0; 234 mInputSource = (uint8_t)inputSource; 235 mFlags = flags; 236 mInput = input; 237 AudioSystem::acquireAudioSessionId(mSessionId); 238 239 return NO_ERROR; 240} 241 242status_t AudioRecord::initCheck() const 243{ 244 return mStatus; 245} 246 247// ------------------------------------------------------------------------- 248 249uint32_t AudioRecord::latency() const 250{ 251 return mLatency; 252} 253 254int AudioRecord::format() const 255{ 256 return mFormat; 257} 258 259int AudioRecord::channelCount() const 260{ 261 return mChannelCount; 262} 263 264uint32_t AudioRecord::frameCount() const 265{ 266 return mFrameCount; 267} 268 269int AudioRecord::frameSize() const 270{ 271 if (audio_is_linear_pcm(mFormat)) { 272 return channelCount()*audio_bytes_per_sample(mFormat); 273 } else { 274 return sizeof(uint8_t); 275 } 276} 277 278int AudioRecord::inputSource() const 279{ 280 return (int)mInputSource; 281} 282 283// ------------------------------------------------------------------------- 284 285status_t AudioRecord::start() 286{ 287 status_t ret = NO_ERROR; 288 sp<ClientRecordThread> t = mClientRecordThread; 289 290 ALOGV("start"); 291 292 if (t != 0) { 293 if (t->exitPending()) { 294 if (t->requestExitAndWait() == WOULD_BLOCK) { 295 LOGE("AudioRecord::start called from thread"); 296 return WOULD_BLOCK; 297 } 298 } 299 t->mLock.lock(); 300 } 301 302 AutoMutex lock(mLock); 303 // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed 304 // while we are accessing the cblk 305 sp <IAudioRecord> audioRecord = mAudioRecord; 306 sp <IMemory> iMem = mCblkMemory; 307 audio_track_cblk_t* cblk = mCblk; 308 if (mActive == 0) { 309 mActive = 1; 310 311 cblk->lock.lock(); 312 if (!(cblk->flags & CBLK_INVALID_MSK)) { 313 cblk->lock.unlock(); 314 ret = mAudioRecord->start(); 315 cblk->lock.lock(); 316 if (ret == DEAD_OBJECT) { 317 android_atomic_or(CBLK_INVALID_ON, &cblk->flags); 318 } 319 } 320 if (cblk->flags & CBLK_INVALID_MSK) { 321 ret = restoreRecord_l(cblk); 322 } 323 cblk->lock.unlock(); 324 if (ret == NO_ERROR) { 325 mNewPosition = cblk->user + mUpdatePeriod; 326 cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; 327 cblk->waitTimeMs = 0; 328 if (t != 0) { 329 t->run("ClientRecordThread", ANDROID_PRIORITY_AUDIO); 330 } else { 331 mPreviousPriority = getpriority(PRIO_PROCESS, 0); 332 mPreviousSchedulingGroup = androidGetThreadSchedulingGroup(0); 333 androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 334 } 335 } else { 336 mActive = 0; 337 } 338 } 339 340 if (t != 0) { 341 t->mLock.unlock(); 342 } 343 344 return ret; 345} 346 347status_t AudioRecord::stop() 348{ 349 sp<ClientRecordThread> t = mClientRecordThread; 350 351 ALOGV("stop"); 352 353 if (t != 0) { 354 t->mLock.lock(); 355 } 356 357 AutoMutex lock(mLock); 358 if (mActive == 1) { 359 mActive = 0; 360 mCblk->cv.signal(); 361 mAudioRecord->stop(); 362 // the record head position will reset to 0, so if a marker is set, we need 363 // to activate it again 364 mMarkerReached = false; 365 if (t != 0) { 366 t->requestExit(); 367 } else { 368 setpriority(PRIO_PROCESS, 0, mPreviousPriority); 369 androidSetThreadSchedulingGroup(0, mPreviousSchedulingGroup); 370 } 371 } 372 373 if (t != 0) { 374 t->mLock.unlock(); 375 } 376 377 return NO_ERROR; 378} 379 380bool AudioRecord::stopped() const 381{ 382 return !mActive; 383} 384 385uint32_t AudioRecord::getSampleRate() 386{ 387 AutoMutex lock(mLock); 388 return mCblk->sampleRate; 389} 390 391status_t AudioRecord::setMarkerPosition(uint32_t marker) 392{ 393 if (mCbf == 0) return INVALID_OPERATION; 394 395 mMarkerPosition = marker; 396 mMarkerReached = false; 397 398 return NO_ERROR; 399} 400 401status_t AudioRecord::getMarkerPosition(uint32_t *marker) 402{ 403 if (marker == 0) return BAD_VALUE; 404 405 *marker = mMarkerPosition; 406 407 return NO_ERROR; 408} 409 410status_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod) 411{ 412 if (mCbf == 0) return INVALID_OPERATION; 413 414 uint32_t curPosition; 415 getPosition(&curPosition); 416 mNewPosition = curPosition + updatePeriod; 417 mUpdatePeriod = updatePeriod; 418 419 return NO_ERROR; 420} 421 422status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) 423{ 424 if (updatePeriod == 0) return BAD_VALUE; 425 426 *updatePeriod = mUpdatePeriod; 427 428 return NO_ERROR; 429} 430 431status_t AudioRecord::getPosition(uint32_t *position) 432{ 433 if (position == 0) return BAD_VALUE; 434 435 AutoMutex lock(mLock); 436 *position = mCblk->user; 437 438 return NO_ERROR; 439} 440 441unsigned int AudioRecord::getInputFramesLost() 442{ 443 if (mActive) 444 return AudioSystem::getInputFramesLost(mInput); 445 else 446 return 0; 447} 448 449// ------------------------------------------------------------------------- 450 451// must be called with mLock held 452status_t AudioRecord::openRecord_l( 453 uint32_t sampleRate, 454 uint32_t format, 455 uint32_t channelMask, 456 int frameCount, 457 uint32_t flags, 458 audio_io_handle_t input) 459{ 460 status_t status; 461 const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); 462 if (audioFlinger == 0) { 463 return NO_INIT; 464 } 465 466 sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input, 467 sampleRate, format, 468 channelMask, 469 frameCount, 470 ((uint16_t)flags) << 16, 471 &mSessionId, 472 &status); 473 474 if (record == 0) { 475 LOGE("AudioFlinger could not create record track, status: %d", status); 476 return status; 477 } 478 sp<IMemory> cblk = record->getCblk(); 479 if (cblk == 0) { 480 LOGE("Could not get control block"); 481 return NO_INIT; 482 } 483 mAudioRecord.clear(); 484 mAudioRecord = record; 485 mCblkMemory.clear(); 486 mCblkMemory = cblk; 487 mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); 488 mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); 489 android_atomic_and(~CBLK_DIRECTION_MSK, &mCblk->flags); 490 mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; 491 mCblk->waitTimeMs = 0; 492 return NO_ERROR; 493} 494 495status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) 496{ 497 AutoMutex lock(mLock); 498 int active; 499 status_t result = NO_ERROR; 500 audio_track_cblk_t* cblk = mCblk; 501 uint32_t framesReq = audioBuffer->frameCount; 502 uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS; 503 504 audioBuffer->frameCount = 0; 505 audioBuffer->size = 0; 506 507 uint32_t framesReady = cblk->framesReady(); 508 509 if (framesReady == 0) { 510 cblk->lock.lock(); 511 goto start_loop_here; 512 while (framesReady == 0) { 513 active = mActive; 514 if (CC_UNLIKELY(!active)) { 515 cblk->lock.unlock(); 516 return NO_MORE_BUFFERS; 517 } 518 if (CC_UNLIKELY(!waitCount)) { 519 cblk->lock.unlock(); 520 return WOULD_BLOCK; 521 } 522 if (!(cblk->flags & CBLK_INVALID_MSK)) { 523 mLock.unlock(); 524 result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); 525 cblk->lock.unlock(); 526 mLock.lock(); 527 if (mActive == 0) { 528 return status_t(STOPPED); 529 } 530 cblk->lock.lock(); 531 } 532 if (cblk->flags & CBLK_INVALID_MSK) { 533 goto create_new_record; 534 } 535 if (CC_UNLIKELY(result != NO_ERROR)) { 536 cblk->waitTimeMs += waitTimeMs; 537 if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { 538 LOGW( "obtainBuffer timed out (is the CPU pegged?) " 539 "user=%08x, server=%08x", cblk->user, cblk->server); 540 cblk->lock.unlock(); 541 result = mAudioRecord->start(); 542 cblk->lock.lock(); 543 if (result == DEAD_OBJECT) { 544 android_atomic_or(CBLK_INVALID_ON, &cblk->flags); 545create_new_record: 546 result = AudioRecord::restoreRecord_l(cblk); 547 } 548 if (result != NO_ERROR) { 549 LOGW("obtainBuffer create Track error %d", result); 550 cblk->lock.unlock(); 551 return result; 552 } 553 cblk->waitTimeMs = 0; 554 } 555 if (--waitCount == 0) { 556 cblk->lock.unlock(); 557 return TIMED_OUT; 558 } 559 } 560 // read the server count again 561 start_loop_here: 562 framesReady = cblk->framesReady(); 563 } 564 cblk->lock.unlock(); 565 } 566 567 cblk->waitTimeMs = 0; 568 569 if (framesReq > framesReady) { 570 framesReq = framesReady; 571 } 572 573 uint32_t u = cblk->user; 574 uint32_t bufferEnd = cblk->userBase + cblk->frameCount; 575 576 if (u + framesReq > bufferEnd) { 577 framesReq = bufferEnd - u; 578 } 579 580 audioBuffer->flags = 0; 581 audioBuffer->channelCount= mChannelCount; 582 audioBuffer->format = mFormat; 583 audioBuffer->frameCount = framesReq; 584 audioBuffer->size = framesReq*cblk->frameSize; 585 audioBuffer->raw = (int8_t*)cblk->buffer(u); 586 active = mActive; 587 return active ? status_t(NO_ERROR) : status_t(STOPPED); 588} 589 590void AudioRecord::releaseBuffer(Buffer* audioBuffer) 591{ 592 AutoMutex lock(mLock); 593 mCblk->stepUser(audioBuffer->frameCount); 594} 595 596audio_io_handle_t AudioRecord::getInput() 597{ 598 AutoMutex lock(mLock); 599 return mInput; 600} 601 602// must be called with mLock held 603audio_io_handle_t AudioRecord::getInput_l() 604{ 605 mInput = AudioSystem::getInput(mInputSource, 606 mCblk->sampleRate, 607 mFormat, 608 mChannelMask, 609 (audio_in_acoustics_t)mFlags, 610 mSessionId); 611 return mInput; 612} 613 614int AudioRecord::getSessionId() 615{ 616 return mSessionId; 617} 618 619// ------------------------------------------------------------------------- 620 621ssize_t AudioRecord::read(void* buffer, size_t userSize) 622{ 623 ssize_t read = 0; 624 Buffer audioBuffer; 625 int8_t *dst = static_cast<int8_t*>(buffer); 626 627 if (ssize_t(userSize) < 0) { 628 // sanity-check. user is most-likely passing an error code. 629 LOGE("AudioRecord::read(buffer=%p, size=%u (%d)", 630 buffer, userSize, userSize); 631 return BAD_VALUE; 632 } 633 634 mLock.lock(); 635 // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed 636 // while we are accessing the cblk 637 sp <IAudioRecord> audioRecord = mAudioRecord; 638 sp <IMemory> iMem = mCblkMemory; 639 mLock.unlock(); 640 641 do { 642 643 audioBuffer.frameCount = userSize/frameSize(); 644 645 // By using a wait count corresponding to twice the timeout period in 646 // obtainBuffer() we give a chance to recover once for a read timeout 647 // (if media_server crashed for instance) before returning a length of 648 // 0 bytes read to the client 649 status_t err = obtainBuffer(&audioBuffer, ((2 * MAX_RUN_TIMEOUT_MS) / WAIT_PERIOD_MS)); 650 if (err < 0) { 651 // out of buffers, return #bytes written 652 if (err == status_t(NO_MORE_BUFFERS)) 653 break; 654 if (err == status_t(TIMED_OUT)) 655 err = 0; 656 return ssize_t(err); 657 } 658 659 size_t bytesRead = audioBuffer.size; 660 memcpy(dst, audioBuffer.i8, bytesRead); 661 662 dst += bytesRead; 663 userSize -= bytesRead; 664 read += bytesRead; 665 666 releaseBuffer(&audioBuffer); 667 } while (userSize); 668 669 return read; 670} 671 672// ------------------------------------------------------------------------- 673 674bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) 675{ 676 Buffer audioBuffer; 677 uint32_t frames = mRemainingFrames; 678 size_t readSize; 679 680 mLock.lock(); 681 // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed 682 // while we are accessing the cblk 683 sp <IAudioRecord> audioRecord = mAudioRecord; 684 sp <IMemory> iMem = mCblkMemory; 685 audio_track_cblk_t* cblk = mCblk; 686 mLock.unlock(); 687 688 // Manage marker callback 689 if (!mMarkerReached && (mMarkerPosition > 0)) { 690 if (cblk->user >= mMarkerPosition) { 691 mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition); 692 mMarkerReached = true; 693 } 694 } 695 696 // Manage new position callback 697 if (mUpdatePeriod > 0) { 698 while (cblk->user >= mNewPosition) { 699 mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition); 700 mNewPosition += mUpdatePeriod; 701 } 702 } 703 704 do { 705 audioBuffer.frameCount = frames; 706 // Calling obtainBuffer() with a wait count of 1 707 // limits wait time to WAIT_PERIOD_MS. This prevents from being 708 // stuck here not being able to handle timed events (position, markers). 709 status_t err = obtainBuffer(&audioBuffer, 1); 710 if (err < NO_ERROR) { 711 if (err != TIMED_OUT) { 712 LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up."); 713 return false; 714 } 715 break; 716 } 717 if (err == status_t(STOPPED)) return false; 718 719 size_t reqSize = audioBuffer.size; 720 mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); 721 readSize = audioBuffer.size; 722 723 // Sanity check on returned size 724 if (ssize_t(readSize) <= 0) { 725 // The callback is done filling buffers 726 // Keep this thread going to handle timed events and 727 // still try to get more data in intervals of WAIT_PERIOD_MS 728 // but don't just loop and block the CPU, so wait 729 usleep(WAIT_PERIOD_MS*1000); 730 break; 731 } 732 if (readSize > reqSize) readSize = reqSize; 733 734 audioBuffer.size = readSize; 735 audioBuffer.frameCount = readSize/frameSize(); 736 frames -= audioBuffer.frameCount; 737 738 releaseBuffer(&audioBuffer); 739 740 } while (frames); 741 742 743 // Manage overrun callback 744 if (mActive && (cblk->framesAvailable() == 0)) { 745 ALOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); 746 if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) { 747 mCbf(EVENT_OVERRUN, mUserData, 0); 748 } 749 } 750 751 if (frames == 0) { 752 mRemainingFrames = mNotificationFrames; 753 } else { 754 mRemainingFrames = frames; 755 } 756 return true; 757} 758 759// must be called with mLock and cblk.lock held. Callers must also hold strong references on 760// the IAudioRecord and IMemory in case they are recreated here. 761// If the IAudioRecord is successfully restored, the cblk pointer is updated 762status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk) 763{ 764 status_t result; 765 766 if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) { 767 LOGW("dead IAudioRecord, creating a new one"); 768 // signal old cblk condition so that other threads waiting for available buffers stop 769 // waiting now 770 cblk->cv.broadcast(); 771 cblk->lock.unlock(); 772 773 // if the new IAudioRecord is created, openRecord_l() will modify the 774 // following member variables: mAudioRecord, mCblkMemory and mCblk. 775 // It will also delete the strong references on previous IAudioRecord and IMemory 776 result = openRecord_l(cblk->sampleRate, mFormat, mChannelMask, 777 mFrameCount, mFlags, getInput_l()); 778 if (result == NO_ERROR) { 779 result = mAudioRecord->start(); 780 } 781 if (result != NO_ERROR) { 782 mActive = false; 783 } 784 785 // signal old cblk condition for other threads waiting for restore completion 786 android_atomic_or(CBLK_RESTORED_ON, &cblk->flags); 787 cblk->cv.broadcast(); 788 } else { 789 if (!(cblk->flags & CBLK_RESTORED_MSK)) { 790 LOGW("dead IAudioRecord, waiting for a new one to be created"); 791 mLock.unlock(); 792 result = cblk->cv.waitRelative(cblk->lock, milliseconds(RESTORE_TIMEOUT_MS)); 793 cblk->lock.unlock(); 794 mLock.lock(); 795 } else { 796 LOGW("dead IAudioRecord, already restored"); 797 result = NO_ERROR; 798 cblk->lock.unlock(); 799 } 800 if (result != NO_ERROR || mActive == 0) { 801 result = status_t(STOPPED); 802 } 803 } 804 ALOGV("restoreRecord_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x", 805 result, mActive, mCblk, cblk, mCblk->flags, cblk->flags); 806 807 if (result == NO_ERROR) { 808 // from now on we switch to the newly created cblk 809 cblk = mCblk; 810 } 811 cblk->lock.lock(); 812 813 LOGW_IF(result != NO_ERROR, "restoreRecord_l() error %d", result); 814 815 return result; 816} 817 818// ========================================================================= 819 820AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava) 821 : Thread(bCanCallJava), mReceiver(receiver) 822{ 823} 824 825bool AudioRecord::ClientRecordThread::threadLoop() 826{ 827 return mReceiver.processAudioBuffer(this); 828} 829 830// ------------------------------------------------------------------------- 831 832}; // namespace android 833 834