PrintJob.java revision 4b9a4d16872bbb50712e007b419ac0b35ff1582d
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.printservice; 18 19import java.io.FileDescriptor; 20import java.io.IOException; 21 22import android.os.ParcelFileDescriptor; 23import android.os.RemoteException; 24import android.print.PrintJobInfo; 25import android.util.Log; 26 27/** 28 * This class represents a print job from the perspective of a 29 * print service. It provides APIs for observing the print job 30 * state and performing operations on the print job. 31 */ 32public final class PrintJob { 33 34 private static final String LOG_TAG = "PrintJob"; 35 36 private final int mId; 37 38 private final IPrintServiceClient mPrintServiceClient; 39 40 private PrintJobInfo mCachedInfo; 41 42 PrintJob(PrintJobInfo info, IPrintServiceClient client) { 43 if (client == null) { 44 throw new IllegalStateException("Print serivice not connected!"); 45 } 46 mCachedInfo = info; 47 mId = info.getId(); 48 mPrintServiceClient = client; 49 } 50 51 /** 52 * Gets the unique print job id. 53 * 54 * @return The id. 55 */ 56 public int getId() { 57 return mId; 58 } 59 60 /** 61 * Gets the {@link PrintJobInfo} that describes this job. 62 * <p> 63 * <strong>Node:</strong>The returned info object is a snapshot of the 64 * current print job state. Every call to this method returns a fresh 65 * info object that reflects the current print jobs state. 66 * </p> 67 * 68 * @return The print job info. 69 */ 70 public PrintJobInfo getInfo() { 71 PrintJobInfo info = null; 72 try { 73 info = mPrintServiceClient.getPrintJob(mId); 74 } catch (RemoteException re) { 75 Log.e(LOG_TAG, "Couldn't get info for job: " + mId, re); 76 } 77 if (info != null) { 78 mCachedInfo = info; 79 } 80 return mCachedInfo; 81 } 82 83 /** 84 * Gets whether this print job is queued. Such a print job is 85 * ready to be printed and can be started. 86 * 87 * @return Whether the print job is queued. 88 * 89 * @see #start() 90 */ 91 public boolean isQueued() { 92 return getInfo().getState() == PrintJobInfo.STATE_QUEUED; 93 } 94 95 /** 96 * Gets whether this print job is started. Such a print job is 97 * being printed and can be completed or canceled or failed. 98 * 99 * @return Whether the print job is started. 100 * 101 * @see #complete() 102 * @see #cancel() 103 * @see #fail() 104 */ 105 public boolean isStarted() { 106 return getInfo().getState() == PrintJobInfo.STATE_STARTED; 107 } 108 109 /** 110 * Starts the print job. You should call this method if {@link 111 * #isQueued()} returns true and you started printing. 112 * 113 * @return Whether the job as started. 114 * 115 * @see #isQueued() 116 */ 117 public boolean start() { 118 if (isQueued()) { 119 return setState(PrintJobInfo.STATE_STARTED); 120 } 121 return false; 122 } 123 124 /** 125 * Completes the print job. You should call this method if {@link 126 * #isStarted()} returns true and you are done printing. 127 * 128 * @return Whether the job as completed. 129 * 130 * @see #isStarted() 131 */ 132 public boolean complete() { 133 if (isStarted()) { 134 return setState(PrintJobInfo.STATE_COMPLETED); 135 } 136 return false; 137 } 138 139 /** 140 * Fails the print job. You should call this method if {@link 141 * #isStarted()} returns true you filed while printing. 142 * 143 * @return Whether the job as failed. 144 * 145 * @see #isStarted() 146 */ 147 public boolean fail(CharSequence error) { 148 // TODO: Propagate the error message to the UI. 149 if (isStarted()) { 150 return setState(PrintJobInfo.STATE_FAILED); 151 } 152 return false; 153 } 154 155 /** 156 * Cancels the print job. You should call this method if {@link 157 * #isStarted()} returns true and you canceled the print job as a 158 * response to a call to {@link PrintService#onRequestCancelPrintJob( 159 * PrintJob)}. 160 * 161 * @return Whether the job as canceled. 162 * 163 * @see #isStarted() 164 */ 165 public boolean cancel() { 166 if (isStarted()) { 167 return setState(PrintJobInfo.STATE_CANCELED); 168 } 169 return false; 170 } 171 172 /** 173 * Sets a tag that is valid in the context of a {@link PrintService} 174 * and is not interpreted by the system. For example, a print service 175 * may set as a tag the key of the print job returned by a remote 176 * print server, if the printing is off handed to a cloud based service. 177 * 178 * @param tag The tag. 179 * @return True if the tag was set, false otherwise. 180 */ 181 public boolean setTag(String tag) { 182 try { 183 return mPrintServiceClient.setPrintJobTag(mId, tag); 184 } catch (RemoteException re) { 185 Log.e(LOG_TAG, "Error setting tag for job:" + mId, re); 186 } 187 return false; 188 } 189 190 /** 191 * Gets the data associated with this print job. It is a responsibility of 192 * the print service to open a stream to the returned file descriptor 193 * and fully read the content. 194 * 195 * @return A file descriptor for reading the data or <code>null</code>. 196 */ 197 public final FileDescriptor getData() { 198 ParcelFileDescriptor source = null; 199 ParcelFileDescriptor sink = null; 200 try { 201 ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe(); 202 source = fds[0]; 203 sink = fds[1]; 204 mPrintServiceClient.writePrintJobData(sink, mId); 205 return source.getFileDescriptor(); 206 } catch (IOException ioe) { 207 Log.e(LOG_TAG, "Error calling getting print job data!", ioe); 208 } catch (RemoteException re) { 209 Log.e(LOG_TAG, "Error calling getting print job data!", re); 210 } finally { 211 if (sink != null) { 212 try { 213 sink.close(); 214 } catch (IOException ioe) { 215 /* ignore */ 216 } 217 } 218 } 219 return null; 220 } 221 222 @Override 223 public boolean equals(Object obj) { 224 if (this == obj) { 225 return true; 226 } 227 if (obj == null) { 228 return false; 229 } 230 if (getClass() != obj.getClass()) { 231 return false; 232 } 233 PrintJob other = (PrintJob) obj; 234 return (mId == other.mId); 235 } 236 237 @Override 238 public int hashCode() { 239 return mId; 240 } 241 242 private boolean setState(int state) { 243 // Best effort - update the state of the cached info since 244 // we may not be able to re-fetch it later if the job gets 245 // removed from the spooler. 246 mCachedInfo.setState(state); 247 try { 248 return mPrintServiceClient.setPrintJobState(mId, state); 249 } catch (RemoteException re) { 250 Log.e(LOG_TAG, "Error setting the state of job:" + mId, re); 251 } 252 return false; 253 } 254} 255