PrintJob.java revision 269403b032f965ff3847eb982c2f697229dc5a92
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 android.os.RemoteException; 20import android.print.PrintJobInfo; 21import android.util.Log; 22 23/** 24 * This class represents a print job from the perspective of a print 25 * service. It provides APIs for observing the print job state and 26 * performing operations on the print job. 27 * <p> 28 * <strong>Note: </strong> All methods of this class must be executed on the main 29 * application thread. 30 * </p> 31 */ 32public final class PrintJob { 33 34 private static final String LOG_TAG = "PrintJob"; 35 36 private final IPrintServiceClient mPrintServiceClient; 37 38 private final PrintDocument mDocument; 39 40 private PrintJobInfo mCachedInfo; 41 42 PrintJob(PrintJobInfo jobInfo, IPrintServiceClient client) { 43 mCachedInfo = jobInfo; 44 mPrintServiceClient = client; 45 mDocument = new PrintDocument(mCachedInfo.getId(), client, 46 jobInfo.getDocumentInfo()); 47 } 48 49 /** 50 * Gets the unique print job id. 51 * 52 * @return The id. 53 */ 54 public int getId() { 55 PrintService.throwIfNotCalledOnMainThread(); 56 return mCachedInfo.getId(); 57 } 58 59 /** 60 * Gets the {@link PrintJobInfo} that describes this job. 61 * <p> 62 * <strong>Node:</strong>The returned info object is a snapshot of the 63 * current print job state. Every call to this method returns a fresh 64 * info object that reflects the current print job state. 65 * </p> 66 * 67 * @return The print job info. 68 */ 69 public PrintJobInfo getInfo() { 70 PrintService.throwIfNotCalledOnMainThread(); 71 if (isInImmutableState()) { 72 return mCachedInfo; 73 } 74 PrintJobInfo info = null; 75 try { 76 info = mPrintServiceClient.getPrintJobInfo(mCachedInfo.getId()); 77 } catch (RemoteException re) { 78 Log.e(LOG_TAG, "Couldn't get info for job: " + mCachedInfo.getId(), re); 79 } 80 if (info != null) { 81 mCachedInfo = info; 82 } 83 return mCachedInfo; 84 } 85 86 /** 87 * Gets the printed document. 88 * 89 * @return The document. 90 */ 91 public PrintDocument getDocument() { 92 PrintService.throwIfNotCalledOnMainThread(); 93 return mDocument; 94 } 95 96 /** 97 * Gets whether this print job is queued. Such a print job is 98 * ready to be printed and can be started or cancelled. 99 * 100 * @return Whether the print job is queued. 101 * 102 * @see #start() 103 * @see #cancel() 104 */ 105 public boolean isQueued() { 106 PrintService.throwIfNotCalledOnMainThread(); 107 return getInfo().getState() == PrintJobInfo.STATE_QUEUED; 108 } 109 110 /** 111 * Gets whether this print job is started. Such a print job is 112 * being printed and can be completed or canceled or failed. 113 * 114 * @return Whether the print job is started. 115 * 116 * @see #complete() 117 * @see #cancel() 118 * @see #fail(CharSequence) 119 */ 120 public boolean isStarted() { 121 PrintService.throwIfNotCalledOnMainThread(); 122 return getInfo().getState() == PrintJobInfo.STATE_STARTED; 123 } 124 125 /** 126 * Gets whether this print job is completed. Such a print job 127 * is successfully printed. This is a final state. 128 * 129 * @return Whether the print job is completed. 130 * 131 * @see #complete() 132 */ 133 public boolean isCompleted() { 134 PrintService.throwIfNotCalledOnMainThread(); 135 return getInfo().getState() == PrintJobInfo.STATE_COMPLETED; 136 } 137 138 /** 139 * Gets whether this print job is failed. Such a print job is 140 * not successfully printed due to an error. This is a final state. 141 * 142 * @return Whether the print job is failed. 143 * 144 * @see #fail(CharSequence) 145 */ 146 public boolean isFailed() { 147 PrintService.throwIfNotCalledOnMainThread(); 148 return getInfo().getState() == PrintJobInfo.STATE_FAILED; 149 } 150 151 /** 152 * Gets whether this print job is cancelled. Such a print job was 153 * cancelled as a result of a user request. This is a final state. 154 * 155 * @return Whether the print job is cancelled. 156 * 157 * @see #cancel() 158 */ 159 public boolean isCancelled() { 160 PrintService.throwIfNotCalledOnMainThread(); 161 return getInfo().getState() == PrintJobInfo.STATE_FAILED; 162 } 163 164 /** 165 * Starts the print job. You should call this method if {@link 166 * #isQueued()} returns true and you started printing. 167 * 168 * @return Whether the job as started. 169 * 170 * @see #isQueued() 171 */ 172 public boolean start() { 173 PrintService.throwIfNotCalledOnMainThread(); 174 if (isQueued()) { 175 return setState(PrintJobInfo.STATE_STARTED, null); 176 } 177 return false; 178 } 179 180 /** 181 * Completes the print job. You should call this method if {@link 182 * #isStarted()} returns true and you are done printing. 183 * 184 * @return Whether the job as completed. 185 * 186 * @see #isStarted() 187 */ 188 public boolean complete() { 189 PrintService.throwIfNotCalledOnMainThread(); 190 if (isStarted()) { 191 return setState(PrintJobInfo.STATE_COMPLETED, null); 192 } 193 return false; 194 } 195 196 /** 197 * Fails the print job. You should call this method if {@link 198 * #isQueued()} or {@link #isStarted()} returns true you failed 199 * while printing. 200 * 201 * @param error The human readable, short, and translated reason 202 * for the failure. 203 * @return Whether the job was failed. 204 * 205 * @see #isQueued() 206 * @see #isStarted() 207 */ 208 public boolean fail(String error) { 209 PrintService.throwIfNotCalledOnMainThread(); 210 if (isQueued() || isStarted()) { 211 return setState(PrintJobInfo.STATE_FAILED, error); 212 } 213 return false; 214 } 215 216 /** 217 * Cancels the print job. You should call this method if {@link 218 * #isQueued()} or {@link #isStarted()} returns true and you canceled 219 * the print job as a response to a call to {@link 220 * PrintService#onRequestCancelPrintJob(PrintJob)}. 221 * 222 * @return Whether the job is canceled. 223 * 224 * @see #isStarted() 225 * @see #isQueued() 226 */ 227 public boolean cancel() { 228 PrintService.throwIfNotCalledOnMainThread(); 229 if (isQueued() || isStarted()) { 230 return setState(PrintJobInfo.STATE_CANCELED, null); 231 } 232 return false; 233 } 234 235 /** 236 * Sets a tag that is valid in the context of a {@link PrintService} 237 * and is not interpreted by the system. For example, a print service 238 * may set as a tag the key of the print job returned by a remote 239 * print server, if the printing is off handed to a cloud based service. 240 * 241 * @param tag The tag. 242 * @return True if the tag was set, false otherwise. 243 */ 244 public boolean setTag(String tag) { 245 PrintService.throwIfNotCalledOnMainThread(); 246 if (isInImmutableState()) { 247 return false; 248 } 249 try { 250 return mPrintServiceClient.setPrintJobTag(mCachedInfo.getId(), tag); 251 } catch (RemoteException re) { 252 Log.e(LOG_TAG, "Error setting tag for job: " + mCachedInfo.getId(), re); 253 } 254 return false; 255 } 256 257 @Override 258 public boolean equals(Object obj) { 259 if (this == obj) { 260 return true; 261 } 262 if (obj == null) { 263 return false; 264 } 265 if (getClass() != obj.getClass()) { 266 return false; 267 } 268 PrintJob other = (PrintJob) obj; 269 return (mCachedInfo.getId() == other.mCachedInfo.getId()); 270 } 271 272 @Override 273 public int hashCode() { 274 return mCachedInfo.getId(); 275 } 276 277 private boolean isInImmutableState() { 278 final int state = mCachedInfo.getState(); 279 return state == PrintJobInfo.STATE_COMPLETED 280 || state == PrintJobInfo.STATE_CANCELED; 281 } 282 283 private boolean setState(int state, String error) { 284 try { 285 if (mPrintServiceClient.setPrintJobState(mCachedInfo.getId(), state, error)) { 286 // Best effort - update the state of the cached info since 287 // we may not be able to re-fetch it later if the job gets 288 // removed from the spooler as a result of the state change. 289 mCachedInfo.setState(state); 290 mCachedInfo.setFailureReason(error); 291 return true; 292 } 293 } catch (RemoteException re) { 294 Log.e(LOG_TAG, "Error setting the state of job: " + mCachedInfo.getId(), re); 295 } 296 return false; 297 } 298} 299