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