189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project/* 289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** 389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Copyright 2008, The Android Open Source Project 489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** 589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** you may not use this file except in compliance with the License. 789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** You may obtain a copy of the License at 889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** 989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 1089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** 1189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 1289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 1389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** See the License for the specific language governing permissions and 1589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** limitations under the License. 1689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project*/ 1789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 1889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project//#define LOG_NDEBUG 0 1989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#define LOG_TAG "AudioRecord" 2089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 2134fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn#include <inttypes.h> 2289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <sys/resource.h> 2334fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn 24868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <binder/IPCThreadState.h> 2589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/AudioRecord.h> 2689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <utils/Log.h> 27868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <private/media/AudioTrackShared.h> 281ab85ec401801ef9a9184650d0f5a1639b45eeb9Glenn Kasten#include <media/IAudioFlinger.h> 2989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#define WAIT_PERIOD_MS 10 319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 3289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectnamespace android { 3315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh// --------------------------------------------------------------------------- 3415304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh 3515304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh// static 3615304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yehstatus_t AudioRecord::getMinFrameCount( 37e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten size_t* frameCount, 3815304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh uint32_t sampleRate, 3958f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten audio_format_t format, 40dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten audio_channel_mask_t channelMask) 4115304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh{ 429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (frameCount == NULL) { 439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 4504cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten 46b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten size_t size; 47c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten status_t status = AudioSystem::getInputBufferSize(sampleRate, format, channelMask, &size); 48c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten if (status != NO_ERROR) { 49b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten ALOGE("AudioSystem could not query the input buffer size for sampleRate %u, format %#x, " 50b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten "channelMask %#x; status %d", sampleRate, format, channelMask, status); 51b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten return status; 5215304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh } 5315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh 54b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten // We double the size of input buffer for ping pong use of record buffer. 55b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten // Assumes audio_is_linear_pcm(format) 56e541269be94f3a1072932d51537905b120ef4733Andy Hung if ((*frameCount = (size * 2) / (audio_channel_count_from_in_mask(channelMask) * 57e541269be94f3a1072932d51537905b120ef4733Andy Hung audio_bytes_per_sample(format))) == 0) { 58cac3daa6332bf6d1f7d26adc4a9915f3d7992dd9Glenn Kasten ALOGE("Unsupported configuration: sampleRate %u, format %#x, channelMask %#x", 59dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten sampleRate, format, channelMask); 6015304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh return BAD_VALUE; 6115304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh } 6215304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh 6315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh return NO_ERROR; 6415304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh} 6589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 6689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// --------------------------------------------------------------------------- 6789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 6889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::AudioRecord() 69aea7ea06394bcb155972d82055d4ea59962e4051Glenn Kasten : mStatus(NO_INIT), mSessionId(AUDIO_SESSION_ALLOCATE), 709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) 7189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 7289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 7389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 7489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::AudioRecord( 75eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten audio_source_t inputSource, 7689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project uint32_t sampleRate, 7758f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten audio_format_t format, 78624a7fcb377f2a40109c16de5109ae8ea1f67a69Glenn Kasten audio_channel_mask_t channelMask, 79bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten size_t frameCount, 8089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project callback_t cbf, 8189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project void* user, 82838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten uint32_t notificationFrames, 839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int sessionId, 8427f7b2a8fe899565487d8a326676a5f7d0a05a37Glenn Kasten transfer_type transferType, 85caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent audio_input_flags_t flags, 86caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent const audio_attributes_t* pAttributes) 87aea7ea06394bcb155972d82055d4ea59962e4051Glenn Kasten : mStatus(NO_INIT), mSessionId(AUDIO_SESSION_ALLOCATE), 88e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten mPreviousPriority(ANDROID_PRIORITY_NORMAL), 89e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten mPreviousSchedulingGroup(SP_DEFAULT), 90e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten mProxy(NULL) 9189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user, 93caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags, 94caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent pAttributes); 9589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 9689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 9789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::~AudioRecord() 9889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 9989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (mStatus == NO_ERROR) { 10089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // Make sure that callback function exits in the case where 10189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // it is looping on buffer empty condition in obtainBuffer(). 10289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // Otherwise the callback thread will never exit. 10389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project stop(); 10468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten if (mAudioRecordThread != 0) { 1055a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten mProxy->interrupt(); 10668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mAudioRecordThread->requestExit(); // see comment in AudioRecord.h 10768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mAudioRecordThread->requestExitAndWait(); 10868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mAudioRecordThread.clear(); 10989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 110089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this); 111089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten mAudioRecord.clear(); 1123bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent mCblkMemory.clear(); 1133bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent mBufferMemory.clear(); 11489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project IPCThreadState::self()->flushCommands(); 115d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen AudioSystem::releaseAudioSessionId(mSessionId, -1); 11689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 11789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 11889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 11989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::set( 120eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten audio_source_t inputSource, 12189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project uint32_t sampleRate, 12258f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten audio_format_t format, 123624a7fcb377f2a40109c16de5109ae8ea1f67a69Glenn Kasten audio_channel_mask_t channelMask, 124bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten size_t frameCount, 12589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project callback_t cbf, 12689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project void* user, 127838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten uint32_t notificationFrames, 128be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent bool threadCanCallJava, 1299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int sessionId, 13027f7b2a8fe899565487d8a326676a5f7d0a05a37Glenn Kasten transfer_type transferType, 131caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent audio_input_flags_t flags, 132caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent const audio_attributes_t* pAttributes) 13389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 134bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, " 135838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten "notificationFrames %u, sessionId %d, transferType %d, flags %#x", 136bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten inputSource, sampleRate, format, channelMask, frameCount, notificationFrames, 13786f04663032ddaa25110149d709bbf896ad83b02Glenn Kasten sessionId, transferType, flags); 13886f04663032ddaa25110149d709bbf896ad83b02Glenn Kasten 1399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten switch (transferType) { 1409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TRANSFER_DEFAULT: 1419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (cbf == NULL || threadCanCallJava) { 1429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten transferType = TRANSFER_SYNC; 1439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 1449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten transferType = TRANSFER_CALLBACK; 1459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 1479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TRANSFER_CALLBACK: 1489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (cbf == NULL) { 1499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Transfer type TRANSFER_CALLBACK but cbf == NULL"); 1509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 1519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 1539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TRANSFER_OBTAIN: 1549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TRANSFER_SYNC: 1559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 1569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten default: 1579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Invalid transfer type %d", transferType); 1589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 1599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mTransfer = transferType; 1619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 1621703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent AutoMutex lock(mLock); 1631703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 164089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten // invariant that mAudioRecord != 0 is true only after set() returns successfully 1651dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent if (mAudioRecord != 0) { 1669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Track already in use"); 16789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return INVALID_OPERATION; 16889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 16989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 170caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent if (pAttributes == NULL) { 171caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent memset(&mAttributes, 0, sizeof(audio_attributes_t)); 172caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent mAttributes.source = inputSource; 173caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent } else { 174caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent // stream type shouldn't be looked at, this track has audio attributes 175caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t)); 176caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent ALOGV("Building AudioRecord with attributes: source=%d flags=0x%x tags=[%s]", 177caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent mAttributes.source, mAttributes.flags, mAttributes.tags); 178caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent } 17989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 18089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (sampleRate == 0) { 181f0f33c4acd231fa95deb9eeef2c46b0129e64463Glenn Kasten ALOGE("Invalid sample rate %u", sampleRate); 182f0f33c4acd231fa95deb9eeef2c46b0129e64463Glenn Kasten return BAD_VALUE; 18389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 184e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten mSampleRate = sampleRate; 185e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten 18689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // these below should probably come from the audioFlinger too... 18758f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten if (format == AUDIO_FORMAT_DEFAULT) { 188fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin format = AUDIO_FORMAT_PCM_16_BIT; 18989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 1909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 191c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent // validate parameters 192fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin if (!audio_is_valid_format(format)) { 193cac3daa6332bf6d1f7d26adc4a9915f3d7992dd9Glenn Kasten ALOGE("Invalid format %#x", format); 194c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent return BAD_VALUE; 19589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 196291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten // Temporary restriction: AudioFlinger currently supports 16-bit PCM only 197291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten if (format != AUDIO_FORMAT_PCM_16_BIT) { 198cac3daa6332bf6d1f7d26adc4a9915f3d7992dd9Glenn Kasten ALOGE("Format %#x is not supported", format); 199291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten return BAD_VALUE; 200291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten } 2012e4664677d72ce54201d3fd0beb0e10280add93cGlenn Kasten mFormat = format; 20289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 2030d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi if (!audio_is_input_channel(channelMask)) { 2049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Invalid channel mask %#x", channelMask); 20589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return BAD_VALUE; 20689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 207a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten mChannelMask = channelMask; 208e541269be94f3a1072932d51537905b120ef4733Andy Hung uint32_t channelCount = audio_channel_count_from_in_mask(channelMask); 209a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten mChannelCount = channelCount; 210c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 211c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten if (audio_is_linear_pcm(format)) { 212c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten mFrameSize = channelCount * audio_bytes_per_sample(format); 213c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten } else { 214c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten mFrameSize = sizeof(uint8_t); 215c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten } 216e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten 217b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten // mFrameCount is initialized in openRecord_l 218b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten mReqFrameCount = frameCount; 21989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 2204a0efb77198c69df711ab369ac482a42dbdfab07Glenn Kasten mNotificationFramesReq = notificationFrames; 2217410591dad836434c72ddee66680802708b70c10Glenn Kasten // mNotificationFramesAct is initialized in openRecord_l 22289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 223aea7ea06394bcb155972d82055d4ea59962e4051Glenn Kasten if (sessionId == AUDIO_SESSION_ALLOCATE) { 224de3f8392fbf380ba6f09d009b00d7172477389a2Eric Laurent mSessionId = AudioSystem::newAudioUniqueId(); 225ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown } else { 226ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown mSessionId = sessionId; 227ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown } 228ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown ALOGV("set(): mSessionId %d", mSessionId); 229ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown 230ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown mFlags = flags; 231879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten mCbf = cbf; 232879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten 233879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten if (cbf != NULL) { 234879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten mAudioRecordThread = new AudioRecordThread(*this, threadCanCallJava); 235879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO); 236879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten } 237ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown 23834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent // create the IAudioRecord 239c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49Glenn Kasten status_t status = openRecord_l(0 /*epoch*/); 240879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten 24138e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten if (status != NO_ERROR) { 242879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten if (mAudioRecordThread != 0) { 243879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten mAudioRecordThread->requestExit(); // see comment in AudioRecord.h 244879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten mAudioRecordThread->requestExitAndWait(); 245879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten mAudioRecordThread.clear(); 246879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten } 24789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return status; 24889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 24934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent 25089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mStatus = NO_ERROR; 25168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mActive = false; 25289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mUserData = user; 25389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // TODO: add audio hardware input latency here 254573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurent mLatency = (1000*mFrameCount) / sampleRate; 25589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mMarkerPosition = 0; 2567d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi mMarkerReached = false; 25789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mNewPosition = 0; 25889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mUpdatePeriod = 0; 259d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen AudioSystem::acquireAudioSessionId(mSessionId, -1); 2609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mSequence = 1; 2619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mObservedSequence = mSequence; 2629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mInOverrun = false; 26389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 26489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 26589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 26689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 26789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ------------------------------------------------------------------------- 26889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 269a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurentstatus_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession) 27089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 271a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent ALOGV("start, sync event %d trigger session %d", event, triggerSession); 27289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 273f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent AutoMutex lock(mLock); 2749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mActive) { 2759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NO_ERROR; 2769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2771703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 2789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // reset current position as seen by client to 0 2799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition()); 2805e1f79baa5c7355effbd2c9183787d6604487908Glenn Kasten // force refresh of remaining frames by processAudioBuffer() as last 2815e1f79baa5c7355effbd2c9183787d6604487908Glenn Kasten // read before stop could be partial. 2825e1f79baa5c7355effbd2c9183787d6604487908Glenn Kasten mRefreshRemaining = true; 2836dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten 2849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mNewPosition = mProxy->getPosition() + mUpdatePeriod; 28596f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten int32_t flags = android_atomic_acquire_load(&mCblk->mFlags); 2869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 2879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status_t status = NO_ERROR; 2889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(flags & CBLK_INVALID)) { 2899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGV("mAudioRecord->start()"); 2909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = mAudioRecord->start(event, triggerSession); 2919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (status == DEAD_OBJECT) { 2929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten flags |= CBLK_INVALID; 2931703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent } 2949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (flags & CBLK_INVALID) { 2969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = restoreRecord_l("start"); 2979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 2999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (status != NO_ERROR) { 3009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("start() status %d", status); 3019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 3029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mActive = true; 3039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten sp<AudioRecordThread> t = mAudioRecordThread; 3049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (t != 0) { 3059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten t->resume(); 3066100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent } else { 3079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mPreviousPriority = getpriority(PRIO_PROCESS, 0); 3089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten get_sched_policy(0, &mPreviousSchedulingGroup); 3099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 31089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 31189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 31289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 3139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return status; 31489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 31589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 316d64cd233eef39430561c1e1df423336a199cc5d7Glenn Kastenvoid AudioRecord::stop() 31789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 318f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent AutoMutex lock(mLock); 3199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!mActive) { 3209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return; 3219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 3229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 3239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mActive = false; 3249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mProxy->interrupt(); 3259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mAudioRecord->stop(); 3269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // the record head position will reset to 0, so if a marker is set, we need 3279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // to activate it again 3289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mMarkerReached = false; 3299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten sp<AudioRecordThread> t = mAudioRecordThread; 3309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (t != 0) { 3319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten t->pause(); 3329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 3339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten setpriority(PRIO_PROCESS, 0, mPreviousPriority); 3349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten set_sched_policy(0, mPreviousSchedulingGroup); 33589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 33689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 33789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 33889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectbool AudioRecord::stopped() const 33989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 34068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten AutoMutex lock(mLock); 34189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return !mActive; 34289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 34389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 34489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setMarkerPosition(uint32_t marker) 34589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 3462b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten // The only purpose of setting marker position is to get a callback 3479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mCbf == NULL) { 3489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return INVALID_OPERATION; 3499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 35089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 351955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten AutoMutex lock(mLock); 35289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mMarkerPosition = marker; 3537d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi mMarkerReached = false; 35489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 35589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 35689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 35789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 358606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getMarkerPosition(uint32_t *marker) const 35989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 3609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (marker == NULL) { 3619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 3629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 36389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 364955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten AutoMutex lock(mLock); 36589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project *marker = mMarkerPosition; 36689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 36789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 36889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 36989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 37089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod) 37189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 3722b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten // The only purpose of setting position update period is to get a callback 3739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mCbf == NULL) { 3749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return INVALID_OPERATION; 3759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 376955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten 377955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten AutoMutex lock(mLock); 3789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mNewPosition = mProxy->getPosition() + updatePeriod; 37989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mUpdatePeriod = updatePeriod; 38089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 38189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 38289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 38389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 384606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const 38589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 3869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (updatePeriod == NULL) { 3879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 3889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 38989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 390955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten AutoMutex lock(mLock); 39189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project *updatePeriod = mUpdatePeriod; 39289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 39389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 39489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 39589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 396606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getPosition(uint32_t *position) const 39789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 3989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (position == NULL) { 3999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 4009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 40189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 4021703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent AutoMutex lock(mLock); 4039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten *position = mProxy->getPosition(); 40489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 40589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 40689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 40789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 4085f972c031d4061f4f037c9fda1ea4bd9b6a756cdGlenn Kastenuint32_t AudioRecord::getInputFramesLost() const 40905bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent{ 410bf04a5d7f287fc712e0ed91849dc85c90c1e182dGlenn Kasten // no need to check mActive, because if inactive this will return 0, which is what we want 4119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return AudioSystem::getInputFramesLost(getInput()); 41205bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent} 41389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 41489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ------------------------------------------------------------------------- 41589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 4161703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent// must be called with mLock held 417ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brownstatus_t AudioRecord::openRecord_l(size_t epoch) 41834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent{ 41934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent status_t status; 42034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); 42134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent if (audioFlinger == 0) { 422b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten ALOGE("Could not get audioflinger"); 42334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent return NO_INIT; 42434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent } 42534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent 426c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten // Fast tracks must be at the primary _output_ [sic] sampling rate, 427c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten // because there is currently no concept of a primary input sampling rate 428c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten uint32_t afSampleRate = AudioSystem::getPrimaryOutputSamplingRate(); 429c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten if (afSampleRate == 0) { 430c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten ALOGW("getPrimaryOutputSamplingRate failed"); 431c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten } 4321879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten 4333151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten // Client can only express a preference for FAST. Server will perform additional tests. 434c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten if ((mFlags & AUDIO_INPUT_FLAG_FAST) && !( 435c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten // use case: callback transfer mode 436c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten (mTransfer == TRANSFER_CALLBACK) && 437c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten // matching sample rate 438c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten (mSampleRate == afSampleRate))) { 439c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten ALOGW("AUDIO_INPUT_FLAG_FAST denied by client"); 440c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten // once denied, do not request again if IAudioRecord is re-created 441c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST); 442c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten } 443c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten 444c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT; 445c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten 446c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten pid_t tid = -1; 447ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown if (mFlags & AUDIO_INPUT_FLAG_FAST) { 448c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten trackFlags |= IAudioFlinger::TRACK_FAST; 449c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten if (mAudioRecordThread != 0) { 4503151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten tid = mAudioRecordThread->getTid(); 4513151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten } 4523151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten } 4533151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten 454caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent audio_io_handle_t input; 455caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent status = AudioSystem::getInputForAttr(&mAttributes, &input, (audio_session_t)mSessionId, 456caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent mSampleRate, mFormat, mChannelMask, mFlags); 457caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent 458caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent if (status != NO_ERROR) { 4596dd62fb91d82dedcfa3ab38c02eb0940b4ba932aGlenn Kasten ALOGE("Could not get audio input for record source %d, sample rate %u, format %#x, " 460b3b1660ecb67f61f9da54efced8677fa3a6f4863Glenn Kasten "channel mask %#x, session %d, flags %#x", 461caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent mAttributes.source, mSampleRate, mFormat, mChannelMask, mSessionId, mFlags); 462ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown return BAD_VALUE; 463ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown } 46438e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten { 46538e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger, 46638e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten // we must release it ourselves if anything goes wrong. 467ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown 4687410591dad836434c72ddee66680802708b70c10Glenn Kasten size_t frameCount = mReqFrameCount; 469b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten size_t temp = frameCount; // temp may be replaced by a revised value of frameCount, 47074935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten // but we will still need the original value also 471955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten int originalSessionId = mSessionId; 4727df8c0b799d8f52d6386e03313286dbd7d5cdc7cGlenn Kasten 4737df8c0b799d8f52d6386e03313286dbd7d5cdc7cGlenn Kasten // The notification frame count is the period between callbacks, as suggested by the server. 4747410591dad836434c72ddee66680802708b70c10Glenn Kasten size_t notificationFrames = mNotificationFramesReq; 4757df8c0b799d8f52d6386e03313286dbd7d5cdc7cGlenn Kasten 476d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten sp<IMemory> iMem; // for cblk 477d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten sp<IMemory> bufferMem; 4788d6cc842e8d525405c68e57fdf3bc5da0b4d7e87Glenn Kasten sp<IAudioRecord> record = audioFlinger->openRecord(input, 479ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown mSampleRate, mFormat, 480a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten mChannelMask, 48174935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten &temp, 482eeca32671896739e84050da5992d5f151a1629deGlenn Kasten &trackFlags, 4831879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten tid, 484be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent &mSessionId, 4857df8c0b799d8f52d6386e03313286dbd7d5cdc7cGlenn Kasten ¬ificationFrames, 486d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten iMem, 487d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten bufferMem, 48834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent &status); 489aea7ea06394bcb155972d82055d4ea59962e4051Glenn Kasten ALOGE_IF(originalSessionId != AUDIO_SESSION_ALLOCATE && mSessionId != originalSessionId, 490955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten "session ID changed from %d to %d", originalSessionId, mSessionId); 4913a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen 492c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten if (status != NO_ERROR) { 49329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("AudioFlinger could not create record track, status: %d", status); 49438e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten goto release; 49534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent } 496c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten ALOG_ASSERT(record != 0); 497c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten 49838e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten // AudioFlinger now owns the reference to the I/O handle, 49938e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten // so we are no longer responsible for releasing it. 50038e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten 501b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten if (iMem == 0) { 50229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Could not get control block"); 50334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent return NO_INIT; 50434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent } 505e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten void *iMemPointer = iMem->pointer(); 506e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten if (iMemPointer == NULL) { 507e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten ALOGE("Could not get control block pointer"); 508e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten return NO_INIT; 509e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten } 510d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer); 511d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten 512d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten // Starting address of buffers in shared memory. 513d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten // The buffers are either immediately after the control block, 514d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten // or in a separate area at discretion of server. 515d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten void *buffers; 516d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten if (bufferMem == 0) { 517d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten buffers = cblk + 1; 518d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten } else { 519d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten buffers = bufferMem->pointer(); 520d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten if (buffers == NULL) { 521d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten ALOGE("Could not get buffer pointer"); 522d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten return NO_INIT; 523d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten } 524d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten } 525d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten 526089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten // invariant that mAudioRecord != 0 is true only after set() returns successfully 5279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mAudioRecord != 0) { 5289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this); 5299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mDeathNotifier.clear(); 5309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 53134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent mAudioRecord = record; 532b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten mCblkMemory = iMem; 533d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten mBufferMemory = bufferMem; 5343bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent IPCThreadState::self()->flushCommands(); 5353bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent 536b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten mCblk = cblk; 5375f631515d098c29603cda88f7a7e7580a2d55b57Glenn Kasten // note that temp is the (possibly revised) value of frameCount 538b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten if (temp < frameCount || (frameCount == 0 && temp == 0)) { 53934fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGW("Requested frameCount %zu but received frameCount %zu", frameCount, temp); 540b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten } 541b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten frameCount = temp; 54274935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten 5437cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten mAwaitBoost = false; 544ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown if (mFlags & AUDIO_INPUT_FLAG_FAST) { 5457cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten if (trackFlags & IAudioFlinger::TRACK_FAST) { 54634fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGV("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu", frameCount); 5477cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten mAwaitBoost = true; 5487cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten } else { 54934fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGV("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %zu", frameCount); 5507cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten // once denied, do not request again if IAudioRecord is re-created 551ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown mFlags = (audio_input_flags_t) (mFlags & ~AUDIO_INPUT_FLAG_FAST); 5522c48f27be6b3ae58e451d9b56c1dfd00e606f345Glenn Kasten } 5537cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten } 5549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5557410591dad836434c72ddee66680802708b70c10Glenn Kasten // Make sure that application is notified with sufficient margin before overrun 5567410591dad836434c72ddee66680802708b70c10Glenn Kasten if (notificationFrames == 0 || notificationFrames > frameCount) { 5577410591dad836434c72ddee66680802708b70c10Glenn Kasten ALOGW("Received notificationFrames %zu for frameCount %zu", notificationFrames, frameCount); 5587410591dad836434c72ddee66680802708b70c10Glenn Kasten } 5597410591dad836434c72ddee66680802708b70c10Glenn Kasten mNotificationFramesAct = notificationFrames; 5607410591dad836434c72ddee66680802708b70c10Glenn Kasten 561045e739161f5ae00321a6cfba20935abb791005bGlenn Kasten // We retain a copy of the I/O handle, but don't own the reference 562045e739161f5ae00321a6cfba20935abb791005bGlenn Kasten mInput = input; 563a5ed48d3476df7dd1e10b380a68e3333f2b646fdGlenn Kasten mRefreshRemaining = true; 564a5ed48d3476df7dd1e10b380a68e3333f2b646fdGlenn Kasten 565b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten mFrameCount = frameCount; 56611cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten // If IAudioRecord is re-created, don't let the requested frameCount 56711cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten // decrease. This can confuse clients that cache frameCount(). 56811cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten if (frameCount > mReqFrameCount) { 56911cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten mReqFrameCount = frameCount; 57011cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten } 571b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten 572e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten // update proxy 573ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown mProxy = new AudioRecordClientProxy(cblk, buffers, mFrameCount, mFrameSize); 5749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mProxy->setEpoch(epoch); 5757cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten mProxy->setMinimum(mNotificationFramesAct); 5769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mDeathNotifier = new DeathNotifier(this); 5789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mAudioRecord->asBinder()->linkToDeath(mDeathNotifier, this); 579e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten 58034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent return NO_ERROR; 58138e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten } 58238e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten 58338e905b3cbba4da443d799b16999989781afc6d8Glenn Kastenrelease: 5844dc680607181e6a76f4e91a39366c4f5dfb7b03eEric Laurent AudioSystem::releaseInput(input, (audio_session_t)mSessionId); 58538e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten if (status == NO_ERROR) { 58638e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten status = NO_INIT; 58738e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten } 58838e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten return status; 58934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent} 59034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent 59189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) 59289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 5939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (audioBuffer == NULL) { 5949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 5959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 5969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mTransfer != TRANSFER_OBTAIN) { 5979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->frameCount = 0; 5989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->size = 0; 5999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->raw = NULL; 6009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return INVALID_OPERATION; 6019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 602e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten 6039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten const struct timespec *requested; 604df576995a5aad3428aeeef765387d650945c161dEric Laurent struct timespec timeout; 6059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (waitCount == -1) { 6069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &ClientProxy::kForever; 6079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (waitCount == 0) { 6089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &ClientProxy::kNonBlocking; 6099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (waitCount > 0) { 6109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten long long ms = WAIT_PERIOD_MS * (long long) waitCount; 6119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout.tv_sec = ms / 1000; 6129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout.tv_nsec = (int) (ms % 1000) * 1000000; 6139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &timeout; 6149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 6159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("%s invalid waitCount %d", __func__, waitCount); 6169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = NULL; 6179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return obtainBuffer(audioBuffer, requested); 6199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 6209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *requested, 6229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec *elapsed, size_t *nonContig) 6239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 6249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // previous and new IAudioRecord sequence numbers are used to detect track re-creation 6259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten uint32_t oldSequence = 0; 6269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten uint32_t newSequence; 6279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten Proxy::Buffer buffer; 6299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status_t status = NO_ERROR; 6309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten static const int32_t kMaxTries = 5; 6329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t tryCounter = kMaxTries; 6339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten do { 6359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // obtainBuffer() is called with mutex unlocked, so keep extra references to these fields to 6369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // keep them from going away if another thread re-creates the track during obtainBuffer() 6379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten sp<AudioRecordClientProxy> proxy; 6389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten sp<IMemory> iMem; 639d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten sp<IMemory> bufferMem; 6409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten { 6419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // start of lock scope 6429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten AutoMutex lock(mLock); 6439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newSequence = mSequence; 6459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // did previous obtainBuffer() fail due to media server death or voluntary invalidation? 6469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (status == DEAD_OBJECT) { 6479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // re-create track, unless someone else has already done so 6489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (newSequence == oldSequence) { 6499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = restoreRecord_l("obtainBuffer"); 6509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (status != NO_ERROR) { 651d8a9d0220e84ae0b5049385aa9b1a0d8ea02b5bbGlenn Kasten buffer.mFrameCount = 0; 652d8a9d0220e84ae0b5049385aa9b1a0d8ea02b5bbGlenn Kasten buffer.mRaw = NULL; 653d8a9d0220e84ae0b5049385aa9b1a0d8ea02b5bbGlenn Kasten buffer.mNonContig = 0; 6549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 65534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent } 65689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 65789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 6589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten oldSequence = newSequence; 65989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 6609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Keep the extra references 6619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten proxy = mProxy; 6629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten iMem = mCblkMemory; 663d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten bufferMem = mBufferMemory; 664c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 6659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Non-blocking if track is stopped 6669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!mActive) { 6679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &ClientProxy::kNonBlocking; 6689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 66989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 6709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } // end of lock scope 67189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 6729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer.mFrameCount = audioBuffer->frameCount; 6739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME starts the requested timeout and elapsed over from scratch 6749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = proxy->obtainBuffer(&buffer, requested, elapsed); 6759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } while ((status == DEAD_OBJECT) && (tryCounter-- > 0)); 67789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 6789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->frameCount = buffer.mFrameCount; 6799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->size = buffer.mFrameCount * mFrameSize; 6809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->raw = buffer.mRaw; 6819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (nonContig != NULL) { 6829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten *nonContig = buffer.mNonContig; 6839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return status; 68589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 68689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 68789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectvoid AudioRecord::releaseBuffer(Buffer* audioBuffer) 68889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 6899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // all TRANSFER_* are valid 6909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t stepCount = audioBuffer->size / mFrameSize; 6929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (stepCount == 0) { 6939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return; 6949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten Proxy::Buffer buffer; 6979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer.mFrameCount = stepCount; 6989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer.mRaw = audioBuffer->raw; 699e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten 7001703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent AutoMutex lock(mLock); 7019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mInOverrun = false; 7029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mProxy->releaseBuffer(&buffer); 7039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // the server does not automatically disable recorder on overrun, so no need to restart 70589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 70689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 707606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenaudio_io_handle_t AudioRecord::getInput() const 7086100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent{ 7091703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent AutoMutex lock(mLock); 710d1a243e41caffa8fd346907eed4625c9c47c1a86Eric Laurent return mInput; 7111703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent} 7121703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 71389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ------------------------------------------------------------------------- 71489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 71589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectssize_t AudioRecord::read(void* buffer, size_t userSize) 71689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 7179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mTransfer != TRANSFER_SYNC) { 7189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return INVALID_OPERATION; 7199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 72089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 7219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) { 7229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // sanity-check. user is most-likely passing an error code, and it would 7239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // make the return value ambiguous (actualSize vs error). 72434fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGE("AudioRecord::read(buffer=%p, size=%zu (%zu)", buffer, userSize, userSize); 72589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return BAD_VALUE; 72689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 72789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 7289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ssize_t read = 0; 7299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten Buffer audioBuffer; 73089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 7319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten while (userSize >= mFrameSize) { 7329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer.frameCount = userSize / mFrameSize; 73389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 7349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status_t err = obtainBuffer(&audioBuffer, &ClientProxy::kForever); 73589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (err < 0) { 7369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (read > 0) { 73789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project break; 738d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten } 73989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return ssize_t(err); 74089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 74189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 74289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project size_t bytesRead = audioBuffer.size; 7439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten memcpy(buffer, audioBuffer.i8, bytesRead); 7449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer = ((char *) buffer) + bytesRead; 74589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project userSize -= bytesRead; 74689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project read += bytesRead; 74789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 74889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project releaseBuffer(&audioBuffer); 7499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 75089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 75189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return read; 75289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 75389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 75489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ------------------------------------------------------------------------- 75589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 7567c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kastennsecs_t AudioRecord::processAudioBuffer() 75789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 7581703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent mLock.lock(); 75928f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten if (mAwaitBoost) { 76028f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten mAwaitBoost = false; 76128f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten mLock.unlock(); 76228f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten static const int32_t kMaxTries = 5; 76328f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten int32_t tryCounter = kMaxTries; 76428f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten uint32_t pollUs = 10000; 76528f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten do { 76628f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten int policy = sched_getscheduler(0); 76728f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten if (policy == SCHED_FIFO || policy == SCHED_RR) { 76828f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten break; 76928f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten } 77028f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten usleep(pollUs); 77128f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten pollUs <<= 1; 77228f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten } while (tryCounter-- > 0); 77328f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten if (tryCounter < 0) { 77428f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten ALOGE("did not receive expected priority boost on time"); 77528f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten } 77628f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten // Run again immediately 77728f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten return 0; 77828f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten } 7799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Can only reference mCblk while locked 78196f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten int32_t flags = android_atomic_and(~CBLK_OVERRUN, &mCblk->mFlags); 7829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Check for track invalidation 7849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (flags & CBLK_INVALID) { 7859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten (void) restoreRecord_l("processAudioBuffer"); 7869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mLock.unlock(); 7879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Run again immediately, but with a new IAudioRecord 7889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return 0; 7899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 79168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten bool active = mActive; 7929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Manage overrun callback, must be done under lock to avoid race with releaseBuffer() 7949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool newOverrun = false; 7959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (flags & CBLK_OVERRUN) { 7969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!mInOverrun) { 7979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mInOverrun = true; 7989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newOverrun = true; 7999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Get current position of server 8039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t position = mProxy->getPosition(); 8049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Manage marker callback 8069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool markerReached = false; 8079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t markerPosition = mMarkerPosition; 8089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME fails for wraparound, need 64 bits 8099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!mMarkerReached && (markerPosition > 0) && (position >= markerPosition)) { 8109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mMarkerReached = markerReached = true; 8119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Determine the number of new position callback(s) that will be needed, while locked 8149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t newPosCount = 0; 8159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t newPosition = mNewPosition; 816955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten uint32_t updatePeriod = mUpdatePeriod; 8179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME fails for wraparound, need 64 bits 8189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (updatePeriod > 0 && position >= newPosition) { 8199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newPosCount = ((position - newPosition) / updatePeriod) + 1; 8209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mNewPosition += updatePeriod * newPosCount; 8219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Cache other fields that will be needed soon 824838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten uint32_t notificationFrames = mNotificationFramesAct; 8259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mRefreshRemaining) { 8269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRefreshRemaining = false; 8279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRemainingFrames = notificationFrames; 8289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRetryOnPartialBuffer = false; 8299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t misalignment = mProxy->getMisalignment(); 8318ff50e7526d24aca11713006933b8dcb64ef6be9Glenn Kasten uint32_t sequence = mSequence; 8329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // These fields don't need to be cached, because they are assigned only by set(): 8342b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten // mTransfer, mCbf, mUserData, mSampleRate, mFrameSize 8359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8361703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent mLock.unlock(); 8371703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 8389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // perform callbacks while unlocked 8399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (newOverrun) { 8409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mCbf(EVENT_OVERRUN, mUserData, NULL); 8419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (markerReached) { 843955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten mCbf(EVENT_MARKER, mUserData, &markerPosition); 84489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 8459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten while (newPosCount > 0) { 8469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t temp = newPosition; 847955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten mCbf(EVENT_NEW_POS, mUserData, &temp); 848955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten newPosition += updatePeriod; 8499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newPosCount--; 8509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mObservedSequence != sequence) { 8529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mObservedSequence = sequence; 8539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mCbf(EVENT_NEW_IAUDIORECORD, mUserData, NULL); 85489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 85589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 8569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // if inactive, then don't run me again until re-started 8579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!active) { 8589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NS_INACTIVE; 8599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Compute the estimated time until the next timed event (position, markers) 8629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten uint32_t minFrames = ~0; 8639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!markerReached && position < markerPosition) { 8649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten minFrames = markerPosition - position; 8659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (updatePeriod > 0 && updatePeriod < minFrames) { 8679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten minFrames = updatePeriod; 8689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // If > 0, poll periodically to recover from a stuck server. A good value is 2. 8719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten static const uint32_t kPoll = 0; 8729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (kPoll > 0 && mTransfer == TRANSFER_CALLBACK && kPoll * notificationFrames < minFrames) { 8739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten minFrames = kPoll * notificationFrames; 8749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Convert frame units to time units 8779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten nsecs_t ns = NS_WHENEVER; 8789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (minFrames != (uint32_t) ~0) { 8799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // This "fudge factor" avoids soaking CPU, and compensates for late progress by server 8809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten static const nsecs_t kFudgeNs = 10000000LL; // 10 ms 8819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ns = ((minFrames * 1000000000LL) / mSampleRate) + kFudgeNs; 8829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // If not supplying data by EVENT_MORE_DATA, then we're done 8859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mTransfer != TRANSFER_CALLBACK) { 8869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return ns; 8879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec timeout; 8909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten const struct timespec *requested = &ClientProxy::kForever; 8919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (ns != NS_WHENEVER) { 8929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout.tv_sec = ns / 1000000000LL; 8939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout.tv_nsec = ns % 1000000000LL; 8949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGV("timeout %ld.%03d", timeout.tv_sec, (int) timeout.tv_nsec / 1000000); 8959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &timeout; 8969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten while (mRemainingFrames > 0) { 8999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 9009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten Buffer audioBuffer; 9019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer.frameCount = mRemainingFrames; 9029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t nonContig; 9039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig); 9049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0), 90534fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn "obtainBuffer() err=%d frameCount=%zu", err, audioBuffer.frameCount); 9069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &ClientProxy::kNonBlocking; 9079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t avail = audioBuffer.frameCount + nonContig; 90834fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGV("obtainBuffer(%u) returned %zu = %zu + %zu err %d", 9092b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err); 9109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (err != NO_ERROR) { 9119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR) { 9129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 9139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 9149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Error %d obtaining an audio buffer, giving up.", err); 9159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NS_NEVER; 9169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 9179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 9189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mRetryOnPartialBuffer) { 9199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRetryOnPartialBuffer = false; 9209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (avail < mRemainingFrames) { 9219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int64_t myns = ((mRemainingFrames - avail) * 9229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 1100000000LL) / mSampleRate; 9239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (ns < 0 || myns < ns) { 9249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ns = myns; 9259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 9269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return ns; 92789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 92889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 92989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 93089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project size_t reqSize = audioBuffer.size; 93189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); 9329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t readSize = audioBuffer.size; 93389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 93489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // Sanity check on returned size 9359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (ssize_t(readSize) < 0 || readSize > reqSize) { 93634fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGE("EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes", 93734fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn reqSize, ssize_t(readSize)); 9389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NS_NEVER; 9399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 9409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 9419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (readSize == 0) { 9429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // The callback is done consuming buffers 943cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent // Keep this thread going to handle timed events and 9449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // still try to provide more data in intervals of WAIT_PERIOD_MS 945cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent // but don't just loop and block the CPU, so wait 9469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return WAIT_PERIOD_MS * 1000000LL; 947cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent } 94889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 9499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t releasedFrames = readSize / mFrameSize; 9509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer.frameCount = releasedFrames; 9519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRemainingFrames -= releasedFrames; 9529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (misalignment >= releasedFrames) { 9539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten misalignment -= releasedFrames; 9549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 9559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten misalignment = 0; 9569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 95789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 95889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project releaseBuffer(&audioBuffer); 95989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 9609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME here is where we would repeat EVENT_MORE_DATA again on same advanced buffer 9619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // if callback doesn't like to accept the full chunk 9629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (readSize < reqSize) { 9639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten continue; 9649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 96589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 9669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // There could be enough non-contiguous frames available to satisfy the remaining request 9679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mRemainingFrames <= nonContig) { 9689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten continue; 9699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 970c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 9719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#if 0 9729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // This heuristic tries to collapse a series of EVENT_MORE_DATA that would total to a 9739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // sum <= notificationFrames. It replaces that series by at most two EVENT_MORE_DATA 9749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // that total to a sum == notificationFrames. 9759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (0 < misalignment && misalignment <= mRemainingFrames) { 9769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRemainingFrames = misalignment; 9779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return (mRemainingFrames * 1100000000LL) / mSampleRate; 97889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 9799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#endif 98089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 98189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 9829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRemainingFrames = notificationFrames; 9839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRetryOnPartialBuffer = true; 9849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 9859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // A lot has transpired since ns was calculated, so run again immediately and re-calculate 9869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return 0; 98789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 98889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 9899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t AudioRecord::restoreRecord_l(const char *from) 9901703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent{ 9919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGW("dead IAudioRecord, creating a new one from %s()", from); 9929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ++mSequence; 9931703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent status_t result; 9941703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 995b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten // if the new IAudioRecord is created, openRecord_l() will modify the 996d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten // following member variables: mAudioRecord, mCblkMemory, mCblk, mBufferMemory. 997b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten // It will also delete the strong references on previous IAudioRecord and IMemory 9989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t position = mProxy->getPosition(); 9999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mNewPosition = position + mUpdatePeriod; 1000ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown result = openRecord_l(position); 1001b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten if (result == NO_ERROR) { 10029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mActive) { 10039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // callback thread or sync event hasn't changed 10049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME this fails if we have a new AudioFlinger instance 10059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0); 10069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1007b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten } 1008b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten if (result != NO_ERROR) { 10099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGW("restoreRecord_l() failed status %d", result); 1010b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten mActive = false; 10111703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent } 1012b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten 10139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return result; 10149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 10151703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 10169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// ========================================================================= 10171703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 10187c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kastenvoid AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused) 10199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 10209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten sp<AudioRecord> audioRecord = mAudioRecord.promote(); 10219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (audioRecord != 0) { 10229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten AutoMutex lock(audioRecord->mLock); 10239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioRecord->mProxy->binderDied(); 10249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 10251703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent} 10261703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 102789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ========================================================================= 102889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 102968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn KastenAudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver, bool bCanCallJava) 103041721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mPausedInt(false), mPausedNs(0LL), 103141721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten mIgnoreNextPausedInt(false) 103268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{ 103368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten} 103468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten 103568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn KastenAudioRecord::AudioRecordThread::~AudioRecordThread() 103668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{ 103768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten} 103868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten 103968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenbool AudioRecord::AudioRecordThread::threadLoop() 104068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{ 104168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten { 104268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten AutoMutex _l(mMyLock); 104368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten if (mPaused) { 104468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mMyCond.wait(mMyLock); 104568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten // caller will check for exitPending() 104668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten return true; 104768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten } 104841721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten if (mIgnoreNextPausedInt) { 104941721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten mIgnoreNextPausedInt = false; 105041721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten mPausedInt = false; 105141721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten } 10525a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten if (mPausedInt) { 10535a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten if (mPausedNs > 0) { 10545a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten (void) mMyCond.waitRelative(mMyLock, mPausedNs); 10555a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten } else { 10565a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten mMyCond.wait(mMyLock); 10575a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten } 10589d2c78c4798ffd8c276c1bf0eaa0b34bc255a2daEric Laurent mPausedInt = false; 10595a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten return true; 10605a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten } 106168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten } 10627c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kasten nsecs_t ns = mReceiver.processAudioBuffer(); 10639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten switch (ns) { 10649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case 0: 10659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return true; 10669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case NS_INACTIVE: 10675a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten pauseInternal(); 10689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return true; 10699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case NS_NEVER: 10709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return false; 10715a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten case NS_WHENEVER: 10725a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten // FIXME increase poll interval, or make event-driven 10735a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten ns = 1000000000LL; 10745a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten // fall through 10759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten default: 107634fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %" PRId64, ns); 10775a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten pauseInternal(ns); 10789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return true; 107968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten } 108068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten} 108168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten 108268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::requestExit() 108389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 108468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten // must be in this order to avoid a race condition 108568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten Thread::requestExit(); 108641721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten resume(); 108789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 108889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 108968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::pause() 109089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 109168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten AutoMutex _l(mMyLock); 109268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mPaused = true; 109389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 109489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 109568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::resume() 10966dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten{ 109768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten AutoMutex _l(mMyLock); 109841721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten mIgnoreNextPausedInt = true; 10999d2c78c4798ffd8c276c1bf0eaa0b34bc255a2daEric Laurent if (mPaused || mPausedInt) { 110068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mPaused = false; 11019d2c78c4798ffd8c276c1bf0eaa0b34bc255a2daEric Laurent mPausedInt = false; 110268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mMyCond.signal(); 11036dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten } 11046dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten} 11056dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten 11065a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kastenvoid AudioRecord::AudioRecordThread::pauseInternal(nsecs_t ns) 11075a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten{ 11085a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten AutoMutex _l(mMyLock); 11095a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten mPausedInt = true; 11105a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten mPausedNs = ns; 11115a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten} 11125a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten 111389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ------------------------------------------------------------------------- 111489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 111589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}; // namespace android 1116