AudioRecord.cpp revision eeca32671896739e84050da5992d5f151a1629de
189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project/*
289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Copyright 2008, The Android Open Source Project
489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** you may not use this file except in compliance with the License.
789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** You may obtain a copy of the License at
889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
1089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
1189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
1289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
1389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** See the License for the specific language governing permissions and
1589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** limitations under the License.
1689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project*/
1789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
1889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project//#define LOG_NDEBUG 0
1989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#define LOG_TAG "AudioRecord"
2089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <sys/resource.h>
22868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <binder/IPCThreadState.h>
2389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/AudioRecord.h>
2489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <utils/Log.h>
25868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <private/media/AudioTrackShared.h>
261ab85ec401801ef9a9184650d0f5a1639b45eeb9Glenn Kasten#include <media/IAudioFlinger.h>
2789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#define WAIT_PERIOD_MS          10
299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectnamespace android {
3115304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh// ---------------------------------------------------------------------------
3215304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh
3315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh// static
3415304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yehstatus_t AudioRecord::getMinFrameCount(
35e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten        size_t* frameCount,
3615304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh        uint32_t sampleRate,
3758f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten        audio_format_t format,
38dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten        audio_channel_mask_t channelMask)
3915304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh{
409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (frameCount == NULL) {
419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
4304cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten
4404cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten    // default to 0 in case of error
4504cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten    *frameCount = 0;
4604cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten
4715304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    size_t size = 0;
48c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten    status_t status = AudioSystem::getInputBufferSize(sampleRate, format, channelMask, &size);
49c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten    if (status != NO_ERROR) {
50c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten        ALOGE("AudioSystem could not query the input buffer size; status %d", status);
5115304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh        return NO_INIT;
5215304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    }
5315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh
5415304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    if (size == 0) {
553b16c766d1ae2cfd8487e8ffb2b23936fc0a8e17Glenn Kasten        ALOGE("Unsupported configuration: sampleRate %u, format %d, channelMask %#x",
56dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten            sampleRate, format, channelMask);
5715304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh        return BAD_VALUE;
5815304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    }
5915304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh
6015304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    // We double the size of input buffer for ping pong use of record buffer.
6115304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    size <<= 1;
6215304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh
63fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    if (audio_is_linear_pcm(format)) {
64a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten        uint32_t channelCount = popcount(channelMask);
65671a636931295d9c33ffca74551a804479d01241Eric Laurent        size /= channelCount * audio_bytes_per_sample(format);
6615304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    }
6715304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh
6815304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    *frameCount = size;
6915304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    return NO_ERROR;
7015304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh}
7189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ---------------------------------------------------------------------------
7389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::AudioRecord()
75879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten    : mStatus(NO_INIT), mSessionId(0),
769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten      mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT)
7789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
7889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
7989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::AudioRecord(
81eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten        audio_source_t inputSource,
8289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t sampleRate,
8358f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten        audio_format_t format,
84624a7fcb377f2a40109c16de5109ae8ea1f67a69Glenn Kasten        audio_channel_mask_t channelMask,
8589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        int frameCount,
8689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        callback_t cbf,
8789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        void* user,
88be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        int notificationFrames,
899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        int sessionId,
9027f7b2a8fe899565487d8a326676a5f7d0a05a37Glenn Kasten        transfer_type transferType,
9127f7b2a8fe899565487d8a326676a5f7d0a05a37Glenn Kasten        audio_input_flags_t flags)
92879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten    : mStatus(NO_INIT), mSessionId(0),
93e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
94e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten      mPreviousSchedulingGroup(SP_DEFAULT),
95e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten      mProxy(NULL)
9689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            notificationFrames, false /*threadCanCallJava*/, sessionId, transferType);
9989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
10089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
10189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::~AudioRecord()
10289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
10389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mStatus == NO_ERROR) {
10489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Make sure that callback function exits in the case where
10589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // it is looping on buffer empty condition in obtainBuffer().
10689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Otherwise the callback thread will never exit.
10789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        stop();
10868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        if (mAudioRecordThread != 0) {
10968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mAudioRecordThread->requestExit();  // see comment in AudioRecord.h
11068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mAudioRecordThread->requestExitAndWait();
11168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mAudioRecordThread.clear();
11289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
1139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mAudioRecord != 0) {
1149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this);
1159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mAudioRecord.clear();
1169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
11789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        IPCThreadState::self()->flushCommands();
1183a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen        AudioSystem::releaseAudioSessionId(mSessionId);
11989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
12089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
12189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
12289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::set(
123eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten        audio_source_t inputSource,
12489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t sampleRate,
12558f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten        audio_format_t format,
126624a7fcb377f2a40109c16de5109ae8ea1f67a69Glenn Kasten        audio_channel_mask_t channelMask,
127e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten        int frameCountInt,
12889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        callback_t cbf,
12989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        void* user,
13089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        int notificationFrames,
131be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        bool threadCanCallJava,
1329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        int sessionId,
13327f7b2a8fe899565487d8a326676a5f7d0a05a37Glenn Kasten        transfer_type transferType,
13427f7b2a8fe899565487d8a326676a5f7d0a05a37Glenn Kasten        audio_input_flags_t flags)
13589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
1369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    switch (transferType) {
1379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_DEFAULT:
1389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (cbf == NULL || threadCanCallJava) {
1399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            transferType = TRANSFER_SYNC;
1409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        } else {
1419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            transferType = TRANSFER_CALLBACK;
1429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
1439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
1449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_CALLBACK:
1459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (cbf == NULL) {
1469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            ALOGE("Transfer type TRANSFER_CALLBACK but cbf == NULL");
1479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return BAD_VALUE;
1489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
1499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
1509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_OBTAIN:
1519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_SYNC:
1529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
1539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    default:
1549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Invalid transfer type %d", transferType);
1559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
1569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
1579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mTransfer = transferType;
1589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
159e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten    // FIXME "int" here is legacy and will be replaced by size_t later
160e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten    if (frameCountInt < 0) {
161e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten        ALOGE("Invalid frame count %d", frameCountInt);
162e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten        return BAD_VALUE;
163e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten    }
164e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten    size_t frameCount = frameCountInt;
16589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
166e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten    ALOGV("set(): sampleRate %u, channelMask %#x, frameCount %u", sampleRate, channelMask,
16785ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten            frameCount);
1681703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
1691703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
1701703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
1711dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent    if (mAudioRecord != 0) {
1729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Track already in use");
17389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return INVALID_OPERATION;
17489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
17589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
176c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    if (inputSource == AUDIO_SOURCE_DEFAULT) {
177c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        inputSource = AUDIO_SOURCE_MIC;
17889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
17989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
18089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (sampleRate == 0) {
18189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        sampleRate = DEFAULT_SAMPLE_RATE;
18289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
183e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    mSampleRate = sampleRate;
184e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
18589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // these below should probably come from the audioFlinger too...
18658f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten    if (format == AUDIO_FORMAT_DEFAULT) {
187fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin        format = AUDIO_FORMAT_PCM_16_BIT;
18889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
1899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
190c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    // validate parameters
191fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    if (!audio_is_valid_format(format)) {
1929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Invalid format %d", format);
193c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        return BAD_VALUE;
19489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
195291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten    // Temporary restriction: AudioFlinger currently supports 16-bit PCM only
196291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten    if (format != AUDIO_FORMAT_PCM_16_BIT) {
197291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten        ALOGE("Format %d is not supported", format);
198291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten        return BAD_VALUE;
199291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten    }
2002e4664677d72ce54201d3fd0beb0e10280add93cGlenn Kasten    mFormat = format;
20189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2020d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi    if (!audio_is_input_channel(channelMask)) {
2039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Invalid channel mask %#x", channelMask);
20489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
20589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
206a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten    mChannelMask = channelMask;
207a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten    uint32_t channelCount = popcount(channelMask);
208a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten    mChannelCount = channelCount;
209c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
2102e4664677d72ce54201d3fd0beb0e10280add93cGlenn Kasten    if (audio_is_linear_pcm(format)) {
211e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten        mFrameSize = channelCount * audio_bytes_per_sample(format);
212e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    } else {
213e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten        mFrameSize = sizeof(uint8_t);
214e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    }
215e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
2167c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent    if (sessionId == 0 ) {
2177c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent        mSessionId = AudioSystem::newAudioSessionId();
2187c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent    } else {
2197c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent        mSessionId = sessionId;
2207c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent    }
2213856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("set(): mSessionId %d", mSessionId);
2227c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent
22327f7b2a8fe899565487d8a326676a5f7d0a05a37Glenn Kasten    mFlags = flags;
22427f7b2a8fe899565487d8a326676a5f7d0a05a37Glenn Kasten
2256100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent    audio_io_handle_t input = AudioSystem::getInput(inputSource,
2267c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent                                                    sampleRate,
2277c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent                                                    format,
2287c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent                                                    channelMask,
2297c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent                                                    mSessionId);
2306100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent    if (input == 0) {
23129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Could not get audio input for record source %d", inputSource);
23289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
23389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
23489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
23589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // validate framecount
236e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten    size_t minFrameCount = 0;
2376f744d75d3439f7984245e3c489cc7cf91cea41cEric Laurent    status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelMask);
23815304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    if (status != NO_ERROR) {
2399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("getMinFrameCount() failed; status %d", status);
24015304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh        return status;
241c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    }
2423856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
24389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
24489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (frameCount == 0) {
24589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        frameCount = minFrameCount;
24689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    } else if (frameCount < minFrameCount) {
2479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("frameCount %u < minFrameCount %u", frameCount, minFrameCount);
24889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
24989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
25089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
25189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (notificationFrames == 0) {
25289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        notificationFrames = frameCount/2;
25389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
25489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
25534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    // create the IAudioRecord
2569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    status = openRecord_l(sampleRate, format, frameCount, input, 0 /*epoch*/);
25734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    if (status != NO_ERROR) {
25889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return status;
25989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
26034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
261a0d68338a88c2ddb4502f95017b546d603ef1ec7Glenn Kasten    if (cbf != NULL) {
26268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        mAudioRecordThread = new AudioRecordThread(*this, threadCanCallJava);
26368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO);
26489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
26589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
26689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mStatus = NO_ERROR;
26789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
26889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // Update buffer size in case it has been limited by AudioFlinger during track creation
269b603744e96b07b1d5bf745bde593fb2c025cefcfGlenn Kasten    mFrameCount = mCblk->frameCount_;
27083a0382dc17364567667a4e6135db43f5bd92efcGlenn Kasten
27168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    mActive = false;
27289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mCbf = cbf;
27389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mNotificationFrames = notificationFrames;
2749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mRefreshRemaining = true;
27589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUserData = user;
27689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // TODO: add audio hardware input latency here
277573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurent    mLatency = (1000*mFrameCount) / sampleRate;
27889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mMarkerPosition = 0;
2797d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi    mMarkerReached = false;
28089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mNewPosition = 0;
28189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUpdatePeriod = 0;
282eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten    mInputSource = inputSource;
28305bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent    mInput = input;
2843a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen    AudioSystem::acquireAudioSessionId(mSessionId);
2859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mSequence = 1;
2869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mObservedSequence = mSequence;
2879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mInOverrun = false;
28889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
28989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
29089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
29189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
29289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
29389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
294a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurentstatus_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
29589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
296a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent    ALOGV("start, sync event %d trigger session %d", event, triggerSession);
29789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
298f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent    AutoMutex lock(mLock);
2999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mActive) {
3009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return NO_ERROR;
3019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
3021703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
3039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // reset current position as seen by client to 0
3049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition());
3056dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten
3069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mNewPosition = mProxy->getPosition() + mUpdatePeriod;
30796f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    int32_t flags = android_atomic_acquire_load(&mCblk->mFlags);
3089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    status_t status = NO_ERROR;
3109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!(flags & CBLK_INVALID)) {
3119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGV("mAudioRecord->start()");
3129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status = mAudioRecord->start(event, triggerSession);
3139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (status == DEAD_OBJECT) {
3149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            flags |= CBLK_INVALID;
3151703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        }
3169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
3179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (flags & CBLK_INVALID) {
3189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status = restoreRecord_l("start");
3199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
3209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (status != NO_ERROR) {
3229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("start() status %d", status);
3239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
3249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mActive = true;
3259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        sp<AudioRecordThread> t = mAudioRecordThread;
3269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (t != 0) {
3279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            t->resume();
3286100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent        } else {
3299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mPreviousPriority = getpriority(PRIO_PROCESS, 0);
3309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            get_sched_policy(0, &mPreviousSchedulingGroup);
3319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
33289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
33389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
33489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
3359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return status;
33689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
33789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
338d64cd233eef39430561c1e1df423336a199cc5d7Glenn Kastenvoid AudioRecord::stop()
33989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
340f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent    AutoMutex lock(mLock);
3419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!mActive) {
3429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
3439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
3449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mActive = false;
3469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->interrupt();
3479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mAudioRecord->stop();
3489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // the record head position will reset to 0, so if a marker is set, we need
3499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // to activate it again
3509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mMarkerReached = false;
3519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    sp<AudioRecordThread> t = mAudioRecordThread;
3529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (t != 0) {
3539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        t->pause();
3549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
3559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        setpriority(PRIO_PROCESS, 0, mPreviousPriority);
3569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        set_sched_policy(0, mPreviousSchedulingGroup);
35789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
35889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
35989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
36089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectbool AudioRecord::stopped() const
36189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
36268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    AutoMutex lock(mLock);
36389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return !mActive;
36489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
36589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
36689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setMarkerPosition(uint32_t marker)
36789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
3689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mCbf == NULL) {
3699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
3709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
37189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
372955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
37389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mMarkerPosition = marker;
3747d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi    mMarkerReached = false;
37589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
37689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
37789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
37889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
379606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getMarkerPosition(uint32_t *marker) const
38089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
3819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (marker == NULL) {
3829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
3839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
38489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
385955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
38689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    *marker = mMarkerPosition;
38789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
38889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
38989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
39089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
39189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod)
39289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
3939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mCbf == NULL) {
3949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
3959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
396955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten
397955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
3989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mNewPosition = mProxy->getPosition() + updatePeriod;
39989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUpdatePeriod = updatePeriod;
40089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
40189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
40289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
40389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
404606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const
40589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
4069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (updatePeriod == NULL) {
4079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
4089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
40989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
410955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
41189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    *updatePeriod = mUpdatePeriod;
41289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
41389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
41489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
41589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
416606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getPosition(uint32_t *position) const
41789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
4189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (position == NULL) {
4199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
4209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
42189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4221703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
4239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    *position = mProxy->getPosition();
42489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
42589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
42689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
42789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
428606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenunsigned int AudioRecord::getInputFramesLost() const
42905bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent{
430bf04a5d7f287fc712e0ed91849dc85c90c1e182dGlenn Kasten    // no need to check mActive, because if inactive this will return 0, which is what we want
4319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return AudioSystem::getInputFramesLost(getInput());
43205bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent}
43389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
43489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
43589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4361703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent// must be called with mLock held
4371703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurentstatus_t AudioRecord::openRecord_l(
43834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        uint32_t sampleRate,
43958f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten        audio_format_t format,
440e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten        size_t frameCount,
4419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audio_io_handle_t input,
4429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t epoch)
44334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent{
44434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    status_t status;
44534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
44634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    if (audioFlinger == 0) {
447b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten        ALOGE("Could not get audioflinger");
44834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        return NO_INIT;
44934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
45034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
4511879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten    pid_t tid = -1;
4529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // FIXME see similar logic at AudioTrack for tid
4531879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten
454eeca32671896739e84050da5992d5f151a1629deGlenn Kasten    IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT;
455955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    int originalSessionId = mSessionId;
4568d6cc842e8d525405c68e57fdf3bc5da0b4d7e87Glenn Kasten    sp<IAudioRecord> record = audioFlinger->openRecord(input,
45734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                                                       sampleRate, format,
458a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten                                                       mChannelMask,
45934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                                                       frameCount,
460eeca32671896739e84050da5992d5f151a1629deGlenn Kasten                                                       &trackFlags,
4611879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten                                                       tid,
462be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent                                                       &mSessionId,
46334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                                                       &status);
464955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    ALOGE_IF(originalSessionId != 0 && mSessionId != originalSessionId,
465955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten            "session ID changed from %d to %d", originalSessionId, mSessionId);
4663a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen
46734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    if (record == 0) {
46829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("AudioFlinger could not create record track, status: %d", status);
46934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        return status;
47034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
471b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    sp<IMemory> iMem = record->getCblk();
472b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    if (iMem == 0) {
47329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Could not get control block");
47434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        return NO_INIT;
47534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
4769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mAudioRecord != 0) {
4779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mAudioRecord->asBinder()->unlinkToDeath(mDeathNotifier, this);
4789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mDeathNotifier.clear();
4799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
48034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    mAudioRecord = record;
481b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    mCblkMemory = iMem;
482b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMem->pointer());
483b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    mCblk = cblk;
4849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
4859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // starting address of buffers in shared memory
4869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    void *buffers = (char*)cblk + sizeof(audio_track_cblk_t);
487e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
488e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    // update proxy
4899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy = new AudioRecordClientProxy(cblk, buffers, frameCount, mFrameSize);
4909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->setEpoch(epoch);
4919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->setMinimum(mNotificationFrames);
4929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
4939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mDeathNotifier = new DeathNotifier(this);
4949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mAudioRecord->asBinder()->linkToDeath(mDeathNotifier, this);
495e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
49634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    return NO_ERROR;
49734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent}
49834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
49989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
50089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
5019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (audioBuffer == NULL) {
5029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
5039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mTransfer != TRANSFER_OBTAIN) {
5059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer->frameCount = 0;
5069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer->size = 0;
5079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer->raw = NULL;
5089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
5099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
510e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
5119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    const struct timespec *requested;
5129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (waitCount == -1) {
5139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &ClientProxy::kForever;
5149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else if (waitCount == 0) {
5159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &ClientProxy::kNonBlocking;
5169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else if (waitCount > 0) {
5179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        long long ms = WAIT_PERIOD_MS * (long long) waitCount;
5189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        struct timespec timeout;
5199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timeout.tv_sec = ms / 1000;
5209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timeout.tv_nsec = (int) (ms % 1000) * 1000000;
5219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &timeout;
5229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
5239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("%s invalid waitCount %d", __func__, waitCount);
5249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = NULL;
5259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return obtainBuffer(audioBuffer, requested);
5279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
5289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
5299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *requested,
5309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        struct timespec *elapsed, size_t *nonContig)
5319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
5329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // previous and new IAudioRecord sequence numbers are used to detect track re-creation
5339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t oldSequence = 0;
5349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t newSequence;
5359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
5369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    Proxy::Buffer buffer;
5379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    status_t status = NO_ERROR;
5389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
5399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    static const int32_t kMaxTries = 5;
5409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    int32_t tryCounter = kMaxTries;
5419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
5429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    do {
5439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // obtainBuffer() is called with mutex unlocked, so keep extra references to these fields to
5449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // keep them from going away if another thread re-creates the track during obtainBuffer()
5459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        sp<AudioRecordClientProxy> proxy;
5469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        sp<IMemory> iMem;
5479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        {
5489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // start of lock scope
5499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            AutoMutex lock(mLock);
5509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
5519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            newSequence = mSequence;
5529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // did previous obtainBuffer() fail due to media server death or voluntary invalidation?
5539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (status == DEAD_OBJECT) {
5549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                // re-create track, unless someone else has already done so
5559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                if (newSequence == oldSequence) {
5569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    status = restoreRecord_l("obtainBuffer");
5579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    if (status != NO_ERROR) {
5589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                        break;
55934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                    }
56089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                }
56189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
5629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            oldSequence = newSequence;
56389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
5649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // Keep the extra references
5659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            proxy = mProxy;
5669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            iMem = mCblkMemory;
567c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
5689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // Non-blocking if track is stopped
5699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (!mActive) {
5709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                requested = &ClientProxy::kNonBlocking;
5719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            }
57289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
5739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }   // end of lock scope
57489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
5759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer.mFrameCount = audioBuffer->frameCount;
5769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // FIXME starts the requested timeout and elapsed over from scratch
5779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status = proxy->obtainBuffer(&buffer, requested, elapsed);
5789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
5799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } while ((status == DEAD_OBJECT) && (tryCounter-- > 0));
58089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
5819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audioBuffer->frameCount = buffer.mFrameCount;
5829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audioBuffer->size = buffer.mFrameCount * mFrameSize;
5839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audioBuffer->raw = buffer.mRaw;
5849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (nonContig != NULL) {
5859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        *nonContig = buffer.mNonContig;
5869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return status;
58889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
58989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
59089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectvoid AudioRecord::releaseBuffer(Buffer* audioBuffer)
59189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
5929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // all TRANSFER_* are valid
5939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
5949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t stepCount = audioBuffer->size / mFrameSize;
5959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (stepCount == 0) {
5969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
5979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
5999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    Proxy::Buffer buffer;
6009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer.mFrameCount = stepCount;
6019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer.mRaw = audioBuffer->raw;
602e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
6031703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
6049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mInOverrun = false;
6059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->releaseBuffer(&buffer);
6069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // the server does not automatically disable recorder on overrun, so no need to restart
60889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
60989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
610606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenaudio_io_handle_t AudioRecord::getInput() const
6116100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent{
6121703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
613d1a243e41caffa8fd346907eed4625c9c47c1a86Eric Laurent    return mInput;
6141703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent}
6151703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
6161703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent// must be called with mLock held
6171703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurentaudio_io_handle_t AudioRecord::getInput_l()
6181703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent{
61905bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent    mInput = AudioSystem::getInput(mInputSource,
620e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten                                mSampleRate,
6217c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent                                mFormat,
6227c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent                                mChannelMask,
6237c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent                                mSessionId);
62405bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent    return mInput;
6256100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent}
6266100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent
62789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
62889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
62989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectssize_t AudioRecord::read(void* buffer, size_t userSize)
63089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
6319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mTransfer != TRANSFER_SYNC) {
6329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
6339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
63489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) {
6369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // sanity-check. user is most-likely passing an error code, and it would
6379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // make the return value ambiguous (actualSize vs error).
6389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("AudioRecord::read(buffer=%p, size=%u (%d)", buffer, userSize, userSize);
63989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
64089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
64189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ssize_t read = 0;
6439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    Buffer audioBuffer;
64489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    while (userSize >= mFrameSize) {
6469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer.frameCount = userSize / mFrameSize;
64789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status_t err = obtainBuffer(&audioBuffer, &ClientProxy::kForever);
64989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (err < 0) {
6509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (read > 0) {
65189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                break;
652d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten            }
65389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            return ssize_t(err);
65489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
65589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
65689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        size_t bytesRead = audioBuffer.size;
6579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        memcpy(buffer, audioBuffer.i8, bytesRead);
6589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer = ((char *) buffer) + bytesRead;
65989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        userSize -= bytesRead;
66089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        read += bytesRead;
66189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
66289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        releaseBuffer(&audioBuffer);
6639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
66489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
66589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return read;
66689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
66789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
66889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
66989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastennsecs_t AudioRecord::processAudioBuffer(const sp<AudioRecordThread>& thread)
67189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
6721703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    mLock.lock();
67328f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten    if (mAwaitBoost) {
67428f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        mAwaitBoost = false;
67528f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        mLock.unlock();
67628f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        static const int32_t kMaxTries = 5;
67728f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        int32_t tryCounter = kMaxTries;
67828f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        uint32_t pollUs = 10000;
67928f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        do {
68028f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            int policy = sched_getscheduler(0);
68128f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            if (policy == SCHED_FIFO || policy == SCHED_RR) {
68228f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten                break;
68328f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            }
68428f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            usleep(pollUs);
68528f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            pollUs <<= 1;
68628f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        } while (tryCounter-- > 0);
68728f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        if (tryCounter < 0) {
68828f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            ALOGE("did not receive expected priority boost on time");
68928f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        }
69028f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        // Run again immediately
69128f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        return 0;
69228f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten    }
6939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Can only reference mCblk while locked
69596f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    int32_t flags = android_atomic_and(~CBLK_OVERRUN, &mCblk->mFlags);
6969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Check for track invalidation
6989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (flags & CBLK_INVALID) {
6999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        (void) restoreRecord_l("processAudioBuffer");
7009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mLock.unlock();
7019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // Run again immediately, but with a new IAudioRecord
7029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return 0;
7039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
70568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    bool active = mActive;
7069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Manage overrun callback, must be done under lock to avoid race with releaseBuffer()
7089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    bool newOverrun = false;
7099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (flags & CBLK_OVERRUN) {
7109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (!mInOverrun) {
7119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mInOverrun = true;
7129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            newOverrun = true;
7139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
7149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Get current position of server
7179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t position = mProxy->getPosition();
7189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Manage marker callback
7209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    bool markerReached = false;
7219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t markerPosition = mMarkerPosition;
7229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // FIXME fails for wraparound, need 64 bits
7239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!mMarkerReached && (markerPosition > 0) && (position >= markerPosition)) {
7249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mMarkerReached = markerReached = true;
7259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Determine the number of new position callback(s) that will be needed, while locked
7289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t newPosCount = 0;
7299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t newPosition = mNewPosition;
730955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    uint32_t updatePeriod = mUpdatePeriod;
7319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // FIXME fails for wraparound, need 64 bits
7329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (updatePeriod > 0 && position >= newPosition) {
7339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        newPosCount = ((position - newPosition) / updatePeriod) + 1;
7349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mNewPosition += updatePeriod * newPosCount;
7359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Cache other fields that will be needed soon
7389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t notificationFrames = mNotificationFrames;
7399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mRefreshRemaining) {
7409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mRefreshRemaining = false;
7419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mRemainingFrames = notificationFrames;
7429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mRetryOnPartialBuffer = false;
7439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t misalignment = mProxy->getMisalignment();
7459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    int32_t sequence = mSequence;
7469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // These fields don't need to be cached, because they are assigned only by set():
7489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    //      mTransfer, mCbf, mUserData, mSampleRate
7499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7501703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    mLock.unlock();
7511703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
7529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // perform callbacks while unlocked
7539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (newOverrun) {
7549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mCbf(EVENT_OVERRUN, mUserData, NULL);
7559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (markerReached) {
757955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten        mCbf(EVENT_MARKER, mUserData, &markerPosition);
75889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
7599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    while (newPosCount > 0) {
7609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t temp = newPosition;
761955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten        mCbf(EVENT_NEW_POS, mUserData, &temp);
762955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten        newPosition += updatePeriod;
7639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        newPosCount--;
7649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mObservedSequence != sequence) {
7669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mObservedSequence = sequence;
7679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mCbf(EVENT_NEW_IAUDIORECORD, mUserData, NULL);
76889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
76989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // if inactive, then don't run me again until re-started
7719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!active) {
7729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return NS_INACTIVE;
7739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Compute the estimated time until the next timed event (position, markers)
7769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t minFrames = ~0;
7779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!markerReached && position < markerPosition) {
7789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        minFrames = markerPosition - position;
7799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (updatePeriod > 0 && updatePeriod < minFrames) {
7819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        minFrames = updatePeriod;
7829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // If > 0, poll periodically to recover from a stuck server.  A good value is 2.
7859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    static const uint32_t kPoll = 0;
7869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (kPoll > 0 && mTransfer == TRANSFER_CALLBACK && kPoll * notificationFrames < minFrames) {
7879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        minFrames = kPoll * notificationFrames;
7889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Convert frame units to time units
7919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    nsecs_t ns = NS_WHENEVER;
7929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (minFrames != (uint32_t) ~0) {
7939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // This "fudge factor" avoids soaking CPU, and compensates for late progress by server
7949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        static const nsecs_t kFudgeNs = 10000000LL; // 10 ms
7959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ns = ((minFrames * 1000000000LL) / mSampleRate) + kFudgeNs;
7969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // If not supplying data by EVENT_MORE_DATA, then we're done
7999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mTransfer != TRANSFER_CALLBACK) {
8009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return ns;
8019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    struct timespec timeout;
8049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    const struct timespec *requested = &ClientProxy::kForever;
8059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (ns != NS_WHENEVER) {
8069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timeout.tv_sec = ns / 1000000000LL;
8079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timeout.tv_nsec = ns % 1000000000LL;
8089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGV("timeout %ld.%03d", timeout.tv_sec, (int) timeout.tv_nsec / 1000000);
8099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &timeout;
8109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    while (mRemainingFrames > 0) {
8139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        Buffer audioBuffer;
8159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer.frameCount = mRemainingFrames;
8169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t nonContig;
8179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig);
8189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0),
8199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                "obtainBuffer() err=%d frameCount=%u", err, audioBuffer.frameCount);
8209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &ClientProxy::kNonBlocking;
8219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t avail = audioBuffer.frameCount + nonContig;
8229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGV("obtainBuffer(%u) returned %u = %u + %u",
8239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                mRemainingFrames, avail, audioBuffer.frameCount, nonContig);
8249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (err != NO_ERROR) {
8259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR) {
8269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                break;
8279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            }
8289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            ALOGE("Error %d obtaining an audio buffer, giving up.", err);
8299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return NS_NEVER;
8309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
8319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mRetryOnPartialBuffer) {
8339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mRetryOnPartialBuffer = false;
8349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (avail < mRemainingFrames) {
8359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                int64_t myns = ((mRemainingFrames - avail) *
8369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                        1100000000LL) / mSampleRate;
8379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                if (ns < 0 || myns < ns) {
8389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    ns = myns;
8399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                }
8409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                return ns;
84189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
84289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
84389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
84489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        size_t reqSize = audioBuffer.size;
84589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
8469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t readSize = audioBuffer.size;
84789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
84889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Sanity check on returned size
8499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (ssize_t(readSize) < 0 || readSize > reqSize) {
8509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            ALOGE("EVENT_MORE_DATA requested %u bytes but callback returned %d bytes",
8519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    reqSize, (int) readSize);
8529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return NS_NEVER;
8539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
8549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (readSize == 0) {
8569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // The callback is done consuming buffers
857cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            // Keep this thread going to handle timed events and
8589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // still try to provide more data in intervals of WAIT_PERIOD_MS
859cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            // but don't just loop and block the CPU, so wait
8609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return WAIT_PERIOD_MS * 1000000LL;
861cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent        }
86289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t releasedFrames = readSize / mFrameSize;
8649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer.frameCount = releasedFrames;
8659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mRemainingFrames -= releasedFrames;
8669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (misalignment >= releasedFrames) {
8679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            misalignment -= releasedFrames;
8689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        } else {
8699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            misalignment = 0;
8709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
87189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
87289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        releaseBuffer(&audioBuffer);
87389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // FIXME here is where we would repeat EVENT_MORE_DATA again on same advanced buffer
8759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // if callback doesn't like to accept the full chunk
8769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (readSize < reqSize) {
8779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            continue;
8789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
87989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // There could be enough non-contiguous frames available to satisfy the remaining request
8819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mRemainingFrames <= nonContig) {
8829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            continue;
8839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
884c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
8859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#if 0
8869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // This heuristic tries to collapse a series of EVENT_MORE_DATA that would total to a
8879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // sum <= notificationFrames.  It replaces that series by at most two EVENT_MORE_DATA
8889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // that total to a sum == notificationFrames.
8899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (0 < misalignment && misalignment <= mRemainingFrames) {
8909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mRemainingFrames = misalignment;
8919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return (mRemainingFrames * 1100000000LL) / mSampleRate;
89289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
8939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#endif
89489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
89589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
8969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mRemainingFrames = notificationFrames;
8979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mRetryOnPartialBuffer = true;
8989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // A lot has transpired since ns was calculated, so run again immediately and re-calculate
9009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return 0;
90189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
90289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
9039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t AudioRecord::restoreRecord_l(const char *from)
9041703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent{
9059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ALOGW("dead IAudioRecord, creating a new one from %s()", from);
9069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ++mSequence;
9071703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    status_t result;
9081703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
909b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    // if the new IAudioRecord is created, openRecord_l() will modify the
910b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    // following member variables: mAudioRecord, mCblkMemory and mCblk.
911b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    // It will also delete the strong references on previous IAudioRecord and IMemory
9129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t position = mProxy->getPosition();
9139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mNewPosition = position + mUpdatePeriod;
9149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    result = openRecord_l(mSampleRate, mFormat, mFrameCount, getInput_l(), position);
915b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    if (result == NO_ERROR) {
9169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mActive) {
9179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // callback thread or sync event hasn't changed
9189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // FIXME this fails if we have a new AudioFlinger instance
9199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0);
9209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
921b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    }
922b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    if (result != NO_ERROR) {
9239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGW("restoreRecord_l() failed status %d", result);
924b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten        mActive = false;
9251703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    }
926b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten
9279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return result;
9289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
9291703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
9309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// =========================================================================
9311703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
9329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who)
9339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
9349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    sp<AudioRecord> audioRecord = mAudioRecord.promote();
9359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (audioRecord != 0) {
9369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        AutoMutex lock(audioRecord->mLock);
9379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioRecord->mProxy->binderDied();
9389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
9391703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent}
9401703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
94189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// =========================================================================
94289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
94368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn KastenAudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver, bool bCanCallJava)
9449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mResumeLatch(false)
94568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{
94668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten}
94768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten
94868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn KastenAudioRecord::AudioRecordThread::~AudioRecordThread()
94968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{
95068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten}
95168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten
95268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenbool AudioRecord::AudioRecordThread::threadLoop()
95368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{
95468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    {
95568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        AutoMutex _l(mMyLock);
95668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        if (mPaused) {
95768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mMyCond.wait(mMyLock);
95868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            // caller will check for exitPending()
95968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            return true;
96068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        }
96168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    }
9629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    nsecs_t ns =  mReceiver.processAudioBuffer(this);
9639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    switch (ns) {
9649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case 0:
9659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return true;
9669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case NS_WHENEVER:
9679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        sleep(1);
9689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return true;
9699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case NS_INACTIVE:
9709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        pauseConditional();
9719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return true;
9729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case NS_NEVER:
9739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return false;
9749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    default:
9759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %lld", ns);
9769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        struct timespec req;
9779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        req.tv_sec = ns / 1000000000LL;
9789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        req.tv_nsec = ns % 1000000000LL;
9799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        nanosleep(&req, NULL /*rem*/);
9809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return true;
98168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    }
98268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten}
98368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten
98468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::requestExit()
98589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
98668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    // must be in this order to avoid a race condition
98768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    Thread::requestExit();
98868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    resume();
98989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
99089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
99168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::pause()
99289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
99368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    AutoMutex _l(mMyLock);
99468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    mPaused = true;
9959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mResumeLatch = false;
9969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
9979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
9989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid AudioRecord::AudioRecordThread::pauseConditional()
9999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
10009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    AutoMutex _l(mMyLock);
10019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mResumeLatch) {
10029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mResumeLatch = false;
10039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
10049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mPaused = true;
10059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
100689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
100789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
100868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::resume()
10096dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten{
101068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    AutoMutex _l(mMyLock);
101168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    if (mPaused) {
101268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        mPaused = false;
10139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mResumeLatch = false;
101468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        mMyCond.signal();
10159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
10169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mResumeLatch = true;
10176dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten    }
10186dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten}
10196dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten
102089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
102189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
102289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}; // namespace android
1023