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 <inttypes.h> 22 #include <sys/resource.h> 23 24 #include <binder/IPCThreadState.h> 25 #include <media/AudioRecord.h> 26 #include <utils/Log.h> 27 #include <private/media/AudioTrackShared.h> 28 #include <media/IAudioFlinger.h> 29 30 #define WAIT_PERIOD_MS 10 31 32 namespace android { 33 // --------------------------------------------------------------------------- 34 35 // static 36 status_t AudioRecord::getMinFrameCount( 37 size_t* frameCount, 38 uint32_t sampleRate, 39 audio_format_t format, 40 audio_channel_mask_t channelMask) 41 { 42 if (frameCount == NULL) { 43 return BAD_VALUE; 44 } 45 46 size_t size; 47 status_t status = AudioSystem::getInputBufferSize(sampleRate, format, channelMask, &size); 48 if (status != NO_ERROR) { 49 ALOGE("AudioSystem could not query the input buffer size for sampleRate %u, format %#x, " 50 "channelMask %#x; status %d", sampleRate, format, channelMask, status); 51 return status; 52 } 53 54 // We double the size of input buffer for ping pong use of record buffer. 55 // Assumes audio_is_linear_pcm(format) 56 if ((*frameCount = (size * 2) / (audio_channel_count_from_in_mask(channelMask) * 57 audio_bytes_per_sample(format))) == 0) { 58 ALOGE("Unsupported configuration: sampleRate %u, format %#x, channelMask %#x", 59 sampleRate, format, channelMask); 60 return BAD_VALUE; 61 } 62 63 return NO_ERROR; 64 } 65 66 // --------------------------------------------------------------------------- 67 68 AudioRecord::AudioRecord(const String16 &opPackageName) 69 : mActive(false), mStatus(NO_INIT), mOpPackageName(opPackageName), mSessionId(AUDIO_SESSION_ALLOCATE), 70 mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT), 71 mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE) 72 { 73 } 74 75 AudioRecord::AudioRecord( 76 audio_source_t inputSource, 77 uint32_t sampleRate, 78 audio_format_t format, 79 audio_channel_mask_t channelMask, 80 const String16& opPackageName, 81 size_t frameCount, 82 callback_t cbf, 83 void* user, 84 uint32_t notificationFrames, 85 audio_session_t sessionId, 86 transfer_type transferType, 87 audio_input_flags_t flags, 88 int uid, 89 pid_t pid, 90 const audio_attributes_t* pAttributes) 91 : mActive(false), 92 mStatus(NO_INIT), 93 mOpPackageName(opPackageName), 94 mSessionId(AUDIO_SESSION_ALLOCATE), 95 mPreviousPriority(ANDROID_PRIORITY_NORMAL), 96 mPreviousSchedulingGroup(SP_DEFAULT), 97 mProxy(NULL), 98 mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE) 99 { 100 mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user, 101 notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags, 102 uid, pid, pAttributes); 103 } 104 105 AudioRecord::~AudioRecord() 106 { 107 if (mStatus == NO_ERROR) { 108 // Make sure that callback function exits in the case where 109 // it is looping on buffer empty condition in obtainBuffer(). 110 // Otherwise the callback thread will never exit. 111 stop(); 112 if (mAudioRecordThread != 0) { 113 mProxy->interrupt(); 114 mAudioRecordThread->requestExit(); // see comment in AudioRecord.h 115 mAudioRecordThread->requestExitAndWait(); 116 mAudioRecordThread.clear(); 117 } 118 // No lock here: worst case we remove a NULL callback which will be a nop 119 if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) { 120 AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); 121 } 122 IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this); 123 mAudioRecord.clear(); 124 mCblkMemory.clear(); 125 mBufferMemory.clear(); 126 IPCThreadState::self()->flushCommands(); 127 ALOGV("~AudioRecord, releasing session id %d", 128 mSessionId); 129 AudioSystem::releaseAudioSessionId(mSessionId, -1 /*pid*/); 130 } 131 } 132 133 status_t AudioRecord::set( 134 audio_source_t inputSource, 135 uint32_t sampleRate, 136 audio_format_t format, 137 audio_channel_mask_t channelMask, 138 size_t frameCount, 139 callback_t cbf, 140 void* user, 141 uint32_t notificationFrames, 142 bool threadCanCallJava, 143 audio_session_t sessionId, 144 transfer_type transferType, 145 audio_input_flags_t flags, 146 int uid, 147 pid_t pid, 148 const audio_attributes_t* pAttributes) 149 { 150 ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, " 151 "notificationFrames %u, sessionId %d, transferType %d, flags %#x, opPackageName %s " 152 "uid %d, pid %d", 153 inputSource, sampleRate, format, channelMask, frameCount, notificationFrames, 154 sessionId, transferType, flags, String8(mOpPackageName).string(), uid, pid); 155 156 switch (transferType) { 157 case TRANSFER_DEFAULT: 158 if (cbf == NULL || threadCanCallJava) { 159 transferType = TRANSFER_SYNC; 160 } else { 161 transferType = TRANSFER_CALLBACK; 162 } 163 break; 164 case TRANSFER_CALLBACK: 165 if (cbf == NULL) { 166 ALOGE("Transfer type TRANSFER_CALLBACK but cbf == NULL"); 167 return BAD_VALUE; 168 } 169 break; 170 case TRANSFER_OBTAIN: 171 case TRANSFER_SYNC: 172 break; 173 default: 174 ALOGE("Invalid transfer type %d", transferType); 175 return BAD_VALUE; 176 } 177 mTransfer = transferType; 178 179 // invariant that mAudioRecord != 0 is true only after set() returns successfully 180 if (mAudioRecord != 0) { 181 ALOGE("Track already in use"); 182 return INVALID_OPERATION; 183 } 184 185 if (pAttributes == NULL) { 186 memset(&mAttributes, 0, sizeof(audio_attributes_t)); 187 mAttributes.source = inputSource; 188 } else { 189 // stream type shouldn't be looked at, this track has audio attributes 190 memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t)); 191 ALOGV("Building AudioRecord with attributes: source=%d flags=0x%x tags=[%s]", 192 mAttributes.source, mAttributes.flags, mAttributes.tags); 193 } 194 195 mSampleRate = sampleRate; 196 197 // these below should probably come from the audioFlinger too... 198 if (format == AUDIO_FORMAT_DEFAULT) { 199 format = AUDIO_FORMAT_PCM_16_BIT; 200 } 201 202 // validate parameters 203 // AudioFlinger capture only supports linear PCM 204 if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) { 205 ALOGE("Format %#x is not linear pcm", format); 206 return BAD_VALUE; 207 } 208 mFormat = format; 209 210 if (!audio_is_input_channel(channelMask)) { 211 ALOGE("Invalid channel mask %#x", channelMask); 212 return BAD_VALUE; 213 } 214 mChannelMask = channelMask; 215 uint32_t channelCount = audio_channel_count_from_in_mask(channelMask); 216 mChannelCount = channelCount; 217 218 if (audio_is_linear_pcm(format)) { 219 mFrameSize = channelCount * audio_bytes_per_sample(format); 220 } else { 221 mFrameSize = sizeof(uint8_t); 222 } 223 224 // mFrameCount is initialized in openRecord_l 225 mReqFrameCount = frameCount; 226 227 mNotificationFramesReq = notificationFrames; 228 // mNotificationFramesAct is initialized in openRecord_l 229 230 if (sessionId == AUDIO_SESSION_ALLOCATE) { 231 mSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION); 232 } else { 233 mSessionId = sessionId; 234 } 235 ALOGV("set(): mSessionId %d", mSessionId); 236 237 int callingpid = IPCThreadState::self()->getCallingPid(); 238 int mypid = getpid(); 239 if (uid == -1 || (callingpid != mypid)) { 240 mClientUid = IPCThreadState::self()->getCallingUid(); 241 } else { 242 mClientUid = uid; 243 } 244 if (pid == -1 || (callingpid != mypid)) { 245 mClientPid = callingpid; 246 } else { 247 mClientPid = pid; 248 } 249 250 mOrigFlags = mFlags = flags; 251 mCbf = cbf; 252 253 if (cbf != NULL) { 254 mAudioRecordThread = new AudioRecordThread(*this, threadCanCallJava); 255 mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO); 256 // thread begins in paused state, and will not reference us until start() 257 } 258 259 // create the IAudioRecord 260 status_t status = openRecord_l(0 /*epoch*/, mOpPackageName); 261 262 if (status != NO_ERROR) { 263 if (mAudioRecordThread != 0) { 264 mAudioRecordThread->requestExit(); // see comment in AudioRecord.h 265 mAudioRecordThread->requestExitAndWait(); 266 mAudioRecordThread.clear(); 267 } 268 return status; 269 } 270 271 mStatus = NO_ERROR; 272 mUserData = user; 273 // TODO: add audio hardware input latency here 274 mLatency = (1000 * mFrameCount) / mSampleRate; 275 mMarkerPosition = 0; 276 mMarkerReached = false; 277 mNewPosition = 0; 278 mUpdatePeriod = 0; 279 AudioSystem::acquireAudioSessionId(mSessionId, -1); 280 mSequence = 1; 281 mObservedSequence = mSequence; 282 mInOverrun = false; 283 mFramesRead = 0; 284 mFramesReadServerOffset = 0; 285 286 return NO_ERROR; 287 } 288 289 // ------------------------------------------------------------------------- 290 291 status_t AudioRecord::start(AudioSystem::sync_event_t event, audio_session_t triggerSession) 292 { 293 ALOGV("start, sync event %d trigger session %d", event, triggerSession); 294 295 AutoMutex lock(mLock); 296 if (mActive) { 297 return NO_ERROR; 298 } 299 300 // discard data in buffer 301 const uint32_t framesFlushed = mProxy->flush(); 302 mFramesReadServerOffset -= mFramesRead + framesFlushed; 303 mFramesRead = 0; 304 mProxy->clearTimestamp(); // timestamp is invalid until next server push 305 306 // reset current position as seen by client to 0 307 mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition()); 308 // force refresh of remaining frames by processAudioBuffer() as last 309 // read before stop could be partial. 310 mRefreshRemaining = true; 311 312 mNewPosition = mProxy->getPosition() + mUpdatePeriod; 313 int32_t flags = android_atomic_acquire_load(&mCblk->mFlags); 314 315 // we reactivate markers (mMarkerPosition != 0) as the position is reset to 0. 316 // This is legacy behavior. This is not done in stop() to avoid a race condition 317 // where the last marker event is issued twice. 318 mMarkerReached = false; 319 mActive = true; 320 321 status_t status = NO_ERROR; 322 if (!(flags & CBLK_INVALID)) { 323 status = mAudioRecord->start(event, triggerSession); 324 if (status == DEAD_OBJECT) { 325 flags |= CBLK_INVALID; 326 } 327 } 328 if (flags & CBLK_INVALID) { 329 status = restoreRecord_l("start"); 330 } 331 332 if (status != NO_ERROR) { 333 mActive = false; 334 ALOGE("start() status %d", status); 335 } else { 336 sp<AudioRecordThread> t = mAudioRecordThread; 337 if (t != 0) { 338 t->resume(); 339 } else { 340 mPreviousPriority = getpriority(PRIO_PROCESS, 0); 341 get_sched_policy(0, &mPreviousSchedulingGroup); 342 androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 343 } 344 } 345 346 return status; 347 } 348 349 void AudioRecord::stop() 350 { 351 AutoMutex lock(mLock); 352 if (!mActive) { 353 return; 354 } 355 356 mActive = false; 357 mProxy->interrupt(); 358 mAudioRecord->stop(); 359 360 // Note: legacy handling - stop does not clear record marker and 361 // periodic update position; we update those on start(). 362 363 sp<AudioRecordThread> t = mAudioRecordThread; 364 if (t != 0) { 365 t->pause(); 366 } else { 367 setpriority(PRIO_PROCESS, 0, mPreviousPriority); 368 set_sched_policy(0, mPreviousSchedulingGroup); 369 } 370 } 371 372 bool AudioRecord::stopped() const 373 { 374 AutoMutex lock(mLock); 375 return !mActive; 376 } 377 378 status_t AudioRecord::setMarkerPosition(uint32_t marker) 379 { 380 // The only purpose of setting marker position is to get a callback 381 if (mCbf == NULL) { 382 return INVALID_OPERATION; 383 } 384 385 AutoMutex lock(mLock); 386 mMarkerPosition = marker; 387 mMarkerReached = false; 388 389 sp<AudioRecordThread> t = mAudioRecordThread; 390 if (t != 0) { 391 t->wake(); 392 } 393 return NO_ERROR; 394 } 395 396 status_t AudioRecord::getMarkerPosition(uint32_t *marker) const 397 { 398 if (marker == NULL) { 399 return BAD_VALUE; 400 } 401 402 AutoMutex lock(mLock); 403 mMarkerPosition.getValue(marker); 404 405 return NO_ERROR; 406 } 407 408 status_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod) 409 { 410 // The only purpose of setting position update period is to get a callback 411 if (mCbf == NULL) { 412 return INVALID_OPERATION; 413 } 414 415 AutoMutex lock(mLock); 416 mNewPosition = mProxy->getPosition() + updatePeriod; 417 mUpdatePeriod = updatePeriod; 418 419 sp<AudioRecordThread> t = mAudioRecordThread; 420 if (t != 0) { 421 t->wake(); 422 } 423 return NO_ERROR; 424 } 425 426 status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const 427 { 428 if (updatePeriod == NULL) { 429 return BAD_VALUE; 430 } 431 432 AutoMutex lock(mLock); 433 *updatePeriod = mUpdatePeriod; 434 435 return NO_ERROR; 436 } 437 438 status_t AudioRecord::getPosition(uint32_t *position) const 439 { 440 if (position == NULL) { 441 return BAD_VALUE; 442 } 443 444 AutoMutex lock(mLock); 445 mProxy->getPosition().getValue(position); 446 447 return NO_ERROR; 448 } 449 450 uint32_t AudioRecord::getInputFramesLost() const 451 { 452 // no need to check mActive, because if inactive this will return 0, which is what we want 453 return AudioSystem::getInputFramesLost(getInputPrivate()); 454 } 455 456 status_t AudioRecord::getTimestamp(ExtendedTimestamp *timestamp) 457 { 458 if (timestamp == nullptr) { 459 return BAD_VALUE; 460 } 461 AutoMutex lock(mLock); 462 status_t status = mProxy->getTimestamp(timestamp); 463 if (status == OK) { 464 timestamp->mPosition[ExtendedTimestamp::LOCATION_CLIENT] = mFramesRead; 465 timestamp->mTimeNs[ExtendedTimestamp::LOCATION_CLIENT] = 0; 466 // server side frame offset in case AudioRecord has been restored. 467 for (int i = ExtendedTimestamp::LOCATION_SERVER; 468 i < ExtendedTimestamp::LOCATION_MAX; ++i) { 469 if (timestamp->mTimeNs[i] >= 0) { 470 timestamp->mPosition[i] += mFramesReadServerOffset; 471 } 472 } 473 } 474 return status; 475 } 476 477 // ---- Explicit Routing --------------------------------------------------- 478 status_t AudioRecord::setInputDevice(audio_port_handle_t deviceId) { 479 AutoMutex lock(mLock); 480 if (mSelectedDeviceId != deviceId) { 481 mSelectedDeviceId = deviceId; 482 // stop capture so that audio policy manager does not reject the new instance start request 483 // as only one capture can be active at a time. 484 if (mAudioRecord != 0 && mActive) { 485 mAudioRecord->stop(); 486 } 487 android_atomic_or(CBLK_INVALID, &mCblk->mFlags); 488 } 489 return NO_ERROR; 490 } 491 492 audio_port_handle_t AudioRecord::getInputDevice() { 493 AutoMutex lock(mLock); 494 return mSelectedDeviceId; 495 } 496 497 audio_port_handle_t AudioRecord::getRoutedDeviceId() { 498 AutoMutex lock(mLock); 499 if (mInput == AUDIO_IO_HANDLE_NONE) { 500 return AUDIO_PORT_HANDLE_NONE; 501 } 502 return AudioSystem::getDeviceIdForIo(mInput); 503 } 504 505 // ------------------------------------------------------------------------- 506 507 // must be called with mLock held 508 status_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16& opPackageName) 509 { 510 const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); 511 if (audioFlinger == 0) { 512 ALOGE("Could not get audioflinger"); 513 return NO_INIT; 514 } 515 516 if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) { 517 AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); 518 } 519 audio_io_handle_t input; 520 521 // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted. 522 // After fast request is denied, we will request again if IAudioRecord is re-created. 523 524 status_t status; 525 526 // Not a conventional loop, but a retry loop for at most two iterations total. 527 // Try first maybe with FAST flag then try again without FAST flag if that fails. 528 // Exits loop normally via a return at the bottom, or with error via a break. 529 // The sp<> references will be dropped when re-entering scope. 530 // The lack of indentation is deliberate, to reduce code churn and ease merges. 531 for (;;) { 532 533 status = AudioSystem::getInputForAttr(&mAttributes, &input, 534 mSessionId, 535 // FIXME compare to AudioTrack 536 mClientPid, 537 mClientUid, 538 mSampleRate, mFormat, mChannelMask, 539 mFlags, mSelectedDeviceId); 540 541 if (status != NO_ERROR || input == AUDIO_IO_HANDLE_NONE) { 542 ALOGE("Could not get audio input for session %d, record source %d, sample rate %u, " 543 "format %#x, channel mask %#x, flags %#x", 544 mSessionId, mAttributes.source, mSampleRate, mFormat, mChannelMask, mFlags); 545 return BAD_VALUE; 546 } 547 548 // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger, 549 // we must release it ourselves if anything goes wrong. 550 551 #if 0 552 size_t afFrameCount; 553 status = AudioSystem::getFrameCount(input, &afFrameCount); 554 if (status != NO_ERROR) { 555 ALOGE("getFrameCount(input=%d) status %d", input, status); 556 break; 557 } 558 #endif 559 560 uint32_t afSampleRate; 561 status = AudioSystem::getSamplingRate(input, &afSampleRate); 562 if (status != NO_ERROR) { 563 ALOGE("getSamplingRate(input=%d) status %d", input, status); 564 break; 565 } 566 if (mSampleRate == 0) { 567 mSampleRate = afSampleRate; 568 } 569 570 // Client can only express a preference for FAST. Server will perform additional tests. 571 if (mFlags & AUDIO_INPUT_FLAG_FAST) { 572 bool useCaseAllowed = 573 // either of these use cases: 574 // use case 1: callback transfer mode 575 (mTransfer == TRANSFER_CALLBACK) || 576 // use case 2: obtain/release mode 577 (mTransfer == TRANSFER_OBTAIN); 578 // sample rates must also match 579 bool fastAllowed = useCaseAllowed && (mSampleRate == afSampleRate); 580 if (!fastAllowed) { 581 ALOGW("AUDIO_INPUT_FLAG_FAST denied by client; transfer %d, " 582 "track %u Hz, input %u Hz", 583 mTransfer, mSampleRate, afSampleRate); 584 mFlags = (audio_input_flags_t) (mFlags & ~(AUDIO_INPUT_FLAG_FAST | 585 AUDIO_INPUT_FLAG_RAW)); 586 AudioSystem::releaseInput(input, mSessionId); 587 continue; // retry 588 } 589 } 590 591 // The notification frame count is the period between callbacks, as suggested by the client 592 // but moderated by the server. For record, the calculations are done entirely on server side. 593 size_t notificationFrames = mNotificationFramesReq; 594 size_t frameCount = mReqFrameCount; 595 596 audio_input_flags_t flags = mFlags; 597 598 pid_t tid = -1; 599 if (mFlags & AUDIO_INPUT_FLAG_FAST) { 600 if (mAudioRecordThread != 0) { 601 tid = mAudioRecordThread->getTid(); 602 } 603 } 604 605 size_t temp = frameCount; // temp may be replaced by a revised value of frameCount, 606 // but we will still need the original value also 607 audio_session_t originalSessionId = mSessionId; 608 609 sp<IMemory> iMem; // for cblk 610 sp<IMemory> bufferMem; 611 sp<IAudioRecord> record = audioFlinger->openRecord(input, 612 mSampleRate, 613 mFormat, 614 mChannelMask, 615 opPackageName, 616 &temp, 617 &flags, 618 mClientPid, 619 tid, 620 mClientUid, 621 &mSessionId, 622 ¬ificationFrames, 623 iMem, 624 bufferMem, 625 &status); 626 ALOGE_IF(originalSessionId != AUDIO_SESSION_ALLOCATE && mSessionId != originalSessionId, 627 "session ID changed from %d to %d", originalSessionId, mSessionId); 628 629 if (status != NO_ERROR) { 630 ALOGE("AudioFlinger could not create record track, status: %d", status); 631 break; 632 } 633 ALOG_ASSERT(record != 0); 634 635 // AudioFlinger now owns the reference to the I/O handle, 636 // so we are no longer responsible for releasing it. 637 638 mAwaitBoost = false; 639 if (mFlags & AUDIO_INPUT_FLAG_FAST) { 640 if (flags & AUDIO_INPUT_FLAG_FAST) { 641 ALOGI("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu", frameCount); 642 mAwaitBoost = true; 643 } else { 644 ALOGW("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %zu", frameCount); 645 mFlags = (audio_input_flags_t) (mFlags & ~(AUDIO_INPUT_FLAG_FAST | 646 AUDIO_INPUT_FLAG_RAW)); 647 continue; // retry 648 } 649 } 650 mFlags = flags; 651 652 if (iMem == 0) { 653 ALOGE("Could not get control block"); 654 return NO_INIT; 655 } 656 void *iMemPointer = iMem->pointer(); 657 if (iMemPointer == NULL) { 658 ALOGE("Could not get control block pointer"); 659 return NO_INIT; 660 } 661 audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer); 662 663 // Starting address of buffers in shared memory. 664 // The buffers are either immediately after the control block, 665 // or in a separate area at discretion of server. 666 void *buffers; 667 if (bufferMem == 0) { 668 buffers = cblk + 1; 669 } else { 670 buffers = bufferMem->pointer(); 671 if (buffers == NULL) { 672 ALOGE("Could not get buffer pointer"); 673 return NO_INIT; 674 } 675 } 676 677 // invariant that mAudioRecord != 0 is true only after set() returns successfully 678 if (mAudioRecord != 0) { 679 IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this); 680 mDeathNotifier.clear(); 681 } 682 mAudioRecord = record; 683 mCblkMemory = iMem; 684 mBufferMemory = bufferMem; 685 IPCThreadState::self()->flushCommands(); 686 687 mCblk = cblk; 688 // note that temp is the (possibly revised) value of frameCount 689 if (temp < frameCount || (frameCount == 0 && temp == 0)) { 690 ALOGW("Requested frameCount %zu but received frameCount %zu", frameCount, temp); 691 } 692 frameCount = temp; 693 694 // Make sure that application is notified with sufficient margin before overrun. 695 // The computation is done on server side. 696 if (mNotificationFramesReq > 0 && notificationFrames != mNotificationFramesReq) { 697 ALOGW("Server adjusted notificationFrames from %u to %zu for frameCount %zu", 698 mNotificationFramesReq, notificationFrames, frameCount); 699 } 700 mNotificationFramesAct = (uint32_t) notificationFrames; 701 702 // We retain a copy of the I/O handle, but don't own the reference 703 mInput = input; 704 mRefreshRemaining = true; 705 706 mFrameCount = frameCount; 707 // If IAudioRecord is re-created, don't let the requested frameCount 708 // decrease. This can confuse clients that cache frameCount(). 709 if (frameCount > mReqFrameCount) { 710 mReqFrameCount = frameCount; 711 } 712 713 // update proxy 714 mProxy = new AudioRecordClientProxy(cblk, buffers, mFrameCount, mFrameSize); 715 mProxy->setEpoch(epoch); 716 mProxy->setMinimum(mNotificationFramesAct); 717 718 mDeathNotifier = new DeathNotifier(this); 719 IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this); 720 721 if (mDeviceCallback != 0) { 722 AudioSystem::addAudioDeviceCallback(mDeviceCallback, mInput); 723 } 724 725 return NO_ERROR; 726 727 // End of retry loop. 728 // The lack of indentation is deliberate, to reduce code churn and ease merges. 729 } 730 731 // Arrive here on error, via a break 732 AudioSystem::releaseInput(input, mSessionId); 733 if (status == NO_ERROR) { 734 status = NO_INIT; 735 } 736 return status; 737 } 738 739 status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount, size_t *nonContig) 740 { 741 if (audioBuffer == NULL) { 742 if (nonContig != NULL) { 743 *nonContig = 0; 744 } 745 return BAD_VALUE; 746 } 747 if (mTransfer != TRANSFER_OBTAIN) { 748 audioBuffer->frameCount = 0; 749 audioBuffer->size = 0; 750 audioBuffer->raw = NULL; 751 if (nonContig != NULL) { 752 *nonContig = 0; 753 } 754 return INVALID_OPERATION; 755 } 756 757 const struct timespec *requested; 758 struct timespec timeout; 759 if (waitCount == -1) { 760 requested = &ClientProxy::kForever; 761 } else if (waitCount == 0) { 762 requested = &ClientProxy::kNonBlocking; 763 } else if (waitCount > 0) { 764 long long ms = WAIT_PERIOD_MS * (long long) waitCount; 765 timeout.tv_sec = ms / 1000; 766 timeout.tv_nsec = (int) (ms % 1000) * 1000000; 767 requested = &timeout; 768 } else { 769 ALOGE("%s invalid waitCount %d", __func__, waitCount); 770 requested = NULL; 771 } 772 return obtainBuffer(audioBuffer, requested, NULL /*elapsed*/, nonContig); 773 } 774 775 status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *requested, 776 struct timespec *elapsed, size_t *nonContig) 777 { 778 // previous and new IAudioRecord sequence numbers are used to detect track re-creation 779 uint32_t oldSequence = 0; 780 uint32_t newSequence; 781 782 Proxy::Buffer buffer; 783 status_t status = NO_ERROR; 784 785 static const int32_t kMaxTries = 5; 786 int32_t tryCounter = kMaxTries; 787 788 do { 789 // obtainBuffer() is called with mutex unlocked, so keep extra references to these fields to 790 // keep them from going away if another thread re-creates the track during obtainBuffer() 791 sp<AudioRecordClientProxy> proxy; 792 sp<IMemory> iMem; 793 sp<IMemory> bufferMem; 794 { 795 // start of lock scope 796 AutoMutex lock(mLock); 797 798 newSequence = mSequence; 799 // did previous obtainBuffer() fail due to media server death or voluntary invalidation? 800 if (status == DEAD_OBJECT) { 801 // re-create track, unless someone else has already done so 802 if (newSequence == oldSequence) { 803 status = restoreRecord_l("obtainBuffer"); 804 if (status != NO_ERROR) { 805 buffer.mFrameCount = 0; 806 buffer.mRaw = NULL; 807 buffer.mNonContig = 0; 808 break; 809 } 810 } 811 } 812 oldSequence = newSequence; 813 814 // Keep the extra references 815 proxy = mProxy; 816 iMem = mCblkMemory; 817 bufferMem = mBufferMemory; 818 819 // Non-blocking if track is stopped 820 if (!mActive) { 821 requested = &ClientProxy::kNonBlocking; 822 } 823 824 } // end of lock scope 825 826 buffer.mFrameCount = audioBuffer->frameCount; 827 // FIXME starts the requested timeout and elapsed over from scratch 828 status = proxy->obtainBuffer(&buffer, requested, elapsed); 829 830 } while ((status == DEAD_OBJECT) && (tryCounter-- > 0)); 831 832 audioBuffer->frameCount = buffer.mFrameCount; 833 audioBuffer->size = buffer.mFrameCount * mFrameSize; 834 audioBuffer->raw = buffer.mRaw; 835 if (nonContig != NULL) { 836 *nonContig = buffer.mNonContig; 837 } 838 return status; 839 } 840 841 void AudioRecord::releaseBuffer(const Buffer* audioBuffer) 842 { 843 // FIXME add error checking on mode, by adding an internal version 844 845 size_t stepCount = audioBuffer->size / mFrameSize; 846 if (stepCount == 0) { 847 return; 848 } 849 850 Proxy::Buffer buffer; 851 buffer.mFrameCount = stepCount; 852 buffer.mRaw = audioBuffer->raw; 853 854 AutoMutex lock(mLock); 855 mInOverrun = false; 856 mProxy->releaseBuffer(&buffer); 857 858 // the server does not automatically disable recorder on overrun, so no need to restart 859 } 860 861 audio_io_handle_t AudioRecord::getInputPrivate() const 862 { 863 AutoMutex lock(mLock); 864 return mInput; 865 } 866 867 // ------------------------------------------------------------------------- 868 869 ssize_t AudioRecord::read(void* buffer, size_t userSize, bool blocking) 870 { 871 if (mTransfer != TRANSFER_SYNC) { 872 return INVALID_OPERATION; 873 } 874 875 if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) { 876 // sanity-check. user is most-likely passing an error code, and it would 877 // make the return value ambiguous (actualSize vs error). 878 ALOGE("AudioRecord::read(buffer=%p, size=%zu (%zu)", buffer, userSize, userSize); 879 return BAD_VALUE; 880 } 881 882 ssize_t read = 0; 883 Buffer audioBuffer; 884 885 while (userSize >= mFrameSize) { 886 audioBuffer.frameCount = userSize / mFrameSize; 887 888 status_t err = obtainBuffer(&audioBuffer, 889 blocking ? &ClientProxy::kForever : &ClientProxy::kNonBlocking); 890 if (err < 0) { 891 if (read > 0) { 892 break; 893 } 894 if (err == TIMED_OUT || err == -EINTR) { 895 err = WOULD_BLOCK; 896 } 897 return ssize_t(err); 898 } 899 900 size_t bytesRead = audioBuffer.size; 901 memcpy(buffer, audioBuffer.i8, bytesRead); 902 buffer = ((char *) buffer) + bytesRead; 903 userSize -= bytesRead; 904 read += bytesRead; 905 906 releaseBuffer(&audioBuffer); 907 } 908 if (read > 0) { 909 mFramesRead += read / mFrameSize; 910 // mFramesReadTime = systemTime(SYSTEM_TIME_MONOTONIC); // not provided at this time. 911 } 912 return read; 913 } 914 915 // ------------------------------------------------------------------------- 916 917 nsecs_t AudioRecord::processAudioBuffer() 918 { 919 mLock.lock(); 920 if (mAwaitBoost) { 921 mAwaitBoost = false; 922 mLock.unlock(); 923 static const int32_t kMaxTries = 5; 924 int32_t tryCounter = kMaxTries; 925 uint32_t pollUs = 10000; 926 do { 927 int policy = sched_getscheduler(0) & ~SCHED_RESET_ON_FORK; 928 if (policy == SCHED_FIFO || policy == SCHED_RR) { 929 break; 930 } 931 usleep(pollUs); 932 pollUs <<= 1; 933 } while (tryCounter-- > 0); 934 if (tryCounter < 0) { 935 ALOGE("did not receive expected priority boost on time"); 936 } 937 // Run again immediately 938 return 0; 939 } 940 941 // Can only reference mCblk while locked 942 int32_t flags = android_atomic_and(~CBLK_OVERRUN, &mCblk->mFlags); 943 944 // Check for track invalidation 945 if (flags & CBLK_INVALID) { 946 (void) restoreRecord_l("processAudioBuffer"); 947 mLock.unlock(); 948 // Run again immediately, but with a new IAudioRecord 949 return 0; 950 } 951 952 bool active = mActive; 953 954 // Manage overrun callback, must be done under lock to avoid race with releaseBuffer() 955 bool newOverrun = false; 956 if (flags & CBLK_OVERRUN) { 957 if (!mInOverrun) { 958 mInOverrun = true; 959 newOverrun = true; 960 } 961 } 962 963 // Get current position of server 964 Modulo<uint32_t> position(mProxy->getPosition()); 965 966 // Manage marker callback 967 bool markerReached = false; 968 Modulo<uint32_t> markerPosition(mMarkerPosition); 969 // FIXME fails for wraparound, need 64 bits 970 if (!mMarkerReached && markerPosition.value() > 0 && position >= markerPosition) { 971 mMarkerReached = markerReached = true; 972 } 973 974 // Determine the number of new position callback(s) that will be needed, while locked 975 size_t newPosCount = 0; 976 Modulo<uint32_t> newPosition(mNewPosition); 977 uint32_t updatePeriod = mUpdatePeriod; 978 // FIXME fails for wraparound, need 64 bits 979 if (updatePeriod > 0 && position >= newPosition) { 980 newPosCount = ((position - newPosition).value() / updatePeriod) + 1; 981 mNewPosition += updatePeriod * newPosCount; 982 } 983 984 // Cache other fields that will be needed soon 985 uint32_t notificationFrames = mNotificationFramesAct; 986 if (mRefreshRemaining) { 987 mRefreshRemaining = false; 988 mRemainingFrames = notificationFrames; 989 mRetryOnPartialBuffer = false; 990 } 991 size_t misalignment = mProxy->getMisalignment(); 992 uint32_t sequence = mSequence; 993 994 // These fields don't need to be cached, because they are assigned only by set(): 995 // mTransfer, mCbf, mUserData, mSampleRate, mFrameSize 996 997 mLock.unlock(); 998 999 // perform callbacks while unlocked 1000 if (newOverrun) { 1001 mCbf(EVENT_OVERRUN, mUserData, NULL); 1002 } 1003 if (markerReached) { 1004 mCbf(EVENT_MARKER, mUserData, &markerPosition); 1005 } 1006 while (newPosCount > 0) { 1007 size_t temp = newPosition.value(); // FIXME size_t != uint32_t 1008 mCbf(EVENT_NEW_POS, mUserData, &temp); 1009 newPosition += updatePeriod; 1010 newPosCount--; 1011 } 1012 if (mObservedSequence != sequence) { 1013 mObservedSequence = sequence; 1014 mCbf(EVENT_NEW_IAUDIORECORD, mUserData, NULL); 1015 } 1016 1017 // if inactive, then don't run me again until re-started 1018 if (!active) { 1019 return NS_INACTIVE; 1020 } 1021 1022 // Compute the estimated time until the next timed event (position, markers) 1023 uint32_t minFrames = ~0; 1024 if (!markerReached && position < markerPosition) { 1025 minFrames = (markerPosition - position).value(); 1026 } 1027 if (updatePeriod > 0) { 1028 uint32_t remaining = (newPosition - position).value(); 1029 if (remaining < minFrames) { 1030 minFrames = remaining; 1031 } 1032 } 1033 1034 // If > 0, poll periodically to recover from a stuck server. A good value is 2. 1035 static const uint32_t kPoll = 0; 1036 if (kPoll > 0 && mTransfer == TRANSFER_CALLBACK && kPoll * notificationFrames < minFrames) { 1037 minFrames = kPoll * notificationFrames; 1038 } 1039 1040 // Convert frame units to time units 1041 nsecs_t ns = NS_WHENEVER; 1042 if (minFrames != (uint32_t) ~0) { 1043 // This "fudge factor" avoids soaking CPU, and compensates for late progress by server 1044 static const nsecs_t kFudgeNs = 10000000LL; // 10 ms 1045 ns = ((minFrames * 1000000000LL) / mSampleRate) + kFudgeNs; 1046 } 1047 1048 // If not supplying data by EVENT_MORE_DATA, then we're done 1049 if (mTransfer != TRANSFER_CALLBACK) { 1050 return ns; 1051 } 1052 1053 struct timespec timeout; 1054 const struct timespec *requested = &ClientProxy::kForever; 1055 if (ns != NS_WHENEVER) { 1056 timeout.tv_sec = ns / 1000000000LL; 1057 timeout.tv_nsec = ns % 1000000000LL; 1058 ALOGV("timeout %ld.%03d", timeout.tv_sec, (int) timeout.tv_nsec / 1000000); 1059 requested = &timeout; 1060 } 1061 1062 size_t readFrames = 0; 1063 while (mRemainingFrames > 0) { 1064 1065 Buffer audioBuffer; 1066 audioBuffer.frameCount = mRemainingFrames; 1067 size_t nonContig; 1068 status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig); 1069 LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0), 1070 "obtainBuffer() err=%d frameCount=%zu", err, audioBuffer.frameCount); 1071 requested = &ClientProxy::kNonBlocking; 1072 size_t avail = audioBuffer.frameCount + nonContig; 1073 ALOGV("obtainBuffer(%u) returned %zu = %zu + %zu err %d", 1074 mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err); 1075 if (err != NO_ERROR) { 1076 if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR) { 1077 break; 1078 } 1079 ALOGE("Error %d obtaining an audio buffer, giving up.", err); 1080 return NS_NEVER; 1081 } 1082 1083 if (mRetryOnPartialBuffer) { 1084 mRetryOnPartialBuffer = false; 1085 if (avail < mRemainingFrames) { 1086 int64_t myns = ((mRemainingFrames - avail) * 1087 1100000000LL) / mSampleRate; 1088 if (ns < 0 || myns < ns) { 1089 ns = myns; 1090 } 1091 return ns; 1092 } 1093 } 1094 1095 size_t reqSize = audioBuffer.size; 1096 mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); 1097 size_t readSize = audioBuffer.size; 1098 1099 // Sanity check on returned size 1100 if (ssize_t(readSize) < 0 || readSize > reqSize) { 1101 ALOGE("EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes", 1102 reqSize, ssize_t(readSize)); 1103 return NS_NEVER; 1104 } 1105 1106 if (readSize == 0) { 1107 // The callback is done consuming buffers 1108 // Keep this thread going to handle timed events and 1109 // still try to provide more data in intervals of WAIT_PERIOD_MS 1110 // but don't just loop and block the CPU, so wait 1111 return WAIT_PERIOD_MS * 1000000LL; 1112 } 1113 1114 size_t releasedFrames = readSize / mFrameSize; 1115 audioBuffer.frameCount = releasedFrames; 1116 mRemainingFrames -= releasedFrames; 1117 if (misalignment >= releasedFrames) { 1118 misalignment -= releasedFrames; 1119 } else { 1120 misalignment = 0; 1121 } 1122 1123 releaseBuffer(&audioBuffer); 1124 readFrames += releasedFrames; 1125 1126 // FIXME here is where we would repeat EVENT_MORE_DATA again on same advanced buffer 1127 // if callback doesn't like to accept the full chunk 1128 if (readSize < reqSize) { 1129 continue; 1130 } 1131 1132 // There could be enough non-contiguous frames available to satisfy the remaining request 1133 if (mRemainingFrames <= nonContig) { 1134 continue; 1135 } 1136 1137 #if 0 1138 // This heuristic tries to collapse a series of EVENT_MORE_DATA that would total to a 1139 // sum <= notificationFrames. It replaces that series by at most two EVENT_MORE_DATA 1140 // that total to a sum == notificationFrames. 1141 if (0 < misalignment && misalignment <= mRemainingFrames) { 1142 mRemainingFrames = misalignment; 1143 return (mRemainingFrames * 1100000000LL) / mSampleRate; 1144 } 1145 #endif 1146 1147 } 1148 if (readFrames > 0) { 1149 AutoMutex lock(mLock); 1150 mFramesRead += readFrames; 1151 // mFramesReadTime = systemTime(SYSTEM_TIME_MONOTONIC); // not provided at this time. 1152 } 1153 mRemainingFrames = notificationFrames; 1154 mRetryOnPartialBuffer = true; 1155 1156 // A lot has transpired since ns was calculated, so run again immediately and re-calculate 1157 return 0; 1158 } 1159 1160 status_t AudioRecord::restoreRecord_l(const char *from) 1161 { 1162 ALOGW("dead IAudioRecord, creating a new one from %s()", from); 1163 ++mSequence; 1164 1165 mFlags = mOrigFlags; 1166 1167 // if the new IAudioRecord is created, openRecord_l() will modify the 1168 // following member variables: mAudioRecord, mCblkMemory, mCblk, mBufferMemory. 1169 // It will also delete the strong references on previous IAudioRecord and IMemory 1170 Modulo<uint32_t> position(mProxy->getPosition()); 1171 mNewPosition = position + mUpdatePeriod; 1172 status_t result = openRecord_l(position, mOpPackageName); 1173 if (result == NO_ERROR) { 1174 if (mActive) { 1175 // callback thread or sync event hasn't changed 1176 // FIXME this fails if we have a new AudioFlinger instance 1177 result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, AUDIO_SESSION_NONE); 1178 } 1179 mFramesReadServerOffset = mFramesRead; // server resets to zero so we need an offset. 1180 } 1181 if (result != NO_ERROR) { 1182 ALOGW("restoreRecord_l() failed status %d", result); 1183 mActive = false; 1184 } 1185 1186 return result; 1187 } 1188 1189 status_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback) 1190 { 1191 if (callback == 0) { 1192 ALOGW("%s adding NULL callback!", __FUNCTION__); 1193 return BAD_VALUE; 1194 } 1195 AutoMutex lock(mLock); 1196 if (mDeviceCallback == callback) { 1197 ALOGW("%s adding same callback!", __FUNCTION__); 1198 return INVALID_OPERATION; 1199 } 1200 status_t status = NO_ERROR; 1201 if (mInput != AUDIO_IO_HANDLE_NONE) { 1202 if (mDeviceCallback != 0) { 1203 ALOGW("%s callback already present!", __FUNCTION__); 1204 AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); 1205 } 1206 status = AudioSystem::addAudioDeviceCallback(callback, mInput); 1207 } 1208 mDeviceCallback = callback; 1209 return status; 1210 } 1211 1212 status_t AudioRecord::removeAudioDeviceCallback( 1213 const sp<AudioSystem::AudioDeviceCallback>& callback) 1214 { 1215 if (callback == 0) { 1216 ALOGW("%s removing NULL callback!", __FUNCTION__); 1217 return BAD_VALUE; 1218 } 1219 AutoMutex lock(mLock); 1220 if (mDeviceCallback != callback) { 1221 ALOGW("%s removing different callback!", __FUNCTION__); 1222 return INVALID_OPERATION; 1223 } 1224 if (mInput != AUDIO_IO_HANDLE_NONE) { 1225 AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput); 1226 } 1227 mDeviceCallback = 0; 1228 return NO_ERROR; 1229 } 1230 1231 // ========================================================================= 1232 1233 void AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused) 1234 { 1235 sp<AudioRecord> audioRecord = mAudioRecord.promote(); 1236 if (audioRecord != 0) { 1237 AutoMutex lock(audioRecord->mLock); 1238 audioRecord->mProxy->binderDied(); 1239 } 1240 } 1241 1242 // ========================================================================= 1243 1244 AudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver, bool bCanCallJava) 1245 : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mPausedInt(false), mPausedNs(0LL), 1246 mIgnoreNextPausedInt(false) 1247 { 1248 } 1249 1250 AudioRecord::AudioRecordThread::~AudioRecordThread() 1251 { 1252 } 1253 1254 bool AudioRecord::AudioRecordThread::threadLoop() 1255 { 1256 { 1257 AutoMutex _l(mMyLock); 1258 if (mPaused) { 1259 mMyCond.wait(mMyLock); 1260 // caller will check for exitPending() 1261 return true; 1262 } 1263 if (mIgnoreNextPausedInt) { 1264 mIgnoreNextPausedInt = false; 1265 mPausedInt = false; 1266 } 1267 if (mPausedInt) { 1268 if (mPausedNs > 0) { 1269 (void) mMyCond.waitRelative(mMyLock, mPausedNs); 1270 } else { 1271 mMyCond.wait(mMyLock); 1272 } 1273 mPausedInt = false; 1274 return true; 1275 } 1276 } 1277 nsecs_t ns = mReceiver.processAudioBuffer(); 1278 switch (ns) { 1279 case 0: 1280 return true; 1281 case NS_INACTIVE: 1282 pauseInternal(); 1283 return true; 1284 case NS_NEVER: 1285 return false; 1286 case NS_WHENEVER: 1287 // Event driven: call wake() when callback notifications conditions change. 1288 ns = INT64_MAX; 1289 // fall through 1290 default: 1291 LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %" PRId64, ns); 1292 pauseInternal(ns); 1293 return true; 1294 } 1295 } 1296 1297 void AudioRecord::AudioRecordThread::requestExit() 1298 { 1299 // must be in this order to avoid a race condition 1300 Thread::requestExit(); 1301 resume(); 1302 } 1303 1304 void AudioRecord::AudioRecordThread::pause() 1305 { 1306 AutoMutex _l(mMyLock); 1307 mPaused = true; 1308 } 1309 1310 void AudioRecord::AudioRecordThread::resume() 1311 { 1312 AutoMutex _l(mMyLock); 1313 mIgnoreNextPausedInt = true; 1314 if (mPaused || mPausedInt) { 1315 mPaused = false; 1316 mPausedInt = false; 1317 mMyCond.signal(); 1318 } 1319 } 1320 1321 void AudioRecord::AudioRecordThread::wake() 1322 { 1323 AutoMutex _l(mMyLock); 1324 if (!mPaused) { 1325 // wake() might be called while servicing a callback - ignore the next 1326 // pause time and call processAudioBuffer. 1327 mIgnoreNextPausedInt = true; 1328 if (mPausedInt && mPausedNs > 0) { 1329 // audio record is active and internally paused with timeout. 1330 mPausedInt = false; 1331 mMyCond.signal(); 1332 } 1333 } 1334 } 1335 1336 void AudioRecord::AudioRecordThread::pauseInternal(nsecs_t ns) 1337 { 1338 AutoMutex _l(mMyLock); 1339 mPausedInt = true; 1340 mPausedNs = ns; 1341 } 1342 1343 // ------------------------------------------------------------------------- 1344 1345 } // namespace android 1346