AudioRecord.cpp revision f0f33c4acd231fa95deb9eeef2c46b0129e64463
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 2189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <sys/resource.h> 22868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <binder/IPCThreadState.h> 2389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/AudioRecord.h> 2489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <utils/Log.h> 25868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <private/media/AudioTrackShared.h> 261ab85ec401801ef9a9184650d0f5a1639b45eeb9Glenn Kasten#include <media/IAudioFlinger.h> 2789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#define WAIT_PERIOD_MS 10 299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 3089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectnamespace android { 3115304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh// --------------------------------------------------------------------------- 3215304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh 3315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh// static 3415304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yehstatus_t AudioRecord::getMinFrameCount( 35e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten size_t* frameCount, 3615304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh uint32_t sampleRate, 3758f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten audio_format_t format, 38dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten audio_channel_mask_t channelMask) 3915304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh{ 409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (frameCount == NULL) { 419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 4304cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten 4404cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten // default to 0 in case of error 4504cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten *frameCount = 0; 4604cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten 4715304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh size_t size = 0; 48c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten status_t status = AudioSystem::getInputBufferSize(sampleRate, format, channelMask, &size); 49c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten if (status != NO_ERROR) { 50c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten ALOGE("AudioSystem could not query the input buffer size; status %d", status); 5115304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh return NO_INIT; 5215304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh } 5315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh 5415304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh if (size == 0) { 553b16c766d1ae2cfd8487e8ffb2b23936fc0a8e17Glenn Kasten ALOGE("Unsupported configuration: sampleRate %u, format %d, channelMask %#x", 56dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten sampleRate, format, channelMask); 5715304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh return BAD_VALUE; 5815304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh } 5915304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh 6015304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh // We double the size of input buffer for ping pong use of record buffer. 6115304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh size <<= 1; 6215304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh 63fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin if (audio_is_linear_pcm(format)) { 64a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten uint32_t channelCount = popcount(channelMask); 65671a636931295d9c33ffca74551a804479d01241Eric Laurent size /= channelCount * audio_bytes_per_sample(format); 6615304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh } 6715304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh 6815304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh *frameCount = size; 6915304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh return NO_ERROR; 7015304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh} 7189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 7289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// --------------------------------------------------------------------------- 7389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 7489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::AudioRecord() 75879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten : mStatus(NO_INIT), mSessionId(0), 769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) 7789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 7889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 7989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 8089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::AudioRecord( 81eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten audio_source_t inputSource, 8289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project uint32_t sampleRate, 8358f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten audio_format_t format, 84624a7fcb377f2a40109c16de5109ae8ea1f67a69Glenn Kasten audio_channel_mask_t channelMask, 8589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project int frameCount, 8689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project callback_t cbf, 8789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project void* user, 88be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent int notificationFrames, 899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int sessionId, 909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten transfer_type transferType) 91879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten : mStatus(NO_INIT), mSessionId(0), 92e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten mPreviousPriority(ANDROID_PRIORITY_NORMAL), 93e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten mPreviousSchedulingGroup(SP_DEFAULT), 94e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten mProxy(NULL) 9589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user, 979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten notificationFrames, false /*threadCanCallJava*/, sessionId, transferType); 9889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 9989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 10089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::~AudioRecord() 10189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 10289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (mStatus == NO_ERROR) { 10389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // Make sure that callback function exits in the case where 10489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // it is looping on buffer empty condition in obtainBuffer(). 10589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // Otherwise the callback thread will never exit. 10689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project stop(); 10768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten if (mAudioRecordThread != 0) { 10868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mAudioRecordThread->requestExit(); // see comment in AudioRecord.h 10968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mAudioRecordThread->requestExitAndWait(); 11068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mAudioRecordThread.clear(); 11189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 1129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mAudioRecord != 0) { 1139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this); 1149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mAudioRecord.clear(); 1159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 11689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project IPCThreadState::self()->flushCommands(); 1173a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen AudioSystem::releaseAudioSessionId(mSessionId); 11889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 11989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 12089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 12189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::set( 122eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten audio_source_t inputSource, 12389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project uint32_t sampleRate, 12458f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten audio_format_t format, 125624a7fcb377f2a40109c16de5109ae8ea1f67a69Glenn Kasten audio_channel_mask_t channelMask, 126e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten int frameCountInt, 12789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project callback_t cbf, 12889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project void* user, 12989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project int notificationFrames, 130be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent bool threadCanCallJava, 1319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int sessionId, 1329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten transfer_type transferType) 13389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 1349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten switch (transferType) { 1359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TRANSFER_DEFAULT: 1369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (cbf == NULL || threadCanCallJava) { 1379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten transferType = TRANSFER_SYNC; 1389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 1399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten transferType = TRANSFER_CALLBACK; 1409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 1429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TRANSFER_CALLBACK: 1439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (cbf == NULL) { 1449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Transfer type TRANSFER_CALLBACK but cbf == NULL"); 1459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 1469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 1489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TRANSFER_OBTAIN: 1499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TRANSFER_SYNC: 1509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 1519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten default: 1529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Invalid transfer type %d", transferType); 1539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 1549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mTransfer = transferType; 1569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 157e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten // FIXME "int" here is legacy and will be replaced by size_t later 158e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten if (frameCountInt < 0) { 159e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten ALOGE("Invalid frame count %d", frameCountInt); 160e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten return BAD_VALUE; 161e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten } 162e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten size_t frameCount = frameCountInt; 16389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 164e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten ALOGV("set(): sampleRate %u, channelMask %#x, frameCount %u", sampleRate, channelMask, 16585ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten frameCount); 1661703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 1671703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent AutoMutex lock(mLock); 1681703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 1691dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent if (mAudioRecord != 0) { 1709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Track already in use"); 17189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return INVALID_OPERATION; 17289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 17389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 174c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent if (inputSource == AUDIO_SOURCE_DEFAULT) { 175c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent inputSource = AUDIO_SOURCE_MIC; 17689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 17789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 17889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (sampleRate == 0) { 179f0f33c4acd231fa95deb9eeef2c46b0129e64463Glenn Kasten ALOGE("Invalid sample rate %u", sampleRate); 180f0f33c4acd231fa95deb9eeef2c46b0129e64463Glenn Kasten return BAD_VALUE; 18189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 182e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten mSampleRate = sampleRate; 183e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten 18489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // these below should probably come from the audioFlinger too... 18558f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten if (format == AUDIO_FORMAT_DEFAULT) { 186fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin format = AUDIO_FORMAT_PCM_16_BIT; 18789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 1889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 189c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent // validate parameters 190fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin if (!audio_is_valid_format(format)) { 1919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Invalid format %d", format); 192c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent return BAD_VALUE; 19389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 194291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten // Temporary restriction: AudioFlinger currently supports 16-bit PCM only 195291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten if (format != AUDIO_FORMAT_PCM_16_BIT) { 196291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten ALOGE("Format %d is not supported", format); 197291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten return BAD_VALUE; 198291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten } 1992e4664677d72ce54201d3fd0beb0e10280add93cGlenn Kasten mFormat = format; 20089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 2010d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi if (!audio_is_input_channel(channelMask)) { 2029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Invalid channel mask %#x", channelMask); 20389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return BAD_VALUE; 20489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 205a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten mChannelMask = channelMask; 206a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten uint32_t channelCount = popcount(channelMask); 207a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten mChannelCount = channelCount; 208c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 2092e4664677d72ce54201d3fd0beb0e10280add93cGlenn Kasten if (audio_is_linear_pcm(format)) { 210e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten mFrameSize = channelCount * audio_bytes_per_sample(format); 211e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten } else { 212e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten mFrameSize = sizeof(uint8_t); 213e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten } 214e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten 2157c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent if (sessionId == 0 ) { 2167c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent mSessionId = AudioSystem::newAudioSessionId(); 2177c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent } else { 2187c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent mSessionId = sessionId; 2197c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent } 2203856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("set(): mSessionId %d", mSessionId); 2217c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent 2226100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent audio_io_handle_t input = AudioSystem::getInput(inputSource, 2237c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent sampleRate, 2247c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent format, 2257c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent channelMask, 2267c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent mSessionId); 2276100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent if (input == 0) { 22829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Could not get audio input for record source %d", inputSource); 22989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return BAD_VALUE; 23089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 23189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 23289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // validate framecount 233e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten size_t minFrameCount = 0; 2346f744d75d3439f7984245e3c489cc7cf91cea41cEric Laurent status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelMask); 23515304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh if (status != NO_ERROR) { 2369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("getMinFrameCount() failed; status %d", status); 23715304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh return status; 238c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent } 2393856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("AudioRecord::set() minFrameCount = %d", minFrameCount); 24089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 24189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (frameCount == 0) { 24289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project frameCount = minFrameCount; 24389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } else if (frameCount < minFrameCount) { 2449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("frameCount %u < minFrameCount %u", frameCount, minFrameCount); 24589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return BAD_VALUE; 24689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 24789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 24889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (notificationFrames == 0) { 24989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project notificationFrames = frameCount/2; 25089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 25189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 25234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent // create the IAudioRecord 2539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = openRecord_l(sampleRate, format, frameCount, input, 0 /*epoch*/); 25434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent if (status != NO_ERROR) { 25589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return status; 25689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 25734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent 258a0d68338a88c2ddb4502f95017b546d603ef1ec7Glenn Kasten if (cbf != NULL) { 25968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mAudioRecordThread = new AudioRecordThread(*this, threadCanCallJava); 26068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO); 26189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 26289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 26389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mStatus = NO_ERROR; 26489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 26589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // Update buffer size in case it has been limited by AudioFlinger during track creation 266b603744e96b07b1d5bf745bde593fb2c025cefcfGlenn Kasten mFrameCount = mCblk->frameCount_; 26783a0382dc17364567667a4e6135db43f5bd92efcGlenn Kasten 26868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mActive = false; 26989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mCbf = cbf; 27089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mNotificationFrames = notificationFrames; 2719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRefreshRemaining = true; 27289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mUserData = user; 27389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // TODO: add audio hardware input latency here 274573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurent mLatency = (1000*mFrameCount) / sampleRate; 27589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mMarkerPosition = 0; 2767d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi mMarkerReached = false; 27789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mNewPosition = 0; 27889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mUpdatePeriod = 0; 279eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten mInputSource = inputSource; 28005bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent mInput = input; 2813a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen AudioSystem::acquireAudioSessionId(mSessionId); 2829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mSequence = 1; 2839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mObservedSequence = mSequence; 2849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mInOverrun = false; 28589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 28689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 28789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 28889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 28989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ------------------------------------------------------------------------- 29089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 291a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurentstatus_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession) 29289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 293a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent ALOGV("start, sync event %d trigger session %d", event, triggerSession); 29489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 295f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent AutoMutex lock(mLock); 2969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mActive) { 2979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NO_ERROR; 2989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2991703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 3009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // reset current position as seen by client to 0 3019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition()); 3026dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten 3039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mNewPosition = mProxy->getPosition() + mUpdatePeriod; 30496f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten int32_t flags = android_atomic_acquire_load(&mCblk->mFlags); 3059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 3069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status_t status = NO_ERROR; 3079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(flags & CBLK_INVALID)) { 3089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGV("mAudioRecord->start()"); 3099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = mAudioRecord->start(event, triggerSession); 3109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (status == DEAD_OBJECT) { 3119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten flags |= CBLK_INVALID; 3121703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent } 3139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 3149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (flags & CBLK_INVALID) { 3159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = restoreRecord_l("start"); 3169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 3179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 3189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (status != NO_ERROR) { 3199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("start() status %d", status); 3209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 3219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mActive = true; 3229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten sp<AudioRecordThread> t = mAudioRecordThread; 3239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (t != 0) { 3249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten t->resume(); 3256100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent } else { 3269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mPreviousPriority = getpriority(PRIO_PROCESS, 0); 3279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten get_sched_policy(0, &mPreviousSchedulingGroup); 3289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 32989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 33089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 33189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 3329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return status; 33389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 33489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 335d64cd233eef39430561c1e1df423336a199cc5d7Glenn Kastenvoid AudioRecord::stop() 33689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 337f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent AutoMutex lock(mLock); 3389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!mActive) { 3399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return; 3409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 3419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 3429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mActive = false; 3439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mProxy->interrupt(); 3449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mAudioRecord->stop(); 3459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // the record head position will reset to 0, so if a marker is set, we need 3469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // to activate it again 3479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mMarkerReached = false; 3489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten sp<AudioRecordThread> t = mAudioRecordThread; 3499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (t != 0) { 3509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten t->pause(); 3519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 3529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten setpriority(PRIO_PROCESS, 0, mPreviousPriority); 3539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten set_sched_policy(0, mPreviousSchedulingGroup); 35489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 35589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 35689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 35789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectbool AudioRecord::stopped() const 35889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 35968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten AutoMutex lock(mLock); 36089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return !mActive; 36189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 36289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 36389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setMarkerPosition(uint32_t marker) 36489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 3659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mCbf == NULL) { 3669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return INVALID_OPERATION; 3679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 36889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 369955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten AutoMutex lock(mLock); 37089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mMarkerPosition = marker; 3717d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi mMarkerReached = false; 37289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 37389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 37489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 37589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 376606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getMarkerPosition(uint32_t *marker) const 37789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 3789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (marker == NULL) { 3799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 3809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 38189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 382955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten AutoMutex lock(mLock); 38389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project *marker = mMarkerPosition; 38489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 38589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 38689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 38789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 38889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod) 38989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 3909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mCbf == NULL) { 3919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return INVALID_OPERATION; 3929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 393955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten 394955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten AutoMutex lock(mLock); 3959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mNewPosition = mProxy->getPosition() + updatePeriod; 39689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mUpdatePeriod = updatePeriod; 39789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 39889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 39989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 40089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 401606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const 40289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 4039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (updatePeriod == NULL) { 4049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 4059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 40689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 407955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten AutoMutex lock(mLock); 40889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project *updatePeriod = mUpdatePeriod; 40989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 41089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 41189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 41289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 413606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getPosition(uint32_t *position) const 41489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 4159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (position == NULL) { 4169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 4179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 41889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 4191703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent AutoMutex lock(mLock); 4209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten *position = mProxy->getPosition(); 42189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 42289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 42389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 42489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 425606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenunsigned int AudioRecord::getInputFramesLost() const 42605bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent{ 427bf04a5d7f287fc712e0ed91849dc85c90c1e182dGlenn Kasten // no need to check mActive, because if inactive this will return 0, which is what we want 4289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return AudioSystem::getInputFramesLost(getInput()); 42905bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent} 43089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 43189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ------------------------------------------------------------------------- 43289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 4331703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent// must be called with mLock held 4341703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurentstatus_t AudioRecord::openRecord_l( 43534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent uint32_t sampleRate, 43658f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten audio_format_t format, 437e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten size_t frameCount, 4389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_io_handle_t input, 4399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t epoch) 44034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent{ 44134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent status_t status; 44234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); 44334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent if (audioFlinger == 0) { 444b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten ALOGE("Could not get audioflinger"); 44534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent return NO_INIT; 44634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent } 44734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent 4481879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten pid_t tid = -1; 4499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME see similar logic at AudioTrack for tid 4501879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten 451955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten int originalSessionId = mSessionId; 4528d6cc842e8d525405c68e57fdf3bc5da0b4d7e87Glenn Kasten sp<IAudioRecord> record = audioFlinger->openRecord(input, 45334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent sampleRate, format, 454a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten mChannelMask, 45534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent frameCount, 456a075db4ff9b086ac2885df77bb6da0869293df92Glenn Kasten IAudioFlinger::TRACK_DEFAULT, 4571879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten tid, 458be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent &mSessionId, 45934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent &status); 460955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten ALOGE_IF(originalSessionId != 0 && mSessionId != originalSessionId, 461955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten "session ID changed from %d to %d", originalSessionId, mSessionId); 4623a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen 46334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent if (record == 0) { 46429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("AudioFlinger could not create record track, status: %d", status); 46534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent return status; 46634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent } 467b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten sp<IMemory> iMem = record->getCblk(); 468b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten if (iMem == 0) { 46929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Could not get control block"); 47034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent return NO_INIT; 47134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent } 4729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mAudioRecord != 0) { 4739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this); 4749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mDeathNotifier.clear(); 4759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 47634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent mAudioRecord = record; 477b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten mCblkMemory = iMem; 478b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMem->pointer()); 479b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten mCblk = cblk; 4809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 4819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // starting address of buffers in shared memory 4829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten void *buffers = (char*)cblk + sizeof(audio_track_cblk_t); 483e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten 484e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten // update proxy 4859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mProxy = new AudioRecordClientProxy(cblk, buffers, frameCount, mFrameSize); 4869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mProxy->setEpoch(epoch); 4879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mProxy->setMinimum(mNotificationFrames); 4889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 4899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mDeathNotifier = new DeathNotifier(this); 4909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mAudioRecord->asBinder()->linkToDeath(mDeathNotifier, this); 491e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten 49234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent return NO_ERROR; 49334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent} 49434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent 49589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) 49689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 4979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (audioBuffer == NULL) { 4989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 4999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 5009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mTransfer != TRANSFER_OBTAIN) { 5019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->frameCount = 0; 5029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->size = 0; 5039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->raw = NULL; 5049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return INVALID_OPERATION; 5059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 506e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten 5079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten const struct timespec *requested; 5089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (waitCount == -1) { 5099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &ClientProxy::kForever; 5109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (waitCount == 0) { 5119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &ClientProxy::kNonBlocking; 5129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (waitCount > 0) { 5139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten long long ms = WAIT_PERIOD_MS * (long long) waitCount; 5149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec timeout; 5159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout.tv_sec = ms / 1000; 5169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout.tv_nsec = (int) (ms % 1000) * 1000000; 5179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &timeout; 5189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 5199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("%s invalid waitCount %d", __func__, waitCount); 5209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = NULL; 5219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 5229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return obtainBuffer(audioBuffer, requested); 5239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 5249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *requested, 5269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec *elapsed, size_t *nonContig) 5279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 5289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // previous and new IAudioRecord sequence numbers are used to detect track re-creation 5299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten uint32_t oldSequence = 0; 5309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten uint32_t newSequence; 5319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten Proxy::Buffer buffer; 5339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status_t status = NO_ERROR; 5349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten static const int32_t kMaxTries = 5; 5369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t tryCounter = kMaxTries; 5379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten do { 5399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // obtainBuffer() is called with mutex unlocked, so keep extra references to these fields to 5409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // keep them from going away if another thread re-creates the track during obtainBuffer() 5419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten sp<AudioRecordClientProxy> proxy; 5429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten sp<IMemory> iMem; 5439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten { 5449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // start of lock scope 5459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten AutoMutex lock(mLock); 5469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newSequence = mSequence; 5489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // did previous obtainBuffer() fail due to media server death or voluntary invalidation? 5499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (status == DEAD_OBJECT) { 5509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // re-create track, unless someone else has already done so 5519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (newSequence == oldSequence) { 5529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = restoreRecord_l("obtainBuffer"); 5539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (status != NO_ERROR) { 5549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 55534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent } 55689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 55789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 5589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten oldSequence = newSequence; 55989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 5609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Keep the extra references 5619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten proxy = mProxy; 5629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten iMem = mCblkMemory; 563c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 5649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Non-blocking if track is stopped 5659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!mActive) { 5669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &ClientProxy::kNonBlocking; 5679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 56889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 5699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } // end of lock scope 57089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 5719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer.mFrameCount = audioBuffer->frameCount; 5729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME starts the requested timeout and elapsed over from scratch 5739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = proxy->obtainBuffer(&buffer, requested, elapsed); 5749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } while ((status == DEAD_OBJECT) && (tryCounter-- > 0)); 57689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 5779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->frameCount = buffer.mFrameCount; 5789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->size = buffer.mFrameCount * mFrameSize; 5799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->raw = buffer.mRaw; 5809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (nonContig != NULL) { 5819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten *nonContig = buffer.mNonContig; 5829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 5839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return status; 58489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 58589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 58689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectvoid AudioRecord::releaseBuffer(Buffer* audioBuffer) 58789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 5889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // all TRANSFER_* are valid 5899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t stepCount = audioBuffer->size / mFrameSize; 5919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (stepCount == 0) { 5929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return; 5939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 5949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten Proxy::Buffer buffer; 5969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer.mFrameCount = stepCount; 5979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer.mRaw = audioBuffer->raw; 598e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten 5991703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent AutoMutex lock(mLock); 6009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mInOverrun = false; 6019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mProxy->releaseBuffer(&buffer); 6029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // the server does not automatically disable recorder on overrun, so no need to restart 60489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 60589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 606606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenaudio_io_handle_t AudioRecord::getInput() const 6076100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent{ 6081703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent AutoMutex lock(mLock); 609d1a243e41caffa8fd346907eed4625c9c47c1a86Eric Laurent return mInput; 6101703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent} 6111703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 6121703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent// must be called with mLock held 6131703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurentaudio_io_handle_t AudioRecord::getInput_l() 6141703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent{ 61505bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent mInput = AudioSystem::getInput(mInputSource, 616e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten mSampleRate, 6177c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent mFormat, 6187c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent mChannelMask, 6197c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent mSessionId); 62005bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent return mInput; 6216100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent} 6226100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent 62389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ------------------------------------------------------------------------- 62489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 62589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectssize_t AudioRecord::read(void* buffer, size_t userSize) 62689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 6279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mTransfer != TRANSFER_SYNC) { 6289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return INVALID_OPERATION; 6299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 63089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 6319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) { 6329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // sanity-check. user is most-likely passing an error code, and it would 6339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // make the return value ambiguous (actualSize vs error). 6349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("AudioRecord::read(buffer=%p, size=%u (%d)", buffer, userSize, userSize); 63589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return BAD_VALUE; 63689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 63789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 6389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ssize_t read = 0; 6399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten Buffer audioBuffer; 64089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 6419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten while (userSize >= mFrameSize) { 6429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer.frameCount = userSize / mFrameSize; 64389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 6449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status_t err = obtainBuffer(&audioBuffer, &ClientProxy::kForever); 64589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (err < 0) { 6469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (read > 0) { 64789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project break; 648d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten } 64989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return ssize_t(err); 65089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 65189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 65289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project size_t bytesRead = audioBuffer.size; 6539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten memcpy(buffer, audioBuffer.i8, bytesRead); 6549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer = ((char *) buffer) + bytesRead; 65589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project userSize -= bytesRead; 65689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project read += bytesRead; 65789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 65889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project releaseBuffer(&audioBuffer); 6599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 66089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 66189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return read; 66289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 66389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 66489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ------------------------------------------------------------------------- 66589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 6669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastennsecs_t AudioRecord::processAudioBuffer(const sp<AudioRecordThread>& thread) 66789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 6681703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent mLock.lock(); 6699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Can only reference mCblk while locked 67196f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten int32_t flags = android_atomic_and(~CBLK_OVERRUN, &mCblk->mFlags); 6729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Check for track invalidation 6749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (flags & CBLK_INVALID) { 6759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten (void) restoreRecord_l("processAudioBuffer"); 6769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mLock.unlock(); 6779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Run again immediately, but with a new IAudioRecord 6789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return 0; 6799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 68168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten bool active = mActive; 6829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Manage overrun callback, must be done under lock to avoid race with releaseBuffer() 6849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool newOverrun = false; 6859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (flags & CBLK_OVERRUN) { 6869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!mInOverrun) { 6879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mInOverrun = true; 6889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newOverrun = true; 6899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Get current position of server 6939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t position = mProxy->getPosition(); 6949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Manage marker callback 6969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool markerReached = false; 6979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t markerPosition = mMarkerPosition; 6989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME fails for wraparound, need 64 bits 6999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!mMarkerReached && (markerPosition > 0) && (position >= markerPosition)) { 7009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mMarkerReached = markerReached = true; 7019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Determine the number of new position callback(s) that will be needed, while locked 7049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t newPosCount = 0; 7059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t newPosition = mNewPosition; 706955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten uint32_t updatePeriod = mUpdatePeriod; 7079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME fails for wraparound, need 64 bits 7089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (updatePeriod > 0 && position >= newPosition) { 7099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newPosCount = ((position - newPosition) / updatePeriod) + 1; 7109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mNewPosition += updatePeriod * newPosCount; 7119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Cache other fields that will be needed soon 7149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t notificationFrames = mNotificationFrames; 7159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mRefreshRemaining) { 7169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRefreshRemaining = false; 7179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRemainingFrames = notificationFrames; 7189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRetryOnPartialBuffer = false; 7199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t misalignment = mProxy->getMisalignment(); 7219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t sequence = mSequence; 7229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // These fields don't need to be cached, because they are assigned only by set(): 7249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // mTransfer, mCbf, mUserData, mSampleRate 7259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7261703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent mLock.unlock(); 7271703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 7289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // perform callbacks while unlocked 7299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (newOverrun) { 7309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mCbf(EVENT_OVERRUN, mUserData, NULL); 7319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (markerReached) { 733955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten mCbf(EVENT_MARKER, mUserData, &markerPosition); 73489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 7359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten while (newPosCount > 0) { 7369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t temp = newPosition; 737955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten mCbf(EVENT_NEW_POS, mUserData, &temp); 738955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten newPosition += updatePeriod; 7399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newPosCount--; 7409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mObservedSequence != sequence) { 7429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mObservedSequence = sequence; 7439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mCbf(EVENT_NEW_IAUDIORECORD, mUserData, NULL); 74489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 74589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 7469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // if inactive, then don't run me again until re-started 7479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!active) { 7489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NS_INACTIVE; 7499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Compute the estimated time until the next timed event (position, markers) 7529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten uint32_t minFrames = ~0; 7539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!markerReached && position < markerPosition) { 7549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten minFrames = markerPosition - position; 7559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (updatePeriod > 0 && updatePeriod < minFrames) { 7579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten minFrames = updatePeriod; 7589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // If > 0, poll periodically to recover from a stuck server. A good value is 2. 7619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten static const uint32_t kPoll = 0; 7629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (kPoll > 0 && mTransfer == TRANSFER_CALLBACK && kPoll * notificationFrames < minFrames) { 7639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten minFrames = kPoll * notificationFrames; 7649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Convert frame units to time units 7679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten nsecs_t ns = NS_WHENEVER; 7689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (minFrames != (uint32_t) ~0) { 7699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // This "fudge factor" avoids soaking CPU, and compensates for late progress by server 7709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten static const nsecs_t kFudgeNs = 10000000LL; // 10 ms 7719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ns = ((minFrames * 1000000000LL) / mSampleRate) + kFudgeNs; 7729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // If not supplying data by EVENT_MORE_DATA, then we're done 7759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mTransfer != TRANSFER_CALLBACK) { 7769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return ns; 7779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec timeout; 7809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten const struct timespec *requested = &ClientProxy::kForever; 7819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (ns != NS_WHENEVER) { 7829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout.tv_sec = ns / 1000000000LL; 7839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout.tv_nsec = ns % 1000000000LL; 7849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGV("timeout %ld.%03d", timeout.tv_sec, (int) timeout.tv_nsec / 1000000); 7859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &timeout; 7869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten while (mRemainingFrames > 0) { 7899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten Buffer audioBuffer; 7919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer.frameCount = mRemainingFrames; 7929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t nonContig; 7939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig); 7949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0), 7959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten "obtainBuffer() err=%d frameCount=%u", err, audioBuffer.frameCount); 7969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &ClientProxy::kNonBlocking; 7979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t avail = audioBuffer.frameCount + nonContig; 7989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGV("obtainBuffer(%u) returned %u = %u + %u", 7999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRemainingFrames, avail, audioBuffer.frameCount, nonContig); 8009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (err != NO_ERROR) { 8019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR) { 8029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 8039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Error %d obtaining an audio buffer, giving up.", err); 8059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NS_NEVER; 8069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mRetryOnPartialBuffer) { 8099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRetryOnPartialBuffer = false; 8109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (avail < mRemainingFrames) { 8119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int64_t myns = ((mRemainingFrames - avail) * 8129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 1100000000LL) / mSampleRate; 8139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (ns < 0 || myns < ns) { 8149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ns = myns; 8159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return ns; 81789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 81889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 81989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 82089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project size_t reqSize = audioBuffer.size; 82189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); 8229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t readSize = audioBuffer.size; 82389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 82489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // Sanity check on returned size 8259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (ssize_t(readSize) < 0 || readSize > reqSize) { 8269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("EVENT_MORE_DATA requested %u bytes but callback returned %d bytes", 8279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten reqSize, (int) readSize); 8289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NS_NEVER; 8299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (readSize == 0) { 8329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // The callback is done consuming buffers 833cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent // Keep this thread going to handle timed events and 8349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // still try to provide more data in intervals of WAIT_PERIOD_MS 835cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent // but don't just loop and block the CPU, so wait 8369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return WAIT_PERIOD_MS * 1000000LL; 837cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent } 83889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 8399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t releasedFrames = readSize / mFrameSize; 8409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer.frameCount = releasedFrames; 8419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRemainingFrames -= releasedFrames; 8429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (misalignment >= releasedFrames) { 8439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten misalignment -= releasedFrames; 8449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 8459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten misalignment = 0; 8469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 84789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 84889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project releaseBuffer(&audioBuffer); 84989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 8509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME here is where we would repeat EVENT_MORE_DATA again on same advanced buffer 8519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // if callback doesn't like to accept the full chunk 8529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (readSize < reqSize) { 8539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten continue; 8549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 85589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 8569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // There could be enough non-contiguous frames available to satisfy the remaining request 8579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mRemainingFrames <= nonContig) { 8589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten continue; 8599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 860c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 8619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#if 0 8629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // This heuristic tries to collapse a series of EVENT_MORE_DATA that would total to a 8639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // sum <= notificationFrames. It replaces that series by at most two EVENT_MORE_DATA 8649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // that total to a sum == notificationFrames. 8659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (0 < misalignment && misalignment <= mRemainingFrames) { 8669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRemainingFrames = misalignment; 8679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return (mRemainingFrames * 1100000000LL) / mSampleRate; 86889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 8699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#endif 87089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 87189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 8729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRemainingFrames = notificationFrames; 8739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRetryOnPartialBuffer = true; 8749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // A lot has transpired since ns was calculated, so run again immediately and re-calculate 8769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return 0; 87789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 87889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 8799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t AudioRecord::restoreRecord_l(const char *from) 8801703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent{ 8819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGW("dead IAudioRecord, creating a new one from %s()", from); 8829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ++mSequence; 8831703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent status_t result; 8841703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 885b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten // if the new IAudioRecord is created, openRecord_l() will modify the 886b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten // following member variables: mAudioRecord, mCblkMemory and mCblk. 887b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten // It will also delete the strong references on previous IAudioRecord and IMemory 8889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t position = mProxy->getPosition(); 8899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mNewPosition = position + mUpdatePeriod; 8909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten result = openRecord_l(mSampleRate, mFormat, mFrameCount, getInput_l(), position); 891b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten if (result == NO_ERROR) { 8929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mActive) { 8939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // callback thread or sync event hasn't changed 8949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME this fails if we have a new AudioFlinger instance 8959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0); 8969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 897b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten } 898b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten if (result != NO_ERROR) { 8999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGW("restoreRecord_l() failed status %d", result); 900b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten mActive = false; 9011703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent } 902b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten 9039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return result; 9049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 9051703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 9069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// ========================================================================= 9071703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 9089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who) 9099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 9109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten sp<AudioRecord> audioRecord = mAudioRecord.promote(); 9119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (audioRecord != 0) { 9129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten AutoMutex lock(audioRecord->mLock); 9139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioRecord->mProxy->binderDied(); 9149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 9151703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent} 9161703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 91789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ========================================================================= 91889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 91968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn KastenAudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver, bool bCanCallJava) 9209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mResumeLatch(false) 92168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{ 92268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten} 92368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten 92468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn KastenAudioRecord::AudioRecordThread::~AudioRecordThread() 92568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{ 92668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten} 92768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten 92868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenbool AudioRecord::AudioRecordThread::threadLoop() 92968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{ 93068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten { 93168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten AutoMutex _l(mMyLock); 93268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten if (mPaused) { 93368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mMyCond.wait(mMyLock); 93468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten // caller will check for exitPending() 93568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten return true; 93668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten } 93768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten } 9389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten nsecs_t ns = mReceiver.processAudioBuffer(this); 9399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten switch (ns) { 9409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case 0: 9419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return true; 9429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case NS_WHENEVER: 9439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten sleep(1); 9449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return true; 9459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case NS_INACTIVE: 9469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten pauseConditional(); 9479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return true; 9489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case NS_NEVER: 9499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return false; 9509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten default: 9519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %lld", ns); 9529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec req; 9539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten req.tv_sec = ns / 1000000000LL; 9549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten req.tv_nsec = ns % 1000000000LL; 9559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten nanosleep(&req, NULL /*rem*/); 9569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return true; 95768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten } 95868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten} 95968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten 96068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::requestExit() 96189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 96268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten // must be in this order to avoid a race condition 96368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten Thread::requestExit(); 96468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten resume(); 96589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 96689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 96768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::pause() 96889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 96968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten AutoMutex _l(mMyLock); 97068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mPaused = true; 9719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mResumeLatch = false; 9729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 9739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 9749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid AudioRecord::AudioRecordThread::pauseConditional() 9759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 9769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten AutoMutex _l(mMyLock); 9779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mResumeLatch) { 9789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mResumeLatch = false; 9799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 9809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mPaused = true; 9819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 98289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 98389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 98468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::resume() 9856dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten{ 98668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten AutoMutex _l(mMyLock); 98768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten if (mPaused) { 98868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mPaused = false; 9899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mResumeLatch = false; 99068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mMyCond.signal(); 9919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 9929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mResumeLatch = true; 9936dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten } 9946dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten} 9956dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten 99689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ------------------------------------------------------------------------- 99789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 99889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}; // namespace android 999