blob: 37f86561b77f51fd627325b308f6d7c9af5f79ff [file] [log] [blame]
Przemyslaw Szczepaniak90d15d22013-06-14 12:02:53 +01001/*
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 */
16package android.speech.tts;
17
18import 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 */
27abstract 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
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 */
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 */
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 */
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 */
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 */
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 != TextToSpeechClient.Status.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
119 protected abstract void logFailure(int statusCode);
120 protected abstract void logSuccess(long audioLatency, long engineLatency,
121 long engineTotal);
122
123
124}