/**
   * Handles when the speech controller finished speaking an instruction.
   *
   * @param status The speech item status code from the speech controller.
   */
  private void onUtteranceComplete(int status) {
    setTouchGuardActive(false);
    mFeedbackController.playSound(R.raw.ready, 1.0f, 1.0f);
    unlockOrientation();

    if (sTutorialIsActive && (mResourceIdToRepeat > 0)) {
      mRepeatHandler.sendEmptyMessageDelayed(RepeatHandler.MSG_REPEAT, REPEAT_DELAY);
    }
  }
  /**
   * Speaks the previously stored instruction text again.
   *
   * <p>Assumes that {@code mTextToRepeat} is non-null.
   */
  private void repeatInstruction() {
    if (!sTutorialIsActive) {
      mRepeatHandler.removeMessages(RepeatHandler.MSG_REPEAT);
      return;
    }

    lockOrientation();
    setTouchGuardActive(true);

    speakInternal(mResourceIdToRepeat, mRepeatedFormatArgs);
  }
  @Override
  protected void onResume() {
    super.onResume();
    sTutorialIsActive = true;

    /*
     * Handle the cases where the tutorial was started with TalkBack in an
     * invalid state (inactive, suspended, or without Explore by Touch
     * enabled).
     */
    final ServiceState serviceState = TalkBackService.getServiceState();
    /*
     * Check for suspended state first because touch exploration reports it
     * is disabled when TalkBack is suspended.
     */
    if (serviceState == ServiceState.SUSPENDED) {
      showAlertDialogAndFinish(
          R.string.accessibility_tutorial_service_suspended_title,
          R.string.accessibility_tutorial_service_suspended_message);
      return;
    } else if ((serviceState == ServiceState.INACTIVE)
        || !mAccessibilityManager.isTouchExplorationEnabled()) {
      showAlertDialogAndFinish(
          R.string.accessibility_tutorial_service_inactive_title,
          R.string.accessibility_tutorial_service_inactive_message);
      return;
    }

    final TalkBackService service = TalkBackService.getInstance();
    service.addServiceStateListener(mServiceStateListener);

    if (mFirstTimeResume) {
      mFirstTimeResume = false;

      if (mSavedInstanceState != null) {
        show(mSavedInstanceState.getInt(KEY_ACTIVE_MODULE, DEFAULT_MODULE));
      } else {
        show(DEFAULT_MODULE);
      }
    }

    getCurrentModule().onResume();

    if (mResourceIdToRepeat > 0) {
      mRepeatHandler.sendEmptyMessageDelayed(RepeatHandler.MSG_REPEAT, RESUME_REPEAT_DELAY);
    }
  }
  @Override
  protected void onPause() {
    super.onPause();
    sTutorialIsActive = false;

    final TalkBackService service = TalkBackService.getInstance();
    if (service != null) {
      service.removeServiceStateListener(mServiceStateListener);
    }

    getCurrentModule().onPause();

    interrupt();

    // This is different than stopRepeating because we want the current
    // instruction text to continue repeating if the activity resumes.
    mRepeatHandler.removeMessages(RepeatHandler.MSG_REPEAT);

    unlockOrientation();
  }
 /**
  * Stops the current instruction from repeating in the future.
  *
  * <p>Note: this carries over even after the activity is paused and resumed.
  */
 public void stopRepeating() {
   mRepeatHandler.removeMessages(RepeatHandler.MSG_REPEAT);
   mResourceIdToRepeat = 0;
 }