Fix EBADF in TTS synthesizeToFile method.

Recent TTS change altered how the TextToSpeech.synthesizeToFile method
operates. Previously, synthesis service was responsible for creating
output file. Now, client API creates a file and then sends opened file
descriptor using ParcelFileDescriptor.

On service side, I forgot to keep a reference to a ParcelFileDescriptor object.
When GC was removing it, it was closing underlying file descriptor, resulting
in a EBADF error for all following writes to the output file.

This change makes use of a ParcelFileDescriptor.AutoCloseOutputStream to keep a
reference to the ParcelFileDescriptor. It will be referenced until we are done
with writing.

Change-Id: I8327af0eaeabaebfbbd8816d959783e89086a7c5
This commit is contained in:
Przemyslaw Szczepaniak
2013-03-05 11:28:50 +00:00
committed by Android (Google) Code Review
parent f4d6f153e6
commit fcf671be89

View File

@@ -36,6 +36,7 @@ import android.util.Log;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Set;
@@ -656,19 +657,18 @@ public abstract class TextToSpeechService extends Service {
}
}
private class SynthesisToFileSpeechDescriptorItem extends SynthesisSpeechItem {
private final FileDescriptor mFileDescriptor;
private class SynthesisToFileOutputStreamSpeechItem extends SynthesisSpeechItem {
private final FileOutputStream mFileOutputStream;
public SynthesisToFileSpeechDescriptorItem(Object callerIdentity, int callerUid,
int callerPid, Bundle params, String text, FileDescriptor fileDescriptor) {
int callerPid, Bundle params, String text, FileOutputStream fileOutputStream) {
super(callerIdentity, callerUid, callerPid, params, text);
mFileDescriptor = fileDescriptor;
mFileOutputStream = fileOutputStream;
}
@Override
protected AbstractSynthesisCallback createSynthesisCallback() {
FileOutputStream fileOutputStream = new FileOutputStream(mFileDescriptor);
return new FileSynthesisCallback(fileOutputStream.getChannel());
return new FileSynthesisCallback(mFileOutputStream.getChannel());
}
@Override
@@ -680,6 +680,11 @@ public abstract class TextToSpeechService extends Service {
} else {
dispatchOnError();
}
try {
mFileOutputStream.close();
} catch(IOException e) {
Log.w(TAG, "Failed to close output file", e);
}
return status;
}
}
@@ -805,9 +810,9 @@ public abstract class TextToSpeechService extends Service {
return TextToSpeech.ERROR;
}
SpeechItem item = new SynthesisToFileSpeechDescriptorItem(caller, Binder.getCallingUid(),
Binder.getCallingPid(), params, text,
fileDescriptor.getFileDescriptor());
SpeechItem item = new SynthesisToFileOutputStreamSpeechItem(caller,
Binder.getCallingUid(), Binder.getCallingPid(), params, text,
new ParcelFileDescriptor.AutoCloseOutputStream(fileDescriptor));
return mSynthHandler.enqueueSpeechItem(TextToSpeech.QUEUE_ADD, item);
}