blob: d2fbef2b578e5321453257348cebba64b41c80be [file] [log] [blame]
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -07001/*
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
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070019import android.os.RemoteException;
20import android.print.PrintJobInfo;
21import android.util.Log;
22
23/**
Svetoslav Ganov798bed62013-08-11 12:29:39 -070024 * 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.
Svetoslav269403b2013-08-14 17:31:04 -070027 * <p>
28 * <strong>Note: </strong> All methods of this class must be executed on the main
29 * application thread.
30 * </p>
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070031 */
32public final class PrintJob {
33
34 private static final String LOG_TAG = "PrintJob";
35
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070036 private final IPrintServiceClient mPrintServiceClient;
37
Svetoslav Ganova0027152013-06-25 14:59:53 -070038 private final PrintDocument mDocument;
39
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070040 private PrintJobInfo mCachedInfo;
41
Svetoslav Ganova0027152013-06-25 14:59:53 -070042 PrintJob(PrintJobInfo jobInfo, IPrintServiceClient client) {
43 mCachedInfo = jobInfo;
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070044 mPrintServiceClient = client;
Svetoslav Ganov798bed62013-08-11 12:29:39 -070045 mDocument = new PrintDocument(mCachedInfo.getId(), client,
46 jobInfo.getDocumentInfo());
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070047 }
48
49 /**
50 * Gets the unique print job id.
51 *
52 * @return The id.
53 */
54 public int getId() {
Svetoslav269403b2013-08-14 17:31:04 -070055 PrintService.throwIfNotCalledOnMainThread();
Svetoslav Ganova0027152013-06-25 14:59:53 -070056 return mCachedInfo.getId();
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070057 }
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
Svetoslavfd906512013-06-24 09:04:48 -070064 * info object that reflects the current print job state.
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070065 * </p>
66 *
67 * @return The print job info.
68 */
69 public PrintJobInfo getInfo() {
Svetoslav269403b2013-08-14 17:31:04 -070070 PrintService.throwIfNotCalledOnMainThread();
Svetoslav Ganov85b1f882013-07-24 17:00:06 -070071 if (isInImmutableState()) {
72 return mCachedInfo;
73 }
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070074 PrintJobInfo info = null;
75 try {
Svetoslav Ganova0027152013-06-25 14:59:53 -070076 info = mPrintServiceClient.getPrintJobInfo(mCachedInfo.getId());
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070077 } catch (RemoteException re) {
Svetoslav Ganova0027152013-06-25 14:59:53 -070078 Log.e(LOG_TAG, "Couldn't get info for job: " + mCachedInfo.getId(), re);
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070079 }
80 if (info != null) {
81 mCachedInfo = info;
82 }
83 return mCachedInfo;
84 }
85
86 /**
Svetoslav Ganov798bed62013-08-11 12:29:39 -070087 * Gets the printed document.
Svetoslav Ganova0027152013-06-25 14:59:53 -070088 *
89 * @return The document.
90 */
91 public PrintDocument getDocument() {
Svetoslav269403b2013-08-14 17:31:04 -070092 PrintService.throwIfNotCalledOnMainThread();
Svetoslav Ganova0027152013-06-25 14:59:53 -070093 return mDocument;
94 }
95
96 /**
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070097 * Gets whether this print job is queued. Such a print job is
Svetoslav Ganov798bed62013-08-11 12:29:39 -070098 * ready to be printed and can be started or cancelled.
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -070099 *
100 * @return Whether the print job is queued.
101 *
102 * @see #start()
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700103 * @see #cancel()
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700104 */
105 public boolean isQueued() {
Svetoslav269403b2013-08-14 17:31:04 -0700106 PrintService.throwIfNotCalledOnMainThread();
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700107 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()
Svetoslavfd906512013-06-24 09:04:48 -0700118 * @see #fail(CharSequence)
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700119 */
120 public boolean isStarted() {
Svetoslav269403b2013-08-14 17:31:04 -0700121 PrintService.throwIfNotCalledOnMainThread();
Svetoslav Ganova0027152013-06-25 14:59:53 -0700122 return getInfo().getState() == PrintJobInfo.STATE_STARTED;
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700123 }
124
125 /**
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700126 * 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() {
Svetoslav269403b2013-08-14 17:31:04 -0700134 PrintService.throwIfNotCalledOnMainThread();
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700135 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() {
Svetoslav269403b2013-08-14 17:31:04 -0700147 PrintService.throwIfNotCalledOnMainThread();
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700148 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() {
Svetoslav269403b2013-08-14 17:31:04 -0700160 PrintService.throwIfNotCalledOnMainThread();
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700161 return getInfo().getState() == PrintJobInfo.STATE_FAILED;
162 }
163
164 /**
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700165 * 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() {
Svetoslav269403b2013-08-14 17:31:04 -0700173 PrintService.throwIfNotCalledOnMainThread();
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700174 if (isQueued()) {
Svetoslav Ganov8c433762013-08-02 14:22:19 -0700175 return setState(PrintJobInfo.STATE_STARTED, null);
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700176 }
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() {
Svetoslav269403b2013-08-14 17:31:04 -0700189 PrintService.throwIfNotCalledOnMainThread();
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700190 if (isStarted()) {
Svetoslav Ganov8c433762013-08-02 14:22:19 -0700191 return setState(PrintJobInfo.STATE_COMPLETED, null);
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700192 }
193 return false;
194 }
195
196 /**
197 * Fails the print job. You should call this method if {@link
Svetoslav Ganov8c433762013-08-02 14:22:19 -0700198 * #isQueued()} or {@link #isStarted()} returns true you failed
199 * while printing.
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700200 *
Svetoslav Ganov8c433762013-08-02 14:22:19 -0700201 * @param error The human readable, short, and translated reason
202 * for the failure.
Svetoslavfd906512013-06-24 09:04:48 -0700203 * @return Whether the job was failed.
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700204 *
Svetoslav Ganov8c433762013-08-02 14:22:19 -0700205 * @see #isQueued()
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700206 * @see #isStarted()
207 */
Svetoslav269403b2013-08-14 17:31:04 -0700208 public boolean fail(String error) {
209 PrintService.throwIfNotCalledOnMainThread();
Svetoslav Ganov8c433762013-08-02 14:22:19 -0700210 if (isQueued() || isStarted()) {
211 return setState(PrintJobInfo.STATE_FAILED, error);
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700212 }
213 return false;
214 }
215
216 /**
217 * Cancels the print job. You should call this method if {@link
Svetoslav Ganov8c433762013-08-02 14:22:19 -0700218 * #isQueued()} or {@link #isStarted()} returns true and you canceled
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700219 * the print job as a response to a call to {@link
220 * PrintService#onRequestCancelPrintJob(PrintJob)}.
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700221 *
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700222 * @return Whether the job is canceled.
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700223 *
224 * @see #isStarted()
Svetoslav Ganov798bed62013-08-11 12:29:39 -0700225 * @see #isQueued()
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700226 */
227 public boolean cancel() {
Svetoslav269403b2013-08-14 17:31:04 -0700228 PrintService.throwIfNotCalledOnMainThread();
Svetoslav Ganov8c433762013-08-02 14:22:19 -0700229 if (isQueued() || isStarted()) {
230 return setState(PrintJobInfo.STATE_CANCELED, null);
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700231 }
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) {
Svetoslav269403b2013-08-14 17:31:04 -0700245 PrintService.throwIfNotCalledOnMainThread();
Svetoslav Ganov85b1f882013-07-24 17:00:06 -0700246 if (isInImmutableState()) {
247 return false;
248 }
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700249 try {
Svetoslav Ganova0027152013-06-25 14:59:53 -0700250 return mPrintServiceClient.setPrintJobTag(mCachedInfo.getId(), tag);
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700251 } catch (RemoteException re) {
Svetoslav Ganova0027152013-06-25 14:59:53 -0700252 Log.e(LOG_TAG, "Error setting tag for job: " + mCachedInfo.getId(), re);
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700253 }
254 return false;
255 }
256
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700257 @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;
Svetoslav Ganova0027152013-06-25 14:59:53 -0700269 return (mCachedInfo.getId() == other.mCachedInfo.getId());
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700270 }
271
272 @Override
273 public int hashCode() {
Svetoslav Ganova0027152013-06-25 14:59:53 -0700274 return mCachedInfo.getId();
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700275 }
276
Svetoslav Ganov85b1f882013-07-24 17:00:06 -0700277 private boolean isInImmutableState() {
278 final int state = mCachedInfo.getState();
279 return state == PrintJobInfo.STATE_COMPLETED
280 || state == PrintJobInfo.STATE_CANCELED;
281 }
282
Svetoslav269403b2013-08-14 17:31:04 -0700283 private boolean setState(int state, String error) {
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700284 try {
Svetoslav Ganov8c433762013-08-02 14:22:19 -0700285 if (mPrintServiceClient.setPrintJobState(mCachedInfo.getId(), state, error)) {
Svetoslav Ganova0027152013-06-25 14:59:53 -0700286 // 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);
Svetoslav Ganov8c433762013-08-02 14:22:19 -0700290 mCachedInfo.setFailureReason(error);
Svetoslav Ganova0027152013-06-25 14:59:53 -0700291 return true;
292 }
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700293 } catch (RemoteException re) {
Svetoslav Ganova0027152013-06-25 14:59:53 -0700294 Log.e(LOG_TAG, "Error setting the state of job: " + mCachedInfo.getId(), re);
Svetoslav Ganov4b9a4d12013-06-11 15:20:06 -0700295 }
296 return false;
297 }
298}