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