/**
   * Cancels the operation and signals the cancellation listener. If the operation has not yet
   * started, then it will be canceled as soon as it does.
   */
  public void cancel() {
    final OnCancelListener listener;
    final ICancellationSignal remote;
    synchronized (this) {
      if (mIsCanceled) {
        return;
      }
      mIsCanceled = true;
      mCancelInProgress = true;
      listener = mOnCancelListener;
      remote = mRemote;
    }

    try {
      if (listener != null) {
        listener.onCancel();
      }
      if (remote != null) {
        try {
          remote.cancel();
        } catch (RemoteException ex) {
        }
      }
    } finally {
      synchronized (this) {
        mCancelInProgress = false;
        notifyAll();
      }
    }
  }
  /**
   * Sets the remote transport.
   *
   * <p>If {@link CancellationSignal#cancel} has already been called, then the provided remote
   * transport is canceled immediately.
   *
   * <p>This method is guaranteed that the remote transport will not be called after it has been
   * removed.
   *
   * @param remote The remote transport, or null to remove.
   * @hide
   */
  public void setRemote(ICancellationSignal remote) {
    synchronized (this) {
      waitForCancelFinishedLocked();

      if (mRemote == remote) {
        return;
      }
      mRemote = remote;
      if (!mIsCanceled || remote == null) {
        return;
      }
    }
    try {
      remote.cancel();
    } catch (RemoteException ex) {
    }
  }