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.print;
  
  import android.annotation.UnsupportedAppUsage;
  import android.os.Bundle;
  import android.os.CancellationSignal;
  import android.os.ParcelFileDescriptor;
  
  /**
   * Base class that provides the content of a document to be printed.
   *
   * <h3>Lifecycle</h3>
   * <p>
   * <ul>
   * <li>
   * Initially, you will receive a call to {@link #onStart()}. This callback
   * can be used to allocate resources.
   * </li>
   * <li>
   * Next, you will get one or more calls to {@link #onLayout(PrintAttributes,
   * PrintAttributes, CancellationSignal, LayoutResultCallback, Bundle)} to
   * inform you that the print attributes (page size, density, etc) changed
   * giving you an opportunity to layout the content to match the new constraints.
   * </li>
   * <li>
   * After every call to {@link #onLayout(PrintAttributes, PrintAttributes,
   * CancellationSignal, LayoutResultCallback, Bundle)}, you <strong>may</strong> get
   * a call to {@link #onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal,
   * WriteResultCallback)} asking you to write a PDF file with the content for
   * specific pages.
   * </li>
   * <li>
   * Finally, you will receive a call to {@link #onFinish()}. You can use this
   * callback to release resources allocated in {@link #onStart()}.
   * </li>
   * </ul>
   * <p>
   * The {@link #onStart()} callback is always the first call you will receive and
   * is useful for doing one time setup or resource allocation before printing. You
   * will not receive a subsequent call here.
   * </p>
   * <p>
   * The {@link #onLayout(PrintAttributes, PrintAttributes, CancellationSignal,
   * LayoutResultCallback, Bundle)} callback requires that you layout the content
   * based on the current {@link PrintAttributes}. The execution of this method is
   * not considered completed until you invoke one of the methods on the passed in
   * callback instance. Hence, you will not receive a subsequent call to any other
   * method of this class until the execution of this method is complete by invoking
   * one of the callback methods.
   * </p>
   * <p>
   * The {@link #onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal,
   * WriteResultCallback)} requires that you render and write the content of some
   * pages to the provided destination. The execution of this method is not
   * considered complete until you invoke one of the methods on the passed in
   * callback instance. Hence, you will not receive a subsequent call to any other
   * method of this class until the execution of this method is complete by invoking
   * one of the callback methods. You will never receive a sequence of one or more
   * calls to this method without a previous call to {@link #onLayout(PrintAttributes,
   * PrintAttributes, CancellationSignal, LayoutResultCallback, Bundle)}.
   * </p>
   * <p>
   * The {@link #onFinish()} callback is always the last call you will receive and
   * is useful for doing one time cleanup or resource deallocation after printing.
   * You will not receive a subsequent call here.
   * </p>
   * </p>
   * <h3>Implementation</h3>
   * <p>
   * The APIs defined in this class are designed to enable doing part or all
   * of the work on an arbitrary thread. For example, if the printed content
   * does not depend on the UI state, i.e. on what is shown on the screen, then
   * you can offload the entire work on a dedicated thread, thus making your
   * application interactive while the print work is being performed. Note that
   * while your activity is covered by the system print UI and a user cannot
   * interact with it, doing the printing work on the main application thread
   * may affect the performance of your other application components as they
   * are also executed on that thread.
   * </p>
   * <p>
   * You can also do work on different threads, for example if you print UI
   * content, you can handle {@link #onStart()} and {@link #onLayout(PrintAttributes,
   * PrintAttributes, CancellationSignal, LayoutResultCallback, Bundle)} on
   * the UI thread (assuming onStart initializes resources needed for layout).
   * This will ensure that the UI does not change while you are laying out the
   * printed content. Then you can handle {@link #onWrite(PageRange[], ParcelFileDescriptor,
   * CancellationSignal, WriteResultCallback)} and {@link #onFinish()} on another
   * thread. This will ensure that the main thread is busy for a minimal amount of
   * time. Also this assumes that you will generate the printed content in
   * {@link #onLayout(PrintAttributes, PrintAttributes, CancellationSignal,
   * LayoutResultCallback, Bundle)} which is not mandatory. If you use multiple
   * threads, you are responsible for proper synchronization.
   * </p>
   */
  public abstract class PrintDocumentAdapter {
  
      /**
       * Extra: mapped to a boolean value that is <code>true</code> if
       * the current layout is for a print preview, <code>false</code> otherwise.
       * This extra is provided in the {@link Bundle} argument of the {@link
       * #onLayout(PrintAttributes, PrintAttributes, CancellationSignal,
       * LayoutResultCallback, Bundle)} callback.
       *
       * @see #onLayout(PrintAttributes, PrintAttributes, CancellationSignal,
       * LayoutResultCallback, Bundle)
       */
      public static final String EXTRA_PRINT_PREVIEW = "EXTRA_PRINT_PREVIEW";
  
      /**
       * Called when printing starts. You can use this callback to allocate
       * resources. This method is invoked on the main thread.
       */
      public void onStart() {
          /* do nothing - stub */
      }
  
      /**
       * Called when the print attributes (page size, density, etc) changed
       * giving you a chance to layout the content such that it matches the
       * new constraints. This method is invoked on the main thread.
       * <p>
       * After you are done laying out, you <strong>must</strong> invoke: {@link
       * LayoutResultCallback#onLayoutFinished(PrintDocumentInfo, boolean)} with
       * the last argument <code>true</code> or <code>false</code> depending on
       * whether the layout changed the content or not, respectively; or {@link
       * LayoutResultCallback#onLayoutFailed(CharSequence)}, if an error occurred;
       * or {@link LayoutResultCallback#onLayoutCancelled()} if layout was
       * cancelled in a response to a cancellation request via the passed in
       * {@link CancellationSignal}. Note that you <strong>must</strong> call one of
       * the methods of the given callback for this method to be considered complete
       * which is you will not receive any calls to this adapter until the current
       * layout operation is complete by invoking a method on the callback instance.
       * The callback methods can be invoked from an arbitrary thread.
       * </p>
       * <p>
       * One of the arguments passed to this method is a {@link CancellationSignal}
       * which is used to propagate requests from the system to your application for
       * canceling the current layout operation. For example, a cancellation may be
       * requested if the user changes a print option that may affect layout while
       * you are performing a layout operation. In such a case the system will make
       * an attempt to cancel the current layout as another one will have to be performed.
       * Typically, you should register a cancellation callback in the cancellation
       * signal. The cancellation callback <strong>will not</strong> be made on the
       * main thread and can be registered as follows:
       * </p>
       * <pre>
       * cancellationSignal.setOnCancelListener(new OnCancelListener() {
       *     &#064;Override
       *     public void onCancel() {
       *         // Cancel layout
       *     }
       * });
       * </pre>
       * <p>
       * <strong>Note:</strong> If the content is large and a layout will be
       * performed, it is a good practice to schedule the work on a dedicated
       * thread and register an observer in the provided {@link
       * CancellationSignal} upon invocation of which you should stop the
       * layout.
       * </p>
       *
       * @param oldAttributes The old print attributes.
       * @param newAttributes The new print attributes.
       * @param cancellationSignal Signal for observing cancel layout requests.
       * @param callback Callback to inform the system for the layout result.
       * @param extras Additional information about how to layout the content.
       *
       * @see LayoutResultCallback
       * @see CancellationSignal
       * @see #EXTRA_PRINT_PREVIEW
       */
      public abstract void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
              CancellationSignal cancellationSignal, LayoutResultCallback callback,
              Bundle extras);
  
      /**
       * Called when specific pages of the content should be written in the
       * form of a PDF file to the given file descriptor. This method is invoked
       * on the main thread.
       *<p>
       * After you are done writing, you should close the file descriptor and
       * invoke {@link WriteResultCallback#onWriteFinished(PageRange[])}, if writing
       * completed successfully; or {@link WriteResultCallback#onWriteFailed(
       * CharSequence)}, if an error occurred; or {@link WriteResultCallback#onWriteCancelled()},
       * if writing was cancelled in a response to a cancellation request via the passed
       * in {@link CancellationSignal}. Note that you <strong>must</strong> call one of
       * the methods of the given callback for this method to be considered complete which
       * is you will not receive any calls to this adapter until the current write
       * operation is complete by invoking a method on the callback instance. The callback
       * methods can be invoked from an arbitrary thread.
       * </p>
       * <p>
       * One of the arguments passed to this method is a {@link CancellationSignal}
       * which is used to propagate requests from the system to your application for
       * canceling the current write operation. For example, a cancellation may be
       * requested if the user changes a print option that may affect layout while
       * you are performing a write operation. In such a case the system will make
       * an attempt to cancel the current write as a layout will have to be performed
       * which then may be followed by a write. Typically, you should register a
       * cancellation callback in the cancellation signal. The cancellation callback
       * <strong>will not</strong> be made on the main thread and can be registered
       * as follows:
       * </p>
       * <pre>
       * cancellationSignal.setOnCancelListener(new OnCancelListener() {
       *     &#064;Override
       *     public void onCancel() {
       *         // Cancel write
       *     }
       * });
       * </pre>
       * <p>
       * <strong>Note:</strong> If the printed content is large, it is a good
       * practice to schedule writing it on a dedicated thread and register an
       * observer in the provided {@link CancellationSignal} upon invocation of
       * which you should stop writing.
       * </p>
       *
       * @param pages The pages whose content to print - non-overlapping in ascending order.
       * @param destination The destination file descriptor to which to write.
       * @param cancellationSignal Signal for observing cancel writing requests.
       * @param callback Callback to inform the system for the write result.
       *
       * @see WriteResultCallback
       * @see CancellationSignal
       */
      public abstract void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
              CancellationSignal cancellationSignal, WriteResultCallback callback);
  
      /**
       * Called when printing finishes. You can use this callback to release
       * resources acquired in {@link #onStart()}. This method is invoked on
       * the main thread.
       */
      public void onFinish() {
          /* do nothing - stub */
      }
  
      /**
       * Base class for implementing a callback for the result of {@link
       * PrintDocumentAdapter#onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal,
       * WriteResultCallback)}.
       */
      public static abstract class WriteResultCallback {
  
          /**
           * @hide
           */
          @UnsupportedAppUsage
          public WriteResultCallback() {
              /* do nothing - hide constructor */
          }
  
          /**
           * Notifies that all the data was written.
           *
           * @param pages The pages that were written. Cannot be <code>null</code>
           *        or empty. <br />
           *        Returning {@link PageRange#ALL_PAGES} indicates that all pages that were
           *        requested as the {@code pages} parameter in {@link #onWrite} were written.
           */
          public void onWriteFinished(PageRange[] pages) {
              /* do nothing - stub */
          }
  
          /**
           * Notifies that an error occurred while writing the data.
           *
           * @param error The <strong>localized</strong> error message.
           * shown to the user. May be <code>null</code> if error is unknown.
           */
          public void onWriteFailed(CharSequence error) {
              /* do nothing - stub */
          }
  
          /**
           * Notifies that write was cancelled as a result of a cancellation request.
           */
          public void onWriteCancelled() {
              /* do nothing - stub */
          }
      }
  
      /**
       * Base class for implementing a callback for the result of {@link
       * PrintDocumentAdapter#onLayout(PrintAttributes, PrintAttributes,
       * CancellationSignal, LayoutResultCallback, Bundle)}.
       */
      public static abstract class LayoutResultCallback {
  
          /**
           * @hide
           */
          @UnsupportedAppUsage
          public LayoutResultCallback() {
              /* do nothing - hide constructor */
          }
  
          /**
           * Notifies that the layout finished and whether the content changed.
           *
           * @param info An info object describing the document. Cannot be <code>null</code>.
           * @param changed Whether the layout changed.
           *
           * @see PrintDocumentInfo
           */
          public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
              /* do nothing - stub */
          }
  
          /**
           * Notifies that an error occurred while laying out the document.
           *
           * @param error The <strong>localized</strong> error message.
           * shown to the user. May be <code>null</code> if error is unknown.
           */
          public void onLayoutFailed(CharSequence error) {
              /* do nothing - stub */
          }
  
          /**
           * Notifies that layout was cancelled as a result of a cancellation request.
           */
          public void onLayoutCancelled() {
              /* do nothing - stub */
          }
      }
  }
  