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