Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d26d4898 authored by Svetoslav Ganov's avatar Svetoslav Ganov
Browse files

Print spooler security and some new print service facing APIs.

1. Updated the security mode of the print spooler. Now the spooler
   is not signed with the system key, it is not a privileged app so if
   it gets compromised (PDF rendering is a potential attack vector)
   it cannot access dangerous permissions. Also only the system
   can bind to the spooler.

2. Added APIs for asking a print service to start and stop tracking
   a given printer. This is need for the case when the user selects
   the printer and the print service should do a best effort to keep
   the system updated for the current state of the printer.

3. Added APIs for putting a print job in a blocked state. A print
   service would report the print job as blocked if for some reason
   the printer cannot proceed, e.g. 99 pages are printed but there
   is no paper for the last one. The user has to add more paper
   and the print service can resume the job.

4. Changed the read/write APIs to use ParcelFileDescriptor instead
   of FileDescriptor since the latter does not have a clean API for
   detaching the wrapped Linux file descriptor when one wants to
   push it to native.

5. Added API for getting the size of the printed document so the
   print service can avoid handling big filed over cellular network
   or ask the user if needed.

6. Now the print services that are preinstalled on the system image
   are automatically enabled.

Change-Id: Ia06c311d3d21cabb9e1368f13928e11cd0030918
parent 7be3a138
Loading
Loading
Loading
Loading
+14 −7
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ package android {
    field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
    field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
    field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
    field public static final java.lang.String BIND_PRINT_SPOOLER_SERVICE = "android.permission.BIND_PRINT_SPOOLER_SERVICE";
    field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
    field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
    field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
@@ -19142,7 +19143,7 @@ package android.print {
    method public void onFinish();
    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[], java.io.FileDescriptor, android.os.CancellationSignal, android.print.PrintDocumentAdapter.WriteResultCallback);
    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";
  }
@@ -19162,6 +19163,7 @@ package android.print {
    method public int describeContents();
    method public int getColorMode();
    method public int getContentType();
    method public long getDataSize();
    method public int getFittingMode();
    method public android.print.PrintAttributes.Margins getMargins();
    method public android.print.PrintAttributes.MediaSize getMediaSize();
@@ -19193,7 +19195,7 @@ package android.print {
  public class PrintFileDocumentAdapter extends android.print.PrintDocumentAdapter {
    ctor public PrintFileDocumentAdapter(android.content.Context, java.io.File, android.print.PrintDocumentInfo);
    method public void onLayout(android.print.PrintAttributes, android.print.PrintAttributes, android.os.CancellationSignal, android.print.PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle);
    method public void onWrite(android.print.PageRange[], java.io.FileDescriptor, android.os.CancellationSignal, android.print.PrintDocumentAdapter.WriteResultCallback);
    method public void onWrite(android.print.PageRange[], android.os.ParcelFileDescriptor, android.os.CancellationSignal, android.print.PrintDocumentAdapter.WriteResultCallback);
  }
  public final class PrintJob {
@@ -19215,9 +19217,10 @@ package android.print {
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator CREATOR;
    field public static final int PRINT_JOB_ID_UNDEFINED = -1; // 0xffffffff
    field public static final int STATE_CANCELED = 6; // 0x6
    field public static final int STATE_COMPLETED = 4; // 0x4
    field public static final int STATE_FAILED = 5; // 0x5
    field public static final int STATE_BLOCKED = 4; // 0x4
    field public static final int STATE_CANCELED = 7; // 0x7
    field public static final int STATE_COMPLETED = 5; // 0x5
    field public static final int STATE_FAILED = 6; // 0x6
    field public static final int STATE_QUEUED = 2; // 0x2
    field public static final int STATE_STARTED = 3; // 0x3
  }
@@ -19335,17 +19338,19 @@ package android.print.pdf {
package android.printservice {
  public final class PrintDocument {
    method public java.io.FileDescriptor getData();
    method public android.os.ParcelFileDescriptor getData();
    method public android.print.PrintDocumentInfo getInfo();
  }
  public final class PrintJob {
    method public boolean block(java.lang.String);
    method public boolean cancel();
    method public boolean complete();
    method public boolean fail(java.lang.String);
    method public android.printservice.PrintDocument getDocument();
    method public int getId();
    method public android.print.PrintJobInfo getInfo();
    method public boolean isBlocked();
    method public boolean isCancelled();
    method public boolean isCompleted();
    method public boolean isFailed();
@@ -19377,9 +19382,11 @@ package android.printservice {
    method public final boolean isDestroyed();
    method public final boolean isPrinterDiscoveryStarted();
    method public abstract void onDestroy();
    method public abstract void onRequestPrinterUpdate(android.print.PrinterId);
    method public abstract void onStartPrinterDiscovery(java.util.List<android.print.PrinterId>);
    method public abstract void onStartPrinterStateTracking(android.print.PrinterId);
    method public abstract void onStopPrinterDiscovery();
    method public abstract void onStopPrinterStateTracking(android.print.PrinterId);
    method public abstract void onValidatePrinters(java.util.List<android.print.PrinterId>);
    method public final void removePrinters(java.util.List<android.print.PrinterId>);
    method public final void updatePrinters(java.util.List<android.print.PrinterInfo>);
  }
+3 −1
Original line number Diff line number Diff line
@@ -41,7 +41,9 @@ interface IPrintManager {
    void startPrinterDiscovery(in IPrinterDiscoveryObserver observer,
            in List<PrinterId> priorityList, int userId);
    void stopPrinterDiscovery(in IPrinterDiscoveryObserver observer, int userId);
    void requestPrinterUpdate(in PrinterId printerId, int userId);
    void validatePrinters(in List<PrinterId> printerIds, int userId);
    void startPrinterStateTracking(in PrinterId printerId, int userId);
    void stopPrinterStateTracking(in PrinterId printerId, int userId);
    void destroyPrinterDiscoverySession(in IPrinterDiscoveryObserver observer,
            int userId);
}
+9 −9
Original line number Diff line number Diff line
@@ -18,8 +18,8 @@ package android.print;

import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;

import java.io.FileDescriptor;
import java.util.List;

/**
@@ -41,7 +41,7 @@ import java.util.List;
 * <li>
 * After every call to {@link #onLayout(PrintAttributes, PrintAttributes,
 * CancellationSignal, LayoutResultCallback, Bundle)}, you may get a call to
 * {@link #onWrite(PageRange[], FileDescriptor, CancellationSignal, WriteResultCallback)}
 * {@link #onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal, WriteResultCallback)}
 * asking you to write a PDF file with the content for specific pages.
 * </li>
 * <li>
@@ -64,7 +64,7 @@ import java.util.List;
 * 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[], FileDescriptor,
 * printed content. Then you can handle {@link #onWrite(PageRange[], ParcelFileDescriptor,
 * CancellationSignal, WriteResultCallback)} and {@link #onFinish()} on another
 * thread. This will ensure that the UI is frozen for the minimal amount of
 * time. Also this assumes that you will generate the printed content in
@@ -150,10 +150,10 @@ public abstract class PrintDocumentAdapter {
     * from 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 <strong>not</strong> close the
     * file descriptor, rather you must invoke: {@link WriteResultCallback
     * #onWriteFinished(List)}, if writing completed successfully; or {@link
     * WriteResultCallback#onWriteFailed(CharSequence)}, if an error occurred.
     * After you are done writing, you should close the file descriptor and
     * invoke {@link WriteResultCallback #onWriteFinished(List)}, if writing
     * completed successfully; or {@link WriteResultCallback#onWriteFailed(
     * CharSequence)}, if an error occurred.
     * </p>
     * <p>
     * <strong>Note:</strong> If the printed content is large, it is a good
@@ -171,7 +171,7 @@ public abstract class PrintDocumentAdapter {
     * @see WriteResultCallback
     * @see CancellationSignal
     */
    public abstract void onWrite(PageRange[] pages, FileDescriptor destination,
    public abstract void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
            CancellationSignal cancellationSignal, WriteResultCallback callback);

    /**
@@ -185,7 +185,7 @@ public abstract class PrintDocumentAdapter {

    /**
     * Base class for implementing a callback for the result of {@link
     * PrintDocumentAdapter#onWrite(PageRange[], FileDescriptor, CancellationSignal,
     * PrintDocumentAdapter#onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal,
     * WriteResultCallback)}.
     */
    public static abstract class WriteResultCallback {
+30 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ public final class PrintDocumentInfo implements Parcelable {
    private int mColorMode;
    private Margins mMargins;
    private MediaSize mMediaSize;
    private long mDataSize;

    /**
     * Creates a new instance.
@@ -82,6 +83,7 @@ public final class PrintDocumentInfo implements Parcelable {
        mColorMode = prototype.mColorMode;
        mMargins = prototype.mMargins;
        mMediaSize = prototype.mMediaSize;
        mDataSize = prototype.mDataSize;
    }

    /**
@@ -98,6 +100,7 @@ public final class PrintDocumentInfo implements Parcelable {
        mColorMode = parcel.readInt();
        mMargins = Margins.createFromParcel(parcel);
        mMediaSize = MediaSize.createFromParcel(parcel);
        mDataSize = parcel.readLong();
    }

    /**
@@ -188,6 +191,26 @@ public final class PrintDocumentInfo implements Parcelable {
        return mMediaSize;
    }

    /**
     * Gets the document data size in bytes.
     *
     * @return The data size.
     */
    public long getDataSize() {
        return mDataSize;
    }

    /**
     * Sets the document data size in bytes.
     *
     * @param dataSize The data size.
     *
     * @hide
     */
    public void setDataSize(long dataSize) {
        mDataSize = dataSize;
    }

    @Override
    public int describeContents() {
        return 0;
@@ -203,6 +226,7 @@ public final class PrintDocumentInfo implements Parcelable {
        parcel.writeInt(mColorMode);
        mMargins.writeToParcel(parcel);
        mMediaSize.writeToParcel(parcel);
        parcel.writeLong(mDataSize);
    }

    @Override
@@ -217,6 +241,8 @@ public final class PrintDocumentInfo implements Parcelable {
        result = prime * result + mColorMode;
        result = prime * result + (mMargins != null ? mMargins.hashCode() : 0);
        result = prime * result + (mMediaSize != null ? mMediaSize.hashCode() : 0);
        result = prime * result + (int) mDataSize;
        result = prime * result + (int) mDataSize >> 32;
        return result;
    }

@@ -264,6 +290,9 @@ public final class PrintDocumentInfo implements Parcelable {
        } else if (!mMediaSize.equals(other.mMediaSize)) {
            return false;
        }
        if (mDataSize != other.mDataSize) {
            return false;
        }
        return true;
    }

@@ -279,6 +308,7 @@ public final class PrintDocumentInfo implements Parcelable {
        builder.append(", colorMode=").append(PrintAttributes.colorModeToString(mColorMode));
        builder.append(", margins=").append(mMargins);
        builder.append(", mediaSize=").append(mMediaSize);
        builder.append(", size=").append(mDataSize);
        builder.append("}");
        return builder.toString();
    }
+5 −5
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.CancellationSignal.OnCancelListener;
import android.os.ParcelFileDescriptor;
import android.util.Log;

import com.android.internal.R;
@@ -28,7 +29,6 @@ import com.android.internal.R;
import libcore.io.IoUtils;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -81,7 +81,7 @@ public class PrintFileDocumentAdapter extends PrintDocumentAdapter {
    }

    @Override
    public void onWrite(PageRange[] pages, FileDescriptor destination,
    public void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
            CancellationSignal cancellationSignal, WriteResultCallback callback) {
        mWriteFileAsyncTask = new WriteFileAsyncTask(destination, cancellationSignal, callback);
        mWriteFileAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
@@ -90,13 +90,13 @@ public class PrintFileDocumentAdapter extends PrintDocumentAdapter {

    private final class WriteFileAsyncTask extends AsyncTask<Void, Void, Void> {

        private final FileDescriptor mDestination;
        private final ParcelFileDescriptor mDestination;

        private final WriteResultCallback mResultCallback;

        private final CancellationSignal mCancellationSignal;

        public WriteFileAsyncTask(FileDescriptor destination,
        public WriteFileAsyncTask(ParcelFileDescriptor destination,
                CancellationSignal cancellationSignal, WriteResultCallback callback) {
            mDestination = destination;
            mResultCallback = callback;
@@ -112,7 +112,7 @@ public class PrintFileDocumentAdapter extends PrintDocumentAdapter {
        @Override
        protected Void doInBackground(Void... params) {
            InputStream in = null;
            OutputStream out = new FileOutputStream(mDestination);
            OutputStream out = new FileOutputStream(mDestination.getFileDescriptor());
            final byte[] buffer = new byte[8192];
            try {
                in = new FileInputStream(mFile);
Loading