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