Merge change 8073 into donut
* changes: Reset the speech synth singleton to null when the service is destroyed so it can be recreated when the service is initialized. In the interface with the native synthesizer library, close the lib in the finalizer, delete the global ref to the SynthProxy java object.
This commit is contained in:
@@ -65,9 +65,9 @@ static Mutex engineMutex;
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
class SynthProxyJniStorage {
|
class SynthProxyJniStorage {
|
||||||
public :
|
public :
|
||||||
//jclass tts_class;
|
|
||||||
jobject tts_ref;
|
jobject tts_ref;
|
||||||
TtsEngine* mNativeSynthInterface;
|
TtsEngine* mNativeSynthInterface;
|
||||||
|
void* mEngineLibHandle;
|
||||||
AudioTrack* mAudioOut;
|
AudioTrack* mAudioOut;
|
||||||
AudioSystem::stream_type mStreamType;
|
AudioSystem::stream_type mStreamType;
|
||||||
uint32_t mSampleRate;
|
uint32_t mSampleRate;
|
||||||
@@ -77,9 +77,9 @@ class SynthProxyJniStorage {
|
|||||||
size_t mBufferSize;
|
size_t mBufferSize;
|
||||||
|
|
||||||
SynthProxyJniStorage() {
|
SynthProxyJniStorage() {
|
||||||
//tts_class = NULL;
|
|
||||||
tts_ref = NULL;
|
tts_ref = NULL;
|
||||||
mNativeSynthInterface = NULL;
|
mNativeSynthInterface = NULL;
|
||||||
|
mEngineLibHandle = NULL;
|
||||||
mAudioOut = NULL;
|
mAudioOut = NULL;
|
||||||
mStreamType = DEFAULT_TTS_STREAM_TYPE;
|
mStreamType = DEFAULT_TTS_STREAM_TYPE;
|
||||||
mSampleRate = DEFAULT_TTS_RATE;
|
mSampleRate = DEFAULT_TTS_RATE;
|
||||||
@@ -91,11 +91,17 @@ class SynthProxyJniStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
~SynthProxyJniStorage() {
|
~SynthProxyJniStorage() {
|
||||||
|
//LOGV("entering ~SynthProxyJniStorage()");
|
||||||
killAudio();
|
killAudio();
|
||||||
if (mNativeSynthInterface) {
|
if (mNativeSynthInterface) {
|
||||||
mNativeSynthInterface->shutdown();
|
mNativeSynthInterface->shutdown();
|
||||||
mNativeSynthInterface = NULL;
|
mNativeSynthInterface = NULL;
|
||||||
}
|
}
|
||||||
|
if (mEngineLibHandle) {
|
||||||
|
//LOGE("~SynthProxyJniStorage(): before close library");
|
||||||
|
int res = dlclose(mEngineLibHandle);
|
||||||
|
LOGE_IF( res != 0, "~SynthProxyJniStorage(): dlclose returned %d", res);
|
||||||
|
}
|
||||||
delete mBuffer;
|
delete mBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,13 +144,13 @@ class SynthProxyJniStorage {
|
|||||||
0, 0, 0, 0); // not using an AudioTrack callback
|
0, 0, 0, 0); // not using an AudioTrack callback
|
||||||
|
|
||||||
if (mAudioOut->initCheck() != NO_ERROR) {
|
if (mAudioOut->initCheck() != NO_ERROR) {
|
||||||
LOGI("AudioTrack error");
|
LOGE("createAudioOut(): AudioTrack error");
|
||||||
delete mAudioOut;
|
delete mAudioOut;
|
||||||
mAudioOut = NULL;
|
mAudioOut = NULL;
|
||||||
} else {
|
} else {
|
||||||
//LOGI("AudioTrack OK");
|
//LOGI("AudioTrack OK");
|
||||||
mAudioOut->start();
|
mAudioOut->start();
|
||||||
LOGI("AudioTrack started");
|
LOGV("AudioTrack started");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -259,16 +265,18 @@ android_tts_SynthProxy_native_setup(JNIEnv *env, jobject thiz,
|
|||||||
|
|
||||||
void *engine_lib_handle = dlopen(nativeSoLibNativeString,
|
void *engine_lib_handle = dlopen(nativeSoLibNativeString,
|
||||||
RTLD_NOW | RTLD_LOCAL);
|
RTLD_NOW | RTLD_LOCAL);
|
||||||
if (engine_lib_handle==NULL) {
|
if (engine_lib_handle == NULL) {
|
||||||
LOGI("engine_lib_handle==NULL");
|
LOGE("android_tts_SynthProxy_native_setup(): engine_lib_handle == NULL");
|
||||||
// TODO report error so the TTS can't be used
|
// TODO report error so the TTS can't be used
|
||||||
} else {
|
} else {
|
||||||
TtsEngine *(*get_TtsEngine)() =
|
TtsEngine *(*get_TtsEngine)() =
|
||||||
reinterpret_cast<TtsEngine* (*)()>(dlsym(engine_lib_handle, "getTtsEngine"));
|
reinterpret_cast<TtsEngine* (*)()>(dlsym(engine_lib_handle, "getTtsEngine"));
|
||||||
|
|
||||||
pJniStorage->mNativeSynthInterface = (*get_TtsEngine)();
|
pJniStorage->mNativeSynthInterface = (*get_TtsEngine)();
|
||||||
|
pJniStorage->mEngineLibHandle = engine_lib_handle;
|
||||||
|
|
||||||
if (pJniStorage->mNativeSynthInterface) {
|
if (pJniStorage->mNativeSynthInterface) {
|
||||||
|
Mutex::Autolock l(engineMutex);
|
||||||
pJniStorage->mNativeSynthInterface->init(ttsSynthDoneCB);
|
pJniStorage->mNativeSynthInterface->init(ttsSynthDoneCB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -287,11 +295,29 @@ android_tts_SynthProxy_native_setup(JNIEnv *env, jobject thiz,
|
|||||||
static void
|
static void
|
||||||
android_tts_SynthProxy_native_finalize(JNIEnv *env, jobject thiz, jint jniData)
|
android_tts_SynthProxy_native_finalize(JNIEnv *env, jobject thiz, jint jniData)
|
||||||
{
|
{
|
||||||
if (jniData) {
|
//LOGV("entering android_tts_SynthProxy_finalize()");
|
||||||
SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
|
if (jniData == 0) {
|
||||||
env->DeleteGlobalRef(pSynthData->tts_ref);
|
//LOGE("android_tts_SynthProxy_native_finalize(): invalid JNI data");
|
||||||
delete pSynthData;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Mutex::Autolock l(engineMutex);
|
||||||
|
|
||||||
|
SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
|
||||||
|
env->DeleteGlobalRef(pSynthData->tts_ref);
|
||||||
|
delete pSynthData;
|
||||||
|
|
||||||
|
env->SetIntField(thiz, javaTTSFields.synthProxyFieldJniData, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
android_tts_SynthProxy_shutdown(JNIEnv *env, jobject thiz, jint jniData)
|
||||||
|
{
|
||||||
|
//LOGV("entering android_tts_SynthProxy_shutdown()");
|
||||||
|
|
||||||
|
// do everything a call to finalize would
|
||||||
|
android_tts_SynthProxy_native_finalize(env, thiz, jniData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -604,24 +630,6 @@ android_tts_SynthProxy_stop(JNIEnv *env, jobject thiz, jint jniData)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
android_tts_SynthProxy_shutdown(JNIEnv *env, jobject thiz, jint jniData)
|
|
||||||
{
|
|
||||||
if (jniData == 0) {
|
|
||||||
LOGE("android_tts_SynthProxy_shutdown(): invalid JNI data");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mutex::Autolock l(engineMutex);
|
|
||||||
|
|
||||||
SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
|
|
||||||
if (pSynthData->mNativeSynthInterface) {
|
|
||||||
pSynthData->mNativeSynthInterface->shutdown();
|
|
||||||
pSynthData->mNativeSynthInterface = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static jobjectArray
|
static jobjectArray
|
||||||
android_tts_SynthProxy_getLanguage(JNIEnv *env, jobject thiz, jint jniData)
|
android_tts_SynthProxy_getLanguage(JNIEnv *env, jobject thiz, jint jniData)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ public class TtsService extends Service implements OnCompletionListener {
|
|||||||
cleanUpPlayer();
|
cleanUpPlayer();
|
||||||
|
|
||||||
sNativeSynth.shutdown();
|
sNativeSynth.shutdown();
|
||||||
|
sNativeSynth = null;
|
||||||
|
|
||||||
// Unregister all callbacks.
|
// Unregister all callbacks.
|
||||||
mCallbacks.kill();
|
mCallbacks.kill();
|
||||||
|
|||||||
Reference in New Issue
Block a user