/* * 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.printservice; import java.io.FileDescriptor; import java.io.IOException; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.print.PrintJobInfo; import android.util.Log; /** * This class represents a print job from the perspective of a * print service. It provides APIs for observing the print job * state and performing operations on the print job. */ public final class PrintJob { private static final String LOG_TAG = "PrintJob"; private final int mId; private final IPrintServiceClient mPrintServiceClient; private PrintJobInfo mCachedInfo; PrintJob(PrintJobInfo info, IPrintServiceClient client) { if (client == null) { throw new IllegalStateException("Print serivice not connected!"); } mCachedInfo = info; mId = info.getId(); mPrintServiceClient = client; } /** * Gets the unique print job id. * * @return The id. */ public int getId() { return mId; } /** * Gets the {@link PrintJobInfo} that describes this job. *
* Node:The returned info object is a snapshot of the * current print job state. Every call to this method returns a fresh * info object that reflects the current print jobs state. *
* * @return The print job info. */ public PrintJobInfo getInfo() { PrintJobInfo info = null; try { info = mPrintServiceClient.getPrintJob(mId); } catch (RemoteException re) { Log.e(LOG_TAG, "Couldn't get info for job: " + mId, re); } if (info != null) { mCachedInfo = info; } return mCachedInfo; } /** * Gets whether this print job is queued. Such a print job is * ready to be printed and can be started. * * @return Whether the print job is queued. * * @see #start() */ public boolean isQueued() { return getInfo().getState() == PrintJobInfo.STATE_QUEUED; } /** * Gets whether this print job is started. Such a print job is * being printed and can be completed or canceled or failed. * * @return Whether the print job is started. * * @see #complete() * @see #cancel() * @see #fail() */ public boolean isStarted() { return getInfo().getState() == PrintJobInfo.STATE_STARTED; } /** * Starts the print job. You should call this method if {@link * #isQueued()} returns true and you started printing. * * @return Whether the job as started. * * @see #isQueued() */ public boolean start() { if (isQueued()) { return setState(PrintJobInfo.STATE_STARTED); } return false; } /** * Completes the print job. You should call this method if {@link * #isStarted()} returns true and you are done printing. * * @return Whether the job as completed. * * @see #isStarted() */ public boolean complete() { if (isStarted()) { return setState(PrintJobInfo.STATE_COMPLETED); } return false; } /** * Fails the print job. You should call this method if {@link * #isStarted()} returns true you filed while printing. * * @return Whether the job as failed. * * @see #isStarted() */ public boolean fail(CharSequence error) { // TODO: Propagate the error message to the UI. if (isStarted()) { return setState(PrintJobInfo.STATE_FAILED); } return false; } /** * Cancels the print job. You should call this method if {@link * #isStarted()} returns true and you canceled the print job as a * response to a call to {@link PrintService#onRequestCancelPrintJob( * PrintJob)}. * * @return Whether the job as canceled. * * @see #isStarted() */ public boolean cancel() { if (isStarted()) { return setState(PrintJobInfo.STATE_CANCELED); } return false; } /** * Sets a tag that is valid in the context of a {@link PrintService} * and is not interpreted by the system. For example, a print service * may set as a tag the key of the print job returned by a remote * print server, if the printing is off handed to a cloud based service. * * @param tag The tag. * @return True if the tag was set, false otherwise. */ public boolean setTag(String tag) { try { return mPrintServiceClient.setPrintJobTag(mId, tag); } catch (RemoteException re) { Log.e(LOG_TAG, "Error setting tag for job:" + mId, re); } return false; } /** * Gets the data associated with this print job. It is a responsibility of * the print service to open a stream to the returned file descriptor * and fully read the content. * * @return A file descriptor for reading the data ornull
.
*/
public final FileDescriptor getData() {
ParcelFileDescriptor source = null;
ParcelFileDescriptor sink = null;
try {
ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
source = fds[0];
sink = fds[1];
mPrintServiceClient.writePrintJobData(sink, mId);
return source.getFileDescriptor();
} catch (IOException ioe) {
Log.e(LOG_TAG, "Error calling getting print job data!", ioe);
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error calling getting print job data!", re);
} finally {
if (sink != null) {
try {
sink.close();
} catch (IOException ioe) {
/* ignore */
}
}
}
return null;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
PrintJob other = (PrintJob) obj;
return (mId == other.mId);
}
@Override
public int hashCode() {
return mId;
}
private boolean setState(int state) {
// Best effort - update the state of the cached info since
// we may not be able to re-fetch it later if the job gets
// removed from the spooler.
mCachedInfo.setState(state);
try {
return mPrintServiceClient.setPrintJobState(mId, state);
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error setting the state of job:" + mId, re);
}
return false;
}
}