AudioRecord.cpp revision e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39
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 <sys/types.h>
2389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
24868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <binder/IPCThreadState.h>
25868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <cutils/atomic.h>
26868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <cutils/compiler.h>
2789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/AudioRecord.h>
28868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <media/AudioSystem.h>
29868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <system/audio.h>
3089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <utils/Log.h>
3189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
32868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <private/media/AudioTrackShared.h>
3389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
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{
4404cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten    if (frameCount == NULL) return BAD_VALUE;
4504cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten
4604cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten    // default to 0 in case of error
4704cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten    *frameCount = 0;
4804cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten
4915304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    size_t size = 0;
50dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten    if (AudioSystem::getInputBufferSize(sampleRate, format, channelMask, &size)
5115304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh            != NO_ERROR) {
5229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("AudioSystem could not query the input buffer size.");
5315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh        return NO_INIT;
5415304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    }
5515304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh
5615304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    if (size == 0) {
573b16c766d1ae2cfd8487e8ffb2b23936fc0a8e17Glenn Kasten        ALOGE("Unsupported configuration: sampleRate %u, format %d, channelMask %#x",
58dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten            sampleRate, format, channelMask);
5915304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh        return BAD_VALUE;
6015304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    }
6115304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh
6215304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    // We double the size of input buffer for ping pong use of record buffer.
6315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    size <<= 1;
6415304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh
65fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    if (audio_is_linear_pcm(format)) {
66a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten        uint32_t channelCount = popcount(channelMask);
67671a636931295d9c33ffca74551a804479d01241Eric Laurent        size /= channelCount * audio_bytes_per_sample(format);
6815304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    }
6915304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh
7015304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    *frameCount = size;
7115304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    return NO_ERROR;
7215304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh}
7389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ---------------------------------------------------------------------------
7589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::AudioRecord()
77879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten    : mStatus(NO_INIT), mSessionId(0),
78e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten      mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT),
79e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten      mProxy(NULL)
8089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
8189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
8289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::AudioRecord(
84eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten        audio_source_t inputSource,
8589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t sampleRate,
8658f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten        audio_format_t format,
87624a7fcb377f2a40109c16de5109ae8ea1f67a69Glenn Kasten        audio_channel_mask_t channelMask,
8889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        int frameCount,
8989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        callback_t cbf,
9089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        void* user,
91be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        int notificationFrames,
92be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        int sessionId)
93879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten    : mStatus(NO_INIT), mSessionId(0),
94e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
95e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten      mPreviousSchedulingGroup(SP_DEFAULT),
96e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten      mProxy(NULL)
9789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
980d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi    mStatus = set(inputSource, sampleRate, format, channelMask,
99f92eec53f886f43e4374a36195be55f2a7bbcf36Glenn Kasten            frameCount, cbf, user, notificationFrames, sessionId);
10089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
10189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
10289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::~AudioRecord()
10389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
10489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mStatus == NO_ERROR) {
10589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Make sure that callback function exits in the case where
10689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // it is looping on buffer empty condition in obtainBuffer().
10789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Otherwise the callback thread will never exit.
10889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        stop();
10968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        if (mAudioRecordThread != 0) {
11068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mAudioRecordThread->requestExit();  // see comment in AudioRecord.h
11168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mAudioRecordThread->requestExitAndWait();
11268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mAudioRecordThread.clear();
11389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
11489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mAudioRecord.clear();
11589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        IPCThreadState::self()->flushCommands();
1163a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen        AudioSystem::releaseAudioSessionId(mSessionId);
11789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
118e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    delete mProxy;
11989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
12089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
12189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::set(
122eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten        audio_source_t inputSource,
12389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t sampleRate,
12458f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten        audio_format_t format,
125624a7fcb377f2a40109c16de5109ae8ea1f67a69Glenn Kasten        audio_channel_mask_t channelMask,
126e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten        int frameCountInt,
12789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        callback_t cbf,
12889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        void* user,
12989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        int notificationFrames,
130be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        bool threadCanCallJava,
131be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        int sessionId)
13289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
133e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten    // FIXME "int" here is legacy and will be replaced by size_t later
134e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten    if (frameCountInt < 0) {
135e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten        ALOGE("Invalid frame count %d", frameCountInt);
136e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten        return BAD_VALUE;
137e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten    }
138e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten    size_t frameCount = frameCountInt;
13989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
140e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten    ALOGV("set(): sampleRate %u, channelMask %#x, frameCount %u", sampleRate, channelMask,
14185ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten            frameCount);
1421703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
1431703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
1441703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
1451dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent    if (mAudioRecord != 0) {
14689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return INVALID_OPERATION;
14789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
14889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
149c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    if (inputSource == AUDIO_SOURCE_DEFAULT) {
150c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        inputSource = AUDIO_SOURCE_MIC;
15189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
15289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
15389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (sampleRate == 0) {
15489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        sampleRate = DEFAULT_SAMPLE_RATE;
15589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
156e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    mSampleRate = sampleRate;
157e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
15889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // these below should probably come from the audioFlinger too...
15958f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten    if (format == AUDIO_FORMAT_DEFAULT) {
160fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin        format = AUDIO_FORMAT_PCM_16_BIT;
16189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
162c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    // validate parameters
163fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    if (!audio_is_valid_format(format)) {
16429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Invalid format");
165c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        return BAD_VALUE;
16689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
16789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
1680d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi    if (!audio_is_input_channel(channelMask)) {
16989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
17089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
171a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten    mChannelMask = channelMask;
172a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten    uint32_t channelCount = popcount(channelMask);
173a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten    mChannelCount = channelCount;
174c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
175e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    if (audio_is_linear_pcm(mFormat)) {
176e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten        mFrameSize = channelCount * audio_bytes_per_sample(format);
177e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    } else {
178e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten        mFrameSize = sizeof(uint8_t);
179e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    }
180e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
1817c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent    if (sessionId == 0 ) {
1827c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent        mSessionId = AudioSystem::newAudioSessionId();
1837c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent    } else {
1847c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent        mSessionId = sessionId;
1857c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent    }
1863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("set(): mSessionId %d", mSessionId);
1877c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent
1886100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent    audio_io_handle_t input = AudioSystem::getInput(inputSource,
1897c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent                                                    sampleRate,
1907c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent                                                    format,
1917c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent                                                    channelMask,
1927c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent                                                    mSessionId);
1936100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent    if (input == 0) {
19429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Could not get audio input for record source %d", inputSource);
19589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
19689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
19789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
19889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // validate framecount
199e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten    size_t minFrameCount = 0;
2006f744d75d3439f7984245e3c489cc7cf91cea41cEric Laurent    status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelMask);
20115304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    if (status != NO_ERROR) {
20215304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh        return status;
203c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    }
2043856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
20589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
20689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (frameCount == 0) {
20789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        frameCount = minFrameCount;
20889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    } else if (frameCount < minFrameCount) {
20989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
21089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
21189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
21289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (notificationFrames == 0) {
21389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        notificationFrames = frameCount/2;
21489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
21589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
21634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    // create the IAudioRecord
217a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten    status = openRecord_l(sampleRate, format, frameCount, input);
21834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    if (status != NO_ERROR) {
21989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return status;
22089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
22134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
222a0d68338a88c2ddb4502f95017b546d603ef1ec7Glenn Kasten    if (cbf != NULL) {
22368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        mAudioRecordThread = new AudioRecordThread(*this, threadCanCallJava);
22468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO);
22589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
22689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
22789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mStatus = NO_ERROR;
22889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
22989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mFormat = format;
23089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // Update buffer size in case it has been limited by AudioFlinger during track creation
231b603744e96b07b1d5bf745bde593fb2c025cefcfGlenn Kasten    mFrameCount = mCblk->frameCount_;
23283a0382dc17364567667a4e6135db43f5bd92efcGlenn Kasten
23368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    mActive = false;
23489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mCbf = cbf;
23589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mNotificationFrames = notificationFrames;
23689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mRemainingFrames = notificationFrames;
23789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUserData = user;
23889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // TODO: add audio hardware input latency here
239573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurent    mLatency = (1000*mFrameCount) / sampleRate;
24089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mMarkerPosition = 0;
2417d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi    mMarkerReached = false;
24289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mNewPosition = 0;
24389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUpdatePeriod = 0;
244eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten    mInputSource = inputSource;
24505bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent    mInput = input;
2463a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen    AudioSystem::acquireAudioSessionId(mSessionId);
24789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
24889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
24989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
25089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
25189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::initCheck() const
25289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
25389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return mStatus;
25489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
25589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
25689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
25789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
25889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectuint32_t AudioRecord::latency() const
25989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
26089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return mLatency;
26189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
26289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
26358f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kastenaudio_format_t AudioRecord::format() const
26489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
26589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return mFormat;
26689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
26789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
268a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kastenuint32_t AudioRecord::channelCount() const
26989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
27089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return mChannelCount;
27189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
27289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
273e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kastensize_t AudioRecord::frameCount() const
27489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
27589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return mFrameCount;
27689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
27789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
278eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kastenaudio_source_t AudioRecord::inputSource() const
279f5879c1448cc6aebc51b26d3ec2399d66144f8f4Eric Laurent{
280eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten    return mInputSource;
281f5879c1448cc6aebc51b26d3ec2399d66144f8f4Eric Laurent}
282f5879c1448cc6aebc51b26d3ec2399d66144f8f4Eric Laurent
28389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
28489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
285a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurentstatus_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
28689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
28789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    status_t ret = NO_ERROR;
28868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    sp<AudioRecordThread> t = mAudioRecordThread;
28989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
290a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent    ALOGV("start, sync event %d trigger session %d", event, triggerSession);
29189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
292f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent    AutoMutex lock(mLock);
2931703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
2941703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    // while we are accessing the cblk
295e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten    sp<IAudioRecord> audioRecord = mAudioRecord;
296e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten    sp<IMemory> iMem = mCblkMemory;
2971703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    audio_track_cblk_t* cblk = mCblk;
2981703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
29968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    if (!mActive) {
30068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        mActive = true;
3016dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten
3021703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        cblk->lock.lock();
3039c5fdd83f9b9f49be35107971feb33528d60b945Glenn Kasten        if (!(cblk->flags & CBLK_INVALID)) {
3041703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent            cblk->lock.unlock();
3053acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten            ALOGV("mAudioRecord->start()");
3063acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten            ret = mAudioRecord->start(event, triggerSession);
3071703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent            cblk->lock.lock();
3081703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent            if (ret == DEAD_OBJECT) {
3099c5fdd83f9b9f49be35107971feb33528d60b945Glenn Kasten                android_atomic_or(CBLK_INVALID, &cblk->flags);
3106100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent            }
3116100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent        }
3129c5fdd83f9b9f49be35107971feb33528d60b945Glenn Kasten        if (cblk->flags & CBLK_INVALID) {
313b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten            audio_track_cblk_t* temp = cblk;
314b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten            ret = restoreRecord_l(temp);
315b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten            cblk = temp;
3161703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        }
3171703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        cblk->lock.unlock();
3186100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent        if (ret == NO_ERROR) {
3191703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent            mNewPosition = cblk->user + mUpdatePeriod;
3202986460984580833161bdaabc7f17da1005a8961Eric Laurent            cblk->bufferTimeoutMs = (event == AudioSystem::SYNC_EVENT_NONE) ? MAX_RUN_TIMEOUT_MS :
3212986460984580833161bdaabc7f17da1005a8961Eric Laurent                                            AudioSystem::kSyncRecordStartTimeOutMs;
3221703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent            cblk->waitTimeMs = 0;
3236100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent            if (t != 0) {
32468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten                t->resume();
325c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent            } else {
326879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten                mPreviousPriority = getpriority(PRIO_PROCESS, 0);
327a636433cbd09c0708b85f337ef45c0cdef3bcb4dGlenn Kasten                get_sched_policy(0, &mPreviousSchedulingGroup);
328879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten                androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
329c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent            }
3306100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent        } else {
33168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mActive = false;
33289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
33389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
33489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
33589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return ret;
33689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
33789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
338d64cd233eef39430561c1e1df423336a199cc5d7Glenn Kastenvoid AudioRecord::stop()
33989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
34068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    sp<AudioRecordThread> t = mAudioRecordThread;
34189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
3423856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("stop");
34389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
344f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent    AutoMutex lock(mLock);
34568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    if (mActive) {
34668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        mActive = false;
3471dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent        mCblk->cv.signal();
34889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mAudioRecord->stop();
3497d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi        // the record head position will reset to 0, so if a marker is set, we need
3507d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi        // to activate it again
3517d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi        mMarkerReached = false;
35289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (t != 0) {
35368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            t->pause();
35489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        } else {
355879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten            setpriority(PRIO_PROCESS, 0, mPreviousPriority);
356a636433cbd09c0708b85f337ef45c0cdef3bcb4dGlenn 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 Project
36189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectbool AudioRecord::stopped() const
36289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
36368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    AutoMutex lock(mLock);
36489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return !mActive;
36589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
36689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
367606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenuint32_t AudioRecord::getSampleRate() const
368573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurent{
369e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    return mSampleRate;
370573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurent}
371573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurent
37289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setMarkerPosition(uint32_t marker)
37389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
374a0d68338a88c2ddb4502f95017b546d603ef1ec7Glenn Kasten    if (mCbf == NULL) return INVALID_OPERATION;
37589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
376955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
37789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mMarkerPosition = marker;
3787d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi    mMarkerReached = false;
37989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
38089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
38189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
38289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
383606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getMarkerPosition(uint32_t *marker) const
38489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
385a0d68338a88c2ddb4502f95017b546d603ef1ec7Glenn Kasten    if (marker == NULL) return BAD_VALUE;
38689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
387955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
38889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    *marker = mMarkerPosition;
38989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
39089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
39189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
39289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
39389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod)
39489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
395a0d68338a88c2ddb4502f95017b546d603ef1ec7Glenn Kasten    if (mCbf == NULL) return INVALID_OPERATION;
39689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
39789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    uint32_t curPosition;
39889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    getPosition(&curPosition);
399955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten
400955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
40189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mNewPosition = curPosition + updatePeriod;
40289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUpdatePeriod = updatePeriod;
40389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
40489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
40589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
40689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
407606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const
40889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
409a0d68338a88c2ddb4502f95017b546d603ef1ec7Glenn Kasten    if (updatePeriod == NULL) return BAD_VALUE;
41089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
411955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
41289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    *updatePeriod = mUpdatePeriod;
41389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
41489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
41589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
41689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
417606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getPosition(uint32_t *position) const
41889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
419a0d68338a88c2ddb4502f95017b546d603ef1ec7Glenn Kasten    if (position == NULL) return BAD_VALUE;
42089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4211703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
42289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    *position = mCblk->user;
42389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
42489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
42589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
42689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
427606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenunsigned int AudioRecord::getInputFramesLost() const
42805bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent{
429bf04a5d7f287fc712e0ed91849dc85c90c1e182dGlenn Kasten    // no need to check mActive, because if inactive this will return 0, which is what we want
430bf04a5d7f287fc712e0ed91849dc85c90c1e182dGlenn Kasten    return AudioSystem::getInputFramesLost(mInput);
43105bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent}
43289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
43389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
43489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4351703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent// must be called with mLock held
4361703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurentstatus_t AudioRecord::openRecord_l(
43734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        uint32_t sampleRate,
43858f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten        audio_format_t format,
439e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten        size_t frameCount,
4406100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent        audio_io_handle_t input)
44134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent{
44234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    status_t status;
44334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
44434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    if (audioFlinger == 0) {
445b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten        ALOGE("Could not get audioflinger");
44634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        return NO_INIT;
44734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
44834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
4491879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten    pid_t tid = -1;
4501879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten    // FIXME see similar logic at AudioTrack
4511879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten
452955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    int originalSessionId = mSessionId;
4536100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input,
45434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                                                       sampleRate, format,
455a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten                                                       mChannelMask,
45634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                                                       frameCount,
457a075db4ff9b086ac2885df77bb6da0869293df92Glenn Kasten                                                       IAudioFlinger::TRACK_DEFAULT,
4581879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten                                                       tid,
459be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent                                                       &mSessionId,
46034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                                                       &status);
461955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    ALOGE_IF(originalSessionId != 0 && mSessionId != originalSessionId,
462955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten            "session ID changed from %d to %d", originalSessionId, mSessionId);
4633a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen
46434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    if (record == 0) {
46529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("AudioFlinger could not create record track, status: %d", status);
46634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        return status;
46734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
468b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    sp<IMemory> iMem = record->getCblk();
469b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    if (iMem == 0) {
47029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Could not get control block");
47134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        return NO_INIT;
47234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
47334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    mAudioRecord.clear();
47434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    mAudioRecord = record;
47534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    mCblkMemory.clear();
476b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    mCblkMemory = iMem;
477b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMem->pointer());
478b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    mCblk = cblk;
479b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    mBuffers = (char*)cblk + sizeof(audio_track_cblk_t);
480b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
481b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    cblk->waitTimeMs = 0;
482e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
483e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    // update proxy
484e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    delete mProxy;
485e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    mProxy = new AudioRecordClientProxy(cblk, mBuffers, frameCount, mFrameSize);
486e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
48734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    return NO_ERROR;
48834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent}
48934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
49089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
49189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
492e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    ALOG_ASSERT(mStatus == NO_ERROR && mProxy != NULL);
493e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
4941703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
49568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    bool active;
496d0965dde97f2815ae0a15fe6b40946f8a741a81eGlenn Kasten    status_t result = NO_ERROR;
49789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    audio_track_cblk_t* cblk = mCblk;
49889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    uint32_t framesReq = audioBuffer->frameCount;
4991dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent    uint32_t waitTimeMs = (waitCount < 0) ? cblk->bufferTimeoutMs : WAIT_PERIOD_MS;
50089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
50189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    audioBuffer->frameCount  = 0;
50289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    audioBuffer->size        = 0;
50389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
504e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    size_t framesReady = mProxy->framesReady();
50589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
50689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (framesReady == 0) {
50734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        cblk->lock.lock();
50889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        goto start_loop_here;
50989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        while (framesReady == 0) {
51089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            active = mActive;
511f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten            if (CC_UNLIKELY(!active)) {
51234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                cblk->lock.unlock();
51389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                return NO_MORE_BUFFERS;
51434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent            }
515f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten            if (CC_UNLIKELY(!waitCount)) {
51634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                cblk->lock.unlock();
51789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                return WOULD_BLOCK;
51834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent            }
5199c5fdd83f9b9f49be35107971feb33528d60b945Glenn Kasten            if (!(cblk->flags & CBLK_INVALID)) {
5201703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent                mLock.unlock();
521b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten                // this condition is in shared memory, so if IAudioRecord and control block
522b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten                // are replaced due to mediaserver death or IAudioRecord invalidation then
523b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten                // cv won't be signalled, but fortunately the timeout will limit the wait
5241703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent                result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
5251703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent                cblk->lock.unlock();
5261703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent                mLock.lock();
52768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten                if (!mActive) {
5281703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent                    return status_t(STOPPED);
5291703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent                }
530b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten                // IAudioRecord may have been re-created while mLock was unlocked
531b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten                cblk = mCblk;
5321703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent                cblk->lock.lock();
5331703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent            }
5349c5fdd83f9b9f49be35107971feb33528d60b945Glenn Kasten            if (cblk->flags & CBLK_INVALID) {
5351703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent                goto create_new_record;
5361703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent            }
537f6b1678f8f508b447155a81b44e214475ab634a8Glenn Kasten            if (CC_UNLIKELY(result != NO_ERROR)) {
5381dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent                cblk->waitTimeMs += waitTimeMs;
53989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
5405ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block                    ALOGW(   "obtainBuffer timed out (is the CPU pegged?) "
54189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                            "user=%08x, server=%08x", cblk->user, cblk->server);
54234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                    cblk->lock.unlock();
543a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent                    // callback thread or sync event hasn't changed
5443acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten                    result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0);
5451703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent                    cblk->lock.lock();
54634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                    if (result == DEAD_OBJECT) {
5479c5fdd83f9b9f49be35107971feb33528d60b945Glenn Kasten                        android_atomic_or(CBLK_INVALID, &cblk->flags);
5481703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurentcreate_new_record:
549b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten                        audio_track_cblk_t* temp = cblk;
550b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten                        result = AudioRecord::restoreRecord_l(temp);
551b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten                        cblk = temp;
5521703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent                    }
5531703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent                    if (result != NO_ERROR) {
5545ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block                        ALOGW("obtainBuffer create Track error %d", result);
5551703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent                        cblk->lock.unlock();
5561703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent                        return result;
55734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                    }
55889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                    cblk->waitTimeMs = 0;
55989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                }
56089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                if (--waitCount == 0) {
56134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                    cblk->lock.unlock();
56289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                    return TIMED_OUT;
56389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                }
56489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
56589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            // read the server count again
56689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        start_loop_here:
567e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten            framesReady = mProxy->framesReady();
56889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
56934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        cblk->lock.unlock();
57089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
57189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
57289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    cblk->waitTimeMs = 0;
5732986460984580833161bdaabc7f17da1005a8961Eric Laurent    // reset time out to running value after obtaining a buffer
5742986460984580833161bdaabc7f17da1005a8961Eric Laurent    cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
575c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
57689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (framesReq > framesReady) {
57789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        framesReq = framesReady;
57889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
57989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
58089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    uint32_t u = cblk->user;
581b603744e96b07b1d5bf745bde593fb2c025cefcfGlenn Kasten    uint32_t bufferEnd = cblk->userBase + mFrameCount;
58289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
583a1472d9883e35edd280201c8be3191695007dfd4Marco Nelissen    if (framesReq > bufferEnd - u) {
58489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        framesReq = bufferEnd - u;
58589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
58689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
58789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    audioBuffer->frameCount  = framesReq;
58883a0382dc17364567667a4e6135db43f5bd92efcGlenn Kasten    audioBuffer->size        = framesReq * mFrameSize;
589e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    audioBuffer->raw         = mProxy->buffer(u);
59089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    active = mActive;
59189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return active ? status_t(NO_ERROR) : status_t(STOPPED);
59289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
59389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
59489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectvoid AudioRecord::releaseBuffer(Buffer* audioBuffer)
59589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
596e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    ALOG_ASSERT(mStatus == NO_ERROR && mProxy != NULL);
597e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
5981703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
599e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    (void) mProxy->stepUser(audioBuffer->frameCount);
60089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
60189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
602606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenaudio_io_handle_t AudioRecord::getInput() const
6036100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent{
6041703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
605d1a243e41caffa8fd346907eed4625c9c47c1a86Eric Laurent    return mInput;
6061703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent}
6071703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
6081703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent// must be called with mLock held
6091703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurentaudio_io_handle_t AudioRecord::getInput_l()
6101703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent{
61105bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent    mInput = AudioSystem::getInput(mInputSource,
612e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten                                mSampleRate,
6137c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent                                mFormat,
6147c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent                                mChannelMask,
6157c7f10bd4fda9a084e5e7f0eb3a040dfcbf01745Eric Laurent                                mSessionId);
61605bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent    return mInput;
6176100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent}
6186100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent
619606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenint AudioRecord::getSessionId() const
620be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent{
621955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    // no lock needed because session ID doesn't change after first set()
622be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    return mSessionId;
623be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent}
624be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent
62589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
62689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
62789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectssize_t AudioRecord::read(void* buffer, size_t userSize)
62889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
62989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    ssize_t read = 0;
63089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    Buffer audioBuffer;
63189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    int8_t *dst = static_cast<int8_t*>(buffer);
63289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
63389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (ssize_t(userSize) < 0) {
63489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // sanity-check. user is most-likely passing an error code.
63529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("AudioRecord::read(buffer=%p, size=%u (%d)",
63689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                buffer, userSize, userSize);
63789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
63889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
63989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6401703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    mLock.lock();
6411703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
6421703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    // while we are accessing the cblk
643e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten    sp<IAudioRecord> audioRecord = mAudioRecord;
644e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten    sp<IMemory> iMem = mCblkMemory;
6451703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    mLock.unlock();
64689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
64789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    do {
64889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
649c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        audioBuffer.frameCount = userSize/frameSize();
65089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
65188335b1a749fe0157547907a2ce6c9632f4d2592Eric Laurent        // By using a wait count corresponding to twice the timeout period in
65288335b1a749fe0157547907a2ce6c9632f4d2592Eric Laurent        // obtainBuffer() we give a chance to recover once for a read timeout
65388335b1a749fe0157547907a2ce6c9632f4d2592Eric Laurent        // (if media_server crashed for instance) before returning a length of
65488335b1a749fe0157547907a2ce6c9632f4d2592Eric Laurent        // 0 bytes read to the client
65588335b1a749fe0157547907a2ce6c9632f4d2592Eric Laurent        status_t err = obtainBuffer(&audioBuffer, ((2 * MAX_RUN_TIMEOUT_MS) / WAIT_PERIOD_MS));
65689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (err < 0) {
65789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            // out of buffers, return #bytes written
658d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten            if (err == status_t(NO_MORE_BUFFERS)) {
65989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                break;
660d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten            }
661d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten            if (err == status_t(TIMED_OUT)) {
66288335b1a749fe0157547907a2ce6c9632f4d2592Eric Laurent                err = 0;
663d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten            }
66489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            return ssize_t(err);
66589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
66689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
66789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        size_t bytesRead = audioBuffer.size;
66889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        memcpy(dst, audioBuffer.i8, bytesRead);
66989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
67089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        dst += bytesRead;
67189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        userSize -= bytesRead;
67289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        read += bytesRead;
67389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
67489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        releaseBuffer(&audioBuffer);
67589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    } while (userSize);
67689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
67789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return read;
67889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
67989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
68089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
68189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
68268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenbool AudioRecord::processAudioBuffer(const sp<AudioRecordThread>& thread)
68389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
68489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    Buffer audioBuffer;
68589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    uint32_t frames = mRemainingFrames;
68689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    size_t readSize;
68789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6881703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    mLock.lock();
6891703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    // acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
6901703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    // while we are accessing the cblk
691e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten    sp<IAudioRecord> audioRecord = mAudioRecord;
692e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten    sp<IMemory> iMem = mCblkMemory;
6931703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    audio_track_cblk_t* cblk = mCblk;
69468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    bool active = mActive;
695955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    uint32_t markerPosition = mMarkerPosition;
696955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    uint32_t newPosition = mNewPosition;
697955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    uint32_t user = cblk->user;
698955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    // determine whether a marker callback will be needed, while locked
699955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    bool needMarker = !mMarkerReached && (mMarkerPosition > 0) && (user >= mMarkerPosition);
700955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    if (needMarker) {
701955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten        mMarkerReached = true;
702955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    }
703955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    // determine the number of new position callback(s) that will be needed, while locked
704955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    uint32_t updatePeriod = mUpdatePeriod;
705955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    uint32_t needNewPos = updatePeriod > 0 && user >= newPosition ?
706955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten            ((user - newPosition) / updatePeriod) + 1 : 0;
707955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    mNewPosition = newPosition + updatePeriod * needNewPos;
7081703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    mLock.unlock();
7091703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
710955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    // perform marker callback, while unlocked
711955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    if (needMarker) {
712955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten        mCbf(EVENT_MARKER, mUserData, &markerPosition);
71389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
71489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
715955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    // perform new position callback(s), while unlocked
716955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    for (; needNewPos > 0; --needNewPos) {
717955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten        uint32_t temp = newPosition;
718955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten        mCbf(EVENT_NEW_POS, mUserData, &temp);
719955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten        newPosition += updatePeriod;
72089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
72189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
72289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    do {
72389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        audioBuffer.frameCount = frames;
724c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        // Calling obtainBuffer() with a wait count of 1
725c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        // limits wait time to WAIT_PERIOD_MS. This prevents from being
72689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // stuck here not being able to handle timed events (position, markers).
72789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        status_t err = obtainBuffer(&audioBuffer, 1);
72889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (err < NO_ERROR) {
72989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            if (err != TIMED_OUT) {
73085ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten                ALOGE_IF(err != status_t(NO_MORE_BUFFERS),
73185ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten                        "Error obtaining an audio buffer, giving up.");
73289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                return false;
73389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
73489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            break;
73589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
73689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (err == status_t(STOPPED)) return false;
73789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
73889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        size_t reqSize = audioBuffer.size;
73989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
74089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        readSize = audioBuffer.size;
74189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
74289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Sanity check on returned size
743cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent        if (ssize_t(readSize) <= 0) {
744cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            // The callback is done filling buffers
745cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            // Keep this thread going to handle timed events and
746cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            // still try to get more data in intervals of WAIT_PERIOD_MS
747cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            // but don't just loop and block the CPU, so wait
748cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            usleep(WAIT_PERIOD_MS*1000);
749cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            break;
750cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent        }
75189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (readSize > reqSize) readSize = reqSize;
75289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
75389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        audioBuffer.size = readSize;
754c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        audioBuffer.frameCount = readSize/frameSize();
75589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        frames -= audioBuffer.frameCount;
75689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
75789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        releaseBuffer(&audioBuffer);
75889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
75989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    } while (frames);
76089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
761c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
76289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // Manage overrun callback
763e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    if (active && (mProxy->framesAvailable() == 0)) {
76468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        // The value of active is stale, but we are almost sure to be active here because
76568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        // otherwise we would have exited when obtainBuffer returned STOPPED earlier.
7663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
7679c5fdd83f9b9f49be35107971feb33528d60b945Glenn Kasten        if (!(android_atomic_or(CBLK_UNDERRUN, &cblk->flags) & CBLK_UNDERRUN)) {
768955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten            mCbf(EVENT_OVERRUN, mUserData, NULL);
76989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
77089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
77189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
77289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (frames == 0) {
77389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mRemainingFrames = mNotificationFrames;
77489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    } else {
77589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mRemainingFrames = frames;
77689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
77789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return true;
77889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
77989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7801703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent// must be called with mLock and cblk.lock held. Callers must also hold strong references on
7811703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent// the IAudioRecord and IMemory in case they are recreated here.
7821703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent// If the IAudioRecord is successfully restored, the cblk pointer is updated
783b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kastenstatus_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& refCblk)
7841703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent{
7851703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    status_t result;
7861703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
787b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    audio_track_cblk_t* cblk = refCblk;
788b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    audio_track_cblk_t* newCblk = cblk;
789b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    ALOGW("dead IAudioRecord, creating a new one");
7901703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
791b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    // signal old cblk condition so that other threads waiting for available buffers stop
792b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    // waiting now
793b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    cblk->cv.broadcast();
794b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    cblk->lock.unlock();
7951703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
796b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    // if the new IAudioRecord is created, openRecord_l() will modify the
797b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    // following member variables: mAudioRecord, mCblkMemory and mCblk.
798b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    // It will also delete the strong references on previous IAudioRecord and IMemory
799e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    result = openRecord_l(mSampleRate, mFormat, mFrameCount, getInput_l());
800b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    if (result == NO_ERROR) {
801b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten        newCblk = mCblk;
802b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten        // callback thread or sync event hasn't changed
803b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten        result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0);
804b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    }
805b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    if (result != NO_ERROR) {
806b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten        mActive = false;
8071703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    }
808b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten
8093856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("restoreRecord_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x",
810b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten        result, mActive, newCblk, cblk, newCblk->flags, cblk->flags);
8111703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
8121703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    if (result == NO_ERROR) {
8131703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        // from now on we switch to the newly created cblk
814b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten        refCblk = newCblk;
8151703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    }
816b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    newCblk->lock.lock();
8171703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
8185ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block    ALOGW_IF(result != NO_ERROR, "restoreRecord_l() error %d", result);
8191703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
8201703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    return result;
8211703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent}
8221703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
82389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// =========================================================================
82489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
82568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn KastenAudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver, bool bCanCallJava)
82668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    : Thread(bCanCallJava), mReceiver(receiver), mPaused(true)
82768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{
82868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten}
82968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten
83068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn KastenAudioRecord::AudioRecordThread::~AudioRecordThread()
83168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{
83268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten}
83368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten
83468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenbool AudioRecord::AudioRecordThread::threadLoop()
83568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{
83668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    {
83768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        AutoMutex _l(mMyLock);
83868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        if (mPaused) {
83968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mMyCond.wait(mMyLock);
84068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            // caller will check for exitPending()
84168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            return true;
84268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        }
84368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    }
84468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    if (!mReceiver.processAudioBuffer(this)) {
84568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        pause();
84668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    }
84768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    return true;
84868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten}
84968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten
85068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::requestExit()
85189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
85268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    // must be in this order to avoid a race condition
85368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    Thread::requestExit();
85468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    resume();
85589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
85689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
85768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::pause()
85889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
85968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    AutoMutex _l(mMyLock);
86068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    mPaused = true;
86189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
86289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
86368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::resume()
8646dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten{
86568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    AutoMutex _l(mMyLock);
86668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    if (mPaused) {
86768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        mPaused = false;
86868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        mMyCond.signal();
8696dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten    }
8706dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten}
8716dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten
87289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
87389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
87489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}; // namespace android
875