Fix issue 2304669: VoiceIME: starting and canceling voice IME yields persistent "error 8" state on future attempts and breaks voice search.

Fixed AudioFlinger::openInput() broken in change ddb78e7753
so that an invalid IO handle (0) is returned in case of failure.
Applied the same correction to openOutput().
Modified RecordThread start procedure so that a failure occuring during the first read from audio input stream is detected and causes
the record start to fail.
Modified RecordThread stop procedure to make sure that audio input stream fd is closed before we exit the stop function.

Fixed AudioRecord JAVA and JNI implementation to take status of native AudioRecord::start() into account
and not change mRecordingState to RECORDSTATE_RECORDING if start fails.
This commit is contained in:
Eric Laurent
2009-12-05 05:20:01 -08:00
parent ae952b3bcc
commit 9cc489a219
5 changed files with 48 additions and 26 deletions

View File

@@ -224,17 +224,17 @@ native_track_failure:
// ----------------------------------------------------------------------------
static void
static int
android_media_AudioRecord_start(JNIEnv *env, jobject thiz)
{
AudioRecord *lpRecorder =
(AudioRecord *)env->GetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
if (lpRecorder == NULL ) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
return;
return AUDIORECORD_ERROR;
}
lpRecorder->start();
return android_media_translateRecorderErrorCode(lpRecorder->start());
}
@@ -482,7 +482,7 @@ static jint android_media_AudioRecord_get_min_buff_size(JNIEnv *env, jobject th
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
// name, signature, funcPtr
{"native_start", "()V", (void *)android_media_AudioRecord_start},
{"native_start", "()I", (void *)android_media_AudioRecord_start},
{"native_stop", "()V", (void *)android_media_AudioRecord_stop},
{"native_setup", "(Ljava/lang/Object;IIIII)I",
(void *)android_media_AudioRecord_setup},

View File

@@ -3086,23 +3086,34 @@ bool AudioFlinger::RecordThread::threadLoop()
}
if (mActiveTrack != 0) {
if (mActiveTrack->mState == TrackBase::PAUSING) {
if (!mStandby) {
mInput->standby();
mStandby = true;
}
mActiveTrack.clear();
mStartStopCond.broadcast();
} else if (mActiveTrack->mState == TrackBase::RESUMING) {
mRsmpInIndex = mFrameCount;
if (mReqChannelCount != mActiveTrack->channelCount()) {
mActiveTrack.clear();
} else {
mActiveTrack->mState = TrackBase::ACTIVE;
mStartStopCond.broadcast();
} else if (mBytesRead != 0) {
// record start succeeds only if first read from audio input
// succeeds
if (mBytesRead > 0) {
mActiveTrack->mState = TrackBase::ACTIVE;
} else {
mActiveTrack.clear();
}
mStartStopCond.broadcast();
}
mStartStopCond.broadcast();
mStandby = false;
}
mStandby = false;
}
}
if (mActiveTrack != 0) {
if (mActiveTrack->mState != TrackBase::ACTIVE) {
if (mActiveTrack->mState != TrackBase::ACTIVE &&
mActiveTrack->mState != TrackBase::RESUMING) {
usleep(5000);
continue;
}
@@ -3140,18 +3151,19 @@ bool AudioFlinger::RecordThread::threadLoop()
}
}
if (framesOut && mFrameCount == mRsmpInIndex) {
ssize_t bytesRead;
if (framesOut == mFrameCount &&
(mChannelCount == mReqChannelCount || mFormat != AudioSystem::PCM_16_BIT)) {
bytesRead = mInput->read(buffer.raw, mInputBytes);
mBytesRead = mInput->read(buffer.raw, mInputBytes);
framesOut = 0;
} else {
bytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
mRsmpInIndex = 0;
}
if (bytesRead < 0) {
if (mBytesRead < 0) {
LOGE("Error reading audio input");
sleep(1);
if (mActiveTrack->mState == TrackBase::ACTIVE) {
sleep(1);
}
mRsmpInIndex = mFrameCount;
framesOut = 0;
buffer.frameCount = 0;
@@ -3220,7 +3232,7 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac
if (recordTrack != mActiveTrack.get()) {
status = -EBUSY;
} else if (mActiveTrack->mState == TrackBase::PAUSING) {
mActiveTrack->mState = TrackBase::RESUMING;
mActiveTrack->mState = TrackBase::ACTIVE;
}
return status;
}
@@ -3235,6 +3247,8 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac
return status;
}
mActiveTrack->mState = TrackBase::RESUMING;
mRsmpInIndex = mFrameCount;
mBytesRead = 0;
// signal thread to start
LOGV("Signal record thread");
mWaitWorkCV.signal();
@@ -3275,6 +3289,7 @@ void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
mLock.unlock();
AudioSystem::stopInput(mId);
mLock.lock();
LOGV("Record stopped OK");
}
}
}
@@ -3325,10 +3340,12 @@ status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer*
int channelCount;
if (framesReady == 0) {
ssize_t bytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
if (bytesRead < 0) {
mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
if (mBytesRead < 0) {
LOGE("RecordThread::getNextBuffer() Error reading audio input");
sleep(1);
if (mActiveTrack->mState == TrackBase::ACTIVE) {
sleep(1);
}
buffer->raw = 0;
buffer->frameCount = 0;
return NOT_ENOUGH_DATA;
@@ -3546,9 +3563,11 @@ int AudioFlinger::openOutput(uint32_t *pDevices,
if (pFormat) *pFormat = format;
if (pChannels) *pChannels = channels;
if (pLatencyMs) *pLatencyMs = thread->latency();
return mNextThreadId;
}
return mNextThreadId;
return 0;
}
int AudioFlinger::openDuplicateOutput(int output1, int output2)
@@ -3694,9 +3713,11 @@ int AudioFlinger::openInput(uint32_t *pDevices,
if (pChannels) *pChannels = reqChannels;
input->standby();
return mNextThreadId;
}
return mNextThreadId;
return 0;
}
status_t AudioFlinger::closeInput(int input)

View File

@@ -744,6 +744,7 @@ private:
size_t mInputBytes;
int mReqChannelCount;
uint32_t mReqSampleRate;
ssize_t mBytesRead;
};
class RecordHandle : public android::BnAudioRecord {

View File

@@ -498,8 +498,9 @@ public class AudioRecord
// start recording
synchronized(mRecordingStateLock) {
native_start();
mRecordingState = RECORDSTATE_RECORDING;
if (native_start() == SUCCESS) {
mRecordingState = RECORDSTATE_RECORDING;
}
}
}
@@ -764,7 +765,7 @@ public class AudioRecord
private native final void native_release();
private native final void native_start();
private native final int native_start();
private native final void native_stop();

View File

@@ -125,7 +125,7 @@ status_t AudioRecord::set(
audio_io_handle_t input = AudioSystem::getInput(inputSource,
sampleRate, format, channels, (AudioSystem::audio_in_acoustics)flags);
if (input == 0) {
LOGE("Could not get audio output for stream type %d", inputSource);
LOGE("Could not get audio input for record source %d", inputSource);
return BAD_VALUE;
}
@@ -539,7 +539,6 @@ ssize_t AudioRecord::read(void* buffer, size_t userSize)
return BAD_VALUE;
}
LOGV("read size: %d", userSize);
do {