189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project/*
289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Copyright 2008, The Android Open Source Project
489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** you may not use this file except in compliance with the License.
789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** You may obtain a copy of the License at
889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
1089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
1189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
1289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
1389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** See the License for the specific language governing permissions and
1589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** limitations under the License.
1689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project*/
1789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
1889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project//#define LOG_NDEBUG 0
1989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#define LOG_TAG "AudioRecord"
2089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2134fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn#include <inttypes.h>
2289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <sys/resource.h>
2334fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn
24868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <binder/IPCThreadState.h>
2589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/AudioRecord.h>
2689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <utils/Log.h>
27868a6a357018e5872e064b7a13a9b891e2078962Glenn Kasten#include <private/media/AudioTrackShared.h>
281ab85ec401801ef9a9184650d0f5a1639b45eeb9Glenn Kasten#include <media/IAudioFlinger.h>
2989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#define WAIT_PERIOD_MS          10
319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectnamespace android {
3315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh// ---------------------------------------------------------------------------
3415304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh
3515304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh// static
3615304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yehstatus_t AudioRecord::getMinFrameCount(
37e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten        size_t* frameCount,
3815304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh        uint32_t sampleRate,
3958f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten        audio_format_t format,
40dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten        audio_channel_mask_t channelMask)
4115304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh{
429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (frameCount == NULL) {
439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
4504cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten
46b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten    size_t size;
47c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten    status_t status = AudioSystem::getInputBufferSize(sampleRate, format, channelMask, &size);
48c9b2e20f7c9a71e07ef398152709c76079decbcdGlenn Kasten    if (status != NO_ERROR) {
49b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten        ALOGE("AudioSystem could not query the input buffer size for sampleRate %u, format %#x, "
50b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten              "channelMask %#x; status %d", sampleRate, format, channelMask, status);
51b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten        return status;
5215304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    }
5315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh
54b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten    // We double the size of input buffer for ping pong use of record buffer.
55b42f318d9733f88c7eb9bedfd33b086b8ea5dff5Glenn Kasten    // Assumes audio_is_linear_pcm(format)
56e541269be94f3a1072932d51537905b120ef4733Andy Hung    if ((*frameCount = (size * 2) / (audio_channel_count_from_in_mask(channelMask) *
57e541269be94f3a1072932d51537905b120ef4733Andy Hung            audio_bytes_per_sample(format))) == 0) {
58cac3daa6332bf6d1f7d26adc4a9915f3d7992dd9Glenn Kasten        ALOGE("Unsupported configuration: sampleRate %u, format %#x, channelMask %#x",
59dd8104cc5367262f0e5f13df4e79f131e8d560bbGlenn Kasten            sampleRate, format, channelMask);
6015304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh        return BAD_VALUE;
6115304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    }
6215304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh
6315304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh    return NO_ERROR;
6415304d601cbf83be6519ca53e1a26b97d50d0192Chia-chi Yeh}
6589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ---------------------------------------------------------------------------
6789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
68be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet GanovAudioRecord::AudioRecord(const String16 &opPackageName)
699b3359feabbf138bb965da5173434da78bfe0929Haynes Mathew George    : mActive(false), mStatus(NO_INIT), mOpPackageName(opPackageName), mSessionId(AUDIO_SESSION_ALLOCATE),
70466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean      mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT),
71466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
7289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
7389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
7489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
7589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::AudioRecord(
76eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten        audio_source_t inputSource,
7789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t sampleRate,
7858f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten        audio_format_t format,
79624a7fcb377f2a40109c16de5109ae8ea1f67a69Glenn Kasten        audio_channel_mask_t channelMask,
80be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov        const String16& opPackageName,
81bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten        size_t frameCount,
8289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        callback_t cbf,
8389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        void* user,
84838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten        uint32_t notificationFrames,
85d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten        audio_session_t sessionId,
8627f7b2a8fe899565487d8a326676a5f7d0a05a37Glenn Kasten        transfer_type transferType,
87caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        audio_input_flags_t flags,
884cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi        int uid,
894cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi        pid_t pid,
90caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        const audio_attributes_t* pAttributes)
919b3359feabbf138bb965da5173434da78bfe0929Haynes Mathew George    : mActive(false),
929b3359feabbf138bb965da5173434da78bfe0929Haynes Mathew George      mStatus(NO_INIT),
93be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov      mOpPackageName(opPackageName),
94be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov      mSessionId(AUDIO_SESSION_ALLOCATE),
95e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
96e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten      mPreviousSchedulingGroup(SP_DEFAULT),
97466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean      mProxy(NULL),
98466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
9989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
1009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
101caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent            notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags,
1024cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi            uid, pid, pAttributes);
10389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
10489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
10589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioRecord::~AudioRecord()
10689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
10789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mStatus == NO_ERROR) {
10889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Make sure that callback function exits in the case where
10989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // it is looping on buffer empty condition in obtainBuffer().
11089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Otherwise the callback thread will never exit.
11189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        stop();
11268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        if (mAudioRecordThread != 0) {
1135a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten            mProxy->interrupt();
11468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mAudioRecordThread->requestExit();  // see comment in AudioRecord.h
11568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mAudioRecordThread->requestExitAndWait();
11668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mAudioRecordThread.clear();
11789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
118296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        // No lock here: worst case we remove a NULL callback which will be a nop
119296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) {
120296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent            AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
121296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        }
122f888020c6e2735624f2b2a30e72aca24e17b8b4dMarco Nelissen        IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this);
123089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten        mAudioRecord.clear();
1243bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent        mCblkMemory.clear();
1253bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent        mBufferMemory.clear();
12689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        IPCThreadState::self()->flushCommands();
1274c36d6f48f4eecacc148317f775f65961a4f03d2Glenn Kasten        ALOGV("~AudioRecord, releasing session id %d",
1284c36d6f48f4eecacc148317f775f65961a4f03d2Glenn Kasten                mSessionId);
1294c36d6f48f4eecacc148317f775f65961a4f03d2Glenn Kasten        AudioSystem::releaseAudioSessionId(mSessionId, -1 /*pid*/);
13089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
13189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
13289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
13389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::set(
134eba51fb3a361f67a6a64d5a16eba6084fe27d60eGlenn Kasten        audio_source_t inputSource,
13589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t sampleRate,
13658f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten        audio_format_t format,
137624a7fcb377f2a40109c16de5109ae8ea1f67a69Glenn Kasten        audio_channel_mask_t channelMask,
138bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten        size_t frameCount,
13989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        callback_t cbf,
14089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        void* user,
141838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten        uint32_t notificationFrames,
142be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        bool threadCanCallJava,
143d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten        audio_session_t sessionId,
14427f7b2a8fe899565487d8a326676a5f7d0a05a37Glenn Kasten        transfer_type transferType,
145caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        audio_input_flags_t flags,
1464cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi        int uid,
1474cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi        pid_t pid,
148caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        const audio_attributes_t* pAttributes)
14989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
150bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten    ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
1514cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi          "notificationFrames %u, sessionId %d, transferType %d, flags %#x, opPackageName %s "
1524cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi          "uid %d, pid %d",
153bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten          inputSource, sampleRate, format, channelMask, frameCount, notificationFrames,
1544cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi          sessionId, transferType, flags, String8(mOpPackageName).string(), uid, pid);
15586f04663032ddaa25110149d709bbf896ad83b02Glenn Kasten
1569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    switch (transferType) {
1579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_DEFAULT:
1589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (cbf == NULL || threadCanCallJava) {
1599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            transferType = TRANSFER_SYNC;
1609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        } else {
1619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            transferType = TRANSFER_CALLBACK;
1629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
1639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
1649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_CALLBACK:
1659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (cbf == NULL) {
1669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            ALOGE("Transfer type TRANSFER_CALLBACK but cbf == NULL");
1679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return BAD_VALUE;
1689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
1699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
1709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_OBTAIN:
1719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_SYNC:
1729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
1739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    default:
1749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Invalid transfer type %d", transferType);
1759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
1769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
1779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mTransfer = transferType;
1789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
179089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten    // invariant that mAudioRecord != 0 is true only after set() returns successfully
1801dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent    if (mAudioRecord != 0) {
1819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Track already in use");
18289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return INVALID_OPERATION;
18389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
18489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
185caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent    if (pAttributes == NULL) {
186caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        memset(&mAttributes, 0, sizeof(audio_attributes_t));
187caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        mAttributes.source = inputSource;
188caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent    } else {
189caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        // stream type shouldn't be looked at, this track has audio attributes
190caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
191caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        ALOGV("Building AudioRecord with attributes: source=%d flags=0x%x tags=[%s]",
192caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent              mAttributes.source, mAttributes.flags, mAttributes.tags);
193caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent    }
19489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
195e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    mSampleRate = sampleRate;
196e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
19789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // these below should probably come from the audioFlinger too...
19858f30210ea540b6ce5aa6a46330cd3499483cb97Glenn Kasten    if (format == AUDIO_FORMAT_DEFAULT) {
199fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin        format = AUDIO_FORMAT_PCM_16_BIT;
20089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
2019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
202c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    // validate parameters
2036770c6faa3467c92eabc5ec9b23d60eb556a0d03Andy Hung    // AudioFlinger capture only supports linear PCM
2046770c6faa3467c92eabc5ec9b23d60eb556a0d03Andy Hung    if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) {
2056770c6faa3467c92eabc5ec9b23d60eb556a0d03Andy Hung        ALOGE("Format %#x is not linear pcm", format);
206291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten        return BAD_VALUE;
207291bb6d8947c5b0c062f0895d623c529259bfa39Glenn Kasten    }
2082e4664677d72ce54201d3fd0beb0e10280add93cGlenn Kasten    mFormat = format;
20989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2100d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi    if (!audio_is_input_channel(channelMask)) {
2119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Invalid channel mask %#x", channelMask);
21289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
21389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
214a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten    mChannelMask = channelMask;
215e541269be94f3a1072932d51537905b120ef4733Andy Hung    uint32_t channelCount = audio_channel_count_from_in_mask(channelMask);
216a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten    mChannelCount = channelCount;
217c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
218c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten    if (audio_is_linear_pcm(format)) {
219c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten        mFrameSize = channelCount * audio_bytes_per_sample(format);
220c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten    } else {
221c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten        mFrameSize = sizeof(uint8_t);
222c85df82b1e8b05714268926a8bb3deb9c65f9a22Glenn Kasten    }
223e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
224b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    // mFrameCount is initialized in openRecord_l
225b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    mReqFrameCount = frameCount;
22689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2274a0efb77198c69df711ab369ac482a42dbdfab07Glenn Kasten    mNotificationFramesReq = notificationFrames;
2287410591dad836434c72ddee66680802708b70c10Glenn Kasten    // mNotificationFramesAct is initialized in openRecord_l
22989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
230aea7ea06394bcb155972d82055d4ea59962e4051Glenn Kasten    if (sessionId == AUDIO_SESSION_ALLOCATE) {
231d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten        mSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
232ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    } else {
233ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown        mSessionId = sessionId;
234ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    }
235ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    ALOGV("set(): mSessionId %d", mSessionId);
236ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown
2374cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi    int callingpid = IPCThreadState::self()->getCallingPid();
2384cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi    int mypid = getpid();
2394cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi    if (uid == -1 || (callingpid != mypid)) {
2404cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi        mClientUid = IPCThreadState::self()->getCallingUid();
2414cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi    } else {
2424cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi        mClientUid = uid;
2434cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi    }
2444cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi    if (pid == -1 || (callingpid != mypid)) {
2454cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi        mClientPid = callingpid;
2464cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi    } else {
2474cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi        mClientPid = pid;
2484cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi    }
2494cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi
25058883a0cbbde53579461ef7d9a639b4ac45cb55eGlenn Kasten    mOrigFlags = mFlags = flags;
251879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten    mCbf = cbf;
252879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten
253879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten    if (cbf != NULL) {
254879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten        mAudioRecordThread = new AudioRecordThread(*this, threadCanCallJava);
255879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten        mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO);
256bfd318402924414fbde4d31c9d23cc423f10b630Glenn Kasten        // thread begins in paused state, and will not reference us until start()
257879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten    }
258ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown
25934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    // create the IAudioRecord
260be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov    status_t status = openRecord_l(0 /*epoch*/, mOpPackageName);
261879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten
26238e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    if (status != NO_ERROR) {
263879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten        if (mAudioRecordThread != 0) {
264879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten            mAudioRecordThread->requestExit();   // see comment in AudioRecord.h
265879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten            mAudioRecordThread->requestExitAndWait();
266879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten            mAudioRecordThread.clear();
267879707057cde0a83b5f6143c918c66b8f4a97581Glenn Kasten        }
26889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return status;
26989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
27034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
27189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mStatus = NO_ERROR;
27289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUserData = user;
27389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // TODO: add audio hardware input latency here
2740b6bbcf0c2b2e249a4cbe5a5f40fcaab84431c1aAndy Hung    mLatency = (1000 * mFrameCount) / mSampleRate;
27589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mMarkerPosition = 0;
2767d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi    mMarkerReached = false;
27789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mNewPosition = 0;
27889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUpdatePeriod = 0;
279d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen    AudioSystem::acquireAudioSessionId(mSessionId, -1);
2809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mSequence = 1;
2819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mObservedSequence = mSequence;
2829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mInOverrun = false;
2833f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    mFramesRead = 0;
2843f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    mFramesReadServerOffset = 0;
28589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
28689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
28789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
28889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
28989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
29089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
291d848eb48c121c119e8ba7583efc75415fe102570Glenn Kastenstatus_t AudioRecord::start(AudioSystem::sync_event_t event, audio_session_t triggerSession)
29289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
293a011e35b22f95f558d81dc9c94b68b1465c4661dEric Laurent    ALOGV("start, sync event %d trigger session %d", event, triggerSession);
29489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
295f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent    AutoMutex lock(mLock);
2969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mActive) {
2979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return NO_ERROR;
2989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
2991703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
3003f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    // discard data in buffer
3013f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    const uint32_t framesFlushed = mProxy->flush();
3023f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    mFramesReadServerOffset -= mFramesRead + framesFlushed;
3033f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    mFramesRead = 0;
3043f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    mProxy->clearTimestamp();  // timestamp is invalid until next server push
3053f0c902beb53a245c9db35e871607dba05b8d391Andy Hung
3069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // reset current position as seen by client to 0
3079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition());
3085e1f79baa5c7355effbd2c9183787d6604487908Glenn Kasten    // force refresh of remaining frames by processAudioBuffer() as last
3095e1f79baa5c7355effbd2c9183787d6604487908Glenn Kasten    // read before stop could be partial.
3105e1f79baa5c7355effbd2c9183787d6604487908Glenn Kasten    mRefreshRemaining = true;
3116dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten
3129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mNewPosition = mProxy->getPosition() + mUpdatePeriod;
31396f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    int32_t flags = android_atomic_acquire_load(&mCblk->mFlags);
3149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3153da23b29af4b920d1bd99c097195409f0fabb83bAndy Hung    // we reactivate markers (mMarkerPosition != 0) as the position is reset to 0.
3163da23b29af4b920d1bd99c097195409f0fabb83bAndy Hung    // This is legacy behavior.  This is not done in stop() to avoid a race condition
3173da23b29af4b920d1bd99c097195409f0fabb83bAndy Hung    // where the last marker event is issued twice.
3183da23b29af4b920d1bd99c097195409f0fabb83bAndy Hung    mMarkerReached = false;
319296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    mActive = true;
320296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent
3219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    status_t status = NO_ERROR;
3229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!(flags & CBLK_INVALID)) {
3239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status = mAudioRecord->start(event, triggerSession);
3249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (status == DEAD_OBJECT) {
3259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            flags |= CBLK_INVALID;
3261703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        }
3279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
3289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (flags & CBLK_INVALID) {
3299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status = restoreRecord_l("start");
3309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
3319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (status != NO_ERROR) {
333296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        mActive = false;
3349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("start() status %d", status);
3359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
3369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        sp<AudioRecordThread> t = mAudioRecordThread;
3379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (t != 0) {
3389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            t->resume();
3396100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent        } else {
3409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mPreviousPriority = getpriority(PRIO_PROCESS, 0);
3419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            get_sched_policy(0, &mPreviousSchedulingGroup);
3429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
34389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
34489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
34589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
3469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return status;
34789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
34889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
349d64cd233eef39430561c1e1df423336a199cc5d7Glenn Kastenvoid AudioRecord::stop()
35089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
351f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent    AutoMutex lock(mLock);
3529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!mActive) {
3539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
3549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
3559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mActive = false;
3579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->interrupt();
3589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mAudioRecord->stop();
3593da23b29af4b920d1bd99c097195409f0fabb83bAndy Hung
3603da23b29af4b920d1bd99c097195409f0fabb83bAndy Hung    // Note: legacy handling - stop does not clear record marker and
3613da23b29af4b920d1bd99c097195409f0fabb83bAndy Hung    // periodic update position; we update those on start().
3623da23b29af4b920d1bd99c097195409f0fabb83bAndy Hung
3639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    sp<AudioRecordThread> t = mAudioRecordThread;
3649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (t != 0) {
3659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        t->pause();
3669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
3679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        setpriority(PRIO_PROCESS, 0, mPreviousPriority);
3689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        set_sched_policy(0, mPreviousSchedulingGroup);
36989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
37089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
37189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
37289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectbool AudioRecord::stopped() const
37389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
37468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    AutoMutex lock(mLock);
37589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return !mActive;
37689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
37789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
37889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setMarkerPosition(uint32_t marker)
37989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
3802b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten    // The only purpose of setting marker position is to get a callback
3819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mCbf == NULL) {
3829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
3839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
38489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
385955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
38689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mMarkerPosition = marker;
3877d563247cdac0509009d579bbf849157d47c38a9Jean-Michel Trivi    mMarkerReached = false;
38889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
389803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung    sp<AudioRecordThread> t = mAudioRecordThread;
390803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung    if (t != 0) {
391803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung        t->wake();
392803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung    }
39389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
39489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
39589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
396606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getMarkerPosition(uint32_t *marker) const
39789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
3989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (marker == NULL) {
3999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
4009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
40189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
402955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
40390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung    mMarkerPosition.getValue(marker);
40489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
40589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
40689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
40789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
40889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioRecord::setPositionUpdatePeriod(uint32_t updatePeriod)
40989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
4102b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten    // The only purpose of setting position update period is to get a callback
4119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mCbf == NULL) {
4129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
4139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
414955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten
415955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
4169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mNewPosition = mProxy->getPosition() + updatePeriod;
41789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUpdatePeriod = updatePeriod;
41889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
419803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung    sp<AudioRecordThread> t = mAudioRecordThread;
420803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung    if (t != 0) {
421803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung        t->wake();
422803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung    }
42389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
42489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
42589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
426606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const
42789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
4289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (updatePeriod == NULL) {
4299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
4309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
43189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
432955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    AutoMutex lock(mLock);
43389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    *updatePeriod = mUpdatePeriod;
43489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
43589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
43689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
43789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
438606ee61616efdba4696ae591ad10a4be33d8c946Glenn Kastenstatus_t AudioRecord::getPosition(uint32_t *position) const
43989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
4409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (position == NULL) {
4419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
4429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
44389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4441703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
44590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung    mProxy->getPosition().getValue(position);
44689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
44789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
44889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
44989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4505f972c031d4061f4f037c9fda1ea4bd9b6a756cdGlenn Kastenuint32_t AudioRecord::getInputFramesLost() const
45105bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent{
452bf04a5d7f287fc712e0ed91849dc85c90c1e182dGlenn Kasten    // no need to check mActive, because if inactive this will return 0, which is what we want
45332860f77787f41abac08afdfc2592272ccc31bcbGlenn Kasten    return AudioSystem::getInputFramesLost(getInputPrivate());
45405bca2fde53bfe3063d2a0a877f2b6bfdd6052cfEric Laurent}
45589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
4563f0c902beb53a245c9db35e871607dba05b8d391Andy Hungstatus_t AudioRecord::getTimestamp(ExtendedTimestamp *timestamp)
4573f0c902beb53a245c9db35e871607dba05b8d391Andy Hung{
4583f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    if (timestamp == nullptr) {
4593f0c902beb53a245c9db35e871607dba05b8d391Andy Hung        return BAD_VALUE;
4603f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    }
4613f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    AutoMutex lock(mLock);
4623f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    status_t status = mProxy->getTimestamp(timestamp);
4633f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    if (status == OK) {
4643f0c902beb53a245c9db35e871607dba05b8d391Andy Hung        timestamp->mPosition[ExtendedTimestamp::LOCATION_CLIENT] = mFramesRead;
4653f0c902beb53a245c9db35e871607dba05b8d391Andy Hung        timestamp->mTimeNs[ExtendedTimestamp::LOCATION_CLIENT] = 0;
4663f0c902beb53a245c9db35e871607dba05b8d391Andy Hung        // server side frame offset in case AudioRecord has been restored.
4673f0c902beb53a245c9db35e871607dba05b8d391Andy Hung        for (int i = ExtendedTimestamp::LOCATION_SERVER;
4683f0c902beb53a245c9db35e871607dba05b8d391Andy Hung                i < ExtendedTimestamp::LOCATION_MAX; ++i) {
4693f0c902beb53a245c9db35e871607dba05b8d391Andy Hung            if (timestamp->mTimeNs[i] >= 0) {
4703f0c902beb53a245c9db35e871607dba05b8d391Andy Hung                timestamp->mPosition[i] += mFramesReadServerOffset;
4713f0c902beb53a245c9db35e871607dba05b8d391Andy Hung            }
4723f0c902beb53a245c9db35e871607dba05b8d391Andy Hung        }
4733f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    }
4743f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    return status;
4753f0c902beb53a245c9db35e871607dba05b8d391Andy Hung}
4763f0c902beb53a245c9db35e871607dba05b8d391Andy Hung
477466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean// ---- Explicit Routing ---------------------------------------------------
478466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLeanstatus_t AudioRecord::setInputDevice(audio_port_handle_t deviceId) {
479466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean    AutoMutex lock(mLock);
480466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean    if (mSelectedDeviceId != deviceId) {
481466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean        mSelectedDeviceId = deviceId;
482296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        // stop capture so that audio policy manager does not reject the new instance start request
483296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        // as only one capture can be active at a time.
484296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        if (mAudioRecord != 0 && mActive) {
485296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent            mAudioRecord->stop();
486296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        }
487466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean        android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
488466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean    }
489466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean    return NO_ERROR;
490466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean}
491466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean
492466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLeanaudio_port_handle_t AudioRecord::getInputDevice() {
493466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean    AutoMutex lock(mLock);
494466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean    return mSelectedDeviceId;
495466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean}
496466dc8ed6ca6b7f585104806c48613dd34e608c9Paul McLean
497296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurentaudio_port_handle_t AudioRecord::getRoutedDeviceId() {
498296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    AutoMutex lock(mLock);
499296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    if (mInput == AUDIO_IO_HANDLE_NONE) {
500296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        return AUDIO_PORT_HANDLE_NONE;
501296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    }
502296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    return AudioSystem::getDeviceIdForIo(mInput);
503296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent}
504296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent
50589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
50689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
5071703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent// must be called with mLock held
50890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hungstatus_t AudioRecord::openRecord_l(const Modulo<uint32_t> &epoch, const String16& opPackageName)
50934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent{
51034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
51134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    if (audioFlinger == 0) {
512b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten        ALOGE("Could not get audioflinger");
51334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        return NO_INIT;
51434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
51534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
5167fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) {
5177fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten        AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
5187fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    }
5197fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    audio_io_handle_t input;
5207fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten
52158883a0cbbde53579461ef7d9a639b4ac45cb55eGlenn Kasten    // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted.
52258883a0cbbde53579461ef7d9a639b4ac45cb55eGlenn Kasten    // After fast request is denied, we will request again if IAudioRecord is re-created.
52358883a0cbbde53579461ef7d9a639b4ac45cb55eGlenn Kasten
5247fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    status_t status;
5252854e5182172de018a727db5862093a08628811cGlenn Kasten
5262854e5182172de018a727db5862093a08628811cGlenn Kasten    // Not a conventional loop, but a retry loop for at most two iterations total.
5272854e5182172de018a727db5862093a08628811cGlenn Kasten    // Try first maybe with FAST flag then try again without FAST flag if that fails.
5282854e5182172de018a727db5862093a08628811cGlenn Kasten    // Exits loop normally via a return at the bottom, or with error via a break.
5292854e5182172de018a727db5862093a08628811cGlenn Kasten    // The sp<> references will be dropped when re-entering scope.
5302854e5182172de018a727db5862093a08628811cGlenn Kasten    // The lack of indentation is deliberate, to reduce code churn and ease merges.
5312854e5182172de018a727db5862093a08628811cGlenn Kasten    for (;;) {
5322854e5182172de018a727db5862093a08628811cGlenn Kasten
5337fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    status = AudioSystem::getInputForAttr(&mAttributes, &input,
534d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten                                        mSessionId,
5357fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten                                        // FIXME compare to AudioTrack
536b2379ba0a32638bae2ea0460644f68cf5a0967ceEric Laurent                                        mClientPid,
537b2379ba0a32638bae2ea0460644f68cf5a0967ceEric Laurent                                        mClientUid,
5387fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten                                        mSampleRate, mFormat, mChannelMask,
5397fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten                                        mFlags, mSelectedDeviceId);
5407fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten
5417fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    if (status != NO_ERROR || input == AUDIO_IO_HANDLE_NONE) {
5427fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten        ALOGE("Could not get audio input for session %d, record source %d, sample rate %u, "
5437fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten              "format %#x, channel mask %#x, flags %#x",
5447fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten              mSessionId, mAttributes.source, mSampleRate, mFormat, mChannelMask, mFlags);
5457fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten        return BAD_VALUE;
5467fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    }
5472854e5182172de018a727db5862093a08628811cGlenn Kasten
5487fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger,
5497fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    // we must release it ourselves if anything goes wrong.
5507fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten
5517fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten#if 0
5527fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    size_t afFrameCount;
5537fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    status = AudioSystem::getFrameCount(input, &afFrameCount);
5547fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    if (status != NO_ERROR) {
5557fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten        ALOGE("getFrameCount(input=%d) status %d", input, status);
5562854e5182172de018a727db5862093a08628811cGlenn Kasten        break;
5577fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    }
5587fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten#endif
5597fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten
5607fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    uint32_t afSampleRate;
5617fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    status = AudioSystem::getSamplingRate(input, &afSampleRate);
5627fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    if (status != NO_ERROR) {
5637fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten        ALOGE("getSamplingRate(input=%d) status %d", input, status);
5642854e5182172de018a727db5862093a08628811cGlenn Kasten        break;
5657fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    }
5667fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    if (mSampleRate == 0) {
5677fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten        mSampleRate = afSampleRate;
568c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    }
5691879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten
5703151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten    // Client can only express a preference for FAST.  Server will perform additional tests.
5717fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
5727fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten        bool useCaseAllowed =
573b7fbf7ecc6b034243ec64f79f3113675b5e3c941Glenn Kasten            // either of these use cases:
574b7fbf7ecc6b034243ec64f79f3113675b5e3c941Glenn Kasten            // use case 1: callback transfer mode
575b7fbf7ecc6b034243ec64f79f3113675b5e3c941Glenn Kasten            (mTransfer == TRANSFER_CALLBACK) ||
576b7fbf7ecc6b034243ec64f79f3113675b5e3c941Glenn Kasten            // use case 2: obtain/release mode
5777fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten            (mTransfer == TRANSFER_OBTAIN);
5787fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten        // sample rates must also match
5797fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten        bool fastAllowed = useCaseAllowed && (mSampleRate == afSampleRate);
5807fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten        if (!fastAllowed) {
5817fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten            ALOGW("AUDIO_INPUT_FLAG_FAST denied by client; transfer %d, "
5827fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten                "track %u Hz, input %u Hz",
5834c36d6f48f4eecacc148317f775f65961a4f03d2Glenn Kasten                mTransfer, mSampleRate, afSampleRate);
5842854e5182172de018a727db5862093a08628811cGlenn Kasten            mFlags = (audio_input_flags_t) (mFlags & ~(AUDIO_INPUT_FLAG_FAST |
5852854e5182172de018a727db5862093a08628811cGlenn Kasten                    AUDIO_INPUT_FLAG_RAW));
586d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten            AudioSystem::releaseInput(input, mSessionId);
5872854e5182172de018a727db5862093a08628811cGlenn Kasten            continue;   // retry
5887fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten        }
589c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    }
590c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten
5917fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    // The notification frame count is the period between callbacks, as suggested by the client
5927fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    // but moderated by the server.  For record, the calculations are done entirely on server side.
5937fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    size_t notificationFrames = mNotificationFramesReq;
5947fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    size_t frameCount = mReqFrameCount;
5957fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten
596c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT;
597c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten
598c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten    pid_t tid = -1;
599ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
600c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten        trackFlags |= IAudioFlinger::TRACK_FAST;
601c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten        if (mAudioRecordThread != 0) {
6023151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten            tid = mAudioRecordThread->getTid();
6033151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten        }
6043151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten    }
6053151427b6b0adf99929433715bab6f1e505100c1Glenn Kasten
606b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    size_t temp = frameCount;   // temp may be replaced by a revised value of frameCount,
60774935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten                                // but we will still need the original value also
608d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten    audio_session_t originalSessionId = mSessionId;
6097df8c0b799d8f52d6386e03313286dbd7d5cdc7cGlenn Kasten
610d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    sp<IMemory> iMem;           // for cblk
611d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    sp<IMemory> bufferMem;
6128d6cc842e8d525405c68e57fdf3bc5da0b4d7e87Glenn Kasten    sp<IAudioRecord> record = audioFlinger->openRecord(input,
613be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov                                                       mSampleRate,
614be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov                                                       mFormat,
615a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten                                                       mChannelMask,
616be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov                                                       opPackageName,
61774935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten                                                       &temp,
618eeca32671896739e84050da5992d5f151a1629deGlenn Kasten                                                       &trackFlags,
6199ea77cdba8c422940adb57a790b44ac04fe0353fHaynes Mathew George                                                       mClientPid,
6201879fff068422852c1483dcf8365c2ff0e2fadfcGlenn Kasten                                                       tid,
6214cb668392ee0433462251afbee109405c6efacc8Jean-Michel Trivi                                                       mClientUid,
622be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent                                                       &mSessionId,
6237df8c0b799d8f52d6386e03313286dbd7d5cdc7cGlenn Kasten                                                       &notificationFrames,
624d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten                                                       iMem,
625d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten                                                       bufferMem,
62634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                                                       &status);
627aea7ea06394bcb155972d82055d4ea59962e4051Glenn Kasten    ALOGE_IF(originalSessionId != AUDIO_SESSION_ALLOCATE && mSessionId != originalSessionId,
628955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten            "session ID changed from %d to %d", originalSessionId, mSessionId);
6293a34befc6fb04a4945a849e8bda8b84e4bf973feMarco Nelissen
630c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten    if (status != NO_ERROR) {
63129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("AudioFlinger could not create record track, status: %d", status);
6322854e5182172de018a727db5862093a08628811cGlenn Kasten        break;
63334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
634c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten    ALOG_ASSERT(record != 0);
635c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten
63638e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    // AudioFlinger now owns the reference to the I/O handle,
63738e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    // so we are no longer responsible for releasing it.
63838e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten
6392854e5182172de018a727db5862093a08628811cGlenn Kasten    mAwaitBoost = false;
6402854e5182172de018a727db5862093a08628811cGlenn Kasten    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
6412854e5182172de018a727db5862093a08628811cGlenn Kasten        if (trackFlags & IAudioFlinger::TRACK_FAST) {
6422854e5182172de018a727db5862093a08628811cGlenn Kasten            ALOGI("AUDIO_INPUT_FLAG_FAST successful; frameCount %zu", frameCount);
6432854e5182172de018a727db5862093a08628811cGlenn Kasten            mAwaitBoost = true;
6442854e5182172de018a727db5862093a08628811cGlenn Kasten        } else {
6452854e5182172de018a727db5862093a08628811cGlenn Kasten            ALOGW("AUDIO_INPUT_FLAG_FAST denied by server; frameCount %zu", frameCount);
6462854e5182172de018a727db5862093a08628811cGlenn Kasten            mFlags = (audio_input_flags_t) (mFlags & ~(AUDIO_INPUT_FLAG_FAST |
6472854e5182172de018a727db5862093a08628811cGlenn Kasten                    AUDIO_INPUT_FLAG_RAW));
6482854e5182172de018a727db5862093a08628811cGlenn Kasten            continue;   // retry
6492854e5182172de018a727db5862093a08628811cGlenn Kasten        }
6502854e5182172de018a727db5862093a08628811cGlenn Kasten    }
6512854e5182172de018a727db5862093a08628811cGlenn Kasten
652b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    if (iMem == 0) {
65329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Could not get control block");
65434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        return NO_INIT;
65534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    }
656e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten    void *iMemPointer = iMem->pointer();
657e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten    if (iMemPointer == NULL) {
658e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten        ALOGE("Could not get control block pointer");
659e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten        return NO_INIT;
660e93cf2ca27ae6f4a81d4ef548bbf10a34db6d98fGlenn Kasten    }
661d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
662d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten
663d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    // Starting address of buffers in shared memory.
664d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    // The buffers are either immediately after the control block,
665d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    // or in a separate area at discretion of server.
666d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    void *buffers;
667d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    if (bufferMem == 0) {
668d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten        buffers = cblk + 1;
669d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    } else {
670d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten        buffers = bufferMem->pointer();
671d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten        if (buffers == NULL) {
672d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten            ALOGE("Could not get buffer pointer");
673d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten            return NO_INIT;
674d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten        }
675d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    }
676d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten
677089e87201522c8979ac8f00fa729e907f54c790bGlenn Kasten    // invariant that mAudioRecord != 0 is true only after set() returns successfully
6789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mAudioRecord != 0) {
679f888020c6e2735624f2b2a30e72aca24e17b8b4dMarco Nelissen        IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this);
6809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mDeathNotifier.clear();
6819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
68234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    mAudioRecord = record;
683b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    mCblkMemory = iMem;
684d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    mBufferMemory = bufferMem;
6853bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent    IPCThreadState::self()->flushCommands();
6863bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent
687b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    mCblk = cblk;
6885f631515d098c29603cda88f7a7e7580a2d55b57Glenn Kasten    // note that temp is the (possibly revised) value of frameCount
689b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    if (temp < frameCount || (frameCount == 0 && temp == 0)) {
69034fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn        ALOGW("Requested frameCount %zu but received frameCount %zu", frameCount, temp);
691b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    }
692b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    frameCount = temp;
69374935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten
6947fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    // Make sure that application is notified with sufficient margin before overrun.
6957fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    // The computation is done on server side.
6967fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    if (mNotificationFramesReq > 0 && notificationFrames != mNotificationFramesReq) {
6977fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten        ALOGW("Server adjusted notificationFrames from %u to %zu for frameCount %zu",
6987fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten                mNotificationFramesReq, notificationFrames, frameCount);
6997410591dad836434c72ddee66680802708b70c10Glenn Kasten    }
7007fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    mNotificationFramesAct = (uint32_t) notificationFrames;
7017410591dad836434c72ddee66680802708b70c10Glenn Kasten
702045e739161f5ae00321a6cfba20935abb791005bGlenn Kasten    // We retain a copy of the I/O handle, but don't own the reference
703045e739161f5ae00321a6cfba20935abb791005bGlenn Kasten    mInput = input;
704a5ed48d3476df7dd1e10b380a68e3333f2b646fdGlenn Kasten    mRefreshRemaining = true;
705a5ed48d3476df7dd1e10b380a68e3333f2b646fdGlenn Kasten
706b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten    mFrameCount = frameCount;
70711cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten    // If IAudioRecord is re-created, don't let the requested frameCount
70811cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten    // decrease.  This can confuse clients that cache frameCount().
70911cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten    if (frameCount > mReqFrameCount) {
71011cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten        mReqFrameCount = frameCount;
71111cb175005db0090345f44bfa049b52fd8c809b8Glenn Kasten    }
712b3b2e23fcf7e050710d23b82a6682c0f3d869b69Glenn Kasten
713e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    // update proxy
714ac0bbe16f3eba46b3d8057b66c2aff9101fc6f7dJeff Brown    mProxy = new AudioRecordClientProxy(cblk, buffers, mFrameCount, mFrameSize);
7159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->setEpoch(epoch);
7167cd9cf70e36ad4b8eb12e24f9adbbe6fd69edebdGlenn Kasten    mProxy->setMinimum(mNotificationFramesAct);
7179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mDeathNotifier = new DeathNotifier(this);
719f888020c6e2735624f2b2a30e72aca24e17b8b4dMarco Nelissen    IInterface::asBinder(mAudioRecord)->linkToDeath(mDeathNotifier, this);
720e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
721296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    if (mDeviceCallback != 0) {
722296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        AudioSystem::addAudioDeviceCallback(mDeviceCallback, mInput);
723296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    }
724296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent
72534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    return NO_ERROR;
7262854e5182172de018a727db5862093a08628811cGlenn Kasten
7272854e5182172de018a727db5862093a08628811cGlenn Kasten    // End of retry loop.
7282854e5182172de018a727db5862093a08628811cGlenn Kasten    // The lack of indentation is deliberate, to reduce code churn and ease merges.
72938e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    }
73038e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten
7312854e5182172de018a727db5862093a08628811cGlenn Kasten// Arrive here on error, via a break
732d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten    AudioSystem::releaseInput(input, mSessionId);
73338e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    if (status == NO_ERROR) {
73438e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        status = NO_INIT;
73538e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    }
73638e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    return status;
73734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent}
73834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
739551b5355d34aa42890811fc3606d3b63429296cdGlenn Kastenstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount, size_t *nonContig)
74089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
7419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (audioBuffer == NULL) {
742551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten        if (nonContig != NULL) {
743551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten            *nonContig = 0;
744551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten        }
7459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
7469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mTransfer != TRANSFER_OBTAIN) {
7489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer->frameCount = 0;
7499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer->size = 0;
7509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer->raw = NULL;
751551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten        if (nonContig != NULL) {
752551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten            *nonContig = 0;
753551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten        }
7549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
7559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
756e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
7579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    const struct timespec *requested;
758df576995a5aad3428aeeef765387d650945c161dEric Laurent    struct timespec timeout;
7599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (waitCount == -1) {
7609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &ClientProxy::kForever;
7619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else if (waitCount == 0) {
7629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &ClientProxy::kNonBlocking;
7639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else if (waitCount > 0) {
7649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        long long ms = WAIT_PERIOD_MS * (long long) waitCount;
7659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timeout.tv_sec = ms / 1000;
7669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timeout.tv_nsec = (int) (ms % 1000) * 1000000;
7679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &timeout;
7689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
7699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("%s invalid waitCount %d", __func__, waitCount);
7709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = NULL;
7719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
772551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten    return obtainBuffer(audioBuffer, requested, NULL /*elapsed*/, nonContig);
7739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
7749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t AudioRecord::obtainBuffer(Buffer* audioBuffer, const struct timespec *requested,
7769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        struct timespec *elapsed, size_t *nonContig)
7779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
7789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // previous and new IAudioRecord sequence numbers are used to detect track re-creation
7799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t oldSequence = 0;
7809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t newSequence;
7819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    Proxy::Buffer buffer;
7839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    status_t status = NO_ERROR;
7849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    static const int32_t kMaxTries = 5;
7869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    int32_t tryCounter = kMaxTries;
7879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    do {
7899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // obtainBuffer() is called with mutex unlocked, so keep extra references to these fields to
7909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // keep them from going away if another thread re-creates the track during obtainBuffer()
7919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        sp<AudioRecordClientProxy> proxy;
7929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        sp<IMemory> iMem;
793d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten        sp<IMemory> bufferMem;
7949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        {
7959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // start of lock scope
7969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            AutoMutex lock(mLock);
7979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            newSequence = mSequence;
7999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // did previous obtainBuffer() fail due to media server death or voluntary invalidation?
8009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (status == DEAD_OBJECT) {
8019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                // re-create track, unless someone else has already done so
8029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                if (newSequence == oldSequence) {
8039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    status = restoreRecord_l("obtainBuffer");
8049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    if (status != NO_ERROR) {
805d8a9d0220e84ae0b5049385aa9b1a0d8ea02b5bbGlenn Kasten                        buffer.mFrameCount = 0;
806d8a9d0220e84ae0b5049385aa9b1a0d8ea02b5bbGlenn Kasten                        buffer.mRaw = NULL;
807d8a9d0220e84ae0b5049385aa9b1a0d8ea02b5bbGlenn Kasten                        buffer.mNonContig = 0;
8089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                        break;
80934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                    }
81089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                }
81189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
8129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            oldSequence = newSequence;
81389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // Keep the extra references
8159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            proxy = mProxy;
8169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            iMem = mCblkMemory;
817d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten            bufferMem = mBufferMemory;
818c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
8199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // Non-blocking if track is stopped
8209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (!mActive) {
8219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                requested = &ClientProxy::kNonBlocking;
8229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            }
82389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }   // end of lock scope
82589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer.mFrameCount = audioBuffer->frameCount;
8279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // FIXME starts the requested timeout and elapsed over from scratch
8289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status = proxy->obtainBuffer(&buffer, requested, elapsed);
8299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } while ((status == DEAD_OBJECT) && (tryCounter-- > 0));
83189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audioBuffer->frameCount = buffer.mFrameCount;
8339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audioBuffer->size = buffer.mFrameCount * mFrameSize;
8349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audioBuffer->raw = buffer.mRaw;
8359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (nonContig != NULL) {
8369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        *nonContig = buffer.mNonContig;
8379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return status;
83989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
84089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8415014c94c1bbac4a4284576b0015ba75145237593Glenn Kastenvoid AudioRecord::releaseBuffer(const Buffer* audioBuffer)
84289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
84317ea1351633d4f5e4f9eafd0778eb8b59fa30f10Glenn Kasten    // FIXME add error checking on mode, by adding an internal version
8449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t stepCount = audioBuffer->size / mFrameSize;
8469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (stepCount == 0) {
8479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
8489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    Proxy::Buffer buffer;
8519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer.mFrameCount = stepCount;
8529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer.mRaw = audioBuffer->raw;
853e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
8541703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
8559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mInOverrun = false;
8569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->releaseBuffer(&buffer);
8579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // the server does not automatically disable recorder on overrun, so no need to restart
85989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
86089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
86132860f77787f41abac08afdfc2592272ccc31bcbGlenn Kastenaudio_io_handle_t AudioRecord::getInputPrivate() const
8626100d2d60517ff33ed8eb35d0b7ea63cde0831c9Eric Laurent{
8631703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
864d1a243e41caffa8fd346907eed4625c9c47c1a86Eric Laurent    return mInput;
8651703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent}
8661703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
86789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
86889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8693622cdff65f34a99d2f55936a895387ad41510ceGlenn Kastenssize_t AudioRecord::read(void* buffer, size_t userSize, bool blocking)
87089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
8719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mTransfer != TRANSFER_SYNC) {
8729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
8739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
87489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) {
8769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // sanity-check. user is most-likely passing an error code, and it would
8779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // make the return value ambiguous (actualSize vs error).
87834fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn        ALOGE("AudioRecord::read(buffer=%p, size=%zu (%zu)", buffer, userSize, userSize);
87989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
88089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
88189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ssize_t read = 0;
8839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    Buffer audioBuffer;
88489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    while (userSize >= mFrameSize) {
8869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer.frameCount = userSize / mFrameSize;
88789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
8883622cdff65f34a99d2f55936a895387ad41510ceGlenn Kasten        status_t err = obtainBuffer(&audioBuffer,
8893622cdff65f34a99d2f55936a895387ad41510ceGlenn Kasten                blocking ? &ClientProxy::kForever : &ClientProxy::kNonBlocking);
89089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (err < 0) {
8919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (read > 0) {
89289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                break;
893d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten            }
89489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            return ssize_t(err);
89589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
89689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
89789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        size_t bytesRead = audioBuffer.size;
8989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        memcpy(buffer, audioBuffer.i8, bytesRead);
8999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer = ((char *) buffer) + bytesRead;
90089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        userSize -= bytesRead;
90189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        read += bytesRead;
90289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
90389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        releaseBuffer(&audioBuffer);
9049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
9053f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    if (read > 0) {
9063f0c902beb53a245c9db35e871607dba05b8d391Andy Hung        mFramesRead += read / mFrameSize;
9073f0c902beb53a245c9db35e871607dba05b8d391Andy Hung        // mFramesReadTime = systemTime(SYSTEM_TIME_MONOTONIC); // not provided at this time.
9083f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    }
90989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return read;
91089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
91189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
91289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
91389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
9147c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kastennsecs_t AudioRecord::processAudioBuffer()
91589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
9161703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    mLock.lock();
91728f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten    if (mAwaitBoost) {
91828f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        mAwaitBoost = false;
91928f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        mLock.unlock();
92028f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        static const int32_t kMaxTries = 5;
92128f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        int32_t tryCounter = kMaxTries;
92228f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        uint32_t pollUs = 10000;
92328f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        do {
92428f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            int policy = sched_getscheduler(0);
92528f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            if (policy == SCHED_FIFO || policy == SCHED_RR) {
92628f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten                break;
92728f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            }
92828f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            usleep(pollUs);
92928f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            pollUs <<= 1;
93028f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        } while (tryCounter-- > 0);
93128f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        if (tryCounter < 0) {
93228f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten            ALOGE("did not receive expected priority boost on time");
93328f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        }
93428f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        // Run again immediately
93528f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten        return 0;
93628f1351369682801e1bb40a835bdae3c97b73c1cGlenn Kasten    }
9379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
9389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Can only reference mCblk while locked
93996f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    int32_t flags = android_atomic_and(~CBLK_OVERRUN, &mCblk->mFlags);
9409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
9419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Check for track invalidation
9429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (flags & CBLK_INVALID) {
9439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        (void) restoreRecord_l("processAudioBuffer");
9449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mLock.unlock();
9459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // Run again immediately, but with a new IAudioRecord
9469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return 0;
9479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
9489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
94968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    bool active = mActive;
9509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
9519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Manage overrun callback, must be done under lock to avoid race with releaseBuffer()
9529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    bool newOverrun = false;
9539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (flags & CBLK_OVERRUN) {
9549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (!mInOverrun) {
9559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mInOverrun = true;
9569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            newOverrun = true;
9579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
9589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
9599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
9609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Get current position of server
96190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung    Modulo<uint32_t> position(mProxy->getPosition());
9629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
9639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Manage marker callback
9649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    bool markerReached = false;
96590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung    Modulo<uint32_t> markerPosition(mMarkerPosition);
9669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // FIXME fails for wraparound, need 64 bits
96790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung    if (!mMarkerReached && markerPosition.value() > 0 && position >= markerPosition) {
9689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mMarkerReached = markerReached = true;
9699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
9709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
9719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Determine the number of new position callback(s) that will be needed, while locked
9729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t newPosCount = 0;
97390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung    Modulo<uint32_t> newPosition(mNewPosition);
974955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten    uint32_t updatePeriod = mUpdatePeriod;
9759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // FIXME fails for wraparound, need 64 bits
9769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (updatePeriod > 0 && position >= newPosition) {
97790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung        newPosCount = ((position - newPosition).value() / updatePeriod) + 1;
9789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mNewPosition += updatePeriod * newPosCount;
9799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
9809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
9819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Cache other fields that will be needed soon
982838b3d8bafa4a781e277870dee4e0390165cff52Glenn Kasten    uint32_t notificationFrames = mNotificationFramesAct;
9839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mRefreshRemaining) {
9849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mRefreshRemaining = false;
9859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mRemainingFrames = notificationFrames;
9869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mRetryOnPartialBuffer = false;
9879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
9889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t misalignment = mProxy->getMisalignment();
9898ff50e7526d24aca11713006933b8dcb64ef6be9Glenn Kasten    uint32_t sequence = mSequence;
9909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
9919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // These fields don't need to be cached, because they are assigned only by set():
9922b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten    //      mTransfer, mCbf, mUserData, mSampleRate, mFrameSize
9939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
9941703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    mLock.unlock();
9951703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
9969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // perform callbacks while unlocked
9979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (newOverrun) {
9989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mCbf(EVENT_OVERRUN, mUserData, NULL);
9999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
10009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (markerReached) {
1001955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten        mCbf(EVENT_MARKER, mUserData, &markerPosition);
100289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
10039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    while (newPosCount > 0) {
100490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung        size_t temp = newPosition.value(); // FIXME size_t != uint32_t
1005955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten        mCbf(EVENT_NEW_POS, mUserData, &temp);
1006955e78180ac6111c54f50930b0c4c12395e86cf7Glenn Kasten        newPosition += updatePeriod;
10079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        newPosCount--;
10089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
10099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mObservedSequence != sequence) {
10109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mObservedSequence = sequence;
10119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mCbf(EVENT_NEW_IAUDIORECORD, mUserData, NULL);
101289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
101389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
10149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // if inactive, then don't run me again until re-started
10159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!active) {
10169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return NS_INACTIVE;
10179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
10189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
10199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Compute the estimated time until the next timed event (position, markers)
10209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t minFrames = ~0;
10219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!markerReached && position < markerPosition) {
102290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung        minFrames = (markerPosition - position).value();
10239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
1024fb7df2c355aad453f1978207e4116b2d4a61f34bAndy Hung    if (updatePeriod > 0) {
102590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung        uint32_t remaining = (newPosition - position).value();
1026fb7df2c355aad453f1978207e4116b2d4a61f34bAndy Hung        if (remaining < minFrames) {
1027fb7df2c355aad453f1978207e4116b2d4a61f34bAndy Hung            minFrames = remaining;
1028fb7df2c355aad453f1978207e4116b2d4a61f34bAndy Hung        }
10299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
10309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
10319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // If > 0, poll periodically to recover from a stuck server.  A good value is 2.
10329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    static const uint32_t kPoll = 0;
10339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (kPoll > 0 && mTransfer == TRANSFER_CALLBACK && kPoll * notificationFrames < minFrames) {
10349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        minFrames = kPoll * notificationFrames;
10359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
10369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
10379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Convert frame units to time units
10389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    nsecs_t ns = NS_WHENEVER;
10399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (minFrames != (uint32_t) ~0) {
10409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // This "fudge factor" avoids soaking CPU, and compensates for late progress by server
10419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        static const nsecs_t kFudgeNs = 10000000LL; // 10 ms
10429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ns = ((minFrames * 1000000000LL) / mSampleRate) + kFudgeNs;
10439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
10449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
10459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // If not supplying data by EVENT_MORE_DATA, then we're done
10469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mTransfer != TRANSFER_CALLBACK) {
10479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return ns;
10489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
10499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
10509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    struct timespec timeout;
10519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    const struct timespec *requested = &ClientProxy::kForever;
10529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (ns != NS_WHENEVER) {
10539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timeout.tv_sec = ns / 1000000000LL;
10549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timeout.tv_nsec = ns % 1000000000LL;
10559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGV("timeout %ld.%03d", timeout.tv_sec, (int) timeout.tv_nsec / 1000000);
10569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &timeout;
10579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
10589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
10593f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    size_t readFrames = 0;
10609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    while (mRemainingFrames > 0) {
10619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
10629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        Buffer audioBuffer;
10639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer.frameCount = mRemainingFrames;
10649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t nonContig;
10659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig);
10669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0),
106734fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn                "obtainBuffer() err=%d frameCount=%zu", err, audioBuffer.frameCount);
10689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        requested = &ClientProxy::kNonBlocking;
10699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t avail = audioBuffer.frameCount + nonContig;
107034fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn        ALOGV("obtainBuffer(%u) returned %zu = %zu + %zu err %d",
10712b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten                mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err);
10729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (err != NO_ERROR) {
10739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR) {
10749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                break;
10759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            }
10769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            ALOGE("Error %d obtaining an audio buffer, giving up.", err);
10779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return NS_NEVER;
10789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
10799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
10809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mRetryOnPartialBuffer) {
10819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mRetryOnPartialBuffer = false;
10829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (avail < mRemainingFrames) {
10839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                int64_t myns = ((mRemainingFrames - avail) *
10849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                        1100000000LL) / mSampleRate;
10859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                if (ns < 0 || myns < ns) {
10869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    ns = myns;
10879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                }
10889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                return ns;
108989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
109089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
109189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
109289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        size_t reqSize = audioBuffer.size;
109389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
10949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t readSize = audioBuffer.size;
109589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
109689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Sanity check on returned size
10979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (ssize_t(readSize) < 0 || readSize > reqSize) {
109834fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn            ALOGE("EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes",
109934fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn                    reqSize, ssize_t(readSize));
11009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return NS_NEVER;
11019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
11029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
11039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (readSize == 0) {
11049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // The callback is done consuming buffers
1105cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            // Keep this thread going to handle timed events and
11069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // still try to provide more data in intervals of WAIT_PERIOD_MS
1107cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent            // but don't just loop and block the CPU, so wait
11089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return WAIT_PERIOD_MS * 1000000LL;
1109cd6725a333395ffeac3215ea4bf834a95aaa8defEric Laurent        }
111089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
11119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t releasedFrames = readSize / mFrameSize;
11129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioBuffer.frameCount = releasedFrames;
11139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mRemainingFrames -= releasedFrames;
11149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (misalignment >= releasedFrames) {
11159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            misalignment -= releasedFrames;
11169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        } else {
11179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            misalignment = 0;
11189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
111989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
112089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        releaseBuffer(&audioBuffer);
11213f0c902beb53a245c9db35e871607dba05b8d391Andy Hung        readFrames += releasedFrames;
112289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
11239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // FIXME here is where we would repeat EVENT_MORE_DATA again on same advanced buffer
11249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // if callback doesn't like to accept the full chunk
11259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (readSize < reqSize) {
11269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            continue;
11279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
112889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
11299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // There could be enough non-contiguous frames available to satisfy the remaining request
11309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mRemainingFrames <= nonContig) {
11319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            continue;
11329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
1133c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
11349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#if 0
11359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // This heuristic tries to collapse a series of EVENT_MORE_DATA that would total to a
11369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // sum <= notificationFrames.  It replaces that series by at most two EVENT_MORE_DATA
11379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // that total to a sum == notificationFrames.
11389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (0 < misalignment && misalignment <= mRemainingFrames) {
11399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mRemainingFrames = misalignment;
11409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return (mRemainingFrames * 1100000000LL) / mSampleRate;
114189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
11429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#endif
114389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
114489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
11453f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    if (readFrames > 0) {
11463f0c902beb53a245c9db35e871607dba05b8d391Andy Hung        AutoMutex lock(mLock);
11473f0c902beb53a245c9db35e871607dba05b8d391Andy Hung        mFramesRead += readFrames;
11483f0c902beb53a245c9db35e871607dba05b8d391Andy Hung        // mFramesReadTime = systemTime(SYSTEM_TIME_MONOTONIC); // not provided at this time.
11493f0c902beb53a245c9db35e871607dba05b8d391Andy Hung    }
11509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mRemainingFrames = notificationFrames;
11519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mRetryOnPartialBuffer = true;
11529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
11539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // A lot has transpired since ns was calculated, so run again immediately and re-calculate
11549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return 0;
115589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
115689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
11579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t AudioRecord::restoreRecord_l(const char *from)
11581703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent{
11599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ALOGW("dead IAudioRecord, creating a new one from %s()", from);
11609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ++mSequence;
11611703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
116258883a0cbbde53579461ef7d9a639b4ac45cb55eGlenn Kasten    mFlags = mOrigFlags;
116358883a0cbbde53579461ef7d9a639b4ac45cb55eGlenn Kasten
1164b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    // if the new IAudioRecord is created, openRecord_l() will modify the
1165d776ac63ce9c013c9626226e43f7db606e035838Glenn Kasten    // following member variables: mAudioRecord, mCblkMemory, mCblk, mBufferMemory.
1166b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    // It will also delete the strong references on previous IAudioRecord and IMemory
116790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung    Modulo<uint32_t> position(mProxy->getPosition());
11689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mNewPosition = position + mUpdatePeriod;
1169be71aa29a3c86d2e01cd17839d2a72ab09a1bce5Svet Ganov    status_t result = openRecord_l(position, mOpPackageName);
1170b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    if (result == NO_ERROR) {
11719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mActive) {
11729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // callback thread or sync event hasn't changed
11739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // FIXME this fails if we have a new AudioFlinger instance
1174d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten            result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, AUDIO_SESSION_NONE);
11759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
11763f0c902beb53a245c9db35e871607dba05b8d391Andy Hung        mFramesReadServerOffset = mFramesRead; // server resets to zero so we need an offset.
1177b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    }
1178b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten    if (result != NO_ERROR) {
11799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGW("restoreRecord_l() failed status %d", result);
1180b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten        mActive = false;
11811703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    }
1182b36a7a68af073b1e7fd5cad6aa2c52223fd30efdGlenn Kasten
11839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return result;
11849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
11851703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
1186296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurentstatus_t AudioRecord::addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback)
1187296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent{
1188296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    if (callback == 0) {
1189296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        ALOGW("%s adding NULL callback!", __FUNCTION__);
1190296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        return BAD_VALUE;
1191296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    }
1192296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    AutoMutex lock(mLock);
1193296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    if (mDeviceCallback == callback) {
1194296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        ALOGW("%s adding same callback!", __FUNCTION__);
1195296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        return INVALID_OPERATION;
1196296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    }
1197296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    status_t status = NO_ERROR;
1198296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    if (mInput != AUDIO_IO_HANDLE_NONE) {
1199296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        if (mDeviceCallback != 0) {
1200296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent            ALOGW("%s callback already present!", __FUNCTION__);
1201296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent            AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
1202296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        }
1203296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        status = AudioSystem::addAudioDeviceCallback(callback, mInput);
1204296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    }
1205296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    mDeviceCallback = callback;
1206296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    return status;
1207296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent}
1208296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent
1209296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurentstatus_t AudioRecord::removeAudioDeviceCallback(
1210296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        const sp<AudioSystem::AudioDeviceCallback>& callback)
1211296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent{
1212296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    if (callback == 0) {
1213296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        ALOGW("%s removing NULL callback!", __FUNCTION__);
1214296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        return BAD_VALUE;
1215296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    }
1216296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    AutoMutex lock(mLock);
1217296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    if (mDeviceCallback != callback) {
1218296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        ALOGW("%s removing different callback!", __FUNCTION__);
1219296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        return INVALID_OPERATION;
1220296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    }
1221296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    if (mInput != AUDIO_IO_HANDLE_NONE) {
1222296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mInput);
1223296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    }
1224296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    mDeviceCallback = 0;
1225296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    return NO_ERROR;
1226296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent}
1227296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent
12289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// =========================================================================
12291703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
12307c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kastenvoid AudioRecord::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
12319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
12329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    sp<AudioRecord> audioRecord = mAudioRecord.promote();
12339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (audioRecord != 0) {
12349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        AutoMutex lock(audioRecord->mLock);
12359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audioRecord->mProxy->binderDied();
12369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
12371703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent}
12381703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
123989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// =========================================================================
124089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
124168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn KastenAudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver, bool bCanCallJava)
124241721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten    : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mPausedInt(false), mPausedNs(0LL),
124341721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten      mIgnoreNextPausedInt(false)
124468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{
124568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten}
124668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten
124768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn KastenAudioRecord::AudioRecordThread::~AudioRecordThread()
124868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{
124968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten}
125068337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten
125168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenbool AudioRecord::AudioRecordThread::threadLoop()
125268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten{
125368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    {
125468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        AutoMutex _l(mMyLock);
125568337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        if (mPaused) {
125668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            mMyCond.wait(mMyLock);
125768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            // caller will check for exitPending()
125868337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten            return true;
125968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        }
126041721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten        if (mIgnoreNextPausedInt) {
126141721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten            mIgnoreNextPausedInt = false;
126241721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten            mPausedInt = false;
126341721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten        }
12645a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten        if (mPausedInt) {
12655a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten            if (mPausedNs > 0) {
12665a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten                (void) mMyCond.waitRelative(mMyLock, mPausedNs);
12675a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten            } else {
12685a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten                mMyCond.wait(mMyLock);
12695a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten            }
12709d2c78c4798ffd8c276c1bf0eaa0b34bc255a2daEric Laurent            mPausedInt = false;
12715a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten            return true;
12725a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten        }
127368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    }
12747c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kasten    nsecs_t ns =  mReceiver.processAudioBuffer();
12759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    switch (ns) {
12769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case 0:
12779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return true;
12789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case NS_INACTIVE:
12795a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten        pauseInternal();
12809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return true;
12819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case NS_NEVER:
12829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return false;
12835a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten    case NS_WHENEVER:
1284803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung        // Event driven: call wake() when callback notifications conditions change.
1285803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung        ns = INT64_MAX;
12865a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten        // fall through
12879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    default:
128834fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn        LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %" PRId64, ns);
12895a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten        pauseInternal(ns);
12909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return true;
129168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    }
129268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten}
129368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten
129468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::requestExit()
129589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
129668337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    // must be in this order to avoid a race condition
129768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    Thread::requestExit();
129841721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten    resume();
129989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
130089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
130168337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::pause()
130289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
130368337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    AutoMutex _l(mMyLock);
130468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    mPaused = true;
130589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
130689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
130768337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kastenvoid AudioRecord::AudioRecordThread::resume()
13086dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten{
130968337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten    AutoMutex _l(mMyLock);
131041721bb796da589f8a669d1db7687a0da8f88761Glenn Kasten    mIgnoreNextPausedInt = true;
13119d2c78c4798ffd8c276c1bf0eaa0b34bc255a2daEric Laurent    if (mPaused || mPausedInt) {
131268337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        mPaused = false;
13139d2c78c4798ffd8c276c1bf0eaa0b34bc255a2daEric Laurent        mPausedInt = false;
131468337edf595a0c345ba4b8adcd4f1e541a1d7eb7Glenn Kasten        mMyCond.signal();
13156dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten    }
13166dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten}
13176dbc1359f778575d09d6da722b060a6d72c2e7c5Glenn Kasten
1318803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hungvoid AudioRecord::AudioRecordThread::wake()
1319803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung{
1320803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung    AutoMutex _l(mMyLock);
1321805a0c70574676d0fb29aa5e1f23417786b42259Andy Hung    if (!mPaused) {
1322805a0c70574676d0fb29aa5e1f23417786b42259Andy Hung        // wake() might be called while servicing a callback - ignore the next
1323805a0c70574676d0fb29aa5e1f23417786b42259Andy Hung        // pause time and call processAudioBuffer.
1324803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung        mIgnoreNextPausedInt = true;
1325805a0c70574676d0fb29aa5e1f23417786b42259Andy Hung        if (mPausedInt && mPausedNs > 0) {
1326805a0c70574676d0fb29aa5e1f23417786b42259Andy Hung            // audio record is active and internally paused with timeout.
1327805a0c70574676d0fb29aa5e1f23417786b42259Andy Hung            mPausedInt = false;
1328805a0c70574676d0fb29aa5e1f23417786b42259Andy Hung            mMyCond.signal();
1329805a0c70574676d0fb29aa5e1f23417786b42259Andy Hung        }
1330803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung    }
1331803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung}
1332803b3e558022c6d0eb069308339dc84e6e8035dcAndy Hung
13335a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kastenvoid AudioRecord::AudioRecordThread::pauseInternal(nsecs_t ns)
13345a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten{
13355a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten    AutoMutex _l(mMyLock);
13365a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten    mPausedInt = true;
13375a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten    mPausedNs = ns;
13385a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten}
13395a6cd224d07c05b496b6aca050ce5ecf96f125afGlenn Kasten
134089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
134189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
134240bc906252974d0b389ae4a147232d0c9a97193fGlenn Kasten} // namespace android
1343