am fcae6c71: am 67b69292: Merge change I93f500a5 into eclair

Merge commit 'fcae6c71794696a074cabf20beeb02fd87853e30' into eclair-mr2-plus-aosp

* commit 'fcae6c71794696a074cabf20beeb02fd87853e30':
  Fix issue 2203561: Sholes: audio playing out of earpiece.
This commit is contained in:
Eric Laurent
2009-11-05 01:55:51 -08:00
committed by Android Git Automerger
9 changed files with 244 additions and 114 deletions

View File

@ -79,7 +79,7 @@ static void android_media_ToneGenerator_release(JNIEnv *env, jobject thiz) {
static void android_media_ToneGenerator_native_setup(JNIEnv *env, jobject thiz,
jint streamType, jint volume) {
ToneGenerator *lpToneGen = new ToneGenerator(streamType, AudioSystem::linearToLog(volume));
ToneGenerator *lpToneGen = new ToneGenerator(streamType, AudioSystem::linearToLog(volume), true);
env->SetIntField(thiz, fields.context, 0);

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;
}
@ -284,15 +267,26 @@ status_t AudioRecord::start()
if (android_atomic_or(1, &mActive) == 0) {
ret = AudioSystem::startInput(mInput);
if (ret == NO_ERROR) {
mNewPosition = mCblk->user + mUpdatePeriod;
mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
mCblk->waitTimeMs = 0;
if (t != 0) {
t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
} else {
setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
}
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;
mCblk->waitTimeMs = 0;
if (t != 0) {
t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
} else {
setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
}
} 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) {

View File

@ -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,16 +318,27 @@ void AudioTrack::start()
}
if (android_atomic_or(1, &mActive) == 0) {
AudioSystem::startOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
mNewPosition = mCblk->server + mUpdatePeriod;
mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
mCblk->waitTimeMs = 0;
if (t != 0) {
t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
} else {
setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
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;
if (t != 0) {
t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
} else {
setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
}
} else {
LOGV("start() failed");
android_atomic_and(~1, &mActive);
}
mAudioTrack->start();
}
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,

View File

@ -15,6 +15,10 @@
** limitations under the License.
*/
#define LOG_TAG "IAudioRecord"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <stdint.h>
#include <sys/types.h>
@ -42,8 +46,13 @@ public:
{
Parcel data, reply;
data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor());
remote()->transact(START, data, &reply);
return reply.readInt32();
status_t status = remote()->transact(START, data, &reply);
if (status == NO_ERROR) {
status = reply.readInt32();
} else {
LOGW("start() error: %s", strerror(-status));
}
return status;
}
virtual void stop()

View File

@ -15,6 +15,10 @@
** limitations under the License.
*/
#define LOG_TAG "IAudioTrack"
//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <stdint.h>
#include <sys/types.h>
@ -45,8 +49,13 @@ public:
{
Parcel data, reply;
data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
remote()->transact(START, data, &reply);
return reply.readInt32();
status_t status = remote()->transact(START, data, &reply);
if (status == NO_ERROR) {
status = reply.readInt32();
} else {
LOGW("start() error: %s", strerror(-status));
}
return status;
}
virtual void stop()

View File

@ -798,7 +798,7 @@ const unsigned char ToneGenerator::sToneMappingTable[NUM_REGIONS-1][NUM_SUP_TONE
// none
//
////////////////////////////////////////////////////////////////////////////////
ToneGenerator::ToneGenerator(int streamType, float volume) {
ToneGenerator::ToneGenerator(int streamType, float volume, bool threadCanCallJava) {
LOGV("ToneGenerator constructor: streamType=%d, volume=%f\n", streamType, volume);
@ -808,6 +808,7 @@ ToneGenerator::ToneGenerator(int streamType, float volume) {
LOGE("Unable to marshal AudioFlinger");
return;
}
mThreadCanCallJava = threadCanCallJava;
mStreamType = streamType;
mVolume = volume;
mpAudioTrack = 0;
@ -1015,15 +1016,25 @@ bool ToneGenerator::initAudioTrack() {
}
// Open audio track in mono, PCM 16bit, default sampling rate, default buffer size
mpAudioTrack
= new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, AudioSystem::CHANNEL_OUT_MONO, 0, 0, audioCallback, this, 0);
mpAudioTrack = new AudioTrack();
if (mpAudioTrack == 0) {
LOGE("AudioTrack allocation failed");
goto initAudioTrack_exit;
}
LOGV("Create Track: %p\n", mpAudioTrack);
mpAudioTrack->set(mStreamType,
0,
AudioSystem::PCM_16_BIT,
AudioSystem::CHANNEL_OUT_MONO,
0,
0,
audioCallback,
this,
0,
0,
mThreadCanCallJava);
if (mpAudioTrack->initCheck() != NO_ERROR) {
LOGE("AudioTrack->initCheck failed");
goto initAudioTrack_exit;