189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project/* 289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** 389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Copyright 2008, The Android Open Source Project 489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** 589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** you may not use this file except in compliance with the License. 789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** You may obtain a copy of the License at 889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** 989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 1089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** 1189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 1289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 1389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** See the License for the specific language governing permissions and 1589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** limitations under the License. 1689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project*/ 1789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 1889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project//#define LOG_NDEBUG 0 1989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#define LOG_TAG "AudioRecord" 2089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 2134fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn#include <inttypes.h> 2289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <sys/resource.h> 2334fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn 24868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <binder/IPCThreadState.h> 2589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/AudioRecord.h> 2689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <utils/Log.h> 27868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <private/media/AudioTrackShared.h> 281ab85ec401801ef9a9184650d0f5a1639b45eeb9Glenn Kasten#include <media/IAudioFlinger.h> 29734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick#include <media/MediaAnalyticsItem.h> 30734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick#include <media/TypeConverter.h> 3189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#define WAIT_PERIOD_MS 10 339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 3489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectnamespace android { 3515304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh// --------------------------------------------------------------------------- 3615304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh 3715304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh// static 3815304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yehstatus_t AudioRecord::getMinFrameCount( 39e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten size_t* frameCount, 4015304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh uint32_t sampleRate, 4158f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten audio_format_t format, 42dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten audio_channel_mask_t channelMask) 4315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh{ 449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (frameCount == NULL) { 459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 4704cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten 48b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten size_t size; 49c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten status_t status = AudioSystem::getInputBufferSize(sampleRate, format, channelMask, &size); 50c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten if (status != NO_ERROR) { 51b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten ALOGE("AudioSystem could not query the input buffer size for sampleRate %u, format %#x, " 52b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten "channelMask %#x; status %d", sampleRate, format, channelMask, status); 53b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten return status; 5415304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh } 5515304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh 56b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten // We double the size of input buffer for ping pong use of record buffer. 57b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten // Assumes audio_is_linear_pcm(format) 58e541269be94f3a1072932d51537905b120ef4733Andy Hung if ((*frameCount = (size * 2) / (audio_channel_count_from_in_mask(channelMask) * 59e541269be94f3a1072932d51537905b120ef4733Andy Hung audio_bytes_per_sample(format))) == 0) { 60cac3daa6332bf6d1f7d26adc4a9915f3d7992dd9Glenn Kasten ALOGE("Unsupported configuration: sampleRate %u, format %#x, channelMask %#x", 61dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten sampleRate, format, channelMask); 6215304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh return BAD_VALUE; 6315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh } 6415304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh 6515304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh return NO_ERROR; 6615304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh} 6789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 6889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// --------------------------------------------------------------------------- 6989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 70734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essickstatic std::string audioFormatTypeString(audio_format_t value) { 71734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick std::string formatType; 72734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick if (FormatConverter::toString(value, formatType)) { 73734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick return formatType; 74734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick } 75734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick char rawbuffer[16]; // room for "%d" 76734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick snprintf(rawbuffer, sizeof(rawbuffer), "%d", value); 77734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick return rawbuffer; 78734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick} 79734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick 808839430158e22382f0f6450c9274071eca945989Ray Essickstatic std::string audioSourceString(audio_source_t value) { 818839430158e22382f0f6450c9274071eca945989Ray Essick std::string source; 828839430158e22382f0f6450c9274071eca945989Ray Essick if (SourceTypeConverter::toString(value, source)) { 838839430158e22382f0f6450c9274071eca945989Ray Essick return source; 848839430158e22382f0f6450c9274071eca945989Ray Essick } 858839430158e22382f0f6450c9274071eca945989Ray Essick char rawbuffer[16]; // room for "%d" 868839430158e22382f0f6450c9274071eca945989Ray Essick snprintf(rawbuffer, sizeof(rawbuffer), "%d", value); 878839430158e22382f0f6450c9274071eca945989Ray Essick return rawbuffer; 888839430158e22382f0f6450c9274071eca945989Ray Essick} 898839430158e22382f0f6450c9274071eca945989Ray Essick 90734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essickvoid AudioRecord::MediaMetrics::gather(const AudioRecord *record) 91734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick{ 92734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick // key for media statistics is defined in the header 93734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick // attrs for media statistics 94de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essick // NB: these are matched with public Java API constants defined 95de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essick // in frameworks/base/media/java/android/media/AudioRecord.java 96de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essick // These must be kept synchronized with the constants there. 978839430158e22382f0f6450c9274071eca945989Ray Essick static constexpr char kAudioRecordEncoding[] = "android.media.audiorecord.encoding"; 98de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essick static constexpr char kAudioRecordSource[] = "android.media.audiorecord.source"; 99734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick static constexpr char kAudioRecordLatency[] = "android.media.audiorecord.latency"; 100734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick static constexpr char kAudioRecordSampleRate[] = "android.media.audiorecord.samplerate"; 101de15b8c160c720c48b93796016801e7ae0b6bd2dRay Essick static constexpr char kAudioRecordChannelCount[] = "android.media.audiorecord.channels"; 10284e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick static constexpr char kAudioRecordCreated[] = "android.media.audiorecord.createdMs"; 10384e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick static constexpr char kAudioRecordDuration[] = "android.media.audiorecord.durationMs"; 10484e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick static constexpr char kAudioRecordCount[] = "android.media.audiorecord.n"; 10584e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick static constexpr char kAudioRecordError[] = "android.media.audiorecord.errcode"; 10684e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick static constexpr char kAudioRecordErrorFunction[] = "android.media.audiorecord.errfunc"; 107734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick 108734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick // constructor guarantees mAnalyticsItem is valid 109734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick 110734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick mAnalyticsItem->setInt32(kAudioRecordLatency, record->mLatency); 111734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick mAnalyticsItem->setInt32(kAudioRecordSampleRate, record->mSampleRate); 112734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick mAnalyticsItem->setInt32(kAudioRecordChannelCount, record->mChannelCount); 1138839430158e22382f0f6450c9274071eca945989Ray Essick mAnalyticsItem->setCString(kAudioRecordEncoding, 114734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick audioFormatTypeString(record->mFormat).c_str()); 1158839430158e22382f0f6450c9274071eca945989Ray Essick mAnalyticsItem->setCString(kAudioRecordSource, 1168839430158e22382f0f6450c9274071eca945989Ray Essick audioSourceString(record->mAttributes.source).c_str()); 11784e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick 11884e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick // log total duration recording, including anything currently running [and count]. 11984e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick nsecs_t active = 0; 12084e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick if (mStartedNs != 0) { 12184e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick active = systemTime() - mStartedNs; 12284e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick } 12384e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick mAnalyticsItem->setInt64(kAudioRecordDuration, (mDurationNs + active) / (1000 * 1000)); 12484e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick mAnalyticsItem->setInt32(kAudioRecordCount, mCount); 12584e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick 12684e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick // XXX I don't know that this adds a lot of value, long term 12784e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick if (mCreatedNs != 0) { 12884e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick mAnalyticsItem->setInt64(kAudioRecordCreated, mCreatedNs / (1000 * 1000)); 12984e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick } 13084e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick 13184e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick if (mLastError != NO_ERROR) { 13284e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick mAnalyticsItem->setInt32(kAudioRecordError, mLastError); 13384e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick mAnalyticsItem->setCString(kAudioRecordErrorFunction, mLastErrorFunc.c_str()); 13484e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick } 1358839430158e22382f0f6450c9274071eca945989Ray Essick} 1368839430158e22382f0f6450c9274071eca945989Ray Essick 1378839430158e22382f0f6450c9274071eca945989Ray Essick// hand the user a snapshot of the metrics. 1388839430158e22382f0f6450c9274071eca945989Ray Essickstatus_t AudioRecord::getMetrics(MediaAnalyticsItem * &item) 1398839430158e22382f0f6450c9274071eca945989Ray Essick{ 1408839430158e22382f0f6450c9274071eca945989Ray Essick mMediaMetrics.gather(this); 1418839430158e22382f0f6450c9274071eca945989Ray Essick MediaAnalyticsItem *tmp = mMediaMetrics.dup(); 1428839430158e22382f0f6450c9274071eca945989Ray Essick if (tmp == nullptr) { 1438839430158e22382f0f6450c9274071eca945989Ray Essick return BAD_VALUE; 1448839430158e22382f0f6450c9274071eca945989Ray Essick } 1458839430158e22382f0f6450c9274071eca945989Ray Essick item = tmp; 1468839430158e22382f0f6450c9274071eca945989Ray Essick return NO_ERROR; 147734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick} 148734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick 149be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet GanovAudioRecord::AudioRecord(const String16 &opPackageName) 150d3bb645f0b7f567b033b8664499d685f8ec10628Glenn Kasten : mActive(false), mStatus(NO_INIT), mOpPackageName(opPackageName), 151d3bb645f0b7f567b033b8664499d685f8ec10628Glenn Kasten mSessionId(AUDIO_SESSION_ALLOCATE), 152466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT), 153f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE), mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE) 15489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 15589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 15689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 15789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::AudioRecord( 158eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten audio_source_t inputSource, 15989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project uint32_t sampleRate, 16058f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten audio_format_t format, 161624a7fcb377f2a40109c16de5109ae8ea1f67a69Glenn Kasten audio_channel_mask_t channelMask, 162be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov const String16& opPackageName, 163bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten size_t frameCount, 16489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project callback_t cbf, 16589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project void* user, 166838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten uint32_t notificationFrames, 167d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten audio_session_t sessionId, 16827f7b2a8fe899565487d8a326676a5f7d0a05a37Glenn Kasten transfer_type transferType, 169caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent audio_input_flags_t flags, 1701f12a8ad958344c50733b948628ffa06db9c5bc6Andy Hung uid_t uid, 1714cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi pid_t pid, 172fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin const audio_attributes_t* pAttributes, 173fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin audio_port_handle_t selectedDeviceId) 1749b3359feabbf138bb965da5173434da78bfe0929Haynes Mathew George : mActive(false), 1759b3359feabbf138bb965da5173434da78bfe0929Haynes Mathew George mStatus(NO_INIT), 176be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov mOpPackageName(opPackageName), 177be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov mSessionId(AUDIO_SESSION_ALLOCATE), 178e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten mPreviousPriority(ANDROID_PRIORITY_NORMAL), 179e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten mPreviousSchedulingGroup(SP_DEFAULT), 180f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mProxy(NULL) 18189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 182f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent (void)set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user, 183caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags, 184fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin uid, pid, pAttributes, selectedDeviceId); 18589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 18689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 18789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::~AudioRecord() 18889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 189734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick mMediaMetrics.gather(this); 190734d186db7ec3d1f877001d71c71de6562ead7f7Ray Essick 19189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (mStatus == NO_ERROR) { 19289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // Make sure that callback function exits in the case where 19389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // it is looping on buffer empty condition in obtainBuffer(). 19489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // Otherwise the callback thread will never exit. 19589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project stop(); 19668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten if (mAudioRecordThread != 0) { 1975a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten mProxy->interrupt(); 19868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mAudioRecordThread->requestExit(); // see comment in AudioRecord.h 19968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mAudioRecordThread->requestExitAndWait(); 20068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mAudioRecordThread.clear(); 20189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 202296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent // No lock here: worst case we remove a NULL callback which will be a nop 203296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) { 204ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent AudioSystem::removeAudioDeviceCallback(this, mInput); 205296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent } 206f888020c6e2735624f2b2a30e72aca24e17b8b4dMarco Nelissen IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this); 207089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten mAudioRecord.clear(); 2083bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent mCblkMemory.clear(); 2093bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent mBufferMemory.clear(); 21089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project IPCThreadState::self()->flushCommands(); 2114c36d6f48f4eecacc148317f775f65961a4f03d2Glenn Kasten ALOGV("~AudioRecord, releasing session id %d", 2124c36d6f48f4eecacc148317f775f65961a4f03d2Glenn Kasten mSessionId); 2134c36d6f48f4eecacc148317f775f65961a4f03d2Glenn Kasten AudioSystem::releaseAudioSessionId(mSessionId, -1 /*pid*/); 21489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 21589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 21689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 21789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::set( 218eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten audio_source_t inputSource, 21989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project uint32_t sampleRate, 22058f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten audio_format_t format, 221624a7fcb377f2a40109c16de5109ae8ea1f67a69Glenn Kasten audio_channel_mask_t channelMask, 222bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten size_t frameCount, 22389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project callback_t cbf, 22489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project void* user, 225838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten uint32_t notificationFrames, 226be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent bool threadCanCallJava, 227d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten audio_session_t sessionId, 22827f7b2a8fe899565487d8a326676a5f7d0a05a37Glenn Kasten transfer_type transferType, 229caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent audio_input_flags_t flags, 2301f12a8ad958344c50733b948628ffa06db9c5bc6Andy Hung uid_t uid, 2314cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi pid_t pid, 232fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin const audio_attributes_t* pAttributes, 233fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin audio_port_handle_t selectedDeviceId) 23489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 235f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent status_t status = NO_ERROR; 236f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent uint32_t channelCount; 237f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent pid_t callingPid; 238f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent pid_t myPid; 239f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent 240bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, " 2414cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi "notificationFrames %u, sessionId %d, transferType %d, flags %#x, opPackageName %s " 2424cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi "uid %d, pid %d", 243bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten inputSource, sampleRate, format, channelMask, frameCount, notificationFrames, 2444cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi sessionId, transferType, flags, String8(mOpPackageName).string(), uid, pid); 24586f04663032ddaa25110149d709bbf896ad83b02Glenn Kasten 246fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin mSelectedDeviceId = selectedDeviceId; 247fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin 2489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten switch (transferType) { 2499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TRANSFER_DEFAULT: 2509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (cbf == NULL || threadCanCallJava) { 2519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten transferType = TRANSFER_SYNC; 2529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 2539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten transferType = TRANSFER_CALLBACK; 2549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 2569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TRANSFER_CALLBACK: 2579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (cbf == NULL) { 2589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Transfer type TRANSFER_CALLBACK but cbf == NULL"); 259f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent status = BAD_VALUE; 260f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent goto exit; 2619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 2639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TRANSFER_OBTAIN: 2649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TRANSFER_SYNC: 2659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 2669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten default: 2679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Invalid transfer type %d", transferType); 268f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent status = BAD_VALUE; 269f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent goto exit; 2709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mTransfer = transferType; 2729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 273089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten // invariant that mAudioRecord != 0 is true only after set() returns successfully 2741dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent if (mAudioRecord != 0) { 2759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Track already in use"); 276f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent status = INVALID_OPERATION; 277f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent goto exit; 27889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 27989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 280caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent if (pAttributes == NULL) { 281caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent memset(&mAttributes, 0, sizeof(audio_attributes_t)); 282caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent mAttributes.source = inputSource; 283caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent } else { 284caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent // stream type shouldn't be looked at, this track has audio attributes 285caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t)); 286caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent ALOGV("Building AudioRecord with attributes: source=%d flags=0x%x tags=[%s]", 287caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent mAttributes.source, mAttributes.flags, mAttributes.tags); 288caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent } 28989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 290e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten mSampleRate = sampleRate; 291e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten 29289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // these below should probably come from the audioFlinger too... 29358f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten if (format == AUDIO_FORMAT_DEFAULT) { 294fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin format = AUDIO_FORMAT_PCM_16_BIT; 29589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 2969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 297c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent // validate parameters 2986770c6faa3467c92eabc5ec9b23d60eb556a0d03Andy Hung // AudioFlinger capture only supports linear PCM 2996770c6faa3467c92eabc5ec9b23d60eb556a0d03Andy Hung if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) { 3006770c6faa3467c92eabc5ec9b23d60eb556a0d03Andy Hung ALOGE("Format %#x is not linear pcm", format); 301f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent status = BAD_VALUE; 302f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent goto exit; 303291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten } 3042e4664677d72ce54201d3fd0beb0e10280add93cGlenn Kasten mFormat = format; 30589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 3060d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi if (!audio_is_input_channel(channelMask)) { 3079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Invalid channel mask %#x", channelMask); 308f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent status = BAD_VALUE; 309f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent goto exit; 31089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 311a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten mChannelMask = channelMask; 312f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent channelCount = audio_channel_count_from_in_mask(channelMask); 313a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten mChannelCount = channelCount; 314c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 315c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten if (audio_is_linear_pcm(format)) { 316c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten mFrameSize = channelCount * audio_bytes_per_sample(format); 317c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten } else { 318c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten mFrameSize = sizeof(uint8_t); 319c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten } 320e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten 321f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent // mFrameCount is initialized in createRecord_l 322b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten mReqFrameCount = frameCount; 32389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 3244a0efb77198c69df711ab369ac482a42dbdfab07Glenn Kasten mNotificationFramesReq = notificationFrames; 325f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent // mNotificationFramesAct is initialized in createRecord_l 32689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 327f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mSessionId = sessionId; 328ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown ALOGV("set(): mSessionId %d", mSessionId); 329ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown 330f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent callingPid = IPCThreadState::self()->getCallingPid(); 331f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent myPid = getpid(); 332f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent if (uid == AUDIO_UID_INVALID || (callingPid != myPid)) { 3334cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi mClientUid = IPCThreadState::self()->getCallingUid(); 3344cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi } else { 3354cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi mClientUid = uid; 3364cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi } 337f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent if (pid == -1 || (callingPid != myPid)) { 338f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mClientPid = callingPid; 3394cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi } else { 3404cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi mClientPid = pid; 3414cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi } 3424cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi 34358883a0cbbde53579461ef7d9a639b4ac45cb55eGlenn Kasten mOrigFlags = mFlags = flags; 344879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten mCbf = cbf; 345879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten 346879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten if (cbf != NULL) { 347879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten mAudioRecordThread = new AudioRecordThread(*this, threadCanCallJava); 348879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO); 349bfd318402924414fbde4d31c9d23cc423f10b630Glenn Kasten // thread begins in paused state, and will not reference us until start() 350879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten } 351ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown 35234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent // create the IAudioRecord 353f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent status = createRecord_l(0 /*epoch*/, mOpPackageName); 354879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten 35538e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten if (status != NO_ERROR) { 356879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten if (mAudioRecordThread != 0) { 357879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten mAudioRecordThread->requestExit(); // see comment in AudioRecord.h 358879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten mAudioRecordThread->requestExitAndWait(); 359879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten mAudioRecordThread.clear(); 360879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten } 361f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent goto exit; 36289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 36334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent 36489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mUserData = user; 36589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // TODO: add audio hardware input latency here 36613969262f704ca27c82d60e3c7cf4b271e3b5918Andy Hung mLatency = (1000LL * mFrameCount) / mSampleRate; 36789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mMarkerPosition = 0; 3687d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi mMarkerReached = false; 36989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mNewPosition = 0; 37089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mUpdatePeriod = 0; 371d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen AudioSystem::acquireAudioSessionId(mSessionId, -1); 3729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mSequence = 1; 3739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mObservedSequence = mSequence; 3749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mInOverrun = false; 3753f0c902beb53a245c9db35e871607dba05b8d391Andy Hung mFramesRead = 0; 3763f0c902beb53a245c9db35e871607dba05b8d391Andy Hung mFramesReadServerOffset = 0; 37789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 378f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurentexit: 379f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mStatus = status; 38084e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick if (status != NO_ERROR) { 38184e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick mMediaMetrics.markError(status, __FUNCTION__); 38284e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick } 383f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent return status; 38489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 38589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 38689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ------------------------------------------------------------------------- 38789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 388d848eb48c121c119e8ba7583efc75415fe102570Glenn Kastenstatus_t AudioRecord::start(AudioSystem::sync_event_t event, audio_session_t triggerSession) 38989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 390a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent ALOGV("start, sync event %d trigger session %d", event, triggerSession); 39189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 392f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent AutoMutex lock(mLock); 3939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mActive) { 3949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NO_ERROR; 3959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 3961703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 3973f0c902beb53a245c9db35e871607dba05b8d391Andy Hung // discard data in buffer 3983f0c902beb53a245c9db35e871607dba05b8d391Andy Hung const uint32_t framesFlushed = mProxy->flush(); 3993f0c902beb53a245c9db35e871607dba05b8d391Andy Hung mFramesReadServerOffset -= mFramesRead + framesFlushed; 4003f0c902beb53a245c9db35e871607dba05b8d391Andy Hung mFramesRead = 0; 4013f0c902beb53a245c9db35e871607dba05b8d391Andy Hung mProxy->clearTimestamp(); // timestamp is invalid until next server push 4023f0c902beb53a245c9db35e871607dba05b8d391Andy Hung 4039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // reset current position as seen by client to 0 4049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition()); 4055e1f79baa5c7355effbd2c9183787d6604487908Glenn Kasten // force refresh of remaining frames by processAudioBuffer() as last 4065e1f79baa5c7355effbd2c9183787d6604487908Glenn Kasten // read before stop could be partial. 4075e1f79baa5c7355effbd2c9183787d6604487908Glenn Kasten mRefreshRemaining = true; 4086dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten 4099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mNewPosition = mProxy->getPosition() + mUpdatePeriod; 41096f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten int32_t flags = android_atomic_acquire_load(&mCblk->mFlags); 4119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 4123da23b29af4b920d1bd99c097195409f0fabb83bAndy Hung // we reactivate markers (mMarkerPosition != 0) as the position is reset to 0. 4133da23b29af4b920d1bd99c097195409f0fabb83bAndy Hung // This is legacy behavior. This is not done in stop() to avoid a race condition 4143da23b29af4b920d1bd99c097195409f0fabb83bAndy Hung // where the last marker event is issued twice. 4153da23b29af4b920d1bd99c097195409f0fabb83bAndy Hung mMarkerReached = false; 416296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent mActive = true; 417296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent 4189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status_t status = NO_ERROR; 4199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(flags & CBLK_INVALID)) { 420ff6900d8f991aac0b67b625f8a1d4d0461b4c50eIvan Lozano status = mAudioRecord->start(event, triggerSession).transactionError(); 4219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (status == DEAD_OBJECT) { 4229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten flags |= CBLK_INVALID; 4231703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent } 4249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 4259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (flags & CBLK_INVALID) { 4269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = restoreRecord_l("start"); 4279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 4289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 4299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (status != NO_ERROR) { 430296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent mActive = false; 4319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("start() status %d", status); 4329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 4339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten sp<AudioRecordThread> t = mAudioRecordThread; 4349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (t != 0) { 4359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten t->resume(); 4366100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent } else { 4379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mPreviousPriority = getpriority(PRIO_PROCESS, 0); 4389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten get_sched_policy(0, &mPreviousSchedulingGroup); 4399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO); 44089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 44184e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick 44284e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick // we've successfully started, log that time 44384e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick mMediaMetrics.logStart(systemTime()); 44489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 44589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 44684e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick if (status != NO_ERROR) { 44784e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick mMediaMetrics.markError(status, __FUNCTION__); 44884e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick } 4499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return status; 45089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 45189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 452d64cd233eef39430561c1e1df423336a199cc5d7Glenn Kastenvoid AudioRecord::stop() 45389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 454f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent AutoMutex lock(mLock); 4559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!mActive) { 4569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return; 4579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 4589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 4599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mActive = false; 4609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mProxy->interrupt(); 4619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mAudioRecord->stop(); 4623da23b29af4b920d1bd99c097195409f0fabb83bAndy Hung 4633da23b29af4b920d1bd99c097195409f0fabb83bAndy Hung // Note: legacy handling - stop does not clear record marker and 4643da23b29af4b920d1bd99c097195409f0fabb83bAndy Hung // periodic update position; we update those on start(). 4653da23b29af4b920d1bd99c097195409f0fabb83bAndy Hung 4669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten sp<AudioRecordThread> t = mAudioRecordThread; 4679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (t != 0) { 4689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten t->pause(); 4699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 4709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten setpriority(PRIO_PROCESS, 0, mPreviousPriority); 4719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten set_sched_policy(0, mPreviousSchedulingGroup); 47289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 47384e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick 47484e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick // we've successfully started, log that time 47584e84a5dd3b6d9ee4cf032e8d6206c70969b7107Ray Essick mMediaMetrics.logStop(systemTime()); 47689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 47789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 47889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectbool AudioRecord::stopped() const 47989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 48068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten AutoMutex lock(mLock); 48189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return !mActive; 48289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 48389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 48489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setMarkerPosition(uint32_t marker) 48589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 4862b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten // The only purpose of setting marker position is to get a callback 4879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mCbf == NULL) { 4889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return INVALID_OPERATION; 4899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 49089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 491955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten AutoMutex lock(mLock); 49289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mMarkerPosition = marker; 4937d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi mMarkerReached = false; 49489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 495803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung sp<AudioRecordThread> t = mAudioRecordThread; 496803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung if (t != 0) { 497803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung t->wake(); 498803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung } 49989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 50089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 50189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 502606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getMarkerPosition(uint32_t *marker) const 50389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 5049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (marker == NULL) { 5059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 5069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 50789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 508955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten AutoMutex lock(mLock); 50990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung mMarkerPosition.getValue(marker); 51089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 51189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 51289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 51389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 51489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod) 51589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 5162b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten // The only purpose of setting position update period is to get a callback 5179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mCbf == NULL) { 5189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return INVALID_OPERATION; 5199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 520955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten 521955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten AutoMutex lock(mLock); 5229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mNewPosition = mProxy->getPosition() + updatePeriod; 52389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mUpdatePeriod = updatePeriod; 52489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 525803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung sp<AudioRecordThread> t = mAudioRecordThread; 526803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung if (t != 0) { 527803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung t->wake(); 528803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung } 52989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 53089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 53189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 532606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const 53389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 5349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (updatePeriod == NULL) { 5359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 5369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 53789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 538955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten AutoMutex lock(mLock); 53989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project *updatePeriod = mUpdatePeriod; 54089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 54189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 54289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 54389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 544606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getPosition(uint32_t *position) const 54589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 5469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (position == NULL) { 5479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 5489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 54989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 5501703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent AutoMutex lock(mLock); 55190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung mProxy->getPosition().getValue(position); 55289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 55389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return NO_ERROR; 55489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 55589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 5565f972c031d4061f4f037c9fda1ea4bd9b6a756cdGlenn Kastenuint32_t AudioRecord::getInputFramesLost() const 55705bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent{ 558bf04a5d7f287fc712e0ed91849dc85c90c1e182dGlenn Kasten // no need to check mActive, because if inactive this will return 0, which is what we want 55932860f77787f41abac08afdfc2592272ccc31bcbGlenn Kasten return AudioSystem::getInputFramesLost(getInputPrivate()); 56005bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent} 56189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 5623f0c902beb53a245c9db35e871607dba05b8d391Andy Hungstatus_t AudioRecord::getTimestamp(ExtendedTimestamp *timestamp) 5633f0c902beb53a245c9db35e871607dba05b8d391Andy Hung{ 5643f0c902beb53a245c9db35e871607dba05b8d391Andy Hung if (timestamp == nullptr) { 5653f0c902beb53a245c9db35e871607dba05b8d391Andy Hung return BAD_VALUE; 5663f0c902beb53a245c9db35e871607dba05b8d391Andy Hung } 5673f0c902beb53a245c9db35e871607dba05b8d391Andy Hung AutoMutex lock(mLock); 5683f0c902beb53a245c9db35e871607dba05b8d391Andy Hung status_t status = mProxy->getTimestamp(timestamp); 5693f0c902beb53a245c9db35e871607dba05b8d391Andy Hung if (status == OK) { 5703f0c902beb53a245c9db35e871607dba05b8d391Andy Hung timestamp->mPosition[ExtendedTimestamp::LOCATION_CLIENT] = mFramesRead; 5713f0c902beb53a245c9db35e871607dba05b8d391Andy Hung timestamp->mTimeNs[ExtendedTimestamp::LOCATION_CLIENT] = 0; 5723f0c902beb53a245c9db35e871607dba05b8d391Andy Hung // server side frame offset in case AudioRecord has been restored. 5733f0c902beb53a245c9db35e871607dba05b8d391Andy Hung for (int i = ExtendedTimestamp::LOCATION_SERVER; 5743f0c902beb53a245c9db35e871607dba05b8d391Andy Hung i < ExtendedTimestamp::LOCATION_MAX; ++i) { 5753f0c902beb53a245c9db35e871607dba05b8d391Andy Hung if (timestamp->mTimeNs[i] >= 0) { 5763f0c902beb53a245c9db35e871607dba05b8d391Andy Hung timestamp->mPosition[i] += mFramesReadServerOffset; 5773f0c902beb53a245c9db35e871607dba05b8d391Andy Hung } 5783f0c902beb53a245c9db35e871607dba05b8d391Andy Hung } 5793f0c902beb53a245c9db35e871607dba05b8d391Andy Hung } 5803f0c902beb53a245c9db35e871607dba05b8d391Andy Hung return status; 5813f0c902beb53a245c9db35e871607dba05b8d391Andy Hung} 5823f0c902beb53a245c9db35e871607dba05b8d391Andy Hung 583466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean// ---- Explicit Routing --------------------------------------------------- 584466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLeanstatus_t AudioRecord::setInputDevice(audio_port_handle_t deviceId) { 585466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean AutoMutex lock(mLock); 586466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean if (mSelectedDeviceId != deviceId) { 587466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean mSelectedDeviceId = deviceId; 588fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent if (mStatus == NO_ERROR) { 589fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent // stop capture so that audio policy manager does not reject the new instance start request 590fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent // as only one capture can be active at a time. 591fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent if (mAudioRecord != 0 && mActive) { 592fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent mAudioRecord->stop(); 593fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent } 594fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent android_atomic_or(CBLK_INVALID, &mCblk->mFlags); 595fec2f93fae282ad10bbb5e3fcce9f60eff2cfb48jiabin mProxy->interrupt(); 596296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent } 597466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean } 598466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean return NO_ERROR; 599466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean} 600466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean 601466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLeanaudio_port_handle_t AudioRecord::getInputDevice() { 602466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean AutoMutex lock(mLock); 603466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean return mSelectedDeviceId; 604466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean} 605466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean 606ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent// must be called with mLock held 607ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurentvoid AudioRecord::updateRoutedDeviceId_l() 608ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent{ 609ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent // if the record is inactive, do not update actual device as the input stream maybe routed 610ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent // from a device not relevant to this client because of other active use cases. 611ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent if (!mActive) { 612ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent return; 613ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent } 614ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent if (mInput != AUDIO_IO_HANDLE_NONE) { 615ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent audio_port_handle_t deviceId = AudioSystem::getDeviceIdForIo(mInput); 616ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent if (deviceId != AUDIO_PORT_HANDLE_NONE) { 617ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent mRoutedDeviceId = deviceId; 618ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent } 619ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent } 620ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent} 621ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent 622296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurentaudio_port_handle_t AudioRecord::getRoutedDeviceId() { 623296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent AutoMutex lock(mLock); 624ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent updateRoutedDeviceId_l(); 625ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent return mRoutedDeviceId; 626296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent} 627296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent 628724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurentstatus_t AudioRecord::dump(int fd, const Vector<String16>& args __unused) const 629724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent{ 630724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent String8 result; 631724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent 632724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent result.append(" AudioRecord::dump\n"); 633724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent result.appendFormat(" status(%d), active(%d), session Id(%d)\n", 634724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent mStatus, mActive, mSessionId); 635724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent result.appendFormat(" flags(%#x), req. flags(%#x), audio source(%d)\n", 636724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent mFlags, mOrigFlags, mAttributes.source); 637724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent result.appendFormat(" format(%#x), channel mask(%#x), channel count(%u), sample rate(%u)\n", 638724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent mFormat, mChannelMask, mChannelCount, mSampleRate); 639724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent result.appendFormat(" frame count(%zu), req. frame count(%zu)\n", 640724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent mFrameCount, mReqFrameCount); 641724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent result.appendFormat(" notif. frame count(%u), req. notif. frame count(%u)\n", 642724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent mNotificationFramesAct, mNotificationFramesReq); 643724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent result.appendFormat(" input(%d), latency(%u), selected device Id(%d), routed device Id(%d)\n", 644724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent mInput, mLatency, mSelectedDeviceId, mRoutedDeviceId); 645724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent ::write(fd, result.string(), result.size()); 646724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent return NO_ERROR; 647724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent} 648724a1816e7bd503d7a1f491a90f76c8cf3ca6a16Eric Laurent 64989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ------------------------------------------------------------------------- 650adbb75af4d3224194b9b772855db93fae19cf4cePhil Burk// TODO Move this macro to a common header file for enum to string conversion in audio framework. 651adbb75af4d3224194b9b772855db93fae19cf4cePhil Burk#define MEDIA_CASE_ENUM(name) case name: return #name 652adbb75af4d3224194b9b772855db93fae19cf4cePhil Burkconst char * AudioRecord::convertTransferToText(transfer_type transferType) { 653adbb75af4d3224194b9b772855db93fae19cf4cePhil Burk switch (transferType) { 654adbb75af4d3224194b9b772855db93fae19cf4cePhil Burk MEDIA_CASE_ENUM(TRANSFER_DEFAULT); 655adbb75af4d3224194b9b772855db93fae19cf4cePhil Burk MEDIA_CASE_ENUM(TRANSFER_CALLBACK); 656adbb75af4d3224194b9b772855db93fae19cf4cePhil Burk MEDIA_CASE_ENUM(TRANSFER_OBTAIN); 657adbb75af4d3224194b9b772855db93fae19cf4cePhil Burk MEDIA_CASE_ENUM(TRANSFER_SYNC); 658adbb75af4d3224194b9b772855db93fae19cf4cePhil Burk default: 659adbb75af4d3224194b9b772855db93fae19cf4cePhil Burk return "UNRECOGNIZED"; 660adbb75af4d3224194b9b772855db93fae19cf4cePhil Burk } 661adbb75af4d3224194b9b772855db93fae19cf4cePhil Burk} 66289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 6631703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent// must be called with mLock held 664f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurentstatus_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String16& opPackageName) 66534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent{ 66634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); 667f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent IAudioFlinger::CreateRecordInput input; 668f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent IAudioFlinger::CreateRecordOutput output; 669f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent audio_session_t originalSessionId; 670f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent sp<media::IAudioRecord> record; 671f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent void *iMemPointer; 672f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent audio_track_cblk_t* cblk; 673f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent status_t status; 674f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent 67534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent if (audioFlinger == 0) { 676b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten ALOGE("Could not get audioflinger"); 677f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent status = NO_INIT; 678f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent goto exit; 67934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent } 68034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent 68158883a0cbbde53579461ef7d9a639b4ac45cb55eGlenn Kasten // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted. 68258883a0cbbde53579461ef7d9a639b4ac45cb55eGlenn Kasten // After fast request is denied, we will request again if IAudioRecord is re-created. 68358883a0cbbde53579461ef7d9a639b4ac45cb55eGlenn Kasten 6847fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger, 6857fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten // we must release it ourselves if anything goes wrong. 6867fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten 6873151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten // Client can only express a preference for FAST. Server will perform additional tests. 6887fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten if (mFlags & AUDIO_INPUT_FLAG_FAST) { 6897fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten bool useCaseAllowed = 690382d11ac489a917d3d009c3d05bc960f4af58176Phil Burk // any of these use cases: 691b7fbf7ecc6b034243ec64f79f3113675b5e3c941Glenn Kasten // use case 1: callback transfer mode 692b7fbf7ecc6b034243ec64f79f3113675b5e3c941Glenn Kasten (mTransfer == TRANSFER_CALLBACK) || 693382d11ac489a917d3d009c3d05bc960f4af58176Phil Burk // use case 2: blocking read mode 694382d11ac489a917d3d009c3d05bc960f4af58176Phil Burk // The default buffer capacity at 48 kHz is 2048 frames, or ~42.6 ms. 695382d11ac489a917d3d009c3d05bc960f4af58176Phil Burk // That's enough for double-buffering with our standard 20 ms rule of thumb for 696382d11ac489a917d3d009c3d05bc960f4af58176Phil Burk // the minimum period of a non-SCHED_FIFO thread. 697382d11ac489a917d3d009c3d05bc960f4af58176Phil Burk // This is needed so that AAudio apps can do a low latency non-blocking read from a 698382d11ac489a917d3d009c3d05bc960f4af58176Phil Burk // callback running with SCHED_FIFO. 699382d11ac489a917d3d009c3d05bc960f4af58176Phil Burk (mTransfer == TRANSFER_SYNC) || 700382d11ac489a917d3d009c3d05bc960f4af58176Phil Burk // use case 3: obtain/release mode 7017fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten (mTransfer == TRANSFER_OBTAIN); 702adbb75af4d3224194b9b772855db93fae19cf4cePhil Burk if (!useCaseAllowed) { 703adbb75af4d3224194b9b772855db93fae19cf4cePhil Burk ALOGW("AUDIO_INPUT_FLAG_FAST denied, incompatible transfer = %s", 704adbb75af4d3224194b9b772855db93fae19cf4cePhil Burk convertTransferToText(mTransfer)); 7052854e5182172de018a727db5862093a08628811cGlenn Kasten mFlags = (audio_input_flags_t) (mFlags & ~(AUDIO_INPUT_FLAG_FAST | 7062854e5182172de018a727db5862093a08628811cGlenn Kasten AUDIO_INPUT_FLAG_RAW)); 7077fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten } 708c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten } 709c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten 710f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent input.attr = mAttributes; 711f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent input.config.sample_rate = mSampleRate; 712f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent input.config.channel_mask = mChannelMask; 713f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent input.config.format = mFormat; 714f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent input.clientInfo.clientUid = mClientUid; 715f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent input.clientInfo.clientPid = mClientPid; 716f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent input.clientInfo.clientTid = -1; 717ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown if (mFlags & AUDIO_INPUT_FLAG_FAST) { 718c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten if (mAudioRecordThread != 0) { 719f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent input.clientInfo.clientTid = mAudioRecordThread->getTid(); 7203151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten } 7213151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten } 722f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent input.opPackageName = opPackageName; 7233151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten 724f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent input.flags = mFlags; 725f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent // The notification frame count is the period between callbacks, as suggested by the client 726f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent // but moderated by the server. For record, the calculations are done entirely on server side. 727f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent input.frameCount = mReqFrameCount; 728f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent input.notificationFrameCount = mNotificationFramesReq; 729f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent input.selectedDeviceId = mSelectedDeviceId; 730f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent input.sessionId = mSessionId; 731f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent originalSessionId = mSessionId; 732f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent 733f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent record = audioFlinger->createRecord(input, 734f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent output, 735f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent &status); 7363a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen 737c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten if (status != NO_ERROR) { 73829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("AudioFlinger could not create record track, status: %d", status); 739f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent goto exit; 74034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent } 741c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten ALOG_ASSERT(record != 0); 742c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten 74338e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten // AudioFlinger now owns the reference to the I/O handle, 74438e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten // so we are no longer responsible for releasing it. 74538e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten 7462854e5182172de018a727db5862093a08628811cGlenn Kasten mAwaitBoost = false; 747f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent if (output.flags & AUDIO_INPUT_FLAG_FAST) { 748f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent ALOGI("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu -> %zu", 749f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mReqFrameCount, output.frameCount); 750f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mAwaitBoost = true; 7512854e5182172de018a727db5862093a08628811cGlenn Kasten } 752f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mFlags = output.flags; 753f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mRoutedDeviceId = output.selectedDeviceId; 754f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mSessionId = output.sessionId; 755f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mSampleRate = output.sampleRate; 7562854e5182172de018a727db5862093a08628811cGlenn Kasten 757f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent if (output.cblk == 0) { 75829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Could not get control block"); 759f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent status = NO_INIT; 760f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent goto exit; 76134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent } 762f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent iMemPointer = output.cblk ->pointer(); 763e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten if (iMemPointer == NULL) { 764e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten ALOGE("Could not get control block pointer"); 765f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent status = NO_INIT; 766f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent goto exit; 767e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten } 768f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent cblk = static_cast<audio_track_cblk_t*>(iMemPointer); 769d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten 770d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten // Starting address of buffers in shared memory. 771d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten // The buffers are either immediately after the control block, 772d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten // or in a separate area at discretion of server. 773d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten void *buffers; 774f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent if (output.buffers == 0) { 775d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten buffers = cblk + 1; 776d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten } else { 777f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent buffers = output.buffers->pointer(); 778d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten if (buffers == NULL) { 779d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten ALOGE("Could not get buffer pointer"); 780f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent status = NO_INIT; 781f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent goto exit; 782d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten } 783d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten } 784d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten 785089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten // invariant that mAudioRecord != 0 is true only after set() returns successfully 7869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mAudioRecord != 0) { 787f888020c6e2735624f2b2a30e72aca24e17b8b4dMarco Nelissen IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this); 7889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mDeathNotifier.clear(); 7899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 79034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent mAudioRecord = record; 791f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mCblkMemory = output.cblk; 792f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mBufferMemory = output.buffers; 7933bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent IPCThreadState::self()->flushCommands(); 7943bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent 795b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten mCblk = cblk; 796f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent // note that output.frameCount is the (possibly revised) value of mReqFrameCount 797f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent if (output.frameCount < mReqFrameCount || (mReqFrameCount == 0 && output.frameCount == 0)) { 798f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent ALOGW("Requested frameCount %zu but received frameCount %zu", 799f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mReqFrameCount, output.frameCount); 800b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten } 80174935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten 8027fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten // Make sure that application is notified with sufficient margin before overrun. 8037fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten // The computation is done on server side. 804f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent if (mNotificationFramesReq > 0 && output.notificationFrameCount != mNotificationFramesReq) { 8057fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten ALOGW("Server adjusted notificationFrames from %u to %zu for frameCount %zu", 806f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mNotificationFramesReq, output.notificationFrameCount, output.frameCount); 8077410591dad836434c72ddee66680802708b70c10Glenn Kasten } 808f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mNotificationFramesAct = (uint32_t)output.notificationFrameCount; 809ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent 810ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent //mInput != input includes the case where mInput == AUDIO_IO_HANDLE_NONE for first creation 811f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent if (mDeviceCallback != 0 && mInput != output.inputId) { 812ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent if (mInput != AUDIO_IO_HANDLE_NONE) { 813ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent AudioSystem::removeAudioDeviceCallback(this, mInput); 814ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent } 815f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent AudioSystem::addAudioDeviceCallback(this, output.inputId); 816ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent } 817ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent 818045e739161f5ae00321a6cfba20935abb791005bGlenn Kasten // We retain a copy of the I/O handle, but don't own the reference 819f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mInput = output.inputId; 820a5ed48d3476df7dd1e10b380a68e3333f2b646fdGlenn Kasten mRefreshRemaining = true; 821a5ed48d3476df7dd1e10b380a68e3333f2b646fdGlenn Kasten 822f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mFrameCount = output.frameCount; 82311cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten // If IAudioRecord is re-created, don't let the requested frameCount 82411cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten // decrease. This can confuse clients that cache frameCount(). 825f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent if (mFrameCount > mReqFrameCount) { 826f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mReqFrameCount = mFrameCount; 82711cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten } 828b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten 829e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten // update proxy 830ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown mProxy = new AudioRecordClientProxy(cblk, buffers, mFrameCount, mFrameSize); 8319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mProxy->setEpoch(epoch); 8327cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten mProxy->setMinimum(mNotificationFramesAct); 8339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mDeathNotifier = new DeathNotifier(this); 835f888020c6e2735624f2b2a30e72aca24e17b8b4dMarco Nelissen IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this); 836e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten 837f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurentexit: 838f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent mStatus = status; 839f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent // sp<IAudioTrack> track destructor will cause releaseOutput() to be called by AudioFlinger 84038e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten return status; 84134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent} 84234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent 843551b5355d34aa42890811fc3606d3b63429296cdGlenn Kastenstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount, size_t *nonContig) 84489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 8459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (audioBuffer == NULL) { 846551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten if (nonContig != NULL) { 847551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten *nonContig = 0; 848551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten } 8499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return BAD_VALUE; 8509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mTransfer != TRANSFER_OBTAIN) { 8529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->frameCount = 0; 8539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->size = 0; 8549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->raw = NULL; 855551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten if (nonContig != NULL) { 856551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten *nonContig = 0; 857551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten } 8589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return INVALID_OPERATION; 8599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 860e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten 8619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten const struct timespec *requested; 862df576995a5aad3428aeeef765387d650945c161dEric Laurent struct timespec timeout; 8639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (waitCount == -1) { 8649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &ClientProxy::kForever; 8659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (waitCount == 0) { 8669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &ClientProxy::kNonBlocking; 8679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (waitCount > 0) { 8689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten long long ms = WAIT_PERIOD_MS * (long long) waitCount; 8699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout.tv_sec = ms / 1000; 8709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout.tv_nsec = (int) (ms % 1000) * 1000000; 8719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &timeout; 8729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 8739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("%s invalid waitCount %d", __func__, waitCount); 8749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = NULL; 8759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 876551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten return obtainBuffer(audioBuffer, requested, NULL /*elapsed*/, nonContig); 8779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 8789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *requested, 8809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec *elapsed, size_t *nonContig) 8819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 8829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // previous and new IAudioRecord sequence numbers are used to detect track re-creation 8839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten uint32_t oldSequence = 0; 8849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten uint32_t newSequence; 8859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten Proxy::Buffer buffer; 8879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status_t status = NO_ERROR; 8889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten static const int32_t kMaxTries = 5; 8909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t tryCounter = kMaxTries; 8919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten do { 8939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // obtainBuffer() is called with mutex unlocked, so keep extra references to these fields to 8949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // keep them from going away if another thread re-creates the track during obtainBuffer() 8959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten sp<AudioRecordClientProxy> proxy; 8969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten sp<IMemory> iMem; 897d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten sp<IMemory> bufferMem; 8989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten { 8999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // start of lock scope 9009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten AutoMutex lock(mLock); 9019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 9029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newSequence = mSequence; 9039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // did previous obtainBuffer() fail due to media server death or voluntary invalidation? 9049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (status == DEAD_OBJECT) { 9059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // re-create track, unless someone else has already done so 9069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (newSequence == oldSequence) { 9079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = restoreRecord_l("obtainBuffer"); 9089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (status != NO_ERROR) { 909d8a9d0220e84ae0b5049385aa9b1a0d8ea02b5bbGlenn Kasten buffer.mFrameCount = 0; 910d8a9d0220e84ae0b5049385aa9b1a0d8ea02b5bbGlenn Kasten buffer.mRaw = NULL; 911d8a9d0220e84ae0b5049385aa9b1a0d8ea02b5bbGlenn Kasten buffer.mNonContig = 0; 9129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 91334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent } 91489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 91589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 9169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten oldSequence = newSequence; 91789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 9189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Keep the extra references 9199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten proxy = mProxy; 9209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten iMem = mCblkMemory; 921d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten bufferMem = mBufferMemory; 922c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 9239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Non-blocking if track is stopped 9249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!mActive) { 9259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &ClientProxy::kNonBlocking; 9269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 92789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 9289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } // end of lock scope 92989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 9309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer.mFrameCount = audioBuffer->frameCount; 9319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME starts the requested timeout and elapsed over from scratch 9329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = proxy->obtainBuffer(&buffer, requested, elapsed); 9339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 9349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } while ((status == DEAD_OBJECT) && (tryCounter-- > 0)); 93589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 9369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->frameCount = buffer.mFrameCount; 9379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->size = buffer.mFrameCount * mFrameSize; 9389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer->raw = buffer.mRaw; 9399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (nonContig != NULL) { 9409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten *nonContig = buffer.mNonContig; 9419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 9429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return status; 94389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 94489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 9455014c94c1bbac4a4284576b0015ba75145237593Glenn Kastenvoid AudioRecord::releaseBuffer(const Buffer* audioBuffer) 94689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 94717ea1351633d4f5e4f9eafd0778eb8b59fa30f10Glenn Kasten // FIXME add error checking on mode, by adding an internal version 9489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 9499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t stepCount = audioBuffer->size / mFrameSize; 9509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (stepCount == 0) { 9519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return; 9529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 9539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 9549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten Proxy::Buffer buffer; 9559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer.mFrameCount = stepCount; 9569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer.mRaw = audioBuffer->raw; 957e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten 9581703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent AutoMutex lock(mLock); 9599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mInOverrun = false; 9609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mProxy->releaseBuffer(&buffer); 9619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 9629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // the server does not automatically disable recorder on overrun, so no need to restart 96389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 96489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 96532860f77787f41abac08afdfc2592272ccc31bcbGlenn Kastenaudio_io_handle_t AudioRecord::getInputPrivate() const 9666100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent{ 9671703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent AutoMutex lock(mLock); 968d1a243e41caffa8fd346907eed4625c9c47c1a86Eric Laurent return mInput; 9691703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent} 9701703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 97189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ------------------------------------------------------------------------- 97289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 9733622cdff65f34a99d2f55936a895387ad41510ceGlenn Kastenssize_t AudioRecord::read(void* buffer, size_t userSize, bool blocking) 97489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 9759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mTransfer != TRANSFER_SYNC) { 9769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return INVALID_OPERATION; 9779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 97889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 9799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) { 9809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // sanity-check. user is most-likely passing an error code, and it would 9819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // make the return value ambiguous (actualSize vs error). 98234fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGE("AudioRecord::read(buffer=%p, size=%zu (%zu)", buffer, userSize, userSize); 98389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return BAD_VALUE; 98489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 98589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 9869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ssize_t read = 0; 9879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten Buffer audioBuffer; 98889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 9899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten while (userSize >= mFrameSize) { 9909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer.frameCount = userSize / mFrameSize; 99189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 9923622cdff65f34a99d2f55936a895387ad41510ceGlenn Kasten status_t err = obtainBuffer(&audioBuffer, 9933622cdff65f34a99d2f55936a895387ad41510ceGlenn Kasten blocking ? &ClientProxy::kForever : &ClientProxy::kNonBlocking); 99489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project if (err < 0) { 9959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (read > 0) { 99689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project break; 997d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten } 9980a2f151f37c715078351ae0be99b0c4dbabc2a23Glenn Kasten if (err == TIMED_OUT || err == -EINTR) { 9990a2f151f37c715078351ae0be99b0c4dbabc2a23Glenn Kasten err = WOULD_BLOCK; 10000a2f151f37c715078351ae0be99b0c4dbabc2a23Glenn Kasten } 100189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return ssize_t(err); 100289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 100389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 100489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project size_t bytesRead = audioBuffer.size; 10059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten memcpy(buffer, audioBuffer.i8, bytesRead); 10069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer = ((char *) buffer) + bytesRead; 100789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project userSize -= bytesRead; 100889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project read += bytesRead; 100989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 101089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project releaseBuffer(&audioBuffer); 10119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 10123f0c902beb53a245c9db35e871607dba05b8d391Andy Hung if (read > 0) { 10133f0c902beb53a245c9db35e871607dba05b8d391Andy Hung mFramesRead += read / mFrameSize; 10143f0c902beb53a245c9db35e871607dba05b8d391Andy Hung // mFramesReadTime = systemTime(SYSTEM_TIME_MONOTONIC); // not provided at this time. 10153f0c902beb53a245c9db35e871607dba05b8d391Andy Hung } 101689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project return read; 101789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 101889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 101989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ------------------------------------------------------------------------- 102089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 10217c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kastennsecs_t AudioRecord::processAudioBuffer() 102289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 10231703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent mLock.lock(); 102428f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten if (mAwaitBoost) { 102528f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten mAwaitBoost = false; 102628f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten mLock.unlock(); 102728f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten static const int32_t kMaxTries = 5; 102828f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten int32_t tryCounter = kMaxTries; 102928f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten uint32_t pollUs = 10000; 103028f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten do { 10318255ba7b40774b2b8868482f1a302db3ae98e905Glenn Kasten int policy = sched_getscheduler(0) & ~SCHED_RESET_ON_FORK; 103228f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten if (policy == SCHED_FIFO || policy == SCHED_RR) { 103328f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten break; 103428f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten } 103528f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten usleep(pollUs); 103628f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten pollUs <<= 1; 103728f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten } while (tryCounter-- > 0); 103828f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten if (tryCounter < 0) { 103928f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten ALOGE("did not receive expected priority boost on time"); 104028f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten } 104128f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten // Run again immediately 104228f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten return 0; 104328f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten } 10449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 10459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Can only reference mCblk while locked 104696f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten int32_t flags = android_atomic_and(~CBLK_OVERRUN, &mCblk->mFlags); 10479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 10489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Check for track invalidation 10499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (flags & CBLK_INVALID) { 10509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten (void) restoreRecord_l("processAudioBuffer"); 10519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mLock.unlock(); 10529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Run again immediately, but with a new IAudioRecord 10539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return 0; 10549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 10559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 105668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten bool active = mActive; 10579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 10589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Manage overrun callback, must be done under lock to avoid race with releaseBuffer() 10599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool newOverrun = false; 10609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (flags & CBLK_OVERRUN) { 10619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!mInOverrun) { 10629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mInOverrun = true; 10639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newOverrun = true; 10649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 10659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 10669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 10679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Get current position of server 106890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung Modulo<uint32_t> position(mProxy->getPosition()); 10699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 10709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Manage marker callback 10719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool markerReached = false; 107290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung Modulo<uint32_t> markerPosition(mMarkerPosition); 10739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME fails for wraparound, need 64 bits 107490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung if (!mMarkerReached && markerPosition.value() > 0 && position >= markerPosition) { 10759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mMarkerReached = markerReached = true; 10769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 10779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 10789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Determine the number of new position callback(s) that will be needed, while locked 10799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t newPosCount = 0; 108090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung Modulo<uint32_t> newPosition(mNewPosition); 1081955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten uint32_t updatePeriod = mUpdatePeriod; 10829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME fails for wraparound, need 64 bits 10839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (updatePeriod > 0 && position >= newPosition) { 108490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung newPosCount = ((position - newPosition).value() / updatePeriod) + 1; 10859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mNewPosition += updatePeriod * newPosCount; 10869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 10879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 10889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Cache other fields that will be needed soon 1089838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten uint32_t notificationFrames = mNotificationFramesAct; 10909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mRefreshRemaining) { 10919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRefreshRemaining = false; 10929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRemainingFrames = notificationFrames; 10939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRetryOnPartialBuffer = false; 10949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 10959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t misalignment = mProxy->getMisalignment(); 10968ff50e7526d24aca11713006933b8dcb64ef6be9Glenn Kasten uint32_t sequence = mSequence; 10979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 10989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // These fields don't need to be cached, because they are assigned only by set(): 10992b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten // mTransfer, mCbf, mUserData, mSampleRate, mFrameSize 11009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 11011703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent mLock.unlock(); 11021703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 11039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // perform callbacks while unlocked 11049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (newOverrun) { 11059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mCbf(EVENT_OVERRUN, mUserData, NULL); 11069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 11079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (markerReached) { 1108955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten mCbf(EVENT_MARKER, mUserData, &markerPosition); 110989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 11109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten while (newPosCount > 0) { 111190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung size_t temp = newPosition.value(); // FIXME size_t != uint32_t 1112955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten mCbf(EVENT_NEW_POS, mUserData, &temp); 1113955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten newPosition += updatePeriod; 11149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newPosCount--; 11159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 11169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mObservedSequence != sequence) { 11179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mObservedSequence = sequence; 11189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mCbf(EVENT_NEW_IAUDIORECORD, mUserData, NULL); 111989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 112089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 11219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // if inactive, then don't run me again until re-started 11229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!active) { 11239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NS_INACTIVE; 11249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 11259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 11269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Compute the estimated time until the next timed event (position, markers) 11279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten uint32_t minFrames = ~0; 11289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!markerReached && position < markerPosition) { 112990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung minFrames = (markerPosition - position).value(); 11309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1131fb7df2c355aad453f1978207e4116b2d4a61f34bAndy Hung if (updatePeriod > 0) { 113290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung uint32_t remaining = (newPosition - position).value(); 1133fb7df2c355aad453f1978207e4116b2d4a61f34bAndy Hung if (remaining < minFrames) { 1134fb7df2c355aad453f1978207e4116b2d4a61f34bAndy Hung minFrames = remaining; 1135fb7df2c355aad453f1978207e4116b2d4a61f34bAndy Hung } 11369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 11379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 11389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // If > 0, poll periodically to recover from a stuck server. A good value is 2. 11399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten static const uint32_t kPoll = 0; 11409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (kPoll > 0 && mTransfer == TRANSFER_CALLBACK && kPoll * notificationFrames < minFrames) { 11419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten minFrames = kPoll * notificationFrames; 11429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 11439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 11449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Convert frame units to time units 11459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten nsecs_t ns = NS_WHENEVER; 11469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (minFrames != (uint32_t) ~0) { 11479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // This "fudge factor" avoids soaking CPU, and compensates for late progress by server 11489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten static const nsecs_t kFudgeNs = 10000000LL; // 10 ms 11499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ns = ((minFrames * 1000000000LL) / mSampleRate) + kFudgeNs; 11509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 11519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 11529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // If not supplying data by EVENT_MORE_DATA, then we're done 11539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mTransfer != TRANSFER_CALLBACK) { 11549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return ns; 11559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 11569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 11579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec timeout; 11589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten const struct timespec *requested = &ClientProxy::kForever; 11599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (ns != NS_WHENEVER) { 11609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout.tv_sec = ns / 1000000000LL; 11619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout.tv_nsec = ns % 1000000000LL; 11629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGV("timeout %ld.%03d", timeout.tv_sec, (int) timeout.tv_nsec / 1000000); 11639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &timeout; 11649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 11659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 11663f0c902beb53a245c9db35e871607dba05b8d391Andy Hung size_t readFrames = 0; 11679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten while (mRemainingFrames > 0) { 11689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 11699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten Buffer audioBuffer; 11709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer.frameCount = mRemainingFrames; 11719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t nonContig; 11729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig); 11739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0), 117434fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn "obtainBuffer() err=%d frameCount=%zu", err, audioBuffer.frameCount); 11759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &ClientProxy::kNonBlocking; 11769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t avail = audioBuffer.frameCount + nonContig; 117734fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGV("obtainBuffer(%u) returned %zu = %zu + %zu err %d", 11782b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err); 11799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (err != NO_ERROR) { 11809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR) { 11819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 11829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 11839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Error %d obtaining an audio buffer, giving up.", err); 11849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NS_NEVER; 11859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 11869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 11879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mRetryOnPartialBuffer) { 11889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRetryOnPartialBuffer = false; 11899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (avail < mRemainingFrames) { 11909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int64_t myns = ((mRemainingFrames - avail) * 11919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 1100000000LL) / mSampleRate; 11929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (ns < 0 || myns < ns) { 11939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ns = myns; 11949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 11959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return ns; 119689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 119789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 119889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 119989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project size_t reqSize = audioBuffer.size; 120089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); 12019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t readSize = audioBuffer.size; 120289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 120389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project // Sanity check on returned size 12049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (ssize_t(readSize) < 0 || readSize > reqSize) { 120534fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGE("EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes", 120634fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn reqSize, ssize_t(readSize)); 12079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NS_NEVER; 12089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 12099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 12109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (readSize == 0) { 12119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // The callback is done consuming buffers 1212cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent // Keep this thread going to handle timed events and 12139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // still try to provide more data in intervals of WAIT_PERIOD_MS 1214cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent // but don't just loop and block the CPU, so wait 12159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return WAIT_PERIOD_MS * 1000000LL; 1216cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent } 121789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 12189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t releasedFrames = readSize / mFrameSize; 12199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioBuffer.frameCount = releasedFrames; 12209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRemainingFrames -= releasedFrames; 12219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (misalignment >= releasedFrames) { 12229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten misalignment -= releasedFrames; 12239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 12249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten misalignment = 0; 12259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 122689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 122789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project releaseBuffer(&audioBuffer); 12283f0c902beb53a245c9db35e871607dba05b8d391Andy Hung readFrames += releasedFrames; 122989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 12309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME here is where we would repeat EVENT_MORE_DATA again on same advanced buffer 12319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // if callback doesn't like to accept the full chunk 12329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (readSize < reqSize) { 12339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten continue; 12349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 123589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 12369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // There could be enough non-contiguous frames available to satisfy the remaining request 12379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mRemainingFrames <= nonContig) { 12389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten continue; 12399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1240c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent 12419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#if 0 12429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // This heuristic tries to collapse a series of EVENT_MORE_DATA that would total to a 12439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // sum <= notificationFrames. It replaces that series by at most two EVENT_MORE_DATA 12449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // that total to a sum == notificationFrames. 12459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (0 < misalignment && misalignment <= mRemainingFrames) { 12469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRemainingFrames = misalignment; 12479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return (mRemainingFrames * 1100000000LL) / mSampleRate; 124889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 12499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#endif 125089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 125189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project } 12523f0c902beb53a245c9db35e871607dba05b8d391Andy Hung if (readFrames > 0) { 12533f0c902beb53a245c9db35e871607dba05b8d391Andy Hung AutoMutex lock(mLock); 12543f0c902beb53a245c9db35e871607dba05b8d391Andy Hung mFramesRead += readFrames; 12553f0c902beb53a245c9db35e871607dba05b8d391Andy Hung // mFramesReadTime = systemTime(SYSTEM_TIME_MONOTONIC); // not provided at this time. 12563f0c902beb53a245c9db35e871607dba05b8d391Andy Hung } 12579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRemainingFrames = notificationFrames; 12589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mRetryOnPartialBuffer = true; 12599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 12609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // A lot has transpired since ns was calculated, so run again immediately and re-calculate 12619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return 0; 126289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 126389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 12649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t AudioRecord::restoreRecord_l(const char *from) 12651703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent{ 12669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGW("dead IAudioRecord, creating a new one from %s()", from); 12679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ++mSequence; 12681703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 1269b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean const int INITIAL_RETRIES = 3; 1270b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean int retries = INITIAL_RETRIES; 1271b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLeanretry: 1272b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean if (retries < INITIAL_RETRIES) { 1273b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean // refresh the audio configuration cache in this process to make sure we get new 1274b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean // input parameters and new IAudioRecord in createRecord_l() 1275b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean AudioSystem::clearAudioConfigCache(); 1276b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean } 127758883a0cbbde53579461ef7d9a639b4ac45cb55eGlenn Kasten mFlags = mOrigFlags; 127858883a0cbbde53579461ef7d9a639b4ac45cb55eGlenn Kasten 1279f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent // if the new IAudioRecord is created, createRecord_l() will modify the 1280d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten // following member variables: mAudioRecord, mCblkMemory, mCblk, mBufferMemory. 1281b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten // It will also delete the strong references on previous IAudioRecord and IMemory 128290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung Modulo<uint32_t> position(mProxy->getPosition()); 12839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mNewPosition = position + mUpdatePeriod; 1284f14db3c3ebc1ea29b3eb5b7e9b944cabcb5f83ffEric Laurent status_t result = createRecord_l(position, mOpPackageName); 1285b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean 1286b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean if (result != NO_ERROR) { 1287b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean ALOGW("%s(): createRecord_l failed, do not retry", __func__); 1288b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean retries = 0; 1289b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean } else { 12909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mActive) { 12919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // callback thread or sync event hasn't changed 12929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME this fails if we have a new AudioFlinger instance 1293ff6900d8f991aac0b67b625f8a1d4d0461b4c50eIvan Lozano result = mAudioRecord->start( 1294ff6900d8f991aac0b67b625f8a1d4d0461b4c50eIvan Lozano AudioSystem::SYNC_EVENT_SAME, AUDIO_SESSION_NONE).transactionError(); 12959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 12963f0c902beb53a245c9db35e871607dba05b8d391Andy Hung mFramesReadServerOffset = mFramesRead; // server resets to zero so we need an offset. 1297b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten } 1298b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean 1299b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean if (result != NO_ERROR) { 1300b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean ALOGW("%s() failed status %d, retries %d", __func__, result, retries); 1301b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean if (--retries > 0) { 1302b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean goto retry; 1303b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean } 1304b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean } 1305b8ca98e81617f33e1b15a210c673b8f4c5a6de28Paul McLean 1306b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten if (result != NO_ERROR) { 13079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGW("restoreRecord_l() failed status %d", result); 1308b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten mActive = false; 13091703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent } 1310b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten 13119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return result; 13129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 13131703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 1314296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurentstatus_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback) 1315296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent{ 1316296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent if (callback == 0) { 1317296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent ALOGW("%s adding NULL callback!", __FUNCTION__); 1318296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent return BAD_VALUE; 1319296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent } 1320296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent AutoMutex lock(mLock); 1321ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent if (mDeviceCallback.unsafe_get() == callback.get()) { 1322296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent ALOGW("%s adding same callback!", __FUNCTION__); 1323296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent return INVALID_OPERATION; 1324296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent } 1325296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent status_t status = NO_ERROR; 1326296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent if (mInput != AUDIO_IO_HANDLE_NONE) { 1327296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent if (mDeviceCallback != 0) { 1328296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent ALOGW("%s callback already present!", __FUNCTION__); 1329ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent AudioSystem::removeAudioDeviceCallback(this, mInput); 1330296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent } 1331ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent status = AudioSystem::addAudioDeviceCallback(this, mInput); 1332296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent } 1333296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent mDeviceCallback = callback; 1334296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent return status; 1335296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent} 1336296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent 1337296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurentstatus_t AudioRecord::removeAudioDeviceCallback( 1338296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent const sp<AudioSystem::AudioDeviceCallback>& callback) 1339296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent{ 1340296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent if (callback == 0) { 1341296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent ALOGW("%s removing NULL callback!", __FUNCTION__); 1342296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent return BAD_VALUE; 1343296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent } 1344296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent AutoMutex lock(mLock); 1345ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent if (mDeviceCallback.unsafe_get() != callback.get()) { 1346296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent ALOGW("%s removing different callback!", __FUNCTION__); 1347296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent return INVALID_OPERATION; 1348296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent } 1349ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent mDeviceCallback.clear(); 1350296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent if (mInput != AUDIO_IO_HANDLE_NONE) { 1351ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent AudioSystem::removeAudioDeviceCallback(this, mInput); 1352296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent } 1353296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent return NO_ERROR; 1354296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent} 1355296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent 1356ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurentvoid AudioRecord::onAudioDeviceUpdate(audio_io_handle_t audioIo, 1357ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent audio_port_handle_t deviceId) 1358ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent{ 1359ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent sp<AudioSystem::AudioDeviceCallback> callback; 1360ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent { 1361ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent AutoMutex lock(mLock); 1362ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent if (audioIo != mInput) { 1363ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent return; 1364ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent } 1365ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent callback = mDeviceCallback.promote(); 1366ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent // only update device if the record is active as route changes due to other use cases are 1367ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent // irrelevant for this client 1368ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent if (mActive) { 1369ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent mRoutedDeviceId = deviceId; 1370ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent } 1371ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent } 1372ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent if (callback.get() != nullptr) { 1373ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent callback->onAudioDeviceUpdate(mInput, mRoutedDeviceId); 1374ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent } 1375ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent} 1376ad2e7b902c0432a0db40906a4b1f5b693ce439ddEric Laurent 1377653cc0ab6d5b714d1f26adcd08f9bc3269b62fa0jiabin// ------------------------------------------------------------------------- 1378653cc0ab6d5b714d1f26adcd08f9bc3269b62fa0jiabin 1379653cc0ab6d5b714d1f26adcd08f9bc3269b62fa0jiabinstatus_t AudioRecord::getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones) 1380653cc0ab6d5b714d1f26adcd08f9bc3269b62fa0jiabin{ 1381653cc0ab6d5b714d1f26adcd08f9bc3269b62fa0jiabin AutoMutex lock(mLock); 1382653cc0ab6d5b714d1f26adcd08f9bc3269b62fa0jiabin return mAudioRecord->getActiveMicrophones(activeMicrophones).transactionError(); 1383653cc0ab6d5b714d1f26adcd08f9bc3269b62fa0jiabin} 1384653cc0ab6d5b714d1f26adcd08f9bc3269b62fa0jiabin 13859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// ========================================================================= 13861703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 13877c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kastenvoid AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused) 13889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 13899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten sp<AudioRecord> audioRecord = mAudioRecord.promote(); 13909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (audioRecord != 0) { 13919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten AutoMutex lock(audioRecord->mLock); 13929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audioRecord->mProxy->binderDied(); 13939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 13941703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent} 13951703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent 139689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ========================================================================= 139789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 139868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn KastenAudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver, bool bCanCallJava) 139941721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mPausedInt(false), mPausedNs(0LL), 140041721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten mIgnoreNextPausedInt(false) 140168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{ 140268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten} 140368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten 140468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn KastenAudioRecord::AudioRecordThread::~AudioRecordThread() 140568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{ 140668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten} 140768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten 140868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenbool AudioRecord::AudioRecordThread::threadLoop() 140968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{ 141068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten { 141168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten AutoMutex _l(mMyLock); 141268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten if (mPaused) { 141375f79038715b4b1cf28e0457abfa84ccd17bb57eGlenn Kasten // TODO check return value and handle or log 141468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mMyCond.wait(mMyLock); 141568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten // caller will check for exitPending() 141668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten return true; 141768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten } 141841721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten if (mIgnoreNextPausedInt) { 141941721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten mIgnoreNextPausedInt = false; 142041721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten mPausedInt = false; 142141721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten } 14225a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten if (mPausedInt) { 14235a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten if (mPausedNs > 0) { 142475f79038715b4b1cf28e0457abfa84ccd17bb57eGlenn Kasten // TODO check return value and handle or log 14255a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten (void) mMyCond.waitRelative(mMyLock, mPausedNs); 14265a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten } else { 142775f79038715b4b1cf28e0457abfa84ccd17bb57eGlenn Kasten // TODO check return value and handle or log 14285a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten mMyCond.wait(mMyLock); 14295a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten } 14309d2c78c4798ffd8c276c1bf0eaa0b34bc255a2daEric Laurent mPausedInt = false; 14315a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten return true; 14325a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten } 143368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten } 1434e813ef9388e9f0b821c0a434521f0e194288c8adKiran Kumar Krishna if (exitPending()) { 1435e813ef9388e9f0b821c0a434521f0e194288c8adKiran Kumar Krishna return false; 1436e813ef9388e9f0b821c0a434521f0e194288c8adKiran Kumar Krishna } 14377c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kasten nsecs_t ns = mReceiver.processAudioBuffer(); 14389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten switch (ns) { 14399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case 0: 14409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return true; 14419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case NS_INACTIVE: 14425a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten pauseInternal(); 14439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return true; 14449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case NS_NEVER: 14459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return false; 14465a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten case NS_WHENEVER: 1447803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung // Event driven: call wake() when callback notifications conditions change. 1448803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung ns = INT64_MAX; 14495a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten // fall through 14509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten default: 145134fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %" PRId64, ns); 14525a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten pauseInternal(ns); 14539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return true; 145468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten } 145568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten} 145668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten 145768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::requestExit() 145889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 145968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten // must be in this order to avoid a race condition 146068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten Thread::requestExit(); 146141721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten resume(); 146289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 146389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 146468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::pause() 146589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{ 146668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten AutoMutex _l(mMyLock); 146768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mPaused = true; 146889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project} 146989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 147068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::resume() 14716dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten{ 147268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten AutoMutex _l(mMyLock); 147341721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten mIgnoreNextPausedInt = true; 14749d2c78c4798ffd8c276c1bf0eaa0b34bc255a2daEric Laurent if (mPaused || mPausedInt) { 147568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mPaused = false; 14769d2c78c4798ffd8c276c1bf0eaa0b34bc255a2daEric Laurent mPausedInt = false; 147768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten mMyCond.signal(); 14786dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten } 14796dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten} 14806dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten 1481803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hungvoid AudioRecord::AudioRecordThread::wake() 1482803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung{ 1483803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung AutoMutex _l(mMyLock); 1484805a0c70574676d0fb29aa5e1f23417786b42259Andy Hung if (!mPaused) { 1485805a0c70574676d0fb29aa5e1f23417786b42259Andy Hung // wake() might be called while servicing a callback - ignore the next 1486805a0c70574676d0fb29aa5e1f23417786b42259Andy Hung // pause time and call processAudioBuffer. 1487803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung mIgnoreNextPausedInt = true; 1488805a0c70574676d0fb29aa5e1f23417786b42259Andy Hung if (mPausedInt && mPausedNs > 0) { 1489805a0c70574676d0fb29aa5e1f23417786b42259Andy Hung // audio record is active and internally paused with timeout. 1490805a0c70574676d0fb29aa5e1f23417786b42259Andy Hung mPausedInt = false; 1491805a0c70574676d0fb29aa5e1f23417786b42259Andy Hung mMyCond.signal(); 1492805a0c70574676d0fb29aa5e1f23417786b42259Andy Hung } 1493803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung } 1494803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung} 1495803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung 14965a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kastenvoid AudioRecord::AudioRecordThread::pauseInternal(nsecs_t ns) 14975a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten{ 14985a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten AutoMutex _l(mMyLock); 14995a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten mPausedInt = true; 15005a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten mPausedNs = ns; 15015a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten} 15025a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten 150389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ------------------------------------------------------------------------- 150489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project 150540bc906252974d0b389ae4a147232d0c9a97193fGlenn Kasten} // namespace android 1506