summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2011-11-29 17:02:06 +0000
committerNarayan Kamath <narayan@google.com>2011-11-30 10:42:03 +0000
commit492b7f0d51f53164aa6eb974cd7ab6a7889af677 (patch)
tree18f697ad229f9a1d9327cce34c1aa76ff78de17f
parent9a8246c8d1ea324b6704bf4fe0b77ade1c2f3639 (diff)
downloadframeworks_base-492b7f0d51f53164aa6eb974cd7ab6a7889af677.zip
frameworks_base-492b7f0d51f53164aa6eb974cd7ab6a7889af677.tar.gz
frameworks_base-492b7f0d51f53164aa6eb974cd7ab6a7889af677.tar.bz2
Allow multiple TextToSpeech instances per calling app.
We now use an IBinder object as an identity token of the caller instead of Context#getPackageName. bug:5680696 Change-Id: I1ca29e7161f709d2a85218206f3f117dfa620282
-rw-r--r--core/java/android/speech/tts/AudioMessageParams.java4
-rw-r--r--core/java/android/speech/tts/AudioPlaybackHandler.java14
-rw-r--r--core/java/android/speech/tts/EventLogTags.logtags4
-rw-r--r--core/java/android/speech/tts/EventLogger.java13
-rw-r--r--core/java/android/speech/tts/ITextToSpeechService.aidl32
-rw-r--r--core/java/android/speech/tts/MessageParams.java10
-rw-r--r--core/java/android/speech/tts/PlaybackSynthesisCallback.java8
-rw-r--r--core/java/android/speech/tts/SilenceMessageParams.java4
-rw-r--r--core/java/android/speech/tts/SynthesisMessageParams.java4
-rwxr-xr-xcore/java/android/speech/tts/TextToSpeech.java30
-rw-r--r--core/java/android/speech/tts/TextToSpeechService.java175
11 files changed, 167 insertions, 131 deletions
diff --git a/core/java/android/speech/tts/AudioMessageParams.java b/core/java/android/speech/tts/AudioMessageParams.java
index 29b4367..a2248a2 100644
--- a/core/java/android/speech/tts/AudioMessageParams.java
+++ b/core/java/android/speech/tts/AudioMessageParams.java
@@ -21,8 +21,8 @@ class AudioMessageParams extends MessageParams {
private final BlockingMediaPlayer mPlayer;
AudioMessageParams(UtteranceProgressDispatcher dispatcher,
- String callingApp, BlockingMediaPlayer player) {
- super(dispatcher, callingApp);
+ Object callerIdentity, BlockingMediaPlayer player) {
+ super(dispatcher, callerIdentity);
mPlayer = player;
}
diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java
index fd00dce..d452b8e 100644
--- a/core/java/android/speech/tts/AudioPlaybackHandler.java
+++ b/core/java/android/speech/tts/AudioPlaybackHandler.java
@@ -110,19 +110,19 @@ class AudioPlaybackHandler {
// synchronization).
// -----------------------------------------------------
- synchronized public void removePlaybackItems(String callingApp) {
- if (DBG_THREADING) Log.d(TAG, "Removing all callback items for : " + callingApp);
- removeMessages(callingApp);
+ synchronized public void removePlaybackItems(Object callerIdentity) {
+ if (DBG_THREADING) Log.d(TAG, "Removing all callback items for : " + callerIdentity);
+ removeMessages(callerIdentity);
final MessageParams current = getCurrentParams();
- if (current != null && TextUtils.equals(callingApp, current.getCallingApp())) {
+ if (current != null && (current.getCallerIdentity() == callerIdentity)) {
stop(current);
}
final MessageParams lastSynthesis = mLastSynthesisRequest;
if (lastSynthesis != null && lastSynthesis != current &&
- TextUtils.equals(callingApp, lastSynthesis.getCallingApp())) {
+ (lastSynthesis.getCallerIdentity() == callerIdentity)) {
stop(lastSynthesis);
}
}
@@ -232,7 +232,7 @@ class AudioPlaybackHandler {
/*
* Remove all messages that originate from a given calling app.
*/
- synchronized private void removeMessages(String callingApp) {
+ synchronized private void removeMessages(Object callerIdentity) {
Iterator<ListEntry> it = mQueue.iterator();
while (it.hasNext()) {
@@ -240,7 +240,7 @@ class AudioPlaybackHandler {
// The null check is to prevent us from removing control messages,
// such as a shutdown message.
if (current.mMessage != null &&
- callingApp.equals(current.mMessage.getCallingApp())) {
+ current.mMessage.getCallerIdentity() == callerIdentity) {
it.remove();
}
}
diff --git a/core/java/android/speech/tts/EventLogTags.logtags b/core/java/android/speech/tts/EventLogTags.logtags
index 1a9f5fe..f8654ad 100644
--- a/core/java/android/speech/tts/EventLogTags.logtags
+++ b/core/java/android/speech/tts/EventLogTags.logtags
@@ -2,5 +2,5 @@
option java_package android.speech.tts;
-76001 tts_speak_success (engine|3),(caller|3),(length|1),(locale|3),(rate|1),(pitch|1),(engine_latency|2|3),(engine_total|2|3),(audio_latency|2|3)
-76002 tts_speak_failure (engine|3),(caller|3),(length|1),(locale|3),(rate|1),(pitch|1)
+76001 tts_speak_success (engine|3),(caller_uid|1),(caller_pid|1),(length|1),(locale|3),(rate|1),(pitch|1),(engine_latency|2|3),(engine_total|2|3),(audio_latency|2|3)
+76002 tts_speak_failure (engine|3),(caller_uid|1),(caller_pid|1),(length|1),(locale|3),(rate|1),(pitch|1)
diff --git a/core/java/android/speech/tts/EventLogger.java b/core/java/android/speech/tts/EventLogger.java
index 63b954b..3c93e18 100644
--- a/core/java/android/speech/tts/EventLogger.java
+++ b/core/java/android/speech/tts/EventLogger.java
@@ -30,8 +30,9 @@ import android.text.TextUtils;
*/
class EventLogger {
private final SynthesisRequest mRequest;
- private final String mCallingApp;
private final String mServiceApp;
+ private final int mCallerUid;
+ private final int mCallerPid;
private final long mReceivedTime;
private long mPlaybackStartTime = -1;
private volatile long mRequestProcessingStartTime = -1;
@@ -42,10 +43,10 @@ class EventLogger {
private volatile boolean mStopped = false;
private boolean mLogWritten = false;
- EventLogger(SynthesisRequest request, String callingApp,
- String serviceApp) {
+ EventLogger(SynthesisRequest request, int callerUid, int callerPid, String serviceApp) {
mRequest = request;
- mCallingApp = callingApp;
+ mCallerUid = callerUid;
+ mCallerPid = callerPid;
mServiceApp = serviceApp;
mReceivedTime = SystemClock.elapsedRealtime();
}
@@ -122,7 +123,7 @@ class EventLogger {
// onPlaybackStart() should normally always be called if an
// error does not occur.
if (mError || mPlaybackStartTime == -1 || mEngineCompleteTime == -1) {
- EventLogTags.writeTtsSpeakFailure(mServiceApp, mCallingApp,
+ EventLogTags.writeTtsSpeakFailure(mServiceApp, mCallerUid, mCallerPid,
getUtteranceLength(), getLocaleString(),
mRequest.getSpeechRate(), mRequest.getPitch());
return;
@@ -138,7 +139,7 @@ class EventLogger {
final long audioLatency = mPlaybackStartTime - mReceivedTime;
final long engineLatency = mEngineStartTime - mRequestProcessingStartTime;
final long engineTotal = mEngineCompleteTime - mRequestProcessingStartTime;
- EventLogTags.writeTtsSpeakSuccess(mServiceApp, mCallingApp,
+ EventLogTags.writeTtsSpeakSuccess(mServiceApp, mCallerUid, mCallerPid,
getUtteranceLength(), getLocaleString(),
mRequest.getSpeechRate(), mRequest.getPitch(),
engineLatency, engineTotal, audioLatency);
diff --git a/core/java/android/speech/tts/ITextToSpeechService.aidl b/core/java/android/speech/tts/ITextToSpeechService.aidl
index 1a8c1fb..ab63187 100644
--- a/core/java/android/speech/tts/ITextToSpeechService.aidl
+++ b/core/java/android/speech/tts/ITextToSpeechService.aidl
@@ -30,47 +30,47 @@ interface ITextToSpeechService {
/**
* Tells the engine to synthesize some speech and play it back.
*
- * @param callingApp The package name of the calling app. Used to connect requests
- * callbacks and to clear requests when the calling app is stopping.
+ * @param callingInstance a binder representing the identity of the calling
+ * TextToSpeech object.
* @param text The text to synthesize.
* @param queueMode Determines what to do to requests already in the queue.
* @param param Request parameters.
*/
- int speak(in String callingApp, in String text, in int queueMode, in Bundle params);
+ int speak(in IBinder callingInstance, in String text, in int queueMode, in Bundle params);
/**
* Tells the engine to synthesize some speech and write it to a file.
*
- * @param callingApp The package name of the calling app. Used to connect requests
- * callbacks and to clear requests when the calling app is stopping.
+ * @param callingInstance a binder representing the identity of the calling
+ * TextToSpeech object.
* @param text The text to synthesize.
* @param filename The file to write the synthesized audio to.
* @param param Request parameters.
*/
- int synthesizeToFile(in String callingApp, in String text,
+ int synthesizeToFile(in IBinder callingInstance, in String text,
in String filename, in Bundle params);
/**
* Plays an existing audio resource.
*
- * @param callingApp The package name of the calling app. Used to connect requests
- * callbacks and to clear requests when the calling app is stopping.
+ * @param callingInstance a binder representing the identity of the calling
+ * TextToSpeech object.
* @param audioUri URI for the audio resource (a file or android.resource URI)
* @param queueMode Determines what to do to requests already in the queue.
* @param param Request parameters.
*/
- int playAudio(in String callingApp, in Uri audioUri, in int queueMode, in Bundle params);
+ int playAudio(in IBinder callingInstance, in Uri audioUri, in int queueMode, in Bundle params);
/**
* Plays silence.
*
- * @param callingApp The package name of the calling app. Used to connect requests
- * callbacks and to clear requests when the calling app is stopping.
+ * @param callingInstance a binder representing the identity of the calling
+ * TextToSpeech object.
* @param duration Number of milliseconds of silence to play.
* @param queueMode Determines what to do to requests already in the queue.
* @param param Request parameters.
*/
- int playSilence(in String callingApp, in long duration, in int queueMode, in Bundle params);
+ int playSilence(in IBinder callingInstance, in long duration, in int queueMode, in Bundle params);
/**
* Checks whether the service is currently playing some audio.
@@ -81,10 +81,10 @@ interface ITextToSpeechService {
* Interrupts the current utterance (if from the given app) and removes any utterances
* in the queue that are from the given app.
*
- * @param callingApp Package name of the app whose utterances
- * should be interrupted and cleared.
+ * @param callingInstance a binder representing the identity of the calling
+ * TextToSpeech object.
*/
- int stop(in String callingApp);
+ int stop(in IBinder callingInstance);
/**
* Returns the language, country and variant currently being used by the TTS engine.
@@ -150,6 +150,6 @@ interface ITextToSpeechService {
* @param callingApp Package name for the app whose utterance the callback will handle.
* @param cb The callback.
*/
- void setCallback(in String callingApp, ITextToSpeechCallback cb);
+ void setCallback(in IBinder caller, ITextToSpeechCallback cb);
}
diff --git a/core/java/android/speech/tts/MessageParams.java b/core/java/android/speech/tts/MessageParams.java
index de9cc07..f83b793 100644
--- a/core/java/android/speech/tts/MessageParams.java
+++ b/core/java/android/speech/tts/MessageParams.java
@@ -23,19 +23,19 @@ abstract class MessageParams {
static final int TYPE_SILENCE = 3;
private final UtteranceProgressDispatcher mDispatcher;
- private final String mCallingApp;
+ private final Object mCallerIdentity;
- MessageParams(UtteranceProgressDispatcher dispatcher, String callingApp) {
+ MessageParams(UtteranceProgressDispatcher dispatcher, Object callerIdentity) {
mDispatcher = dispatcher;
- mCallingApp = callingApp;
+ mCallerIdentity = callerIdentity;
}
UtteranceProgressDispatcher getDispatcher() {
return mDispatcher;
}
- String getCallingApp() {
- return mCallingApp;
+ Object getCallerIdentity() {
+ return mCallerIdentity;
}
@Override
diff --git a/core/java/android/speech/tts/PlaybackSynthesisCallback.java b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
index 91a3452..8634506 100644
--- a/core/java/android/speech/tts/PlaybackSynthesisCallback.java
+++ b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
@@ -63,18 +63,18 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
private volatile boolean mDone = false;
private final UtteranceProgressDispatcher mDispatcher;
- private final String mCallingApp;
+ private final Object mCallerIdentity;
private final EventLogger mLogger;
PlaybackSynthesisCallback(int streamType, float volume, float pan,
AudioPlaybackHandler audioTrackHandler, UtteranceProgressDispatcher dispatcher,
- String callingApp, EventLogger logger) {
+ Object callerIdentity, EventLogger logger) {
mStreamType = streamType;
mVolume = volume;
mPan = pan;
mAudioTrackHandler = audioTrackHandler;
mDispatcher = dispatcher;
- mCallingApp = callingApp;
+ mCallerIdentity = callerIdentity;
mLogger = logger;
}
@@ -158,7 +158,7 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
}
SynthesisMessageParams params = new SynthesisMessageParams(
mStreamType, sampleRateInHz, audioFormat, channelCount, mVolume, mPan,
- mDispatcher, mCallingApp, mLogger);
+ mDispatcher, mCallerIdentity, mLogger);
mAudioTrackHandler.enqueueSynthesisStart(params);
mToken = params;
diff --git a/core/java/android/speech/tts/SilenceMessageParams.java b/core/java/android/speech/tts/SilenceMessageParams.java
index 9909126..2431808 100644
--- a/core/java/android/speech/tts/SilenceMessageParams.java
+++ b/core/java/android/speech/tts/SilenceMessageParams.java
@@ -23,8 +23,8 @@ class SilenceMessageParams extends MessageParams {
private final long mSilenceDurationMs;
SilenceMessageParams(UtteranceProgressDispatcher dispatcher,
- String callingApp, long silenceDurationMs) {
- super(dispatcher, callingApp);
+ Object callerIdentity, long silenceDurationMs) {
+ super(dispatcher, callerIdentity);
mSilenceDurationMs = silenceDurationMs;
}
diff --git a/core/java/android/speech/tts/SynthesisMessageParams.java b/core/java/android/speech/tts/SynthesisMessageParams.java
index ed66420..ef73d30 100644
--- a/core/java/android/speech/tts/SynthesisMessageParams.java
+++ b/core/java/android/speech/tts/SynthesisMessageParams.java
@@ -58,8 +58,8 @@ final class SynthesisMessageParams extends MessageParams {
SynthesisMessageParams(int streamType, int sampleRate,
int audioFormat, int channelCount,
float volume, float pan, UtteranceProgressDispatcher dispatcher,
- String callingApp, EventLogger logger) {
- super(dispatcher, callingApp);
+ Object callerIdentity, EventLogger logger) {
+ super(dispatcher, callerIdentity);
mStreamType = streamType;
mSampleRateInHz = sampleRate;
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index a220615..cd065ec 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -547,10 +547,6 @@ public class TextToSpeech {
initTts();
}
- private String getPackageName() {
- return mPackageName;
- }
-
private <R> R runActionNoReconnect(Action<R> action, R errorResult, String method) {
return runAction(action, errorResult, method, false);
}
@@ -630,6 +626,10 @@ public class TextToSpeech {
}
}
+ private IBinder getCallerIdentity() {
+ return mServiceConnection.getCallerIdentity();
+ }
+
/**
* Releases the resources used by the TextToSpeech engine.
* It is good practice for instance to call this method in the onDestroy() method of an Activity
@@ -639,8 +639,8 @@ public class TextToSpeech {
runActionNoReconnect(new Action<Void>() {
@Override
public Void run(ITextToSpeechService service) throws RemoteException {
- service.setCallback(getPackageName(), null);
- service.stop(getPackageName());
+ service.setCallback(getCallerIdentity(), null);
+ service.stop(getCallerIdentity());
mServiceConnection.disconnect();
// Context#unbindService does not result in a call to
// ServiceConnection#onServiceDisconnected. As a result, the
@@ -800,10 +800,10 @@ public class TextToSpeech {
public Integer run(ITextToSpeechService service) throws RemoteException {
Uri utteranceUri = mUtterances.get(text);
if (utteranceUri != null) {
- return service.playAudio(getPackageName(), utteranceUri, queueMode,
+ return service.playAudio(getCallerIdentity(), utteranceUri, queueMode,
getParams(params));
} else {
- return service.speak(getPackageName(), text, queueMode, getParams(params));
+ return service.speak(getCallerIdentity(), text, queueMode, getParams(params));
}
}
}, ERROR, "speak");
@@ -836,7 +836,7 @@ public class TextToSpeech {
if (earconUri == null) {
return ERROR;
}
- return service.playAudio(getPackageName(), earconUri, queueMode,
+ return service.playAudio(getCallerIdentity(), earconUri, queueMode,
getParams(params));
}
}, ERROR, "playEarcon");
@@ -863,7 +863,7 @@ public class TextToSpeech {
return runAction(new Action<Integer>() {
@Override
public Integer run(ITextToSpeechService service) throws RemoteException {
- return service.playSilence(getPackageName(), durationInMs, queueMode,
+ return service.playSilence(getCallerIdentity(), durationInMs, queueMode,
getParams(params));
}
}, ERROR, "playSilence");
@@ -926,7 +926,7 @@ public class TextToSpeech {
return runAction(new Action<Integer>() {
@Override
public Integer run(ITextToSpeechService service) throws RemoteException {
- return service.stop(getPackageName());
+ return service.stop(getCallerIdentity());
}
}, ERROR, "stop");
}
@@ -1091,7 +1091,7 @@ public class TextToSpeech {
return runAction(new Action<Integer>() {
@Override
public Integer run(ITextToSpeechService service) throws RemoteException {
- return service.synthesizeToFile(getPackageName(), text, filename,
+ return service.synthesizeToFile(getCallerIdentity(), text, filename,
getParams(params));
}
}, ERROR, "synthesizeToFile");
@@ -1275,7 +1275,7 @@ public class TextToSpeech {
mServiceConnection = this;
mService = ITextToSpeechService.Stub.asInterface(service);
try {
- mService.setCallback(getPackageName(), mCallback);
+ mService.setCallback(getCallerIdentity(), mCallback);
dispatchOnInit(SUCCESS);
} catch (RemoteException re) {
Log.e(TAG, "Error connecting to service, setCallback() failed");
@@ -1284,6 +1284,10 @@ public class TextToSpeech {
}
}
+ public IBinder getCallerIdentity() {
+ return mCallback;
+ }
+
public void onServiceDisconnected(ComponentName name) {
synchronized(mStartLock) {
mService = null;
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index aee678a..2f62d39 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -18,6 +18,7 @@ package android.speech.tts;
import android.app.Service;
import android.content.Intent;
import android.net.Uri;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
@@ -272,9 +273,9 @@ public abstract class TextToSpeechService extends Service {
return old;
}
- private synchronized SpeechItem maybeRemoveCurrentSpeechItem(String callingApp) {
+ private synchronized SpeechItem maybeRemoveCurrentSpeechItem(Object callerIdentity) {
if (mCurrentSpeechItem != null &&
- TextUtils.equals(mCurrentSpeechItem.getCallingApp(), callingApp)) {
+ mCurrentSpeechItem.getCallerIdentity() == callerIdentity) {
SpeechItem current = mCurrentSpeechItem;
mCurrentSpeechItem = null;
return current;
@@ -311,7 +312,7 @@ public abstract class TextToSpeechService extends Service {
}
if (queueMode == TextToSpeech.QUEUE_FLUSH) {
- stopForApp(speechItem.getCallingApp());
+ stopForApp(speechItem.getCallerIdentity());
} else if (queueMode == TextToSpeech.QUEUE_DESTROY) {
stopAll();
}
@@ -328,7 +329,7 @@ public abstract class TextToSpeechService extends Service {
// stopForApp(String).
//
// Note that this string is interned, so the == comparison works.
- msg.obj = speechItem.getCallingApp();
+ msg.obj = speechItem.getCallerIdentity();
if (sendMessage(msg)) {
return TextToSpeech.SUCCESS;
} else {
@@ -344,12 +345,12 @@ public abstract class TextToSpeechService extends Service {
*
* Called on a service binder thread.
*/
- public int stopForApp(String callingApp) {
- if (TextUtils.isEmpty(callingApp)) {
+ public int stopForApp(Object callerIdentity) {
+ if (callerIdentity == null) {
return TextToSpeech.ERROR;
}
- removeCallbacksAndMessages(callingApp);
+ removeCallbacksAndMessages(callerIdentity);
// This stops writing data to the file / or publishing
// items to the audio playback handler.
//
@@ -357,13 +358,13 @@ public abstract class TextToSpeechService extends Service {
// belongs to the callingApp, else the item will be "orphaned" and
// not stopped correctly if a stop request comes along for the item
// from the app it belongs to.
- SpeechItem current = maybeRemoveCurrentSpeechItem(callingApp);
+ SpeechItem current = maybeRemoveCurrentSpeechItem(callerIdentity);
if (current != null) {
current.stop();
}
// Remove any enqueued audio too.
- mAudioPlaybackHandler.removePlaybackItems(callingApp);
+ mAudioPlaybackHandler.removePlaybackItems(callerIdentity);
return TextToSpeech.SUCCESS;
}
@@ -393,18 +394,22 @@ public abstract class TextToSpeechService extends Service {
* An item in the synth thread queue.
*/
private abstract class SpeechItem implements UtteranceProgressDispatcher {
- private final String mCallingApp;
+ private final Object mCallerIdentity;
protected final Bundle mParams;
+ private final int mCallerUid;
+ private final int mCallerPid;
private boolean mStarted = false;
private boolean mStopped = false;
- public SpeechItem(String callingApp, Bundle params) {
- mCallingApp = callingApp;
+ public SpeechItem(Object caller, int callerUid, int callerPid, Bundle params) {
+ mCallerIdentity = caller;
mParams = params;
+ mCallerUid = callerUid;
+ mCallerPid = callerPid;
}
- public String getCallingApp() {
- return mCallingApp;
+ public Object getCallerIdentity() {
+ return mCallerIdentity;
}
/**
@@ -451,7 +456,7 @@ public abstract class TextToSpeechService extends Service {
public void dispatchOnDone() {
final String utteranceId = getUtteranceId();
if (utteranceId != null) {
- mCallbacks.dispatchOnDone(getCallingApp(), utteranceId);
+ mCallbacks.dispatchOnDone(getCallerIdentity(), utteranceId);
}
}
@@ -459,7 +464,7 @@ public abstract class TextToSpeechService extends Service {
public void dispatchOnStart() {
final String utteranceId = getUtteranceId();
if (utteranceId != null) {
- mCallbacks.dispatchOnStart(getCallingApp(), utteranceId);
+ mCallbacks.dispatchOnStart(getCallerIdentity(), utteranceId);
}
}
@@ -467,10 +472,18 @@ public abstract class TextToSpeechService extends Service {
public void dispatchOnError() {
final String utteranceId = getUtteranceId();
if (utteranceId != null) {
- mCallbacks.dispatchOnError(getCallingApp(), utteranceId);
+ mCallbacks.dispatchOnError(getCallerIdentity(), utteranceId);
}
}
+ public int getCallerUid() {
+ return mCallerUid;
+ }
+
+ public int getCallerPid() {
+ return mCallerPid;
+ }
+
protected synchronized boolean isStopped() {
return mStopped;
}
@@ -518,13 +531,15 @@ public abstract class TextToSpeechService extends Service {
private AbstractSynthesisCallback mSynthesisCallback;
private final EventLogger mEventLogger;
- public SynthesisSpeechItem(String callingApp, Bundle params, String text) {
- super(callingApp, params);
+ public SynthesisSpeechItem(Object callerIdentity, int callerUid, int callerPid,
+ Bundle params, String text) {
+ super(callerIdentity, callerUid, callerPid, params);
mText = text;
mSynthesisRequest = new SynthesisRequest(mText, mParams);
mDefaultLocale = getSettingsLocale();
setRequestParams(mSynthesisRequest);
- mEventLogger = new EventLogger(mSynthesisRequest, getCallingApp(), mPackageName);
+ mEventLogger = new EventLogger(mSynthesisRequest, callerUid, callerPid,
+ mPackageName);
}
public String getText() {
@@ -563,7 +578,7 @@ public abstract class TextToSpeechService extends Service {
protected AbstractSynthesisCallback createSynthesisCallback() {
return new PlaybackSynthesisCallback(getStreamType(), getVolume(), getPan(),
- mAudioPlaybackHandler, this, getCallingApp(), mEventLogger);
+ mAudioPlaybackHandler, this, getCallerIdentity(), mEventLogger);
}
private void setRequestParams(SynthesisRequest request) {
@@ -618,9 +633,10 @@ public abstract class TextToSpeechService extends Service {
private class SynthesisToFileSpeechItem extends SynthesisSpeechItem {
private final File mFile;
- public SynthesisToFileSpeechItem(String callingApp, Bundle params, String text,
+ public SynthesisToFileSpeechItem(Object callerIdentity, int callerUid, int callerPid,
+ Bundle params, String text,
File file) {
- super(callingApp, params, text);
+ super(callerIdentity, callerUid, callerPid, params, text);
mFile = file;
}
@@ -682,8 +698,9 @@ public abstract class TextToSpeechService extends Service {
private final BlockingMediaPlayer mPlayer;
private AudioMessageParams mToken;
- public AudioSpeechItem(String callingApp, Bundle params, Uri uri) {
- super(callingApp, params);
+ public AudioSpeechItem(Object callerIdentity, int callerUid, int callerPid,
+ Bundle params, Uri uri) {
+ super(callerIdentity, callerUid, callerPid, params);
mPlayer = new BlockingMediaPlayer(TextToSpeechService.this, uri, getStreamType());
}
@@ -694,7 +711,7 @@ public abstract class TextToSpeechService extends Service {
@Override
protected int playImpl() {
- mToken = new AudioMessageParams(this, getCallingApp(), mPlayer);
+ mToken = new AudioMessageParams(this, getCallerIdentity(), mPlayer);
mAudioPlaybackHandler.enqueueAudio(mToken);
return TextToSpeech.SUCCESS;
}
@@ -709,8 +726,9 @@ public abstract class TextToSpeechService extends Service {
private final long mDuration;
private SilenceMessageParams mToken;
- public SilenceSpeechItem(String callingApp, Bundle params, long duration) {
- super(callingApp, params);
+ public SilenceSpeechItem(Object callerIdentity, int callerUid, int callerPid,
+ Bundle params, long duration) {
+ super(callerIdentity, callerUid, callerPid, params);
mDuration = duration;
}
@@ -721,7 +739,7 @@ public abstract class TextToSpeechService extends Service {
@Override
protected int playImpl() {
- mToken = new SilenceMessageParams(this, getCallingApp(), mDuration);
+ mToken = new SilenceMessageParams(this, getCallerIdentity(), mDuration);
mAudioPlaybackHandler.enqueueSilence(mToken);
return TextToSpeech.SUCCESS;
}
@@ -747,58 +765,67 @@ public abstract class TextToSpeechService extends Service {
// NOTE: All calls that are passed in a calling app are interned so that
// they can be used as message objects (which are tested for equality using ==).
private final ITextToSpeechService.Stub mBinder = new ITextToSpeechService.Stub() {
-
- public int speak(String callingApp, String text, int queueMode, Bundle params) {
- if (!checkNonNull(callingApp, text, params)) {
+ @Override
+ public int speak(IBinder caller, String text, int queueMode, Bundle params) {
+ if (!checkNonNull(caller, text, params)) {
return TextToSpeech.ERROR;
}
- SpeechItem item = new SynthesisSpeechItem(intern(callingApp), params, text);
+ SpeechItem item = new SynthesisSpeechItem(caller,
+ Binder.getCallingUid(), Binder.getCallingPid(), params, text);
return mSynthHandler.enqueueSpeechItem(queueMode, item);
}
- public int synthesizeToFile(String callingApp, String text, String filename,
+ @Override
+ public int synthesizeToFile(IBinder caller, String text, String filename,
Bundle params) {
- if (!checkNonNull(callingApp, text, filename, params)) {
+ if (!checkNonNull(caller, text, filename, params)) {
return TextToSpeech.ERROR;
}
File file = new File(filename);
- SpeechItem item = new SynthesisToFileSpeechItem(intern(callingApp),
- params, text, file);
+ SpeechItem item = new SynthesisToFileSpeechItem(caller, Binder.getCallingUid(),
+ Binder.getCallingPid(), params, text, file);
return mSynthHandler.enqueueSpeechItem(TextToSpeech.QUEUE_ADD, item);
}
- public int playAudio(String callingApp, Uri audioUri, int queueMode, Bundle params) {
- if (!checkNonNull(callingApp, audioUri, params)) {
+ @Override
+ public int playAudio(IBinder caller, Uri audioUri, int queueMode, Bundle params) {
+ if (!checkNonNull(caller, audioUri, params)) {
return TextToSpeech.ERROR;
}
- SpeechItem item = new AudioSpeechItem(intern(callingApp), params, audioUri);
+ SpeechItem item = new AudioSpeechItem(caller,
+ Binder.getCallingUid(), Binder.getCallingPid(), params, audioUri);
return mSynthHandler.enqueueSpeechItem(queueMode, item);
}
- public int playSilence(String callingApp, long duration, int queueMode, Bundle params) {
- if (!checkNonNull(callingApp, params)) {
+ @Override
+ public int playSilence(IBinder caller, long duration, int queueMode, Bundle params) {
+ if (!checkNonNull(caller, params)) {
return TextToSpeech.ERROR;
}
- SpeechItem item = new SilenceSpeechItem(intern(callingApp), params, duration);
+ SpeechItem item = new SilenceSpeechItem(caller,
+ Binder.getCallingUid(), Binder.getCallingPid(), params, duration);
return mSynthHandler.enqueueSpeechItem(queueMode, item);
}
+ @Override
public boolean isSpeaking() {
return mSynthHandler.isSpeaking() || mAudioPlaybackHandler.isSpeaking();
}
- public int stop(String callingApp) {
- if (!checkNonNull(callingApp)) {
+ @Override
+ public int stop(IBinder caller) {
+ if (!checkNonNull(caller)) {
return TextToSpeech.ERROR;
}
- return mSynthHandler.stopForApp(intern(callingApp));
+ return mSynthHandler.stopForApp(caller);
}
+ @Override
public String[] getLanguage() {
return onGetLanguage();
}
@@ -807,6 +834,7 @@ public abstract class TextToSpeechService extends Service {
* If defaults are enforced, then no language is "available" except
* perhaps the default language selected by the user.
*/
+ @Override
public int isLanguageAvailable(String lang, String country, String variant) {
if (!checkNonNull(lang)) {
return TextToSpeech.ERROR;
@@ -815,6 +843,7 @@ public abstract class TextToSpeechService extends Service {
return onIsLanguageAvailable(lang, country, variant);
}
+ @Override
public String[] getFeaturesForLanguage(String lang, String country, String variant) {
Set<String> features = onGetFeaturesForLanguage(lang, country, variant);
String[] featuresArray = null;
@@ -831,6 +860,7 @@ public abstract class TextToSpeechService extends Service {
* There is no point loading a non default language if defaults
* are enforced.
*/
+ @Override
public int loadLanguage(String lang, String country, String variant) {
if (!checkNonNull(lang)) {
return TextToSpeech.ERROR;
@@ -839,13 +869,14 @@ public abstract class TextToSpeechService extends Service {
return onLoadLanguage(lang, country, variant);
}
- public void setCallback(String packageName, ITextToSpeechCallback cb) {
+ @Override
+ public void setCallback(IBinder caller, ITextToSpeechCallback cb) {
// Note that passing in a null callback is a valid use case.
- if (!checkNonNull(packageName)) {
+ if (!checkNonNull(caller)) {
return;
}
- mCallbacks.setCallback(packageName, cb);
+ mCallbacks.setCallback(caller, cb);
}
private String intern(String in) {
@@ -862,18 +893,17 @@ public abstract class TextToSpeechService extends Service {
};
private class CallbackMap extends RemoteCallbackList<ITextToSpeechCallback> {
+ private final HashMap<IBinder, ITextToSpeechCallback> mCallerToCallback
+ = new HashMap<IBinder, ITextToSpeechCallback>();
- private final HashMap<String, ITextToSpeechCallback> mAppToCallback
- = new HashMap<String, ITextToSpeechCallback>();
-
- public void setCallback(String packageName, ITextToSpeechCallback cb) {
- synchronized (mAppToCallback) {
+ public void setCallback(IBinder caller, ITextToSpeechCallback cb) {
+ synchronized (mCallerToCallback) {
ITextToSpeechCallback old;
if (cb != null) {
- register(cb, packageName);
- old = mAppToCallback.put(packageName, cb);
+ register(cb, caller);
+ old = mCallerToCallback.put(caller, cb);
} else {
- old = mAppToCallback.remove(packageName);
+ old = mCallerToCallback.remove(caller);
}
if (old != null && old != cb) {
unregister(old);
@@ -881,8 +911,8 @@ public abstract class TextToSpeechService extends Service {
}
}
- public void dispatchOnDone(String packageName, String utteranceId) {
- ITextToSpeechCallback cb = getCallbackFor(packageName);
+ public void dispatchOnDone(Object callerIdentity, String utteranceId) {
+ ITextToSpeechCallback cb = getCallbackFor(callerIdentity);
if (cb == null) return;
try {
cb.onDone(utteranceId);
@@ -891,8 +921,8 @@ public abstract class TextToSpeechService extends Service {
}
}
- public void dispatchOnStart(String packageName, String utteranceId) {
- ITextToSpeechCallback cb = getCallbackFor(packageName);
+ public void dispatchOnStart(Object callerIdentity, String utteranceId) {
+ ITextToSpeechCallback cb = getCallbackFor(callerIdentity);
if (cb == null) return;
try {
cb.onStart(utteranceId);
@@ -902,8 +932,8 @@ public abstract class TextToSpeechService extends Service {
}
- public void dispatchOnError(String packageName, String utteranceId) {
- ITextToSpeechCallback cb = getCallbackFor(packageName);
+ public void dispatchOnError(Object callerIdentity, String utteranceId) {
+ ITextToSpeechCallback cb = getCallbackFor(callerIdentity);
if (cb == null) return;
try {
cb.onError(utteranceId);
@@ -914,25 +944,26 @@ public abstract class TextToSpeechService extends Service {
@Override
public void onCallbackDied(ITextToSpeechCallback callback, Object cookie) {
- String packageName = (String) cookie;
- synchronized (mAppToCallback) {
- mAppToCallback.remove(packageName);
+ IBinder caller = (IBinder) cookie;
+ synchronized (mCallerToCallback) {
+ mCallerToCallback.remove(caller);
}
- mSynthHandler.stopForApp(packageName);
+ mSynthHandler.stopForApp(caller);
}
@Override
public void kill() {
- synchronized (mAppToCallback) {
- mAppToCallback.clear();
+ synchronized (mCallerToCallback) {
+ mCallerToCallback.clear();
super.kill();
}
}
- private ITextToSpeechCallback getCallbackFor(String packageName) {
+ private ITextToSpeechCallback getCallbackFor(Object caller) {
ITextToSpeechCallback cb;
- synchronized (mAppToCallback) {
- cb = mAppToCallback.get(packageName);
+ IBinder asBinder = (IBinder) caller;
+ synchronized (mCallerToCallback) {
+ cb = mCallerToCallback.get(asBinder);
}
return cb;