content: /*
   * Copyright (C) 2013 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License"); you may not
   * use this file except in compliance with the License. You may obtain a copy of
   * the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   * License for the specific language governing permissions and limitations under
   * the License.
   */
  package android.speech.tts;
  
  import android.os.SystemClock;
  
  /**
   * Base class for storing data about a given speech synthesis request to the
   * event logs. The data that is logged depends on actual implementation. Note
   * that {@link AbstractEventLogger#onAudioDataWritten()} and
   * {@link AbstractEventLogger#onEngineComplete()} must be called from a single
   * thread (usually the audio playback thread}.
   */
  abstract class AbstractEventLogger {
      protected final String mServiceApp;
      protected final int mCallerUid;
      protected final int mCallerPid;
      protected final long mReceivedTime;
      protected long mPlaybackStartTime = -1;
  
      private volatile long mRequestProcessingStartTime = -1;
      private volatile long mEngineStartTime = -1;
      private volatile long mEngineCompleteTime = -1;
  
      private boolean mLogWritten = false;
  
      AbstractEventLogger(int callerUid, int callerPid, String serviceApp) {
          mCallerUid = callerUid;
          mCallerPid = callerPid;
          mServiceApp = serviceApp;
          mReceivedTime = SystemClock.elapsedRealtime();
      }
  
      /**
       * Notifies the logger that this request has been selected from
       * the processing queue for processing. Engine latency / total time
       * is measured from this baseline.
       */
      public void onRequestProcessingStart() {
          mRequestProcessingStartTime = SystemClock.elapsedRealtime();
      }
  
      /**
       * Notifies the logger that a chunk of data has been received from
       * the engine. Might be called multiple times.
       */
      public void onEngineDataReceived() {
          if (mEngineStartTime == -1) {
              mEngineStartTime = SystemClock.elapsedRealtime();
          }
      }
  
      /**
       * Notifies the logger that the engine has finished processing data.
       * Will be called exactly once.
       */
      public void onEngineComplete() {
          mEngineCompleteTime = SystemClock.elapsedRealtime();
      }
  
      /**
       * Notifies the logger that audio playback has started for some section
       * of the synthesis. This is normally some amount of time after the engine
       * has synthesized data and varies depending on utterances and
       * other audio currently in the queue.
       */
      public void onAudioDataWritten() {
          // For now, keep track of only the first chunk of audio
          // that was played.
          if (mPlaybackStartTime == -1) {
              mPlaybackStartTime = SystemClock.elapsedRealtime();
          }
      }
  
      /**
       * Notifies the logger that the current synthesis has completed.
       * All available data is not logged.
       */
      public void onCompleted(int statusCode) {
          if (mLogWritten) {
              return;
          } else {
              mLogWritten = true;
          }
  
          long completionTime = SystemClock.elapsedRealtime();
  
          // We don't report latency for stopped syntheses because their overall
          // total time spent will be inaccurate (will not correlate with
          // the length of the utterance).
  
          // onAudioDataWritten() should normally always be called, and hence mPlaybackStartTime
          // should be set, if an error does not occur.
          if (statusCode != TextToSpeech.SUCCESS
                  || mPlaybackStartTime == -1 || mEngineCompleteTime == -1) {
              logFailure(statusCode);
              return;
          }
  
          final long audioLatency = mPlaybackStartTime - mReceivedTime;
          final long engineLatency = mEngineStartTime - mRequestProcessingStartTime;
          final long engineTotal = mEngineCompleteTime - mRequestProcessingStartTime;
          logSuccess(audioLatency, engineLatency, engineTotal);
      }
  
      protected abstract void logFailure(int statusCode);
      protected abstract void logSuccess(long audioLatency, long engineLatency,
              long engineTotal);
  
  
  }
  