Merge "Move PdfDocument to android.graphics.pdf" into klp-dev
diff --git a/api/current.txt b/api/current.txt
index b3e5c6e..f04bf40 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10372,6 +10372,37 @@
 
 }
 
+package android.graphics.pdf {
+
+  public class PdfDocument {
+    ctor public PdfDocument();
+    method public void close();
+    method public void finishPage(android.graphics.pdf.PdfDocument.Page);
+    method public java.util.List<android.graphics.pdf.PdfDocument.PageInfo> getPages();
+    method public android.graphics.pdf.PdfDocument.Page startPage(android.graphics.pdf.PdfDocument.PageInfo);
+    method public void writeTo(java.io.OutputStream) throws java.io.IOException;
+  }
+
+  public static final class PdfDocument.Page {
+    method public android.graphics.Canvas getCanvas();
+    method public android.graphics.pdf.PdfDocument.PageInfo getInfo();
+  }
+
+  public static final class PdfDocument.PageInfo {
+    method public android.graphics.Rect getContentRect();
+    method public int getPageHeight();
+    method public int getPageNumber();
+    method public int getPageWidth();
+  }
+
+  public static final class PdfDocument.PageInfo.Builder {
+    ctor public PdfDocument.PageInfo.Builder(int, int, int);
+    method public android.graphics.pdf.PdfDocument.PageInfo create();
+    method public android.graphics.pdf.PdfDocument.PageInfo.Builder setContentRect(android.graphics.Rect);
+  }
+
+}
+
 package android.hardware {
 
   public class Camera {
@@ -19250,7 +19281,7 @@
     method public abstract void onLayout(android.print.PrintAttributes, android.print.PrintAttributes, android.os.CancellationSignal, android.print.PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle);
     method public void onStart();
     method public abstract void onWrite(android.print.PageRange[], android.os.ParcelFileDescriptor, android.os.CancellationSignal, android.print.PrintDocumentAdapter.WriteResultCallback);
-    field public static final java.lang.String METADATA_KEY_PRINT_PREVIEW = "KEY_METADATA_PRINT_PREVIEW";
+    field public static final java.lang.String EXTRA_PRINT_PREVIEW = "EXTRA_PRINT_PREVIEW";
   }
 
   public static abstract class PrintDocumentAdapter.LayoutResultCallback {
@@ -19386,41 +19417,12 @@
 
 package android.print.pdf {
 
-  public final class PdfDocument {
-    method public void close();
-    method public void finishPage(android.print.pdf.PdfDocument.Page);
-    method public java.util.List<android.print.pdf.PdfDocument.PageInfo> getPages();
-    method public static android.print.pdf.PdfDocument open();
-    method public android.print.pdf.PdfDocument.Page startPage(android.print.pdf.PdfDocument.PageInfo);
-    method public void writeTo(java.io.OutputStream);
-  }
-
-  public static final class PdfDocument.Page {
-    method public android.graphics.Canvas getCanvas();
-    method public android.print.pdf.PdfDocument.PageInfo getInfo();
-  }
-
-  public static final class PdfDocument.PageInfo {
-    method public android.graphics.Rect getContentSize();
-    method public android.graphics.Matrix getInitialTransform();
-    method public int getPageNumber();
-    method public android.graphics.Rect getPageSize();
-  }
-
-  public static final class PdfDocument.PageInfo.Builder {
-    ctor public PdfDocument.PageInfo.Builder(android.graphics.Rect, int);
-    method public android.print.pdf.PdfDocument.PageInfo create();
-    method public android.print.pdf.PdfDocument.PageInfo.Builder setContentSize(android.graphics.Rect);
-    method public android.print.pdf.PdfDocument.PageInfo.Builder setInitialTransform(android.graphics.Matrix);
-  }
-
-  public final class PrintedPdfDocument {
-    method public void close();
-    method public void finishPage(android.print.pdf.PdfDocument.Page);
-    method public java.util.List<android.print.pdf.PdfDocument.PageInfo> getPages();
-    method public static android.print.pdf.PrintedPdfDocument open(android.content.Context, android.print.PrintAttributes);
-    method public android.print.pdf.PdfDocument.Page startPage(int);
-    method public void writeTo(java.io.OutputStream);
+  public class PrintedPdfDocument extends android.graphics.pdf.PdfDocument {
+    ctor public PrintedPdfDocument(android.content.Context, android.print.PrintAttributes);
+    method public android.graphics.Rect getPageContentRect();
+    method public int getPageHeight();
+    method public int getPageWidth();
+    method public android.graphics.pdf.PdfDocument.Page startPage(int);
   }
 
 }
diff --git a/core/java/android/print/PrintDocumentAdapter.java b/core/java/android/print/PrintDocumentAdapter.java
index 8ac34c1..4113ac7 100644
--- a/core/java/android/print/PrintDocumentAdapter.java
+++ b/core/java/android/print/PrintDocumentAdapter.java
@@ -74,10 +74,10 @@
 public abstract class PrintDocumentAdapter {
 
     /**
-     * Meta-data key: mapped to a boolean value that is <code>true</code> if
+     * Extra: mapped to a boolean value that is <code>true</code> if
      * the current layout is for a print preview, <code>false</code> otherwise.
      */
-    public static final String METADATA_KEY_PRINT_PREVIEW = "KEY_METADATA_PRINT_PREVIEW";
+    public static final String EXTRA_PRINT_PREVIEW = "EXTRA_PRINT_PREVIEW";
 
     /**
      * Called when printing starts. You can use this callback to allocate
@@ -112,15 +112,15 @@
      * @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 metadata Additional information about how layout the content.
+     * @param extras Additional information about how to layout the content.
      *
      * @see LayoutResultCallback
      * @see CancellationSignal
-     * @see #METADATA_KEY_PRINT_PREVIEW
+     * @see #EXTRA_PRINT_PREVIEW
      */
     public abstract void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
             CancellationSignal cancellationSignal, LayoutResultCallback callback,
-            Bundle metadata);
+            Bundle extras);
 
     /**
      * Called when specific pages of the content should be written in the
diff --git a/core/java/android/print/pdf/PrintedPdfDocument.java b/core/java/android/print/pdf/PrintedPdfDocument.java
index 1fd4646..2d8aafa 100644
--- a/core/java/android/print/pdf/PrintedPdfDocument.java
+++ b/core/java/android/print/pdf/PrintedPdfDocument.java
@@ -18,67 +18,81 @@
 
 import android.content.Context;
 import android.graphics.Rect;
+import android.graphics.pdf.PdfDocument;
+import android.graphics.pdf.PdfDocument.Page;
+import android.graphics.pdf.PdfDocument.PageInfo;
 import android.print.PrintAttributes;
 import android.print.PrintAttributes.Margins;
 import android.print.PrintAttributes.MediaSize;
-import android.print.pdf.PdfDocument;
-import android.print.pdf.PdfDocument.Page;
-import android.print.pdf.PdfDocument.PageInfo;
-
-import java.io.OutputStream;
-import java.util.List;
 
 /**
- * This class is a helper for printing content to a different media
- * size. This class is responsible for computing a correct page size
- * given some print constraints, i.e. {@link PrintAttributes}. It is
- * an adapter around a {@link PdfDocument}.
+ * This class is a helper for creating a PDF file for given print
+ * attributes. It is useful for implementing printing via the native
+ * Android graphics APIs.
+ * <p>
+ * This class computes the page width, page height, and content rectangle
+ * from the provided print attributes and these precomputed values can be
+ * accessed via {@link #getPageWidth()}, {@link #getPageHeight()}, and
+ * {@link #getPageContentRect()}, respectively. The {@link #startPage(int)}
+ * methods creates pages whose {@link PageInfo} is initialized with the
+ * precomputed values for width, height, and content rectangle.
+ * <p>
+ * A typical use of the APIs looks like this:
+ * </p>
+ * <pre>
+ * // open a new document
+ * PrintedPdfDocument document = new PrintedPdfDocument(context,
+ *         printAttributes);
+ *
+ * // start a page
+ * Page page = document.startPage(0);
+ *
+ * // draw something on the page
+ * View content = getContentView();
+ * content.draw(page.getCanvas());
+ *
+ * // finish the page
+ * document.finishPage(page);
+ * . . .
+ * // add more pages
+ * . . .
+ * // write the document content
+ * document.writeTo(getOutputStream());
+ *
+ * //close the document
+ * document.close();
+ * </pre>
  */
-public final class PrintedPdfDocument {
+public class PrintedPdfDocument extends PdfDocument {
     private static final int MILS_PER_INCH = 1000;
     private static final int POINTS_IN_INCH = 72;
 
-    private final PdfDocument mDocument = PdfDocument.open();
-    private final Rect mPageSize = new Rect();
-    private final Rect mContentSize = new Rect();
+    private final int mPageWidth;
+    private final int mPageHeight;
+    private final Rect mContentRect;
 
     /**
-     * Opens a new document. The document pages are computed based on
-     * the passes in {@link PrintAttributes}.
+     * Creates a new document.
      * <p>
      * <strong>Note:</strong> You must close the document after you are
-     * done by calling {@link #close()}
+     * done by calling {@link #close()}.
      * </p>
      *
      * @param context Context instance for accessing resources.
      * @param attributes The print attributes.
-     * @return The document.
-     *
-     * @see #close()
      */
-    public static PrintedPdfDocument open(Context context, PrintAttributes attributes) {
-        return new PrintedPdfDocument(context, attributes);
-    }
-
-    /**
-     * Creates a new instance.
-     *
-     * @param context Context instance for accessing resources and services.
-     * @param attributes The {@link PrintAttributes} to user.
-     */
-    private PrintedPdfDocument(Context context, PrintAttributes attributes) {
+    public PrintedPdfDocument(Context context, PrintAttributes attributes) {
         MediaSize mediaSize = attributes.getMediaSize();
 
         // Compute the size of the target canvas from the attributes.
-        final int pageWidth = (int) (((float) mediaSize.getWidthMils() / MILS_PER_INCH)
+        mPageWidth = (int) (((float) mediaSize.getWidthMils() / MILS_PER_INCH)
                 * POINTS_IN_INCH);
-        final int pageHeight = (int) (((float) mediaSize.getHeightMils() / MILS_PER_INCH)
+        mPageHeight = (int) (((float) mediaSize.getHeightMils() / MILS_PER_INCH)
                 * POINTS_IN_INCH);
-        mPageSize.set(0, 0, pageWidth, pageHeight);
 
         // Compute the content size from the attributes.
         Margins minMargins = attributes.getMinMargins();
-        final int marginLeft = (int) (((float) minMargins.getLeftMils() /MILS_PER_INCH)
+        final int marginLeft = (int) (((float) minMargins.getLeftMils() / MILS_PER_INCH)
                 * POINTS_IN_INCH);
         final int marginTop = (int) (((float) minMargins.getTopMils() / MILS_PER_INCH)
                 * POINTS_IN_INCH);
@@ -86,14 +100,14 @@
                 * POINTS_IN_INCH);
         final int marginBottom = (int) (((float) minMargins.getBottomMils() / MILS_PER_INCH)
                 * POINTS_IN_INCH);
-        mContentSize.set(mPageSize.left + marginLeft, mPageSize.top + marginTop,
-                mPageSize.right - marginRight, mPageSize.bottom - marginBottom);
+        mContentRect = new Rect(marginLeft, marginTop, mPageWidth - marginRight,
+                mPageHeight - marginBottom);
     }
 
     /**
-     * Starts a page using a page size computed from the print attributes
-     * passed in {@link #open(Context, PrintAttributes)} and the given page
-     * number to create appropriate {@link PageInfo}.
+     * Starts a new page. The page is created using width, height  and content
+     * rectangle computed from the print attributes passed in the constructor
+     * and the given page number to create an appropriate {@link PageInfo}.
      * <p>
      * After the page is created you can draw arbitrary content on the page's
      * canvas which you can get by calling {@link Page#getCanvas() Page.getCanvas()}.
@@ -103,63 +117,48 @@
      * </p>
      * <p>
      * <strong>Note:</strong> Do not call this method after {@link #close()}.
+     * Also do not call this method if the last page returned by this method
+     * is not finished by calling {@link #finishPage(Page)}.
      * </p>
      *
-     * @param pageNumber The page number.
+     * @param pageNumber The page number. Must be a positive value.
      * @return A blank page.
      *
      * @see #finishPage(Page)
      */
     public Page startPage(int pageNumber) {
         PageInfo pageInfo = new PageInfo
-                .Builder(mPageSize, 0)
-                .setContentSize(mContentSize)
+                .Builder(mPageWidth, mPageHeight, pageNumber)
+                .setContentRect(mContentRect)
                 .create();
-        Page page = mDocument.startPage(pageInfo);
-        return page;
+        return startPage(pageInfo);
     }
 
     /**
-     * Finishes a started page. You should always finish the last started page.
-     * <p>
-     * <strong>Note:</strong> Do not call this method after {@link #close()}.
-     * </p>
+     * Gets the page width.
      *
-     * @param page The page.
-     *
-     * @see #startPage(int)
+     * @return The page width in PostScript points (1/72th of an inch).
      */
-    public void finishPage(Page page) {
-        mDocument.finishPage(page);
+    public int getPageWidth() {
+        return mPageWidth;
     }
 
     /**
-     * Writes the document to an output stream.
-     * <p>
-     * <strong>Note:</strong> Do not call this method after {@link #close()}.
-     * </p>
+     * Gets the page height.
      *
-     * @param out The output stream.
+     * @return The page height in PostScript points (1/72th of an inch).
      */
-    public void writeTo(OutputStream out) {
-        mDocument.writeTo(out);
+    public int getPageHeight() {
+        return mPageHeight;
     }
 
     /**
-     * Gets the pages of the document.
+     * Gets the content rectangle. This is the area of the page that
+     * contains printed data and is relative to the page top left.
      *
-     * @return The pages.
+     * @return The content rectangle.
      */
-    public List<PageInfo> getPages() {
-        return mDocument.getPages();
-    }
-
-    /**
-     * Closes this document. This method should be called after you
-     * are done working with the document. After this call the document
-     * is considered closed and none of its methods should be called.
-     */
-    public void close() {
-        mDocument.close();
+    public Rect getPageContentRect() {
+        return mContentRect;
     }
 }
diff --git a/core/java/android/printservice/package.html b/core/java/android/printservice/package.html
index 7410a49..2fb06bd 100644
--- a/core/java/android/printservice/package.html
+++ b/core/java/android/printservice/package.html
@@ -4,12 +4,12 @@
 Provides classes for implementing print services. Print services are plug-in components
 that know how to talk to printers via some standard protocols. These services serve as a
 bridge between the system and the printers. Hence, the printer and print protocol specific
-implementation is factored out of the system and can by independently developed and updated.
+implementation is factored out of the system and can be independently developed and updated.
 </p>
 <p>
 A print service implementation should extend {@link android.printservice.PrintService}
 and implement its abstract methods. Also the print service has to follow the contract for
-managing print {@link android.printservice.PrintJob}s.
+managing {@link android.printservice.PrintJob}s.
 <p/>
 <p>
 The system is responsible for starting and stopping a print service depending on whether
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index d5d746a..f78d807 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -118,6 +118,7 @@
 	android/graphics/Utils.cpp \
 	android/graphics/Xfermode.cpp \
 	android/graphics/YuvToJpegEncoder.cpp \
+	android/graphics/pdf/PdfDocument.cpp \
 	android_media_AudioRecord.cpp \
 	android_media_AudioSystem.cpp \
 	android_media_AudioTrack.cpp \
@@ -135,7 +136,6 @@
 	android_util_FileObserver.cpp \
 	android/opengl/poly_clip.cpp.arm \
 	android/opengl/util.cpp.arm \
-	android/print/android_print_pdf_PdfDocument.cpp \
 	android_server_NetworkManagementSocketTagger.cpp \
 	android_server_Watchdog.cpp \
 	android_ddm_DdmHandleNativeHeap.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 490d85c..8518101 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -117,6 +117,7 @@
 extern int register_android_graphics_Region(JNIEnv* env);
 extern int register_android_graphics_SurfaceTexture(JNIEnv* env);
 extern int register_android_graphics_Xfermode(JNIEnv* env);
+extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env);
 extern int register_android_view_DisplayEventReceiver(JNIEnv* env);
 extern int register_android_view_GraphicBuffer(JNIEnv* env);
 extern int register_android_view_GLES20DisplayList(JNIEnv* env);
@@ -144,7 +145,6 @@
 extern int register_android_os_FileUtils(JNIEnv *env);
 extern int register_android_os_UEventObserver(JNIEnv* env);
 extern int register_android_os_MemoryFile(JNIEnv* env);
-extern int register_android_print_pdf_PdfDocument(JNIEnv* env);
 extern int register_android_net_LocalSocketImpl(JNIEnv* env);
 extern int register_android_net_NetworkUtils(JNIEnv* env);
 extern int register_android_net_TrafficStats(JNIEnv* env);
@@ -1161,6 +1161,7 @@
     REG_JNI(register_android_graphics_Typeface),
     REG_JNI(register_android_graphics_Xfermode),
     REG_JNI(register_android_graphics_YuvImage),
+    REG_JNI(register_android_graphics_pdf_PdfDocument),
 
     REG_JNI(register_android_database_CursorWindow),
     REG_JNI(register_android_database_SQLiteConnection),
@@ -1173,7 +1174,6 @@
     REG_JNI(register_android_os_SELinux),
     REG_JNI(register_android_os_Trace),
     REG_JNI(register_android_os_UEventObserver),
-    REG_JNI(register_android_print_pdf_PdfDocument),
     REG_JNI(register_android_net_LocalSocketImpl),
     REG_JNI(register_android_net_NetworkUtils),
     REG_JNI(register_android_net_TrafficStats),
diff --git a/core/jni/android/print/android_print_pdf_PdfDocument.cpp b/core/jni/android/graphics/pdf/PdfDocument.cpp
similarity index 73%
rename from core/jni/android/print/android_print_pdf_PdfDocument.cpp
rename to core/jni/android/graphics/pdf/PdfDocument.cpp
index 3daad5c..b57a0fe 100644
--- a/core/jni/android/print/android_print_pdf_PdfDocument.cpp
+++ b/core/jni/android/graphics/pdf/PdfDocument.cpp
@@ -28,6 +28,8 @@
 
 namespace android {
 
+#define LOGD(x...) do { Log::Instance()->printf(Log::ELogD, x); } while(0)
+
 static jint nativeCreateDocument(JNIEnv* env, jobject clazz) {
     return reinterpret_cast<jint>(new SkPDFDocument());
 }
@@ -36,21 +38,16 @@
     delete reinterpret_cast<SkPDFDocument*>(documentPtr);
 }
 
-static jint nativeCreatePage(JNIEnv* env, jobject thiz,
-        jobject pageSize, jobject contentSize, jint initialTransformation) {
-    SkIRect skPageSizeRect;
-    GraphicsJNI::jrect_to_irect(env, pageSize, &skPageSizeRect);
-    SkISize skPageSize = SkISize::Make(skPageSizeRect.width(),
-            skPageSizeRect.height());
+static jint nativeCreatePage(JNIEnv* env, jobject thiz, jint pageWidth, jint pageHeight,
+        jint contentLeft, jint contentTop, jint contentRight, jint contentBottom) {
 
-    SkIRect skContentRect;
-    GraphicsJNI::jrect_to_irect(env, contentSize, &skContentRect);
-    SkISize skContentSize = SkISize::Make(skContentRect.width(),
-            skContentRect.height());
+    SkMatrix transformation;
+    transformation.setTranslate(contentLeft, contentTop);
 
-    SkMatrix* transformation = reinterpret_cast<SkMatrix*>(initialTransformation);
-    SkPDFDevice* skPdfDevice = new SkPDFDevice(skPageSize, skContentSize, *transformation);
+    SkISize skPageSize = SkISize::Make(pageWidth, pageHeight);
+    SkISize skContentSize = SkISize::Make(contentRight - contentLeft, contentBottom - contentTop);
 
+    SkPDFDevice* skPdfDevice = new SkPDFDevice(skPageSize, skContentSize, transformation);
     return reinterpret_cast<jint>(new SkCanvas(skPdfDevice));
 }
 
@@ -72,15 +69,15 @@
 static JNINativeMethod gPdfDocument_Methods[] = {
     {"nativeCreateDocument", "()I", (void*) nativeCreateDocument},
     {"nativeFinalize", "(I)V", (void*) nativeFinalize},
-    {"nativeCreatePage", "(Landroid/graphics/Rect;Landroid/graphics/Rect;I)I",
+    {"nativeCreatePage", "(IIIIII)I",
             (void*) nativeCreatePage},
     {"nativeAppendPage", "(II)V", (void*) nativeAppendPage},
     {"nativeWriteTo", "(ILjava/io/OutputStream;[B)V", (void*) nativeWriteTo}
 };
 
-int register_android_print_pdf_PdfDocument(JNIEnv* env) {
+int register_android_graphics_pdf_PdfDocument(JNIEnv* env) {
     int result = android::AndroidRuntime::registerNativeMethods(
-            env, "android/print/pdf/PdfDocument", gPdfDocument_Methods,
+            env, "android/graphics/pdf/PdfDocument", gPdfDocument_Methods,
             NELEM(gPdfDocument_Methods));
     return result;
 }
diff --git a/core/java/android/print/pdf/PdfDocument.java b/graphics/java/android/graphics/pdf/PdfDocument.java
similarity index 65%
rename from core/java/android/print/pdf/PdfDocument.java
rename to graphics/java/android/graphics/pdf/PdfDocument.java
index a2883cf..066ae2b 100644
--- a/core/java/android/print/pdf/PdfDocument.java
+++ b/graphics/java/android/graphics/pdf/PdfDocument.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package android.print.pdf;
+package android.graphics.pdf;
 
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.Matrix;
 import android.graphics.Rect;
 
 import dalvik.system.CloseGuard;
 
+import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -34,14 +34,16 @@
  * open a new document and then for every page you want to add you start a page,
  * write content to the page, and finish the page. After you are done with all
  * pages, you write the document to an output stream and close the document.
- * After a document is closed you should not use it anymore.
+ * After a document is closed you should not use it anymore. Note that pages are
+ * created one by one, i.e. you can have only a single page to which you are
+ * writing at any given time. This class is not thread safe.
  * </p>
  * <p>
  * A typical use of the APIs looks like this:
  * </p>
  * <pre>
- * // open a new document
- * PdfDocument document = PdfDocument.open();
+ * // create a new document
+ * PdfDocument document = new PdfDocument();
  *
  * // crate a page description
  * PageInfo pageInfo = new PageInfo.Builder(new Rect(0, 0, 100, 100), 1).create();
@@ -65,7 +67,7 @@
  * document.close();
  * </pre>
  */
-public final class PdfDocument {
+public class PdfDocument {
 
     private final byte[] mChunk = new byte[4096];
 
@@ -78,24 +80,9 @@
     private Page mCurrentPage;
 
     /**
-     * Opens a new document.
-     * <p>
-     * <strong>Note:</strong> You must close the document after you are
-     * done by calling {@link #close()}
-     * </p>
-     *
-     * @return The document.
-     *
-     * @see #close()
-     */
-    public static PdfDocument open() {
-        return new PdfDocument();
-    }
-
-    /**
      * Creates a new instance.
      */
-    private PdfDocument() {
+    public PdfDocument() {
         mNativeDocument = nativeCreateDocument();
         mCloseGuard.open("close");
     }
@@ -109,23 +96,24 @@
      * no longer access the page or its canvas.
      * <p>
      * <strong>Note:</strong> Do not call this method after {@link #close()}.
+     * Also do not call this method if the last page returned by this method
+     * is not finished by calling {@link #finishPage(Page)}.
      * </p>
      *
-     * @param pageInfo The page info.
+     * @param pageInfo The page info. Cannot be null.
      * @return A blank page.
      *
      * @see #finishPage(Page)
      */
     public Page startPage(PageInfo pageInfo) {
         throwIfClosed();
+        throwIfCurrentPageNotFinished();
         if (pageInfo == null) {
-            throw new IllegalArgumentException("page cannot be null!");
+            throw new IllegalArgumentException("page cannot be null");
         }
-        if (mCurrentPage != null) {
-            throw new IllegalStateException("Previous page not finished!");
-        }
-        Canvas canvas = new PdfCanvas(nativeCreatePage(pageInfo.mPageSize,
-                pageInfo.mContentSize, pageInfo.mInitialTransform.native_instance));
+        Canvas canvas = new PdfCanvas(nativeCreatePage(pageInfo.mPageWidth,
+                pageInfo.mPageHeight, pageInfo.mContentRect.left, pageInfo.mContentRect.top,
+                pageInfo.mContentRect.right, pageInfo.mContentRect.bottom));
         mCurrentPage = new Page(canvas, pageInfo);
         return mCurrentPage;
     }
@@ -134,9 +122,10 @@
      * Finishes a started page. You should always finish the last started page.
      * <p>
      * <strong>Note:</strong> Do not call this method after {@link #close()}.
+     * You should not finish the same page more than once.
      * </p>
      *
-     * @param page The page.
+     * @param page The page. Cannot be null.
      *
      * @see #startPage(PageInfo)
      */
@@ -148,6 +137,9 @@
         if (page != mCurrentPage) {
             throw new IllegalStateException("invalid page");
         }
+        if (page.isFinished()) {
+            throw new IllegalStateException("page already finished");
+        }
         mPages.add(page.getInfo());
         mCurrentPage = null;
         nativeAppendPage(mNativeDocument, page.mCanvas.mNativeCanvas);
@@ -155,15 +147,21 @@
     }
 
     /**
-     * Writes the document to an output stream.
+     * Writes the document to an output stream. You can call this method
+     * multiple times.
      * <p>
      * <strong>Note:</strong> Do not call this method after {@link #close()}.
+     * Also do not call this method if a page returned by {@link #startPage(
+     * PageInfo)} is not finished by calling {@link #finishPage(Page)}.
      * </p>
      *
-     * @param out The output stream.
+     * @param out The output stream. Cannot be null.
+     *
+     * @throws IOException If an error occurs while writing.
      */
-    public void writeTo(OutputStream out) {
+    public void writeTo(OutputStream out) throws IOException {
         throwIfClosed();
+        throwIfCurrentPageNotFinished();
         if (out == null) {
             throw new IllegalArgumentException("out cannot be null!");
         }
@@ -173,7 +171,7 @@
     /**
      * Gets the pages of the document.
      *
-     * @return The pages.
+     * @return The pages or an empty list.
      */
     public List<PageInfo> getPages() {
         return Collections.unmodifiableList(mPages);
@@ -183,8 +181,14 @@
      * Closes this document. This method should be called after you
      * are done working with the document. After this call the document
      * is considered closed and none of its methods should be called.
+     * <p>
+     * <strong>Note:</strong> Do not call this method if the page
+     * returned by {@link #startPage(PageInfo)} is not finished by
+     * calling {@link #finishPage(Page)}.
+     * </p>
      */
     public void close() {
+        throwIfCurrentPageNotFinished();
         dispose();
     }
 
@@ -215,6 +219,15 @@
         }
     }
 
+    /**
+     * Throws an exception if the last started page is not finished.
+     */
+    private void throwIfCurrentPageNotFinished() {
+        if (mCurrentPage != null) {
+            throw new IllegalStateException("Current page not finished!");
+        }
+    }
+
     private native int nativeCreateDocument();
 
     private native void nativeFinalize(int document);
@@ -223,9 +236,8 @@
 
     private native void nativeWriteTo(int document, OutputStream out, byte[] chunk);
 
-    private static native int nativeCreatePage(Rect pageSize,
-            Rect contentSize, int nativeMatrix);
-
+    private static native int nativeCreatePage(int pageWidth, int pageHeight, int contentLeft,
+            int contentTop, int contentRight, int contentBottom);
 
     private final class PdfCanvas extends Canvas {
 
@@ -243,9 +255,9 @@
      * This class represents meta-data that describes a PDF {@link Page}.
      */
     public static final class PageInfo {
-        private Rect mPageSize;
-        private Rect mContentSize;
-        private Matrix mInitialTransform;
+        private int mPageWidth;
+        private int mPageHeight;
+        private Rect mContentRect;
         private int mPageNumber;
 
         /**
@@ -256,32 +268,32 @@
         }
 
         /**
-         * Gets the page size in PostScript points (1/72th of an inch).
+         * Gets the page width in PostScript points (1/72th of an inch).
          *
-         * @return The page size.
+         * @return The page width.
          */
-        public Rect getPageSize() {
-            return mPageSize;
+        public int getPageWidth() {
+            return mPageWidth;
         }
 
         /**
-         * Get the content size in PostScript points (1/72th of an inch).
+         * Gets the page height in PostScript points (1/72th of an inch).
          *
-         * @return The content size.
+         * @return The page height.
          */
-        public Rect getContentSize() {
-            return mContentSize;
+        public int getPageHeight() {
+            return mPageHeight;
         }
 
         /**
-         * Gets the initial transform which is applied to the page. This may be
-         * useful to move the origin to account for a margin, apply scale, or
-         * apply a rotation.
+         * Get the content rectangle in PostScript points (1/72th of an inch).
+         * This is the area that contains the page content and is relative to
+         * the page top left.
          *
-         * @return The initial transform.
+         * @return The content rectangle.
          */
-        public Matrix getInitialTransform() {
-            return mInitialTransform;
+        public Rect getContentRect() {
+            return mContentRect;
         }
 
         /**
@@ -302,47 +314,40 @@
             /**
              * Creates a new builder with the mandatory page info attributes.
              *
-             * @param pageSize The page size in PostScript (1/72th of an inch).
+             * @param pageWidth The page width in PostScript (1/72th of an inch).
+             * @param pageHeight The page height in PostScript (1/72th of an inch).
              * @param pageNumber The page number.
              */
-            public Builder(Rect pageSize, int pageNumber) {
-                if (pageSize.width() == 0 || pageSize.height() == 0) {
-                    throw new IllegalArgumentException("page width and height" +
-                            " must be greater than zero!");
+            public Builder(int pageWidth, int pageHeight, int pageNumber) {
+                if (pageWidth <= 0) {
+                    throw new IllegalArgumentException("page width must be positive");
+                }
+                if (pageHeight <= 0) {
+                    throw new IllegalArgumentException("page width must be positive");
                 }
                 if (pageNumber < 0) {
-                    throw new IllegalArgumentException("pageNumber cannot be less than zero!");
+                    throw new IllegalArgumentException("pageNumber must be non negative");
                 }
-                mPageInfo.mPageSize = pageSize;
+                mPageInfo.mPageWidth = pageWidth;
+                mPageInfo.mPageHeight = pageHeight;
                 mPageInfo.mPageNumber = pageNumber;
             }
 
             /**
-             * Sets the content size in PostScript point (1/72th of an inch).
+             * Sets the content rectangle in PostScript point (1/72th of an inch).
+             * This is the area that contains the page content and is relative to
+             * the page top left.
              *
-             * @param contentSize The content size.
+             * @param contentRect The content rectangle. Must fit in the page.
              */
-            public Builder setContentSize(Rect contentSize) {
-                Rect pageSize = mPageInfo.mPageSize;
-                if (contentSize != null && (pageSize.left > contentSize.left
-                        || pageSize.top > contentSize.top
-                        || pageSize.right < contentSize.right
-                        || pageSize.bottom < contentSize.bottom)) {
-                    throw new IllegalArgumentException("contentSize does not fit the pageSize!");
+            public Builder setContentRect(Rect contentRect) {
+                if (contentRect != null && (contentRect.left < 0
+                        || contentRect.top < 0
+                        || contentRect.right > mPageInfo.mPageWidth
+                        || contentRect.bottom > mPageInfo.mPageHeight)) {
+                    throw new IllegalArgumentException("contentRect does not fit the page");
                 }
-                mPageInfo.mContentSize = contentSize;
-                return this;
-            }
-
-            /**
-             * Sets the initial transform which is applied to the page. This may be
-             * useful to move the origin to account for a margin, apply scale, or
-             * apply a rotation.
-             *
-             * @param transform The initial transform.
-             */
-            public Builder setInitialTransform(Matrix transform) {
-                mPageInfo.mInitialTransform = transform;
+                mPageInfo.mContentRect = contentRect;
                 return this;
             }
 
@@ -352,11 +357,9 @@
              * @return The new instance.
              */
             public PageInfo create() {
-                if (mPageInfo.mContentSize == null) {
-                    mPageInfo.mContentSize = mPageInfo.mPageSize;
-                }
-                if (mPageInfo.mInitialTransform == null) {
-                    mPageInfo.mInitialTransform = new Matrix();
+                if (mPageInfo.mContentRect == null) {
+                    mPageInfo.mContentRect = new Rect(0, 0,
+                            mPageInfo.mPageWidth, mPageInfo.mPageHeight);
                 }
                 return mPageInfo;
             }
@@ -367,7 +370,8 @@
      * This class represents a PDF document page. It has associated
      * a canvas on which you can draw content and is acquired by a
      * call to {@link #getCanvas()}. It also has associated a
-     * {@link PageInfo} instance that describes its attributes.
+     * {@link PageInfo} instance that describes its attributes. Also
+     * a page has 
      */
     public static final class Page {
         private final PageInfo mPageInfo;
@@ -406,6 +410,10 @@
             return mPageInfo;
         }
 
+        boolean isFinished() {
+            return mCanvas == null;
+        }
+
         private void finish() {
             if (mCanvas != null) {
                 mCanvas.release();
diff --git a/graphics/java/android/graphics/pdf/package.html b/graphics/java/android/graphics/pdf/package.html
new file mode 100644
index 0000000..51f2460
--- /dev/null
+++ b/graphics/java/android/graphics/pdf/package.html
@@ -0,0 +1,5 @@
+<HTML>
+<BODY>
+Contains classes for manipulation of PDF content.
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index 34e87cc..af1c60e 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -358,7 +358,7 @@
                 PrintSpoolerService.peekInstance().setPrintJobAttributesNoPersistence(
                         mPrintJobId, mCurrPrintAttributes);
 
-                mMetadata.putBoolean(PrintDocumentAdapter.METADATA_KEY_PRINT_PREVIEW,
+                mMetadata.putBoolean(PrintDocumentAdapter.EXTRA_PRINT_PREVIEW,
                         !mEditor.isPrintConfirmed());
 
                 mControllerState = CONTROLLER_STATE_LAYOUT_STARTED;