PrintJob.java revision fd90651cfcc7e2b75254666fd6861038b72fb4ac
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 job 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(CharSequence) 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 * @param error The reason for the failure. 144 * @return Whether the job was failed. 145 * 146 * @see #isStarted() 147 */ 148 public boolean fail(CharSequence error) { 149 // TODO: Propagate the error message to the UI. 150 if (isStarted()) { 151 return setState(PrintJobInfo.STATE_FAILED); 152 } 153 return false; 154 } 155 156 /** 157 * Cancels the print job. You should call this method if {@link 158 * #isStarted()} returns true and you canceled the print job as a 159 * response to a call to {@link PrintService#onRequestCancelPrintJob( 160 * PrintJob)}. 161 * 162 * @return Whether the job as canceled. 163 * 164 * @see #isStarted() 165 */ 166 public boolean cancel() { 167 if (isStarted()) { 168 return setState(PrintJobInfo.STATE_CANCELED); 169 } 170 return false; 171 } 172 173 /** 174 * Sets a tag that is valid in the context of a {@link PrintService} 175 * and is not interpreted by the system. For example, a print service 176 * may set as a tag the key of the print job returned by a remote 177 * print server, if the printing is off handed to a cloud based service. 178 * 179 * @param tag The tag. 180 * @return True if the tag was set, false otherwise. 181 */ 182 public boolean setTag(String tag) { 183 try { 184 return mPrintServiceClient.setPrintJobTag(mId, tag); 185 } catch (RemoteException re) { 186 Log.e(LOG_TAG, "Error setting tag for job:" + mId, re); 187 } 188 return false; 189 } 190 191 /** 192 * Gets the data associated with this print job. It is a responsibility of 193 * the print service to open a stream to the returned file descriptor 194 * and fully read the content. 195 * <p> 196 * <strong>Note:</strong> It is your responsibility to close the file descriptor. 197 * </p> 198 * 199 * @return A file descriptor for reading the data or <code>null</code>. 200 */ 201 public final FileDescriptor getData() { 202 ParcelFileDescriptor source = null; 203 ParcelFileDescriptor sink = null; 204 try { 205 ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe(); 206 source = fds[0]; 207 sink = fds[1]; 208 mPrintServiceClient.writePrintJobData(sink, mId); 209 return source.getFileDescriptor(); 210 } catch (IOException ioe) { 211 Log.e(LOG_TAG, "Error calling getting print job data!", ioe); 212 } catch (RemoteException re) { 213 Log.e(LOG_TAG, "Error calling getting print job data!", re); 214 } finally { 215 if (sink != null) { 216 try { 217 sink.close(); 218 } catch (IOException ioe) { 219 /* ignore */ 220 } 221 } 222 } 223 return null; 224 } 225 226 @Override 227 public boolean equals(Object obj) { 228 if (this == obj) { 229 return true; 230 } 231 if (obj == null) { 232 return false; 233 } 234 if (getClass() != obj.getClass()) { 235 return false; 236 } 237 PrintJob other = (PrintJob) obj; 238 return (mId == other.mId); 239 } 240 241 @Override 242 public int hashCode() { 243 return mId; 244 } 245 246 private boolean setState(int state) { 247 // Best effort - update the state of the cached info since 248 // we may not be able to re-fetch it later if the job gets 249 // removed from the spooler. 250 mCachedInfo.setState(state); 251 try { 252 return mPrintServiceClient.setPrintJobState(mId, state); 253 } catch (RemoteException re) { 254 Log.e(LOG_TAG, "Error setting the state of job:" + mId, re); 255 } 256 return false; 257 } 258} 259