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