Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dee7f834 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change I93f500a5 into eclair

* changes:
  Fix issue 2203561: Sholes: audio playing out of earpiece.
parents d763b951 34f1d8ec
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -314,6 +314,11 @@ private:
    };

            bool processAudioBuffer(const sp<ClientRecordThread>& thread);
            status_t openRecord(uint32_t sampleRate,
                                int format,
                                int channelCount,
                                int frameCount,
                                uint32_t flags);

    sp<IAudioRecord>        mAudioRecord;
    sp<IMemory>             mCblkMemory;
@@ -341,6 +346,7 @@ private:
    uint32_t                mNewPosition;
    uint32_t                mUpdatePeriod;
    audio_io_handle_t       mInput;
    uint32_t                mFlags;
};

}; // namespace android
+8 −0
Original line number Diff line number Diff line
@@ -391,6 +391,14 @@ private:
    };

            bool processAudioBuffer(const sp<AudioTrackThread>& thread);
            status_t createTrack(int streamType,
                                 uint32_t sampleRate,
                                 int format,
                                 int channelCount,
                                 int frameCount,
                                 uint32_t flags,
                                 const sp<IMemory>& sharedBuffer,
                                 audio_io_handle_t output);

    sp<IAudioTrack>         mAudioTrack;
    sp<IMemory>             mCblkMemory;
+2 −1
Original line number Diff line number Diff line
@@ -151,7 +151,7 @@ public:
        NUM_SUP_TONES = LAST_SUP_TONE-FIRST_SUP_TONE+1
    };

    ToneGenerator(int streamType, float volume);
    ToneGenerator(int streamType, float volume, bool threadCanCallJava = false);
    ~ToneGenerator();

    bool startTone(int toneType, int durationMs = -1);
@@ -242,6 +242,7 @@ private:

    static const ToneDescriptor sToneDescriptors[];

    bool mThreadCanCallJava;
    unsigned int mTotalSmp;  // Total number of audio samples played (gives current time)
    unsigned int mNextSegSmp;  // Position of next segment transition expressed in samples
    // NOTE: because mTotalSmp, mNextSegSmp are stored on 32 bit, current design will operate properly
+85 −42
Original line number Diff line number Diff line
@@ -101,11 +101,6 @@ status_t AudioRecord::set(
        return INVALID_OPERATION;
    }

    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
    if (audioFlinger == 0) {
        return NO_INIT;
    }

    if (inputSource == AUDIO_SOURCE_DEFAULT) {
        inputSource = AUDIO_SOURCE_MIC;
    }
@@ -171,22 +166,14 @@ status_t AudioRecord::set(
        notificationFrames = frameCount/2;
    }

    // open record channel
    status_t status;
    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), mInput,
                                                       sampleRate, format,
                                                       channelCount,
                                                       frameCount,
                                                       ((uint16_t)flags) << 16,
                                                       &status);
    if (record == 0) {
        LOGE("AudioFlinger could not create record track, status: %d", status);
    // create the IAudioRecord
    status_t status = openRecord(sampleRate, format, channelCount,
                                 frameCount, flags);

    if (status != NO_ERROR) {
        return status;
    }
    sp<IMemory> cblk = record->getCblk();
    if (cblk == 0) {
        return NO_INIT;
    }

    if (cbf != 0) {
        mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava);
        if (mClientRecordThread == 0) {
@@ -196,11 +183,6 @@ status_t AudioRecord::set(

    mStatus = NO_ERROR;

    mAudioRecord = record;
    mCblkMemory = cblk;
    mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
    mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
    mCblk->out = 0;
    mFormat = format;
    // Update buffer size in case it has been limited by AudioFlinger during track creation
    mFrameCount = mCblk->frameCount;
@@ -217,6 +199,7 @@ status_t AudioRecord::set(
    mNewPosition = 0;
    mUpdatePeriod = 0;
    mInputSource = (uint8_t)inputSource;
    mFlags = flags;

    return NO_ERROR;
}
@@ -283,6 +266,13 @@ status_t AudioRecord::start()

    if (android_atomic_or(1, &mActive) == 0) {
        ret = AudioSystem::startInput(mInput);
        if (ret == NO_ERROR) {
            ret = mAudioRecord->start();
            if (ret == DEAD_OBJECT) {
                LOGV("start() dead IAudioRecord: creating a new one");
                ret = openRecord(mCblk->sampleRate, mFormat, mChannelCount,
                        mFrameCount, mFlags);
            }
            if (ret == NO_ERROR) {
                mNewPosition = mCblk->user + mUpdatePeriod;
                mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
@@ -292,7 +282,11 @@ status_t AudioRecord::start()
                } else {
                    setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
                }
            ret = mAudioRecord->start();
            } else {
                LOGV("start() failed");
                AudioSystem::stopInput(mInput);
                android_atomic_and(~1, &mActive);
            }
        }
    }

@@ -396,10 +390,48 @@ status_t AudioRecord::getPosition(uint32_t *position)

// -------------------------------------------------------------------------

status_t AudioRecord::openRecord(
        uint32_t sampleRate,
        int format,
        int channelCount,
        int frameCount,
        uint32_t flags)
{
    status_t status;
    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
    if (audioFlinger == 0) {
        return NO_INIT;
    }

    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), mInput,
                                                       sampleRate, format,
                                                       channelCount,
                                                       frameCount,
                                                       ((uint16_t)flags) << 16,
                                                       &status);
    if (record == 0) {
        LOGE("AudioFlinger could not create record track, status: %d", status);
        return status;
    }
    sp<IMemory> cblk = record->getCblk();
    if (cblk == 0) {
        LOGE("Could not get control block");
        return NO_INIT;
    }
    mAudioRecord.clear();
    mAudioRecord = record;
    mCblkMemory.clear();
    mCblkMemory = cblk;
    mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
    mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
    mCblk->out = 0;

    return NO_ERROR;
}

status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
{
    int active;
    int timeout = 0;
    status_t result;
    audio_track_cblk_t* cblk = mCblk;
    uint32_t framesReq = audioBuffer->frameCount;
@@ -411,25 +443,40 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
    uint32_t framesReady = cblk->framesReady();

    if (framesReady == 0) {
        Mutex::Autolock _l(cblk->lock);
        cblk->lock.lock();
        goto start_loop_here;
        while (framesReady == 0) {
            active = mActive;
            if (UNLIKELY(!active))
            if (UNLIKELY(!active)) {
                cblk->lock.unlock();
                return NO_MORE_BUFFERS;
            if (UNLIKELY(!waitCount))
            }
            if (UNLIKELY(!waitCount)) {
                cblk->lock.unlock();
                return WOULD_BLOCK;
            timeout = 0;
            }
            result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
            if (__builtin_expect(result!=NO_ERROR, false)) {
                cblk->waitTimeMs += waitTimeMs;
                if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
                    LOGW(   "obtainBuffer timed out (is the CPU pegged?) "
                            "user=%08x, server=%08x", cblk->user, cblk->server);
                    timeout = 1;
                    cblk->lock.unlock();
                    result = mAudioRecord->start();
                    if (result == DEAD_OBJECT) {
                        LOGW("obtainBuffer() dead IAudioRecord: creating a new one");
                        result = openRecord(cblk->sampleRate, mFormat, mChannelCount,
                                            mFrameCount, mFlags);
                        if (result == NO_ERROR) {
                            cblk = mCblk;
                            cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
                        }
                    }
                    cblk->lock.lock();
                    cblk->waitTimeMs = 0;
                }
                if (--waitCount == 0) {
                    cblk->lock.unlock();
                    return TIMED_OUT;
                }
            }
@@ -437,13 +484,9 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
        start_loop_here:
            framesReady = cblk->framesReady();
        }
        cblk->lock.unlock();
    }

    LOGW_IF(timeout,
        "*** SERIOUS WARNING *** obtainBuffer() timed out "
        "but didn't need to be locked. We recovered, but "
        "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server);

    cblk->waitTimeMs = 0;

    if (framesReq > framesReady) {
+103 −60
Original line number Diff line number Diff line
@@ -122,11 +122,6 @@ status_t AudioTrack::set(
        return INVALID_OPERATION;
    }

    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
    if (audioFlinger == 0) {
       LOGE("Could not get audioflinger");
       return NO_INIT;
    }
    int afSampleRate;
    if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
        return NO_INIT;
@@ -217,28 +212,16 @@ status_t AudioTrack::set(
        }
    }

    // create the track
    status_t status;
    sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
                                                      streamType,
                                                      sampleRate,
                                                      format,
                                                      channelCount,
                                                      frameCount,
                                                      ((uint16_t)flags) << 16,
                                                      sharedBuffer,
                                                      output,
                                                      &status);
    mVolume[LEFT] = 1.0f;
    mVolume[RIGHT] = 1.0f;
    // create the IAudioTrack
    status_t status = createTrack(streamType, sampleRate, format, channelCount,
                                  frameCount, flags, sharedBuffer, output);

    if (track == 0) {
        LOGE("AudioFlinger could not create track, status: %d", status);
    if (status != NO_ERROR) {
        return status;
    }
    sp<IMemory> cblk = track->getCblk();
    if (cblk == 0) {
        LOGE("Could not get control block");
        return NO_INIT;
    }

    if (cbf != 0) {
        mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
        if (mAudioTrackThread == 0) {
@@ -249,22 +232,6 @@ status_t AudioTrack::set(

    mStatus = NO_ERROR;

    mAudioTrack = track;
    mCblkMemory = cblk;
    mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
    mCblk->out = 1;
    // Update buffer size in case it has been limited by AudioFlinger during track creation
    mFrameCount = mCblk->frameCount;
    if (sharedBuffer == 0) {
        mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
    } else {
        mCblk->buffers = sharedBuffer->pointer();
         // Force buffer full condition as data is already present in shared memory
        mCblk->stepUser(mFrameCount);
    }
    mCblk->volume[0] = mCblk->volume[1] = 0x1000;
    mVolume[LEFT] = 1.0f;
    mVolume[RIGHT] = 1.0f;
    mStreamType = streamType;
    mFormat = format;
    mChannels = channels;
@@ -351,7 +318,15 @@ void AudioTrack::start()
     }

    if (android_atomic_or(1, &mActive) == 0) {
        AudioSystem::startOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
        audio_io_handle_t output = AudioTrack::getOutput();
        status_t status = mAudioTrack->start();
        if (status == DEAD_OBJECT) {
            LOGV("start() dead IAudioTrack: creating a new one");
            status = createTrack(mStreamType, mCblk->sampleRate, mFormat, mChannelCount,
                                 mFrameCount, mFlags, mSharedBuffer, output);
        }
        if (status == NO_ERROR) {
            AudioSystem::startOutput(output, (AudioSystem::stream_type)mStreamType);
            mNewPosition = mCblk->server + mUpdatePeriod;
            mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
            mCblk->waitTimeMs = 0;
@@ -360,7 +335,10 @@ void AudioTrack::start()
            } else {
                setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
            }
        mAudioTrack->start();
        } else {
            LOGV("start() failed");
            android_atomic_and(~1, &mActive);
        }
    }

    if (t != 0) {
@@ -617,10 +595,67 @@ audio_io_handle_t AudioTrack::getOutput()

// -------------------------------------------------------------------------

status_t AudioTrack::createTrack(
        int streamType,
        uint32_t sampleRate,
        int format,
        int channelCount,
        int frameCount,
        uint32_t flags,
        const sp<IMemory>& sharedBuffer,
        audio_io_handle_t output)
{
    status_t status;
    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
    if (audioFlinger == 0) {
       LOGE("Could not get audioflinger");
       return NO_INIT;
    }

    sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
                                                      streamType,
                                                      sampleRate,
                                                      format,
                                                      channelCount,
                                                      frameCount,
                                                      ((uint16_t)flags) << 16,
                                                      sharedBuffer,
                                                      output,
                                                      &status);

    if (track == 0) {
        LOGE("AudioFlinger could not create track, status: %d", status);
        return status;
    }
    sp<IMemory> cblk = track->getCblk();
    if (cblk == 0) {
        LOGE("Could not get control block");
        return NO_INIT;
    }
    mAudioTrack.clear();
    mAudioTrack = track;
    mCblkMemory.clear();
    mCblkMemory = cblk;
    mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
    mCblk->out = 1;
    // Update buffer size in case it has been limited by AudioFlinger during track creation
    mFrameCount = mCblk->frameCount;
    if (sharedBuffer == 0) {
        mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
    } else {
        mCblk->buffers = sharedBuffer->pointer();
         // Force buffer full condition as data is already present in shared memory
        mCblk->stepUser(mFrameCount);
    }

    mCblk->volumeLR = (int32_t(int16_t(mVolume[LEFT] * 0x1000)) << 16) | int16_t(mVolume[RIGHT] * 0x1000);

    return NO_ERROR;
}

status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
{
    int active;
    int timeout = 0;
    status_t result;
    audio_track_cblk_t* cblk = mCblk;
    uint32_t framesReq = audioBuffer->frameCount;
@@ -632,17 +667,20 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
    uint32_t framesAvail = cblk->framesAvailable();

    if (framesAvail == 0) {
        Mutex::Autolock _l(cblk->lock);
        cblk->lock.lock();
        goto start_loop_here;
        while (framesAvail == 0) {
            active = mActive;
            if (UNLIKELY(!active)) {
                LOGV("Not active and NO_MORE_BUFFERS");
                cblk->lock.unlock();
                return NO_MORE_BUFFERS;
            }
            if (UNLIKELY(!waitCount))
            if (UNLIKELY(!waitCount)) {
                cblk->lock.unlock();
                return WOULD_BLOCK;
            timeout = 0;
            }

            result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
            if (__builtin_expect(result!=NO_ERROR, false)) {
                cblk->waitTimeMs += waitTimeMs;
@@ -654,14 +692,23 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
                                "user=%08x, server=%08x", this, cblk->user, cblk->server);
                        //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140)
                        cblk->lock.unlock();
                        mAudioTrack->start();
                        result = mAudioTrack->start();
                        if (result == DEAD_OBJECT) {
                            LOGW("obtainBuffer() dead IAudioTrack: creating a new one");
                            result = createTrack(mStreamType, cblk->sampleRate, mFormat, mChannelCount,
                                                 mFrameCount, mFlags, mSharedBuffer, getOutput());
                            if (result == NO_ERROR) {
                                cblk = mCblk;
                                cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
                            }
                        }
                        cblk->lock.lock();
                        timeout = 1;
                    }
                    cblk->waitTimeMs = 0;
                }

                if (--waitCount == 0) {
                    cblk->lock.unlock();
                    return TIMED_OUT;
                }
            }
@@ -669,6 +716,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
        start_loop_here:
            framesAvail = cblk->framesAvailable_l();
        }
        cblk->lock.unlock();
    }

    cblk->waitTimeMs = 0;
@@ -684,11 +732,6 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
        framesReq = bufferEnd - u;
    }

    LOGW_IF(timeout,
        "*** SERIOUS WARNING *** obtainBuffer() timed out "
        "but didn't need to be locked. We recovered, but "
        "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server);

    audioBuffer->flags = mMuted ? Buffer::MUTE : 0;
    audioBuffer->channelCount = mChannelCount;
    audioBuffer->frameCount = framesReq;
@@ -991,7 +1034,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount)
        // Mark that we have read the first buffer so that next time stepUser() is called
        // we switch to normal obtainBuffer() timeout period
        if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) {
            bufferTimeoutMs = MAX_RUN_TIMEOUT_MS - 1;
            bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS - 1;
        }
        // It is possible that we receive a flush()
        // while the mixer is processing a block: in this case,
Loading