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