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