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