• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 package android.speech.tts;
17 
18 import android.os.SystemClock;
19 
20 /**
21  * Base class for storing data about a given speech synthesis request to the
22  * event logs. The data that is logged depends on actual implementation. Note
23  * that {@link AbstractEventLogger#onAudioDataWritten()} and
24  * {@link AbstractEventLogger#onEngineComplete()} must be called from a single
25  * thread (usually the audio playback thread}.
26  */
27 abstract class AbstractEventLogger {
28     protected final String mServiceApp;
29     protected final int mCallerUid;
30     protected final int mCallerPid;
31     protected final long mReceivedTime;
32     protected long mPlaybackStartTime = -1;
33 
34     private volatile long mRequestProcessingStartTime = -1;
35     private volatile long mEngineStartTime = -1;
36     private volatile long mEngineCompleteTime = -1;
37 
38     private boolean mLogWritten = false;
39 
AbstractEventLogger(int callerUid, int callerPid, String serviceApp)40     AbstractEventLogger(int callerUid, int callerPid, String serviceApp) {
41         mCallerUid = callerUid;
42         mCallerPid = callerPid;
43         mServiceApp = serviceApp;
44         mReceivedTime = SystemClock.elapsedRealtime();
45     }
46 
47     /**
48      * Notifies the logger that this request has been selected from
49      * the processing queue for processing. Engine latency / total time
50      * is measured from this baseline.
51      */
onRequestProcessingStart()52     public void onRequestProcessingStart() {
53         mRequestProcessingStartTime = SystemClock.elapsedRealtime();
54     }
55 
56     /**
57      * Notifies the logger that a chunk of data has been received from
58      * the engine. Might be called multiple times.
59      */
onEngineDataReceived()60     public void onEngineDataReceived() {
61         if (mEngineStartTime == -1) {
62             mEngineStartTime = SystemClock.elapsedRealtime();
63         }
64     }
65 
66     /**
67      * Notifies the logger that the engine has finished processing data.
68      * Will be called exactly once.
69      */
onEngineComplete()70     public void onEngineComplete() {
71         mEngineCompleteTime = SystemClock.elapsedRealtime();
72     }
73 
74     /**
75      * Notifies the logger that audio playback has started for some section
76      * of the synthesis. This is normally some amount of time after the engine
77      * has synthesized data and varies depending on utterances and
78      * other audio currently in the queue.
79      */
onAudioDataWritten()80     public void onAudioDataWritten() {
81         // For now, keep track of only the first chunk of audio
82         // that was played.
83         if (mPlaybackStartTime == -1) {
84             mPlaybackStartTime = SystemClock.elapsedRealtime();
85         }
86     }
87 
88     /**
89      * Notifies the logger that the current synthesis has completed.
90      * All available data is not logged.
91      */
onCompleted(int statusCode)92     public void onCompleted(int statusCode) {
93         if (mLogWritten) {
94             return;
95         } else {
96             mLogWritten = true;
97         }
98 
99         long completionTime = SystemClock.elapsedRealtime();
100 
101         // We don't report latency for stopped syntheses because their overall
102         // total time spent will be inaccurate (will not correlate with
103         // the length of the utterance).
104 
105         // onAudioDataWritten() should normally always be called, and hence mPlaybackStartTime
106         // should be set, if an error does not occur.
107         if (statusCode != TextToSpeech.SUCCESS
108                 || mPlaybackStartTime == -1 || mEngineCompleteTime == -1) {
109             logFailure(statusCode);
110             return;
111         }
112 
113         final long audioLatency = mPlaybackStartTime - mReceivedTime;
114         final long engineLatency = mEngineStartTime - mRequestProcessingStartTime;
115         final long engineTotal = mEngineCompleteTime - mRequestProcessingStartTime;
116         logSuccess(audioLatency, engineLatency, engineTotal);
117     }
118 
logFailure(int statusCode)119     protected abstract void logFailure(int statusCode);
logSuccess(long audioLatency, long engineLatency, long engineTotal)120     protected abstract void logSuccess(long audioLatency, long engineLatency,
121             long engineTotal);
122 
123 
124 }
125