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