AudioRecord.cpp revision 3a34befc6fb04a4945a849e8bda8b84e4bf973fe
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 2e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy** 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Copyright 2008, The Android Open Source Project 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** you may not use this file except in compliance with the License. 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** You may obtain a copy of the License at 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 90795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopian** http://www.apache.org/licenses/LICENSE-2.0 10d84e1ce0b535128f03416145554fb405f9fade3eJeff Sharkey** 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** See the License for the specific language governing permissions and 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** limitations under the License. 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 179aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy 189aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy//#define LOG_NDEBUG 0 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "AudioRecord" 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdint.h> 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sched.h> 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/resource.h> 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <private/media/AudioTrackShared.h> 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/AudioSystem.h> 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/AudioRecord.h> 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/mediarecorder.h> 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <binder/IServiceManager.h> 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 358cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen#include <binder/Parcel.h> 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <binder/IPCThreadState.h> 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Timers.h> 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Atomic.h> 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <system/audio.h> 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/bitops.h> 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) 448cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// --------------------------------------------------------------------------- 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// static 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioRecord::getMinFrameCount( 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int* frameCount, 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t sampleRate, 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int format, 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int channelCount) 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 568cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen size_t size = 0; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &size) 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != NO_ERROR) { 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("AudioSystem could not query the input buffer size."); 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_INIT; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (size == 0) { 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Unsupported configuration: sampleRate %d, format %d, channelCount %d", 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sampleRate, format, channelCount); 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return BAD_VALUE; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We double the size of input buffer for ping pong use of record buffer. 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size <<= 1; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (audio_is_linear_pcm(format)) { 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size /= channelCount * audio_bytes_per_sample(format); 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *frameCount = size; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// --------------------------------------------------------------------------- 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectAudioRecord::AudioRecord() 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : mStatus(NO_INIT), mSessionId(0) 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 878cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta ChenAudioRecord::AudioRecord( 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int inputSource, 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t sampleRate, 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int format, 918cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen uint32_t channelMask, 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int frameCount, 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t flags, 948cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen callback_t cbf, 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void* user, 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int notificationFrames, 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int sessionId) 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : mStatus(NO_INIT), mSessionId(0) 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStatus = set(inputSource, sampleRate, format, channelMask, 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project frameCount, flags, cbf, user, notificationFrames, sessionId); 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1038cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen 1041a81aea8144b92ebaf807af9de69a0ab3415a5aaRomain GuyAudioRecord::~AudioRecord() 1051a81aea8144b92ebaf807af9de69a0ab3415a5aaRomain Guy{ 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mStatus == NO_ERROR) { 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Make sure that callback function exits in the case where 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // it is looping on buffer empty condition in obtainBuffer(). 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Otherwise the callback thread will never exit. 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stop(); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mClientRecordThread != 0) { 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mClientRecordThread->requestExitAndWait(); 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mClientRecordThread.clear(); 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioRecord.clear(); 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IPCThreadState::self()->flushCommands(); 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioSystem::releaseAudioSessionId(mSessionId); 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioRecord::set( 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int inputSource, 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t sampleRate, 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int format, 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t channelMask, 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int frameCount, 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t flags, 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project callback_t cbf, 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void* user, 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int notificationFrames, 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool threadCanCallJava, 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int sessionId) 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("set(): sampleRate %d, channelMask %d, frameCount %d",sampleRate, channelMask, frameCount); 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AutoMutex lock(mLock); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAudioRecord != 0) { 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_OPERATION; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (inputSource == AUDIO_SOURCE_DEFAULT) { 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inputSource = AUDIO_SOURCE_MIC; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sampleRate == 0) { 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sampleRate = DEFAULT_SAMPLE_RATE; 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // these below should probably come from the audioFlinger too... 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (format == 0) { 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project format = AUDIO_FORMAT_PCM_16_BIT; 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // validate parameters 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!audio_is_valid_format(format)) { 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Invalid format"); 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return BAD_VALUE; 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!audio_is_input_channel(channelMask)) { 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return BAD_VALUE; 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int channelCount = popcount(channelMask); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sessionId == 0 ) { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSessionId = AudioSystem::newAudioSessionId(); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSessionId = sessionId; 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("set(): mSessionId %d", mSessionId); 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audio_io_handle_t input = AudioSystem::getInput(inputSource, 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sampleRate, 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project format, 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project channelMask, 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (audio_in_acoustics_t)flags, 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSessionId); 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (input == 0) { 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Could not get audio input for record source %d", inputSource); 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return BAD_VALUE; 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // validate framecount 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int minFrameCount = 0; 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelCount); 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (status != NO_ERROR) { 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return status; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount); 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (frameCount == 0) { 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project frameCount = minFrameCount; 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (frameCount < minFrameCount) { 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return BAD_VALUE; 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (notificationFrames == 0) { 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project notificationFrames = frameCount/2; 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // create the IAudioRecord 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status = openRecord_l(sampleRate, format, channelMask, 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project frameCount, flags, input); 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (status != NO_ERROR) { 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return status; 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cbf != 0) { 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava); 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mClientRecordThread == 0) { 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_INIT; 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStatus = NO_ERROR; 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFormat = format; 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Update buffer size in case it has been limited by AudioFlinger during track creation 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFrameCount = mCblk->frameCount; 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChannelCount = (uint8_t)channelCount; 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChannelMask = channelMask; 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mActive = 0; 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCbf = cbf; 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNotificationFrames = notificationFrames; 2268cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen mRemainingFrames = notificationFrames; 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUserData = user; 228e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy // TODO: add audio hardware input latency here 229e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy mLatency = (1000*mFrameCount) / sampleRate; 230e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy mMarkerPosition = 0; 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMarkerReached = false; 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNewPosition = 0; 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUpdatePeriod = 0; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInputSource = (uint8_t)inputSource; 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFlags = flags; 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInput = input; 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioSystem::acquireAudioSessionId(mSessionId); 2388cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen 239ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani return NO_ERROR; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioRecord::initCheck() const 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mStatus; 245e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy} 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ------------------------------------------------------------------------- 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectuint32_t AudioRecord::latency() const 2508cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen{ 251ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani return mLatency; 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint AudioRecord::format() const 2559aaa8269a3e7291aab84d01c3fc9c744d8f2d2f4Romain Guy{ 256a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guy return mFormat; 2575c13d89c1332fcc499379b9064b891187b75ca32Chet Haase} 25827f0b17d853d8bef918c3d869044e50cf3904ee3Chet Haase 259a2341a9f6addcd79723965ec5b1a1c5ae0f8bd65Romain Guyint AudioRecord::channelCount() const 26027f0b17d853d8bef918c3d869044e50cf3904ee3Chet Haase{ 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mChannelCount; 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectuint32_t AudioRecord::frameCount() const 2655c13d89c1332fcc499379b9064b891187b75ca32Chet Haase{ 2665c13d89c1332fcc499379b9064b891187b75ca32Chet Haase return mFrameCount; 2675c13d89c1332fcc499379b9064b891187b75ca32Chet Haase} 26827f0b17d853d8bef918c3d869044e50cf3904ee3Chet Haase 2695c13d89c1332fcc499379b9064b891187b75ca32Chet Haaseint AudioRecord::frameSize() const 2705c13d89c1332fcc499379b9064b891187b75ca32Chet Haase{ 27127f0b17d853d8bef918c3d869044e50cf3904ee3Chet Haase if (audio_is_linear_pcm(mFormat)) { 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return channelCount()*audio_bytes_per_sample(mFormat); 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sizeof(uint8_t); 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2772305ac9e4a262ed09fd034ae417e9b1dda4c0ccbVikas Arora 2782305ac9e4a262ed09fd034ae417e9b1dda4c0ccbVikas Aroraint AudioRecord::inputSource() const 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (int)mInputSource; 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ------------------------------------------------------------------------- 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioRecord::start() 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t ret = NO_ERROR; 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<ClientRecordThread> t = mClientRecordThread; 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("start"); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (t != 0) { 2932305ac9e4a262ed09fd034ae417e9b1dda4c0ccbVikas Arora if (t->exitPending()) { 2942305ac9e4a262ed09fd034ae417e9b1dda4c0ccbVikas Arora if (t->requestExitAndWait() == WOULD_BLOCK) { 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("AudioRecord::start called from thread"); 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return WOULD_BLOCK; 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->mLock.lock(); 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30135ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski 30235ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski AutoMutex lock(mLock); 30335ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed 30435ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski // while we are accessing the cblk 30535ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski sp <IAudioRecord> audioRecord = mAudioRecord; 30635ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski sp <IMemory> iMem = mCblkMemory; 30735ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski audio_track_cblk_t* cblk = mCblk; 30835ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski if (mActive == 0) { 30935ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski mActive = 1; 31035ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski 31135ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski cblk->lock.lock(); 31235ef567140e42f354be4a98cce6a7666ac085c13Michal Stawinski if (!(cblk->flags & CBLK_INVALID_MSK)) { 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->lock.unlock(); 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = mAudioRecord->start(); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->lock.lock(); 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret == DEAD_OBJECT) { 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android_atomic_or(CBLK_INVALID_ON, &cblk->flags); 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cblk->flags & CBLK_INVALID_MSK) { 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = restoreRecord_l(cblk); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->lock.unlock(); 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ret == NO_ERROR) { 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNewPosition = cblk->user + mUpdatePeriod; 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->waitTimeMs = 0; 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (t != 0) { 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->run("ClientRecordThread", ANDROID_PRIORITY_AUDIO); 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO); 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mActive = 0; 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (t != 0) { 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->mLock.unlock(); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 3430bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy} 3440bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy 3450bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guystatus_t AudioRecord::stop() 3460bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy{ 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<ClientRecordThread> t = mClientRecordThread; 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGV("stop"); 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 351a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed if (t != 0) { 352a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed t->mLock.lock(); 353a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed } 354a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed 355a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed AutoMutex lock(mLock); 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mActive == 1) { 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mActive = 0; 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCblk->cv.signal(); 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioRecord->stop(); 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the record head position will reset to 0, so if a marker is set, we need 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // to activate it again 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMarkerReached = false; 3638cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen if (t != 0) { 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t->requestExit(); 3658cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen } else { 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL); 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (t != 0) { 371de0dfb7b65a02d4dd74c271b558adee0973fc267Dianne Hackborn t->mLock.unlock(); 3728cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen } 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AudioRecord::stopped() const 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return !mActive; 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectuint32_t AudioRecord::getSampleRate() 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AutoMutex lock(mLock); 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mCblk->sampleRate; 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioRecord::setMarkerPosition(uint32_t marker) 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCbf == 0) return INVALID_OPERATION; 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMarkerPosition = marker; 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMarkerReached = false; 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3958cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen return NO_ERROR; 396e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy} 397e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy 3986062c5912dc79704b489fc8c289b78a400ed05eeDerek Sollenbergerstatus_t AudioRecord::getMarkerPosition(uint32_t *marker) 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (marker == 0) return BAD_VALUE; 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *marker = mMarkerPosition; 4036062c5912dc79704b489fc8c289b78a400ed05eeDerek Sollenberger 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4066579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown 4076579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brownstatus_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod) 4086579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown{ 4096579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown if (mCbf == 0) return INVALID_OPERATION; 4106579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown 4116579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown uint32_t curPosition; 4126579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown getPosition(&curPosition); 4136579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown mNewPosition = curPosition + updatePeriod; 4146579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown mUpdatePeriod = updatePeriod; 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4166579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown return NO_ERROR; 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4188cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen 4196579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brownstatus_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) 420ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani{ 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (updatePeriod == 0) return BAD_VALUE; 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *updatePeriod = mUpdatePeriod; 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 425de0dfb7b65a02d4dd74c271b558adee0973fc267Dianne Hackborn return NO_ERROR; 426de0dfb7b65a02d4dd74c271b558adee0973fc267Dianne Hackborn} 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioRecord::getPosition(uint32_t *position) 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (position == 0) return BAD_VALUE; 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AutoMutex lock(mLock); 4338cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen *position = mCblk->user; 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_ERROR; 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectunsigned int AudioRecord::getInputFramesLost() 439de0dfb7b65a02d4dd74c271b558adee0973fc267Dianne Hackborn{ 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mActive) 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AudioSystem::getInputFramesLost(mInput); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ------------------------------------------------------------------------- 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// must be called with mLock held 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioRecord::openRecord_l( 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t sampleRate, 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t format, 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t channelMask, 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int frameCount, 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t flags, 455b6377170960d40e66858d8b4d335a95eac773762Bart Sears audio_io_handle_t input) 4566579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown{ 4576579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown status_t status; 4586579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); 4596579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown if (audioFlinger == 0) { 4606579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown return NO_INIT; 4616579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown } 462b6377170960d40e66858d8b4d335a95eac773762Bart Sears 4636579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input, 4646579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown sampleRate, format, 465dee4cb07a3652457e18a0bf4be57d2cedeca7359Jack Palevich channelMask, 4666579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown frameCount, 467dee4cb07a3652457e18a0bf4be57d2cedeca7359Jack Palevich ((uint16_t)flags) << 16, 4686579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown &mSessionId, 469dee4cb07a3652457e18a0bf4be57d2cedeca7359Jack Palevich &status); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4716579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown if (record == 0) { 4726579a9d6fe2302fa149452f66c4062ebc60c2523Jeff Brown LOGE("AudioFlinger could not create record track, status: %d", status); 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return status; 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<IMemory> cblk = record->getCblk(); 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cblk == 0) { 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Could not get control block"); 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_INIT; 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioRecord.clear(); 481e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy mAudioRecord = record; 4828cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen mCblkMemory.clear(); 483e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy mCblkMemory = cblk; 484ef7be262e5859efdf805d1b9612bc2b250d5971eEric Hassold mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); 485ef7be262e5859efdf805d1b9612bc2b250d5971eEric Hassold mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); 486ef7be262e5859efdf805d1b9612bc2b250d5971eEric Hassold android_atomic_and(~CBLK_DIRECTION_MSK, &mCblk->flags); 487ef7be262e5859efdf805d1b9612bc2b250d5971eEric Hassold mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; 488ef7be262e5859efdf805d1b9612bc2b250d5971eEric Hassold mCblk->waitTimeMs = 0; 489ef7be262e5859efdf805d1b9612bc2b250d5971eEric Hassold return NO_ERROR; 490ef7be262e5859efdf805d1b9612bc2b250d5971eEric Hassold} 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AutoMutex lock(mLock); 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int active; 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project status_t result = NO_ERROR; 4978cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen audio_track_cblk_t* cblk = mCblk; 498ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani uint32_t framesReq = audioBuffer->frameCount; 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS; 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audioBuffer->frameCount = 0; 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audioBuffer->size = 0; 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t framesReady = cblk->framesReady(); 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (framesReady == 0) { 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->lock.lock(); 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto start_loop_here; 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (framesReady == 0) { 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project active = mActive; 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (UNLIKELY(!active)) { 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->lock.unlock(); 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NO_MORE_BUFFERS; 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5158cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen if (UNLIKELY(!waitCount)) { 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->lock.unlock(); 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return WOULD_BLOCK; 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!(cblk->flags & CBLK_INVALID_MSK)) { 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLock.unlock(); 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->lock.unlock(); 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLock.lock(); 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mActive == 0) { 5258cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen return status_t(STOPPED); 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->lock.lock(); 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cblk->flags & CBLK_INVALID_MSK) { 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto create_new_record; 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (__builtin_expect(result!=NO_ERROR, false)) { 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->waitTimeMs += waitTimeMs; 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGW( "obtainBuffer timed out (is the CPU pegged?) " 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "user=%08x, server=%08x", cblk->user, cblk->server); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->lock.unlock(); 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = mAudioRecord->start(); 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->lock.lock(); 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result == DEAD_OBJECT) { 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android_atomic_or(CBLK_INVALID_ON, &cblk->flags); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectcreate_new_record: 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = AudioRecord::restoreRecord_l(cblk); 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (result != NO_ERROR) { 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGW("obtainBuffer create Track error %d", result); 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->lock.unlock(); 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->waitTimeMs = 0; 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (--waitCount == 0) { 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->lock.unlock(); 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return TIMED_OUT; 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // read the server count again 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start_loop_here: 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project framesReady = cblk->framesReady(); 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5611a81aea8144b92ebaf807af9de69a0ab3415a5aaRomain Guy cblk->lock.unlock(); 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cblk->waitTimeMs = 0; 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (framesReq > framesReady) { 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project framesReq = framesReady; 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t u = cblk->user; 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t bufferEnd = cblk->userBase + cblk->frameCount; 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (u + framesReq > bufferEnd) { 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project framesReq = bufferEnd - u; 5758cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen } 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audioBuffer->flags = 0; 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audioBuffer->channelCount= mChannelCount; 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audioBuffer->format = mFormat; 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audioBuffer->frameCount = framesReq; 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audioBuffer->size = framesReq*cblk->frameSize; 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audioBuffer->raw = (int8_t*)cblk->buffer(u); 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project active = mActive; 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return active ? status_t(NO_ERROR) : status_t(STOPPED); 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid AudioRecord::releaseBuffer(Buffer* audioBuffer) 5888cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen{ 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AutoMutex lock(mLock); 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCblk->stepUser(audioBuffer->frameCount); 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5932c183fa5bf666c5f6b2221fd04db8ee3c738d1fdRomain Guyaudio_io_handle_t AudioRecord::getInput() 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AutoMutex lock(mLock); 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mInput; 59776d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed} 59876d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed 59976d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed// must be called with mLock held 60076d1e01d5e65c4631c827831e98ad4e300d99eabMike Reedaudio_io_handle_t AudioRecord::getInput_l() 60176d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed{ 60276d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed mInput = AudioSystem::getInput(mInputSource, 60376d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed mCblk->sampleRate, 60476d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed mFormat, 60576d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed mChannelMask, 60676d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed (audio_in_acoustics_t)mFlags, 60776d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed mSessionId); 60876d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed return mInput; 60976d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed} 61076d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed 61176d1e01d5e65c4631c827831e98ad4e300d99eabMike Reedint AudioRecord::getSessionId() 61276d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed{ 61376d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed return mSessionId; 61476d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed} 61576d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed 61676d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed// ------------------------------------------------------------------------- 61776d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed 61876d1e01d5e65c4631c827831e98ad4e300d99eabMike Reedssize_t AudioRecord::read(void* buffer, size_t userSize) 61976d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed{ 62076d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed ssize_t read = 0; 62176d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed Buffer audioBuffer; 62276d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed int8_t *dst = static_cast<int8_t*>(buffer); 62376d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed 62476d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed if (ssize_t(userSize) < 0) { 62576d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed // sanity-check. user is most-likely passing an error code. 62676d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed LOGE("AudioRecord::read(buffer=%p, size=%u (%d)", 62776d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed buffer, userSize, userSize); 62876d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed return BAD_VALUE; 62976d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed } 63076d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed 63176d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed mLock.lock(); 63276d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed 63376d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed // while we are accessing the cblk 63476d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed sp <IAudioRecord> audioRecord = mAudioRecord; 63576d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed sp <IMemory> iMem = mCblkMemory; 63676d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed mLock.unlock(); 63776d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed 63876d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed do { 63976d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed 64076d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed audioBuffer.frameCount = userSize/frameSize(); 64176d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed 64276d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed // By using a wait count corresponding to twice the timeout period in 64376d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed // obtainBuffer() we give a chance to recover once for a read timeout 6448cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen // (if media_server crashed for instance) before returning a length of 6458cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen // 0 bytes read to the client 6468cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen status_t err = obtainBuffer(&audioBuffer, ((2 * MAX_RUN_TIMEOUT_MS) / WAIT_PERIOD_MS)); 6478cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen if (err < 0) { 6488cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen // out of buffers, return #bytes written 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err == status_t(NO_MORE_BUFFERS)) 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err == status_t(TIMED_OUT)) 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = 0; 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ssize_t(err); 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t bytesRead = audioBuffer.size; 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memcpy(dst, audioBuffer.i8, bytesRead); 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dst += bytesRead; 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project userSize -= bytesRead; 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project read += bytesRead; 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project releaseBuffer(&audioBuffer); 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (userSize); 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return read; 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 668a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ------------------------------------------------------------------------- 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread) 672de0dfb7b65a02d4dd74c271b558adee0973fc267Dianne Hackborn{ 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Buffer audioBuffer; 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint32_t frames = mRemainingFrames; 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t readSize; 6760bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLock.lock(); 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // while we are accessing the cblk 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp <IAudioRecord> audioRecord = mAudioRecord; 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp <IMemory> iMem = mCblkMemory; 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project audio_track_cblk_t* cblk = mCblk; 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLock.unlock(); 6848cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen 68576d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed // Manage marker callback 68676d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed if (!mMarkerReached && (mMarkerPosition > 0)) { 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (cblk->user >= mMarkerPosition) { 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCbf(EVENT_MARKER, mUserData, (void *)&mMarkerPosition); 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMarkerReached = true; 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Manage new position callback 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mUpdatePeriod > 0) { 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (cblk->user >= mNewPosition) { 696 mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition); 697 mNewPosition += mUpdatePeriod; 698 } 699 } 700 701 do { 702 audioBuffer.frameCount = frames; 703 // Calling obtainBuffer() with a wait count of 1 704 // limits wait time to WAIT_PERIOD_MS. This prevents from being 705 // stuck here not being able to handle timed events (position, markers). 706 status_t err = obtainBuffer(&audioBuffer, 1); 707 if (err < NO_ERROR) { 708 if (err != TIMED_OUT) { 709 LOGE_IF(err != status_t(NO_MORE_BUFFERS), "Error obtaining an audio buffer, giving up."); 710 return false; 711 } 712 break; 713 } 714 if (err == status_t(STOPPED)) return false; 715 716 size_t reqSize = audioBuffer.size; 717 mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); 718 readSize = audioBuffer.size; 719 720 // Sanity check on returned size 721 if (ssize_t(readSize) <= 0) { 722 // The callback is done filling buffers 723 // Keep this thread going to handle timed events and 724 // still try to get more data in intervals of WAIT_PERIOD_MS 725 // but don't just loop and block the CPU, so wait 726 usleep(WAIT_PERIOD_MS*1000); 727 break; 728 } 729 if (readSize > reqSize) readSize = reqSize; 730 731 audioBuffer.size = readSize; 732 audioBuffer.frameCount = readSize/frameSize(); 733 frames -= audioBuffer.frameCount; 734 735 releaseBuffer(&audioBuffer); 736 737 } while (frames); 738 739 740 // Manage overrun callback 741 if (mActive && (cblk->framesAvailable() == 0)) { 742 LOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); 743 if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) { 744 mCbf(EVENT_OVERRUN, mUserData, 0); 745 } 746 } 747 748 if (frames == 0) { 749 mRemainingFrames = mNotificationFrames; 750 } else { 751 mRemainingFrames = frames; 752 } 753 return true; 754} 755 756// must be called with mLock and cblk.lock held. Callers must also hold strong references on 757// the IAudioRecord and IMemory in case they are recreated here. 758// If the IAudioRecord is successfully restored, the cblk pointer is updated 759status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk) 760{ 761 status_t result; 762 763 if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) { 764 LOGW("dead IAudioRecord, creating a new one"); 765 // signal old cblk condition so that other threads waiting for available buffers stop 766 // waiting now 767 cblk->cv.broadcast(); 768 cblk->lock.unlock(); 769 770 // if the new IAudioRecord is created, openRecord_l() will modify the 771 // following member variables: mAudioRecord, mCblkMemory and mCblk. 772 // It will also delete the strong references on previous IAudioRecord and IMemory 773 result = openRecord_l(cblk->sampleRate, mFormat, mChannelMask, 774 mFrameCount, mFlags, getInput_l()); 775 if (result == NO_ERROR) { 776 result = mAudioRecord->start(); 777 } 778 if (result != NO_ERROR) { 779 mActive = false; 780 } 781 782 // signal old cblk condition for other threads waiting for restore completion 783 android_atomic_or(CBLK_RESTORED_ON, &cblk->flags); 784 cblk->cv.broadcast(); 785 } else { 786 if (!(cblk->flags & CBLK_RESTORED_MSK)) { 787 LOGW("dead IAudioRecord, waiting for a new one to be created"); 788 mLock.unlock(); 789 result = cblk->cv.waitRelative(cblk->lock, milliseconds(RESTORE_TIMEOUT_MS)); 790 cblk->lock.unlock(); 791 mLock.lock(); 792 } else { 793 LOGW("dead IAudioRecord, already restored"); 794 result = NO_ERROR; 795 cblk->lock.unlock(); 796 } 797 if (result != NO_ERROR || mActive == 0) { 798 result = status_t(STOPPED); 799 } 800 } 801 LOGV("restoreRecord_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x", 802 result, mActive, mCblk, cblk, mCblk->flags, cblk->flags); 803 804 if (result == NO_ERROR) { 805 // from now on we switch to the newly created cblk 806 cblk = mCblk; 807 } 808 cblk->lock.lock(); 809 810 LOGW_IF(result != NO_ERROR, "restoreRecord_l() error %d", result); 811 812 return result; 813} 814 815// ========================================================================= 816 817AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava) 818 : Thread(bCanCallJava), mReceiver(receiver) 819{ 820} 821 822bool AudioRecord::ClientRecordThread::threadLoop() 823{ 824 return mReceiver.processAudioBuffer(this); 825} 826 827// ------------------------------------------------------------------------- 828 829}; // namespace android 830 831