190d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak/* 290d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * Copyright (C) 2013 The Android Open Source Project 390d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * 490d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * Licensed under the Apache License, Version 2.0 (the "License"); you may not 590d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * use this file except in compliance with the License. You may obtain a copy of 690d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * the License at 790d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * 890d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * http://www.apache.org/licenses/LICENSE-2.0 990d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * 1090d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * Unless required by applicable law or agreed to in writing, software 1190d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 1290d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 1390d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * License for the specific language governing permissions and limitations under 1490d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * the License. 1590d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak */ 1690d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniakpackage android.speech.tts; 1790d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 1890d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniakimport android.os.SystemClock; 1990d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 2090d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak/** 2190d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * Base class for storing data about a given speech synthesis request to the 2290d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * event logs. The data that is logged depends on actual implementation. Note 2390d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * that {@link AbstractEventLogger#onAudioDataWritten()} and 2490d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * {@link AbstractEventLogger#onEngineComplete()} must be called from a single 2590d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * thread (usually the audio playback thread}. 2690d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak */ 2790d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniakabstract class AbstractEventLogger { 2890d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak protected final String mServiceApp; 2990d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak protected final int mCallerUid; 3090d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak protected final int mCallerPid; 3190d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak protected final long mReceivedTime; 3290d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak protected long mPlaybackStartTime = -1; 3390d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 3490d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak private volatile long mRequestProcessingStartTime = -1; 3590d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak private volatile long mEngineStartTime = -1; 3690d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak private volatile long mEngineCompleteTime = -1; 3790d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 3890d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak private boolean mLogWritten = false; 3990d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 4090d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak AbstractEventLogger(int callerUid, int callerPid, String serviceApp) { 4190d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak mCallerUid = callerUid; 4290d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak mCallerPid = callerPid; 4390d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak mServiceApp = serviceApp; 4490d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak mReceivedTime = SystemClock.elapsedRealtime(); 4590d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak } 4690d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 4790d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak /** 4890d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * Notifies the logger that this request has been selected from 4990d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * the processing queue for processing. Engine latency / total time 5090d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * is measured from this baseline. 5190d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak */ 5290d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak public void onRequestProcessingStart() { 5390d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak mRequestProcessingStartTime = SystemClock.elapsedRealtime(); 5490d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak } 5590d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 5690d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak /** 5790d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * Notifies the logger that a chunk of data has been received from 5890d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * the engine. Might be called multiple times. 5990d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak */ 6090d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak public void onEngineDataReceived() { 6190d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak if (mEngineStartTime == -1) { 6290d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak mEngineStartTime = SystemClock.elapsedRealtime(); 6390d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak } 6490d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak } 6590d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 6690d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak /** 6790d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * Notifies the logger that the engine has finished processing data. 6890d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * Will be called exactly once. 6990d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak */ 7090d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak public void onEngineComplete() { 7190d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak mEngineCompleteTime = SystemClock.elapsedRealtime(); 7290d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak } 7390d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 7490d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak /** 7590d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * Notifies the logger that audio playback has started for some section 7690d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * of the synthesis. This is normally some amount of time after the engine 7790d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * has synthesized data and varies depending on utterances and 7890d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * other audio currently in the queue. 7990d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak */ 8090d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak public void onAudioDataWritten() { 8190d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak // For now, keep track of only the first chunk of audio 8290d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak // that was played. 8390d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak if (mPlaybackStartTime == -1) { 8490d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak mPlaybackStartTime = SystemClock.elapsedRealtime(); 8590d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak } 8690d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak } 8790d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 8890d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak /** 8990d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * Notifies the logger that the current synthesis has completed. 9090d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak * All available data is not logged. 9190d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak */ 9290d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak public void onCompleted(int statusCode) { 9390d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak if (mLogWritten) { 9490d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak return; 9590d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak } else { 9690d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak mLogWritten = true; 9790d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak } 9890d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 9990d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak long completionTime = SystemClock.elapsedRealtime(); 10090d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 10190d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak // We don't report latency for stopped syntheses because their overall 10290d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak // total time spent will be inaccurate (will not correlate with 10390d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak // the length of the utterance). 10490d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 10590d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak // onAudioDataWritten() should normally always be called, and hence mPlaybackStartTime 10690d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak // should be set, if an error does not occur. 107fc4b2890378eb1b6e0b11d60d703eb6854268064Przemyslaw Szczepaniak if (statusCode != TextToSpeech.SUCCESS 10890d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak || mPlaybackStartTime == -1 || mEngineCompleteTime == -1) { 10990d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak logFailure(statusCode); 11090d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak return; 11190d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak } 11290d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 11390d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak final long audioLatency = mPlaybackStartTime - mReceivedTime; 11490d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak final long engineLatency = mEngineStartTime - mRequestProcessingStartTime; 11590d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak final long engineTotal = mEngineCompleteTime - mRequestProcessingStartTime; 11690d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak logSuccess(audioLatency, engineLatency, engineTotal); 11790d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak } 11890d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 11990d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak protected abstract void logFailure(int statusCode); 12090d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak protected abstract void logSuccess(long audioLatency, long engineLatency, 12190d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak long engineTotal); 12290d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 12390d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak 12490d15d2371ad85f22254be6985455aa2baa5d15dPrzemyslaw Szczepaniak} 125